Use X509_get_serialNumber() instead of accessing internals in x509.c
[openssl.git] / apps / x509.c
index 391bb3eef9504521a8a567ed4a2323bf9d797861..4869b14025d467c38eca805b8faba4eaa95d1cad 100644 (file)
@@ -73,7 +73,8 @@
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
 #include <openssl/pem.h>
-#include <openssl/engine.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
 
 #undef PROG
 #define PROG x509_main
@@ -93,7 +94,9 @@ static char *x509_usage[]={
 " -out arg        - output file - default stdout\n",
 " -passin arg     - private key password source\n",
 " -serial         - print serial number value\n",
-" -hash           - print hash value\n",
+" -subject_hash   - print subject hash value\n",
+" -issuer_hash    - print issuer hash value\n",
+" -hash           - synonym for -subject_hash\n",
 " -subject        - print subject DN\n",
 " -issuer         - print issuer DN\n",
 " -email          - print email address(es)\n",
@@ -123,7 +126,7 @@ 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",
@@ -132,17 +135,19 @@ static char *x509_usage[]={
 " -extensions     - section from config file with X509V3 extensions to add\n",
 " -clrext         - delete extensions before signing and input certificate\n",
 " -nameopt arg    - various certificate name options\n",
+#ifndef OPENSSL_NO_ENGINE
 " -engine e       - use engine e, possibly a hardware device.\n",
+#endif
 " -certopt arg    - various certificate text options\n",
 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;
@@ -166,8 +171,8 @@ int MAIN(int argc, char **argv)
        char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
        char *CAkeyfile=NULL,*CAserial=NULL;
        char *alias=NULL;
-       int text=0,serial=0,hash=0,subject=0,issuer=0,startdate=0,enddate=0;
-       int ocspid=0;
+       int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
+       int subject_hash=0,issuer_hash=0,ocspid=0;
        int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
        int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
        int C=0;
@@ -179,12 +184,14 @@ 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;
        unsigned long nmflag = 0, certflag = 0;
+#ifndef OPENSSL_NO_ENGINE
        char *engine=NULL;
+#endif
 
        reqfile=0;
 
@@ -192,6 +199,9 @@ 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 OPENSSL_SYS_VMS
        {
@@ -243,7 +253,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)
                        {
@@ -352,17 +362,13 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        if (!set_name_ex(&nmflag, *(++argv))) goto bad;
                        }
-               else if (strcmp(*argv,"-setalias") == 0)
-                       {
-                       if (--argc < 1) goto bad;
-                       alias= *(++argv);
-                       trustout = 1;
-                       }
+#ifndef OPENSSL_NO_ENGINE
                else if (strcmp(*argv,"-engine") == 0)
                        {
                        if (--argc < 1) goto bad;
                        engine= *(++argv);
                        }
+#endif
                else if (strcmp(*argv,"-C") == 0)
                        C= ++num;
                else if (strcmp(*argv,"-email") == 0)
@@ -377,8 +383,11 @@ int MAIN(int argc, char **argv)
                        x509req= ++num;
                else if (strcmp(*argv,"-text") == 0)
                        text= ++num;
-               else if (strcmp(*argv,"-hash") == 0)
-                       hash= ++num;
+               else if (strcmp(*argv,"-hash") == 0
+                       || strcmp(*argv,"-subject_hash") == 0)
+                       subject_hash= ++num;
+               else if (strcmp(*argv,"-issuer_hash") == 0)
+                       issuer_hash= ++num;
                else if (strcmp(*argv,"-subject") == 0)
                        subject= ++num;
                else if (strcmp(*argv,"-issuer") == 0)
@@ -448,23 +457,9 @@ bad:
                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);
-               }
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
 
        if (need_rand)
                app_RAND_load_file(NULL, bio_err, 0);
@@ -493,9 +488,10 @@ bad:
 
        if (extfile)
                {
-               long errorline;
+               long errorline = -1;
                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,
@@ -509,7 +505,7 @@ bad:
                        }
                if (!extsect)
                        {
-                       extsect = CONF_get_string(extconf, "default", "extensions");
+                       extsect = NCONF_get_string(extconf, "default", "extensions");
                        if (!extsect)
                                {
                                ERR_clear_error();
@@ -517,8 +513,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",
@@ -619,12 +615,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;
                }
 
@@ -699,7 +695,8 @@ bad:
                        else if (serial == i)
                                {
                                BIO_printf(STDout,"serial=");
-                               i2a_ASN1_INTEGER(STDout,x->cert_info->serialNumber);
+                               i2a_ASN1_INTEGER(STDout,
+                                       X509_get_serialNumber(x));
                                BIO_printf(STDout,"\n");
                                }
                        else if (email == i) 
@@ -718,10 +715,14 @@ bad:
                                if (alstr) BIO_printf(STDout,"%s\n", alstr);
                                else BIO_puts(STDout,"<No Alias>\n");
                                }
-                       else if (hash == i)
+                       else if (subject_hash == i)
                                {
                                BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
                                }
