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