diff options
author | tb <> | 2024-05-28 15:33:35 +0000 |
---|---|---|
committer | tb <> | 2024-05-28 15:33:35 +0000 |
commit | 3736b64da9b4f391ef4ec6e13fb42575c1766d50 (patch) | |
tree | 3c2fc50130345745cb7476feff0887d908d3b711 /src | |
parent | 444ca4712a0791a9e0ee3d6e226598198a1c3580 (diff) | |
download | openbsd-3736b64da9b4f391ef4ec6e13fb42575c1766d50.tar.gz openbsd-3736b64da9b4f391ef4ec6e13fb42575c1766d50.tar.bz2 openbsd-3736b64da9b4f391ef4ec6e13fb42575c1766d50.zip |
Add regress coverage for X509V3_add1_i2d()
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/x509/Makefile | 4 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/x509/x509_extensions_test.c | 603 |
2 files changed, 605 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/x509/Makefile b/src/regress/lib/libcrypto/x509/Makefile index 283e3379d4..5a90facb2d 100644 --- a/src/regress/lib/libcrypto/x509/Makefile +++ b/src/regress/lib/libcrypto/x509/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # $OpenBSD: Makefile,v 1.21 2023/04/30 05:02:59 tb Exp $ | 1 | # $OpenBSD: Makefile,v 1.22 2024/05/28 15:33:35 tb Exp $ |
2 | 2 | ||
3 | PROGS = constraints verify x509attribute x509name x509req_ext callback | 3 | PROGS = constraints verify x509attribute x509name x509req_ext callback |
4 | PROGS += expirecallback callbackfailures x509_asn1 | 4 | PROGS += expirecallback callbackfailures x509_asn1 x509_extensions_test |
5 | LDADD = -lcrypto | 5 | LDADD = -lcrypto |
6 | DPADD = ${LIBCRYPTO} | 6 | DPADD = ${LIBCRYPTO} |
7 | 7 | ||
diff --git a/src/regress/lib/libcrypto/x509/x509_extensions_test.c b/src/regress/lib/libcrypto/x509/x509_extensions_test.c new file mode 100644 index 0000000000..a90a173e1d --- /dev/null +++ b/src/regress/lib/libcrypto/x509/x509_extensions_test.c | |||
@@ -0,0 +1,603 @@ | |||
1 | /* $OpenBSD: x509_extensions_test.c,v 1.1 2024/05/28 15:33:35 tb Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <err.h> | ||
20 | #include <stdio.h> | ||
21 | |||
22 | #include <openssl/asn1.h> | ||
23 | #include <openssl/err.h> | ||
24 | #include <openssl/x509.h> | ||
25 | #include <openssl/x509v3.h> | ||
26 | |||
27 | #define ASN1_BOOLEAN_TRUE 0xff | ||
28 | #define ASN1_BOOLEAN_FALSE 0x00 | ||
29 | |||
30 | static BASIC_CONSTRAINTS * | ||
31 | create_basic_constraints(int ca) | ||
32 | { | ||
33 | BASIC_CONSTRAINTS *bc; | ||
34 | |||
35 | if ((bc = BASIC_CONSTRAINTS_new()) == NULL) | ||
36 | errx(1, "BASIC_CONSTRAINTS_new"); | ||
37 | |||
38 | bc->ca = ca ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; | ||
39 | |||
40 | return bc; | ||
41 | } | ||
42 | |||
43 | static int | ||
44 | test_x509v3_add1_i2d_empty_stack(STACK_OF(X509_EXTENSION) **extensions) | ||
45 | { | ||
46 | unsigned long error; | ||
47 | int op, got; | ||
48 | int nid = NID_basic_constraints; | ||
49 | int failed = 1; | ||
50 | |||
51 | if (X509v3_get_ext_count(*extensions) != 0) { | ||
52 | fprintf(stderr, "%s: FAIL: need empty stack\n", __func__); | ||
53 | goto err; | ||
54 | } | ||
55 | |||
56 | ERR_clear_error(); | ||
57 | |||
58 | op = X509V3_ADD_REPLACE_EXISTING; | ||
59 | |||
60 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { | ||
61 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
62 | "want %d, got %d.\n", __func__, 0, got); | ||
63 | goto err; | ||
64 | } | ||
65 | |||
66 | error = ERR_get_error(); | ||
67 | if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_NOT_FOUND) { | ||
68 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
69 | "pushed %d for empty stack, want %d.\n", __func__, | ||
70 | ERR_GET_REASON(error), X509V3_R_EXTENSION_NOT_FOUND); | ||
71 | goto err; | ||
72 | } | ||
73 | if ((error = ERR_get_error()) != 0) { | ||
74 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
75 | "expected exactly one error.\n", __func__); | ||
76 | goto err; | ||
77 | } | ||
78 | |||
79 | op = X509V3_ADD_REPLACE_EXISTING | X509V3_ADD_SILENT; | ||
80 | |||
81 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { | ||
82 | fprintf(stderr, "%s: FAIL: silent X509V3_ADD_REPLACE_EXISTING " | ||
83 | "want %d, got %d.\n", __func__, 0, got); | ||
84 | goto err; | ||
85 | } | ||
86 | if ((error = ERR_get_error()) != 0) { | ||
87 | fprintf(stderr, "%s: FAIL: silent X509V3_ADD_REPLACE_EXISTING " | ||
88 | "added error %d, want %d.\n", __func__, | ||
89 | ERR_GET_REASON(error), 0); | ||
90 | goto err; | ||
91 | } | ||
92 | |||
93 | op = X509V3_ADD_DELETE; | ||
94 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { | ||
95 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
96 | "want %d, got %d.\n", __func__, 0, got); | ||
97 | goto err; | ||
98 | } | ||
99 | |||
100 | error = ERR_get_error(); | ||
101 | if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_NOT_FOUND) { | ||
102 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
103 | "pushed %d for empty stack, want %d.\n", __func__, | ||
104 | ERR_GET_REASON(error), X509V3_R_EXTENSION_NOT_FOUND); | ||
105 | goto err; | ||
106 | } | ||
107 | |||
108 | if ((error = ERR_get_error()) != 0) { | ||
109 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
110 | "expected exactly one error.\n", __func__); | ||
111 | goto err; | ||
112 | } | ||
113 | |||
114 | failed = 0; | ||
115 | |||
116 | err: | ||
117 | |||
118 | return failed; | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | test_x509v3_add1_i2d_single_nid(STACK_OF(X509_EXTENSION) **extensions) | ||
123 | { | ||
124 | BASIC_CONSTRAINTS *bc = NULL; | ||
125 | unsigned long error; | ||
126 | int crit, got, nid, op; | ||
127 | int failed = 1; | ||
128 | |||
129 | if (X509v3_get_ext_count(*extensions) != 0) { | ||
130 | fprintf(stderr, "%s: FAIL: need an empty stack.\n", __func__); | ||
131 | goto err; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Add basic ca constraints. | ||
136 | */ | ||
137 | |||
138 | nid = NID_basic_constraints; | ||
139 | bc = create_basic_constraints(1); | ||
140 | op = X509V3_ADD_DEFAULT; | ||
141 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { | ||
142 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT failed to add " | ||
143 | "basic constraints to empty stack: want %d, got %d.\n", | ||
144 | __func__, 1, got); | ||
145 | goto err; | ||
146 | } | ||
147 | BASIC_CONSTRAINTS_free(bc); | ||
148 | bc = NULL; | ||
149 | |||
150 | if ((got = X509v3_get_ext_count(*extensions)) != 1) { | ||
151 | fprintf(stderr, "%s: FAIL: expected 1 extension, have %d.\n", | ||
152 | __func__, got); | ||
153 | goto err; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Can't delete or replace non-existent extension. | ||
158 | */ | ||
159 | |||
160 | nid = NID_policy_constraints; | ||
161 | op = X509V3_ADD_DELETE; | ||
162 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { | ||
163 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE non-existent " | ||
164 | "want %d, got %d,\n", __func__, 0, got); | ||
165 | goto err; | ||
166 | } | ||
167 | nid = NID_policy_constraints; | ||
168 | op = X509V3_ADD_REPLACE_EXISTING; | ||
169 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { | ||
170 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING non-existent " | ||
171 | "want %d, got %d.\n", __func__, 0, got); | ||
172 | goto err; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * X509V3_ADD_DEFAULT refuses to add second basic constraints extension. | ||
177 | */ | ||
178 | |||
179 | ERR_clear_error(); | ||
180 | |||
181 | nid = NID_basic_constraints; | ||
182 | bc = create_basic_constraints(0); | ||
183 | op = X509V3_ADD_DEFAULT; | ||
184 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 0) { | ||
185 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second constraints " | ||
186 | "want %d, got %d.\n", __func__, 0, got); | ||
187 | goto err; | ||
188 | } | ||
189 | BASIC_CONSTRAINTS_free(bc); | ||
190 | bc = NULL; | ||
191 | |||
192 | error = ERR_get_error(); | ||
193 | if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_EXISTS) { | ||
194 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second constraints " | ||
195 | " pushed %d, want %d.\n", __func__, | ||
196 | ERR_GET_REASON(error), X509V3_R_EXTENSION_EXISTS); | ||
197 | goto err; | ||
198 | } | ||
199 | |||
200 | if ((got = X509v3_get_ext_count(*extensions)) != 1) { | ||
201 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second contraints " | ||
202 | "expected 1 extension, have %d.\n", __func__, got); | ||
203 | goto err; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * We can replace existing basic constraints using X509V3_ADD_REPLACE. | ||
208 | */ | ||
209 | |||
210 | nid = NID_basic_constraints; | ||
211 | bc = create_basic_constraints(0); | ||
212 | op = X509V3_ADD_REPLACE; | ||
213 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { | ||
214 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
215 | "want %d, got %d.\n", __func__, 1, got); | ||
216 | goto err; | ||
217 | } | ||
218 | BASIC_CONSTRAINTS_free(bc); | ||
219 | bc = NULL; | ||
220 | |||
221 | if ((got = X509v3_get_ext_count(*extensions)) != 1) { | ||
222 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
223 | "expected 1 extension, have %d.\n", __func__, got); | ||
224 | goto err; | ||
225 | } | ||
226 | |||
227 | /* Check that the extension was actually replaced. */ | ||
228 | nid = NID_basic_constraints; | ||
229 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { | ||
230 | if (crit != -1) | ||
231 | errx(1, "X509V3_get_d2i"); | ||
232 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
233 | "expected basic constraints\n", __func__); | ||
234 | goto err; | ||
235 | } | ||
236 | if (bc->ca != ASN1_BOOLEAN_FALSE) { | ||
237 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
238 | "expected cA = false in basic constraints\n", __func__); | ||
239 | goto err; | ||
240 | } | ||
241 | BASIC_CONSTRAINTS_free(bc); | ||
242 | bc = NULL; | ||
243 | |||
244 | /* | ||
245 | * X509V3_ADD_KEEP_EXISTING existing does what it is supposed to do | ||
246 | * if basic constraints are already present. | ||
247 | */ | ||
248 | |||
249 | nid = NID_basic_constraints; | ||
250 | bc = create_basic_constraints(1); | ||
251 | op = X509V3_ADD_KEEP_EXISTING; | ||
252 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { | ||
253 | fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " | ||
254 | "want %d, got %d.\n", __func__, 1, got); | ||
255 | goto err; | ||
256 | } | ||
257 | BASIC_CONSTRAINTS_free(bc); | ||
258 | bc = NULL; | ||
259 | |||
260 | /* | ||
261 | * Check we still have non-ca basic constraints. | ||
262 | */ | ||
263 | |||
264 | nid = NID_basic_constraints; | ||
265 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { | ||
266 | if (crit != -1) | ||
267 | errx(1, "X509V3_get_d2i"); | ||
268 | fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " | ||
269 | "expected basic constraints\n", __func__); | ||
270 | goto err; | ||
271 | } | ||
272 | if (bc->ca != ASN1_BOOLEAN_FALSE) { | ||
273 | fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " | ||
274 | "expected non-ca basic constraints\n", __func__); | ||
275 | goto err; | ||
276 | } | ||
277 | BASIC_CONSTRAINTS_free(bc); | ||
278 | bc = NULL; | ||
279 | |||
280 | /* | ||
281 | * X509V3_ADD_REPLACE_EXISTING also works. | ||
282 | */ | ||
283 | |||
284 | nid = NID_basic_constraints; | ||
285 | bc = create_basic_constraints(1); | ||
286 | op = X509V3_ADD_REPLACE_EXISTING; | ||
287 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { | ||
288 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
289 | "want %d, got %d.\n", __func__, 1, got); | ||
290 | goto err; | ||
291 | } | ||
292 | BASIC_CONSTRAINTS_free(bc); | ||
293 | bc = NULL; | ||
294 | |||
295 | /* | ||
296 | * Check we again have ca basic constraints. | ||
297 | */ | ||
298 | |||
299 | nid = NID_basic_constraints; | ||
300 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { | ||
301 | if (crit != -1) | ||
302 | errx(1, "X509V3_get_d2i"); | ||
303 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
304 | "expected basic constraints\n", __func__); | ||
305 | goto err; | ||
306 | } | ||
307 | if (bc->ca != ASN1_BOOLEAN_TRUE) { | ||
308 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " | ||
309 | "expected ca basic constraints\n", __func__); | ||
310 | goto err; | ||
311 | } | ||
312 | BASIC_CONSTRAINTS_free(bc); | ||
313 | bc = NULL; | ||
314 | |||
315 | /* | ||
316 | * And X509V3_ADD_DELETE now works. | ||
317 | */ | ||
318 | |||
319 | nid = NID_basic_constraints; | ||
320 | op = X509V3_ADD_DELETE; | ||
321 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { | ||
322 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
323 | "want %d, got %d.\n", __func__, 0, got); | ||
324 | goto err; | ||
325 | } | ||
326 | |||
327 | if ((got = X509v3_get_ext_count(*extensions)) != 0) { | ||
328 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
329 | "expected 0 extensions, have %d.\n", __func__, got); | ||
330 | goto err; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * X509V3_ADD_REPLACE adds the extension to empty stack as it should. | ||
335 | */ | ||
336 | |||
337 | nid = NID_basic_constraints; | ||
338 | bc = create_basic_constraints(0); | ||
339 | op = X509V3_ADD_REPLACE; | ||
340 | if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { | ||
341 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE on empty stack " | ||
342 | "want %d, got %d.\n", __func__, 1, got); | ||
343 | goto err; | ||
344 | } | ||
345 | BASIC_CONSTRAINTS_free(bc); | ||
346 | bc = NULL; | ||
347 | |||
348 | if ((got = X509v3_get_ext_count(*extensions)) != 1) { | ||
349 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
350 | "expected 1 extension, have %d.\n", __func__, got); | ||
351 | goto err; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * And X509V3_ADD_DELETE works again. | ||
356 | */ | ||
357 | |||
358 | nid = NID_basic_constraints; | ||
359 | op = X509V3_ADD_DELETE; | ||
360 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { | ||
361 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE after add replace " | ||
362 | "want %d, got %d.\n", __func__, 0, got); | ||
363 | goto err; | ||
364 | } | ||
365 | |||
366 | if ((got = X509v3_get_ext_count(*extensions)) != 0) { | ||
367 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
368 | "expected 0 extensions, have %d.\n", __func__, got); | ||
369 | goto err; | ||
370 | } | ||
371 | |||
372 | failed = 0; | ||
373 | |||
374 | err: | ||
375 | BASIC_CONSTRAINTS_free(bc); | ||
376 | |||
377 | return failed; | ||
378 | } | ||
379 | |||
380 | static int | ||
381 | test_x509v3_add1_i2d_add_append(STACK_OF(X509_EXTENSION) **extensions) | ||
382 | { | ||
383 | BASIC_CONSTRAINTS *bc = NULL; | ||
384 | int crit, got, idx, nid, op; | ||
385 | int failed = 1; | ||
386 | |||
387 | if (X509v3_get_ext_count(*extensions) != 0) { | ||
388 | fprintf(stderr, "%s: FAIL: need empty stack.\n", __func__); | ||
389 | goto err; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Let the toolkit add two basic constraints extensions. | ||
394 | */ | ||
395 | |||
396 | nid = NID_basic_constraints; | ||
397 | bc = create_basic_constraints(1); | ||
398 | crit = 1; | ||
399 | op = X509V3_ADD_APPEND; | ||
400 | if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { | ||
401 | fprintf(stderr, "%s: FAIL: first X509V3_ADD_APPEND " | ||
402 | "want %d, got %d.\n", __func__, 0, got); | ||
403 | goto err; | ||
404 | } | ||
405 | BASIC_CONSTRAINTS_free(bc); | ||
406 | bc = NULL; | ||
407 | |||
408 | nid = NID_basic_constraints; | ||
409 | bc = create_basic_constraints(0); | ||
410 | crit = 1; | ||
411 | op = X509V3_ADD_APPEND; | ||
412 | if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { | ||
413 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " | ||
414 | "want %d, got %d.\n", __func__, 0, got); | ||
415 | goto err; | ||
416 | } | ||
417 | BASIC_CONSTRAINTS_free(bc); | ||
418 | bc = NULL; | ||
419 | |||
420 | if ((got = X509v3_get_ext_count(*extensions)) != 2) { | ||
421 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " | ||
422 | "expected 2 extensions, have %d.\n", __func__, got); | ||
423 | goto err; | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * Inspect the extensions on the stack. First we should get the one | ||
428 | * with the ca bit set and it should be critical. | ||
429 | */ | ||
430 | |||
431 | nid = NID_basic_constraints; | ||
432 | idx = -1; | ||
433 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { | ||
434 | fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " | ||
435 | "expected basic constraints.\n", __func__); | ||
436 | goto err; | ||
437 | } | ||
438 | if (bc->ca != ASN1_BOOLEAN_TRUE) { | ||
439 | fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " | ||
440 | "expected ca basic constraints.\n", __func__); | ||
441 | goto err; | ||
442 | } | ||
443 | if (crit != 1) { | ||
444 | fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " | ||
445 | "expected critical basic constraints.\n", __func__); | ||
446 | goto err; | ||
447 | } | ||
448 | BASIC_CONSTRAINTS_free(bc); | ||
449 | bc = NULL; | ||
450 | |||
451 | /* Redo the exercise and get the basic constraints with ca bit unset. */ | ||
452 | nid = NID_basic_constraints; | ||
453 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { | ||
454 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " | ||
455 | "expected basic constraints.\n", __func__); | ||
456 | goto err; | ||
457 | } | ||
458 | if (bc->ca != ASN1_BOOLEAN_FALSE) { | ||
459 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " | ||
460 | "expected basic constraints to be non-ca.\n", __func__); | ||
461 | goto err; | ||
462 | } | ||
463 | if (crit != 1) { | ||
464 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " | ||
465 | "expected critical basic constraints.\n", __func__); | ||
466 | goto err; | ||
467 | } | ||
468 | BASIC_CONSTRAINTS_free(bc); | ||
469 | bc = NULL; | ||
470 | |||
471 | /* | ||
472 | * Now X509V3_ADD_REPLACE non-critical ca constraints. They should | ||
473 | * replace the critical ca constraints we added before. | ||
474 | */ | ||
475 | |||
476 | nid = NID_basic_constraints; | ||
477 | bc = create_basic_constraints(1); | ||
478 | crit = 0; | ||
479 | op = X509V3_ADD_REPLACE; | ||
480 | if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { | ||
481 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
482 | "want %d, got %d\n", __func__, 1, got); | ||
483 | goto err; | ||
484 | } | ||
485 | BASIC_CONSTRAINTS_free(bc); | ||
486 | bc = NULL; | ||
487 | |||
488 | /* | ||
489 | * If we get basic constraints now, we get the non-critical one with the | ||
490 | * ca bit set. | ||
491 | */ | ||
492 | |||
493 | nid = NID_basic_constraints; | ||
494 | idx = -1; | ||
495 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { | ||
496 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
497 | "expected basic constraints.\n", __func__); | ||
498 | goto err; | ||
499 | } | ||
500 | if (bc->ca != ASN1_BOOLEAN_TRUE) { | ||
501 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
502 | "expected ca basic constraints.\n", __func__); | ||
503 | goto err; | ||
504 | } | ||
505 | if (crit != 0) { | ||
506 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
507 | "expected non-critical basic constraints.\n", __func__); | ||
508 | goto err; | ||
509 | } | ||
510 | BASIC_CONSTRAINTS_free(bc); | ||
511 | bc = NULL; | ||
512 | |||
513 | if ((got = X509v3_get_ext_count(*extensions)) != 2) { | ||
514 | fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " | ||
515 | "expected 2 extensions, got %d.\n", __func__, got); | ||
516 | goto err; | ||
517 | } | ||
518 | |||
519 | nid = NID_basic_constraints; | ||
520 | op = X509V3_ADD_DELETE; | ||
521 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { | ||
522 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
523 | "want %d, got %d\n", __func__, 1, got); | ||
524 | goto err; | ||
525 | } | ||
526 | |||
527 | if ((got = X509v3_get_ext_count(*extensions)) != 1) { | ||
528 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
529 | "expected 1 extension, got %d.\n", __func__, got); | ||
530 | goto err; | ||
531 | } | ||
532 | |||
533 | /* The last deletion will have left the critical non-ca constraints. */ | ||
534 | nid = NID_basic_constraints; | ||
535 | idx = -1; | ||
536 | if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { | ||
537 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
538 | "expected basic constraints.\n", __func__); | ||
539 | goto err; | ||
540 | } | ||
541 | if (bc->ca != ASN1_BOOLEAN_FALSE) { | ||
542 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
543 | "expected ca basic constraints.\n", __func__); | ||
544 | goto err; | ||
545 | } | ||
546 | if (crit != 1) { | ||
547 | fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " | ||
548 | "expected critical basic constraints.\n", __func__); | ||
549 | goto err; | ||
550 | } | ||
551 | BASIC_CONSTRAINTS_free(bc); | ||
552 | bc = NULL; | ||
553 | |||
554 | /* Now delete the last extension. */ | ||
555 | nid = NID_basic_constraints; | ||
556 | op = X509V3_ADD_DELETE; | ||
557 | if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { | ||
558 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_DELETE " | ||
559 | "want %d, got %d\n", __func__, 1, got); | ||
560 | goto err; | ||
561 | } | ||
562 | |||
563 | if ((got = X509v3_get_ext_count(*extensions)) != 0) { | ||
564 | fprintf(stderr, "%s: FAIL: second X509V3_ADD_DELETE " | ||
565 | "expected 0 extensions, got %d.\n", __func__, got); | ||
566 | goto err; | ||
567 | } | ||
568 | |||
569 | failed = 0; | ||
570 | |||
571 | err: | ||
572 | BASIC_CONSTRAINTS_free(bc); | ||
573 | |||
574 | return failed; | ||
575 | } | ||
576 | |||
577 | static int | ||
578 | test_x509v3_add1_i2d(void) | ||
579 | { | ||
580 | STACK_OF(X509_EXTENSION) *extensions; | ||
581 | int failed = 0; | ||
582 | |||
583 | if ((extensions = sk_X509_EXTENSION_new_null()) == NULL) | ||
584 | errx(1, "sk_X509_EXTENSION_new_null"); | ||
585 | |||
586 | failed |= test_x509v3_add1_i2d_empty_stack(&extensions); | ||
587 | failed |= test_x509v3_add1_i2d_single_nid(&extensions); | ||
588 | failed |= test_x509v3_add1_i2d_add_append(&extensions); | ||
589 | |||
590 | sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free); | ||
591 | |||
592 | return failed; | ||
593 | } | ||
594 | |||
595 | int | ||
596 | main(void) | ||
597 | { | ||
598 | int failed = 0; | ||
599 | |||
600 | failed |= test_x509v3_add1_i2d(); | ||
601 | |||
602 | return failed; | ||
603 | } | ||