Annotation of src/usr.bin/openssl/x509.c, Revision 1.6
1.6 ! bcook 1: /* $OpenBSD: x509.c,v 1.5 2015/08/22 16:36:05 jsing Exp $ */
1.1 jsing 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 <assert.h>
60: #include <stdio.h>
61: #include <stdlib.h>
62: #include <limits.h>
63: #include <string.h>
64:
65: #include "apps.h"
66:
67: #include <openssl/asn1.h>
68: #include <openssl/bio.h>
69: #include <openssl/bn.h>
70: #include <openssl/err.h>
71: #include <openssl/evp.h>
72: #include <openssl/objects.h>
73: #include <openssl/pem.h>
74: #include <openssl/x509.h>
75: #include <openssl/x509v3.h>
76:
77: #include <openssl/dsa.h>
78:
79: #include <openssl/rsa.h>
80:
81: #define POSTFIX ".srl"
82: #define DEF_DAYS 30
83:
84: static const char *x509_usage[] = {
85: "usage: x509 args\n",
86: " -inform arg - input format - default PEM (one of DER, NET or PEM)\n",
87: " -outform arg - output format - default PEM (one of DER, NET or PEM)\n",
88: " -keyform arg - private key format - default PEM\n",
89: " -CAform arg - CA format - default PEM\n",
90: " -CAkeyform arg - CA key format - default PEM\n",
91: " -in arg - input file - default stdin\n",
92: " -out arg - output file - default stdout\n",
93: " -passin arg - private key password source\n",
94: " -serial - print serial number value\n",
95: " -subject_hash - print subject hash value\n",
96: #ifndef OPENSSL_NO_MD5
97: " -subject_hash_old - print old-style (MD5) subject hash value\n",
98: #endif
99: " -issuer_hash - print issuer hash value\n",
100: #ifndef OPENSSL_NO_MD5
101: " -issuer_hash_old - print old-style (MD5) issuer hash value\n",
102: #endif
103: " -hash - synonym for -subject_hash\n",
104: " -subject - print subject DN\n",
105: " -issuer - print issuer DN\n",
106: " -email - print email address(es)\n",
107: " -startdate - notBefore field\n",
108: " -enddate - notAfter field\n",
109: " -purpose - print out certificate purposes\n",
110: " -dates - both Before and After dates\n",
111: " -modulus - print the RSA key modulus\n",
112: " -pubkey - output the public key\n",
113: " -fingerprint - print the certificate fingerprint\n",
114: " -alias - output certificate alias\n",
115: " -noout - no certificate output\n",
116: " -ocspid - print OCSP hash values for the subject name and public key\n",
117: " -ocsp_uri - print OCSP Responder URL(s)\n",
118: " -trustout - output a \"trusted\" certificate\n",
119: " -clrtrust - clear all trusted purposes\n",
120: " -clrreject - clear all rejected purposes\n",
121: " -addtrust arg - trust certificate for a given purpose\n",
122: " -addreject arg - reject certificate for a given purpose\n",
123: " -setalias arg - set certificate alias\n",
124: " -days arg - How long till expiry of a signed certificate - def 30 days\n",
125: " -checkend arg - check whether the cert expires in the next arg seconds\n",
126: " exit 1 if so, 0 if not\n",
127: " -signkey arg - self sign cert with arg\n",
128: " -x509toreq - output a certification request object\n",
129: " -req - input is a certificate request, sign and output.\n",
130: " -CA arg - set the CA certificate, must be PEM format.\n",
131: " -CAkey arg - set the CA key, must be PEM format\n",
132: " missing, it is assumed to be in the CA file.\n",
133: " -CAcreateserial - create serial number file if it does not exist\n",
134: " -CAserial arg - serial file\n",
135: " -set_serial - serial number to use\n",
136: " -text - print the certificate in text form\n",
137: " -C - print out C code forms\n",
1.3 doug 138: " -md2/-md5/-sha1 - digest to use\n",
1.1 jsing 139: " -extfile - configuration file with X509V3 extensions to add\n",
140: " -extensions - section from config file with X509V3 extensions to add\n",
141: " -clrext - delete extensions before signing and input certificate\n",
142: " -nameopt arg - various certificate name options\n",
143: " -certopt arg - various certificate text options\n",
144: NULL
145: };
146:
147: static int callb(int ok, X509_STORE_CTX *ctx);
148: static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
149: const EVP_MD *digest, CONF *conf, char *section);
150: static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
151: X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
152: char *serial, int create, int days, int clrext, CONF *conf, char *section,
153: ASN1_INTEGER *sno);
154: static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
155: static int reqfile = 0;
156:
157: int
158: x509_main(int argc, char **argv)
159: {
160: int ret = 1;
161: X509_REQ *req = NULL;
162: X509 *x = NULL, *xca = NULL;
163: ASN1_OBJECT *objtmp;
164: STACK_OF(OPENSSL_STRING) *sigopts = NULL;
165: EVP_PKEY *Upkey = NULL, *CApkey = NULL;
166: ASN1_INTEGER *sno = NULL;
167: int i, num, badops = 0;
168: BIO *out = NULL;
169: BIO *STDout = NULL;
170: STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
171: int informat, outformat, keyformat, CAformat, CAkeyformat;
172: char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
173: char *CAkeyfile = NULL, *CAserial = NULL;
174: char *alias = NULL;
175: int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0,
176: enddate = 0;
177: int next_serial = 0;
178: int subject_hash = 0, issuer_hash = 0, ocspid = 0;
179: #ifndef OPENSSL_NO_MD5
180: int subject_hash_old = 0, issuer_hash_old = 0;
181: #endif
182: int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0,
183: email = 0;
184: int ocsp_uri = 0;
185: int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0;
186: int C = 0;
187: int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0;
188: int pprint = 0;
189: const char **pp;
190: X509_STORE *ctx = NULL;
191: X509_REQ *rq = NULL;
192: int fingerprint = 0;
193: char buf[256];
194: const EVP_MD *md_alg, *digest = NULL;
195: CONF *extconf = NULL;
196: char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
197: int checkend = 0, checkoffset = 0;
198: unsigned long nmflag = 0, certflag = 0;
199: const char *errstr = NULL;
200:
201: reqfile = 0;
202:
203: STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
204:
205: informat = FORMAT_PEM;
206: outformat = FORMAT_PEM;
207: keyformat = FORMAT_PEM;
208: CAformat = FORMAT_PEM;
209: CAkeyformat = FORMAT_PEM;
210:
211: ctx = X509_STORE_new();
212: if (ctx == NULL)
213: goto end;
214: X509_STORE_set_verify_cb(ctx, callb);
215:
216: argc--;
217: argv++;
218: num = 0;
219: while (argc >= 1) {
220: if (strcmp(*argv, "-inform") == 0) {
221: if (--argc < 1)
222: goto bad;
223: informat = str2fmt(*(++argv));
224: } else if (strcmp(*argv, "-outform") == 0) {
225: if (--argc < 1)
226: goto bad;
227: outformat = str2fmt(*(++argv));
228: } else if (strcmp(*argv, "-keyform") == 0) {
229: if (--argc < 1)
230: goto bad;
231: keyformat = str2fmt(*(++argv));
232: } else if (strcmp(*argv, "-req") == 0) {
233: reqfile = 1;
234: } else if (strcmp(*argv, "-CAform") == 0) {
235: if (--argc < 1)
236: goto bad;
237: CAformat = str2fmt(*(++argv));
238: } else if (strcmp(*argv, "-CAkeyform") == 0) {
239: if (--argc < 1)
240: goto bad;
241: CAkeyformat = str2fmt(*(++argv));
242: } else if (strcmp(*argv, "-sigopt") == 0) {
243: if (--argc < 1)
244: goto bad;
245: if (!sigopts)
246: sigopts = sk_OPENSSL_STRING_new_null();
247: if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
248: goto bad;
249: } else if (strcmp(*argv, "-days") == 0) {
250: if (--argc < 1)
251: goto bad;
252: days = strtonum(*(++argv), 1, INT_MAX, &errstr);
253: if (errstr) {
254: BIO_printf(bio_err, "bad number of days: %s\n", errstr);
255: goto bad;
256: }
257: } else if (strcmp(*argv, "-passin") == 0) {
258: if (--argc < 1)
259: goto bad;
260: passargin = *(++argv);
261: } else if (strcmp(*argv, "-extfile") == 0) {
262: if (--argc < 1)
263: goto bad;
264: extfile = *(++argv);
265: } else if (strcmp(*argv, "-extensions") == 0) {
266: if (--argc < 1)
267: goto bad;
268: extsect = *(++argv);
269: } else if (strcmp(*argv, "-in") == 0) {
270: if (--argc < 1)
271: goto bad;
272: infile = *(++argv);
273: } else if (strcmp(*argv, "-out") == 0) {
274: if (--argc < 1)
275: goto bad;
276: outfile = *(++argv);
277: } else if (strcmp(*argv, "-signkey") == 0) {
278: if (--argc < 1)
279: goto bad;
280: keyfile = *(++argv);
281: sign_flag = ++num;
282: } else if (strcmp(*argv, "-CA") == 0) {
283: if (--argc < 1)
284: goto bad;
285: CAfile = *(++argv);
286: CA_flag = ++num;
287: } else if (strcmp(*argv, "-CAkey") == 0) {
288: if (--argc < 1)
289: goto bad;
290: CAkeyfile = *(++argv);
291: } else if (strcmp(*argv, "-CAserial") == 0) {
292: if (--argc < 1)
293: goto bad;
294: CAserial = *(++argv);
295: } else if (strcmp(*argv, "-set_serial") == 0) {
296: if (--argc < 1)
297: goto bad;
1.4 doug 298: M_ASN1_INTEGER_free(sno);
1.1 jsing 299: if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
300: goto bad;
301: } else if (strcmp(*argv, "-addtrust") == 0) {
302: if (--argc < 1)
303: goto bad;
304: if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
305: BIO_printf(bio_err,
306: "Invalid trust object value %s\n", *argv);
307: goto bad;
308: }
309: if (!trust)
310: trust = sk_ASN1_OBJECT_new_null();
311: sk_ASN1_OBJECT_push(trust, objtmp);
312: trustout = 1;
313: } else if (strcmp(*argv, "-addreject") == 0) {
314: if (--argc < 1)
315: goto bad;
316: if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
317: BIO_printf(bio_err,
318: "Invalid reject object value %s\n", *argv);
319: goto bad;
320: }
321: if (!reject)
322: reject = sk_ASN1_OBJECT_new_null();
323: sk_ASN1_OBJECT_push(reject, objtmp);
324: trustout = 1;
325: } else if (strcmp(*argv, "-setalias") == 0) {
326: if (--argc < 1)
327: goto bad;
328: alias = *(++argv);
329: trustout = 1;
330: } else if (strcmp(*argv, "-certopt") == 0) {
331: if (--argc < 1)
332: goto bad;
333: if (!set_cert_ex(&certflag, *(++argv)))
334: goto bad;
335: } else if (strcmp(*argv, "-nameopt") == 0) {
336: if (--argc < 1)
337: goto bad;
338: if (!set_name_ex(&nmflag, *(++argv)))
339: goto bad;
340: }
341: else if (strcmp(*argv, "-C") == 0)
342: C = ++num;
343: else if (strcmp(*argv, "-email") == 0)
344: email = ++num;
345: else if (strcmp(*argv, "-ocsp_uri") == 0)
346: ocsp_uri = ++num;
347: else if (strcmp(*argv, "-serial") == 0)
348: serial = ++num;
349: else if (strcmp(*argv, "-next_serial") == 0)
350: next_serial = ++num;
351: else if (strcmp(*argv, "-modulus") == 0)
352: modulus = ++num;
353: else if (strcmp(*argv, "-pubkey") == 0)
354: pubkey = ++num;
355: else if (strcmp(*argv, "-x509toreq") == 0)
356: x509req = ++num;
357: else if (strcmp(*argv, "-text") == 0)
358: text = ++num;
359: else if (strcmp(*argv, "-hash") == 0 ||
360: strcmp(*argv, "-subject_hash") == 0)
361: subject_hash = ++num;
362: #ifndef OPENSSL_NO_MD5
363: else if (strcmp(*argv, "-subject_hash_old") == 0)
364: subject_hash_old = ++num;
365: #endif
366: else if (strcmp(*argv, "-issuer_hash") == 0)
367: issuer_hash = ++num;
368: #ifndef OPENSSL_NO_MD5
369: else if (strcmp(*argv, "-issuer_hash_old") == 0)
370: issuer_hash_old = ++num;
371: #endif
372: else if (strcmp(*argv, "-subject") == 0)
373: subject = ++num;
374: else if (strcmp(*argv, "-issuer") == 0)
375: issuer = ++num;
376: else if (strcmp(*argv, "-fingerprint") == 0)
377: fingerprint = ++num;
378: else if (strcmp(*argv, "-dates") == 0) {
379: startdate = ++num;
380: enddate = ++num;
381: } else if (strcmp(*argv, "-purpose") == 0)
382: pprint = ++num;
383: else if (strcmp(*argv, "-startdate") == 0)
384: startdate = ++num;
385: else if (strcmp(*argv, "-enddate") == 0)
386: enddate = ++num;
387: else if (strcmp(*argv, "-checkend") == 0) {
388: if (--argc < 1)
389: goto bad;
390: checkoffset = strtonum(*(++argv), 0, INT_MAX, &errstr);
391: if (errstr) {
392: BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
393: goto bad;
394: }
395: checkend = 1;
396: } else if (strcmp(*argv, "-noout") == 0)
397: noout = ++num;
398: else if (strcmp(*argv, "-trustout") == 0)
399: trustout = 1;
400: else if (strcmp(*argv, "-clrtrust") == 0)
401: clrtrust = ++num;
402: else if (strcmp(*argv, "-clrreject") == 0)
403: clrreject = ++num;
404: else if (strcmp(*argv, "-alias") == 0)
405: aliasout = ++num;
406: else if (strcmp(*argv, "-CAcreateserial") == 0)
407: CA_createserial = ++num;
408: else if (strcmp(*argv, "-clrext") == 0)
409: clrext = 1;
410: else if (strcmp(*argv, "-ocspid") == 0)
411: ocspid = ++num;
412: else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
413: /* ok */
414: digest = md_alg;
415: } else {
416: BIO_printf(bio_err, "unknown option %s\n", *argv);
417: badops = 1;
418: break;
419: }
420: argc--;
421: argv++;
422: }
423:
424: if (badops) {
425: bad:
426: for (pp = x509_usage; (*pp != NULL); pp++)
427: BIO_printf(bio_err, "%s", *pp);
428: goto end;
429: }
430:
431: if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
432: BIO_printf(bio_err, "Error getting password\n");
433: goto end;
434: }
435: if (!X509_STORE_set_default_paths(ctx)) {
436: ERR_print_errors(bio_err);
437: goto end;
438: }
439: if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
440: CAkeyfile = CAfile;
441: } else if ((CA_flag) && (CAkeyfile == NULL)) {
442: BIO_printf(bio_err,
443: "need to specify a CAkey if using the CA command\n");
444: goto end;
445: }
446: if (extfile) {
447: long errorline = -1;
448: X509V3_CTX ctx2;
449: extconf = NCONF_new(NULL);
450: if (!NCONF_load(extconf, extfile, &errorline)) {
451: if (errorline <= 0)
452: BIO_printf(bio_err,
453: "error loading the config file '%s'\n",
454: extfile);
455: else
456: BIO_printf(bio_err,
457: "error on line %ld of config file '%s'\n",
458: errorline, extfile);
459: goto end;
460: }
461: if (!extsect) {
462: extsect = NCONF_get_string(extconf, "default",
463: "extensions");
464: if (!extsect) {
465: ERR_clear_error();
466: extsect = "default";
467: }
468: }
469: X509V3_set_ctx_test(&ctx2);
470: X509V3_set_nconf(&ctx2, extconf);
471: if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
472: BIO_printf(bio_err,
473: "Error Loading extension section %s\n",
474: extsect);
475: ERR_print_errors(bio_err);
476: goto end;
477: }
478: }
479: if (reqfile) {
480: EVP_PKEY *pkey;
481: BIO *in;
482:
483: if (!sign_flag && !CA_flag) {
484: BIO_printf(bio_err, "We need a private key to sign with\n");
485: goto end;
486: }
487: in = BIO_new(BIO_s_file());
488: if (in == NULL) {
489: ERR_print_errors(bio_err);
490: goto end;
491: }
492: if (infile == NULL)
493: BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
494: else {
495: if (BIO_read_filename(in, infile) <= 0) {
496: perror(infile);
497: BIO_free(in);
498: goto end;
499: }
500: }
501: req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
502: BIO_free(in);
503:
504: if (req == NULL) {
505: ERR_print_errors(bio_err);
506: goto end;
507: }
508: if ((req->req_info == NULL) ||
509: (req->req_info->pubkey == NULL) ||
510: (req->req_info->pubkey->public_key == NULL) ||
511: (req->req_info->pubkey->public_key->data == NULL)) {
512: BIO_printf(bio_err, "The certificate request appears to corrupted\n");
513: BIO_printf(bio_err, "It does not contain a public key\n");
514: goto end;
515: }
516: if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
517: BIO_printf(bio_err, "error unpacking public key\n");
518: goto end;
519: }
520: i = X509_REQ_verify(req, pkey);
521: EVP_PKEY_free(pkey);
522: if (i < 0) {
523: BIO_printf(bio_err, "Signature verification error\n");
524: ERR_print_errors(bio_err);
525: goto end;
526: }
527: if (i == 0) {
528: BIO_printf(bio_err, "Signature did not match the certificate request\n");
529: goto end;
530: } else
531: BIO_printf(bio_err, "Signature ok\n");
532:
533: print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
534:
535: if ((x = X509_new()) == NULL)
536: goto end;
537:
538: if (sno == NULL) {
539: sno = ASN1_INTEGER_new();
540: if (!sno || !rand_serial(NULL, sno))
541: goto end;
542: if (!X509_set_serialNumber(x, sno))
543: goto end;
544: ASN1_INTEGER_free(sno);
545: sno = NULL;
546: } else if (!X509_set_serialNumber(x, sno))
547: goto end;
548:
549: if (!X509_set_issuer_name(x, req->req_info->subject))
550: goto end;
551: if (!X509_set_subject_name(x, req->req_info->subject))
552: goto end;
553:
554: X509_gmtime_adj(X509_get_notBefore(x), 0);
555: X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
556:
557: pkey = X509_REQ_get_pubkey(req);
558: X509_set_pubkey(x, pkey);
559: EVP_PKEY_free(pkey);
560: } else
1.6 ! bcook 561: x = load_cert(bio_err, infile, informat, NULL, "Certificate");
1.1 jsing 562:
563: if (x == NULL)
564: goto end;
565: if (CA_flag) {
1.6 ! bcook 566: xca = load_cert(bio_err, CAfile, CAformat, NULL, "CA Certificate");
1.1 jsing 567: if (xca == NULL)
568: goto end;
569: }
570: if (!noout || text || next_serial) {
571: OBJ_create("2.99999.3",
572: "SET.ex3", "SET x509v3 extension 3");
573:
574: out = BIO_new(BIO_s_file());
575: if (out == NULL) {
576: ERR_print_errors(bio_err);
577: goto end;
578: }
579: if (outfile == NULL) {
580: BIO_set_fp(out, stdout, BIO_NOCLOSE);
581: } else {
582: if (BIO_write_filename(out, outfile) <= 0) {
583: perror(outfile);
584: goto end;
585: }
586: }
587: }
588: if (alias)
589: X509_alias_set1(x, (unsigned char *) alias, -1);
590:
591: if (clrtrust)
592: X509_trust_clear(x);
593: if (clrreject)
594: X509_reject_clear(x);
595:
596: if (trust) {
597: for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
598: objtmp = sk_ASN1_OBJECT_value(trust, i);
599: X509_add1_trust_object(x, objtmp);
600: }
601: }
602: if (reject) {
603: for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
604: objtmp = sk_ASN1_OBJECT_value(reject, i);
605: X509_add1_reject_object(x, objtmp);
606: }
607: }
608: if (num) {
609: for (i = 1; i <= num; i++) {
610: if (issuer == i) {
611: print_name(STDout, "issuer= ",
612: X509_get_issuer_name(x), nmflag);
613: } else if (subject == i) {
614: print_name(STDout, "subject= ",
615: X509_get_subject_name(x), nmflag);
616: } else if (serial == i) {
617: BIO_printf(STDout, "serial=");
618: i2a_ASN1_INTEGER(STDout,
619: X509_get_serialNumber(x));
620: BIO_printf(STDout, "\n");
621: } else if (next_serial == i) {
622: BIGNUM *bnser;
623: ASN1_INTEGER *ser;
624: ser = X509_get_serialNumber(x);
625: bnser = ASN1_INTEGER_to_BN(ser, NULL);
626: if (!bnser)
627: goto end;
628: if (!BN_add_word(bnser, 1))
629: goto end;
630: ser = BN_to_ASN1_INTEGER(bnser, NULL);
631: if (!ser)
632: goto end;
633: BN_free(bnser);
634: i2a_ASN1_INTEGER(out, ser);
635: ASN1_INTEGER_free(ser);
636: BIO_puts(out, "\n");
637: } else if ((email == i) || (ocsp_uri == i)) {
638: int j;
639: STACK_OF(OPENSSL_STRING) *emlst;
640: if (email == i)
641: emlst = X509_get1_email(x);
642: else
643: emlst = X509_get1_ocsp(x);
644: for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
645: BIO_printf(STDout, "%s\n",
646: sk_OPENSSL_STRING_value(emlst, j));
647: X509_email_free(emlst);
648: } else if (aliasout == i) {
649: unsigned char *alstr;
650: alstr = X509_alias_get0(x, NULL);
651: if (alstr)
652: BIO_printf(STDout, "%s\n", alstr);
653: else
654: BIO_puts(STDout, "<No Alias>\n");
655: } else if (subject_hash == i) {
656: BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
657: }
658: #ifndef OPENSSL_NO_MD5
659: else if (subject_hash_old == i) {
660: BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x));
661: }
662: #endif
663: else if (issuer_hash == i) {
664: BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
665: }
666: #ifndef OPENSSL_NO_MD5
667: else if (issuer_hash_old == i) {
668: BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x));
669: }
670: #endif
671: else if (pprint == i) {
672: X509_PURPOSE *ptmp;
673: int j;
674: BIO_printf(STDout, "Certificate purposes:\n");
675: for (j = 0; j < X509_PURPOSE_get_count(); j++) {
676: ptmp = X509_PURPOSE_get0(j);
677: purpose_print(STDout, x, ptmp);
678: }
679: } else if (modulus == i) {
680: EVP_PKEY *pkey;
681:
682: pkey = X509_get_pubkey(x);
683: if (pkey == NULL) {
684: BIO_printf(bio_err, "Modulus=unavailable\n");
685: ERR_print_errors(bio_err);
686: goto end;
687: }
688: BIO_printf(STDout, "Modulus=");
689: if (pkey->type == EVP_PKEY_RSA)
690: BN_print(STDout, pkey->pkey.rsa->n);
691: else
692: if (pkey->type == EVP_PKEY_DSA)
693: BN_print(STDout, pkey->pkey.dsa->pub_key);
694: else
695: BIO_printf(STDout, "Wrong Algorithm type");
696: BIO_printf(STDout, "\n");
697: EVP_PKEY_free(pkey);
698: } else if (pubkey == i) {
699: EVP_PKEY *pkey;
700:
701: pkey = X509_get_pubkey(x);
702: if (pkey == NULL) {
703: BIO_printf(bio_err, "Error getting public key\n");
704: ERR_print_errors(bio_err);
705: goto end;
706: }
707: PEM_write_bio_PUBKEY(STDout, pkey);
708: EVP_PKEY_free(pkey);
709: } else if (C == i) {
710: unsigned char *d;
711: char *m;
712: int y, z;
713:
714: X509_NAME_oneline(X509_get_subject_name(x),
715: buf, sizeof buf);
716: BIO_printf(STDout, "/* subject:%s */\n", buf);
717: m = X509_NAME_oneline(
718: X509_get_issuer_name(x), buf,
719: sizeof buf);
720: BIO_printf(STDout, "/* issuer :%s */\n", buf);
721:
722: z = i2d_X509(x, NULL);
723: m = malloc(z);
724:
725: d = (unsigned char *) m;
726: z = i2d_X509_NAME(X509_get_subject_name(x), &d);
727: BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", z);
728: d = (unsigned char *) m;
729: for (y = 0; y < z; y++) {
730: BIO_printf(STDout, "0x%02X,", d[y]);
731: if ((y & 0x0f) == 0x0f)
732: BIO_printf(STDout, "\n");
733: }
734: if (y % 16 != 0)
735: BIO_printf(STDout, "\n");
736: BIO_printf(STDout, "};\n");
737:
738: z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
739: BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
740: d = (unsigned char *) m;
741: for (y = 0; y < z; y++) {
742: BIO_printf(STDout, "0x%02X,", d[y]);
743: if ((y & 0x0f) == 0x0f)
744: BIO_printf(STDout, "\n");
745: }
746: if (y % 16 != 0)
747: BIO_printf(STDout, "\n");
748: BIO_printf(STDout, "};\n");
749:
750: z = i2d_X509(x, &d);
751: BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", z);
752: d = (unsigned char *) m;
753: for (y = 0; y < z; y++) {
754: BIO_printf(STDout, "0x%02X,", d[y]);
755: if ((y & 0x0f) == 0x0f)
756: BIO_printf(STDout, "\n");
757: }
758: if (y % 16 != 0)
759: BIO_printf(STDout, "\n");
760: BIO_printf(STDout, "};\n");
761:
762: free(m);
763: } else if (text == i) {
764: X509_print_ex(STDout, x, nmflag, certflag);
765: } else if (startdate == i) {
766: BIO_puts(STDout, "notBefore=");
767: ASN1_TIME_print(STDout, X509_get_notBefore(x));
768: BIO_puts(STDout, "\n");
769: } else if (enddate == i) {
770: BIO_puts(STDout, "notAfter=");
771: ASN1_TIME_print(STDout, X509_get_notAfter(x));
772: BIO_puts(STDout, "\n");
773: } else if (fingerprint == i) {
774: int j;
775: unsigned int n;
776: unsigned char md[EVP_MAX_MD_SIZE];
777: const EVP_MD *fdig = digest;
778:
779: if (!fdig)
780: fdig = EVP_sha1();
781:
782: if (!X509_digest(x, fdig, md, &n)) {
783: BIO_printf(bio_err, "out of memory\n");
784: goto end;
785: }
786: BIO_printf(STDout, "%s Fingerprint=",
787: OBJ_nid2sn(EVP_MD_type(fdig)));
788: for (j = 0; j < (int) n; j++) {
789: BIO_printf(STDout, "%02X%c", md[j],
790: (j + 1 == (int)n) ? '\n' : ':');
791: }
792: }
793: /* should be in the library */
794: else if ((sign_flag == i) && (x509req == 0)) {
795: BIO_printf(bio_err, "Getting Private key\n");
796: if (Upkey == NULL) {
797: Upkey = load_key(bio_err,
798: keyfile, keyformat, 0,
1.6 ! bcook 799: passin, "Private key");
1.1 jsing 800: if (Upkey == NULL)
801: goto end;
802: }
803: if (!sign(x, Upkey, days, clrext, digest,
804: extconf, extsect))
805: goto end;
806: } else if (CA_flag == i) {
807: BIO_printf(bio_err, "Getting CA Private Key\n");
808: if (CAkeyfile != NULL) {
809: CApkey = load_key(bio_err,
810: CAkeyfile, CAkeyformat,
1.6 ! bcook 811: 0, passin, "CA Private Key");
1.1 jsing 812: if (CApkey == NULL)
813: goto end;
814: }
815: if (!x509_certify(ctx, CAfile, digest, x, xca,
816: CApkey, sigopts,
817: CAserial, CA_createserial, days, clrext,
818: extconf, extsect, sno))
819: goto end;
820: } else if (x509req == i) {
821: EVP_PKEY *pk;
822:
823: BIO_printf(bio_err, "Getting request Private Key\n");
824: if (keyfile == NULL) {
825: BIO_printf(bio_err, "no request key file specified\n");
826: goto end;
827: } else {
828: pk = load_key(bio_err,
829: keyfile, keyformat, 0,
1.6 ! bcook 830: passin, "request key");
1.1 jsing 831: if (pk == NULL)
832: goto end;
833: }
834:
835: BIO_printf(bio_err, "Generating certificate request\n");
836:
837: rq = X509_to_X509_REQ(x, pk, digest);
838: EVP_PKEY_free(pk);
839: if (rq == NULL) {
840: ERR_print_errors(bio_err);
841: goto end;
842: }
843: if (!noout) {
844: X509_REQ_print(out, rq);
845: PEM_write_bio_X509_REQ(out, rq);
846: }
847: noout = 1;
848: } else if (ocspid == i) {
849: X509_ocspid_print(out, x);
850: }
851: }
852: }
853: if (checkend) {
854: time_t tcheck = time(NULL) + checkoffset;
855:
856: if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
857: BIO_printf(out, "Certificate will expire\n");
858: ret = 1;
859: } else {
860: BIO_printf(out, "Certificate will not expire\n");
861: ret = 0;
862: }
863: goto end;
864: }
865: if (noout) {
866: ret = 0;
867: goto end;
868: }
869: if (outformat == FORMAT_ASN1)
870: i = i2d_X509_bio(out, x);
871: else if (outformat == FORMAT_PEM) {
872: if (trustout)
873: i = PEM_write_bio_X509_AUX(out, x);
874: else
875: i = PEM_write_bio_X509(out, x);
876: } else if (outformat == FORMAT_NETSCAPE) {
877: NETSCAPE_X509 nx;
878: ASN1_OCTET_STRING hdr;
879:
880: hdr.data = (unsigned char *) NETSCAPE_CERT_HDR;
881: hdr.length = strlen(NETSCAPE_CERT_HDR);
882: nx.header = &hdr;
883: nx.cert = x;
884:
885: i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx);
886: } else {
887: BIO_printf(bio_err, "bad output format specified for outfile\n");
888: goto end;
889: }
890: if (!i) {
891: BIO_printf(bio_err, "unable to write certificate\n");
892: ERR_print_errors(bio_err);
893: goto end;
894: }
895: ret = 0;
896:
897: end:
898: OBJ_cleanup();
899: NCONF_free(extconf);
900: BIO_free_all(out);
901: BIO_free_all(STDout);
902: X509_STORE_free(ctx);
903: X509_REQ_free(req);
904: X509_free(x);
905: X509_free(xca);
906: EVP_PKEY_free(Upkey);
907: EVP_PKEY_free(CApkey);
908: if (sigopts)
909: sk_OPENSSL_STRING_free(sigopts);
910: X509_REQ_free(rq);
911: ASN1_INTEGER_free(sno);
912: sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
913: sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
914: free(passin);
915:
916: return (ret);
917: }
918:
919: static ASN1_INTEGER *
920: x509_load_serial(char *CAfile, char *serialfile, int create)
921: {
922: char *buf = NULL, *p;
923: ASN1_INTEGER *bs = NULL;
924: BIGNUM *serial = NULL;
925: size_t len;
926:
927: len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
928: (strlen(serialfile))) + 1;
929: buf = malloc(len);
930: if (buf == NULL) {
931: BIO_printf(bio_err, "out of mem\n");
932: goto end;
933: }
934: if (serialfile == NULL) {
935: strlcpy(buf, CAfile, len);
936: for (p = buf; *p; p++)
937: if (*p == '.') {
938: *p = '\0';
939: break;
940: }
941: strlcat(buf, POSTFIX, len);
942: } else
943: strlcpy(buf, serialfile, len);
944:
945: serial = load_serial(buf, create, NULL);
946: if (serial == NULL)
947: goto end;
948:
949: if (!BN_add_word(serial, 1)) {
950: BIO_printf(bio_err, "add_word failure\n");
951: goto end;
952: }
953: if (!save_serial(buf, NULL, serial, &bs))
954: goto end;
955:
956: end:
957: free(buf);
958: BN_free(serial);
959:
960: return bs;
961: }
962:
963: static int
964: x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
965: X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
966: char *serialfile, int create, int days, int clrext, CONF *conf,
967: char *section, ASN1_INTEGER *sno)
968: {
969: int ret = 0;
970: ASN1_INTEGER *bs = NULL;
971: X509_STORE_CTX xsc;
972: EVP_PKEY *upkey;
973:
974: upkey = X509_get_pubkey(xca);
975: EVP_PKEY_copy_parameters(upkey, pkey);
976: EVP_PKEY_free(upkey);
977:
978: if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
979: BIO_printf(bio_err, "Error initialising X509 store\n");
980: goto end;
981: }
982: if (sno)
983: bs = sno;
984: else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
985: goto end;
986:
987: /* if (!X509_STORE_add_cert(ctx,x)) goto end;*/
988:
989: /*
990: * NOTE: this certificate can/should be self signed, unless it was a
991: * certificate request in which case it is not.
992: */
993: X509_STORE_CTX_set_cert(&xsc, x);
994: X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
995: if (!reqfile && X509_verify_cert(&xsc) <= 0)
996: goto end;
997:
998: if (!X509_check_private_key(xca, pkey)) {
999: BIO_printf(bio_err, "CA certificate and CA private key do not match\n");
1000: goto end;
1001: }
1002: if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1003: goto end;
1004: if (!X509_set_serialNumber(x, bs))
1005: goto end;
1006:
1007: if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1008: goto end;
1009:
1010: /* hardwired expired */
1011: if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1012: goto end;
1013:
1014: if (clrext) {
1015: while (X509_get_ext_count(x) > 0)
1016: X509_delete_ext(x, 0);
1017: }
1018: if (conf) {
1019: X509V3_CTX ctx2;
1020: X509_set_version(x, 2); /* version 3 certificate */
1021: X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1022: X509V3_set_nconf(&ctx2, conf);
1023: if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1024: goto end;
1025: }
1026: if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1027: goto end;
1028: ret = 1;
1029: end:
1030: X509_STORE_CTX_cleanup(&xsc);
1031: if (!ret)
1032: ERR_print_errors(bio_err);
1033: if (!sno)
1034: ASN1_INTEGER_free(bs);
1035: return ret;
1036: }
1037:
1038: static int
1039: callb(int ok, X509_STORE_CTX *ctx)
1040: {
1041: int err;
1042: X509 *err_cert;
1043:
1044: /*
1045: * it is ok to use a self signed certificate This case will catch
1046: * both the initial ok == 0 and the final ok == 1 calls to this
1047: * function
1048: */
1049: err = X509_STORE_CTX_get_error(ctx);
1050: if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1051: return 1;
1052:
1053: /*
1054: * BAD we should have gotten an error. Normally if everything worked
1055: * X509_STORE_CTX_get_error(ctx) will still be set to
1056: * DEPTH_ZERO_SELF_....
1057: */
1058: if (ok) {
1059: BIO_printf(bio_err, "error with certificate to be certified - should be self signed\n");
1060: return 0;
1061: } else {
1062: err_cert = X509_STORE_CTX_get_current_cert(ctx);
1063: print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1064: BIO_printf(bio_err, "error with certificate - error %d at depth %d\n%s\n",
1065: err, X509_STORE_CTX_get_error_depth(ctx),
1066: X509_verify_cert_error_string(err));
1067: return 1;
1068: }
1069: }
1070:
1071: /* self sign */
1072: static int
1073: sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1074: CONF *conf, char *section)
1075: {
1076:
1077: EVP_PKEY *pktmp;
1078:
1079: pktmp = X509_get_pubkey(x);
1080: EVP_PKEY_copy_parameters(pktmp, pkey);
1081: EVP_PKEY_save_parameters(pktmp, 1);
1082: EVP_PKEY_free(pktmp);
1083:
1084: if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1085: goto err;
1086: if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1087: goto err;
1088:
1089: /* Lets just make it 12:00am GMT, Jan 1 1970 */
1090: /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
1091: /* 28 days to be certified */
1092:
1093: if (X509_gmtime_adj(X509_get_notAfter(x),
1094: (long) 60 * 60 * 24 * days) == NULL)
1095: goto err;
1096:
1097: if (!X509_set_pubkey(x, pkey))
1098: goto err;
1099: if (clrext) {
1100: while (X509_get_ext_count(x) > 0)
1101: X509_delete_ext(x, 0);
1102: }
1103: if (conf) {
1104: X509V3_CTX ctx;
1105: X509_set_version(x, 2); /* version 3 certificate */
1106: X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1107: X509V3_set_nconf(&ctx, conf);
1108: if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1109: goto err;
1110: }
1111: if (!X509_sign(x, pkey, digest))
1112: goto err;
1113: return 1;
1114:
1115: err:
1116: ERR_print_errors(bio_err);
1117: return 0;
1118: }
1119:
1120: static int
1121: purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1122: {
1123: int id, i, idret;
1124: char *pname;
1125:
1126: id = X509_PURPOSE_get_id(pt);
1127: pname = X509_PURPOSE_get0_name(pt);
1128: for (i = 0; i < 2; i++) {
1129: idret = X509_check_purpose(cert, id, i);
1130: BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1131: if (idret == 1)
1132: BIO_printf(bio, "Yes\n");
1133: else if (idret == 0)
1134: BIO_printf(bio, "No\n");
1135: else
1136: BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1137: }
1138: return 1;
1139: }