GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/openssl/x509.c Lines: 418 641 65.2 %
Date: 2017-11-07 Branches: 285 524 54.4 %

Line Branch Exec Source
1
/* $OpenBSD: x509.c,v 1.14 2017/01/20 08:57:12 deraadt Exp $ */
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",
138
	" -md5/-sha1      - digest to use\n",
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
178
	char buf[256];
194
	const EVP_MD *md_alg, *digest = NULL;
195
	CONF *extconf = NULL;
196
89
	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
197
	int checkend = 0, checkoffset = 0;
198
89
	unsigned long nmflag = 0, certflag = 0;
199
89
	const char *errstr = NULL;
200
201
89
	if (single_execution) {
202
89
		if (pledge("stdio cpath wpath rpath tty flock", NULL) == -1) {
203
			perror("pledge");
204
			exit(1);
205
		}
206
	}
207
208
89
	reqfile = 0;
209
210
89
	STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
211
212
	informat = FORMAT_PEM;
213
	outformat = FORMAT_PEM;
214
	keyformat = FORMAT_PEM;
215
	CAformat = FORMAT_PEM;
216
	CAkeyformat = FORMAT_PEM;
217
218
89
	ctx = X509_STORE_new();
219
89
	if (ctx == NULL)
220
		goto end;
221
89
	X509_STORE_set_verify_cb(ctx, callb);
222
223
89
	argc--;
224
89
	argv++;
225
	num = 0;
226
1136
	while (argc >= 1) {
227
487
		if (strcmp(*argv, "-inform") == 0) {
228
8
			if (--argc < 1)
229
				goto bad;
230
8
			informat = str2fmt(*(++argv));
231
487
		} else if (strcmp(*argv, "-outform") == 0) {
232
8
			if (--argc < 1)
233
				goto bad;
234
8
			outformat = str2fmt(*(++argv));
235
479
		} else if (strcmp(*argv, "-keyform") == 0) {
236
			if (--argc < 1)
237
				goto bad;
238
			keyformat = str2fmt(*(++argv));
239
471
		} else if (strcmp(*argv, "-req") == 0) {
240
28
			reqfile = 1;
241
471
		} else if (strcmp(*argv, "-CAform") == 0) {
242
			if (--argc < 1)
243
				goto bad;
244
			CAformat = str2fmt(*(++argv));
245
443
		} else if (strcmp(*argv, "-CAkeyform") == 0) {
246
			if (--argc < 1)
247
				goto bad;
248
			CAkeyformat = str2fmt(*(++argv));
249
443
		} else if (strcmp(*argv, "-sigopt") == 0) {
250
			if (--argc < 1)
251
				goto bad;
252
			if (!sigopts)
253
				sigopts = sk_OPENSSL_STRING_new_null();
254
			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
255
				goto bad;
256
443
		} else if (strcmp(*argv, "-days") == 0) {
257
			if (--argc < 1)
258
				goto bad;
259
			days = strtonum(*(++argv), 1, INT_MAX, &errstr);
260
			if (errstr) {
261
				BIO_printf(bio_err, "bad number of days: %s\n", errstr);
262
				goto bad;
263
			}
264
443
		} else if (strcmp(*argv, "-passin") == 0) {
265
16
			if (--argc < 1)
266
				goto bad;
267
16
			passargin = *(++argv);
268
443
		} else if (strcmp(*argv, "-extfile") == 0) {
269
			if (--argc < 1)
270
				goto bad;
271
			extfile = *(++argv);
272
427
		} else if (strcmp(*argv, "-extensions") == 0) {
273
			if (--argc < 1)
274
				goto bad;
275
			extsect = *(++argv);
276
427
		} else if (strcmp(*argv, "-in") == 0) {
277
81
			if (--argc < 1)
278
				goto bad;
279
81
			infile = *(++argv);
280
427
		} else if (strcmp(*argv, "-out") == 0) {
281
52
			if (--argc < 1)
282
				goto bad;
283
52
			outfile = *(++argv);
284
346
		} else if (strcmp(*argv, "-signkey") == 0) {
285
8
			if (--argc < 1)
286
				goto bad;
287
8
			keyfile = *(++argv);
288
8
			sign_flag = ++num;
289
294
		} else if (strcmp(*argv, "-CA") == 0) {
290
28
			if (--argc < 1)
291
				goto bad;
292
28
			CAfile = *(++argv);
293
28
			CA_flag = ++num;
294
286
		} else if (strcmp(*argv, "-CAkey") == 0) {
295
28
			if (--argc < 1)
296
				goto bad;
297
28
			CAkeyfile = *(++argv);
298
258
		} else if (strcmp(*argv, "-CAserial") == 0) {
299
			if (--argc < 1)
300
				goto bad;
301
			CAserial = *(++argv);
302
230
		} else if (strcmp(*argv, "-set_serial") == 0) {
303
			if (--argc < 1)
304
				goto bad;
305
			ASN1_INTEGER_free(sno);
306
			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
307
				goto bad;
308
230
		} else if (strcmp(*argv, "-addtrust") == 0) {
309
8
			if (--argc < 1)
310
				goto bad;
311
8
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
312
				BIO_printf(bio_err,
313
				    "Invalid trust object value %s\n", *argv);
314
				goto bad;
315
			}
316
8
			if (!trust)
317
8
				trust = sk_ASN1_OBJECT_new_null();
318
8
			sk_ASN1_OBJECT_push(trust, objtmp);
319
			trustout = 1;
320
230
		} else if (strcmp(*argv, "-addreject") == 0) {
321
			if (--argc < 1)
322
				goto bad;
323
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
324
				BIO_printf(bio_err,
325
				    "Invalid reject object value %s\n", *argv);
326
				goto bad;
327
			}
