1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_decode_object_identifier.c
7   ASN.1 DER, Decode Object Identifier, Tom St Denis
8 */
9 
10 #ifdef LTC_DER
11 /**
12   Decode OID data and store the array of integers in words
13   @param in      The OID DER encoded data
14   @param inlen   The length of the OID data
15   @param words   [out] The destination of the OID words
16   @param outlen  [in/out] The number of OID words
17   @return CRYPT_OK if successful
18 */
der_decode_object_identifier(const unsigned char * in,unsigned long inlen,unsigned long * words,unsigned long * outlen)19 int der_decode_object_identifier(const unsigned char *in,    unsigned long  inlen,
20                                        unsigned long *words, unsigned long *outlen)
21 {
22    unsigned long x, y, t, len;
23    int err;
24 
25    LTC_ARGCHK(in     != NULL);
26    LTC_ARGCHK(words  != NULL);
27    LTC_ARGCHK(outlen != NULL);
28 
29    /* header is at least 3 bytes */
30    if (inlen < 3) {
31       return CRYPT_INVALID_PACKET;
32    }
33 
34    /* must be room for at least two words */
35    if (*outlen < 2) {
36       *outlen = 2;
37       return CRYPT_BUFFER_OVERFLOW;
38    }
39 
40    /* decode the packet header */
41    x = 0;
42    if ((in[x++] & 0x1F) != 0x06) {
43       return CRYPT_INVALID_PACKET;
44    }
45 
46    /* get the length of the data */
47    y = inlen - x;
48    if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
49       return err;
50    }
51    x += y;
52 
53    if ((len == 0) || (len > (inlen - x))) {
54       return CRYPT_INVALID_PACKET;
55    }
56 
57    /* decode words */
58    y = 0;
59    t = 0;
60    while (len--) {
61       t = (t << 7) | (in[x] & 0x7F);
62       if (!(in[x++] & 0x80)) {
63          /* store t */
64          if (y >= *outlen) {
65             y++;
66          } else {
67             if (y == 0) {
68                if (t <= 79) {
69                   words[0] = t / 40;
70                   words[1] = t % 40;
71                } else {
72                   words[0] = 2;
73                   words[1] = t - 80;
74                }
75                y = 2;
76             } else {
77                words[y++] = t;
78             }
79          }
80          t = 0;
81       }
82    }
83 
84    if (y > *outlen) {
85       err =  CRYPT_BUFFER_OVERFLOW;
86    } else {
87       err =  CRYPT_OK;
88    }
89 
90    *outlen = y;
91    return err;
92 }
93 
94 #endif
95