xref: /openssl/test/recipes/25-test_req.t (revision 7e3f7f1d)
1#! /usr/bin/env perl
2# Copyright 2015-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
10use strict;
11use warnings;
12
13use OpenSSL::Test::Utils;
14use OpenSSL::Test qw/:DEFAULT srctop_file/;
15
16setup("test_req");
17
18plan tests => 111;
19
20require_ok(srctop_file('test', 'recipes', 'tconversion.pl'));
21
22my @certs = qw(test certs);
23
24# What type of key to generate?
25my @req_new;
26if (disabled("rsa")) {
27    @req_new = ("-newkey", "dsa:".srctop_file("apps", "dsa512.pem"));
28} else {
29    @req_new = ("-new");
30    note("There should be a 2 sequences of .'s and some +'s.");
31    note("There should not be more that at most 80 per line");
32}
33
34# Prevent MSys2 filename munging for arguments that look like file paths but
35# aren't
36$ENV{MSYS2_ARG_CONV_EXCL} = "/CN=";
37
38# Check for duplicate -addext parameters, and one "working" case.
39my @addext_args = ( "openssl", "req", "-new", "-out", "testreq-addexts.pem",
40                    "-key",  srctop_file(@certs, "ee-key.pem"),
41    "-config", srctop_file("test", "test.cnf"), @req_new );
42my $val = "subjectAltName=DNS:example.com";
43my $val1 = "subjectAltName=otherName:1.2.3.4;UTF8:test,email:info\@example.com";
44my $val2 = " " . $val;
45my $val3 = $val;
46$val3 =~ s/=/    =/;
47ok( run(app([@addext_args, "-addext", $val])));
48ok( run(app([@addext_args, "-addext", $val1])));
49$val1 =~ s/UTF8/XXXX/; # execute the error handling in do_othername
50ok(!run(app([@addext_args, "-addext", $val1])));
51ok(!run(app([@addext_args, "-addext", $val, "-addext", $val])));
52ok(!run(app([@addext_args, "-addext", $val, "-addext", $val2])));
53ok(!run(app([@addext_args, "-addext", $val, "-addext", $val3])));
54ok(!run(app([@addext_args, "-addext", $val2, "-addext", $val3])));
55ok(run(app([@addext_args, "-addext", "SXNetID=1:one, 2:two, 3:three"])));
56ok(run(app([@addext_args, "-addext", "subjectAltName=dirName:dirname_sec"])));
57
58ok(run(app([@addext_args, "-addext", "keyUsage=digitalSignature",
59           "-reqexts", "reqexts"]))); # referring to section in test.cnf
60
61# If a CSR is provided with neither of -key or -CA/-CAkey, this should fail.
62ok(!run(app(["openssl", "req", "-x509",
63                "-in", srctop_file(@certs, "x509-check.csr"),
64                "-out", "testreq.pem"])));
65
66subtest "generating alt certificate requests with RSA" => sub {
67    plan tests => 3;
68
69    SKIP: {
70        skip "RSA is not supported by this OpenSSL build", 2
71            if disabled("rsa");
72
73        ok(run(app(["openssl", "req",
74                    "-config", srctop_file("test", "test.cnf"),
75                    "-section", "altreq",
76                    "-new", "-out", "testreq-rsa.pem", "-utf8",
77                    "-key", srctop_file("test", "testrsa.pem")])),
78           "Generating request");
79
80        ok(run(app(["openssl", "req",
81                    "-config", srctop_file("test", "test.cnf"),
82                    "-verify", "-in", "testreq-rsa.pem", "-noout"])),
83           "Verifying signature on request");
84
85        ok(run(app(["openssl", "req",
86                    "-config", srctop_file("test", "test.cnf"),
87                    "-section", "altreq",
88                    "-verify", "-in", "testreq-rsa.pem", "-noout"])),
89           "Verifying signature on request");
90    }
91};
92
93
94subtest "generating certificate requests with RSA" => sub {
95    plan tests => 8;
96
97    SKIP: {
98        skip "RSA is not supported by this OpenSSL build", 2
99            if disabled("rsa");
100
101        ok(!run(app(["openssl", "req",
102                     "-config", srctop_file("test", "test.cnf"),
103                     "-new", "-out", "testreq-rsa.pem", "-utf8",
104                     "-key", srctop_file("test", "testrsa.pem"),
105                     "-keyform", "DER"])),
106           "Checking that mismatching keyform fails");
107
108        ok(run(app(["openssl", "req",
109                    "-config", srctop_file("test", "test.cnf"),
110                    "-new", "-out", "testreq-rsa.pem", "-utf8",
111                    "-key", srctop_file("test", "testrsa.pem"),
112                    "-keyform", "PEM"])),
113           "Generating request");
114
115        ok(run(app(["openssl", "req",
116                    "-config", srctop_file("test", "test.cnf"),
117                    "-verify", "-in", "testreq-rsa.pem", "-noout"])),
118           "Verifying signature on request");
119
120        ok(run(app(["openssl", "req",
121                    "-config", srctop_file("test", "test.cnf"),
122                    "-modulus", "-in", "testreq-rsa.pem", "-noout"])),
123           "Printing a modulus of the request key");
124
125        ok(run(app(["openssl", "req",
126                    "-config", srctop_file("test", "test.cnf"),
127                    "-new", "-out", "testreq_withattrs_pem.pem", "-utf8",
128                    "-key", srctop_file("test", "testrsa_withattrs.pem")])),
129           "Generating request from a key with extra attributes - PEM");
130
131        ok(run(app(["openssl", "req",
132                    "-config", srctop_file("test", "test.cnf"),
133                    "-verify", "-in", "testreq_withattrs_pem.pem", "-noout"])),
134           "Verifying signature on request from a key with extra attributes - PEM");
135
136        ok(run(app(["openssl", "req",
137                    "-config", srctop_file("test", "test.cnf"),
138                    "-new", "-out", "testreq_withattrs_der.pem", "-utf8",
139                    "-key", srctop_file("test", "testrsa_withattrs.der"),
140                    "-keyform", "DER"])),
141           "Generating request from a key with extra attributes - PEM");
142
143        ok(run(app(["openssl", "req",
144                    "-config", srctop_file("test", "test.cnf"),
145                    "-verify", "-in", "testreq_withattrs_der.pem", "-noout"])),
146           "Verifying signature on request from a key with extra attributes - PEM");
147    }
148};
149
150subtest "generating certificate requests with RSA-PSS" => sub {
151    plan tests => 12;
152
153    SKIP: {
154        skip "RSA is not supported by this OpenSSL build", 2
155            if disabled("rsa");
156
157        ok(run(app(["openssl", "req",
158                    "-config", srctop_file("test", "test.cnf"),
159                    "-new", "-out", "testreq-rsapss.pem", "-utf8",
160                    "-key", srctop_file("test", "testrsapss.pem")])),
161           "Generating request");
162        ok(run(app(["openssl", "req",
163                    "-config", srctop_file("test", "test.cnf"),
164                    "-verify", "-in", "testreq-rsapss.pem", "-noout"])),
165           "Verifying signature on request");
166
167        ok(run(app(["openssl", "req",
168                    "-config", srctop_file("test", "test.cnf"),
169                    "-new", "-out", "testreq-rsapss2.pem", "-utf8",
170                    "-sigopt", "rsa_padding_mode:pss",
171                    "-sigopt", "rsa_pss_saltlen:-1",
172                    "-key", srctop_file("test", "testrsapss.pem")])),
173           "Generating request");
174        ok(run(app(["openssl", "req",
175                    "-config", srctop_file("test", "test.cnf"),
176                    "-verify", "-in", "testreq-rsapss2.pem", "-noout"])),
177           "Verifying signature on request");
178
179        ok(run(app(["openssl", "req",
180                    "-config", srctop_file("test", "test.cnf"),
181                    "-new", "-out", "testreq-rsapssmand.pem", "-utf8",
182                    "-sigopt", "rsa_padding_mode:pss",
183                    "-key", srctop_file("test", "testrsapssmandatory.pem")])),
184           "Generating request");
185        ok(run(app(["openssl", "req",
186                    "-config", srctop_file("test", "test.cnf"),
187                    "-verify", "-in", "testreq-rsapssmand.pem", "-noout"])),
188           "Verifying signature on request");
189
190        ok(run(app(["openssl", "req",
191                    "-config", srctop_file("test", "test.cnf"),
192                    "-new", "-out", "testreq-rsapssmand2.pem", "-utf8",
193                    "-sigopt", "rsa_pss_saltlen:100",
194                    "-key", srctop_file("test", "testrsapssmandatory.pem")])),
195           "Generating request");
196        ok(run(app(["openssl", "req",
197                    "-config", srctop_file("test", "test.cnf"),
198                    "-verify", "-in", "testreq-rsapssmand2.pem", "-noout"])),
199           "Verifying signature on request");
200
201        ok(!run(app(["openssl", "req",
202                     "-config", srctop_file("test", "test.cnf"),
203                     "-new", "-out", "testreq-rsapss3.pem", "-utf8",
204                     "-sigopt", "rsa_padding_mode:pkcs1",
205                     "-key", srctop_file("test", "testrsapss.pem")])),
206           "Generating request with expected failure");
207
208        ok(!run(app(["openssl", "req",
209                     "-config", srctop_file("test", "test.cnf"),
210                     "-new", "-out", "testreq-rsapss3.pem", "-utf8",
211                     "-sigopt", "rsa_pss_saltlen:-5",
212                     "-key", srctop_file("test", "testrsapss.pem")])),
213           "Generating request with expected failure");
214
215        ok(!run(app(["openssl", "req",
216                     "-config", srctop_file("test", "test.cnf"),
217                     "-new", "-out", "testreq-rsapssmand3.pem", "-utf8",
218                     "-sigopt", "rsa_pss_saltlen:10",
219                     "-key", srctop_file("test", "testrsapssmandatory.pem")])),
220           "Generating request with expected failure");
221
222        ok(!run(app(["openssl", "req",
223                     "-config", srctop_file("test", "test.cnf"),
224                     "-new", "-out", "testreq-rsapssmand3.pem", "-utf8",
225                     "-sha256",
226                     "-key", srctop_file("test", "testrsapssmandatory.pem")])),
227           "Generating request with expected failure");
228    }
229};
230
231subtest "generating certificate requests with DSA" => sub {
232    plan tests => 2;
233
234    SKIP: {
235        skip "DSA is not supported by this OpenSSL build", 2
236            if disabled("dsa");
237
238        ok(run(app(["openssl", "req",
239                    "-config", srctop_file("test", "test.cnf"),
240                    "-new", "-out", "testreq-dsa.pem", "-utf8",
241                    "-key", srctop_file("test", "testdsa.pem")])),
242           "Generating request");
243
244        ok(run(app(["openssl", "req",
245                    "-config", srctop_file("test", "test.cnf"),
246                    "-verify", "-in", "testreq-dsa.pem", "-noout"])),
247           "Verifying signature on request");
248    }
249};
250
251subtest "generating certificate requests with ECDSA" => sub {
252    plan tests => 2;
253
254    SKIP: {
255        skip "ECDSA is not supported by this OpenSSL build", 2
256            if disabled("ec");
257
258        ok(run(app(["openssl", "req",
259                    "-config", srctop_file("test", "test.cnf"),
260                    "-new", "-out", "testreq-ec.pem", "-utf8",
261                    "-key", srctop_file("test", "testec-p256.pem")])),
262           "Generating request");
263
264        ok(run(app(["openssl", "req",
265                    "-config", srctop_file("test", "test.cnf"),
266                    "-verify", "-in", "testreq-ec.pem", "-noout"])),
267           "Verifying signature on request");
268    }
269};
270
271subtest "generating certificate requests with Ed25519" => sub {
272    plan tests => 2;
273
274    SKIP: {
275        skip "Ed25519 is not supported by this OpenSSL build", 2
276            if disabled("ecx");
277
278        ok(run(app(["openssl", "req",
279                    "-config", srctop_file("test", "test.cnf"),
280                    "-new", "-out", "testreq-ed25519.pem", "-utf8",
281                    "-key", srctop_file("test", "tested25519.pem")])),
282           "Generating request");
283
284        ok(run(app(["openssl", "req",
285                    "-config", srctop_file("test", "test.cnf"),
286                    "-verify", "-in", "testreq-ed25519.pem", "-noout"])),
287           "Verifying signature on request");
288    }
289};
290
291subtest "generating certificate requests with Ed448" => sub {
292    plan tests => 2;
293
294    SKIP: {
295        skip "Ed448 is not supported by this OpenSSL build", 2
296            if disabled("ecx");
297
298        ok(run(app(["openssl", "req",
299                    "-config", srctop_file("test", "test.cnf"),
300                    "-new", "-out", "testreq-ed448.pem", "-utf8",
301                    "-key", srctop_file("test", "tested448.pem")])),
302           "Generating request");
303
304        ok(run(app(["openssl", "req",
305                    "-config", srctop_file("test", "test.cnf"),
306                    "-verify", "-in", "testreq-ed448.pem", "-noout"])),
307           "Verifying signature on request");
308    }
309};
310
311subtest "generating certificate requests" => sub {
312    plan tests => 2;
313
314    ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"),
315                "-key", srctop_file(@certs, "ee-key.pem"),
316                @req_new, "-out", "testreq.pem"])),
317       "Generating request");
318
319    ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"),
320                "-verify", "-in", "testreq.pem", "-noout"])),
321       "Verifying signature on request");
322};
323
324subtest "generating SM2 certificate requests" => sub {
325    plan tests => 4;
326
327    SKIP: {
328        skip "SM2 is not supported by this OpenSSL build", 4
329        if disabled("sm2");
330        ok(run(app(["openssl", "req",
331                    "-config", srctop_file("test", "test.cnf"),
332                    "-new", "-key", srctop_file(@certs, "sm2.key"),
333                    "-sigopt", "distid:1234567812345678",
334                    "-out", "testreq-sm2.pem", "-sm3"])),
335           "Generating SM2 certificate request");
336
337        ok(run(app(["openssl", "req",
338                    "-config", srctop_file("test", "test.cnf"),
339                    "-verify", "-in", "testreq-sm2.pem", "-noout",
340                    "-vfyopt", "distid:1234567812345678", "-sm3"])),
341           "Verifying signature on SM2 certificate request");
342
343        ok(run(app(["openssl", "req",
344                    "-config", srctop_file("test", "test.cnf"),
345                    "-new", "-key", srctop_file(@certs, "sm2.key"),
346                    "-sigopt", "hexdistid:DEADBEEF",
347                    "-out", "testreq-sm2.pem", "-sm3"])),
348           "Generating SM2 certificate request with hex id");
349
350        ok(run(app(["openssl", "req",
351                    "-config", srctop_file("test", "test.cnf"),
352                    "-verify", "-in", "testreq-sm2.pem", "-noout",
353                    "-vfyopt", "hexdistid:DEADBEEF", "-sm3"])),
354           "Verifying signature on SM2 certificate request");
355    }
356};
357
358subtest "generating certificate requests with -cipher flag" => sub {
359    plan tests => 6;
360
361    diag("Testing -cipher flag with aes-256-cbc...");
362    ok(run(app(["openssl", "req",
363                "-config", srctop_file("test", "test.cnf"),
364                "-newkey", "rsa:2048",
365                "-keyout", "privatekey-aes256.pem",
366                "-out", "testreq-rsa-cipher.pem",
367                "-utf8",
368                "-cipher", "aes-256-cbc",
369                "-passout", "pass:password"])),
370       "Generating request with -cipher flag (AES-256-CBC)");
371
372    diag("Verifying signature for aes-256-cbc...");
373    ok(run(app(["openssl", "req",
374                "-config", srctop_file("test", "test.cnf"),
375                "-verify", "-in", "testreq-rsa-cipher.pem", "-noout"])),
376       "Verifying signature on request with -cipher (AES-256-CBC)");
377
378    open my $fh, '<', "privatekey-aes256.pem" or BAIL_OUT("Could not open key file: $!");
379    my $first_line = <$fh>;
380    close $fh;
381    ok($first_line =~ /^-----BEGIN ENCRYPTED PRIVATE KEY-----/,
382       "Check that the key file is encrypted (AES-256-CBC)");
383
384    diag("Testing -cipher flag with aes-128-cbc...");
385    ok(run(app(["openssl", "req",
386                "-config", srctop_file("test", "test.cnf"),
387                "-newkey", "rsa:2048",
388                "-keyout", "privatekey-aes128.pem",
389                "-out", "testreq-rsa-cipher-aes128.pem",
390                "-utf8",
391                "-cipher", "aes-128-cbc",
392                "-passout", "pass:password"])),
393       "Generating request with -cipher flag (AES-128-CBC)");
394
395    diag("Verifying signature for aes-128-cbc...");
396    ok(run(app(["openssl", "req",
397                "-config", srctop_file("test", "test.cnf"),
398                "-verify", "-in", "testreq-rsa-cipher-aes128.pem", "-noout"])),
399       "Verifying signature on request with -cipher (AES-128-CBC)");
400
401    open my $fh_aes128, '<', "privatekey-aes128.pem" or BAIL_OUT("Could not open key file: $!");
402    my $first_line_aes128 = <$fh_aes128>;
403    close $fh_aes128;
404    ok($first_line_aes128 =~ /^-----BEGIN ENCRYPTED PRIVATE KEY-----/,
405       "Check that the key file is encrypted (AES-128-CBC)");
406};
407
408my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf"));
409
410run_conversion('req conversions',
411               "testreq.pem");
412run_conversion('req conversions -- testreq2',
413               srctop_file("test", "testreq2.pem"));
414
415sub run_conversion {
416    my $title = shift;
417    my $reqfile = shift;
418
419    subtest $title => sub {
420        run(app(["openssl", @openssl_args,
421                 "-in", $reqfile, "-inform", "p",
422                 "-noout", "-text"],
423                stderr => "req-check.err", stdout => undef));
424        open DATA, "req-check.err";
425        SKIP: {
426            plan skip_all => "skipping req conversion test for $reqfile"
427                if grep /Unknown Public Key/, map { s/\R//; } <DATA>;
428
429            tconversion( -type => 'req', -in => $reqfile,
430                         -args => [ @openssl_args ] );
431        }
432        close DATA;
433        unlink "req-check.err";
434
435        done_testing();
436    };
437}
438
439# Test both generation and verification of certs w.r.t. RFC 5280 requirements
440
441my $ca_cert; # will be set below
442sub generate_cert {
443    my $cert = shift @_;
444    my $ss = $cert =~ m/self-signed/;
445    my $is_ca = $cert =~ m/CA/;
446    my $cn = $is_ca ? "CA" : "EE";
447    my $ca_key = srctop_file(@certs, "ca-key.pem");
448    my $key = $is_ca ? $ca_key : srctop_file(@certs, "ee-key.pem");
449    my @cmd = ("openssl", "req", "-config", "", "-x509",
450               "-subj", "/CN=$cn", @_, "-out", $cert);
451    push(@cmd, ("-key", $key)) if $ss;
452    push(@cmd, ("-CA", $ca_cert, "-CAkey", $ca_key)) unless $ss;
453    ok(run(app([@cmd])), "generate $cert");
454}
455
456sub has_keyUsage {
457    my $cert = shift @_;
458    my $expect = shift @_;
459    cert_contains($cert, "Key Usage", $expect);
460}
461sub strict_verify {
462    my $cert = shift @_;
463    my $expect = shift @_;
464    my $trusted = shift @_;
465    $trusted = $cert unless $trusted;
466    ok(run(app(["openssl", "verify", "-x509_strict", "-trusted", $trusted,
467                "-partial_chain", $cert])) == $expect,
468       "strict verify allow $cert");
469}
470
471my @v3_ca = ("-addext", "basicConstraints = critical,CA:true",
472             "-addext", "keyUsage = keyCertSign");
473my $SKID_AKID = "subjectKeyIdentifier,authorityKeyIdentifier";
474
475# # SKID
476
477my $cert = "self-signed_default_SKID_no_explicit_exts.pem";
478generate_cert($cert);
479has_version($cert, 3);
480has_SKID($cert, 1); # SKID added, though no explicit extensions given
481has_AKID($cert, 0);
482
483my $cert = "self-signed_v3_CA_hash_SKID.pem";
484generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = hash");
485has_SKID($cert, 1); # explicit hash SKID
486
487$cert = "self-signed_v3_CA_no_SKID.pem";
488generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = none");
489cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID
490#TODO strict_verify($cert, 0);
491
492$cert = "self-signed_v3_CA_given_SKID.pem";
493generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = 45");
494cert_contains($cert, "Subject Key Identifier: 45 ", 1); # given SKID
495strict_verify($cert, 1);
496
497# AKID of self-signed certs
498
499$cert = "self-signed_v1_CA_no_KIDs.pem";
500generate_cert($cert, "-x509v1");
501has_version($cert, 1);
502cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID
503#TODO strict_verify($cert, 1); # self-signed v1 root cert should be accepted as CA
504
505$ca_cert = "self-signed_v3_CA_default_SKID.pem"; # will also be used below
506generate_cert($ca_cert, @v3_ca);
507has_SKID($ca_cert, 1); # default SKID
508has_AKID($ca_cert, 0); # no default AKID
509strict_verify($ca_cert, 1);
510
511$cert = "self-signed_v3_CA_no_AKID.pem";
512generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = none");
513has_AKID($cert, 0); # forced no AKID
514
515$cert = "self-signed_v3_CA_explicit_AKID.pem";
516generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid");
517has_AKID($cert, 0); # for self-signed cert, AKID suppressed and not forced
518
519$cert = "self-signed_v3_CA_forced_AKID.pem";
520generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always");
521cert_ext_has_n_different_lines($cert, 3, $SKID_AKID); # forced AKID, AKID == SKID
522strict_verify($cert, 1);
523
524$cert = "self-signed_v3_CA_issuer_AKID.pem";
525generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer");
526has_AKID($cert, 0); # suppressed AKID since not forced
527
528$cert = "self-signed_v3_CA_forced_issuer_AKID.pem";
529generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer:always");
530cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # forced issuer AKID
531
532$cert = "self-signed_v3_CA_nonforced_keyid_issuer_AKID.pem";
533generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid, issuer");
534has_AKID($cert, 0); # AKID not present because not forced and cert self-signed
535
536$cert = "self-signed_v3_CA_keyid_forced_issuer_AKID.pem";
537generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid, issuer:always");
538cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # issuer AKID forced, with keyid not forced
539
540$cert = "self-signed_v3_CA_forced_keyid_issuer_AKID.pem";
541generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always, issuer");
542has_AKID($cert, 1); # AKID with keyid forced
543cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 0); # no issuer AKID
544
545$cert = "self-signed_v3_CA_forced_keyid_forced_issuer_AKID.pem";
546generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always, issuer:always");
547cert_contains($cert, "Authority Key Identifier: keyid(:[0-9A-Fa-f]{2})+ DirName:/CN=CA serial:", 1); # AKID with keyid and issuer forced
548
549$cert = "self-signed_v3_EE_wrong_keyUsage.pem";
550generate_cert($cert, "-addext", "keyUsage = keyCertSign");
551#TODO strict_verify($cert, 1); # should be accepted because RFC 5280 does not apply
552
553# AKID of self-issued but not self-signed certs
554
555$cert = "self-issued_x509_v3_CA_default_KIDs.pem";
556ok(run(app([("openssl", "x509", "-copy_extensions", "copy",
557             "-req", "-in", srctop_file(@certs, "ext-check.csr"),
558             "-key", srctop_file(@certs, "ca-key.pem"),
559             "-force_pubkey", srctop_file("test", "testrsapub.pem"),
560             "-out", $cert)])), "generate using x509: $cert");
561cert_contains($cert, "Issuer: CN=test .*? Subject: CN=test", 1);
562cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
563strict_verify($cert, 1);
564
565$cert = "self-issued_v3_CA_default_KIDs.pem";
566generate_cert($cert, "-addext", "keyUsage = dataEncipherment",
567    "-in", srctop_file(@certs, "x509-check.csr"));
568cert_contains($cert, "Issuer: CN=CA .*? Subject: CN=CA", 1);
569cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
570strict_verify($cert, 1);
571
572$cert = "self-issued_v3_CA_no_AKID.pem";
573generate_cert($cert, "-addext", "authorityKeyIdentifier = none",
574    "-in", srctop_file(@certs, "x509-check.csr"));
575has_version($cert, 3);
576has_SKID($cert, 1); # SKID added, though no explicit extensions given
577has_AKID($cert, 0);
578strict_verify($cert, 1);
579
580$cert = "self-issued_v3_CA_explicit_AKID.pem";
581generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid",
582    "-in", srctop_file(@certs, "x509-check.csr"));
583cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
584strict_verify($cert, 1);
585
586$cert = "self-issued_v3_CA_forced_AKID.pem";
587generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid:always",
588    "-in", srctop_file(@certs, "x509-check.csr"));
589cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
590
591$cert = "self-issued_v3_CA_issuer_AKID.pem";
592generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer",
593    "-in", srctop_file(@certs, "x509-check.csr"));
594cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # just issuer AKID
595
596$cert = "self-issued_v3_CA_forced_issuer_AKID.pem";
597generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer:always",
598    "-in", srctop_file(@certs, "x509-check.csr"));
599cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # just issuer AKID
600
601$cert = "self-issued_v3_CA_keyid_issuer_AKID.pem";
602generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid, issuer",
603    "-in", srctop_file(@certs, "x509-check.csr"));
604cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID, not forced
605
606$cert = "self-issued_v3_CA_keyid_forced_issuer_AKID.pem";
607generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid, issuer:always",
608    "-in", srctop_file(@certs, "x509-check.csr"));
609cert_ext_has_n_different_lines($cert, 6, $SKID_AKID); # SKID != AKID, with forced issuer
610
611$cert = "self-issued_v3_CA_forced_keyid_and_issuer_AKID.pem";
612generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid:always, issuer:always",
613    "-in", srctop_file(@certs, "x509-check.csr"));
614cert_ext_has_n_different_lines($cert, 6, $SKID_AKID); # SKID != AKID, both forced
615
616# AKID of not self-issued certs
617
618$cert = "regular_v3_EE_default_KIDs_no_other_exts.pem";
619generate_cert($cert, "-key", srctop_file(@certs, "ee-key.pem"));
620has_version($cert, 3);
621cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
622
623$cert = "regular_v3_EE_default_KIDs.pem";
624generate_cert($cert, "-addext", "keyUsage = dataEncipherment",
625    "-key", srctop_file(@certs, "ee-key.pem"));
626cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
627strict_verify($cert, 1, $ca_cert);
628
629$cert = "regular_v3_EE_copied_exts_default_KIDs.pem";
630generate_cert($cert, "-copy_extensions", "copy",
631              "-in", srctop_file(@certs, "ext-check.csr"));
632cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
633strict_verify($cert, 1);
634
635$cert = "v3_EE_no_AKID.pem";
636generate_cert($cert, "-addext", "authorityKeyIdentifier = none",
637    "-key", srctop_file(@certs, "ee-key.pem"));
638has_SKID($cert, 1);
639has_AKID($cert, 0);
640strict_verify($cert, 0, $ca_cert);
641
642
643# Key Usage
644
645$cert = "self-signed_CA_no_keyUsage.pem";
646generate_cert($cert, "-in", srctop_file(@certs, "ext-check.csr"));
647has_keyUsage($cert, 0);
648$cert = "self-signed_CA_with_keyUsages.pem";
649generate_cert($cert, "-in", srctop_file(@certs, "ext-check.csr"),
650    "-copy_extensions", "copy");
651has_keyUsage($cert, 1);
652
653# Generate cert using req with '-modulus'
654ok(run(app(["openssl", "req", "-x509", "-new", "-days", "365",
655            "-key", srctop_file("test", "testrsa.pem"),
656            "-config", srctop_file('test', 'test.cnf'),
657            "-out", "testreq-cert.pem",
658            "-modulus"])), "cert req creation - with -modulus");
659
660# Verify cert
661ok(run(app(["openssl", "x509", "-in", "testreq-cert.pem",
662            "-noout", "-text"])), "cert verification");
663
664# Generate cert with explicit start and end dates
665my %today = (strftime("%Y-%m-%d", gmtime) => 1);
666my $cert = "self-signed_explicit_date.pem";
667ok(run(app(["openssl", "req", "-x509", "-new", "-text",
668            "-config", srctop_file('test', 'test.cnf'),
669            "-key", srctop_file("test", "testrsa.pem"),
670            "-not_before", "today",
671            "-not_after", "today",
672            "-out", $cert]))
673&& ++$today{strftime("%Y-%m-%d", gmtime)}
674&& (grep { defined $today{$_} } get_not_before_date($cert))
675&& (grep { defined $today{$_} } get_not_after_date($cert)), "explicit start and end dates");
676