328
			if (!reject)
329
				reject = sk_ASN1_OBJECT_new_null();
330
			sk_ASN1_OBJECT_push(reject, objtmp);
331
			trustout = 1;
332
222
		} else if (strcmp(*argv, "-setalias") == 0) {
333
8
			if (--argc < 1)
334
				goto bad;
335
8
			alias = *(++argv);
336
			trustout = 1;
337
222
		} else if (strcmp(*argv, "-certopt") == 0) {
338
			if (--argc < 1)
339
				goto bad;
340
			if (!set_cert_ex(&certflag, *(++argv)))
341
				goto bad;
342
214
		} else if (strcmp(*argv, "-nameopt") == 0) {
343
			if (--argc < 1)
344
				goto bad;
345
			if (!set_name_ex(&nmflag, *(++argv)))
346
				goto bad;
347
		}
348
214
		else if (strcmp(*argv, "-C") == 0)
349
8
			C = ++num;
350
206
		else if (strcmp(*argv, "-email") == 0)
351
8
			email = ++num;
352
198
		else if (strcmp(*argv, "-ocsp_uri") == 0)
353
8
			ocsp_uri = ++num;
354
190
		else if (strcmp(*argv, "-serial") == 0)
355
8
			serial = ++num;
356
182
		else if (strcmp(*argv, "-next_serial") == 0)
357
			next_serial = ++num;
358
182
		else if (strcmp(*argv, "-modulus") == 0)
359
8
			modulus = ++num;
360
174
		else if (strcmp(*argv, "-pubkey") == 0)
361
8
			pubkey = ++num;
362
166
		else if (strcmp(*argv, "-x509toreq") == 0)
363
			x509req = ++num;
364
166
		else if (strcmp(*argv, "-text") == 0)
365
29
			text = ++num;
366

274
		else if (strcmp(*argv, "-hash") == 0 ||
367
137
		    strcmp(*argv, "-subject_hash") == 0)
368
8
			subject_hash = ++num;
369
#ifndef OPENSSL_NO_MD5
370
129
		else if (strcmp(*argv, "-subject_hash_old") == 0)
371
8
			subject_hash_old = ++num;
372
#endif
373
121
		else if (strcmp(*argv, "-issuer_hash") == 0)
374
8
			issuer_hash = ++num;
375
#ifndef OPENSSL_NO_MD5
376
113
		else if (strcmp(*argv, "-issuer_hash_old") == 0)
377
8
			issuer_hash_old = ++num;
378
#endif
379
105
		else if (strcmp(*argv, "-subject") == 0)
380
8
			subject = ++num;
381
97
		else if (strcmp(*argv, "-issuer") == 0)
382
8
			issuer = ++num;
383
89
		else if (strcmp(*argv, "-fingerprint") == 0)
384
8
			fingerprint = ++num;
385
81
		else if (strcmp(*argv, "-dates") == 0) {
386
8
			startdate = ++num;
387
8
			enddate = ++num;
388
81
		} else if (strcmp(*argv, "-purpose") == 0)
389
8
			pprint = ++num;
390
65
		else if (strcmp(*argv, "-startdate") == 0)
391
8
			startdate = ++num;
392
57
		else if (strcmp(*argv, "-enddate") == 0)
393
8
			enddate = ++num;
394
49
		else if (strcmp(*argv, "-checkend") == 0) {
395
			if (--argc < 1)
396
				goto bad;
397
			checkoffset = strtonum(*(++argv), 0, INT_MAX, &errstr);
398
			if (errstr) {
399
				BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
400
				goto bad;
401
			}
402
			checkend = 1;
403
49
		} else if (strcmp(*argv, "-noout") == 0)
