-CAserial does take a filename argument.
[openssl.git] / apps / x509.c
index 9422e1d15cdef004d915ad272eb5203b5fc3a599..12b269f9ab70a29e4298f430f8dbc841d1d1ebac 100644 (file)
@@ -60,7 +60,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef NO_STDIO
+#ifdef OPENSSL_NO_STDIO
 #define APPS_WIN16
 #endif
 #include "apps.h"
@@ -73,7 +73,6 @@
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
 #include <openssl/pem.h>
-#include <openssl/engine.h>
 
 #undef PROG
 #define PROG x509_main
@@ -123,7 +122,8 @@ static char *x509_usage[]={
 " -CAkey arg      - set the CA key, must be PEM format\n",
 "                   missing, it is assumed to be in the CA file.\n",
 " -CAcreateserial - create serial number file if it does not exist\n",
-" -CAserial       - serial file\n",
+" -CAserial arg   - serial file\n",
+" -set_serial     - serial number to use\n",
 " -text           - print the certificate in text form\n",
 " -C              - print out C code forms\n",
 " -md2/-md5/-sha1/-mdc2 - digest to use\n",
@@ -138,10 +138,11 @@ NULL
 
 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
 static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
-                                               LHASH *conf, char *section);
+                                               CONF *conf, char *section);
 static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
                         X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
-                        int create,int days, int clrext, LHASH *conf, char *section);
+                        int create,int days, int clrext, CONF *conf, char *section,
+                                               ASN1_INTEGER *sno);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 static int reqfile=0;
 
@@ -155,6 +156,7 @@ int MAIN(int argc, char **argv)
        X509 *x=NULL,*xca=NULL;
        ASN1_OBJECT *objtmp;
        EVP_PKEY *Upkey=NULL,*CApkey=NULL;
+       ASN1_INTEGER *sno = NULL;
        int i,num,badops=0;
        BIO *out=NULL;
        BIO *STDout=NULL;
@@ -176,7 +178,7 @@ int MAIN(int argc, char **argv)
        int fingerprint=0;
        char buf[256];
        const EVP_MD *md_alg,*digest=EVP_md5();
-       LHASH *extconf = NULL;
+       CONF *extconf = NULL;
        char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
        int need_rand = 0;
        int checkend=0,checkoffset=0;
@@ -189,8 +191,11 @@ int MAIN(int argc, char **argv)
 
        if (bio_err == NULL)
                bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
+
+       if (!load_config(bio_err, NULL))
+               goto end;
        STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