+                       else if (issuer_hash == i)
+                               {
+                               BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
+                               }
                        else if (pprint == i)
                                {
                                X509_PURPOSE *ptmp;
@@ -783,10 +784,11 @@ bad:
                                int y,z;
 
                                X509_NAME_oneline(X509_get_subject_name(x),
-                                       buf,256);
+                                       buf,sizeof buf);
                                BIO_printf(STDout,"/* subject:%s */\n",buf);
                                m=X509_NAME_oneline(
-                                       X509_get_issuer_name(x),buf,256);
+                                       X509_get_issuer_name(x),buf,
+                                       sizeof buf);
                                BIO_printf(STDout,"/* issuer :%s */\n",buf);
 
                                z=i2d_X509(x,NULL);
@@ -874,13 +876,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 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,
@@ -892,14 +899,19 @@ 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 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,
@@ -920,14 +932,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);
@@ -1009,7 +1028,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);
@@ -1023,113 +1042,53 @@ end:
        sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
        sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
        if (passin) OPENSSL_free(passin);
-       EXIT(ret);
+       apps_shutdown();
+       OPENSSL_EXIT(ret);
        }
 
-static ASN1_INTEGER *load_serial(char *CAfile, char *serialfile, int create)
+static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
        {
        char *buf = NULL, *p;
-       MS_STATIC char buf2[1024];
-       ASN1_INTEGER *bs = NULL, *bs2 = NULL;
-       BIO *io = NULL;
+       ASN1_INTEGER *bs = NULL;
        BIGNUM *serial = NULL;
+       size_t len;
 
-       buf=OPENSSL_malloc( ((serialfile == NULL)
-                       ?(strlen(CAfile)+strlen(POSTFIX)+1)
-                       :(strlen(serialfile)))+1);
+       len = ((serialfile == NULL)
+               ?(strlen(CAfile)+strlen(POSTFIX)+1)
+               :(strlen(serialfile)))+1;
+       buf=OPENSSL_malloc(len);
        if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
        if (serialfile == NULL)
                {
-               strcpy(buf,CAfile);
+               BUF_strlcpy(buf,CAfile,len);
                for (p=buf; *p; p++)
                        if (*p == '.')
                                {
                                *p='\0';
                                break;
                                }
-               strcat(buf,POSTFIX);
+               BUF_strlcat(buf,POSTFIX,len);
                }
        else
-               strcpy(buf,serialfile);
-       serial=BN_new();
-       bs=ASN1_INTEGER_new();
-       if ((serial == NULL) || (bs == NULL))
-               {
-               ERR_print_errors(bio_err);
-               goto end;
-               }
+               BUF_strlcpy(buf,serialfile,len);
 
-       io=BIO_new(BIO_s_file());
-       if (io == NULL)
-               {
-               ERR_print_errors(bio_err);
-               goto end;
-               }
-       
-       if (BIO_read_filename(io,buf) <= 0)
-               {
-               if (!create)
-                       {
-                       perror(buf);
-                       goto end;
-                       }
-               else
-                       {
-                       ASN1_INTEGER_set(bs,1);
-                       BN_one(serial);
-                       }
-               }
-       else 
-               {
-               if (!a2i_ASN1_INTEGER(io,bs,buf2,1024))
-                       {
-                       BIO_printf(bio_err,"unable to load serial number from %s\n",buf);
-                       ERR_print_errors(bio_err);
-                       goto end;
-                       }
-               else
-                       {
-                       serial=BN_bin2bn(bs->data,bs->length,serial);
-                       if (serial == NULL)
-                               {
-                               BIO_printf(bio_err,"error converting bin 2 bn");
-                               goto end;
-                               }
-                       }
-               }
+       serial = load_serial(buf, create, NULL);
+       if (serial == NULL) goto end;
 
        if (!BN_add_word(serial,1))
                { BIO_printf(bio_err,"add_word failure\n"); goto end; }
-       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);
-       BIO_puts(io,"\n");
 
-       BIO_free(io);
-       if (buf) OPENSSL_free(buf);
-       ASN1_INTEGER_free(bs2);
-       BN_free(serial);
-       io=NULL;
-       return bs;
+       if (!save_serial(buf, NULL, serial, &bs)) goto end;
 
      end:
+ end:
        if (buf) OPENSSL_free(buf);
-       BIO_free(io);
-       ASN1_INTEGER_free(bs);
        BN_free(serial);
-       return NULL;
-
+       return bs;
        }
 
 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, ASN1_INTEGER *sno)
+            int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
        {
        int ret=0;
        ASN1_INTEGER *bs=NULL;
@@ -1140,12 +1099,16 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
        EVP_PKEY_copy_parameters(upkey,pkey);
        EVP_PKEY_free(upkey);
 
-       X509_STORE_CTX_init(&xsc,ctx,x,NULL);
+       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)))
+       else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
                goto end;
 
-       if (!X509_STORE_add_cert(ctx,x)) goto end;
+/*     if (!X509_STORE_add_cert(ctx,x)) goto end;*/
 
        /* NOTE: this certificate can/should be self signed, unless it was
         * a certificate request in which case it is not. */
@@ -1179,8 +1142,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;
@@ -1226,7 +1189,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;
@@ -1256,8 +1219,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;