404
5
			noout = ++num;
405
44
		else if (strcmp(*argv, "-trustout") == 0)
406
			trustout = 1;
407
44
		else if (strcmp(*argv, "-clrtrust") == 0)
408
			clrtrust = ++num;
409
44
		else if (strcmp(*argv, "-clrreject") == 0)
410
			clrreject = ++num;
411
44
		else if (strcmp(*argv, "-alias") == 0)
412
			aliasout = ++num;
413
44
		else if (strcmp(*argv, "-CAcreateserial") == 0)
414
28
			CA_createserial = ++num;
415
16
		else if (strcmp(*argv, "-clrext") == 0)
416
			clrext = 1;
417
16
		else if (strcmp(*argv, "-ocspid") == 0)
418
8
			ocspid = ++num;
419
8
		else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
420
			/* ok */
421
			digest = md_alg;
422
		} else {
423
8
			BIO_printf(bio_err, "unknown option %s\n", *argv);
424
			badops = 1;
425
8
			break;
426
		}
427
479
		argc--;
428
479
		argv++;
429
	}
430
431
89
	if (badops) {
432
bad:
433
896
		for (pp = x509_usage; (*pp != NULL); pp++)
434
440
			BIO_printf(bio_err, "%s", *pp);
435
		goto end;
436
	}
437
438
81
	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
439
		BIO_printf(bio_err, "Error getting password\n");
440
		goto end;
441
	}
442
81
	if (!X509_STORE_set_default_paths(ctx)) {
443
		ERR_print_errors(bio_err);
444
		goto end;
445
	}
446
81
	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
447
		CAkeyfile = CAfile;
448
81
	} else if ((CA_flag) && (CAkeyfile == NULL)) {
449
		BIO_printf(bio_err,
450
		    "need to specify a CAkey if using the CA command\n");
451
		goto end;
452
	}
453
81
	if (extfile) {
454
		long errorline = -1;
455
		X509V3_CTX ctx2;
456
		extconf = NCONF_new(NULL);
457
		if (!NCONF_load(extconf, extfile, &errorline)) {
458
			if (errorline <= 0)
459
				BIO_printf(bio_err,
460
				    "error loading the config file '%s'\n",
461
				    extfile);
462
			else
463
				BIO_printf(bio_err,
464
				    "error on line %ld of config file '%s'\n",
465
				    errorline, extfile);
466
			goto end;
467
		}
468
		if (!extsect) {
469
			extsect = NCONF_get_string(extconf, "default",
470
			    "extensions");
471
			if (!extsect) {
472
				ERR_clear_error();
473
				extsect = "default";
474
			}
475
		}
476
		X509V3_set_ctx_test(&ctx2);
477
		X509V3_set_nconf(&ctx2, extconf);
478
		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
479
			BIO_printf(bio_err,
480
			    "Error Loading extension section %s\n",
481
			    extsect);
482
			ERR_print_errors(bio_err);
483
			goto end;
484
		}
485
	}
486
81
	if (reqfile) {
487
		EVP_PKEY *pkey;
488
		BIO *in;
489
490
28
		if (!sign_flag && !CA_flag) {
491
			BIO_printf(bio_err, "We need a private key to sign with\n");
492
			goto end;
493
		}
494
28
		in = BIO_new(BIO_s_file());
495
28
		if (in == NULL) {
496
			ERR_print_errors(bio_err);
497
			goto end;
498
		}
499
28
		if (infile == NULL)
500
			BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
501
		else {
502
28
			if (BIO_read_filename(in, infile) <= 0) {
503
				perror(infile);
504
				BIO_free(in);
505
				goto end;
506
			}
507
		}
508
28
		req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
509
28
		BIO_free(in);
510
511
28
		if (req == NULL) {
512
			ERR_print_errors(bio_err);
513
			goto end;
514
		}
515

56
		if ((req->req_info == NULL) ||
516
28
		    (req->req_info->pubkey == NULL) ||
517
28
		    (req->req_info->pubkey->public_key == NULL) ||
518
28
		    (req->req_info->pubkey->public_key->data == NULL)) {
519
			BIO_printf(bio_err, "The certificate request appears to corrupted\n");
520
			BIO_printf(bio_err, "It does not contain a public key\n");
521
			goto end;
522
		}
523
28
		if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
524
			BIO_printf(bio_err, "error unpacking public key\n");
525
			goto end;
526
		}
527
28
		i = X509_REQ_verify(req, pkey);
528
28
		EVP_PKEY_free(pkey);
529
28
		if (i < 0) {
530
			BIO_printf(bio_err, "Signature verification error\n");
531
			ERR_print_errors(bio_err);
532
			goto end;
533
		}
