summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJob Snijders <job@sobornost.net>2024-01-10 17:15:52 +0000
committerTomas Mraz <tomas@openssl.org>2024-01-15 10:40:01 +0100
commit4e5bf933131863e0459d7b39931d464fef77b078 (patch)
tree1ca2f5c4702aa4d977c9aa5b0462e79e593473e7
parentdf04e81794ac3083804c34c173eb2b2fa55d373d (diff)
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)
-rw-r--r--CHANGES.md6
-rw-r--r--apps/x509.c26
-rw-r--r--doc/man1/openssl-x509.pod.in21
-rw-r--r--test/recipes/25-test_x509.t11
4 files changed, 53 insertions, 11 deletions
diff --git a/CHANGES.md b/CHANGES.md
index eb16a6e24e..58d06ae498 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -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.
diff --git a/apps/x509.c b/apps/x509.c
index 578af2364f..ce3fda6716 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -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);
diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in
index 2d7a1b859a..3a5bd25d56 100644
--- a/doc/man1/openssl-x509.pod.in
+++ b/doc/man1/openssl-x509.pod.in
@@ -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
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
index 9b11169a98..eeb8083506 100644
--- a/test/recipes/25-test_x509.t
+++ b/test/recipes/25-test_x509.t
@@ -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";