Implement CRL numbers.
Contributed in whole by Laurent Genier <Laurent.Genier@intrinsec.com>
PR: 644
diff --git a/apps/ca.c b/apps/ca.c
index 618d88b..2c7e91a 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -122,6 +122,7 @@
 #define ENV_NEW_CERTS_DIR	"new_certs_dir"
 #define ENV_CERTIFICATE 	"certificate"
 #define ENV_SERIAL		"serial"
+#define ENV_CRLNUMBER		"crlnumber"
 #define ENV_CRL			"crl"
 #define ENV_PRIVATE_KEY		"private_key"
 #define ENV_RANDFILE		"RANDFILE"
@@ -277,6 +278,7 @@
 	char *outfile=NULL;
 	char *outdir=NULL;
 	char *serialfile=NULL;
+	char *crlnumberfile=NULL;
 	char *extensions=NULL;
 	char *extfile=NULL;
 	char *subj=NULL;
@@ -285,6 +287,7 @@
 	int rev_type = REV_NONE;
 	char *rev_arg = NULL;
 	BIGNUM *serial=NULL;
+	BIGNUM *crlnumber=NULL;
 	char *startdate=NULL;
 	char *enddate=NULL;
 	long days=0;
@@ -1337,6 +1340,14 @@
 				}
 			}
 
+		if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
+			!= NULL)
+			if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
+				{
+				BIO_printf(bio_err,"error while loading CRL number\n");
+				goto err;
+				}
+
 		if (!crldays && !crlhours)
 			{
 			if (!NCONF_get_number(conf,section,
@@ -1418,14 +1429,24 @@
 
 		/* Add any extensions asked for */
 
-		if (crl_ext)
+		if (crl_ext || crlnumberfile != NULL)
 			{
 			X509V3_CTX crlctx;
 			X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
 			X509V3_set_nconf(&crlctx, conf);
 
-			if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
-				crl_ext, crl)) goto err;
+			if (crl_ext)
+				if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
+					crl_ext, crl)) goto err;
+			if (crlnumberfile != NULL)
+				{
+				tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
+				if (!tmpser) goto err;
+				X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
+				ASN1_INTEGER_free(tmpser);
+				crl_v2 = 1;
+				if (!BN_add_word(crlnumber,1)) goto err;
+				}
 			}
 		if (crl_ext || crl_v2)
 			{
@@ -1433,9 +1454,17 @@
 				goto err; /* version 2 CRL */
 			}
 
+		
+		if (crlnumberfile != NULL)	/* we have a CRL number that need updating */
+			if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
+
 		if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
 
 		PEM_write_bio_X509_CRL(Sout,crl);
+
+		if (crlnumberfile != NULL)	/* Rename the crlnumber file */
+			if (!rotate_serial(crlnumberfile,"new","old")) goto err;
+
 		}
 	/*****************************************************************/
 	if (dorevoke)
@@ -3086,4 +3115,3 @@
 
 	return ret;
 	}
-
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 2696044..8941f45 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -44,6 +44,8 @@
 
 certificate	= $dir/cacert.pem 	# The CA certificate
 serial		= $dir/serial 		# The current serial number
+crlnumber	= $dir/crlnumber	# the current crl number
+					# must be commented out to leave a V1 CRL
 crl		= $dir/crl.pem 		# The current CRL
 private_key	= $dir/private/cakey.pem# The private key
 RANDFILE	= $dir/private/.rand	# private random number file
@@ -60,6 +62,7 @@
 
 # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
 # so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
 # crl_extensions	= crl_ext
 
 default_days	= 365			# how long to certify for