Reduce chances of issuer and serial number duplication by use of random
authorDr. Stephen Henson <steve@openssl.org>
Tue, 20 Apr 2004 12:05:26 +0000 (12:05 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 20 Apr 2004 12:05:26 +0000 (12:05 +0000)
initial serial numbers.

PR: 842

CHANGES
apps/CA.pl.in
apps/apps.c
apps/apps.h
apps/ca.c
apps/req.c

diff --git a/CHANGES b/CHANGES
index 5dd7a41b51cd5d8bc9308a67937e5359a1f28263..d6630830fc06bc9203340269cfbae04623291cb9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,15 @@
 
  Changes between 0.9.7c and 0.9.8  [xx XXX xxxx]
 
+  *) Reduce the chances of duplicate issuer name and serial numbers (in
+     violation of RFC3280) using the OpenSSL certificate creation utilities. 
+     This is done by creating a random 64 bit value for the initial serial
+     number when a serial number file is created or when a self signed
+     certificate is created using 'openssl req -x509'. The initial serial
+     number file is now moved from CA.pl to the 'ca' utility with a new
+     option -create_serial.
+     [Steve Henson]
+
   *) Reduced header interdepencies by declaring more opaque objects in
      ossl_typ.h. As a consequence, including some headers (eg. engine.h) will
      give fewer recursive includes, which could break lazy source code - so
index 2242f7e03b1c7b0430dafca30342498f881f4576..b09820755dca1056e613ff34f9e930330813f0c9 100644 (file)
@@ -84,9 +84,6 @@ foreach (@ARGV) {
                mkdir "${CATOP}/crl", $DIRMODE ;
                mkdir "${CATOP}/newcerts", $DIRMODE;
                mkdir "${CATOP}/private", $DIRMODE;
-               open OUT, ">${CATOP}/serial";
-               print OUT "01\n";
-               close OUT;
                open OUT, ">${CATOP}/index.txt";
                close OUT;
            }
@@ -105,7 +102,8 @@ foreach (@ARGV) {
                    print "Making CA certificate ...\n";
                    system ("$REQ -new -keyout " .
                        "${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ");
-                   system ("$CA -out ${CATOP}/$CACERT $CADAYS -batch " . 
+                   system ("$CA -create_serial " .
+                       "-out ${CATOP}/$CACERT $CADAYS -batch " . 
                        "-keyfile ${CATOP}/private/$CAKEY -selfsign " .
                        "-infiles ${CATOP}/$CAREQ ");
                    $RET=$?;
index 5e443221d334cd19f7b784d3ba087315f53f4c73..6925ab4cdd84c6ce80b459b151c47f7ec95ab06b 100644 (file)
@@ -1434,12 +1434,9 @@ BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
                        }
                else
                        {
-                       ASN1_INTEGER_set(ai,1);
                        ret=BN_new();
-                       if (ret == NULL)
+                       if (ret == NULL || !rand_serial(ret, ai))
                                BIO_printf(bio_err, "Out of memory\n");
-                       else
-                               BN_one(ret);
                        }
                }
        else
@@ -1601,6 +1598,33 @@ int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
        return 0;
        }
 
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
+       {
+       BIGNUM *btmp;
+       int ret = 0;
+       if (b)
+               btmp = b;
+       else
+               btmp = BN_new();
+
+       if (!btmp)
+               return 0;
+
+       if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+               goto error;
+       if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
+               goto error;
+
+       ret = 1;
+       
+       error:
+
+       if (!b)
+               BN_free(btmp);
+       
+       return ret;
+       }
+
 CA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
        {
        CA_DB *retdb = NULL;
index 7edafa4244876fdd2c01c80dd66ca2d63a229b05..6072a10bd3371d8df38b0a34169e7967a7a26f0d 100644 (file)
@@ -309,6 +309,7 @@ typedef struct ca_db_st
 BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai);
 int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai);
 int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix);
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
 CA_DB *load_index(char *dbfile, DB_ATTR *dbattr);
 int index_index(CA_DB *db);
 int save_index(char *dbfile, char *suffix, CA_DB *db);
@@ -338,4 +339,6 @@ X509_NAME *parse_name(char *str, long chtype, int multirdn);
 
 #define APP_PASS_LEN   1024
 
+#define SERIAL_RAND_BITS       64
+
 #endif
index 2e8377391aeee7e29444fd77dbf0531274d49abd..0fd445613d4ff25e62571afb5a3c7c8e6a0b7e93 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -241,6 +241,7 @@ int MAIN(int argc, char **argv)
        {
        ENGINE *e = NULL;
        char *key=NULL,*passargin=NULL;
+       int create_ser = 0;
        int free_key = 0;
        int total=0;
        int total_done=0;
@@ -354,6 +355,8 @@ EF_ALIGNMENT=0;
                        subj= *(++argv);
                        /* preserve=1; */
                        }
+               else if (strcmp(*argv,"-create_serial") == 0)
+                       create_ser = 1;
                else if (strcmp(*argv,"-multivalue-rdn") == 0)
                        multirdn=1;
                else if (strcmp(*argv,"-startdate") == 0)
@@ -1097,7 +1100,7 @@ bad:
                        goto err;
                        }
 
-               if ((serial=load_serial(serialfile, 0, NULL)) == NULL)
+               if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
                        {
                        BIO_printf(bio_err,"error while loading serial number\n");
                        goto err;
index 5df8f89fcd03f7223e56f2b4b9184400eece5991..16e27d1b38acbce8862571d73e30995ff2f59fd0 100644 (file)
@@ -919,7 +919,9 @@ loop:
                                }
                        else
                                {
-                               if (!ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L)) goto end;
+                               if (!rand_serial(NULL,
+                                       X509_get_serialNumber(x509ss)))
+                                               goto end;
                                }
 
                        if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end;