-#ifdef VMS
+#ifdef OPENSSL_SYS_VMS
        {
        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
        STDout = BIO_push(tmpbio, STDout);
@@ -240,7 +245,7 @@ int MAIN(int argc, char **argv)
                else if (strcmp(*argv,"-CAkeyform") == 0)
                        {
                        if (--argc < 1) goto bad;
-                       CAformat=str2fmt(*(++argv));
+                       CAkeyformat=str2fmt(*(++argv));
                        }
                else if (strcmp(*argv,"-days") == 0)
                        {
@@ -301,6 +306,12 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        CAserial= *(++argv);
                        }
+               else if (strcmp(*argv,"-set_serial") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-addtrust") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -435,27 +446,11 @@ int MAIN(int argc, char **argv)
                {
 bad:
                for (pp=x509_usage; (*pp != NULL); pp++)
-                       BIO_printf(bio_err,*pp);
+                       BIO_printf(bio_err,"%s",*pp);
                goto end;
                }
 
-       if (engine != NULL)
-               {
-               if((e = ENGINE_by_id(engine)) == NULL)
-                       {
-                       BIO_printf(bio_err,"invalid engine \"%s\"\n",
-                               engine);
-                       goto end;
-                       }
-               if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
-                       {
-                       BIO_printf(bio_err,"can't use that engine\n");
-                       goto end;
-                       }
-               BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
-               /* Free our "structural" reference. */
-               ENGINE_free(e);
-               }
+        e = setup_engine(bio_err, engine, 0);
 
        if (need_rand)
                app_RAND_load_file(NULL, bio_err, 0);
@@ -486,7 +481,8 @@ bad:
                {
                long errorline;
                X509V3_CTX ctx2;
-               if (!(extconf=CONF_load(NULL,extfile,&errorline)))
+               extconf = NCONF_new(NULL);
+               if (!NCONF_load(extconf, extfile,&errorline))
                        {
                        if (errorline <= 0)
                                BIO_printf(bio_err,
@@ -500,7 +496,7 @@ bad:
                        }
                if (!extsect)
                        {
-                       extsect = CONF_get_string(extconf, "default", "extensions");
+                       extsect = NCONF_get_string(extconf, "default", "extensions");
                        if (!extsect)
                                {
                                ERR_clear_error();
@@ -508,8 +504,8 @@ bad:
                                }
                        }
                X509V3_set_ctx_test(&ctx2);
-               X509V3_set_conf_lhash(&ctx2, extconf);
-               if (!X509V3_EXT_add_conf(extconf, &ctx2, extsect, NULL))
+               X509V3_set_nconf(&ctx2, extconf);
+               if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
                        {
                        BIO_printf(bio_err,
                                "Error Loading extension section %s\n",
@@ -593,7 +589,12 @@ bad:
                if ((x=X509_new()) == NULL) goto end;
                ci=x->cert_info;
 
-               if (!ASN1_INTEGER_set(X509_get_serialNumber(x),0)) goto end;
+               if (sno)
+                       {
+                       if (!X509_set_serialNumber(x, sno))
+                               goto end;
+                       }
+               else if (!ASN1_INTEGER_set(X509_get_serialNumber(x),0)) goto end;
                if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
                if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
 
@@ -605,12 +606,12 @@ bad:
                EVP_PKEY_free(pkey);
                }
        else
-               x=load_cert(bio_err,infile,informat);
+               x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
 
        if (x == NULL) goto end;
        if (CA_flag)
                {
-               xca=load_cert(bio_err,CAfile,CAformat);
+               xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
                if (xca == NULL) goto end;
                }
 
@@ -628,7 +629,7 @@ bad:
                if (outfile == NULL)
                        {
                        BIO_set_fp(out,stdout,BIO_NOCLOSE);
-#ifdef VMS
+#ifdef OPENSSL_SYS_VMS
                        {
                        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                        out = BIO_push(tmpbio, out);
@@ -732,12 +733,12 @@ bad:
                                        goto end;
                                        }
                                BIO_printf(STDout,"Modulus=");
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
                                if (pkey->type == EVP_PKEY_RSA)
                                        BN_print(STDout,pkey->pkey.rsa->n);
                                else
 #endif
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
                                if (pkey->type == EVP_PKEY_DSA)
                                        BN_print(STDout,pkey->pkey.dsa->pub_key);
                                else
@@ -860,13 +861,18 @@ bad:
                                if (Upkey == NULL)
                                        {
                                        Upkey=load_key(bio_err,
-                                               keyfile,keyformat, passin, e);
+                                               keyfile, keyformat, 0,
+                                               passin, e, "Private key");
                                        if (Upkey == NULL) goto end;
                                        }
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
                                if (Upkey->type == EVP_PKEY_DSA)
                                        digest=EVP_dss1();
 #endif
+#ifndef OPENSSL_NO_ECDSA
+                               if (Upkey->type == EVP_PKEY_EC)
+                                       digest=EVP_ecdsa();
+#endif
 
                                assert(need_rand);
                                if (!sign(x,Upkey,days,clrext,digest,
@@ -878,19 +884,24 @@ bad:
                                if (CAkeyfile != NULL)
                                        {
                                        CApkey=load_key(bio_err,
-                                               CAkeyfile,CAkeyformat, passin,
-                                               e);
+                                               CAkeyfile, CAkeyformat,
+                                               0, passin, e,
+                                               "CA Private Key");
                                        if (CApkey == NULL) goto end;
                                        }
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
                                if (CApkey->type == EVP_PKEY_DSA)
                                        digest=EVP_dss1();
 #endif
+#ifndef OPENSSL_NO_ECDSA
+                               if (CApkey->type == EVP_PKEY_EC)
+                                       digest = EVP_ecdsa();
+#endif
                                
                                assert(need_rand);
                                if (!x509_certify(ctx,CAfile,digest,x,xca,
                                        CApkey, CAserial,CA_createserial,days, clrext,
-                                       extconf, extsect))
+                                       extconf, extsect, sno))
                                        goto end;
                                }
                        else if (x509req == i)
@@ -906,14 +917,21 @@ bad:
                                else
                                        {
                                        pk=load_key(bio_err,
-                                               keyfile,FORMAT_PEM, passin, e);
+                                               keyfile, FORMAT_PEM, 0,
+                                               passin, e, "request key");
                                        if (pk == NULL) goto end;
                                        }
 
                                BIO_printf(bio_err,"Generating certificate request\n");
 
+#ifndef OPENSSL_NO_DSA
                                if (pk->type == EVP_PKEY_DSA)
                                        digest=EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+                               if (pk->type == EVP_PKEY_EC)
+                                       digest=EVP_ecdsa();
+#endif
 
                                rq=X509_to_X509_REQ(x,pk,digest);
                                EVP_PKEY_free(pk);
@@ -995,7 +1013,7 @@ end:
        if (need_rand)
                app_RAND_write_file(NULL, bio_err);
        OBJ_cleanup();
-       CONF_free(extconf);
+       NCONF_free(extconf);
        BIO_free_all(out);
        BIO_free_all(STDout);
        X509_STORE_free(ctx);
@@ -1005,32 +1023,23 @@ end:
        EVP_PKEY_free(Upkey);
        EVP_PKEY_free(CApkey);
        X509_REQ_free(rq);
+       ASN1_INTEGER_free(sno);
        sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
        sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
        if (passin) OPENSSL_free(passin);
+       apps_shutdown();
        EXIT(ret);
        }
 
-static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
-            X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
-            int days, int clrext, LHASH *conf, char *section)
+static ASN1_INTEGER *load_serial(char *CAfile, char *serialfile, int create)
        {
-       int ret=0;
-       BIO *io=NULL;
+       char *buf = NULL, *p;
        MS_STATIC char buf2[1024];
-       char *buf=NULL,*p;
-       BIGNUM *serial=NULL;
-       ASN1_INTEGER *bs=NULL,bs2;
-       X509_STORE_CTX xsc;
-       EVP_PKEY *upkey;
-
-       upkey = X509_get_pubkey(xca);
-       EVP_PKEY_copy_parameters(upkey,pkey);
-       EVP_PKEY_free(upkey);
+       ASN1_INTEGER *bs = NULL, *bs2 = NULL;
+       BIO *io = NULL;
+       BIGNUM *serial = NULL;
 
-       X509_STORE_CTX_init(&xsc,ctx,x,NULL);
-       buf=OPENSSL_malloc(EVP_PKEY_size(pkey)*2+
-               ((serialfile == NULL)
+       buf=OPENSSL_malloc( ((serialfile == NULL)
                        ?(strlen(CAfile)+strlen(POSTFIX)+1)
                        :(strlen(serialfile)))+1);
        if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
@@ -1096,20 +1105,55 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
 
        if (!BN_add_word(serial,1))
                { BIO_printf(bio_err,"add_word failure\n"); goto end; }
-       bs2.data=(unsigned char *)buf2;
-       bs2.length=BN_bn2bin(serial,bs2.data);
-
+       if (!(bs2 = BN_to_ASN1_INTEGER(serial, NULL)))
+               { BIO_printf(bio_err,"error converting bn 2 asn1_integer\n"); goto end; }
        if (BIO_write_filename(io,buf) <= 0)
                {
                BIO_printf(bio_err,"error attempting to write serial number file\n");
                perror(buf);
                goto end;
                }
-       i2a_ASN1_INTEGER(io,&bs2);
+       i2a_ASN1_INTEGER(io,bs2);
        BIO_puts(io,"\n");
+
        BIO_free(io);
+       if (buf) OPENSSL_free(buf);
+       ASN1_INTEGER_free(bs2);
+       BN_free(serial);
        io=NULL;
-       
+       return bs;
+
+       end:
+       if (buf) OPENSSL_free(buf);
+       BIO_free(io);
+       ASN1_INTEGER_free(bs);
+       BN_free(serial);
+       return NULL;
+
+       }
+
+static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
+            X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
+            int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
+       {
+       int ret=0;
+       ASN1_INTEGER *bs=NULL;
+       X509_STORE_CTX xsc;
+       EVP_PKEY *upkey;
+
+       upkey = X509_get_pubkey(xca);
+       EVP_PKEY_copy_parameters(upkey,pkey);
+       EVP_PKEY_free(upkey);
+
+       if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
+               {
+               BIO_printf(bio_err,"Error initialising X509 store\n");
+               goto end;
+               }
+       if (sno) bs = sno;
+       else if (!(bs = load_serial(CAfile, serialfile, create)))
+               goto end;
+
        if (!X509_STORE_add_cert(ctx,x)) goto end;
 
        /* NOTE: this certificate can/should be self signed, unless it was
@@ -1144,8 +1188,8 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                X509V3_CTX ctx2;
                X509_set_version(x,2); /* version 3 certificate */
                 X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
-                X509V3_set_conf_lhash(&ctx2, conf);
-                if (!X509V3_EXT_add_conf(conf, &ctx2, section, x)) goto end;
+                X509V3_set_nconf(&ctx2, conf);
+                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
                }
 
        if (!X509_sign(x,pkey,digest)) goto end;
@@ -1154,10 +1198,7 @@ end:
        X509_STORE_CTX_cleanup(&xsc);
        if (!ret)
                ERR_print_errors(bio_err);
-       if (buf != NULL) OPENSSL_free(buf);
-       if (bs != NULL) ASN1_INTEGER_free(bs);
-       if (io != NULL) BIO_free(io);
-       if (serial != NULL) BN_free(serial);
+       if (!sno) ASN1_INTEGER_free(bs);
        return ret;
        }
 
@@ -1194,7 +1235,7 @@ static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
 
 /* self sign */
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 
-                                               LHASH *conf, char *section)
+                                               CONF *conf, char *section)
        {
 
        EVP_PKEY *pktmp;
@@ -1224,8 +1265,8 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *dig
                X509V3_CTX ctx;
                X509_set_version(x,2); /* version 3 certificate */
                 X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
-                X509V3_set_conf_lhash(&ctx, conf);
-                if (!X509V3_EXT_add_conf(conf, &ctx, section, x)) goto err;
+                X509V3_set_nconf(&ctx, conf);
+                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
                }
        if (!X509_sign(x,pkey,digest)) goto err;
        return 1;
@@ -1250,6 +1291,3 @@ static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
                }
        return 1;
 }
-
-
-