1 /*
2 * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include <openssl/rand.h>
14 #include <openssl/asn1.h>
15 #include <openssl/asn1t.h>
16 #include <openssl/obj_mac.h>
17 #include "internal/numbers.h"
18 #include "testutil.h"
19
20 #ifdef __GNUC__
21 #pragma GCC diagnostic ignored "-Wunused-function"
22 #endif
23 #ifdef __clang__
24 #pragma clang diagnostic ignored "-Wunused-function"
25 #endif
26
27 /* Badly coded ASN.1 INTEGER zero wrapped in a sequence */
28 static unsigned char t_invalid_zero[] = {
29 0x30, 0x02, /* SEQUENCE tag + length */
30 0x02, 0x00 /* INTEGER tag + length */
31 };
32
33 #ifndef OPENSSL_NO_DEPRECATED_3_0
34 /* LONG case ************************************************************* */
35
36 typedef struct {
37 long test_long;
38 } ASN1_LONG_DATA;
39
40 ASN1_SEQUENCE(ASN1_LONG_DATA) = {
41 ASN1_EMBED(ASN1_LONG_DATA, test_long, LONG),
42 } static_ASN1_SEQUENCE_END(ASN1_LONG_DATA)
43
44 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_LONG_DATA)
45 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_LONG_DATA)
46
47 static int test_long(void)
48 {
49 const unsigned char *p = t_invalid_zero;
50 ASN1_LONG_DATA *dectst = d2i_ASN1_LONG_DATA(NULL, &p, sizeof(t_invalid_zero));
51
52 if (dectst == NULL)
53 return 0; /* Fail */
54
55 ASN1_LONG_DATA_free(dectst);
56 return 1;
57 }
58 #endif
59
60 /* INT32 case ************************************************************* */
61
62 typedef struct {
63 int32_t test_int32;
64 } ASN1_INT32_DATA;
65
66 ASN1_SEQUENCE(ASN1_INT32_DATA) = {
67 ASN1_EMBED(ASN1_INT32_DATA, test_int32, INT32),
68 } static_ASN1_SEQUENCE_END(ASN1_INT32_DATA)
69
70 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT32_DATA)
71 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT32_DATA)
72
73 static int test_int32(void)
74 {
75 const unsigned char *p = t_invalid_zero;
76 ASN1_INT32_DATA *dectst = d2i_ASN1_INT32_DATA(NULL, &p, sizeof(t_invalid_zero));
77
78 if (dectst == NULL)
79 return 0; /* Fail */
80
81 ASN1_INT32_DATA_free(dectst);
82 return 1;
83 }
84
85 /* UINT32 case ************************************************************* */
86
87 typedef struct {
88 uint32_t test_uint32;
89 } ASN1_UINT32_DATA;
90
91 ASN1_SEQUENCE(ASN1_UINT32_DATA) = {
92 ASN1_EMBED(ASN1_UINT32_DATA, test_uint32, UINT32),
93 } static_ASN1_SEQUENCE_END(ASN1_UINT32_DATA)
94
95 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT32_DATA)
96 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT32_DATA)
97
98 static int test_uint32(void)
99 {
100 const unsigned char *p = t_invalid_zero;
101 ASN1_UINT32_DATA *dectst = d2i_ASN1_UINT32_DATA(NULL, &p, sizeof(t_invalid_zero));
102
103 if (dectst == NULL)
104 return 0; /* Fail */
105
106 ASN1_UINT32_DATA_free(dectst);
107 return 1;
108 }
109
110 /* INT64 case ************************************************************* */
111
112 typedef struct {
113 int64_t test_int64;
114 } ASN1_INT64_DATA;
115
116 ASN1_SEQUENCE(ASN1_INT64_DATA) = {
117 ASN1_EMBED(ASN1_INT64_DATA, test_int64, INT64),
118 } static_ASN1_SEQUENCE_END(ASN1_INT64_DATA)
119
120 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT64_DATA)
121 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT64_DATA)
122
123 static int test_int64(void)
124 {
125 const unsigned char *p = t_invalid_zero;
126 ASN1_INT64_DATA *dectst = d2i_ASN1_INT64_DATA(NULL, &p, sizeof(t_invalid_zero));
127
128 if (dectst == NULL)
129 return 0; /* Fail */
130
131 ASN1_INT64_DATA_free(dectst);
132 return 1;
133 }
134
135 /* UINT64 case ************************************************************* */
136
137 typedef struct {
138 uint64_t test_uint64;
139 } ASN1_UINT64_DATA;
140
141 ASN1_SEQUENCE(ASN1_UINT64_DATA) = {
142 ASN1_EMBED(ASN1_UINT64_DATA, test_uint64, UINT64),
143 } static_ASN1_SEQUENCE_END(ASN1_UINT64_DATA)
144
145 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT64_DATA)
146 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT64_DATA)
147
148 static int test_uint64(void)
149 {
150 const unsigned char *p = t_invalid_zero;
151 ASN1_UINT64_DATA *dectst = d2i_ASN1_UINT64_DATA(NULL, &p, sizeof(t_invalid_zero));
152
153 if (dectst == NULL)
154 return 0; /* Fail */
155
156 ASN1_UINT64_DATA_free(dectst);
157 return 1;
158 }
159
160 /* GeneralizedTime underflow *********************************************** */
161
test_gentime(void)162 static int test_gentime(void)
163 {
164 /* Underflowing GeneralizedTime 161208193400Z (YYMMDDHHMMSSZ) */
165 const unsigned char der[] = {
166 0x18,
167 0x0d,
168 0x31,
169 0x36,
170 0x31,
171 0x32,
172 0x30,
173 0x38,
174 0x31,
175 0x39,
176 0x33,
177 0x34,
178 0x30,
179 0x30,
180 0x5a,
181 };
182 const unsigned char *p;
183 int der_len, rc = 1;
184 ASN1_GENERALIZEDTIME *gentime;
185
186 p = der;
187 der_len = sizeof(der);
188 gentime = d2i_ASN1_GENERALIZEDTIME(NULL, &p, der_len);
189
190 if (!TEST_ptr_null(gentime))
191 rc = 0; /* fail */
192
193 ASN1_GENERALIZEDTIME_free(gentime);
194 return rc;
195 }
196
197 /* UTCTime underflow ******************************************************* */
198
test_utctime(void)199 static int test_utctime(void)
200 {
201 /* Underflowing UTCTime 0205104700Z (MMDDHHMMSSZ) */
202 const unsigned char der[] = {
203 0x17,
204 0x0b,
205 0x30,
206 0x32,
207 0x30,
208 0x35,
209 0x31,
210 0x30,
211 0x34,
212 0x37,
213 0x30,
214 0x30,
215 0x5a,
216 };
217 const unsigned char *p;
218 int der_len, rc = 1;
219 ASN1_UTCTIME *utctime;
220
221 p = der;
222 der_len = sizeof(der);
223 utctime = d2i_ASN1_UTCTIME(NULL, &p, der_len);
224
225 if (!TEST_ptr_null(utctime))
226 rc = 0; /* fail */
227
228 ASN1_UTCTIME_free(utctime);
229 return rc;
230 }
231
232 /* Invalid template ******************************************************** */
233
234 typedef struct {
235 ASN1_STRING *invalidDirString;
236 } INVALIDTEMPLATE;
237
238 ASN1_SEQUENCE(INVALIDTEMPLATE) = {
239 /*
240 * DirectoryString is a CHOICE type so it must use explicit tagging -
241 * but we deliberately use implicit here, which makes this template invalid.
242 */
243 ASN1_IMP(INVALIDTEMPLATE, invalidDirString, DIRECTORYSTRING, 12)
244 } static_ASN1_SEQUENCE_END(INVALIDTEMPLATE)
245
246 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(INVALIDTEMPLATE)
247 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(INVALIDTEMPLATE)
248
249 /* Empty sequence for invalid template test */
250 static unsigned char t_invalid_template[] = {
251 0x30, 0x03, /* SEQUENCE tag + length */
252 0x0c, 0x01, 0x41 /* UTF8String, length 1, "A" */
253 };
254
test_invalid_template(void)255 static int test_invalid_template(void)
256 {
257 const unsigned char *p = t_invalid_template;
258 INVALIDTEMPLATE *tmp = d2i_INVALIDTEMPLATE(NULL, &p,
259 sizeof(t_invalid_template));
260
261 /* We expect a NULL pointer return */
262 if (TEST_ptr_null(tmp))
263 return 1;
264
265 INVALIDTEMPLATE_free(tmp);
266 return 0;
267 }
268
test_reuse_asn1_object(void)269 static int test_reuse_asn1_object(void)
270 {
271 static unsigned char cn_der[] = { 0x06, 0x03, 0x55, 0x04, 0x06 };
272 static unsigned char oid_der[] = {
273 0x06, 0x06, 0x2a, 0x03, 0x04, 0x05, 0x06, 0x07
274 };
275 int ret = 0;
276 ASN1_OBJECT *obj;
277 unsigned char const *p = oid_der;
278
279 /* Create an object that owns dynamically allocated 'sn' and 'ln' fields */
280
281 if (!TEST_ptr(obj = ASN1_OBJECT_create(NID_undef, cn_der, sizeof(cn_der),
282 "C", "countryName")))
283 goto err;
284 /* reuse obj - this should not leak sn and ln */
285 if (!TEST_ptr(d2i_ASN1_OBJECT(&obj, &p, sizeof(oid_der))))
286 goto err;
287 ret = 1;
288 err:
289 ASN1_OBJECT_free(obj);
290 return ret;
291 }
292
setup_tests(void)293 int setup_tests(void)
294 {
295 #ifndef OPENSSL_NO_DEPRECATED_3_0
296 ADD_TEST(test_long);
297 #endif
298 ADD_TEST(test_int32);
299 ADD_TEST(test_uint32);
300 ADD_TEST(test_int64);
301 ADD_TEST(test_uint64);
302 ADD_TEST(test_gentime);
303 ADD_TEST(test_utctime);
304 ADD_TEST(test_invalid_template);
305 ADD_TEST(test_reuse_asn1_object);
306 return 1;
307 }
308