1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 #include <stdarg.h>
5 
6 
7 /**
8   @file der_encode_sequence_multi.c
9   ASN.1 DER, encode a SEQUENCE, Tom St Denis
10 */
11 
12 #ifdef LTC_DER
13 
14 /**
15   Encode a SEQUENCE type using a VA list
16   @param out    [out] Destination for data
17   @param outlen [in/out] Length of buffer and resulting length of output
18   @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
19   @return CRYPT_OK on success
20 */
der_encode_sequence_multi(unsigned char * out,unsigned long * outlen,...)21 int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
22 {
23    int           err;
24    ltc_asn1_type type;
25    unsigned long size, x;
26    void          *data;
27    va_list       args;
28    ltc_asn1_list *list;
29 
30    LTC_ARGCHK(out    != NULL);
31    LTC_ARGCHK(outlen != NULL);
32 
33    /* get size of output that will be required */
34    va_start(args, outlen);
35    x = 0;
36    for (;;) {
37        type = (ltc_asn1_type)va_arg(args, int);
38 
39        if (type == LTC_ASN1_EOL) {
40           break;
41        }
42 
43        size = va_arg(args, unsigned long);
44        data = va_arg(args, void*);
45        LTC_UNUSED_PARAM(size);
46        LTC_UNUSED_PARAM(data);
47 
48        switch (type) {
49            case LTC_ASN1_BOOLEAN:
50            case LTC_ASN1_INTEGER:
51            case LTC_ASN1_SHORT_INTEGER:
52            case LTC_ASN1_BIT_STRING:
53            case LTC_ASN1_OCTET_STRING:
54            case LTC_ASN1_NULL:
55            case LTC_ASN1_OBJECT_IDENTIFIER:
56            case LTC_ASN1_IA5_STRING:
57            case LTC_ASN1_PRINTABLE_STRING:
58            case LTC_ASN1_UTF8_STRING:
59            case LTC_ASN1_UTCTIME:
60            case LTC_ASN1_SEQUENCE:
61            case LTC_ASN1_SET:
62            case LTC_ASN1_SETOF:
63            case LTC_ASN1_RAW_BIT_STRING:
64            case LTC_ASN1_GENERALIZEDTIME:
65                 ++x;
66                 break;
67 
68            case LTC_ASN1_CHOICE:
69            case LTC_ASN1_CUSTOM_TYPE:
70            case LTC_ASN1_EOL:
71            case LTC_ASN1_TELETEX_STRING:
72            default:
73                va_end(args);
74                return CRYPT_INVALID_ARG;
75        }
76    }
77    va_end(args);
78 
79    /* allocate structure for x elements */
80    if (x == 0) {
81       return CRYPT_NOP;
82    }
83 
84    list = XCALLOC(sizeof(*list), x);
85    if (list == NULL) {
86       return CRYPT_MEM;
87    }
88 
89    /* fill in the structure */
90    va_start(args, outlen);
91    x = 0;
92    for (;;) {
93        type = (ltc_asn1_type)va_arg(args, int);
94 
95        if (type == LTC_ASN1_EOL) {
96           break;
97        }
98 
99        size = va_arg(args, unsigned long);
100        data = va_arg(args, void*);
101 
102        switch (type) {
103            case LTC_ASN1_BOOLEAN:
104            case LTC_ASN1_INTEGER:
105            case LTC_ASN1_SHORT_INTEGER:
106            case LTC_ASN1_BIT_STRING:
107            case LTC_ASN1_OCTET_STRING:
108            case LTC_ASN1_NULL:
109            case LTC_ASN1_OBJECT_IDENTIFIER:
110            case LTC_ASN1_IA5_STRING:
111            case LTC_ASN1_PRINTABLE_STRING:
112            case LTC_ASN1_UTF8_STRING:
113            case LTC_ASN1_UTCTIME:
114            case LTC_ASN1_SEQUENCE:
115            case LTC_ASN1_SET:
116            case LTC_ASN1_SETOF:
117            case LTC_ASN1_RAW_BIT_STRING:
118            case LTC_ASN1_GENERALIZEDTIME:
119                 LTC_SET_ASN1(list, x++, type, data, size);
120                 break;
121 
122            case LTC_ASN1_CHOICE:
123            case LTC_ASN1_CUSTOM_TYPE:
124            case LTC_ASN1_EOL:
125            case LTC_ASN1_TELETEX_STRING:
126            default:
127                va_end(args);
128                err = CRYPT_INVALID_ARG;
129                goto LBL_ERR;
130        }
131    }
132    va_end(args);
133 
134    err = der_encode_sequence(list, x, out, outlen);
135 LBL_ERR:
136    XFREE(list);
137    return err;
138 }
139 
140 #endif
141 
142