#!/bin/sh
#
-# $OpenBSD: appstest.sh,v 1.60 2024/01/12 13:16:48 tb Exp $
+# $OpenBSD: appstest.sh,v 1.61 2024/01/26 11:58:36 job Exp $
#
# Copyright (c) 2016 Kinichiro Inoguchi <inoguchi@openbsd.org>
#
diff $server_dir/testpubkey.pem $revoke_cert.pub
check_exit_status $?
+ start_message "x509 ... test -new"
+ $openssl_bin genrsa -out $server_dir/ca-new.key 2048
+ check_exit_status $?
+ $openssl_bin x509 -new -set_issuer '/CN=test-issuer' \
+ -set_subject '/CN=test-subject' \
+ -out $server_dir/new.pem -days 1 -key $server_dir/ca-new.key \
+ -force_pubkey $revoke_cert.pub
+ check_exit_status $?
+ $openssl_bin x509 -in $server_dir/new.pem -pubkey -noout \
+ > $server_dir/new.pem.pub
+ check_exit_status $?
+
+ start_message "x509 ... check if -new cert has proper pubkey"
+ diff $server_dir/testpubkey.pem $server_dir/new.pem.pub
+ check_exit_status $?
+
+ start_message "x509 ... check if -new cert has proper issuer & subject"
+ if [ "$($openssl_bin x509 -in $server_dir/new.pem -issuer -noout)" != \
+ "issuer= /CN=test-issuer" ]; then
+ exit 1
+ fi
+ if [ "$($openssl_bin x509 -in $server_dir/new.pem -subject -noout)" != \
+ "subject= /CN=test-subject" ]; then
+ exit 1
+ fi
+ check_exit_status 0
+
+ start_message "x509 ... test -new without -force_pubkey"
+ $openssl_bin x509 -new -set_subject '/CN=test-subject2' \
+ -out $server_dir/new2.pem -days 1 -key $server_dir/ca-new.key
+ check_exit_status $?
+ $openssl_bin x509 -in $server_dir/new2.pem -pubkey -noout \
+ > $server_dir/new2.pem.pub
+ check_exit_status $?
+ $openssl_bin rsa -in $server_dir/ca-new.key -pubout \
+ -out $server_dir/ca-new.pubkey
+ check_exit_status $?
+ diff $server_dir/new2.pem.pub $server_dir/ca-new.pubkey
+ check_exit_status $?
+ if [ "$($openssl_bin x509 -in $server_dir/new2.pem -issuer -noout)" \
+ != "issuer= /CN=test-subject2" ]; then
+ exit 1
+ fi
+ if [ "$($openssl_bin x509 -in $server_dir/new2.pem -subject -noout)" \
+ != "subject= /CN=test-subject2" ]; then
+ exit 1
+ fi
+ check_exit_status 0
+
start_message "ca ... issue cert for server csr#3"
sv_ecdsa_cert=$server_dir/sv_ecdsa_cert.pem
-.\" $OpenBSD: openssl.1,v 1.154 2024/01/12 11:24:03 job Exp $
+.\" $OpenBSD: openssl.1,v 1.155 2024/01/26 11:58:37 job Exp $
.\" ====================================================================
.\" Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
.\"
.\" copied and put under another distribution licence
.\" [including the GNU Public Licence.]
.\"
-.Dd $Mdocdate: January 12 2024 $
+.Dd $Mdocdate: January 26 2024 $
.Dt OPENSSL 1
.Os
.Sh NAME
.Op Fl modulus
.Op Fl multivalue-rdn
.Op Fl nameopt Ar option
+.Op Fl new
.Op Fl next_serial
.Op Fl noout
.Op Fl ocsp_uri
.It Fl in Ar file
The input file to read from,
or standard input if not specified.
+This option cannot be used with
+.Fl new .
.It Fl inform Cm der | net | pem
The input format.
Normally, the command will expect an X.509 certificate,
but this can change if other options such as
+.Fl in
+or
.Fl req
are present.
.It Fl md5 | sha1
and
.Fl signkey
options.
+.It Fl new
+Generate a new certificate using the subject given by
+.Fl set_subject
+and signed by
+.Fl signkey .
+If no public key is provided with
+.Fl force_pubkey ,
+the resulting certificate is self-signed.
+This option cannot be used with
+.Fl in
+or
+.Fl req .
.It Fl req
Expect a certificate request on input instead of a certificate.
+This option cannot be used with
+.Fl new .
.It Fl set_issuer Ar name
The issuer name to use.
.Ar name
-/* $OpenBSD: x509.c,v 1.36 2024/01/12 11:24:03 job Exp $ */
+/* $OpenBSD: x509.c,v 1.37 2024/01/26 11:58:37 job Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
static int callb(int ok, X509_STORE_CTX *ctx);
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
- const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer);
+ const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer,
+ char *force_pubkey);
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
char *serial, int create, int days, int clrext, CONF *conf, char *section,
const EVP_MD *md_alg;
int modulus;
int multirdn;
+ int new;
int next_serial;
unsigned long nmflag;
int noout;
.order = &cfg.num,
},
#endif
+ {
+ .name = "key",
+ .argname = "file",
+ .type = OPTION_ARG_FUNC,
+ .opt.argfunc = x509_opt_signkey,
+ },
{
.name = "keyform",
.argname = "fmt",
.type = OPTION_ARG_FUNC,
.opt.argfunc = x509_opt_nameopt,
},
+ {
+ .name = "new",
+ .desc = "Generate a new certificate",
+ .type = OPTION_FLAG,
+ .opt.flag = &cfg.new,
+ },
{
.name = "next_serial",
.desc = "Print the next serial number",
" [-in file] [-inform der | net | pem] [-issuer]\n"
" [-issuer_hash] [-issuer_hash_old] [-keyform der | pem]\n"
" [-md5 | -sha1] [-modulus] [-multivalue-rdn]\n"
- " [-nameopt option] [-next_serial] [-noout] [-ocsp_uri]\n"
+ " [-nameopt option] [-new] [-next_serial] [-noout] [-ocsp_uri]\n"
" [-ocspid] [-out file] [-outform der | net | pem]\n"
" [-passin arg] [-pubkey] [-purpose] [-req] [-serial]\n"
" [-set_issuer name] [-set_serial n] [-set_subject name]\n"
X509 *x = NULL, *xca = NULL;
X509_NAME *iname = NULL, *sname = NULL;
EVP_PKEY *Fpkey = NULL, *Upkey = NULL, *CApkey = NULL;
+ EVP_PKEY *pkey;
int i;
BIO *out = NULL;
BIO *STDout = NULL;
cfg.keyformat, 0, NULL, "Forced key")) == NULL)
goto end;
}
+ if (cfg.new) {
+ if (cfg.infile != NULL) {
+ BIO_printf(bio_err, "Can't combine -new and -in\n");
+ goto end;
+ }
+ if (cfg.reqfile) {
+ BIO_printf(bio_err, "Can't combine -new and -req\n");
+ goto end;
+ }
+ if (cfg.set_subject == NULL) {
+ BIO_printf(bio_err, "Must use -set_subject with -new\n");
+ goto end;
+ }
+ if (cfg.keyfile == NULL) {
+ BIO_printf(bio_err, "Must use -signkey with -new\n");
+ goto end;
+ }
+ if ((Upkey = load_key(bio_err, cfg.keyfile, cfg.keyformat, 0,
+ passin, "Private key")) == NULL)
+ goto end;
+ }
if (cfg.reqfile) {
- EVP_PKEY *pkey;
BIO *in;
if (!cfg.sign_flag && !cfg.CA_flag) {
print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
cfg.nmflag);
+ }
+ if (cfg.reqfile || cfg.new) {
if ((x = X509_new()) == NULL)
goto end;
if ((pkey = Fpkey) == NULL)
pkey = X509_REQ_get0_pubkey(req);
+ if (pkey == NULL)
+ pkey = Upkey;
if (pkey == NULL)
goto end;
if (!X509_set_pubkey(x, pkey))
BIO_printf(STDout, "%02X%c", md[j],
(j + 1 == (int)n) ? '\n' : ':');
}
-
- /* should be in the library */
} else if (cfg.sign_flag == i && cfg.x509req == 0) {
- BIO_printf(bio_err, "Getting Private key\n");
if (Upkey == NULL) {
Upkey = load_key(bio_err, cfg.keyfile,
cfg.keyformat, 0, passin,
}
if (!sign(x, Upkey, cfg.days,
cfg.clrext, cfg.digest,
- extconf, cfg.extsect, iname))
+ extconf, cfg.extsect, iname,
+ cfg.force_pubkey))
goto end;
} else if (cfg.CA_flag == i) {
- BIO_printf(bio_err, "Getting CA Private Key\n");
if (cfg.CAkeyfile != NULL) {
CApkey = load_key(bio_err, cfg.CAkeyfile,
cfg.CAkeyformat, 0, passin,
/* self sign */
static int
sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
- CONF *conf, char *section, X509_NAME *issuer)
+ CONF *conf, char *section, X509_NAME *issuer, char *force_pubkey)
{
EVP_PKEY *pktmp;
(long) 60 * 60 * 24 * days) == NULL)
goto err;
- if (!X509_set_pubkey(x, pkey))
- goto err;
+ if (force_pubkey == NULL) {
+ if (!X509_set_pubkey(x, pkey))
+ goto err;
+ }
if (clrext) {
while (X509_get_ext_count(x) > 0) {
if (X509_delete_ext(x, 0) == NULL)