1 /* $OpenBSD: x509_algor.c,v 1.7 2024/02/29 20:03:47 tb Exp $ */
2 /*
3 * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <err.h>
19 #include <stdio.h>
20
21 #include <openssl/asn1.h>
22 #include <openssl/evp.h>
23 #include <openssl/objects.h>
24 #include <openssl/x509.h>
25
26 int X509_ALGOR_set_evp_md(X509_ALGOR *alg, const EVP_MD *md);
27
28 static int
x509_algor_new_test(void)29 x509_algor_new_test(void)
30 {
31 X509_ALGOR *alg = NULL;
32 const ASN1_OBJECT *aobj;
33 int failed = 1;
34
35 if ((alg = X509_ALGOR_new()) == NULL)
36 errx(1, "%s: X509_ALGOR_new", __func__);
37
38 if ((aobj = OBJ_nid2obj(NID_undef)) == NULL)
39 errx(1, "%s: OBJ_nid2obj", __func__);
40
41 if (alg->algorithm != aobj) {
42 fprintf(stderr, "FAIL: %s: want NID_undef OID\n", __func__);
43 goto failure;
44 }
45 if (alg->parameter != NULL) {
46 fprintf(stderr, "FAIL: %s: want NULL parameters\n", __func__);
47 goto failure;
48 }
49
50 failed = 0;
51
52 failure:
53 X509_ALGOR_free(alg);
54
55 return failed;
56 }
57
58 static int
x509_algor_set0_test(void)59 x509_algor_set0_test(void)
60 {
61 X509_ALGOR *alg = NULL;
62 ASN1_TYPE *old_parameter;
63 ASN1_OBJECT *oid;
64 ASN1_INTEGER *aint = NULL, *aint_ref;
65 int ret;
66 int failed = 1;
67
68 if ((ret = X509_ALGOR_set0(NULL, NULL, 0, NULL)) != 0) {
69 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(NULL, NULL, 0, NULL)"
70 ", want: %d, got %d\n", __func__, 0, ret);
71 goto failure;
72 }
73
74 if ((alg = X509_ALGOR_new()) == NULL)
75 errx(1, "%s: X509_ALGOR_new", __func__);
76
77 /* This sets algorithm to NULL and allocates new parameters. */
78 if ((ret = X509_ALGOR_set0(alg, NULL, 0, NULL)) != 1) {
79 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, NULL)"
80 ", want: %d, got %d\n", __func__, 1, ret);
81 goto failure;
82 }
83 if (alg->algorithm != NULL) {
84 fprintf(stderr, "FAIL: %s: want NULL algorithm after "
85 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__);
86 goto failure;
87 }
88 if ((old_parameter = alg->parameter) == NULL) {
89 fprintf(stderr, "FAIL: %s: want non-NULL parameter after "
90 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__);
91 goto failure;
92 }
93 if (alg->parameter->type != V_ASN1_UNDEF) {
94 fprintf(stderr, "FAIL: %s: want %d parameter type after "
95 "X509_ALGOR_set0(alg, NULL, 0, NULL), got %d\n",
96 __func__, V_ASN1_UNDEF, alg->parameter->type);
97 goto failure;
98 }
99 if (alg->parameter->value.ptr != NULL) {
100 fprintf(stderr, "FAIL: %s: want NULL parameter value after "
101 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__);
102 goto failure;
103 }
104
105 /* This should leave algorithm at NULL and parameters untouched. */
106 if ((ret = X509_ALGOR_set0(alg, NULL, 0, NULL)) != 1) {
107 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, NULL)"
108 ", want: %d, got %d\n", __func__, 1, ret);
109 goto failure;
110 }
111 if (alg->algorithm != NULL) {
112 fprintf(stderr, "FAIL: %s: want NULL algorithm after second"
113 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__);
114 goto failure;
115 }
116 if (alg->parameter != old_parameter) {
117 fprintf(stderr, "FAIL: %s: parameter changed after second"
118 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__);
119 goto failure;
120 }
121
122 /* This ignores pval (old_parameter). */
123 if ((ret = X509_ALGOR_set0(alg, NULL, 0, old_parameter)) != 1) {
124 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, ptr)"
125 ", want: %d, got %d\n", __func__, 1, ret);
126 goto failure;
127 }
128 if (alg->algorithm != NULL) {
129 fprintf(stderr, "FAIL: %s: want NULL algorithm after "
130 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__);
131 goto failure;
132 }
133 if (alg->parameter == NULL) {
134 fprintf(stderr, "FAIL: %s: want non-NULL parameter after "
135 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__);
136 goto failure;
137 }
138 if (alg->parameter->type != V_ASN1_UNDEF) {
139 fprintf(stderr, "FAIL: %s: want %d parameter type after "
140 "X509_ALGOR_set0(alg, NULL, 0, ptr), got %d\n",
141 __func__, V_ASN1_UNDEF, alg->parameter->type);
142 goto failure;
143 }
144 if (alg->parameter->value.ptr != NULL) {
145 fprintf(stderr, "FAIL: %s: want NULL parameter value after "
146 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__);
147 goto failure;
148 }
149
150 old_parameter = NULL;
151
152 /* This frees parameters and ignores pval. */
153 if ((ret = X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)) != 1) {
154 fprintf(stderr, "FAIL: %s: "
155 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)"
156 ", want: %d, got %d\n", __func__, 1, ret);
157 goto failure;
158 }
159 if (alg->algorithm != NULL) {
160 fprintf(stderr, "FAIL: %s: want NULL algorithm after "
161 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)\n", __func__);
162 goto failure;
163 }
164 if (alg->parameter != NULL) {
165 fprintf(stderr, "FAIL: %s: want NULL parameter after "
166 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)\n", __func__);
167 goto failure;
168 }
169
170 /* This frees parameters and ignores "foo". */
171 if ((ret = X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, "foo")) != 1) {
172 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, \"foo\")"
173 ", want: %d, got %d\n", __func__, 1, ret);
174 goto failure;
175 }
176 if (alg->algorithm != NULL) {
177 fprintf(stderr, "FAIL: %s: want NULL algorithm after "
178 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, \"foo\")\n", __func__);
179 goto failure;
180 }
181 if (alg->parameter != NULL) {
182 fprintf(stderr, "FAIL: %s: want NULL parameter after "
183 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, \"foo\")\n", __func__);
184 goto failure;
185 }
186
187 if ((oid = OBJ_nid2obj(NID_sha512_224)) == NULL) {
188 fprintf(stderr, "FAIL: %s: OBJ_nid2obj(NID_sha512_224)\n", __func__);
189 goto failure;
190 }
191 if ((aint = aint_ref = ASN1_INTEGER_new()) == NULL)
192 errx(1, "%s: ASN1_INTEGER_new()", __func__);
193 if (!ASN1_INTEGER_set_uint64(aint, 57))
194 errx(1, "%s: ASN1_INTEGER_set_uint64()", __func__);
195
196 if ((ret = X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)) != 1) {
197 fprintf(stderr, "Fail: %s: "
198 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)"
199 ", want: %d, got %d\n", __func__, 1, ret);
200 goto failure;
201 }
202 aint = NULL;
203 if (alg->algorithm != oid) {
204 fprintf(stderr, "FAIL: %s: unexpected oid on alg after "
205 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)"
206 ", want: %d, got %d\n", __func__, 1, ret);
207 goto failure;
208 }
209 if (alg->parameter == NULL) {
210 fprintf(stderr, "FAIL: %s: expected non-NULL parameter after "
211 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)"
212 ", want: %d, got %d\n", __func__, 1, ret);
213 goto failure;
214 }
215 if (alg->parameter->type != V_ASN1_INTEGER) {
216 fprintf(stderr, "FAIL: %s: want %d parameter type after "
217 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint), got %d\n",
218 __func__, V_ASN1_INTEGER, alg->parameter->type);
219 goto failure;
220 }
221 if (alg->parameter->value.asn1_string != aint_ref) {
222 fprintf(stderr, "FAIL: %s: unexpected parameter value after "
223 "X509_ALGOR_set0(alg, oid, V_ASN1_NULL, aint)\n", __func__);
224 goto failure;
225 }
226
227 failed = 0;
228
229 failure:
230 X509_ALGOR_free(alg);
231 ASN1_INTEGER_free(aint);
232
233 return failed;
234 }
235
236 static int
x509_algor_get0_test(void)237 x509_algor_get0_test(void)
238 {
239 X509_ALGOR *alg;
240 const ASN1_OBJECT *aobj = NULL;
241 int ptype = 0;
242 const void *pval = NULL;
243 ASN1_OBJECT *oid;
244 ASN1_INTEGER *aint = NULL, *aint_ref = NULL;
245 int ret;
246 int failed = 1;
247
248 if ((alg = X509_ALGOR_new()) == NULL)
249 errx(1, "%s: X509_ALGOR_new", __func__);
250
251 X509_ALGOR_get0(&aobj, NULL, NULL, alg);
252 if (aobj == NULL) {
253 fprintf(stderr, "FAIL: %s: expected non-NULL aobj\n", __func__);
254 goto failure;
255 }
256 X509_ALGOR_get0(NULL, &ptype, NULL, alg);
257 if (ptype != V_ASN1_UNDEF) {
258 fprintf(stderr, "FAIL: %s: want %d, got %d\n",
259 __func__, V_ASN1_UNDEF, ptype);
260 goto failure;
261 }
262
263 if ((oid = OBJ_nid2obj(NID_ED25519)) == NULL)
264 errx(1, "%s: OBJ_nid2obj(NID_ED25519)", __func__);
265 if ((aint = aint_ref = ASN1_INTEGER_new()) == NULL)
266 errx(1, "%s: ASN1_INTEGER_new()", __func__);
267 if (!ASN1_INTEGER_set_uint64(aint, 99))
268 errx(1, "%s: ASN1_INTEGER_set_uint64()", __func__);
269
270 if ((ret = X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)) != 1) {
271 fprintf(stderr, "Fail: %s: "
272 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)"
273 ", want: %d, got %d\n", __func__, 1, ret);
274 goto failure;
275 }
276 aint = NULL;
277
278 X509_ALGOR_get0(&aobj, NULL, NULL, alg);
279 if (aobj != oid) {
280 fprintf(stderr, "FAIL: %s: expected Ed25519 oid\n", __func__);
281 goto failure;
282 }
283 X509_ALGOR_get0(NULL, &ptype, NULL, alg);
284 if (ptype != V_ASN1_INTEGER) {
285 fprintf(stderr, "FAIL: %s: expected %d, got %d\n",
286 __func__, V_ASN1_INTEGER, ptype);
287 goto failure;
288 }
289 pval = oid;
290 X509_ALGOR_get0(NULL, NULL, &pval, alg);
291 if (pval != NULL) {
292 fprintf(stderr, "FAIL: %s: got non-NULL pval\n", __func__);
293 goto failure;
294 }
295
296 aobj = NULL;
297 ptype = V_ASN1_UNDEF;
298 pval = oid;
299 X509_ALGOR_get0(&aobj, &ptype, &pval, alg);
300 if (aobj != oid) {
301 fprintf(stderr, "FAIL: %s: expected Ed25519 oid 2\n", __func__);
302 goto failure;
303 }
304 if (ptype != V_ASN1_INTEGER) {
305 fprintf(stderr, "FAIL: %s: expected %d, got %d 2\n",
306 __func__, V_ASN1_INTEGER, ptype);
307 goto failure;
308 }
309 if (pval != aint_ref) {
310 fprintf(stderr, "FAIL: %s: expected ASN.1 integer\n", __func__);
311 goto failure;
312 }
313
314 failed = 0;
315
316 failure:
317 X509_ALGOR_free(alg);
318 ASN1_INTEGER_free(aint);
319
320 return failed;
321 }
322
323 static int
x509_algor_set_evp_md_test(void)324 x509_algor_set_evp_md_test(void)
325 {
326 X509_ALGOR *alg = NULL;
327 const ASN1_OBJECT *aobj;
328 int ptype = 0, nid = 0;
329 int failed = 1;
330
331 if ((alg = X509_ALGOR_new()) == NULL)
332 errx(1, "%s: X509_ALGOR_new", __func__);
333
334 if (!X509_ALGOR_set_evp_md(alg, EVP_sm3())) {
335 fprintf(stderr, "%s: X509_ALGOR_set_evp_md to sm3 failed\n",
336 __func__);
337 goto failure;
338 }
339 X509_ALGOR_get0(&aobj, &ptype, NULL, alg);
340 if ((nid = OBJ_obj2nid(aobj)) != NID_sm3) {
341 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__,
342 NID_sm3, nid);
343 goto failure;
344 }
345 if (ptype != V_ASN1_UNDEF) {
346 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__,
347 V_ASN1_UNDEF, ptype);
348 goto failure;
349 }
350
351 /* Preallocate as recommended in the manual. */
352 if (!X509_ALGOR_set0(alg, NULL, 0, NULL))
353 errx(1, "%s: X509_ALGOR_set0", __func__);
354
355 if (!X509_ALGOR_set_evp_md(alg, EVP_md5())) {
356 fprintf(stderr, "%s: X509_ALGOR_set_evp_md to md5 failed\n",
357 __func__);
358 goto failure;
359 }
360 X509_ALGOR_get0(&aobj, &ptype, NULL, alg);
361 if ((nid = OBJ_obj2nid(aobj)) != NID_md5) {
362 fprintf(stderr, "%s: md5 want %d, got %d\n", __func__,
363 NID_sm3, nid);
364 goto failure;
365 }
366 if (ptype != V_ASN1_NULL) {
367 fprintf(stderr, "%s: md5 want %d, got %d\n", __func__,
368 V_ASN1_NULL, ptype);
369 goto failure;
370 }
371
372 failed = 0;
373
374 failure:
375 X509_ALGOR_free(alg);
376
377 return failed;
378 }
379
380 int
main(void)381 main(void)
382 {
383 int failed = 0;
384
385 failed |= x509_algor_new_test();
386 failed |= x509_algor_set0_test();
387 failed |= x509_algor_get0_test();
388 failed |= x509_algor_set_evp_md_test();
389
390 return failed;
391 }
392