Commit ffb46830 authored by Rich Salz's avatar Rich Salz
Browse files

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: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4185)
parent 932c0df2
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -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;
+6 −1
Original line number Diff line number Diff line
@@ -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);
+41 −21
Original line number Diff line number Diff line
@@ -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);

        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,6 +849,12 @@ end_of_options:
            goto end;
        }

        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;
@@ -852,6 +869,7 @@ end_of_options:
                    OPENSSL_free(f);
                }
            }
        }

        if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
            BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
@@ -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);
+9 −0
Original line number Diff line number Diff line
@@ -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

+1 −1
Original line number Diff line number Diff line
@@ -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');