1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_decode_asn1_identifier.c
7   ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel
8 */
9 
10 #ifdef LTC_DER
11 /* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */
12 static const unsigned char tag_constructed_map[] =
13 {
14  /*  0 */
15  255,
16  LTC_ASN1_PC_PRIMITIVE,
17  LTC_ASN1_PC_PRIMITIVE,
18  LTC_ASN1_PC_PRIMITIVE,
19  LTC_ASN1_PC_PRIMITIVE,
20  /*  5 */
21  LTC_ASN1_PC_PRIMITIVE,
22  LTC_ASN1_PC_PRIMITIVE,
23  LTC_ASN1_PC_PRIMITIVE,
24  LTC_ASN1_PC_PRIMITIVE,
25  LTC_ASN1_PC_PRIMITIVE,
26  /* 10 */
27  LTC_ASN1_PC_PRIMITIVE,
28  LTC_ASN1_PC_PRIMITIVE,
29  LTC_ASN1_PC_PRIMITIVE,
30  LTC_ASN1_PC_PRIMITIVE,
31  LTC_ASN1_PC_PRIMITIVE,
32  /* 15 */
33  255,
34  LTC_ASN1_PC_CONSTRUCTED,
35  LTC_ASN1_PC_CONSTRUCTED,
36  LTC_ASN1_PC_PRIMITIVE,
37  LTC_ASN1_PC_PRIMITIVE,
38  /* 20 */
39  LTC_ASN1_PC_PRIMITIVE,
40  LTC_ASN1_PC_PRIMITIVE,
41  LTC_ASN1_PC_PRIMITIVE,
42  LTC_ASN1_PC_PRIMITIVE,
43  LTC_ASN1_PC_PRIMITIVE,
44  /* 25 */
45  LTC_ASN1_PC_PRIMITIVE,
46  LTC_ASN1_PC_PRIMITIVE,
47  LTC_ASN1_PC_PRIMITIVE,
48  LTC_ASN1_PC_PRIMITIVE,
49 };
50  static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
51 
52 /**
53   Decode the ASN.1 Identifier
54   @param id    Where to store the decoded Identifier
55   @param in    Where to read the Identifier from
56   @param inlen [in/out] The size of in available/read
57   @return CRYPT_OK if successful
58 */
der_decode_asn1_identifier(const unsigned char * in,unsigned long * inlen,ltc_asn1_list * id)59 int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id)
60 {
61    ulong64 tmp;
62    unsigned long tag_len;
63    int err;
64 
65    LTC_ARGCHK(id    != NULL);
66    LTC_ARGCHK(in    != NULL);
67    LTC_ARGCHK(inlen != NULL);
68 
69    if (*inlen == 0) {
70       return CRYPT_BUFFER_OVERFLOW;
71    }
72 
73    tag_len = 1;
74    id->klass = (in[0] >> 6) & 0x3;
75    id->pc = (in[0] >> 5) & 0x1;
76    id->tag = in[0] & 0x1f;
77 
78    err = CRYPT_OK;
79    if (id->tag == 0x1f) {
80       id->tag = 0;
81       do {
82          if (*inlen < tag_len) {
83             /* break the loop and trigger the BOF error-code */
84             tmp = 0xff;
85             break;
86          }
87          id->tag <<= 7;
88          id->tag |= in[tag_len] & 0x7f;
89          tmp = in[tag_len] & 0x80;
90          tag_len++;
91       } while ((tmp != 0) && (tag_len < 10));
92 
93       if (tmp != 0) {
94          err = CRYPT_BUFFER_OVERFLOW;
95       } else if (id->tag < 0x1f) {
96          err = CRYPT_PK_ASN1_ERROR;
97       }
98    }
99 
100    if (err != CRYPT_OK) {
101       id->pc = 0;
102       id->klass = 0;
103       id->tag = 0;
104    } else {
105       *inlen = tag_len;
106       if ((id->klass == LTC_ASN1_CL_UNIVERSAL) &&
107             (id->tag < der_asn1_tag_to_type_map_sz) &&
108             (id->tag < tag_constructed_map_sz) &&
109             (id->pc == tag_constructed_map[id->tag])) {
110          id->type = der_asn1_tag_to_type_map[id->tag];
111       } else {
112          if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) {
113             id->type = LTC_ASN1_EOL;
114          } else {
115             id->type = LTC_ASN1_CUSTOM_TYPE;
116          }
117       }
118    }
119 
120    return CRYPT_OK;
121 }
122 
123 #endif
124