Add apps/x509 -set_issuer & -set_subject option to override issuer & subject

This changeset adds the counterpart to the '-subj' option to allow overriding
the Issuer. For consistency, the `-subj` option is aliased to `-set_subject`.

The issuer can be specified as following apps/openssl x509 -new -set_issuer
'/CN=example-nro-ta' -subj '/CN=2a7dd1d787d793e4c8af56e197d4eed92af6ba13' ...

This is useful in constructing specific test-cases or rechaining PKI trees

Joint work with George Michaelson (@geeohgeegeeoh)

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23257)
This commit is contained in:
Job Snijders 2024-01-10 17:15:52 +00:00 committed by Tomas Mraz
parent df04e81794
commit 4e5bf93313
4 changed files with 53 additions and 11 deletions

View File

@ -36,6 +36,12 @@ OpenSSL 3.3
*Neil Horman*
* Added `-set_issuer` and `-set_subject` options to `openssl x509` to
override the Issuer and Subject when creating a certificate. The `-subj`
option now is an alias for `-set_subject`.
*Job Snijders, George Michaelson*
* OPENSSL_sk_push() and sk_<TYPE>_push() functions now return 0 instead of -1
if called with a NULL stack argument.

View File

@ -43,7 +43,7 @@ typedef enum OPTION_choice {
OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_ISSU, OPT_SUBJ,
OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT,
OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
@ -138,7 +138,9 @@ const OPTIONS x509_options[] = {
"Number of days until newly generated certificate expires - default 30"},
{"preserve_dates", OPT_PRESERVE_DATES, '-',
"Preserve existing validity dates"},
{"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
{"set_issuer", OPT_ISSU, 's', "Set or override certificate issuer"},
{"set_subject", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
{"subj", OPT_SUBJ, 's', "Alias for -set_subject"},
{"force_pubkey", OPT_FORCE_PUBKEY, '<',
"Key to be placed in new certificate or certificate request"},
{"clrext", OPT_CLREXT, '-',
@ -262,8 +264,8 @@ int x509_main(int argc, char **argv)
EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL;
EVP_PKEY *pkey;
int newcert = 0;
char *subj = NULL, *digest = NULL;
X509_NAME *fsubj = NULL;
char *issu = NULL, *subj = NULL, *digest = NULL;
X509_NAME *fissu = NULL, *fsubj = NULL;
const unsigned long chtype = MBSTRING_ASC;
const int multirdn = 1;
STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
@ -425,6 +427,9 @@ int x509_main(int argc, char **argv)
case OPT_FORCE_PUBKEY:
pubkeyfile = opt_arg();
break;
case OPT_ISSU:
issu = opt_arg();
break;
case OPT_SUBJ:
subj = opt_arg();
break;
@ -651,6 +656,9 @@ int x509_main(int argc, char **argv)
goto err;
}
}
if (issu != NULL
&& (fissu = parse_name(issu, chtype, multirdn, "issuer")) == NULL)
goto end;
if (subj != NULL
&& (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
goto end;
@ -830,8 +838,13 @@ int x509_main(int argc, char **argv)
if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
goto end;
if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
goto end;
if (fissu != NULL) {
if (!X509_set_issuer_name(x, fissu))
goto end;
} else {
if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
goto end;
}
}
X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
@ -1079,6 +1092,7 @@ int x509_main(int argc, char **argv)
NCONF_free(extconf);
BIO_free_all(out);
X509_STORE_free(ctx);
X509_NAME_free(fissu);
X509_NAME_free(fsubj);
X509_REQ_free(req);
X509_free(x);

View File

@ -56,6 +56,8 @@ B<openssl> B<x509>
[B<-next_serial>]
[B<-days> I<arg>]
[B<-preserve_dates>]
[B<-set_issuer> I<arg>]
[B<-set_subject> I<arg>]
[B<-subj> I<arg>]
[B<-force_pubkey> I<filename>]
[B<-clrext>]
@ -123,7 +125,7 @@ see L<openssl-passphrase-options(1)>.
Generate a certificate from scratch, not using an input certificate
or certificate request.
So this excludes the B<-in> and B<-req> options.
Instead, the B<-subj> option needs to be given.
Instead, the B<-set_subject> option needs to be given.
The public key to include can be given with the B<-force_pubkey> option
and defaults to the key given with the B<-key> (or B<-signkey>) option,
which implies self-signature.
@ -386,10 +388,17 @@ When signing a certificate, preserve "notBefore" and "notAfter" dates of any
input certificate instead of adjusting them to current time and duration.
Cannot be used together with the B<-days> option.
=item B<-subj> I<arg>
=item B<-set_issuer> I<arg>
When a certificate is created set its issuer name to the given value.
See B<-set_subject> on how the arg must be formatted.
=item B<-set_subject> I<arg>
When a certificate is created set its subject name to the given value.
When the certificate is self-signed the issuer name is set to the same value.
When the certificate is self-signed the issuer name is set to the same value,
unless the B<-set_issuer> option is given.
The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
Special characters may be escaped by C<\> (backslash), whitespace is retained.
@ -405,6 +414,10 @@ C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
This option can be used with the B<-new> and B<-force_pubkey> options to create
a new certificate without providing an input certificate or certificate request.
=item B<-subj> I<arg>
This option is an alias of B<-set_subject>.
=item B<-force_pubkey> I<filename>
When a new certificate or certificate request is created
@ -413,7 +426,7 @@ instead of the key contained in the input
or given with the B<-key> (or B<-signkey>) option.
If the input contains no public key but a private key, its public part is used.
This option can be used in conjunction with b<-new> and B<-subj>
This option can be used in conjunction with b<-new> and B<-set_subject>
to directly generate a certificate containing any desired public key.
This option is also useful for creating self-issued certificates that are not

View File

@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_x509");
plan tests => 44;
plan tests => 46;
# Prevent MSys2 filename munging for arguments that look like file paths but
# aren't
@ -81,6 +81,15 @@ ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey]))
# not unlinking $pubkey
# not unlinking $selfout
# test -set_issuer option
my $ca_issu = srctop_file(@certs, "ca-cert.pem"); # issuer cert
my $caout_issu = "ca-issu.out";
ok(run(app(["openssl", "x509", "-new", "-force_pubkey", $key, "-subj", "/CN=EE",
"-set_issuer", "/CN=TEST-CA", "-extfile", $extfile, "-CA", $ca_issu,
"-CAkey", $pkey, "-text", "-out", $caout_issu])));
ok(get_issuer($caout_issu) =~ /CN=TEST-CA/);
# not unlinking $caout
# simple way of directly producing a CA-signed cert with private/pubkey input
my $ca = srctop_file(@certs, "ca-cert.pem"); # issuer cert
my $caout = "ca-issued.out";