534
28
		if (i == 0) {
535
			BIO_printf(bio_err, "Signature did not match the certificate request\n");
536
			goto end;
537
		} else
538
28
			BIO_printf(bio_err, "Signature ok\n");
539
540
28
		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
541
542
28
		if ((x = X509_new()) == NULL)
543
			goto end;
544
545
28
		if (sno == NULL) {
546
28
			sno = ASN1_INTEGER_new();
547

56
			if (!sno || !rand_serial(NULL, sno))
548
				goto end;
549
28
			if (!X509_set_serialNumber(x, sno))
550
				goto end;
551
28
			ASN1_INTEGER_free(sno);
552
			sno = NULL;
553
28
		} else if (!X509_set_serialNumber(x, sno))
554
			goto end;
555
556
28
		if (!X509_set_issuer_name(x, req->req_info->subject))
557
			goto end;
558
28
		if (!X509_set_subject_name(x, req->req_info->subject))
559
			goto end;
560
561
28
		X509_gmtime_adj(X509_get_notBefore(x), 0);
562
28
		X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
563
564
28
		pkey = X509_REQ_get_pubkey(req);
565
28
		X509_set_pubkey(x, pkey);
566
28
		EVP_PKEY_free(pkey);
567
28
	} else
568
53
		x = load_cert(bio_err, infile, informat, NULL, "Certificate");
569
570
81
	if (x == NULL)
571
		goto end;
572
81
	if (CA_flag) {
573
28
		xca = load_cert(bio_err, CAfile, CAformat, NULL, "CA Certificate");
574
28
		if (xca == NULL)
575
			goto end;
576
	}
577
81
	if (!noout || text || next_serial) {
578
81
		OBJ_create("2.99999.3",
579
		    "SET.ex3", "SET x509v3 extension 3");
580
581
81
		out = BIO_new(BIO_s_file());
582
81
		if (out == NULL) {
583
			ERR_print_errors(bio_err);
584
			goto end;
585
		}
586
81
		if (outfile == NULL) {
587
29
			BIO_set_fp(out, stdout, BIO_NOCLOSE);
588
29
		} else {
589
52
			if (BIO_write_filename(out, outfile) <= 0) {
590
				perror(outfile);
591
				goto end;
592
			}
593
		}
594
	}
595
81
	if (alias)
596
8
		X509_alias_set1(x, (unsigned char *) alias, -1);
597
598
81
	if (clrtrust)
599
		X509_trust_clear(x);
600
81
	if (clrreject)
601
		X509_reject_clear(x);
602
603
81
	if (trust) {
604
32
		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
605
8
			objtmp = sk_ASN1_OBJECT_value(trust, i);
606
8
			X509_add1_trust_object(x, objtmp);
607
		}
608
	}
609
81
	if (reject) {
610
		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
611
			objtmp = sk_ASN1_OBJECT_value(reject, i);
612
			X509_add1_reject_object(x, objtmp);
613
		}
614
	}
615
81
	if (num) {
616
646
		for (i = 1; i <= num; i++) {
617
250
			if (issuer == i) {
618
8
				print_name(STDout, "issuer= ",
619
8
				    X509_get_issuer_name(x), nmflag);
620
250
			} else if (subject == i) {
621
8
				print_name(STDout, "subject= ",
622
8
				    X509_get_subject_name(x), nmflag);
623
242
			} else if (serial == i) {
624
8
				BIO_printf(STDout, "serial=");
625
8
				i2a_ASN1_INTEGER(STDout,
626
8
				    X509_get_serialNumber(x));
627
8
				BIO_printf(STDout, "\n");
628
234
			} else if (next_serial == i) {
629
				BIGNUM *bnser;
630
				ASN1_INTEGER *ser;
631
				ser = X509_get_serialNumber(x);
632
				bnser = ASN1_INTEGER_to_BN(ser, NULL);
633
				if (!bnser)
634
					goto end;
635
				if (!BN_add_word(bnser, 1))
636
					goto end;
637
				ser = BN_to_ASN1_INTEGER(bnser, NULL);
638
				if (!ser)
639
					goto end;
640
				BN_free(bnser);
641
				i2a_ASN1_INTEGER(out, ser);
642
				ASN1_INTEGER_free(ser);
643
				BIO_puts(out, "\n");
644

444
			} else if ((email == i) || (ocsp_uri == i)) {
645
				int j;
646
				STACK_OF(OPENSSL_STRING) *emlst;
647
16
				if (email == i)
648
8
					emlst = X509_get1_email(x);
649
				else
650
8
					emlst = X509_get1_ocsp(x);
651
32
				for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
652
					BIO_printf(STDout, "%s\n",
653
					    sk_OPENSSL_STRING_value(emlst, j));
654
16
				X509_email_free(emlst);
655
226
			} else if (aliasout == i) {
656
				unsigned char *alstr;
657
				alstr = X509_alias_get0(x, NULL);
658
				if (alstr)
659
					BIO_printf(STDout, "%s\n", alstr);
660
				else
661
					BIO_puts(STDout, "<No Alias>\n");
662
210
			} else if (subject_hash == i) {
663
8
				BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
664
8
			}
665
#ifndef OPENSSL_NO_MD5
666
202
			else if (subject_hash_old == i) {
667
8
				BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x));
668
8
			}
