APPS: generated certs bear X.509 V3, unless -x509v1 option of req app is given

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/19271)
This commit is contained in:
Dr. David von Oheimb 2022-09-24 23:59:12 +02:00 committed by Dr. David von Oheimb
parent 66fc90f18c
commit 342e3652c7
20 changed files with 155 additions and 45 deletions

View File

@ -127,6 +127,13 @@ OpenSSL 3.2
* Lutz Jänicke* * Lutz Jänicke*
* The `x509`, `ca`, and `req` apps now produce X.509 v3 certificates.
The `-x509v1` option of `req` prefers generation of X.509 v1 certificates.
`X509_sign()` and `X509_sign_ctx()` make sure that the certificate has
X.509 version 3 if the certificate information includes X.509 extensions.
*David von Oheimb*
* Fix and extend certificate handling and the apps `x509`, `verify` etc. * Fix and extend certificate handling and the apps `x509`, `verify` etc.
such as adding a trace facility for debugging certificate chain building. such as adding a trace facility for debugging certificate chain building.

View File

@ -1926,7 +1926,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
!EVP_PKEY_missing_parameters(pkey)) !EVP_PKEY_missing_parameters(pkey))
EVP_PKEY_copy_parameters(pktmp, pkey); EVP_PKEY_copy_parameters(pktmp, pkey);
if (!do_X509_sign(ret, pkey, dgst, sigopts, &ext_ctx)) if (!do_X509_sign(ret, 0, pkey, dgst, sigopts, &ext_ctx))
goto end; goto end;
/* We now just add it to the database as DB_TYPE_VAL('V') */ /* We now just add it to the database as DB_TYPE_VAL('V') */

View File

@ -259,7 +259,7 @@ int init_gen_str(EVP_PKEY_CTX **pctx,
const char *algname, ENGINE *e, int do_param, const char *algname, ENGINE *e, int do_param,
OSSL_LIB_CTX *libctx, const char *propq); OSSL_LIB_CTX *libctx, const char *propq);
int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey); int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey);
int do_X509_sign(X509 *x, EVP_PKEY *pkey, const char *md, int do_X509_sign(X509 *x, int force_v1, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx); STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx);
int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts); int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts);
int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md, int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,

View File

@ -2289,16 +2289,14 @@ int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey)
} }
/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */ /* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md, int do_X509_sign(X509 *cert, int force_v1, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx) STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
{ {
const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
EVP_MD_CTX *mctx = EVP_MD_CTX_new(); EVP_MD_CTX *mctx = EVP_MD_CTX_new();
int self_sign; int self_sign;
int rv = 0; int rv = 0;
if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) { if (!force_v1) {
/* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */
if (!X509_set_version(cert, X509_VERSION_3)) if (!X509_set_version(cert, X509_VERSION_3))
goto end; goto end;

View File

