Commit 16b1b035 authored by Richard Levitte's avatar Richard Levitte
Browse files

Implement self-signing in 'openssl ca'. This makes it easier to have

the CA certificate part of the CA database, and combined with
'unique_subject=no', it should make operations like CA certificate
roll-over easier.
parent e6526fbf
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -4,6 +4,13 @@

 Changes between 0.9.7a and 0.9.8  [xx XXX xxxx]

  *) Make it possible to create self-signed certificates with 'openssl ca'
     in such a way that the self-signed certificate becomes part of the
     CA database and uses the same mechanisms for serial number generation
     as all other certificate signing.  The new flag '-selfsign' enables
     this functionality.  Adapt CA.sh and CA.pl.in.
     [Richard Levitte]

  *) Add functionality to check the public key of a certificate request
     against a given private.  This is useful to check that a certificate
     request can be signed by that key (self-signing).
+8 −3
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@
# demoCA ... where everything is stored

$SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"};
$DAYS="-days 365";
$DAYS="-days 365";	# 1 year
$CADAYS="-days 1095";	# 3 years
$REQ="openssl req $SSLEAY_CONFIG";
$CA="openssl ca $SSLEAY_CONFIG";
$VERIFY="openssl verify";
@@ -46,6 +47,7 @@ $PKCS12="openssl pkcs12";

$CATOP="./demoCA";
$CAKEY="cakey.pem";
$CAREQ="careq.pem";
$CACERT="cacert.pem";

$DIRMODE = 0777;
@@ -101,8 +103,11 @@ foreach (@ARGV) {
		    $RET=$?;
		} else {
		    print "Making CA certificate ...\n";
		    system ("$REQ -new -x509 -keyout " .
			"${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS");
		    system ("$REQ -new -keyout " .
			"${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ");
		    system ("$CA -out ${CATOP}/$CACERT $CADAYS -batch " . 
			"-keyfile ${CATOP}/private/$CAKEY -selfsign " .
			"-infiles ${CATOP}/$CAREQ ");
		    $RET=$?;
		}
	    }
+9 −4
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@
# default openssl.cnf file has setup as per the following
# demoCA ... where everything is stored

DAYS="-days 365"
DAYS="-days 365"	# 1 year
CADAYS="-days 1095"	# 3 years
REQ="openssl req $SSLEAY_CONFIG"
CA="openssl ca $SSLEAY_CONFIG"
VERIFY="openssl verify"
@@ -38,6 +39,7 @@ X509="openssl x509"

CATOP=./demoCA
CAKEY=./cakey.pem
CAREQ=./careq.pem
CACERT=./cacert.pem

for i
@@ -70,7 +72,7 @@ case $i in
	mkdir ${CATOP}/crl 
	mkdir ${CATOP}/newcerts
	mkdir ${CATOP}/private
	echo "01" > ${CATOP}/serial
	echo "00" > ${CATOP}/serial
	touch ${CATOP}/index.txt
    fi
    if [ ! -f ${CATOP}/private/$CAKEY ]; then
@@ -83,8 +85,11 @@ case $i in
	    RET=$?
	else
	    echo "Making CA certificate ..."
	    $REQ -new -x509 -keyout ${CATOP}/private/$CAKEY \
			   -out ${CATOP}/$CACERT $DAYS
	    $REQ -new -keyout ${CATOP}/private/$CAKEY \
			   -out ${CATOP}/$CAREQ
	    $CA -out ${CATOP}/$CACERT $CADAYS -batch \
			   -keyfile ${CATOP}/private/$CAKEY -selfsign \
			   -infiles ${CATOP}/$CAREQ 
	    RET=$?
	fi
    fi
+59 −31
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
		   BIGNUM *serial, char *subj, int email_dn, char *startdate,
		   char *enddate, long days, int batch, char *ext_sect, CONF *conf,
		   int verbose, unsigned long certopt, unsigned long nameopt,
		   int default_op, int ext_copy);
		   int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
			const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
			CA_DB *db, BIGNUM *serial, char *subj, int email_dn,
@@ -225,7 +225,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
	int email_dn, char *startdate, char *enddate, long days, int batch,
       	int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
	unsigned long certopt, unsigned long nameopt, int default_op,
	int ext_copy);
	int ext_copy, int selfsign);
static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
static int get_certificate_status(const char *ser_status, CA_DB *db);
static int do_updatedb(CA_DB *db);
@@ -292,7 +292,8 @@ int MAIN(int argc, char **argv)
	unsigned long nameopt = 0, certopt = 0;
	int default_op = 1;
	int ext_copy = EXT_COPY_NONE;
	X509 *x509=NULL;
	int selfsign = 0;
	X509 *x509=NULL, *x509p = NULL;
	X509 *x=NULL;
	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
	char *dbfile=NULL;
@@ -406,6 +407,8 @@ EF_ALIGNMENT=0;
			if (--argc < 1) goto bad;
			certfile= *(++argv);
			}
		else if (strcmp(*argv,"-selfsign") == 0)
			selfsign=1;
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
@@ -700,7 +703,7 @@ bad:
	}

	/*****************************************************************/
	/* we definitely need a public key, so let's get it */
	/* we definitely need a private key, so let's get it */

	if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
		section,ENV_PRIVATE_KEY)) == NULL))
