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