669
#endif
670
194
			else if (issuer_hash == i) {
671
8
				BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
672
8
			}
673
#ifndef OPENSSL_NO_MD5
674
186
			else if (issuer_hash_old == i) {
675
8
				BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x));
676
8
			}
677
#endif
678
178
			else if (pprint == i) {
679
				X509_PURPOSE *ptmp;
680
				int j;
681
8
				BIO_printf(STDout, "Certificate purposes:\n");
682
160
				for (j = 0; j < X509_PURPOSE_get_count(); j++) {
683
72
					ptmp = X509_PURPOSE_get0(j);
684
72
					purpose_print(STDout, x, ptmp);
685
				}
686
178
			} else if (modulus == i) {
687
				EVP_PKEY *pkey;
688
689
8
				pkey = X509_get_pubkey(x);
690
8
				if (pkey == NULL) {
691
					BIO_printf(bio_err, "Modulus=unavailable\n");
692
					ERR_print_errors(bio_err);
693
					goto end;
694
				}
695
8
				BIO_printf(STDout, "Modulus=");
696
8
				if (pkey->type == EVP_PKEY_RSA)
697
8
					BN_print(STDout, pkey->pkey.rsa->n);
698
				else
699
						if (pkey->type == EVP_PKEY_DSA)
700
							BN_print(STDout, pkey->pkey.dsa->pub_key);
701
				else
702
						BIO_printf(STDout, "Wrong Algorithm type");
703
8
				BIO_printf(STDout, "\n");
704
8
				EVP_PKEY_free(pkey);
705

170
			} else if (pubkey == i) {
706
				EVP_PKEY *pkey;
707
708
8
				pkey = X509_get_pubkey(x);
709
8
				if (pkey == NULL) {
710
					BIO_printf(bio_err, "Error getting public key\n");
711
					ERR_print_errors(bio_err);
712
					goto end;
713
				}
714
8
				PEM_write_bio_PUBKEY(STDout, pkey);
715
8
				EVP_PKEY_free(pkey);
716

162
			} else if (C == i) {
717
8
				unsigned char *d;
718
				char *m;
719
				int y, z;
720
721
16
				X509_NAME_oneline(X509_get_subject_name(x),
722
8
				    buf, sizeof buf);
723
8
				BIO_printf(STDout, "/* subject:%s */\n", buf);
724
8
				m = X509_NAME_oneline(
725
8
				    X509_get_issuer_name(x), buf,
726
				    sizeof buf);
727
8
				BIO_printf(STDout, "/* issuer :%s */\n", buf);
728
729
8
				z = i2d_X509(x, NULL);
730
8
				m = malloc(z);
731
8
				if (m == NULL) {
732
					BIO_printf(bio_err, "out of mem\n");
733
					goto end;
734
				}
735
736
8
				d = (unsigned char *) m;
737
8
				z = i2d_X509_NAME(X509_get_subject_name(x), &d);
738
8
				BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", z);
739
8
				d = (unsigned char *) m;
740
1536
				for (y = 0; y < z; y++) {
741
760
					BIO_printf(STDout, "0x%02X,", d[y]);
742
760
					if ((y & 0x0f) == 0x0f)
743
40
						BIO_printf(STDout, "\n");
744
				}
745
8
				if (y % 16 != 0)
746
8
					BIO_printf(STDout, "\n");
747
8
				BIO_printf(STDout, "};\n");
748
749
8
				z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
750
8
				BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
751
8
				d = (unsigned char *) m;
752
4720
				for (y = 0; y < z; y++) {
753
2352
					BIO_printf(STDout, "0x%02X,", d[y]);
754
2352
					if ((y & 0x0f) == 0x0f)
755
144
						BIO_printf(STDout, "\n");
756
				}
757
8
				if (y % 16 != 0)
758
8
					BIO_printf(STDout, "\n");
759
8
				BIO_printf(STDout, "};\n");
760
761
8
				z = i2d_X509(x, &d);
762
8
				BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", z);
763
8
				d = (unsigned char *) m;
764
13056
				for (y = 0; y < z; y++) {
765
6520
					BIO_printf(STDout, "0x%02X,", d[y]);
766
6520
					if ((y & 0x0f) == 0x0f)
767
400
						BIO_printf(STDout, "\n");
768
				}
769
8
				if (y % 16 != 0)
770
8
					BIO_printf(STDout, "\n");
771
8
				BIO_printf(STDout, "};\n");
772
773
8
				free(m);
774

194
			} else if (text == i) {
775
29
				X509_print_ex(STDout, x, nmflag, certflag);
776
146
			} else if (startdate == i) {
777
8
				BIO_puts(STDout, "notBefore=");
778
8
				ASN1_TIME_print(STDout, X509_get_notBefore(x));
779
8
				BIO_puts(STDout, "\n");
780
117
			} else if (enddate == i) {
781
8
				BIO_puts(STDout, "notAfter=");
782
8
				ASN1_TIME_print(STDout, X509_get_notAfter(x));
783
8
				BIO_puts(STDout, "\n");
784
109
			} else if (fingerprint == i) {
785
				int j;
786
8
				unsigned int n;
787
8
				unsigned char md[EVP_MAX_MD_SIZE];
788
				const EVP_MD *fdig = digest;
789
790
8
				if (!fdig)
791
8
					fdig = EVP_sha1();
792
793
8
				if (!X509_digest(x, fdig, md, &n)) {
794
					BIO_printf(bio_err, "out of memory\n");
795
					goto end;
796
				}
797
8
				BIO_printf(STDout, "%s Fingerprint=",
798
8
				    OBJ_nid2sn(EVP_MD_type(fdig)));
799
336
				for (j = 0; j < (int) n; j++) {
800
320
					BIO_printf(STDout, "%02X%c", md[j],
801
160
					    (j + 1 == (int)n) ? '\n' : ':');
802
				}
803
80
			}
