Merge from the ASN1 branch of new ASN1 code
[openssl.git] / apps / ca.c
index d28cde99d8c8ecb34397d948842d6da91b852c36..c0677a5f2b3db5fcfaaf34bc32a4d864a2dac72c 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -74,6 +74,7 @@
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
 #include <openssl/pem.h>
+#include <openssl/engine.h>
 
 #ifndef W_OK
 #  ifdef VMS
@@ -152,7 +153,8 @@ static char *ca_usage[]={
 " -days arg       - number of days to certify the certificate for\n",
 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
 " -policy arg     - The CA 'policy' to support\n",
-" -keyfile arg    - PEM private key file\n",
+" -keyfile arg    - private key file\n",
+" -keyform arg    - private key file format (PEM or ENGINE)\n",
 " -key arg        - key to decode the private key if it is encrypted\n",
 " -cert file      - The CA certificate\n",
 " -in file        - The input PEM encoded certificate request(s)\n",
@@ -167,6 +169,7 @@ static char *ca_usage[]={
 " -revoke file    - Revoke a certificate (given in file)\n",
 " -extensions ..  - Extension section (override value in config file)\n",
 " -crlexts ..     - CRL extension section (override value in config file)\n",
+" -engine e       - use engine e, possibly a hardware device.\n",
 NULL
 };
 
@@ -177,11 +180,11 @@ extern int EF_ALIGNMENT;
 #endif
 
 static void lookup_fail(char *name,char *tag);
-static unsigned long index_serial_hash(char **a);
-static int index_serial_cmp(char **a, char **b);
-static unsigned long index_name_hash(char **a);
+static unsigned long index_serial_hash(const char **a);
+static int index_serial_cmp(const char **a, const char **b);
+static unsigned long index_name_hash(const char **a);
 static int index_name_qual(char **a);
-static int index_name_cmp(char **a,char **b);
+static int index_name_cmp(const char **a,const char **b);
 static BIGNUM *load_serial(char *serialfile);
 static int save_serial(char *serialfile, BIGNUM *serial);
 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
@@ -212,11 +215,18 @@ static char *section=NULL;
 static int preserve=0;
 static int msie_hack=0;
 
+static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
+static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
+static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
+static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
+
+
 int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
        {
-       char *key=NULL;
+       ENGINE *e = NULL;
+       char *key=NULL,*passargin=NULL;
        int total=0;
        int total_done=0;
        int badops=0;
@@ -233,6 +243,7 @@ int MAIN(int argc, char **argv)
        char *policy=NULL;
        char *keyfile=NULL;
        char *certfile=NULL;
+       int keyform=FORMAT_PEM;
        char *infile=NULL;
        char *spkac_file=NULL;
        char *ss_cert_file=NULL;
@@ -268,6 +279,7 @@ int MAIN(int argc, char **argv)
 #define BSIZE 256
        MS_STATIC char buf[3][BSIZE];
        char *randfile=NULL;
+       char *engine = NULL;
 
 #ifdef EFENCE
 EF_PROTECT_FREE=1;
@@ -333,6 +345,16 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        keyfile= *(++argv);
                        }
+               else if (strcmp(*argv,"-keyform") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keyform=str2fmt(*(++argv));
+                       }
+               else if (strcmp(*argv,"-passin") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       passargin= *(++argv);
+                       }
                else if (strcmp(*argv,"-key") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -414,6 +436,11 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        crl_ext= *(++argv);
                        }
+               else if (strcmp(*argv,"-engine") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       engine= *(++argv);
+                       }
                else
                        {
 bad:
@@ -434,6 +461,24 @@ bad:
 
        ERR_load_crypto_strings();
 
+       if (engine != NULL)
+               {
+               if((e = ENGINE_by_id(engine)) == NULL)
+                       {
+                       BIO_printf(bio_err,"invalid engine \"%s\"\n",
+                               engine);
+                       goto err;
+                       }
+               if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
+                       {
+                       BIO_printf(bio_err,"can't use that engine\n");
+                       goto err;
+                       }
+               BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
+               /* Free our "structural" reference. */
+               ENGINE_free(e);
+               }
+
        /*****************************************************************/
        if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
        if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
@@ -526,14 +571,36 @@ bad:
                lookup_fail(section,ENV_PRIVATE_KEY);
                goto err;
                }
-       if (BIO_read_filename(in,keyfile) <= 0)
+       if(!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
                {
-               perror(keyfile);
-               BIO_printf(bio_err,"trying to load CA private key\n");
+               BIO_printf(bio_err,"Error getting password\n");
                goto err;
                }
+       if (keyform == FORMAT_ENGINE)
+               {
+               if (!e)
+                       {
+                       BIO_printf(bio_err,"no engine specified\n");
+                       goto err;
+                       }
+               pkey = ENGINE_load_private_key(e, keyfile, key);
+               }
+       else if (keyform == FORMAT_PEM)
+               {
+               if (BIO_read_filename(in,keyfile) <= 0)
+                       {
+                       perror(keyfile);
+                       BIO_printf(bio_err,"trying to load CA private key\n");
+                       goto err;
+                       }
                pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
-               if(key) memset(key,0,strlen(key));
+               }
+       else
+               {
+               BIO_printf(bio_err,"bad input format specified for key file\n");
+               goto err;
+               }
+       if(key) memset(key,0,strlen(key));
        if (pkey == NULL)
                {
                BIO_printf(bio_err,"unable to load CA private key\n");
@@ -680,21 +747,29 @@ bad:
        if (verbose)
                {
                BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
+#ifdef VMS
+               {
+               BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+               out = BIO_push(tmpbio, out);
+               }
+#endif
                TXT_DB_write(out,db);
                BIO_printf(bio_err,"%d entries loaded from the database\n",
                        db->data->num);
                BIO_printf(bio_err,"generating index\n");
                }
        
-       if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash,
-               index_serial_cmp))
+       if (!TXT_DB_create_index(db, DB_serial, NULL,
+                       LHASH_HASH_FN(index_serial_hash),
+                       LHASH_COMP_FN(index_serial_cmp)))
                {
                BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
                goto err;
                }
 
-       if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash,
-               index_name_cmp))
+       if (!TXT_DB_create_index(db, DB_name, index_name_qual,
+                       LHASH_HASH_FN(index_name_hash),
+                       LHASH_COMP_FN(index_name_cmp)))
                {
                BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
                        db->error,db->arg1,db->arg2);
