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