804
			/* should be in the library */
805
93
			else if ((sign_flag == i) && (x509req == 0)) {
806
8
				BIO_printf(bio_err, "Getting Private key\n");
807
8
				if (Upkey == NULL) {
808
16
					Upkey = load_key(bio_err,
809
					    keyfile, keyformat, 0,
810
8
					    passin, "Private key");
811
8
					if (Upkey == NULL)
812
						goto end;
813
				}
814
8
				if (!sign(x, Upkey, days, clrext, digest,
815
				    extconf, extsect))
816
					goto end;
817
85
			} else if (CA_flag == i) {
818
28
				BIO_printf(bio_err, "Getting CA Private Key\n");
819
28
				if (CAkeyfile != NULL) {
820
56
					CApkey = load_key(bio_err,
821
					    CAkeyfile, CAkeyformat,
822
28
					    0, passin, "CA Private Key");
823
28
					if (CApkey == NULL)
824
						goto end;
825
				}
826
28
				if (!x509_certify(ctx, CAfile, digest, x, xca,
827
				    CApkey, sigopts,
828
				    CAserial, CA_createserial, days, clrext,
829
				    extconf, extsect, sno))
830
					goto end;
831
57
			} else if (x509req == i) {
832
				EVP_PKEY *pk;
833
834
				BIO_printf(bio_err, "Getting request Private Key\n");
835
				if (keyfile == NULL) {
836
					BIO_printf(bio_err, "no request key file specified\n");
837
					goto end;
838
				} else {
839
					pk = load_key(bio_err,
840
					    keyfile, keyformat, 0,
841
					    passin, "request key");
842
					if (pk == NULL)
843
						goto end;
844
				}
845
846
				BIO_printf(bio_err, "Generating certificate request\n");
847
848
				rq = X509_to_X509_REQ(x, pk, digest);
849
				EVP_PKEY_free(pk);
850
				if (rq == NULL) {
851
					ERR_print_errors(bio_err);
852
					goto end;
853
				}
854
				if (!noout) {
855
					X509_REQ_print(out, rq);
856
					PEM_write_bio_X509_REQ(out, rq);
857
				}
858
				noout = 1;
859

57
			} else if (ocspid == i) {
860
8
				X509_ocspid_print(out, x);
861
8
			}
862
		}
863
	}
864
81
	if (checkend) {
865
		time_t tcheck = time(NULL) + checkoffset;
866
867
		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
868
			BIO_printf(out, "Certificate will expire\n");
869
			ret = 1;
870
		} else {
871
			BIO_printf(out, "Certificate will not expire\n");
872
			ret = 0;
873
		}
874
		goto end;
875
	}
876
81
	if (noout) {
877
		ret = 0;
878
5
		goto end;
879
	}
