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 OpenSSL::Test::Utils; 14use OpenSSL::Test qw/:DEFAULT srctop_file/; 15 16setup("test_req"); 17 18plan tests => 116; 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 ML-DSA" => sub { 359 plan tests => 5; 360 361 SKIP: { 362 skip "ML-DSA is not supported by this OpenSSL build", 5 363 if disabled("ml-dsa"); 364 365 ok(run(app(["openssl", "req", 366 "-config", srctop_file("test", "test.cnf"), 367 "-x509", "-sha256", "-nodes", "-days", "365", 368 "-newkey", "ML-DSA-44", 369 "-keyout", "privatekey_ml_dsa_44.pem", 370 "-out", "cert_ml_dsa_44.pem", 371 "-subj", "/CN=test-self-signed", 372 "-addext","keyUsage=digitalSignature"])), 373 "Generating self signed ML-DSA-44 cert and private key"); 374 ok(run(app(["openssl", "req", 375 "-config", srctop_file("test", "test.cnf"), 376 "-x509", "-sha256", "-nodes", "-days", "365", 377 "-newkey", "ML-DSA-65", 378 "-keyout", "privatekey_ml_dsa_65.pem", 379 "-out", "cert_ml_dsa_65.pem", 380 "-subj", "/CN=test-self-signed", 381 "-addext","keyUsage=digitalSignature"])), 382 "Generating self signed ML-DSA-65 cert and private key"); 383 ok(run(app(["openssl", "req", 384 "-config", srctop_file("test", "test.cnf"), 385 "-x509", "-sha256", "-nodes", "-days", "365", 386 "-newkey", "ML-DSA-44", 387 "-keyout", "privatekey_ml_dsa_87.pem", 388 "-out", "cert_ml_dsa_87.pem", 389 "-subj", "/CN=test-self-signed", 390 "-addext","keyUsage=digitalSignature"])), 391 "Generating self signed ML-DSA-87 cert and private key"); 392 ok(run(app(["openssl", "req", 393 "-config", srctop_file("test", "test.cnf"), 394 "-new", 395 "-sigopt","hextest-entropy:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 396 "-out", "csr_ml_dsa_87.pem", 397 "-newkey", "ML-DSA-87", 398 "-passout", "pass:x"])), 399 "Generating ML-DSA-87 csr"); 400 ok(run(app(["openssl", "req", 401 "-config", srctop_file("test", "test.cnf"), 402 "-in", "csr_ml_dsa_87.pem"])), 403 "verifying ML-DSA-87 csr"); 404 } 405}; 406 407subtest "generating certificate requests with -cipher flag" => sub { 408 plan tests => 6; 409 410 diag("Testing -cipher flag with aes-256-cbc..."); 411 ok(run(app(["openssl", "req", 412 "-config", srctop_file("test", "test.cnf"), 413 "-newkey", "rsa:2048", 414 "-keyout", "privatekey-aes256.pem", 415 "-out", "testreq-rsa-cipher.pem", 416 "-utf8", 417 "-cipher", "aes-256-cbc", 418 "-passout", "pass:password"])), 419 "Generating request with -cipher flag (AES-256-CBC)"); 420 421 diag("Verifying signature for aes-256-cbc..."); 422 ok(run(app(["openssl", "req", 423 "-config", srctop_file("test", "test.cnf"), 424 "-verify", "-in", "testreq-rsa-cipher.pem", "-noout"])), 425 "Verifying signature on request with -cipher (AES-256-CBC)"); 426 427 open my $fh, '<', "privatekey-aes256.pem" or BAIL_OUT("Could not open key file: $!"); 428 my $first_line = <$fh>; 429 close $fh; 430 ok($first_line =~ /^-----BEGIN ENCRYPTED PRIVATE KEY-----/, 431 "Check that the key file is encrypted (AES-256-CBC)"); 432 433 diag("Testing -cipher flag with aes-128-cbc..."); 434 ok(run(app(["openssl", "req", 435 "-config", srctop_file("test", "test.cnf"), 436 "-newkey", "rsa:2048", 437 "-keyout", "privatekey-aes128.pem", 438 "-out", "testreq-rsa-cipher-aes128.pem", 439 "-utf8", 440 "-cipher", "aes-128-cbc", 441 "-passout", "pass:password"])), 442 "Generating request with -cipher flag (AES-128-CBC)"); 443 444 diag("Verifying signature for aes-128-cbc..."); 445 ok(run(app(["openssl", "req", 446 "-config", srctop_file("test", "test.cnf"), 447 "-verify", "-in", "testreq-rsa-cipher-aes128.pem", "-noout"])), 448 "Verifying signature on request with -cipher (AES-128-CBC)"); 449 450 open my $fh_aes128, '<', "privatekey-aes128.pem" or BAIL_OUT("Could not open key file: $!"); 451 my $first_line_aes128 = <$fh_aes128>; 452 close $fh_aes128; 453 ok($first_line_aes128 =~ /^-----BEGIN ENCRYPTED PRIVATE KEY-----/, 454 "Check that the key file is encrypted (AES-128-CBC)"); 455}; 456 457subtest "generating certificate requests with SLH-DSA" => sub { 458 plan tests => 5; 459 460 SKIP: { 461 skip "SLH-DSA is not supported by this OpenSSL build", 5 462 if disabled("slh-dsa"); 463 464 ok(run(app(["openssl", "req", 465 "-config", srctop_file("test", "test.cnf"), 466 "-x509", "-sha256", "-nodes", "-days", "365", 467 "-newkey", "SLH-DSA-SHA2-128f", 468 "-keyout", "privatekey_slh_dsa_sha2_128f.pem", 469 "-out", "cert_slh_dsa_sha2_128f.pem", 470 "-subj", "/CN=test-self-signed", 471 "-addext","keyUsage=digitalSignature"])), 472 "Generating self signed SLH-DSA-SHA2-128f cert and private key"); 473 ok(run(app(["openssl", "req", 474 "-config", srctop_file("test", "test.cnf"), 475 "-x509", "-sha256", "-nodes", "-days", "365", 476 "-newkey", "SLH-DSA-SHA2-256s", 477 "-keyout", "privatekey_slh_dsa_sha2_256s.pem", 478 "-out", "cert_slh_dsa_sha2_256s.pem", 479 "-subj", "/CN=test-self-signed", 480 "-addext","keyUsage=digitalSignature"])), 481 "Generating self signed SLH-DSA-SHA2-256s cert and private key"); 482 ok(run(app(["openssl", "req", 483 "-config", srctop_file("test", "test.cnf"), 484 "-x509", "-sha256", "-nodes", "-days", "365", 485 "-newkey", "SLH-DSA-SHAKE-256f", 486 "-keyout", "privatekey_slh_dsa_shake_256f.pem", 487 "-out", "cert_slh_dsa_shake_256f.pem", 488 "-subj", "/CN=test-self-signed", 489 "-addext","keyUsage=digitalSignature"])), 490 "Generating self signed SLH-DSA-SHAKE-256f cert and private key"); 491 ok(run(app(["openssl", "req", 492 "-config", srctop_file("test", "test.cnf"), 493 "-new", 494 "-sigopt","hextest-entropy:000102030405060708090a0b0c0d0e0f", 495 "-out", "csr_slh_dsa_shake128.pem", 496 "-newkey", "SLH-DSA-SHAKE-128s", 497 "-passout", "pass:x"])), 498 "Generating SLH-DSA-SHAKE-128s csr"); 499 ok(run(app(["openssl", "req", 500 "-config", srctop_file("test", "test.cnf"), 501 "-in", "csr_slh_dsa_shake128.pem"])), 502 "verifying SLH-DSA-SHAKE-128s csr"); 503 } 504}; 505 506my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf")); 507 508run_conversion('req conversions', 509 "testreq.pem"); 510run_conversion('req conversions -- testreq2', 511 srctop_file("test", "testreq2.pem")); 512 513sub run_conversion { 514 my $title = shift; 515 my $reqfile = shift; 516 517 subtest $title => sub { 518 run(app(["openssl", @openssl_args, 519 "-in", $reqfile, "-inform", "p", 520 "-noout", "-text"], 521 stderr => "req-check.err", stdout => undef)); 522 open DATA, "req-check.err"; 523 SKIP: { 524 plan skip_all => "skipping req conversion test for $reqfile" 525 if grep /Unknown Public Key/, map { s/\R//; } <DATA>; 526 527 tconversion( -type => 'req', -in => $reqfile, 528 -args => [ @openssl_args ] ); 529 } 530 close DATA; 531 unlink "req-check.err"; 532 533 done_testing(); 534 }; 535} 536 537# Test both generation and verification of certs w.r.t. RFC 5280 requirements 538 539my $ca_cert; # will be set below 540sub generate_cert { 541 my $cert = shift @_; 542 my $ss = $cert =~ m/self-signed/; 543 my $is_ca = $cert =~ m/CA/; 544 my $cn = $is_ca ? "CA" : "EE"; 545 my $ca_key = srctop_file(@certs, "ca-key.pem"); 546 my $key = $is_ca ? $ca_key : srctop_file(@certs, "ee-key.pem"); 547 my @cmd = ("openssl", "req", "-config", "", "-x509", 548 "-subj", "/CN=$cn", @_, "-out", $cert); 549 push(@cmd, ("-key", $key)) if $ss; 550 push(@cmd, ("-CA", $ca_cert, "-CAkey", $ca_key)) unless $ss; 551 ok(run(app([@cmd])), "generate $cert"); 552} 553 554sub has_keyUsage { 555 my $cert = shift @_; 556 my $expect = shift @_; 557 cert_contains($cert, "Key Usage", $expect); 558} 559sub strict_verify { 560 my $cert = shift @_; 561 my $expect = shift @_; 562 my $trusted = shift @_; 563 $trusted = $cert unless $trusted; 564 ok(run(app(["openssl", "verify", "-x509_strict", "-trusted", $trusted, 565 "-partial_chain", $cert])) == $expect, 566 "strict verify allow $cert"); 567} 568 569my @v3_ca = ("-addext", "basicConstraints = critical,CA:true", 570 "-addext", "keyUsage = keyCertSign"); 571my $SKID_AKID = "subjectKeyIdentifier,authorityKeyIdentifier"; 572 573# # SKID 574 575my $cert = "self-signed_default_SKID_no_explicit_exts.pem"; 576generate_cert($cert); 577has_version($cert, 3); 578has_SKID($cert, 1); # SKID added, though no explicit extensions given 579has_AKID($cert, 0); 580 581my $cert = "self-signed_v3_CA_hash_SKID.pem"; 582generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = hash"); 583has_SKID($cert, 1); # explicit hash SKID 584 585$cert = "self-signed_v3_CA_no_SKID.pem"; 586generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = none"); 587cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID 588#TODO strict_verify($cert, 0); 589 590$cert = "self-signed_v3_CA_given_SKID.pem"; 591generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = 45"); 592cert_contains($cert, "Subject Key Identifier: 45 ", 1); # given SKID 593strict_verify($cert, 1); 594 595# AKID of self-signed certs 596 597$cert = "self-signed_v1_CA_no_KIDs.pem"; 598generate_cert($cert, "-x509v1"); 599has_version($cert, 1); 600cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID 601#TODO strict_verify($cert, 1); # self-signed v1 root cert should be accepted as CA 602 603$ca_cert = "self-signed_v3_CA_default_SKID.pem"; # will also be used below 604generate_cert($ca_cert, @v3_ca); 605has_SKID($ca_cert, 1); # default SKID 606has_AKID($ca_cert, 0); # no default AKID 607strict_verify($ca_cert, 1); 608 609$cert = "self-signed_v3_CA_no_AKID.pem"; 610generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = none"); 611has_AKID($cert, 0); # forced no AKID 612 613$cert = "self-signed_v3_CA_explicit_AKID.pem"; 614generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid"); 615has_AKID($cert, 0); # for self-signed cert, AKID suppressed and not forced 616 617$cert = "self-signed_v3_CA_forced_AKID.pem"; 618generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always"); 619cert_ext_has_n_different_lines($cert, 3, $SKID_AKID); # forced AKID, AKID == SKID 620strict_verify($cert, 1); 621 622$cert = "self-signed_v3_CA_issuer_AKID.pem"; 623generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer"); 624has_AKID($cert, 0); # suppressed AKID since not forced 625 626$cert = "self-signed_v3_CA_forced_issuer_AKID.pem"; 627generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer:always"); 628cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # forced issuer AKID 629 630$cert = "self-signed_v3_CA_nonforced_keyid_issuer_AKID.pem"; 631generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid, issuer"); 632has_AKID($cert, 0); # AKID not present because not forced and cert self-signed 633 634$cert = "self-signed_v3_CA_keyid_forced_issuer_AKID.pem"; 635generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid, issuer:always"); 636cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # issuer AKID forced, with keyid not forced 637 638$cert = "self-signed_v3_CA_forced_keyid_issuer_AKID.pem"; 639generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always, issuer"); 640has_AKID($cert, 1); # AKID with keyid forced 641cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 0); # no issuer AKID 642 643$cert = "self-signed_v3_CA_forced_keyid_forced_issuer_AKID.pem"; 644generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = keyid:always, issuer:always"); 645cert_contains($cert, "Authority Key Identifier: keyid(:[0-9A-Fa-f]{2})+ DirName:/CN=CA serial:", 1); # AKID with keyid and issuer forced 646 647$cert = "self-signed_v3_EE_wrong_keyUsage.pem"; 648generate_cert($cert, "-addext", "keyUsage = keyCertSign"); 649#TODO strict_verify($cert, 1); # should be accepted because RFC 5280 does not apply 650 651# AKID of self-issued but not self-signed certs 652 653$cert = "self-issued_x509_v3_CA_default_KIDs.pem"; 654ok(run(app([("openssl", "x509", "-copy_extensions", "copy", 655 "-req", "-in", srctop_file(@certs, "ext-check.csr"), 656 "-key", srctop_file(@certs, "ca-key.pem"), 657 "-force_pubkey", srctop_file("test", "testrsapub.pem"), 658 "-out", $cert)])), "generate using x509: $cert"); 659cert_contains($cert, "Issuer: CN=test .*? Subject: CN=test", 1); 660cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 661strict_verify($cert, 1); 662 663$cert = "self-issued_v3_CA_default_KIDs.pem"; 664generate_cert($cert, "-addext", "keyUsage = dataEncipherment", 665 "-in", srctop_file(@certs, "x509-check.csr")); 666cert_contains($cert, "Issuer: CN=CA .*? Subject: CN=CA", 1); 667cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 668strict_verify($cert, 1); 669 670$cert = "self-issued_v3_CA_no_AKID.pem"; 671generate_cert($cert, "-addext", "authorityKeyIdentifier = none", 672 "-in", srctop_file(@certs, "x509-check.csr")); 673has_version($cert, 3); 674has_SKID($cert, 1); # SKID added, though no explicit extensions given 675has_AKID($cert, 0); 676strict_verify($cert, 1); 677 678$cert = "self-issued_v3_CA_explicit_AKID.pem"; 679generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid", 680 "-in", srctop_file(@certs, "x509-check.csr")); 681cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 682strict_verify($cert, 1); 683 684$cert = "self-issued_v3_CA_forced_AKID.pem"; 685generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid:always", 686 "-in", srctop_file(@certs, "x509-check.csr")); 687cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 688 689$cert = "self-issued_v3_CA_issuer_AKID.pem"; 690generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer", 691 "-in", srctop_file(@certs, "x509-check.csr")); 692cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # just issuer AKID 693 694$cert = "self-issued_v3_CA_forced_issuer_AKID.pem"; 695generate_cert($cert, @v3_ca, "-addext", "authorityKeyIdentifier = issuer:always", 696 "-in", srctop_file(@certs, "x509-check.csr")); 697cert_contains($cert, "Authority Key Identifier: DirName:/CN=CA serial:", 1); # just issuer AKID 698 699$cert = "self-issued_v3_CA_keyid_issuer_AKID.pem"; 700generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid, issuer", 701 "-in", srctop_file(@certs, "x509-check.csr")); 702cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID, not forced 703 704$cert = "self-issued_v3_CA_keyid_forced_issuer_AKID.pem"; 705generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid, issuer:always", 706 "-in", srctop_file(@certs, "x509-check.csr")); 707cert_ext_has_n_different_lines($cert, 6, $SKID_AKID); # SKID != AKID, with forced issuer 708 709$cert = "self-issued_v3_CA_forced_keyid_and_issuer_AKID.pem"; 710generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid:always, issuer:always", 711 "-in", srctop_file(@certs, "x509-check.csr")); 712cert_ext_has_n_different_lines($cert, 6, $SKID_AKID); # SKID != AKID, both forced 713 714# AKID of not self-issued certs 715 716$cert = "regular_v3_EE_default_KIDs_no_other_exts.pem"; 717generate_cert($cert, "-key", srctop_file(@certs, "ee-key.pem")); 718has_version($cert, 3); 719cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 720 721$cert = "regular_v3_EE_default_KIDs.pem"; 722generate_cert($cert, "-addext", "keyUsage = dataEncipherment", 723 "-key", srctop_file(@certs, "ee-key.pem")); 724cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 725strict_verify($cert, 1, $ca_cert); 726 727$cert = "regular_v3_EE_copied_exts_default_KIDs.pem"; 728generate_cert($cert, "-copy_extensions", "copy", 729 "-in", srctop_file(@certs, "ext-check.csr")); 730cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID 731strict_verify($cert, 1); 732 733$cert = "v3_EE_no_AKID.pem"; 734generate_cert($cert, "-addext", "authorityKeyIdentifier = none", 735 "-key", srctop_file(@certs, "ee-key.pem")); 736has_SKID($cert, 1); 737has_AKID($cert, 0); 738strict_verify($cert, 0, $ca_cert); 739 740 741# Key Usage 742 743$cert = "self-signed_CA_no_keyUsage.pem"; 744generate_cert($cert, "-in", srctop_file(@certs, "ext-check.csr")); 745has_keyUsage($cert, 0); 746$cert = "self-signed_CA_with_keyUsages.pem"; 747generate_cert($cert, "-in", srctop_file(@certs, "ext-check.csr"), 748 "-copy_extensions", "copy"); 749has_keyUsage($cert, 1); 750 751# keyUsage=contentCommitment is an alias for nonRepudiation 752$cert = "self-issued-v3_CA_keyUsage_contentCommitment.pem"; 753generate_cert($cert, "-addext", "keyUsage = contentCommitment", 754 "-in", srctop_file(@certs, "x509-check.csr")); 755cert_contains($cert, "Non Repudiation", 1); 756cert_contains($cert, "Content Commitment", 0); 757 758# Generate cert using req with '-modulus' 759ok(run(app(["openssl", "req", "-x509", "-new", "-days", "365", 760 "-key", srctop_file("test", "testrsa.pem"), 761 "-config", srctop_file('test', 'test.cnf'), 762 "-out", "testreq-cert.pem", 763 "-modulus"])), "cert req creation - with -modulus"); 764 765# Verify cert 766ok(run(app(["openssl", "x509", "-in", "testreq-cert.pem", 767 "-noout", "-text"])), "cert verification"); 768 769# Generate cert with explicit start and end dates 770my %today = (strftime("%Y-%m-%d", gmtime) => 1); 771my $cert = "self-signed_explicit_date.pem"; 772ok(run(app(["openssl", "req", "-x509", "-new", "-text", 773 "-config", srctop_file('test', 'test.cnf'), 774 "-key", srctop_file("test", "testrsa.pem"), 775 "-not_before", "today", 776 "-not_after", "today", 777 "-out", $cert])) 778&& ++$today{strftime("%Y-%m-%d", gmtime)} 779&& (grep { defined $today{$_} } get_not_before_date($cert)) 780&& (grep { defined $today{$_} } get_not_after_date($cert)), "explicit start and end dates"); 781