xref: /freebsd/crypto/openssl/test/recipes/25-test_x509.t (revision 7e97c6adffde3bd6f60f042ed2603335c005c6a7)
1#! /usr/bin/env perl
2# Copyright 2015-2025 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 File::Spec;
14use OpenSSL::Test::Utils;
15use OpenSSL::Test qw/:DEFAULT srctop_file/;
16
17setup("test_x509");
18
19plan tests => 138;
20
21# Prevent MSys2 filename munging for arguments that look like file paths but
22# aren't
23$ENV{MSYS2_ARG_CONV_EXCL} = "/CN=";
24
25require_ok(srctop_file("test", "recipes", "tconversion.pl"));
26
27my @certs = qw(test certs);
28my $pem = srctop_file(@certs, "cyrillic.pem");
29my $out_msb = "out-cyrillic.msb";
30my $out_utf8 = "out-cyrillic.utf8";
31my $der = "cyrillic.der";
32my $der2 = "cyrillic.der";
33my $msb = srctop_file(@certs, "cyrillic.msb");
34my $utf = srctop_file(@certs, "cyrillic.utf8");
35
36ok(run(app(["openssl", "x509", "-text", "-in", $pem, "-out", $out_msb,
37            "-nameopt", "esc_msb"])));
38is(cmp_text($out_msb, $msb),
39   0, 'Comparing esc_msb output with cyrillic.msb');
40ok(run(app(["openssl", "x509", "-text", "-in", $pem, "-out", $out_utf8,
41            "-nameopt", "utf8"])));
42is(cmp_text($out_utf8, $utf),
43   0, 'Comparing utf8 output with cyrillic.utf8');
44
45SKIP: {
46    skip "EdDSA disabled", 2 if disabled("ecx");
47
48    $pem = srctop_file(@certs, "tab-in-dn.pem");
49    my $out_text = "out-tab-in-dn.text";
50    my $text = srctop_file(@certs, "tab-in-dn.text");
51    ok(run(app(["openssl", "x509", "-text", "-noout",
52            "-in", $pem, "-out", $out_text])));
53    is(cmp_text($out_text, $text),
54       0, 'Comparing default output with tab-in-dn.text');
55}
56
57SKIP: {
58    skip "DES disabled", 1 if disabled("des");
59    skip "Platform doesn't support command line UTF-8", 1 if $^O =~ /^(VMS|msys)$/;
60
61    my $p12 = srctop_file("test", "shibboleth.pfx");
62    my $p12pass = "σύνθημα γνώρισμα";
63    my $out_pem = "out.pem";
64    ok(run(app(["openssl", "x509", "-text", "-in", $p12, "-out", $out_pem,
65                "-passin", "pass:$p12pass"])));
66    # not unlinking $out_pem
67}
68
69ok(!run(app(["openssl", "x509", "-in", $pem, "-inform", "DER",
70             "-out", $der, "-outform", "DER"])),
71   "Checking failure of mismatching -inform DER");
72ok(run(app(["openssl", "x509", "-in", $pem, "-inform", "PEM",
73            "-out", $der, "-outform", "DER"])),
74   "Conversion to DER");
75ok(!run(app(["openssl", "x509", "-in", $der, "-inform", "PEM",
76             "-out", $der2, "-outform", "DER"])),
77   "Checking failure of mismatching -inform PEM");
78
79# producing and checking self-issued (but not self-signed) cert
80my $subj = "/CN=CA"; # using same DN as in issuer of ee-cert.pem
81my $extfile = srctop_file("test", "v3_ca_exts.cnf");
82my $pkey = srctop_file(@certs, "ca-key.pem"); # issuer private key
83my $pubkey = "ca-pubkey.pem"; # the corresponding issuer public key
84# use any (different) key for signing our self-issued cert:
85my $key = srctop_file(@certs, "serverkey.pem");
86my $selfout = "self-issued.out";
87my $testcert = srctop_file(@certs, "ee-cert.pem");
88ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey]))
89&& run(app(["openssl", "x509", "-new", "-force_pubkey", $pubkey, "-subj", $subj,
90            "-extfile", $extfile, "-key", $key, "-out", $selfout]))
91&& run(app(["openssl", "verify", "-no_check_time",
92            "-trusted", $selfout, "-partial_chain", $testcert])));
93# not unlinking $pubkey
94# not unlinking $selfout
95
96# test -set_issuer option
97my $ca_issu = srctop_file(@certs, "ca-cert.pem"); # issuer cert
98my $caout_issu = "ca-issu.out";
99ok(run(app(["openssl", "x509", "-new", "-force_pubkey", $key, "-subj", "/CN=EE",
100            "-set_issuer", "/CN=TEST-CA", "-extfile", $extfile, "-CA", $ca_issu,
101            "-CAkey", $pkey, "-text", "-out", $caout_issu])));
102ok(get_issuer($caout_issu) =~ /CN=TEST-CA/);
103# not unlinking $caout
104
105# simple way of directly producing a CA-signed cert with private/pubkey input
106my $ca = srctop_file(@certs, "ca-cert.pem"); # issuer cert
107my $caout = "ca-issued.out";
108ok(run(app(["openssl", "x509", "-new", "-force_pubkey", $key, "-subj", "/CN=EE",
109            "-extfile", $extfile, "-CA", $ca, "-CAkey", $pkey, "-out", $caout]))
110&& run(app(["openssl", "verify", "-no_check_time",
111            "-trusted", $ca, "-partial_chain", $caout])));
112
113# test trust decoration
114ok(run(app(["openssl", "x509", "-in", $ca, "-addtrust", "emailProtection",
115            "-out", "ca-trusted.pem"])));
116cert_contains("ca-trusted.pem", "Trusted Uses: E-mail Protection",
117              1, 'trusted use - E-mail Protection');
118ok(run(app(["openssl", "x509", "-in", $ca, "-addreject", "emailProtection",
119            "-out", "ca-rejected.pem"])));
120cert_contains("ca-rejected.pem", "Rejected Uses: E-mail Protection",
121              1, 'rejected use - E-mail Protection');
122
123subtest 'x509 -- x.509 v1 certificate' => sub {
124    tconversion( -type => 'x509', -prefix => 'x509v1',
125                 -in => srctop_file("test", "testx509.pem") );
126};
127subtest 'x509 -- first x.509 v3 certificate' => sub {
128    tconversion( -type => 'x509', -prefix => 'x509v3-1',
129                 -in => srctop_file("test", "v3-cert1.pem") );
130};
131subtest 'x509 -- second x.509 v3 certificate' => sub {
132    tconversion( -type => 'x509', -prefix => 'x509v3-2',
133                 -in => srctop_file("test", "v3-cert2.pem") );
134};
135
136subtest 'x509 -- pathlen' => sub {
137    ok(run(test(["v3ext", srctop_file(@certs, "pathlen.pem")])));
138};
139
140cert_contains(srctop_file(@certs, "fake-gp.pem"),
141              "2.16.528.1.1003.1.3.5.5.2-1-0000006666-Z-12345678-01.015-12345678",
142              1, 'x500 -- subjectAltName');
143
144cert_contains(srctop_file(@certs, "ext-noAssertion.pem"),
145              "No Assertion",
146              1, 'X.509 Not Assertion Extension');
147
148cert_contains(srctop_file(@certs, "ext-groupAC.pem"),
149              "Group Attribute Certificate",
150              1, 'X.509 Group Attribute Certificate Extension');
151
152cert_contains(srctop_file(@certs, "ext-sOAIdentifier.pem"),
153              "Source of Authority",
154              1, 'X.509 Source of Authority Extension');
155
156cert_contains(srctop_file(@certs, "ext-noRevAvail.pem"),
157              "No Revocation Available",
158              1, 'X.509 No Revocation Available');
159
160cert_contains(srctop_file(@certs, "ext-singleUse.pem"),
161              "Single Use",
162              1, 'X509v3 Single Use');
163
164cert_contains(srctop_file(@certs, "ext-indirectIssuer.pem"),
165              "Indirect Issuer",
166              1, 'X.509 Indirect Issuer');
167
168my $tgt_info_cert = srctop_file(@certs, "ext-targetingInformation.pem");
169cert_contains($tgt_info_cert,
170              "AC Targeting",
171              1, 'X.509 Targeting Information Extension');
172cert_contains($tgt_info_cert,
173              "Targets:",
174              1, 'X.509 Targeting Information Targets');
175cert_contains($tgt_info_cert,
176              "Target:",
177              1, 'X.509 Targeting Information Target');
178cert_contains($tgt_info_cert,
179              "Target Name: DirName:CN = W",
180              1, 'X.509 Targeting Information Target Name');
181cert_contains($tgt_info_cert,
182              "Target Group: DNS:wildboarsoftware.com",
183              1, 'X.509 Targeting Information Target Name');
184cert_contains($tgt_info_cert,
185              "Issuer Names:",
186              1, 'X.509 Targeting Information Issuer Names');
187cert_contains($tgt_info_cert,
188              "Issuer Serial: 01020304",
189              1, 'X.509 Targeting Information Issuer Serial');
190cert_contains($tgt_info_cert,
191              "Issuer UID: B0",
192              1, 'X.509 Targeting Information Issuer UID');
193cert_contains($tgt_info_cert,
194              "Digest Type: Public Key",
195              1, 'X.509 Targeting Information Object Digest Type');
196
197my $hnc_cert = srctop_file(@certs, "ext-holderNameConstraints.pem");
198cert_contains($hnc_cert,
199              "X509v3 Holder Name Constraints",
200              1, 'X.509 Holder Name Constraints');
201cert_contains($hnc_cert,
202              "Permitted:",
203              1, 'X.509 Holder Name Constraints Permitted');
204cert_contains($hnc_cert,
205              "DirName:CN = Wildboar",
206              1, 'X.509 Holder Name Constraint');
207
208my $dnc_cert = srctop_file(@certs, "ext-delegatedNameConstraints.pem");
209cert_contains($dnc_cert,
210              "X509v3 Delegated Name Constraints",
211              1, 'X.509 Delegated Name Constraints');
212cert_contains($dnc_cert,
213              "Permitted:",
214              1, 'X.509 Delegated Name Constraints Permitted');
215cert_contains($dnc_cert,
216              "DirName:CN = Wildboar",
217              1, 'X.509 Delegated Name Constraint');
218my $sda_cert = srctop_file(@certs, "ext-subjectDirectoryAttributes.pem");
219cert_contains($sda_cert,
220              "Steve Brule",
221              1, 'X.509 Subject Directory Attributes');
222cert_contains($sda_cert,
223              "CN=Hi mom",
224              1, 'X.509 Subject Directory Attributes');
225cert_contains($sda_cert,
226              "<No Values>",
227              1, 'X.509 Subject Directory Attributes');
228cert_contains($sda_cert,
229              "Funkytown",
230              1, 'X.509 Subject Directory Attributes');
231cert_contains($sda_cert,
232              "commonName",
233              1, 'X.509 Subject Directory Attributes');
234cert_contains($sda_cert,
235              "owner",
236              1, 'X.509 Subject Directory Attributes');
237cert_contains($sda_cert,
238              "givenName",
239              1, 'X.509 Subject Directory Attributes');
240cert_contains($sda_cert,
241              "localityName",
242              1, 'X.509 Subject Directory Attributes');
243
244my $ass_info_cert = srctop_file(@certs, "ext-associatedInformation.pem");
245cert_contains($ass_info_cert,
246              "Steve Brule",
247              1, 'X509v3 Associated Information');
248cert_contains($ass_info_cert,
249              "CN=Hi mom",
250              1, 'X509v3 Associated Information');
251cert_contains($ass_info_cert,
252              "<No Values>",
253              1, 'X509v3 Associated Information');
254cert_contains($ass_info_cert,
255              "Funkytown",
256              1, 'X509v3 Associated Information');
257cert_contains($ass_info_cert,
258              "commonName",
259              1, 'X509v3 Associated Information');
260cert_contains($ass_info_cert,
261              "owner",
262              1, 'X509v3 Associated Information');
263cert_contains($sda_cert,
264              "givenName",
265              1, 'X509v3 Associated Information');
266cert_contains($ass_info_cert,
267              "localityName",
268              1, 'X509v3 Associated Information');
269
270my $acc_cert_pol = srctop_file(@certs, "ext-acceptableCertPolicies.pem");
271cert_contains($acc_cert_pol,
272              "X509v3 Acceptable Certification Policies",
273              1, 'X509v3 Acceptable Certification Policies');
274# Yes, I know these OIDs make no sense in a policies extension. It's just a test.
275cert_contains($acc_cert_pol,
276              "organizationalUnitName",
277              1, 'X509v3 Acceptable Certification Policies');
278cert_contains($acc_cert_pol,
279              "description",
280              1, 'X509v3 Acceptable Certification Policies');
281
282my $acc_priv_pol = srctop_file(@certs, "ext-acceptablePrivilegePolicies.pem");
283cert_contains($acc_priv_pol,
284              "X509v3 Acceptable Privilege Policies",
285              1, 'X509v3 Acceptable Privilege Policies');
286# Yes, I know these OIDs make no sense in a policies extension. It's just a test.
287cert_contains($acc_priv_pol,
288              "commonName",
289              1, 'X509v3 Acceptable Certification Policies');
290cert_contains($acc_priv_pol,
291              "organizationName",
292              1, 'X509v3 Acceptable Certification Policies');
293
294my $user_notice_cert = srctop_file(@certs, "ext-userNotice.pem");
295cert_contains($user_notice_cert,
296              "Organization: Wildboar Software",
297              1, 'X509v3 User Notice');
298cert_contains($user_notice_cert,
299              "Numbers: 123, 456",
300              1, 'X509v3 User Notice');
301cert_contains($user_notice_cert,
302              "Explicit Text: Hey there big boi",
303              1, 'X509v3 User Notice');
304cert_contains($user_notice_cert,
305              "Number: 50505",
306              1, 'X509v3 User Notice');
307cert_contains($user_notice_cert,
308              "Explicit Text: Ice ice baby",
309              1, 'X509v3 User Notice');
310
311my $battcons_cert = srctop_file(@certs, "ext-basicAttConstraints.pem");
312cert_contains($battcons_cert,
313              "authority:TRUE",
314              1, 'X.509 Basic Attribute Constraints Authority');
315cert_contains($battcons_cert,
316              "pathlen:3",
317              1, 'X.509 Basic Attribute Constraints Path Length');
318
319my $audit_id_cert = srctop_file(@certs, "ext-auditIdentity.pem");
320cert_contains($audit_id_cert,
321              "09:08:07",
322              1, 'X509v3 Audit Identity');
323
324my $iobo_cert = srctop_file(@certs, "ext-issuedOnBehalfOf.pem");
325cert_contains($iobo_cert,
326              "DirName:CN = Wildboar",
327              1, 'X.509 Issued On Behalf Of');
328
329my $auth_att_id_cert = srctop_file(@certs, "ext-authorityAttributeIdentifier.pem");
330cert_contains($auth_att_id_cert,
331              "DirName:CN = Wildboar",
332              1, 'X.509 Authority Attribute Identifier');
333cert_contains($auth_att_id_cert,
334              "Issuer Serial: 01030507",
335              1, 'X.509 Authority Attribute Identifier');
336cert_contains($auth_att_id_cert,
337              "Issuer UID: B2",
338              1, 'X.509 Authority Attribute Identifier');
339
340my $role_spec_cert = srctop_file(@certs, "ext-roleSpecCertIdentifier.pem");
341cert_contains($role_spec_cert,
342              "Role Name: DirName:CN = Wildboar",
343              1, 'X.509 Role Spec Certificate Identifier');
344cert_contains($role_spec_cert,
345              "Role Certificate Issuer: DirName:CN",
346              1, 'X.509 Role Spec Certificate Identifier');
347cert_contains($role_spec_cert,
348              "Role Certificate Serial Number: 33818120 \\(0x2040608\\)",
349              1, 'X.509 Role Spec Certificate Identifier');
350cert_contains($role_spec_cert,
351              "DNS:wildboarsoftware.com",
352              1, 'X.509 Role Spec Certificate Identifier');
353cert_contains($role_spec_cert,
354              "Registered ID:description",
355              1, 'X.509 Role Spec Certificate Identifier');
356
357my $attr_desc_cert = srctop_file(@certs, "ext-attributeDescriptor.pem");
358cert_contains($attr_desc_cert,
359              "Identifier: 2.5.4.3",
360              1, 'X.509 Attribute Descriptor');
361# This comes from the syntax field, which starts on the next line.
362cert_contains($attr_desc_cert,
363              "UnboundedDirectoryString",
364              1, 'X.509 Attribute Descriptor');
365cert_contains($attr_desc_cert,
366              "Name: commonName",
367              1, 'X.509 Attribute Descriptor');
368# These comes from the dominationRule field.
369cert_contains($attr_desc_cert,
370              "Privilege Policy Identifier: 2.5.4.10",
371              1, 'X.509 Attribute Descriptor');
372cert_contains($attr_desc_cert,
373              "DirName:CN = Wildboar",
374              1, 'X.509 Attribute Descriptor');
375cert_contains($attr_desc_cert,
376              "Algorithm: sha256",
377              1, 'X.509 Attribute Descriptor');
378
379my $time_spec_abs_cert = srctop_file(@certs, "ext-timeSpecification-absolute.pem");
380cert_contains($time_spec_abs_cert,
381              "Timezone: UTC-05:00",
382              1, 'X.509 Time Specification (Absolute)');
383cert_contains($time_spec_abs_cert,
384              "Absolute: Any time between Dec 20 13:07:21 2022 GMT and Dec 20 13:07:21 2022 GMT",
385              1, 'X.509 Time Specification (Absolute)');
386
387my $time_spec_per_cert = srctop_file(@certs, "ext-timeSpecification-periodic.pem");
388cert_contains($time_spec_per_cert,
389              "Timezone: UTC-05:00",
390              1, 'X.509 Time Specification (Periodic)');
391cert_contains($time_spec_per_cert,
392              "NOT this time:",
393              1, 'X.509 Time Specification (Periodic)');
394cert_contains($time_spec_per_cert,
395              "05:43:21 - 12:34:56",
396              1, 'X.509 Time Specification (Periodic)');
397cert_contains($time_spec_per_cert,
398              "Days of the week: SUN, MON",
399              1, 'X.509 Time Specification (Periodic)');
400cert_contains($time_spec_per_cert,
401              "Weeks of the month: 3, 4",
402              1, 'X.509 Time Specification (Periodic)');
403cert_contains($time_spec_per_cert,
404              "Months: MAY, JUN",
405              1, 'X.509 Time Specification (Periodic)');
406cert_contains($time_spec_per_cert,
407              "Years: 2022, 2023",
408              1, 'X.509 Time Specification (Periodic)');
409cert_contains($time_spec_per_cert,
410              "Months: JUL, AUG",
411              1, 'X.509 Time Specification (Periodic)');
412cert_contains($time_spec_per_cert,
413              "Years: 2023, 2024",
414              1, 'X.509 Time Specification (Periodic)');
415
416my $attr_map_cert = srctop_file(@certs, "ext-attributeMappings.pem");
417cert_contains($attr_map_cert,
418              "commonName == localityName",
419              1, 'X.509 Attribute Mappings');
420# localityName has an INTEGER value here, which was intentional to test the
421# display of non-string values.
422cert_contains($attr_map_cert,
423              "commonName:asdf == localityName:03:3E",
424              1, 'X.509 Attribute Mappings');
425
426my $aaa_cert = srctop_file(@certs, "ext-allowedAttributeAssignments.pem");
427cert_contains($aaa_cert,
428              "Attribute Type: commonName",
429              1, 'X.509 Allowed Attribute Assignments');
430cert_contains($aaa_cert,
431              "Holder Domain: email:jonathan.wilbur",
432              1, 'X.509 Allowed Attribute Assignments');
433
434my $aa_idp_cert = srctop_file(@certs, "ext-aAissuingDistributionPoint.pem");
435cert_contains($aa_idp_cert,
436              "DirName:CN = Wildboar",
437              1, 'X.509 Attribute Authority Issuing Distribution Point');
438cert_contains($aa_idp_cert,
439              "CA Compromise",
440              1, 'X.509 Attribute Authority Issuing Distribution Point');
441cert_contains($aa_idp_cert,
442              "Indirect CRL: TRUE",
443              1, 'X.509 Attribute Authority Issuing Distribution Point');
444cert_contains($aa_idp_cert,
445              "Contains User Attribute Certificates: TRUE",
446              1, 'X.509 Attribute Authority Issuing Distribution Point');
447cert_contains($aa_idp_cert,
448              "Contains Attribute Authority \\(AA\\) Certificates: TRUE",
449              1, 'X.509 Attribute Authority Issuing Distribution Point');
450cert_contains($aa_idp_cert,
451              "Contains Source Of Authority \\(SOA\\) Public Key Certificates: TRUE",
452              1, 'X.509 Attribute Authority Issuing Distribution Point');
453
454sub test_errors { # actually tests diagnostics of OSSL_STORE
455    my ($expected, $cert, @opts) = @_;
456    my $infile = srctop_file(@certs, $cert);
457    my @args = qw(openssl x509 -in);
458    push(@args, $infile, @opts);
459    my $tmpfile = 'out.txt';
460    my $res =  grep(/-text/, @opts) ? run(app([@args], stdout => $tmpfile))
461                                    : !run(app([@args], stderr => $tmpfile));
462    my $found = 0;
463    open(my $in, '<', $tmpfile) or die "Could not open file $tmpfile";
464    while(<$in>) {
465        print; # this may help debugging
466        $res &&= !m/asn1 encoding/; # output must not include ASN.1 parse errors
467        $found = 1 if m/$expected/; # output must include $expected
468    }
469    close $in;
470    # $tmpfile is kept to help with investigation in case of failure
471    return $res && $found;
472}
473
474# 3 tests for non-existence of spurious OSSL_STORE ASN.1 parse error output.
475# This requires provoking a failure exit of the app after reading input files.
476ok(test_errors("Bad output format", "root-cert.pem", '-outform', 'http'),
477   "load root-cert errors");
478ok(test_errors("RC2-40-CBC", "v3-certs-RC2.p12", '-passin', 'pass:v3-certs'),
479   "load v3-certs-RC2 no asn1 errors"); # error msg should mention "RC2-40-CBC"
480SKIP: {
481    skip "sm2 not disabled", 1 if !disabled("sm2");
482
483    ok(test_errors("Unable to load Public Key", "sm2.pem", '-text'),
484       "error loading unsupported sm2 cert");
485}
486
487# 3 tests for -dateopts formats
488ok(run(app(["openssl", "x509", "-noout", "-dates", "-dateopt", "rfc_822",
489	     "-in", srctop_file("test/certs", "ca-cert.pem")])),
490   "Run with rfc_8222 -dateopt format");
491ok(run(app(["openssl", "x509", "-noout", "-dates", "-dateopt", "iso_8601",
492	     "-in", srctop_file("test/certs", "ca-cert.pem")])),
493   "Run with iso_8601 -dateopt format");
494ok(!run(app(["openssl", "x509", "-noout", "-dates", "-dateopt", "invalid_format",
495	     "-in", srctop_file("test/certs", "ca-cert.pem")])),
496   "Run with invalid -dateopt format");
497
498# Tests for signing certs (broken in 1.1.1o)
499my $a_key = "a-key.pem";
500my $a_cert = "a-cert.pem";
501my $a2_cert = "a2-cert.pem";
502my $ca_key = "ca-key.pem";
503my $ca_cert = "ca-cert.pem";
504my $cnf = srctop_file('apps', 'openssl.cnf');
505
506# Create cert A
507ok(run(app(["openssl", "req", "-x509", "-newkey", "rsa:2048",
508            "-config", $cnf,
509            "-keyout", $a_key, "-out", $a_cert, "-days", "365",
510            "-nodes", "-subj", "/CN=test.example.com"])));
511# Create cert CA - note key size
512ok(run(app(["openssl", "req", "-x509", "-newkey", "rsa:4096",
513            "-config", $cnf,
514            "-keyout", $ca_key, "-out", $ca_cert, "-days", "3650",
515            "-nodes", "-subj", "/CN=ca.example.com"])));
516# Sign cert A with CA (errors on 1.1.1o)
517ok(run(app(["openssl", "x509", "-in", $a_cert, "-CA", $ca_cert,
518            "-CAkey", $ca_key, "-set_serial", "1234567890",
519            "-preserve_dates", "-sha256", "-text", "-out", $a2_cert])));
520# verify issuer is CA
521ok(get_issuer($a2_cert) =~ /CN=ca.example.com/);
522
523my $in_csr = srctop_file('test', 'certs', 'x509-check.csr');
524my $in_key = srctop_file('test', 'certs', 'x509-check-key.pem');
525my $invextfile = srctop_file('test', 'invalid-x509.cnf');
526# Test that invalid extensions settings fail
527ok(!run(app(["openssl", "x509", "-req", "-in", $in_csr, "-signkey", $in_key,
528            "-out", "/dev/null", "-days", "3650" , "-extensions", "ext",
529            "-extfile", $invextfile])));
530
531# Tests for issue #16080 (fixed in 1.1.1o)
532my $b_key = "b-key.pem";
533my $b_csr = "b-cert.csr";
534my $b_cert = "b-cert.pem";
535# Create the CSR
536ok(run(app(["openssl", "req", "-new", "-newkey", "rsa:4096",
537            "-keyout", $b_key, "-out", $b_csr, "-nodes",
538            "-config", $cnf,
539            "-subj", "/CN=b.example.com"])));
540# Sign it - position of "-text" matters!
541ok(run(app(["openssl", "x509", "-req", "-text", "-CAcreateserial",
542            "-CA", $ca_cert, "-CAkey", $ca_key,
543            "-in", $b_csr, "-out", $b_cert])));
544# Verify issuer is CA
545ok(get_issuer($b_cert) =~ /CN=ca.example.com/);
546
547# although no explicit extensions given:
548has_version($b_cert, 3);
549has_SKID($b_cert, 1);
550has_AKID($b_cert, 1);
551
552# Tests for https://github.com/openssl/openssl/issues/10442 (fixed in 1.1.1a)
553# (incorrect default `-CAcreateserial` if `-CA` path has a dot in it)
554my $folder_with_dot = "test_x509.folder";
555ok(mkdir $folder_with_dot);
556my $ca_cert_dot_in_dir = File::Spec->catfile($folder_with_dot, "ca-cert.pem");
557ok(copy($ca_cert,$ca_cert_dot_in_dir));
558my $ca_serial_dot_in_dir = File::Spec->catfile($folder_with_dot, "ca-cert.srl");
559
560ok(run(app(["openssl", "x509", "-req", "-text", "-CAcreateserial",
561            "-CA", $ca_cert_dot_in_dir, "-CAkey", $ca_key,
562            "-in", $b_csr])));
563ok(-e $ca_serial_dot_in_dir);
564
565# Tests for explicit start and end dates of certificates
566my %today = (strftime("%Y-%m-%d", gmtime) => 1);
567my $enddate;
568ok(run(app(["openssl", "x509", "-req", "-text",
569	    "-key", $b_key,
570	    "-not_before", "20231031000000Z",
571	    "-not_after", "today",
572            "-in", $b_csr, "-out", $b_cert]))
573&& get_not_before($b_cert) =~ /Oct 31 00:00:00 2023 GMT/
574&& ++$today{strftime("%Y-%m-%d", gmtime)}
575&& (grep { defined $today{$_} } get_not_after_date($b_cert)));
576# explicit start and end dates
577ok(run(app(["openssl", "x509", "-req", "-text",
578	    "-key", $b_key,
579	    "-not_before", "20231031000000Z",
580	    "-not_after", "20231231000000Z",
581	    "-days", "99",
582            "-in", $b_csr, "-out", $b_cert]))
583&& get_not_before($b_cert) =~ /Oct 31 00:00:00 2023 GMT/
584&& get_not_after($b_cert) =~ /Dec 31 00:00:00 2023 GMT/);
585# start date today and days
586%today = (strftime("%Y-%m-%d", gmtime) => 1);
587$enddate = strftime("%Y-%m-%d", gmtime(time + 99 * 24 * 60 * 60));
588ok(run(app(["openssl", "x509", "-req", "-text",
589	    "-key", $b_key,
590	    "-not_before", "today",
591	    "-days", "99",
592            "-in", $b_csr, "-out", $b_cert]))
593&& ++$today{strftime("%Y-%m-%d", gmtime)}
594&& (grep { defined $today{$_} } get_not_before_date($b_cert))
595&& get_not_after_date($b_cert) eq $enddate);
596# end date before start date
597ok(!run(app(["openssl", "x509", "-req", "-text",
598	      "-key", $b_key,
599	      "-not_before", "today",
600	      "-not_after", "20231031000000Z",
601              "-in", $b_csr, "-out", $b_cert])));
602# default days option
603%today = (strftime("%Y-%m-%d", gmtime) => 1);
604$enddate = strftime("%Y-%m-%d", gmtime(time + 30 * 24 * 60 * 60));
605ok(run(app(["openssl", "x509", "-req", "-text",
606	    "-key", $b_key,
607            "-in", $b_csr, "-out", $b_cert]))
608&& ++$today{strftime("%Y-%m-%d", gmtime)}
609&& (grep { defined $today{$_} } get_not_before_date($b_cert))
610&& get_not_after_date($b_cert) eq $enddate);
611
612SKIP: {
613    skip "EC is not supported by this OpenSSL build", 1
614        if disabled("ec");
615    my $psscert = srctop_file(@certs, "ee-self-signed-pss.pem");
616
617    ok(run(test(["x509_test", $psscert])), "running x509_test");
618}
619