aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Salz <rsalz@openssl.org>2017-08-16 15:49:25 -0400
committerRich Salz <rsalz@openssl.org>2017-08-22 09:00:04 -0400
commitffb46830e2dfd3203044e6190f50a20fec50162d (patch)
tree744d016ce5d6dea1aa48a36e95024d8333dff969
parent932c0df29b7a5a2902c52e2f536b5b83392e2d42 (diff)
downloadopenssl-ffb46830e2dfd3203044e6190f50a20fec50162d.tar.gz
Add random serial# support.
Add -rand_serial to CA command and "serial_rand" config option. Up RAND_BITS to 159, and comment why: now confirms to CABForum guidelines (Ballot 164) as well as IETF RFC 5280 (PKIX). Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4185)
-rw-r--r--apps/apps.c8
-rw-r--r--apps/apps.h7
-rw-r--r--apps/ca.c62
-rw-r--r--doc/man1/ca.pod9
-rw-r--r--test/recipes/80-test_ca.t2
5 files changed, 59 insertions, 29 deletions
diff --git a/apps/apps.c b/apps/apps.c
index 6ff41972e3..79ef933935 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -1503,15 +1503,11 @@ int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
BIGNUM *btmp;
int ret = 0;
- if (b)
- btmp = b;
- else
- btmp = BN_new();
-
+ btmp = b == NULL ? BN_new() : b;
if (btmp == NULL)
return 0;
- if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+ if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
goto error;
if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
goto error;
diff --git a/apps/apps.h b/apps/apps.h
index 3b6597869f..fdf316a08e 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -568,7 +568,12 @@ void store_setup_crl_download(X509_STORE *st);
# define APP_PASS_LEN 1024
-# define SERIAL_RAND_BITS 64
+/*
+ * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
+ * so that the first bit will never be one, so that the DER encoding
+ * rules won't force a leading octet.
+ */
+# define SERIAL_RAND_BITS 159
int app_isdir(const char *);
int app_access(const char *, int flag);
diff --git a/apps/ca.c b/apps/ca.c
index c1c2c49047..436aa855cf 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -62,6 +62,7 @@
#define ENV_NEW_CERTS_DIR "new_certs_dir"
#define ENV_CERTIFICATE "certificate"
#define ENV_SERIAL "serial"
+#define ENV_RAND_SERIAL "rand_serial"
#define ENV_CRLNUMBER "crlnumber"
#define ENV_PRIVATE_KEY "private_key"
#define ENV_DEFAULT_DAYS "default_days"
@@ -153,6 +154,7 @@ typedef enum OPTION_choice {
OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
+ OPT_RAND_SERIAL,
OPT_R_ENUM,
/* Do not change the order here; see related case statements below */
OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
@@ -167,6 +169,8 @@ const OPTIONS ca_options[] = {
{"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
{"create_serial", OPT_CREATE_SERIAL, '-',
"If reading serial fails, create a new random serial"},
+ {"rand_serial", OPT_RAND_SERIAL, '-',
+ "Always create a random serial; do not store it"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
"Enable support for multivalued RDNs"},
{"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
@@ -258,7 +262,7 @@ int ca_main(int argc, char **argv)
int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
- int i, j, selfsign = 0;
+ int rand_ser = 0, i, j, selfsign = 0;
long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
unsigned long chtype = MBSTRING_ASC, certopt = 0;
X509 *x509 = NULL, *x509p = NULL, *x = NULL;
@@ -303,6 +307,9 @@ opthelp:
case OPT_UTF8:
chtype = MBSTRING_UTF8;
break;
+ case OPT_RAND_SERIAL:
+ rand_ser = 1;
+ break;
case OPT_CREATE_SERIAL:
create_ser = 1;
break;
@@ -774,9 +781,13 @@ end_of_options:
if (verbose)
BIO_printf(bio_err, "policy is %s\n", policy);
- serialfile = lookup_conf(conf, section, ENV_SERIAL);
- if (serialfile == NULL)
- goto end;
+ if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) {
+ rand_ser = 1;
+ } else {
+ serialfile = lookup_conf(conf, section, ENV_SERIAL);
+ if (serialfile == NULL)
+ goto end;
+ }
if (extconf == NULL) {
/*
@@ -838,18 +849,25 @@ end_of_options:
goto end;
}
- if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
- BIO_printf(bio_err, "error while loading serial number\n");
- goto end;
- }
- if (verbose) {
- if (BN_is_zero(serial)) {
- BIO_printf(bio_err, "next serial number is 00\n");
- } else {
- if ((f = BN_bn2hex(serial)) == NULL)
- goto end;
- BIO_printf(bio_err, "next serial number is %s\n", f);
- OPENSSL_free(f);
+ if (rand_ser) {
+ if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) {
+ BIO_printf(bio_err, "error generating serial number\n");
+ goto end;
+ }
+ } else {
+ if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
+ BIO_printf(bio_err, "error while loading serial number\n");
+ goto end;
+ }
+ if (verbose) {
+ if (BN_is_zero(serial)) {
+ BIO_printf(bio_err, "next serial number is 00\n");
+ } else {
+ if ((f = BN_bn2hex(serial)) == NULL)
+ goto end;
+ BIO_printf(bio_err, "next serial number is %s\n", f);
+ OPENSSL_free(f);
+ }
}
}
@@ -973,7 +991,8 @@ end_of_options:
BIO_printf(bio_err, "Write out database with %d new entries\n",
sk_X509_num(cert_sk));
- if (!save_serial(serialfile, "new", serial, NULL))
+ if (!rand_ser
+ && !save_serial(serialfile, "new", serial, NULL))
goto end;
if (!save_index(dbfile, "new", db))
@@ -1171,7 +1190,8 @@ end_of_options:
/* we have a CRL number that need updating */
if (crlnumberfile != NULL)
- if (!save_serial(crlnumberfile, "new", crlnumber, NULL))
+ if (!rand_ser
+ && !save_serial(crlnumberfile, "new", crlnumber, NULL))
goto end;
BN_free(crlnumber);
@@ -1213,16 +1233,16 @@ end_of_options:
BIO_printf(bio_err, "Data Base Updated\n");
}
}
- /*****************************************************************/
ret = 0;
+
end:
+ if (ret)
+ ERR_print_errors(bio_err);
BIO_free_all(Sout);
BIO_free_all(out);
BIO_free_all(in);
sk_X509_pop_free(cert_sk, X509_free);
- if (ret)
- ERR_print_errors(bio_err);
if (free_key)
OPENSSL_free(key);
BN_free(serial);
diff --git a/doc/man1/ca.pod b/doc/man1/ca.pod
index a985631531..21e692e511 100644
--- a/doc/man1/ca.pod
+++ b/doc/man1/ca.pod
@@ -51,6 +51,7 @@ B<openssl> B<ca>
[B<-subj arg>]
[B<-utf8>]
[B<-create_serial>]
+[B<-rand_serial>]
[B<-multivalue-rdn>]
[B<-rand file...>]
[B<-writerand file>]
@@ -262,6 +263,13 @@ configuration file, must be valid UTF8 strings.
If reading serial from the text file as specified in the configuration
fails, specifying this option creates a new random serial to be used as next
serial number.
+To get random serial numbers, use the B<-rand_serial> flag instead; this
+should only be used for simple error-recovery.
+
+=item B<-rand_serial>
+
+Generate a large random number to use as the serial number.
+This overrides any option or configuration to use a serial number file.
=item B<-multivalue-rdn>
@@ -614,6 +622,7 @@ A sample configuration file with the relevant sections for B<ca>:
certificate = $dir/cacert.pem # The CA cert
serial = $dir/serial # serial no file
+ #rand_serial = yes # for random serial#'s
private_key = $dir/private/cakey.pem# CA private key
RANDFILE = $dir/private/.rand # random number file
diff --git a/test/recipes/80-test_ca.t b/test/recipes/80-test_ca.t
index 4c470fbfe2..557777e191 100644
--- a/test/recipes/80-test_ca.t
+++ b/test/recipes/80-test_ca.t
@@ -35,7 +35,7 @@ plan tests => 5;
if !ok(run(perlapp(["CA.pl","-newreq"])),
'creating certificate request');
- $ENV{OPENSSL_CONFIG} = '-config "'.$std_openssl_cnf.'"';
+ $ENV{OPENSSL_CONFIG} = '-rand_serial -config "'.$std_openssl_cnf.'"';
skip "failed to sign certificate request", 2
if !is(yes(cmdstr(perlapp(["CA.pl", "-sign"]))), 0,
'signing certificate request');