@@ -714,7 +789,15 @@ bad:
                                }
                        }
                else
+                       {
                        BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
+#ifdef VMS
+                       {
+                       BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+                       Sout = BIO_push(tmpbio, Sout);
+                       }
+#endif
+                       }
                }
 
        if (req)
@@ -1010,7 +1093,7 @@ bad:
 #endif
 
                        BIO_free(in);
-                       BIO_free(out);
+                       BIO_free_all(out);
                        in=NULL;
                        out=NULL;
                        if (rename(serialfile,buf[2]) < 0)
@@ -1118,7 +1201,7 @@ bad:
                                if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
                                        buf[0],BSIZE)) goto err;
 
-                               sk_X509_REVOKED_push(ci->revoked,r);
+                               X509_CRL_add0_revoked(crl,r);
                                }
                        }
                /* sort the data so it will be written in serial
@@ -1227,9 +1310,9 @@ bad:
        ret=0;
 err:
        BIO_free(hex);
-       BIO_free(Cout);
-       BIO_free(Sout);
-       BIO_free(out);
+       BIO_free_all(Cout);
+       BIO_free_all(Sout);
+       BIO_free_all(out);
        BIO_free(in);
 
        sk_X509_pop_free(cert_sk,X509_free);
@@ -1251,31 +1334,31 @@ static void lookup_fail(char *name, char *tag)
        BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
        }
 
-static unsigned long index_serial_hash(char **a)
+static unsigned long index_serial_hash(const char **a)
        {
-       char *n;
+       const char *n;
 
        n=a[DB_serial];
        while (*n == '0') n++;
        return(lh_strhash(n));
        }
 
-static int index_serial_cmp(char **a, char **b)
+static int index_serial_cmp(const char **a, const char **b)
        {
-       char *aa,*bb;
+       const char *aa,*bb;
 
        for (aa=a[DB_serial]; *aa == '0'; aa++);
        for (bb=b[DB_serial]; *bb == '0'; bb++);
        return(strcmp(aa,bb));
        }
 
-static unsigned long index_name_hash(char **a)
+static unsigned long index_name_hash(const char **a)
        { return(lh_strhash(a[DB_name])); }
 
 static int index_name_qual(char **a)
        { return(a[0][0] == 'V'); }
 
-static int index_name_cmp(char **a, char **b)
+static int index_name_cmp(const char **a, const char **b)
        { return(strcmp(a[DB_name],
             b[DB_name])); }
 
@@ -1344,7 +1427,7 @@ static int save_serial(char *serialfile, BIGNUM *serial)
        BIO_puts(out,"\n");
        ret=1;
 err:
-       if (out != NULL) BIO_free(out);
+       if (out != NULL) BIO_free_all(out);
        if (ai != NULL) ASN1_INTEGER_free(ai);
        return(ret);
        }
@@ -2176,7 +2259,7 @@ static int do_revoke(X509 *x509, TXT_DB *db)
                goto err;
 
                }
-       else if (index_name_cmp(row,rrow))
+       else if (index_name_cmp((const char **)row,(const char **)rrow))
                {
                BIO_printf(bio_err,"ERROR:name does not match %s\n",
                           row[DB_name]);