summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjob <>2024-01-26 11:58:37 +0000
committerjob <>2024-01-26 11:58:37 +0000
commitebf8195ae2a041b9e833b4a53bdf3b0f0ac2fee7 (patch)
tree22591d8d23256836bf7d611b624a079dc6dafe19 /src
parente71abd74fd0206dc7a48c9c5a889e557b2afbb45 (diff)
downloadopenbsd-ebf8195ae2a041b9e833b4a53bdf3b0f0ac2fee7.tar.gz
openbsd-ebf8195ae2a041b9e833b4a53bdf3b0f0ac2fee7.tar.bz2
openbsd-ebf8195ae2a041b9e833b4a53bdf3b0f0ac2fee7.zip
Add 'openssl x509 -new' functionality to the libcrypto CLI utility
The ability to generate a new certificate is useful for testing and experimentation with rechaining PKIs. While there, alias '-key' to '-signkey' for compatibility. with and OK tb@
Diffstat (limited to 'src')
-rwxr-xr-xsrc/regress/usr.bin/openssl/appstest.sh51
-rw-r--r--src/usr.bin/openssl/openssl.123
-rw-r--r--src/usr.bin/openssl/x509.c62
3 files changed, 121 insertions, 15 deletions
diff --git a/src/regress/usr.bin/openssl/appstest.sh b/src/regress/usr.bin/openssl/appstest.sh
index 500fae0251..8c0e75deb4 100755
--- a/src/regress/usr.bin/openssl/appstest.sh
+++ b/src/regress/usr.bin/openssl/appstest.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2# 2#
3# $OpenBSD: appstest.sh,v 1.60 2024/01/12 13:16:48 tb Exp $ 3# $OpenBSD: appstest.sh,v 1.61 2024/01/26 11:58:36 job Exp $
4# 4#
5# Copyright (c) 2016 Kinichiro Inoguchi <inoguchi@openbsd.org> 5# Copyright (c) 2016 Kinichiro Inoguchi <inoguchi@openbsd.org>
6# 6#
@@ -867,6 +867,55 @@ __EOF__
867 diff $server_dir/testpubkey.pem $revoke_cert.pub 867 diff $server_dir/testpubkey.pem $revoke_cert.pub
868 check_exit_status $? 868 check_exit_status $?
869 869
870 start_message "x509 ... test -new"
871 $openssl_bin genrsa -out $server_dir/ca-new.key 2048
872 check_exit_status $?
873 $openssl_bin x509 -new -set_issuer '/CN=test-issuer' \
874 -set_subject '/CN=test-subject' \
875 -out $server_dir/new.pem -days 1 -key $server_dir/ca-new.key \
876 -force_pubkey $revoke_cert.pub
877 check_exit_status $?
878 $openssl_bin x509 -in $server_dir/new.pem -pubkey -noout \
879 > $server_dir/new.pem.pub
880 check_exit_status $?
881
882 start_message "x509 ... check if -new cert has proper pubkey"
883 diff $server_dir/testpubkey.pem $server_dir/new.pem.pub
884 check_exit_status $?
885
886 start_message "x509 ... check if -new cert has proper issuer & subject"
887 if [ "$($openssl_bin x509 -in $server_dir/new.pem -issuer -noout)" != \
888 "issuer= /CN=test-issuer" ]; then
889 exit 1
890 fi
891 if [ "$($openssl_bin x509 -in $server_dir/new.pem -subject -noout)" != \
892 "subject= /CN=test-subject" ]; then
893 exit 1
894 fi
895 check_exit_status 0
896
897 start_message "x509 ... test -new without -force_pubkey"
898 $openssl_bin x509 -new -set_subject '/CN=test-subject2' \
899 -out $server_dir/new2.pem -days 1 -key $server_dir/ca-new.key
900 check_exit_status $?
901 $openssl_bin x509 -in $server_dir/new2.pem -pubkey -noout \
902 > $server_dir/new2.pem.pub
903 check_exit_status $?
904 $openssl_bin rsa -in $server_dir/ca-new.key -pubout \
905 -out $server_dir/ca-new.pubkey
906 check_exit_status $?
907 diff $server_dir/new2.pem.pub $server_dir/ca-new.pubkey
908 check_exit_status $?
909 if [ "$($openssl_bin x509 -in $server_dir/new2.pem -issuer -noout)" \
910 != "issuer= /CN=test-subject2" ]; then
911 exit 1
912 fi
913 if [ "$($openssl_bin x509 -in $server_dir/new2.pem -subject -noout)" \
914 != "subject= /CN=test-subject2" ]; then
915 exit 1
916 fi
917 check_exit_status 0
918
870 start_message "ca ... issue cert for server csr#3" 919 start_message "ca ... issue cert for server csr#3"
871 920
872 sv_ecdsa_cert=$server_dir/sv_ecdsa_cert.pem 921 sv_ecdsa_cert=$server_dir/sv_ecdsa_cert.pem
diff --git a/src/usr.bin/openssl/openssl.1 b/src/usr.bin/openssl/openssl.1
index b608b1634e..0e2ffbcd00 100644
--- a/src/usr.bin/openssl/openssl.1
+++ b/src/usr.bin/openssl/openssl.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: openssl.1,v 1.154 2024/01/12 11:24:03 job Exp $ 1.\" $OpenBSD: openssl.1,v 1.155 2024/01/26 11:58:37 job Exp $
2.\" ==================================================================== 2.\" ====================================================================
3.\" Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. 3.\" Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
4.\" 4.\"
@@ -110,7 +110,7 @@
110.\" copied and put under another distribution licence 110.\" copied and put under another distribution licence
111.\" [including the GNU Public Licence.] 111.\" [including the GNU Public Licence.]
112.\" 112.\"
113.Dd $Mdocdate: January 12 2024 $ 113.Dd $Mdocdate: January 26 2024 $
114.Dt OPENSSL 1 114.Dt OPENSSL 1
115.Os 115.Os
116.Sh NAME 116.Sh NAME
@@ -6112,6 +6112,7 @@ version.
6112.Op Fl modulus 6112.Op Fl modulus
6113.Op Fl multivalue-rdn 6113.Op Fl multivalue-rdn
6114.Op Fl nameopt Ar option 6114.Op Fl nameopt Ar option
6115.Op Fl new
6115.Op Fl next_serial 6116.Op Fl next_serial
6116.Op Fl noout 6117.Op Fl noout
6117.Op Fl ocsp_uri 6118.Op Fl ocsp_uri
@@ -6153,10 +6154,14 @@ The following are x509 input, output, and general purpose options:
6153.It Fl in Ar file 6154.It Fl in Ar file
6154The input file to read from, 6155The input file to read from,
6155or standard input if not specified. 6156or standard input if not specified.
6157This option cannot be used with
6158.Fl new .
6156.It Fl inform Cm der | net | pem 6159.It Fl inform Cm der | net | pem
6157The input format. 6160The input format.
6158Normally, the command will expect an X.509 certificate, 6161Normally, the command will expect an X.509 certificate,
6159but this can change if other options such as 6162but this can change if other options such as
6163.Fl in
6164or
6160.Fl req 6165.Fl req
6161are present. 6166are present.
6162.It Fl md5 | sha1 6167.It Fl md5 | sha1
@@ -6710,8 +6715,22 @@ The format of the key file used in the
6710and 6715and
6711.Fl signkey 6716.Fl signkey
6712options. 6717options.
6718.It Fl new
6719Generate a new certificate using the subject given by
6720.Fl set_subject
6721and signed by
6722.Fl signkey .
6723If no public key is provided with
6724.Fl force_pubkey ,
6725the resulting certificate is self-signed.
6726This option cannot be used with
6727.Fl in
6728or
6729.Fl req .
6713.It Fl req 6730.It Fl req
6714Expect a certificate request on input instead of a certificate. 6731Expect a certificate request on input instead of a certificate.
6732This option cannot be used with
6733.Fl new .
6715.It Fl set_issuer Ar name 6734.It Fl set_issuer Ar name
6716The issuer name to use. 6735The issuer name to use.
6717.Ar name 6736.Ar name
diff --git a/src/usr.bin/openssl/x509.c b/src/usr.bin/openssl/x509.c
index 332399e7cc..0d5cf5d033 100644
--- a/src/usr.bin/openssl/x509.c
+++ b/src/usr.bin/openssl/x509.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509.c,v 1.36 2024/01/12 11:24:03 job Exp $ */ 1/* $OpenBSD: x509.c,v 1.37 2024/01/26 11:58:37 job Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -81,7 +81,8 @@
81 81
82static int callb(int ok, X509_STORE_CTX *ctx); 82static int callb(int ok, X509_STORE_CTX *ctx);
83static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 83static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
84 const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer); 84 const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer,
85 char *force_pubkey);
85static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 86static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
86 X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, 87 X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
87 char *serial, int create, int days, int clrext, CONF *conf, char *section, 88 char *serial, int create, int days, int clrext, CONF *conf, char *section,
@@ -127,6 +128,7 @@ static struct {
127 const EVP_MD *md_alg; 128 const EVP_MD *md_alg;
128 int modulus; 129 int modulus;
129 int multirdn; 130 int multirdn;
131 int new;
130 int next_serial; 132 int next_serial;
131 unsigned long nmflag; 133 unsigned long nmflag;
132 int noout; 134 int noout;
@@ -531,6 +533,12 @@ static const struct option x509_options[] = {
531 }, 533 },
532#endif 534#endif
533 { 535 {
536 .name = "key",
537 .argname = "file",
538 .type = OPTION_ARG_FUNC,
539 .opt.argfunc = x509_opt_signkey,
540 },
541 {
534 .name = "keyform", 542 .name = "keyform",
535 .argname = "fmt", 543 .argname = "fmt",
536 .desc = "Private key format - default PEM", 544 .desc = "Private key format - default PEM",
@@ -558,6 +566,12 @@ static const struct option x509_options[] = {
558 .opt.argfunc = x509_opt_nameopt, 566 .opt.argfunc = x509_opt_nameopt,
559 }, 567 },
560 { 568 {
569 .name = "new",
570 .desc = "Generate a new certificate",
571 .type = OPTION_FLAG,
572 .opt.flag = &cfg.new,
573 },
574 {
561 .name = "next_serial", 575 .name = "next_serial",
562 .desc = "Print the next serial number", 576 .desc = "Print the next serial number",
563 .type = OPTION_ORDER, 577 .type = OPTION_ORDER,
@@ -758,7 +772,7 @@ x509_usage(void)
758 " [-in file] [-inform der | net | pem] [-issuer]\n" 772 " [-in file] [-inform der | net | pem] [-issuer]\n"
759 " [-issuer_hash] [-issuer_hash_old] [-keyform der | pem]\n" 773 " [-issuer_hash] [-issuer_hash_old] [-keyform der | pem]\n"
760 " [-md5 | -sha1] [-modulus] [-multivalue-rdn]\n" 774 " [-md5 | -sha1] [-modulus] [-multivalue-rdn]\n"
761 " [-nameopt option] [-next_serial] [-noout] [-ocsp_uri]\n" 775 " [-nameopt option] [-new] [-next_serial] [-noout] [-ocsp_uri]\n"
762 " [-ocspid] [-out file] [-outform der | net | pem]\n" 776 " [-ocspid] [-out file] [-outform der | net | pem]\n"
763 " [-passin arg] [-pubkey] [-purpose] [-req] [-serial]\n" 777 " [-passin arg] [-pubkey] [-purpose] [-req] [-serial]\n"
764 " [-set_issuer name] [-set_serial n] [-set_subject name]\n" 778 " [-set_issuer name] [-set_serial n] [-set_subject name]\n"
@@ -778,6 +792,7 @@ x509_main(int argc, char **argv)
778 X509 *x = NULL, *xca = NULL; 792 X509 *x = NULL, *xca = NULL;
779 X509_NAME *iname = NULL, *sname = NULL; 793 X509_NAME *iname = NULL, *sname = NULL;
780 EVP_PKEY *Fpkey = NULL, *Upkey = NULL, *CApkey = NULL; 794 EVP_PKEY *Fpkey = NULL, *Upkey = NULL, *CApkey = NULL;
795 EVP_PKEY *pkey;
781 int i; 796 int i;
782 BIO *out = NULL; 797 BIO *out = NULL;
783 BIO *STDout = NULL; 798 BIO *STDout = NULL;
@@ -869,8 +884,28 @@ x509_main(int argc, char **argv)
869 cfg.keyformat, 0, NULL, "Forced key")) == NULL) 884 cfg.keyformat, 0, NULL, "Forced key")) == NULL)
870 goto end; 885 goto end;
871 } 886 }
887 if (cfg.new) {
888 if (cfg.infile != NULL) {
889 BIO_printf(bio_err, "Can't combine -new and -in\n");
890 goto end;
891 }
892 if (cfg.reqfile) {
893 BIO_printf(bio_err, "Can't combine -new and -req\n");
894 goto end;
895 }
896 if (cfg.set_subject == NULL) {
897 BIO_printf(bio_err, "Must use -set_subject with -new\n");
898 goto end;
899 }
900 if (cfg.keyfile == NULL) {
901 BIO_printf(bio_err, "Must use -signkey with -new\n");
902 goto end;
903 }
904 if ((Upkey = load_key(bio_err, cfg.keyfile, cfg.keyformat, 0,
905 passin, "Private key")) == NULL)
906 goto end;
907 }
872 if (cfg.reqfile) { 908 if (cfg.reqfile) {
873 EVP_PKEY *pkey;
874 BIO *in; 909 BIO *in;
875 910
876 if (!cfg.sign_flag && !cfg.CA_flag) { 911 if (!cfg.sign_flag && !cfg.CA_flag) {
@@ -919,6 +954,8 @@ x509_main(int argc, char **argv)
919 print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 954 print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
920 cfg.nmflag); 955 cfg.nmflag);
921 956
957 }
958 if (cfg.reqfile || cfg.new) {
922 if ((x = X509_new()) == NULL) 959 if ((x = X509_new()) == NULL)
923 goto end; 960 goto end;
924 961
@@ -959,6 +996,8 @@ x509_main(int argc, char **argv)
959 if ((pkey = Fpkey) == NULL) 996 if ((pkey = Fpkey) == NULL)
960 pkey = X509_REQ_get0_pubkey(req); 997 pkey = X509_REQ_get0_pubkey(req);
961 if (pkey == NULL) 998 if (pkey == NULL)
999 pkey = Upkey;
1000 if (pkey == NULL)
962 goto end; 1001 goto end;
963 if (!X509_set_pubkey(x, pkey)) 1002 if (!X509_set_pubkey(x, pkey))
964 goto end; 1003 goto end;
@@ -1263,10 +1302,7 @@ x509_main(int argc, char **argv)
1263 BIO_printf(STDout, "%02X%c", md[j], 1302 BIO_printf(STDout, "%02X%c", md[j],
1264 (j + 1 == (int)n) ? '\n' : ':'); 1303 (j + 1 == (int)n) ? '\n' : ':');
1265 } 1304 }
1266
1267 /* should be in the library */
1268 } else if (cfg.sign_flag == i && cfg.x509req == 0) { 1305 } else if (cfg.sign_flag == i && cfg.x509req == 0) {
1269 BIO_printf(bio_err, "Getting Private key\n");
1270 if (Upkey == NULL) { 1306 if (Upkey == NULL) {
1271 Upkey = load_key(bio_err, cfg.keyfile, 1307 Upkey = load_key(bio_err, cfg.keyfile,
1272 cfg.keyformat, 0, passin, 1308 cfg.keyformat, 0, passin,
@@ -1276,10 +1312,10 @@ x509_main(int argc, char **argv)
1276 } 1312 }
1277 if (!sign(x, Upkey, cfg.days, 1313 if (!sign(x, Upkey, cfg.days,
1278 cfg.clrext, cfg.digest, 1314 cfg.clrext, cfg.digest,
1279 extconf, cfg.extsect, iname)) 1315 extconf, cfg.extsect, iname,
1316 cfg.force_pubkey))
1280 goto end; 1317 goto end;
1281 } else if (cfg.CA_flag == i) { 1318 } else if (cfg.CA_flag == i) {
1282 BIO_printf(bio_err, "Getting CA Private Key\n");
1283 if (cfg.CAkeyfile != NULL) { 1319 if (cfg.CAkeyfile != NULL) {
1284 CApkey = load_key(bio_err, cfg.CAkeyfile, 1320 CApkey = load_key(bio_err, cfg.CAkeyfile,
1285 cfg.CAkeyformat, 0, passin, 1321 cfg.CAkeyformat, 0, passin,
@@ -1564,7 +1600,7 @@ callb(int ok, X509_STORE_CTX *ctx)
1564/* self sign */ 1600/* self sign */
1565static int 1601static int
1566sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 1602sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1567 CONF *conf, char *section, X509_NAME *issuer) 1603 CONF *conf, char *section, X509_NAME *issuer, char *force_pubkey)
1568{ 1604{
1569 EVP_PKEY *pktmp; 1605 EVP_PKEY *pktmp;
1570 1606
@@ -1591,8 +1627,10 @@ sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1591 (long) 60 * 60 * 24 * days) == NULL) 1627 (long) 60 * 60 * 24 * days) == NULL)
1592 goto err; 1628 goto err;
1593 1629
1594 if (!X509_set_pubkey(x, pkey)) 1630 if (force_pubkey == NULL) {
1595 goto err; 1631 if (!X509_set_pubkey(x, pkey))
1632 goto err;
1633 }
1596 if (clrext) { 1634 if (clrext) {
1597 while (X509_get_ext_count(x) > 0) { 1635 while (X509_get_ext_count(x) > 0) {
1598 if (X509_delete_ext(x, 0) == NULL) 1636 if (X509_delete_ext(x, 0) == NULL)