9d2a0c8d2ac4ecb005de59a02bef529025b2337f
[openssl.git] / apps / x509.c
1 /* apps/x509.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #ifdef NO_STDIO
63 #define APPS_WIN16
64 #endif
65 #include "apps.h"
66 #include <openssl/bio.h>
67 #include <openssl/asn1.h>
68 #include <openssl/err.h>
69 #include <openssl/bn.h>
70 #include <openssl/evp.h>
71 #include <openssl/x509.h>
72 #include <openssl/x509v3.h>
73 #include <openssl/objects.h>
74 #include <openssl/pem.h>
75
76 #undef PROG
77 #define PROG x509_main
78
79 #undef POSTFIX
80 #define POSTFIX ".srl"
81 #define DEF_DAYS        30
82
83 #define CERT_HDR        "certificate"
84
85 static char *x509_usage[]={
86 "usage: x509 args\n",
87 " -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
88 " -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
89 " -keyform arg    - private key format - default PEM\n",
90 " -CAform arg     - CA format - default PEM\n",
91 " -CAkeyform arg  - CA key format - default PEM\n",
92 " -in arg         - input file - default stdin\n",
93 " -out arg        - output file - default stdout\n",
94 " -serial         - print serial number value\n",
95 " -hash           - print hash value\n",
96 " -subject        - print subject DN\n",
97 " -issuer         - print issuer DN\n",
98 " -startdate      - notBefore field\n",
99 " -enddate        - notAfter field\n",
100 " -purpose        - print out certificate purposes\n",
101 " -dates          - both Before and After dates\n",
102 " -modulus        - print the RSA key modulus\n",
103 " -fingerprint    - print the certificate fingerprint\n",
104 " -noout          - no certificate output\n",
105
106 " -days arg       - How long till expiry of a signed certificate - def 30 days\n",
107 " -signkey arg    - self sign cert with arg\n",
108 " -x509toreq      - output a certification request object\n",
109 " -req            - input is a certificate request, sign and output.\n",
110 " -CA arg         - set the CA certificate, must be PEM format.\n",
111 " -CAkey arg      - set the CA key, must be PEM format\n",
112 "                   missing, it is asssumed to be in the CA file.\n",
113 " -CAcreateserial - create serial number file if it does not exist\n",
114 " -CAserial       - serial file\n",
115 " -text           - print the certificate in text form\n",
116 " -C              - print out C code forms\n",
117 " -md2/-md5/-sha1/-mdc2 - digest to do an RSA sign with\n",
118 " -extfile        - configuration file with X509V3 extensions to add\n",
119 " -extensions     - section from config file with X509V3 extensions to add\n",
120 NULL
121 };
122
123 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
124 static EVP_PKEY *load_key(char *file, int format);
125 static X509 *load_cert(char *file, int format);
126 static int sign (X509 *x, EVP_PKEY *pkey,int days,const EVP_MD *digest,
127                                                 LHASH *conf, char *section);
128 static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
129                          X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
130                          int create,int days, LHASH *conf, char *section);
131 static int efunc(X509_PURPOSE *pt, void *arg);
132 static int reqfile=0;
133
134 typedef struct {
135 BIO *bio;
136 X509 *cert;
137 } X509_PPRINT;
138
139 int MAIN(int argc, char **argv)
140         {
141         int ret=1;
142         X509_REQ *req=NULL;
143         X509 *x=NULL,*xca=NULL;
144         EVP_PKEY *Upkey=NULL,*CApkey=NULL;
145         int i,num,badops=0;
146         BIO *out=NULL;
147         BIO *STDout=NULL;
148         int informat,outformat,keyformat,CAformat,CAkeyformat;
149         char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
150         char *CAkeyfile=NULL,*CAserial=NULL;
151         int text=0,serial=0,hash=0,subject=0,issuer=0,startdate=0,enddate=0;
152         int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0;
153         int C=0;
154         int x509req=0,days=DEF_DAYS,modulus=0;
155         int pprint = 0;
156         char **pp;
157         X509_STORE *ctx=NULL;
158         X509_REQ *rq=NULL;
159         int fingerprint=0;
160         char buf[256];
161         const EVP_MD *md_alg,*digest=EVP_md5();
162         LHASH *extconf = NULL;
163         char *extsect = NULL, *extfile = NULL;
164
165         reqfile=0;
166
167         apps_startup();
168
169         if (bio_err == NULL)
170                 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
171         STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
172
173         informat=FORMAT_PEM;
174         outformat=FORMAT_PEM;
175         keyformat=FORMAT_PEM;
176         CAformat=FORMAT_PEM;
177         CAkeyformat=FORMAT_PEM;
178
179         ctx=X509_STORE_new();
180         if (ctx == NULL) goto end;
181         X509_STORE_set_verify_cb_func(ctx,callb);
182
183         argc--;
184         argv++;
185         num=0;
186         while (argc >= 1)
187                 {
188                 if      (strcmp(*argv,"-inform") == 0)
189                         {
190                         if (--argc < 1) goto bad;
191                         informat=str2fmt(*(++argv));
192                         }
193                 else if (strcmp(*argv,"-outform") == 0)
194                         {
195                         if (--argc < 1) goto bad;
196                         outformat=str2fmt(*(++argv));
197                         }
198                 else if (strcmp(*argv,"-keyform") == 0)
199                         {
200                         if (--argc < 1) goto bad;
201                         keyformat=str2fmt(*(++argv));
202                         }
203                 else if (strcmp(*argv,"-req") == 0)
204                         reqfile=1;
205                 else if (strcmp(*argv,"-CAform") == 0)
206                         {
207                         if (--argc < 1) goto bad;
208                         CAformat=str2fmt(*(++argv));
209                         }
210                 else if (strcmp(*argv,"-CAkeyform") == 0)
211                         {
212                         if (--argc < 1) goto bad;
213                         CAformat=str2fmt(*(++argv));
214                         }
215                 else if (strcmp(*argv,"-days") == 0)
216                         {
217                         if (--argc < 1) goto bad;
218                         days=atoi(*(++argv));
219                         if (days == 0)
220                                 {
221                                 BIO_printf(STDout,"bad number of days\n");
222                                 goto bad;
223                                 }
224                         }
225                 else if (strcmp(*argv,"-extfile") == 0)
226                         {
227                         if (--argc < 1) goto bad;
228                         extfile= *(++argv);
229                         }
230                 else if (strcmp(*argv,"-extensions") == 0)
231                         {
232                         if (--argc < 1) goto bad;
233                         extsect= *(++argv);
234                         }
235                 else if (strcmp(*argv,"-in") == 0)
236                         {
237                         if (--argc < 1) goto bad;
238                         infile= *(++argv);
239                         }
240                 else if (strcmp(*argv,"-out") == 0)
241                         {
242                         if (--argc < 1) goto bad;
243                         outfile= *(++argv);
244                         }
245                 else if (strcmp(*argv,"-signkey") == 0)
246                         {
247                         if (--argc < 1) goto bad;
248                         keyfile= *(++argv);
249                         sign_flag= ++num;
250                         }
251                 else if (strcmp(*argv,"-CA") == 0)
252                         {
253                         if (--argc < 1) goto bad;
254                         CAfile= *(++argv);
255                         CA_flag= ++num;
256                         }
257                 else if (strcmp(*argv,"-CAkey") == 0)
258                         {
259                         if (--argc < 1) goto bad;
260                         CAkeyfile= *(++argv);
261                         }
262                 else if (strcmp(*argv,"-CAserial") == 0)
263                         {
264                         if (--argc < 1) goto bad;
265                         CAserial= *(++argv);
266                         }
267                 else if (strcmp(*argv,"-C") == 0)
268                         C= ++num;
269                 else if (strcmp(*argv,"-serial") == 0)
270                         serial= ++num;
271                 else if (strcmp(*argv,"-modulus") == 0)
272                         modulus= ++num;
273                 else if (strcmp(*argv,"-x509toreq") == 0)
274                         x509req= ++num;
275                 else if (strcmp(*argv,"-text") == 0)
276                         text= ++num;
277                 else if (strcmp(*argv,"-hash") == 0)
278                         hash= ++num;
279                 else if (strcmp(*argv,"-subject") == 0)
280                         subject= ++num;
281                 else if (strcmp(*argv,"-issuer") == 0)
282                         issuer= ++num;
283                 else if (strcmp(*argv,"-fingerprint") == 0)
284                         fingerprint= ++num;
285                 else if (strcmp(*argv,"-dates") == 0)
286                         {
287                         startdate= ++num;
288                         enddate= ++num;
289                         }
290                 else if (strcmp(*argv,"-purpose") == 0)
291                         pprint= ++num;
292                 else if (strcmp(*argv,"-startdate") == 0)
293                         startdate= ++num;
294                 else if (strcmp(*argv,"-enddate") == 0)
295                         enddate= ++num;
296                 else if (strcmp(*argv,"-noout") == 0)
297                         noout= ++num;
298                 else if (strcmp(*argv,"-CAcreateserial") == 0)
299                         CA_createserial= ++num;
300                 else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
301                         {
302                         /* ok */
303                         digest=md_alg;
304                         }
305                 else
306                         {
307                         BIO_printf(bio_err,"unknown option %s\n",*argv);
308                         badops=1;
309                         break;
310                         }
311                 argc--;
312                 argv++;
313                 }
314
315         if (badops)
316                 {
317 bad:
318                 for (pp=x509_usage; (*pp != NULL); pp++)
319                         BIO_printf(bio_err,*pp);
320                 goto end;
321                 }
322
323         ERR_load_crypto_strings();
324         X509V3_add_standard_extensions();
325         X509_PURPOSE_add_standard();
326
327         if (!X509_STORE_set_default_paths(ctx))
328                 {
329                 ERR_print_errors(bio_err);
330                 goto end;
331                 }
332
333         if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
334                 { CAkeyfile=CAfile; }
335         else if ((CA_flag) && (CAkeyfile == NULL))
336                 {
337                 BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
338                 goto end;
339                 }
340
341         if (extfile) {
342                 long errorline;
343                 X509V3_CTX ctx2;
344                 if (!(extconf=CONF_load(NULL,extfile,&errorline))) {
345                         if (errorline <= 0)
346                                 BIO_printf(bio_err,
347                                         "error loading the config file '%s'\n",
348                                                                 extfile);
349                         else
350                                 BIO_printf(bio_err,
351                                        "error on line %ld of config file '%s'\n"
352                                                         ,errorline,extfile);
353                         goto end;
354                 }
355                 if(!extsect && !(extsect = CONF_get_string(extconf, "default",
356                                          "extensions"))) extsect = "default";
357                 X509V3_set_ctx_test(&ctx2);
358                 X509V3_set_conf_lhash(&ctx2, extconf);
359                 if(!X509V3_EXT_add_conf(extconf, &ctx2, extsect, NULL)) {
360                         BIO_printf(bio_err,
361                                 "Error Loading extension section %s\n",
362                                                                  extsect);
363                         ERR_print_errors(bio_err);
364                         goto end;
365                 }
366         } 
367
368
369         if (reqfile)
370                 {
371                 EVP_PKEY *pkey;
372                 X509_CINF *ci;
373                 BIO *in;
374
375                 if (!sign_flag && !CA_flag)
376                         {
377                         BIO_printf(bio_err,"We need a private key to sign with\n");
378                         goto end;
379                         }
380                 in=BIO_new(BIO_s_file());
381                 if (in == NULL)
382                         {
383                         ERR_print_errors(bio_err);
384                         goto end;
385                         }
386
387                 if (infile == NULL)
388                         BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
389                 else
390                         {
391                         if (BIO_read_filename(in,infile) <= 0)
392                                 {
393                                 perror(infile);
394                                 goto end;
395                                 }
396                         }
397                 req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
398                 BIO_free(in);
399
400                 if (req == NULL) { perror(infile); goto end; }
401
402                 if (    (req->req_info == NULL) ||
403                         (req->req_info->pubkey == NULL) ||
404                         (req->req_info->pubkey->public_key == NULL) ||
405                         (req->req_info->pubkey->public_key->data == NULL))
406                         {
407                         BIO_printf(bio_err,"The certificate request appears to corrupted\n");
408                         BIO_printf(bio_err,"It does not contain a public key\n");
409                         goto end;
410                         }
411                 if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
412                         {
413                         BIO_printf(bio_err,"error unpacking public key\n");
414                         goto end;
415                         }
416                 i=X509_REQ_verify(req,pkey);
417                 EVP_PKEY_free(pkey);
418                 if (i < 0)
419                         {
420                         BIO_printf(bio_err,"Signature verification error\n");
421                         ERR_print_errors(bio_err);
422                         goto end;
423                         }
424                 if (i == 0)
425                         {
426                         BIO_printf(bio_err,"Signature did not match the certificate request\n");
427                         goto end;
428                         }
429                 else
430                         BIO_printf(bio_err,"Signature ok\n");
431                 
432                 X509_NAME_oneline(req->req_info->subject,buf,256);
433                 BIO_printf(bio_err,"subject=%s\n",buf);
434
435                 if ((x=X509_new()) == NULL) goto end;
436                 ci=x->cert_info;
437
438                 if (!ASN1_INTEGER_set(X509_get_serialNumber(x),0)) goto end;
439                 if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
440                 if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
441
442                 X509_gmtime_adj(X509_get_notBefore(x),0);
443                 X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
444
445 #if 0
446                 X509_PUBKEY_free(ci->key);
447                 ci->key=req->req_info->pubkey;
448                 req->req_info->pubkey=NULL;
449 #else
450                 pkey = X509_REQ_get_pubkey(req);
451                 X509_set_pubkey(x,pkey);
452                 EVP_PKEY_free(pkey);
453 #endif
454                 }
455         else
456                 x=load_cert(infile,informat);
457
458         if (x == NULL) goto end;
459         if (CA_flag)
460                 {
461                 xca=load_cert(CAfile,CAformat);
462                 if (xca == NULL) goto end;
463                 }
464
465         if (!noout || text)
466                 {
467                 OBJ_create("2.99999.3",
468                         "SET.ex3","SET x509v3 extension 3");
469
470                 out=BIO_new(BIO_s_file());
471                 if (out == NULL)
472                         {
473                         ERR_print_errors(bio_err);
474                         goto end;
475                         }
476                 if (outfile == NULL)
477                         BIO_set_fp(out,stdout,BIO_NOCLOSE);
478                 else
479                         {
480                         if (BIO_write_filename(out,outfile) <= 0)
481                                 {
482                                 perror(outfile);
483                                 goto end;
484                                 }
485                         }
486                 }
487
488         if (num)
489                 {
490                 for (i=1; i<=num; i++)
491                         {
492                         if (issuer == i)
493                                 {
494                                 X509_NAME_oneline(X509_get_issuer_name(x),
495                                         buf,256);
496                                 BIO_printf(STDout,"issuer= %s\n",buf);
497                                 }
498                         else if (subject == i) 
499                                 {
500                                 X509_NAME_oneline(X509_get_subject_name(x),
501                                         buf,256);
502                                 BIO_printf(STDout,"subject=%s\n",buf);
503                                 }
504                         else if (serial == i)
505                                 {
506                                 BIO_printf(STDout,"serial=");
507                                 i2a_ASN1_INTEGER(STDout,x->cert_info->serialNumber);
508                                 BIO_printf(STDout,"\n");
509                                 }
510                         else if (hash == i)
511                                 {
512                                 BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
513                                 }
514                         else if (pprint == i)
515                                 {
516                                 X509_PPRINT ptmp;
517                                 ptmp.bio = STDout;
518                                 ptmp.cert = x;
519                                 BIO_printf(STDout, "Certificate purposes:\n");
520                                 X509_PURPOSE_enum(efunc, &ptmp);
521                                 }
522                         else
523                                 if (modulus == i)
524                                 {
525                                 EVP_PKEY *pkey;
526
527                                 pkey=X509_get_pubkey(x);
528                                 if (pkey == NULL)
529                                         {
530                                         BIO_printf(bio_err,"Modulus=unavailable\n");
531                                         ERR_print_errors(bio_err);
532                                         goto end;
533                                         }
534                                 BIO_printf(STDout,"Modulus=");
535 #ifndef NO_RSA
536                                 if (pkey->type == EVP_PKEY_RSA)
537                                         BN_print(STDout,pkey->pkey.rsa->n);
538                                 else
539 #endif
540 #ifndef NO_DSA
541                                 if (pkey->type == EVP_PKEY_DSA)
542                                         BN_print(STDout,pkey->pkey.dsa->pub_key);
543                                 else
544 #endif
545                                         BIO_printf(STDout,"Wrong Algorithm type");
546                                 BIO_printf(STDout,"\n");
547                                 EVP_PKEY_free(pkey);
548                                 }
549                         else
550                                 if (C == i)
551                                 {
552                                 unsigned char *d;
553                                 char *m;
554                                 int y,z;
555
556                                 X509_NAME_oneline(X509_get_subject_name(x),
557                                         buf,256);
558                                 BIO_printf(STDout,"/* subject:%s */\n",buf);
559                                 m=X509_NAME_oneline(
560                                         X509_get_issuer_name(x),buf,256);
561                                 BIO_printf(STDout,"/* issuer :%s */\n",buf);
562
563                                 z=i2d_X509(x,NULL);
564                                 m=Malloc(z);
565
566                                 d=(unsigned char *)m;
567                                 z=i2d_X509_NAME(X509_get_subject_name(x),&d);
568                                 BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
569                                 d=(unsigned char *)m;
570                                 for (y=0; y<z; y++)
571                                         {
572                                         BIO_printf(STDout,"0x%02X,",d[y]);
573                                         if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
574                                         }
575                                 if (y%16 != 0) BIO_printf(STDout,"\n");
576                                 BIO_printf(STDout,"};\n");
577
578                                 z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
579                                 BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
580                                 d=(unsigned char *)m;
581                                 for (y=0; y<z; y++)
582                                         {
583                                         BIO_printf(STDout,"0x%02X,",d[y]);
584                                         if ((y & 0x0f) == 0x0f)
585                                                 BIO_printf(STDout,"\n");
586                                         }
587                                 if (y%16 != 0) BIO_printf(STDout,"\n");
588                                 BIO_printf(STDout,"};\n");
589
590                                 z=i2d_X509(x,&d);
591                                 BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
592                                 d=(unsigned char *)m;
593                                 for (y=0; y<z; y++)
594                                         {
595                                         BIO_printf(STDout,"0x%02X,",d[y]);
596                                         if ((y & 0x0f) == 0x0f)
597                                                 BIO_printf(STDout,"\n");
598                                         }
599                                 if (y%16 != 0) BIO_printf(STDout,"\n");
600                                 BIO_printf(STDout,"};\n");
601
602                                 Free(m);
603                                 }
604                         else if (text == i)
605                                 {
606                                 X509_print(out,x);
607                                 }
608                         else if (startdate == i)
609                                 {
610                                 BIO_puts(STDout,"notBefore=");
611                                 ASN1_TIME_print(STDout,X509_get_notBefore(x));
612                                 BIO_puts(STDout,"\n");
613                                 }
614                         else if (enddate == i)
615                                 {
616                                 BIO_puts(STDout,"notAfter=");
617                                 ASN1_TIME_print(STDout,X509_get_notAfter(x));
618                                 BIO_puts(STDout,"\n");
619                                 }
620                         else if (fingerprint == i)
621                                 {
622                                 int j;
623                                 unsigned int n;
624                                 unsigned char md[EVP_MAX_MD_SIZE];
625
626                                 if (!X509_digest(x,EVP_md5(),md,&n))
627                                         {
628                                         BIO_printf(bio_err,"out of memory\n");
629                                         goto end;
630                                         }
631                                 BIO_printf(STDout,"MD5 Fingerprint=");
632                                 for (j=0; j<(int)n; j++)
633                                         {
634                                         BIO_printf(STDout,"%02X%c",md[j],
635                                                 (j+1 == (int)n)
636                                                 ?'\n':':');
637                                         }
638                                 }
639
640                         /* should be in the library */
641                         else if ((sign_flag == i) && (x509req == 0))
642                                 {
643                                 BIO_printf(bio_err,"Getting Private key\n");
644                                 if (Upkey == NULL)
645                                         {
646                                         Upkey=load_key(keyfile,keyformat);
647                                         if (Upkey == NULL) goto end;
648                                         }
649 #ifndef NO_DSA
650                                 if (Upkey->type == EVP_PKEY_DSA)
651                                         digest=EVP_dss1();
652 #endif
653
654                                 if (!sign(x,Upkey,days,digest,
655                                                  extconf, extsect)) goto end;
656                                 }
657                         else if (CA_flag == i)
658                                 {
659                                 BIO_printf(bio_err,"Getting CA Private Key\n");
660                                 if (CAkeyfile != NULL)
661                                         {
662                                         CApkey=load_key(CAkeyfile,CAkeyformat);
663                                         if (CApkey == NULL) goto end;
664                                         }
665 #ifndef NO_DSA
666                                 if (CApkey->type == EVP_PKEY_DSA)
667                                         digest=EVP_dss1();
668 #endif
669                                 
670                                 if (!x509_certify(ctx,CAfile,digest,x,xca,
671                                         CApkey, CAserial,CA_createserial,days,
672                                         extconf, extsect))
673                                         goto end;
674                                 }
675                         else if (x509req == i)
676                                 {
677                                 EVP_PKEY *pk;
678
679                                 BIO_printf(bio_err,"Getting request Private Key\n");
680                                 if (keyfile == NULL)
681                                         {
682                                         BIO_printf(bio_err,"no request key file specified\n");
683                                         goto end;
684                                         }
685                                 else
686                                         {
687                                         pk=load_key(keyfile,FORMAT_PEM);
688                                         if (pk == NULL) goto end;
689                                         }
690
691                                 BIO_printf(bio_err,"Generating certificate request\n");
692
693                                 rq=X509_to_X509_REQ(x,pk,EVP_md5());
694                                 EVP_PKEY_free(pk);
695                                 if (rq == NULL)
696                                         {
697                                         ERR_print_errors(bio_err);
698                                         goto end;
699                                         }
700                                 if (!noout)
701                                         {
702                                         X509_REQ_print(out,rq);
703                                         PEM_write_bio_X509_REQ(out,rq);
704                                         }
705                                 noout=1;
706                                 }
707                         }
708                 }
709
710         if (noout)
711                 {
712                 ret=0;
713                 goto end;
714                 }
715
716         if      (outformat == FORMAT_ASN1)
717                 i=i2d_X509_bio(out,x);
718         else if (outformat == FORMAT_PEM)
719                 i=PEM_write_bio_X509(out,x);
720         else if (outformat == FORMAT_NETSCAPE)
721                 {
722                 ASN1_HEADER ah;
723                 ASN1_OCTET_STRING os;
724
725                 os.data=(unsigned char *)CERT_HDR;
726                 os.length=strlen(CERT_HDR);
727                 ah.header= &os;
728                 ah.data=(char *)x;
729                 ah.meth=X509_asn1_meth();
730
731                 /* no macro for this one yet */
732                 i=ASN1_i2d_bio(i2d_ASN1_HEADER,out,(unsigned char *)&ah);
733                 }
734         else    {
735                 BIO_printf(bio_err,"bad output format specified for outfile\n");
736                 goto end;
737                 }
738         if (!i) {
739                 BIO_printf(bio_err,"unable to write certificate\n");
740                 ERR_print_errors(bio_err);
741                 goto end;
742                 }
743         ret=0;
744 end:
745         OBJ_cleanup();
746         CONF_free(extconf);
747         BIO_free(out);
748         BIO_free(STDout);
749         X509_STORE_free(ctx);
750         X509_REQ_free(req);
751         X509_free(x);
752         X509_free(xca);
753         EVP_PKEY_free(Upkey);
754         EVP_PKEY_free(CApkey);
755         X509_REQ_free(rq);
756         X509V3_EXT_cleanup();
757         X509_PURPOSE_cleanup();
758         EXIT(ret);
759         }
760
761 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
762              X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
763              int days, LHASH *conf, char *section)
764         {
765         int ret=0;
766         BIO *io=NULL;
767         MS_STATIC char buf2[1024];
768         char *buf=NULL,*p;
769         BIGNUM *serial=NULL;
770         ASN1_INTEGER *bs=NULL,bs2;
771         X509_STORE_CTX xsc;
772         EVP_PKEY *upkey;
773
774         upkey = X509_get_pubkey(xca);
775         EVP_PKEY_copy_parameters(upkey,pkey);
776         EVP_PKEY_free(upkey);
777
778         X509_STORE_CTX_init(&xsc,ctx,x,NULL);
779         buf=(char *)Malloc(EVP_PKEY_size(pkey)*2+
780                 ((serialfile == NULL)
781                         ?(strlen(CAfile)+strlen(POSTFIX)+1)
782                         :(strlen(serialfile)))+1);
783         if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
784         if (serialfile == NULL)
785                 {
786                 strcpy(buf,CAfile);
787                 for (p=buf; *p; p++)
788                         if (*p == '.')
789                                 {
790                                 *p='\0';
791                                 break;
792                                 }
793                 strcat(buf,POSTFIX);
794                 }
795         else
796                 strcpy(buf,serialfile);
797         serial=BN_new();
798         bs=ASN1_INTEGER_new();
799         if ((serial == NULL) || (bs == NULL))
800                 {
801                 ERR_print_errors(bio_err);
802                 goto end;
803                 }
804
805         io=BIO_new(BIO_s_file());
806         if (io == NULL)
807                 {
808                 ERR_print_errors(bio_err);
809                 goto end;
810                 }
811         
812         if (BIO_read_filename(io,buf) <= 0)
813                 {
814                 if (!create)
815                         {
816                         perror(buf);
817                         goto end;
818                         }
819                 else
820                         {
821                         ASN1_INTEGER_set(bs,0);
822                         BN_zero(serial);
823                         }
824                 }
825         else 
826                 {
827                 if (!a2i_ASN1_INTEGER(io,bs,buf2,1024))
828                         {
829                         BIO_printf(bio_err,"unable to load serial number from %s\n",buf);
830                         ERR_print_errors(bio_err);
831                         goto end;
832                         }
833                 else
834                         {
835                         serial=BN_bin2bn(bs->data,bs->length,serial);
836                         if (serial == NULL)
837                                 {
838                                 BIO_printf(bio_err,"error converting bin 2 bn");
839                                 goto end;
840                                 }
841                         }
842                 }
843
844         if (!BN_add_word(serial,1))
845                 { BIO_printf(bio_err,"add_word failure\n"); goto end; }
846         bs2.data=(unsigned char *)buf2;
847         bs2.length=BN_bn2bin(serial,bs2.data);
848
849         if (BIO_write_filename(io,buf) <= 0)
850                 {
851                 BIO_printf(bio_err,"error attempting to write serial number file\n");
852                 perror(buf);
853                 goto end;
854                 }
855         i2a_ASN1_INTEGER(io,&bs2);
856         BIO_puts(io,"\n");
857         BIO_free(io);
858         io=NULL;
859         
860         if (!X509_STORE_add_cert(ctx,x)) goto end;
861
862         /* NOTE: this certificate can/should be self signed, unless it was
863          * a certificate request in which case it is not. */
864         X509_STORE_CTX_set_cert(&xsc,x);
865         if (!reqfile && !X509_verify_cert(&xsc))
866                 goto end;
867
868         if (!X509_check_private_key(xca,pkey))
869                 {
870                 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
871                 goto end;
872                 }
873
874         if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
875         if (!X509_set_serialNumber(x,bs)) goto end;
876
877         if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
878                 goto end;
879
880         /* hardwired expired */
881         if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
882                 goto end;
883
884         if(conf) {
885                 X509V3_CTX ctx2;
886                 X509_set_version(x,2); /* version 3 certificate */
887                 X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
888                 X509V3_set_conf_lhash(&ctx2, conf);
889                 if(!X509V3_EXT_add_conf(conf, &ctx2, section, x)) goto end;
890         }
891
892         if (!X509_sign(x,pkey,digest)) goto end;
893         ret=1;
894 end:
895         X509_STORE_CTX_cleanup(&xsc);
896         if (!ret)
897                 ERR_print_errors(bio_err);
898         if (buf != NULL) Free(buf);
899         if (bs != NULL) ASN1_INTEGER_free(bs);
900         if (io != NULL) BIO_free(io);
901         if (serial != NULL) BN_free(serial);
902         return(ret);
903         }
904
905 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
906         {
907         char buf[256];
908         int err;
909         X509 *err_cert;
910
911         /* it is ok to use a self signed certificate
912          * This case will catch both the initial ok == 0 and the
913          * final ok == 1 calls to this function */
914         err=X509_STORE_CTX_get_error(ctx);
915         if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
916                 return(1);
917
918         /* BAD we should have gotten an error.  Normally if everything
919          * worked X509_STORE_CTX_get_error(ctx) will still be set to
920          * DEPTH_ZERO_SELF_.... */
921         if (ok)
922                 {
923                 BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
924                 return(0);
925                 }
926         else
927                 {
928                 err_cert=X509_STORE_CTX_get_current_cert(ctx);
929                 X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
930                 BIO_printf(bio_err,"%s\n",buf);
931                 BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
932                         err,X509_STORE_CTX_get_error_depth(ctx),
933                         X509_verify_cert_error_string(err));
934                 return(1);
935                 }
936         }
937
938 static EVP_PKEY *load_key(char *file, int format)
939         {
940         BIO *key=NULL;
941         EVP_PKEY *pkey=NULL;
942
943         if (file == NULL)
944                 {
945                 BIO_printf(bio_err,"no keyfile specified\n");
946                 goto end;
947                 }
948         key=BIO_new(BIO_s_file());
949         if (key == NULL)
950                 {
951                 ERR_print_errors(bio_err);
952                 goto end;
953                 }
954         if (BIO_read_filename(key,file) <= 0)
955                 {
956                 perror(file);
957                 goto end;
958                 }
959 #ifndef NO_RSA
960         if      (format == FORMAT_ASN1)
961                 {
962                 RSA *rsa;
963
964                 rsa=d2i_RSAPrivateKey_bio(key,NULL);
965                 if (rsa != NULL)
966                         {
967                         if ((pkey=EVP_PKEY_new()) != NULL)
968                                 EVP_PKEY_assign_RSA(pkey,rsa);
969                         else
970                                 RSA_free(rsa);
971                         }
972                 }
973         else
974 #endif
975                 if (format == FORMAT_PEM)
976                 {
977                 pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,NULL);
978                 }
979         else
980                 {
981                 BIO_printf(bio_err,"bad input format specified for key\n");
982                 goto end;
983                 }
984 end:
985         if (key != NULL) BIO_free(key);
986         if (pkey == NULL)
987                 BIO_printf(bio_err,"unable to load Private Key\n");
988         return(pkey);
989         }
990
991 static X509 *load_cert(char *file, int format)
992         {
993         ASN1_HEADER *ah=NULL;
994         BUF_MEM *buf=NULL;
995         X509 *x=NULL;
996         BIO *cert;
997
998         if ((cert=BIO_new(BIO_s_file())) == NULL)
999                 {
1000                 ERR_print_errors(bio_err);
1001                 goto end;
1002                 }
1003
1004         if (file == NULL)
1005                 BIO_set_fp(cert,stdin,BIO_NOCLOSE);
1006         else
1007                 {
1008                 if (BIO_read_filename(cert,file) <= 0)
1009                         {
1010                         perror(file);
1011                         goto end;
1012                         }
1013                 }
1014         if      (format == FORMAT_ASN1)
1015                 x=d2i_X509_bio(cert,NULL);
1016         else if (format == FORMAT_NETSCAPE)
1017                 {
1018                 unsigned char *p,*op;
1019                 int size=0,i;
1020
1021                 /* We sort of have to do it this way because it is sort of nice
1022                  * to read the header first and check it, then
1023                  * try to read the certificate */
1024                 buf=BUF_MEM_new();
1025                 for (;;)
1026                         {
1027                         if ((buf == NULL) || (!BUF_MEM_grow(buf,size+1024*10)))
1028                                 goto end;
1029                         i=BIO_read(cert,&(buf->data[size]),1024*10);
1030                         size+=i;
1031                         if (i == 0) break;
1032                         if (i < 0)
1033                                 {
1034                                 perror("reading certificate");
1035                                 goto end;
1036                                 }
1037                         }
1038                 p=(unsigned char *)buf->data;
1039                 op=p;
1040
1041                 /* First load the header */
1042                 if ((ah=d2i_ASN1_HEADER(NULL,&p,(long)size)) == NULL)
1043                         goto end;
1044                 if ((ah->header == NULL) || (ah->header->data == NULL) ||
1045                         (strncmp(CERT_HDR,(char *)ah->header->data,
1046                         ah->header->length) != 0))
1047                         {
1048                         BIO_printf(bio_err,"Error reading header on certificate\n");
1049                         goto end;
1050                         }
1051                 /* header is ok, so now read the object */
1052                 p=op;
1053                 ah->meth=X509_asn1_meth();
1054                 if ((ah=d2i_ASN1_HEADER(&ah,&p,(long)size)) == NULL)
1055                         goto end;
1056                 x=(X509 *)ah->data;
1057                 ah->data=NULL;
1058                 }
1059         else if (format == FORMAT_PEM)
1060                 x=PEM_read_bio_X509(cert,NULL,NULL,NULL);
1061         else    {
1062                 BIO_printf(bio_err,"bad input format specified for input cert\n");
1063                 goto end;
1064                 }
1065 end:
1066         if (x == NULL)
1067                 {
1068                 BIO_printf(bio_err,"unable to load certificate\n");
1069                 ERR_print_errors(bio_err);
1070                 }
1071         if (ah != NULL) ASN1_HEADER_free(ah);
1072         if (cert != NULL) BIO_free(cert);
1073         if (buf != NULL) BUF_MEM_free(buf);
1074         return(x);
1075         }
1076
1077 /* self sign */
1078 static int sign(X509 *x, EVP_PKEY *pkey, int days, const EVP_MD *digest, 
1079                                                 LHASH *conf, char *section)
1080         {
1081
1082         EVP_PKEY *pktmp;
1083
1084         pktmp = X509_get_pubkey(x);
1085         EVP_PKEY_copy_parameters(pktmp,pkey);
1086         EVP_PKEY_save_parameters(pktmp,1);
1087         EVP_PKEY_free(pktmp);
1088
1089         if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
1090         if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;
1091
1092         /* Lets just make it 12:00am GMT, Jan 1 1970 */
1093         /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
1094         /* 28 days to be certified */
1095
1096         if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
1097                 goto err;
1098
1099         if (!X509_set_pubkey(x,pkey)) goto err;
1100         if(conf) {
1101                 X509V3_CTX ctx;
1102                 X509_set_version(x,2); /* version 3 certificate */
1103                 X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1104                 X509V3_set_conf_lhash(&ctx, conf);
1105                 if(!X509V3_EXT_add_conf(conf, &ctx, section, x)) goto err;
1106         }
1107         if (!X509_sign(x,pkey,digest)) goto err;
1108         return(1);
1109 err:
1110         ERR_print_errors(bio_err);
1111         return(0);
1112         }
1113
1114 static int efunc(X509_PURPOSE *pt, void *arg)
1115 {
1116         X509_PPRINT *ptmp;
1117         int id, i, idret;
1118         char *pname;
1119         ptmp = arg;
1120         id = X509_PURPOSE_get_id(pt);
1121         pname = X509_PURPOSE_get_name(pt);
1122         for(i = 0; i < 2; i++) {
1123                 idret = X509_check_purpose(ptmp->cert, id, i);
1124                 BIO_printf(ptmp->bio, "%s%s : ", pname, i ? " CA" : ""); 
1125                 if(idret == 1) BIO_printf(ptmp->bio, "Yes\n");
1126                 else if (idret == 0) BIO_printf(ptmp->bio, "No\n");
1127                 else BIO_printf(ptmp->bio, "Yes (WARNING code=%d)\n", idret);
1128         }
1129         return 1;
1130 }
1131
1132
1133