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