880
76
	if (outformat == FORMAT_ASN1)
881
		i = i2d_X509_bio(out, x);
882
76
	else if (outformat == FORMAT_PEM) {
883
76
		if (trustout)
884
8
			i = PEM_write_bio_X509_AUX(out, x);
885
		else
886
68
			i = PEM_write_bio_X509(out, x);
887
	} else if (outformat == FORMAT_NETSCAPE) {
888
		NETSCAPE_X509 nx;
889
		ASN1_OCTET_STRING hdr;
890
891
		hdr.data = (unsigned char *) NETSCAPE_CERT_HDR;
892
		hdr.length = strlen(NETSCAPE_CERT_HDR);
893
		nx.header = &hdr;
894
		nx.cert = x;
895
896
		i = ASN1_item_i2d_bio(&NETSCAPE_X509_it, out, &nx);
897
	} else {
898
		BIO_printf(bio_err, "bad output format specified for outfile\n");
899
		goto end;
900
	}
901
76
	if (!i) {
902
		BIO_printf(bio_err, "unable to write certificate\n");
903
		ERR_print_errors(bio_err);
904
		goto end;
905
	}
906
76
	ret = 0;
907
908
end:
909
89
	OBJ_cleanup();
910
89
	NCONF_free(extconf);
911
89
	BIO_free_all(out);
912
89
	BIO_free_all(STDout);
913
89
	X509_STORE_free(ctx);
914
89
	X509_REQ_free(req);
915
89
	X509_free(x);
916
89
	X509_free(xca);
917
89
	EVP_PKEY_free(Upkey);
918
89
	EVP_PKEY_free(CApkey);
919
89
	if (sigopts)
920
		sk_OPENSSL_STRING_free(sigopts);
921
89
	X509_REQ_free(rq);
922
89
	ASN1_INTEGER_free(sno);
923
89
	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
924
89
	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
925
89
	free(passin);
926
927
89
	return (ret);
928
89
}
929
930
static ASN1_INTEGER *
931
x509_load_serial(char *CAfile, char *serialfile, int create)
932
{
933
	char *buf = NULL, *p;
934
56
	ASN1_INTEGER *bs = NULL;
935
	BIGNUM *serial = NULL;
936
	size_t len;
937
938
84
	len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
939
28
	    (strlen(serialfile))) + 1;
940
28
	buf = malloc(len);
941
28
	if (buf == NULL) {
942
		BIO_printf(bio_err, "out of mem\n");
943
		goto end;
944
	}
945
28
	if (serialfile == NULL) {
946
28
		strlcpy(buf, CAfile, len);
947
568
		for (p = buf; *p; p++)
948
284
			if (*p == '.') {
949
28
				*p = '\0';
950
28
				break;
951
			}
952
28
		strlcat(buf, POSTFIX, len);
953
28
	} else
954
		strlcpy(buf, serialfile, len);
955
956
28
	serial = load_serial(buf, create, NULL);
957
28
	if (serial == NULL)
958
		goto end;
959
960
28
	if (!BN_add_word(serial, 1)) {
961
		BIO_printf(bio_err, "add_word failure\n");
962
		goto end;
963
	}
964
28
	if (!save_serial(buf, NULL, serial, &bs))
965
		goto end;
966
967
end:
968
28
	free(buf);
969
28
	BN_free(serial);
970
971
56
	return bs;
972
28
}
973
974
static int
975
x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
976
    X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
977
    char *serialfile, int create, int days, int clrext, CONF *conf,
978
    char *section, ASN1_INTEGER *sno)
979
{
980
	int ret = 0;
981
	ASN1_INTEGER *bs = NULL;
982
56
	X509_STORE_CTX xsc;
983
	EVP_PKEY *upkey;
984
985
28
	upkey = X509_get_pubkey(xca);
986
28
	EVP_PKEY_copy_parameters(upkey, pkey);
987
28
	EVP_PKEY_free(upkey);
988
989
28
	if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
990
		BIO_printf(bio_err, "Error initialising X509 store\n");
991
		goto end;
992
	}
993
28
	if (sno)
994
		bs = sno;
995
28
	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
996
		goto end;
997
998
/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/
999
1000
	/*
1001
	 * NOTE: this certificate can/should be self signed, unless it was a
1002
	 * certificate request in which case it is not.
1003
	 */
1004
28
	X509_STORE_CTX_set_cert(&xsc, x);
1005
28
	X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1006

28
	if (!reqfile && X509_verify_cert(&xsc) <= 0)
1007
		goto end;
1008
1009
28
	if (!X509_check_private_key(xca, pkey)) {
1010
		BIO_printf(bio_err, "CA certificate and CA private key do not match\n");
1011
		goto end;
1012
	}