@ -85,8 +85,8 @@ typedef enum OPTION_choice {
OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT,
OPT_CA, OPT_CAKEY, OPT_X509, OPT_X509V1, OPT_CA, OPT_CAKEY,
OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
OPT_COPY_EXTENSIONS, OPT_EXTENSIONS, OPT_REQEXTS, OPT_ADDEXT, OPT_COPY_EXTENSIONS, OPT_EXTENSIONS, OPT_REQEXTS, OPT_ADDEXT,
OPT_PRECERT, OPT_MD, OPT_PRECERT, OPT_MD,
@ -117,6 +117,7 @@ const OPTIONS req_options[] = {
{"text", OPT_TEXT, '-', "Text form of request"}, {"text", OPT_TEXT, '-', "Text form of request"},
{"x509", OPT_X509, '-', {"x509", OPT_X509, '-',
"Output an X.509 certificate structure instead of a cert request"}, "Output an X.509 certificate structure instead of a cert request"},
{"x509v1", OPT_X509V1, '-', "Request cert generation with X.509 version 1"},
{"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"}, {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"},
{"CAkey", OPT_CAKEY, 's', {"CAkey", OPT_CAKEY, 's',
"Issuer private key to use with -CA; default is -CA arg"}, "Issuer private key to use with -CA; default is -CA arg"},
@ -261,7 +262,7 @@ int req_main(int argc, char **argv)
int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0; int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0;
int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF; int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0; int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0, x509v1 = 0;
long newkey_len = -1; long newkey_len = -1;
unsigned long chtype = MBSTRING_ASC, reqflag = 0; unsigned long chtype = MBSTRING_ASC, reqflag = 0;
@ -403,6 +404,9 @@ int req_main(int argc, char **argv)
case OPT_TEXT: case OPT_TEXT:
text = 1; text = 1;
break; break;
case OPT_X509V1:
x509v1 = 1;
/* fall thru */
case OPT_X509: case OPT_X509:
gen_x509 = 1; gen_x509 = 1;
break; break;
@ -867,7 +871,8 @@ int req_main(int argc, char **argv)
} }
} }
i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx); i = do_X509_sign(new_x509, x509v1, issuer_key, digest, sigopts,
&ext_ctx);
if (!i) if (!i)
goto end; goto end;
} else { } else {

View File

@ -894,7 +894,7 @@ int x509_main(int argc, char **argv)
} }
noout = 1; noout = 1;
} else if (privkey != NULL) { } else if (privkey != NULL) {
if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx)) if (!do_X509_sign(x, 0, privkey, digest, sigopts, &ext_ctx))
goto end; goto end;
} else if (CAfile != NULL) { } else if (CAfile != NULL) {
if ((CAkey = load_key(CAkeyfile, CAkeyformat, if ((CAkey = load_key(CAkeyfile, CAkeyformat,
@ -906,7 +906,7 @@ int x509_main(int argc, char **argv)
goto err; goto err;
} }
if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx)) if (!do_X509_sign(x, 0, CAkey, digest, sigopts, &ext_ctx))
goto end; goto end;
} }
if (badsig) { if (badsig) {

View File

@ -63,6 +63,9 @@ int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0; return 0;
} }
if (sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0
&& !X509_set_version(x, X509_VERSION_3))
return 0;
/* /*
* Setting the modified flag before signing it. This makes the cached * Setting the modified flag before signing it. This makes the cached
@ -83,6 +86,9 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0; return 0;
} }
if (sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0
&& !X509_set_version(x, X509_VERSION_3))
return 0;
x->cert_info.enc.modified = 1; x->cert_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
&x->cert_info.signature, &x->cert_info.signature,

View File

@ -71,6 +71,11 @@ B<openssl> B<ca>
This command emulates a CA application. This command emulates a CA application.
See the B<WARNINGS> especially when considering to use it productively. See the B<WARNINGS> especially when considering to use it productively.
It generates certificates bearing X.509 version 3.
Unless specified otherwise,
key identifier extensions are included as described in L<x509v3_config(5)>.
It can be used to sign certificate requests (CSRs) in a variety of forms It can be used to sign certificate requests (CSRs) in a variety of forms
and generate certificate revocation lists (CRLs). and generate certificate revocation lists (CRLs).
It also maintains a text database of issued certificates and their status. It also maintains a text database of issued certificates and their status.
@ -287,8 +292,7 @@ and all certificates will be certified automatically.
The section of the configuration file containing certificate extensions The section of the configuration file containing certificate extensions
to be added when a certificate is issued (defaults to B<x509_extensions> to be added when a certificate is issued (defaults to B<x509_extensions>
unless the B<-extfile> option is used). unless the B<-extfile> option is used).
If no X.509 extensions are specified then a V1 certificate is created,
else a V3 certificate is created.
See the L<x509v3_config(5)> manual page for details of the See the L<x509v3_config(5)> manual page for details of the
extension section format. extension section format.
@ -833,6 +837,9 @@ has no effect.
The B<-engine> option was deprecated in OpenSSL 3.0. The B<-engine> option was deprecated in OpenSSL 3.0.
Since OpenSSL 3.2, generated certificates bear X.509 version 3,
and key identifier extensions are included by default.
=head1 SEE ALSO =head1 SEE ALSO
L<openssl(1)>, L<openssl(1)>,

View File

@ -33,6 +33,7 @@ B<openssl> B<req>
[B<-config> I<filename>] [B<-config> I<filename>]
[B<-section> I<name>] [B<-section> I<name>]
[B<-x509>] [B<-x509>]
[B<-x509v1>]
[B<-CA> I<filename>|I<uri>] [B<-CA> I<filename>|I<uri>]
[B<-CAkey> I<filename>|I<uri>] [B<-CAkey> I<filename>|I<uri>]
[B<-days> I<n>] [B<-days> I<n>]
@ -299,6 +300,16 @@ X.509 extensions to be added can be specified in the configuration file,
possibly using the B<-config> and B<-extensions> options, possibly using the B<-config> and B<-extensions> options,
and/or using the B<-addext> option. and/or using the B<-addext> option.
Unless B<-x509v1> is given, generated certificates bear X.509 version 3.
Unless specified otherwise,
key identifier extensions are included as described in L<x509v3_config(5)>.
=item B<-x509v1>
Request generation of certificates with X.509 version 1.
This implies B<-x509>.
If X.509 extensions are given, anyway X.509 version 3 is set.
=item B<-CA> I<filename>|I<uri> =item B<-CA> I<filename>|I<uri>
Specifies the "CA" certificate to be used for signing a new certificate Specifies the "CA" certificate to be used for signing a new certificate
@ -349,7 +360,7 @@ file to specify requests for a variety of purposes.
Add a specific extension to the certificate (if B<-x509> is in use) Add a specific extension to the certificate (if B<-x509> is in use)
or certificate request. The argument must have the form of or certificate request. The argument must have the form of
a key=value pair as it would appear in a config file. a C<key=value> pair as it would appear in a config file.
This option can be given multiple times. This option can be given multiple times.
@ -770,6 +781,10 @@ The <-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead.
The B<-reqexts> option has been made an alias of B<-extensions> in OpenSSL 3.2. The B<-reqexts> option has been made an alias of B<-extensions> in OpenSSL 3.2.
Since OpenSSL 3.2,
generated certificates bear X.509 version 3 unless B<-x509v1> is given,
and key identifier extensions are included by default.
=head1 COPYRIGHT =head1 COPYRIGHT
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -87,6 +87,10 @@ convert certificates to various forms, edit certificate trust settings,
generate certificates from scratch or from certificating requests generate certificates from scratch or from certificating requests
and then self-signing them or signing them like a "micro CA". and then self-signing them or signing them like a "micro CA".
Generated certificates bear X.509 version 3.
Unless specified otherwise,
key identifier extensions are included as described in L<x509v3_config(5)>.
Since there are a large number of options they will split up into Since there are a large number of options they will split up into
various sections. various sections.
@ -303,7 +307,7 @@ as used by OpenSSL before version 1.0.0.
Prints out the certificate extensions in text form. Prints out the certificate extensions in text form.
Can also be used to restrict which extensions to copy. Can also be used to restrict which extensions to copy.
Extensions are specified Extensions are specified
with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier". with a comma separated string, e.g., "subjectAltName, subjectKeyIdentifier".
See the L<x509v3_config(5)> manual page for the extension names. See the L<x509v3_config(5)> manual page for the extension names.
=item B<-ocspid> =item B<-ocspid>
@ -435,9 +439,13 @@ If this option is not
specified then the extensions should either be contained in the unnamed specified then the extensions should either be contained in the unnamed
(default) section or the default section should contain a variable called (default) section or the default section should contain a variable called
"extensions" which contains the section to use. "extensions" which contains the section to use.
See the L<x509v3_config(5)> manual page for details of the See the L<x509v3_config(5)> manual page for details of the
extension section format. extension section format.
Unless specified otherwise,
key identifier extensions are included as described in L<x509v3_config(5)>.
=item B<-sigopt> I<nm>:I<v> =item B<-sigopt> I<nm>:I<v>
Pass options to the signature algorithm during sign operations. Pass options to the signature algorithm during sign operations.
@ -782,6 +790,9 @@ The B<-engine> option was deprecated in OpenSSL 3.0.
The B<-C> option was removed in OpenSSL 3.0. The B<-C> option was removed in OpenSSL 3.0.
Since OpenSSL 3.2, generated certificates bear X.509 version 3,
and key identifier extensions are included by default.
=head1 COPYRIGHT =head1 COPYRIGHT
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -22,13 +22,13 @@ certificate request or CRL version
=head1 DESCRIPTION =head1 DESCRIPTION
X509_get_version() returns the numerical value of the version field of X509_get_version() returns the numerical value of the version field of
certificate B<x>. These correspond to the constants B<X509_VERSION_1>, certificate I<x>. These correspond to the constants B<X509_VERSION_1>,
B<X509_VERSION_2>, and B<X509_VERSION_3>. Note: the values of these constants B<X509_VERSION_2>, and B<X509_VERSION_3>. Note: the values of these constants
are defined by standards (X.509 et al) to be one less than the certificate are defined by standards (X.509 et al) to be one less than the certificate
version. So B<X509_VERSION_3> has value 2 and B<X509_VERSION_1> has value 0. version. So B<X509_VERSION_3> has value 2 and B<X509_VERSION_1> has value 0.
X509_set_version() sets the numerical value of the version field of certificate X509_set_version() sets the numerical value of the version field of certificate
B<x> to B<version>. I<x> to I<version>.
Similarly X509_REQ_get_version(), X509_REQ_set_version(), Similarly X509_REQ_get_version(), X509_REQ_set_version(),
X509_CRL_get_version() and X509_CRL_set_version() get and set the version X509_CRL_get_version() and X509_CRL_set_version() get and set the version

View File

@ -25,6 +25,8 @@ sign certificate, certificate request, or CRL signature
X509_sign() signs certificate I<x> using private key I<pkey> and message X509_sign() signs certificate I<x> using private key I<pkey> and message
digest I<md> and sets the signature in I<x>. X509_sign_ctx() also signs digest I<md> and sets the signature in I<x>. X509_sign_ctx() also signs
certificate I<x> but uses the parameters contained in digest context I<ctx>. certificate I<x> but uses the parameters contained in digest context I<ctx>.
If the certificate information includes X.509 extensions,
these two functions make sure that the certificate bears X.509 version 3.
X509_REQ_sign(), X509_REQ_sign_ctx(), X509_REQ_sign(), X509_REQ_sign_ctx(),
X509_CRL_sign(), and X509_CRL_sign_ctx() X509_CRL_sign(), and X509_CRL_sign_ctx()

View File

@ -173,14 +173,27 @@ Examples:
=head2 Subject Key Identifier =head2 Subject Key Identifier
The SKID extension specification has a value with three choices. The SKID extension specification has a value with three choices.
If the value is the word B<none> then no SKID extension will be included.
If the value is the word B<hash>, or by default for the B<x509>, B<req>, and =over 4
B<ca> apps, the process specified in RFC 5280 section 4.2.1.2. (1) is followed:
=item B<none>
No SKID extension will be included.
=item B<hash>
The process specified in RFC 5280 section 4.2.1.2. (1) is followed:
The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT
STRING subjectPublicKey (excluding the tag, length, and number of unused bits). STRING subjectPublicKey (excluding the tag, length, and number of unused bits).
Otherwise, the value must be a hex string (possibly with C<:> separating bytes) =item A hex string (possibly with C<:> separating bytes)
to output directly, however, this is strongly discouraged.
The provided value is output directly.
This choice is strongly discouraged.
=back
By default the B<x509>, B<req>, and B<ca> apps behave as if B<hash> was given.
Example: Example:
@ -195,6 +208,7 @@ or both of them, separated by C<,>.
Either or both can have the option B<always>, Either or both can have the option B<always>,
indicated by putting a colon C<:> between the value and this option. indicated by putting a colon C<:> between the value and this option.
For self-signed certificates the AKID is suppressed unless B<always> is present. For self-signed certificates the AKID is suppressed unless B<always> is present.
By default the B<x509>, B<req>, and B<ca> apps behave as if B<none> was given By default the B<x509>, B<req>, and B<ca> apps behave as if B<none> was given
for self-signed certificates and B<keyid>C<,> B<issuer> otherwise. for self-signed certificates and B<keyid>C<,> B<issuer> otherwise.

@ -1 +1 @@
Subproject commit b2b4d629f100eaee9f5942a106b1ccefe85b8808 Subproject commit a6b90523e4ea6010b1109b0bae7e2a73b5b025c5

View File

@ -31,6 +31,8 @@ organizationName = Dodgy Brothers
0.commonName = Brother 1 0.commonName = Brother 1
1.commonName = $ENV::CN2 1.commonName = $ENV::CN2
[ empty ]
[ v3_ee ] [ v3_ee ]
subjectKeyIdentifier = hash subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always authorityKeyIdentifier = keyid,issuer:always

View File

@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_req"); setup("test_req");
plan tests => 92; plan tests => 102;
require_ok(srctop_file('test', 'recipes', 'tconversion.pl')); require_ok(srctop_file('test', 'recipes', 'tconversion.pl'));
@ -393,16 +393,7 @@ sub generate_cert {
push(@cmd, ("-CA", $ca_cert, "-CAkey", $ca_key)) unless $ss; push(@cmd, ("-CA", $ca_cert, "-CAkey", $ca_key)) unless $ss;
ok(run(app([@cmd])), "generate $cert"); ok(run(app([@cmd])), "generate $cert");
} }
sub has_SKID {
my $cert = shift @_;
my $expect = shift @_;
cert_contains($cert, "Subject Key Identifier", $expect);
}
sub has_AKID {
my $cert = shift @_;
my $expect = shift @_;
cert_contains($cert, "Authority Key Identifier", $expect);
}
sub has_keyUsage { sub has_keyUsage {
my $cert = shift @_; my $cert = shift @_;
my $expect = shift @_; my $expect = shift @_;
@ -424,6 +415,12 @@ my $SKID_AKID = "subjectKeyIdentifier,authorityKeyIdentifier";
# # SKID # # SKID
my $cert = "self-signed_default_SKID_no_explicit_exts.pem";
generate_cert($cert);
has_version($cert, 3);
has_SKID($cert, 1); # SKID added, though no explicit extensions given
has_AKID($cert, 0);
my $cert = "self-signed_v3_CA_hash_SKID.pem"; my $cert = "self-signed_v3_CA_hash_SKID.pem";
generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = hash"); generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = hash");
has_SKID($cert, 1); # explicit hash SKID has_SKID($cert, 1); # explicit hash SKID
@ -441,7 +438,8 @@ strict_verify($cert, 1);
# AKID of self-signed certs # AKID of self-signed certs
$cert = "self-signed_v1_CA_no_KIDs.pem"; $cert = "self-signed_v1_CA_no_KIDs.pem";
generate_cert($cert); generate_cert($cert, "-x509v1");
has_version($cert, 1);
cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID cert_ext_has_n_different_lines($cert, 0, $SKID_AKID); # no SKID and no AKID
#TODO strict_verify($cert, 1); # self-signed v1 root cert should be accepted as CA #TODO strict_verify($cert, 1); # self-signed v1 root cert should be accepted as CA
@ -515,6 +513,8 @@ strict_verify($cert, 1);
$cert = "self-issued_v3_CA_no_AKID.pem"; $cert = "self-issued_v3_CA_no_AKID.pem";
generate_cert($cert, "-addext", "authorityKeyIdentifier = none", generate_cert($cert, "-addext", "authorityKeyIdentifier = none",
"-in", srctop_file(@certs, "x509-check.csr")); "-in", srctop_file(@certs, "x509-check.csr"));
has_version($cert, 3);
has_SKID($cert, 1); # SKID added, though no explicit extensions given
has_AKID($cert, 0); has_AKID($cert, 0);
strict_verify($cert, 1); strict_verify($cert, 1);
@ -556,6 +556,11 @@ cert_ext_has_n_different_lines($cert, 6, $SKID_AKID); # SKID != AKID, both force
# AKID of not self-issued certs # AKID of not self-issued certs
$cert = "regular_v3_EE_default_KIDs_no_other_exts.pem";
generate_cert($cert, "-key", srctop_file(@certs, "ee-key.pem"));
has_version($cert, 3);
cert_ext_has_n_different_lines($cert, 4, $SKID_AKID); # SKID != AKID
$cert = "regular_v3_EE_default_KIDs.pem"; $cert = "regular_v3_EE_default_KIDs.pem";
generate_cert($cert, "-addext", "keyUsage = dataEncipherment", generate_cert($cert, "-addext", "keyUsage = dataEncipherment",
"-key", srctop_file(@certs, "ee-key.pem")); "-key", srctop_file(@certs, "ee-key.pem"));

View File

@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_x509"); setup("test_x509");
plan tests => 29; plan tests => 32;
# Prevent MSys2 filename munging for arguments that look like file paths but # Prevent MSys2 filename munging for arguments that look like file paths but
# aren't # aren't
@ -202,6 +202,11 @@ ok(run(app(["openssl", "x509", "-req", "-text", "-CAcreateserial",
# Verify issuer is CA # Verify issuer is CA
ok(get_issuer($b_cert) =~ /CN=ca.example.com/); ok(get_issuer($b_cert) =~ /CN=ca.example.com/);
# although no explicit extensions given:
has_version($b_cert, 3);
has_SKID($b_cert, 1);
has_AKID($b_cert, 1);
SKIP: { SKIP: {
skip "EC is not supported by this OpenSSL build", 1 skip "EC is not supported by this OpenSSL build", 1
if disabled("ec"); if disabled("ec");

View File

@ -25,18 +25,25 @@ my $std_openssl_cnf = '"'
. srctop_file("apps", $^O eq "VMS" ? "openssl-vms.cnf" : "openssl.cnf") . srctop_file("apps", $^O eq "VMS" ? "openssl-vms.cnf" : "openssl.cnf")
. '"'; . '"';
sub src_file {
return srctop_file("test", "certs", shift);
}
rmtree("demoCA", { safe => 0 }); rmtree("demoCA", { safe => 0 });
plan tests => 15; plan tests => 20;
require_ok(srctop_file("test", "recipes", "tconversion.pl"));
SKIP: { SKIP: {
my $cakey = srctop_file("test", "certs", "ca-key.pem"); my $cakey = src_file("ca-key.pem");
$ENV{OPENSSL_CONFIG} = qq(-config "$cnf"); $ENV{OPENSSL_CONFIG} = qq(-config "$cnf");
skip "failed creating CA structure", 4 skip "failed creating CA structure", 4
if !ok(run(perlapp(["CA.pl","-newca", if !ok(run(perlapp(["CA.pl","-newca",
"-extra-req", "-key $cakey"], stdin => undef)), "-extra-req", "-key $cakey"], stdin => undef)),
'creating CA structure'); 'creating CA structure');
my $eekey = srctop_file("test", "certs", "ee-key.pem"); my $eekey = src_file("ee-key.pem");
$ENV{OPENSSL_CONFIG} = qq(-config "$cnf"); $ENV{OPENSSL_CONFIG} = qq(-config "$cnf");
skip "failed creating new certificate request", 3 skip "failed creating new certificate request", 3
if !ok(run(perlapp(["CA.pl","-newreq", if !ok(run(perlapp(["CA.pl","-newreq",
@ -53,7 +60,7 @@ plan tests => 15;
skip "CT not configured, can't use -precert", 1 skip "CT not configured, can't use -precert", 1
if disabled("ct"); if disabled("ct");
my $eekey2 = srctop_file("test", "certs", "ee-key-3072.pem"); my $eekey2 = src_file("ee-key-3072.pem");
$ENV{OPENSSL_CONFIG} = qq(-config "$cnf"); $ENV{OPENSSL_CONFIG} = qq(-config "$cnf");
ok(run(perlapp(["CA.pl", "-precert", '-extra-req', "-section userreq -key $eekey2"], stderr => undef)), ok(run(perlapp(["CA.pl", "-precert", '-extra-req', "-section userreq -key $eekey2"], stderr => undef)),
'creating new pre-certificate'); 'creating new pre-certificate');
@ -65,17 +72,25 @@ SKIP: {
is(yes(cmdstr(app(["openssl", "ca", "-config", is(yes(cmdstr(app(["openssl", "ca", "-config",
$cnf, $cnf,
"-in", srctop_file("test", "certs", "sm2-csr.pem"), "-in", src_file("sm2-csr.pem"),
"-out", "sm2-test.crt", "-out", "sm2-test.crt",
"-sigopt", "distid:1234567812345678", "-sigopt", "distid:1234567812345678",
"-vfyopt", "distid:1234567812345678", "-vfyopt", "distid:1234567812345678",
"-md", "sm3", "-md", "sm3",
"-cert", srctop_file("test", "certs", "sm2-root.crt"), "-cert", src_file("sm2-root.crt"),
"-keyfile", srctop_file("test", "certs", "sm2-root.key")]))), "-keyfile", src_file("sm2-root.key")]))),
0, 0,
"Signing SM2 certificate request"); "Signing SM2 certificate request");
} }
my $v3_cert = "v3-test.crt";
ok(run(app(["openssl", "ca", "-batch", "-config", $cnf, "-extensions", "empty",
"-in", src_file("x509-check.csr"), "-out", $v3_cert])));
# although no explicit extensions given:
has_version($v3_cert, 3);
has_SKID($v3_cert, 1);
has_AKID($v3_cert, 1);
test_revoke('notimes', { test_revoke('notimes', {
should_succeed => 1, should_succeed => 1,
}); });

View File

@ -402,7 +402,7 @@ sub init {
}, grep(/-key-pkcs8-pbes2-sha256\.pem$/, @generated_files)) }, grep(/-key-pkcs8-pbes2-sha256\.pem$/, @generated_files))
# *-cert.pem (intermediary for the .p12 inits) # *-cert.pem (intermediary for the .p12 inits)
&& run(app(["openssl", "req", "-x509", @std_args, && run(app(["openssl", "req", "-x509", @std_args,
"-config", $cnf, "-noenc", "-config", $cnf, "-reqexts", "v3_ca", "-noenc",
"-key", $cakey, "-out", "cacert.pem"])) "-key", $cakey, "-out", "cacert.pem"]))
&& runall(sub { && runall(sub {
my $srckey = shift; my $srckey = shift;

View File

@ -132,6 +132,24 @@ sub cert_contains {
# not unlinking $out # not unlinking $out
} }
sub has_version {
my $cert = shift @_;
my $expect = shift @_;
cert_contains($cert, "Version: $expect", 1);
}
sub has_SKID {
my $cert = shift @_;
my $expect = shift @_;
cert_contains($cert, "Subject Key Identifier", $expect);
}
sub has_AKID {
my $cert = shift @_;
my $expect = shift @_;
cert_contains($cert, "Authority Key Identifier", $expect);
}
sub uniq (@) { sub uniq (@) {
my %seen = (); my %seen = ();
grep { not $seen{$_}++ } @_; grep { not $seen{$_}++ } @_;