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