1013
28
	if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1014
		goto end;
1015
28
	if (!X509_set_serialNumber(x, bs))
1016
		goto end;
1017
1018
28
	if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1019
		goto end;
1020
1021
	/* hardwired expired */
1022
28
	if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1023
		goto end;
1024
1025
28
	if (clrext) {
1026
		while (X509_get_ext_count(x) > 0)
1027
			X509_delete_ext(x, 0);
1028
	}
1029
28
	if (conf) {
1030
		X509V3_CTX ctx2;
1031
		X509_set_version(x, 2);	/* version 3 certificate */
1032
		X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1033
		X509V3_set_nconf(&ctx2, conf);
1034
		if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1035
			goto end;
1036
	}
1037
28
	if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1038
		goto end;
1039
28
	ret = 1;
1040
end:
1041
28
	X509_STORE_CTX_cleanup(&xsc);
1042
28
	if (!ret)
1043
		ERR_print_errors(bio_err);
1044
28
	if (!sno)
1045
28
		ASN1_INTEGER_free(bs);
1046
28
	return ret;
1047
28
}
1048
1049
static int
1050
callb(int ok, X509_STORE_CTX *ctx)
1051
{
1052
	int err;
1053
	X509 *err_cert;
1054
1055
	/*
1056
	 * it is ok to use a self signed certificate This case will catch
1057
	 * both the initial ok == 0 and the final ok == 1 calls to this
1058
	 * function
1059
	 */
1060
	err = X509_STORE_CTX_get_error(ctx);
1061
	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1062
		return 1;
1063
1064
	/*
1065
	 * BAD we should have gotten an error.  Normally if everything worked
1066
	 * X509_STORE_CTX_get_error(ctx) will still be set to
1067
	 * DEPTH_ZERO_SELF_....
1068
	 */
1069
	if (ok) {
1070
		BIO_printf(bio_err, "error with certificate to be certified - should be self signed\n");
1071
		return 0;
1072
	} else {
1073
		err_cert = X509_STORE_CTX_get_current_cert(ctx);
1074
		print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1075
		BIO_printf(bio_err, "error with certificate - error %d at depth %d\n%s\n",
1076
		    err, X509_STORE_CTX_get_error_depth(ctx),
1077
		    X509_verify_cert_error_string(err));
1078
		return 1;
1079
	}
1080
}
1081
1082
/* self sign */
1083
static int
1084
sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1085
    CONF *conf, char *section)
1086
{
1087
1088
	EVP_PKEY *pktmp;
1089
1090
16
	pktmp = X509_get_pubkey(x);
1091
8
	EVP_PKEY_copy_parameters(pktmp, pkey);
1092
8
	EVP_PKEY_save_parameters(pktmp, 1);
1093
8
	EVP_PKEY_free(pktmp);
1094
1095
8
	if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1096
		goto err;
1097
8
	if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1098
		goto err;
1099
1100
	/* Lets just make it 12:00am GMT, Jan 1 1970 */
1101
	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
1102
	/* 28 days to be certified */
1103
1104
24
	if (X509_gmtime_adj(X509_get_notAfter(x),
1105
16
	    (long) 60 * 60 * 24 * days) == NULL)
1106
		goto err;
1107
1108
8
	if (!X509_set_pubkey(x, pkey))
1109
		goto err;
1110
8
	if (clrext) {
1111
		while (X509_get_ext_count(x) > 0)
1112
			X509_delete_ext(x, 0);
1113
	}
1114
8
	if (conf) {
1115
		X509V3_CTX ctx;
1116
		X509_set_version(x, 2);	/* version 3 certificate */
1117
		X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1118
		X509V3_set_nconf(&ctx, conf);
1119
		if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1120
			goto err;
1121
	}
1122
8
	if (!X509_sign(x, pkey, digest))
1123
		goto err;
1124
8
	return 1;
1125
1126
err:
1127
	ERR_print_errors(bio_err);
1128
	return 0;
1129
8
}
1130
1131
static int
1132
purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1133
{
1134
	int id, i, idret;
1135
	char *pname;
1136
1137
144
	id = X509_PURPOSE_get_id(pt);
1138
72
	pname = X509_PURPOSE_get0_name(pt);
1139
432
	for (i = 0; i < 2; i++) {
1140
144
		idret = X509_check_purpose(cert, id, i);
1141
144
		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1142
144
		if (idret == 1)
1143
72
			BIO_printf(bio, "Yes\n");
1144
72
		else if (idret == 0)
1145
8
			BIO_printf(bio, "No\n");
1146
		else
1147
64
			BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1148
	}
1149
72
	return 1;
1150
}