1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file der_length_sequence.c
7 ASN.1 DER, length a SEQUENCE, Tom St Denis
8 */
9
10 #ifdef LTC_DER
11
12 /**
13 Get the length of a DER sequence
14 @param list The sequences of items in the SEQUENCE
15 @param inlen The number of items
16 @param outlen [out] The length required in octets to store it
17 @return CRYPT_OK on success
18 */
der_length_sequence(const ltc_asn1_list * list,unsigned long inlen,unsigned long * outlen)19 int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen,
20 unsigned long *outlen)
21 {
22 return der_length_sequence_ex(list, inlen, outlen, NULL);
23 }
24
der_length_sequence_ex(const ltc_asn1_list * list,unsigned long inlen,unsigned long * outlen,unsigned long * payloadlen)25 int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
26 unsigned long *outlen, unsigned long *payloadlen)
27 {
28 int err;
29 ltc_asn1_type type;
30 unsigned long size, x, y, i;
31 void *data;
32
33 LTC_ARGCHK(list != NULL);
34 LTC_ARGCHK(outlen != NULL);
35
36 /* get size of output that will be required */
37 y = 0;
38 for (i = 0; i < inlen; i++) {
39 type = list[i].type;
40 size = list[i].size;
41 data = list[i].data;
42
43 if (type == LTC_ASN1_EOL) {
44 break;
45 }
46
47 /* some items may be optional during import */
48 if (!list[i].used && list[i].optional) continue;
49
50 switch (type) {
51 case LTC_ASN1_BOOLEAN:
52 if ((err = der_length_boolean(&x)) != CRYPT_OK) {
53 goto LBL_ERR;
54 }
55 y += x;
56 break;
57
58 case LTC_ASN1_INTEGER:
59 if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
60 goto LBL_ERR;
61 }
62 y += x;
63 break;
64
65 case LTC_ASN1_SHORT_INTEGER:
66 if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
67 goto LBL_ERR;
68 }
69 y += x;
70 break;
71
72 case LTC_ASN1_BIT_STRING:
73 case LTC_ASN1_RAW_BIT_STRING:
74 if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
75 goto LBL_ERR;
76 }
77 y += x;
78 break;
79
80 case LTC_ASN1_OCTET_STRING:
81 if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
82 goto LBL_ERR;
83 }
84 y += x;
85 break;
86
87 case LTC_ASN1_NULL:
88 y += 2;
89 break;
90
91 case LTC_ASN1_OBJECT_IDENTIFIER:
92 if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
93 goto LBL_ERR;
94 }
95 y += x;
96 break;
97
98 case LTC_ASN1_IA5_STRING:
99 if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
100 goto LBL_ERR;
101 }
102 y += x;
103 break;
104
105 case LTC_ASN1_TELETEX_STRING:
106 if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
107 goto LBL_ERR;
108 }
109 y += x;
110 break;
111
112 case LTC_ASN1_PRINTABLE_STRING:
113 if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
114 goto LBL_ERR;
115 }
116 y += x;
117 break;
118
119 case LTC_ASN1_UTCTIME:
120 if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
121 goto LBL_ERR;
122 }
123 y += x;
124 break;
125
126 case LTC_ASN1_GENERALIZEDTIME:
127 if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
128 goto LBL_ERR;
129 }
130 y += x;
131 break;
132
133 case LTC_ASN1_UTF8_STRING:
134 if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
135 goto LBL_ERR;
136 }
137 y += x;
138 break;
139
140 case LTC_ASN1_CUSTOM_TYPE:
141 if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
142 goto LBL_ERR;
143 }
144 y += x;
145 break;
146
147 case LTC_ASN1_SET:
148 case LTC_ASN1_SETOF:
149 case LTC_ASN1_SEQUENCE:
150 if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
151 goto LBL_ERR;
152 }
153 y += x;
154 break;
155
156 case LTC_ASN1_CHOICE:
157 case LTC_ASN1_EOL:
158 default:
159 err = CRYPT_INVALID_ARG;
160 goto LBL_ERR;
161 }
162 }
163
164 if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
165 goto LBL_ERR;
166 }
167
168 if (payloadlen != NULL) {
169 *payloadlen = y;
170 }
171
172 /* store size */
173 *outlen = y + x + 1;
174 err = CRYPT_OK;
175
176 LBL_ERR:
177 return err;
178 }
179
180 #endif
181