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