@@ -728,7 +731,10 @@ bad:

	/*****************************************************************/
	/* we need a certificate */
	if ((certfile == NULL) && ((certfile=NCONF_get_string(conf,
	if (!selfsign || spkac_file || ss_cert_file || gencrl)
		{
		if ((certfile == NULL)
			&& ((certfile=NCONF_get_string(conf,
				     section,ENV_CERTIFICATE)) == NULL))
			{
			lookup_fail(section,ENV_CERTIFICATE);
@@ -744,6 +750,8 @@ bad:
			BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
			goto err;
			}
		}
	if (!selfsign) x509p = x509;

	f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
	if (f == NULL)
@@ -1175,10 +1183,10 @@ bad:
		if (infile != NULL)
			{
			total++;
			j=certify(&x,infile,pkey,x509,dgst,attribs,db,
			j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
				serial,subj,email_dn,startdate,enddate,days,batch,
				extensions,conf,verbose, certopt, nameopt,
				default_op, ext_copy);
				default_op, ext_copy, selfsign);
			if (j < 0) goto err;
			if (j > 0)
				{
@@ -1195,10 +1203,10 @@ bad:
		for (i=0; i<argc; i++)
			{
			total++;
			j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
			j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
				serial,subj,email_dn,startdate,enddate,days,batch,
				extensions,conf,verbose, certopt, nameopt,
				default_op, ext_copy);
				default_op, ext_copy, selfsign);
			if (j < 0) goto err;
			if (j > 0)
				{
@@ -1515,7 +1523,7 @@ err:
	BN_free(serial);
	free_index(db);
	EVP_PKEY_free(pkey);
	X509_free(x509);
	if (x509) X509_free(x509);
	X509_CRL_free(crl);
	NCONF_free(conf);
	OBJ_cleanup();
@@ -1533,7 +1541,7 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
	     BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
	     unsigned long certopt, unsigned long nameopt, int default_op,
	     int ext_copy)
	     int ext_copy, int selfsign)
	{
	X509_REQ *req=NULL;
	BIO *in=NULL;
@@ -1558,6 +1566,12 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,

	BIO_printf(bio_err,"Check that the request matches the signature\n");

	if (selfsign && !X509_REQ_check_private_key(req,pkey))
		{
		BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
		ok=0;
		goto err;
		}
	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
		{
		BIO_printf(bio_err,"error unpacking public key\n");
@@ -1582,7 +1596,7 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,

	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
		startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
		certopt, nameopt, default_op, ext_copy);
		certopt, nameopt, default_op, ext_copy, selfsign);

err:
	if (req != NULL) X509_REQ_free(req);
@@ -1636,7 +1650,7 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,

	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
		days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
		ext_copy);
		ext_copy, 0);

err:
	if (rreq != NULL) X509_REQ_free(rreq);
@@ -1649,7 +1663,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
	     int email_dn, char *startdate, char *enddate, long days, int batch,
	     int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
	     unsigned long certopt, unsigned long nameopt, int default_op,
	     int ext_copy)
	     int ext_copy, int selfsign)
	{
	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
	ASN1_UTCTIME *tm,*tmptm;
@@ -1753,6 +1767,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
		}

	/* take a copy of the issuer name before we mess with it. */
	if (selfsign)
		CAname=X509_NAME_dup(name);
	else
		CAname=X509_NAME_dup(x509->cert_info->subject);
	if (CAname == NULL) goto err;
	str=str2=NULL;
@@ -1965,8 +1982,16 @@ again2:

	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
		goto err;
	if (selfsign)
		{
		if (!X509_set_issuer_name(ret,subject))
			goto err;
		}
	else
		{
		if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
			goto err;
		}

	if (strcmp(startdate,"today") == 0)
		X509_gmtime_adj(X509_get_notBefore(ret),0);
@@ -2001,6 +2026,9 @@ again2:
		ci->extensions = NULL;

		/* Initialize the context structure */
		if (selfsign)
			X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
		else
			X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);

		if (extconf)
@@ -2344,7 +2372,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
	EVP_PKEY_free(pktmp);
	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
		   days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
			ext_copy);
			ext_copy, 0);
err:
	if (req != NULL) X509_REQ_free(req);
	if (parms != NULL) CONF_free(parms);
+5 −6
Original line number Diff line number Diff line
@@ -66,14 +66,13 @@ Section 5 will tell you more on how to handle the certificate you
received.


4. Creating a self-signed certificate
4. Creating a self-signed test certificate

If you don't want to deal with another certificate authority, or just
want to create a test certificate for yourself, or are setting up a
certificate authority of your own, you may want to make the requested
certificate a self-signed one.  This is similar to creating a
certificate request, but creates a certificate instead of a
certificate request (1095 is 3 years):
want to create a test certificate for yourself.  This is similar to
creating a certificate request, but creates a certificate instead of
a certificate request.  This is NOT the recommended way to create a
CA certificate, see ca.txt.

  openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095