Line data Source code
1 : /* crypto/asn1/t_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 "cryptlib.h"
61 : #include <openssl/buffer.h>
62 : #include <openssl/bn.h>
63 : #ifndef OPENSSL_NO_RSA
64 : # include <openssl/rsa.h>
65 : #endif
66 : #ifndef OPENSSL_NO_DSA
67 : # include <openssl/dsa.h>
68 : #endif
69 : #ifndef OPENSSL_NO_EC
70 : # include <openssl/ec.h>
71 : #endif
72 : #include <openssl/objects.h>
73 : #include <openssl/x509.h>
74 : #include <openssl/x509v3.h>
75 : #include "asn1_locl.h"
76 :
77 : #ifndef OPENSSL_NO_FP_API
78 0 : int X509_print_fp(FILE *fp, X509 *x)
79 : {
80 0 : return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
81 : }
82 :
83 0 : int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
84 : unsigned long cflag)
85 : {
86 : BIO *b;
87 : int ret;
88 :
89 0 : if ((b = BIO_new(BIO_s_file())) == NULL) {
90 0 : X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB);
91 0 : return (0);
92 : }
93 0 : BIO_set_fp(b, fp, BIO_NOCLOSE);
94 0 : ret = X509_print_ex(b, x, nmflag, cflag);
95 0 : BIO_free(b);
96 0 : return (ret);
97 : }
98 : #endif
99 :
100 0 : int X509_print(BIO *bp, X509 *x)
101 : {
102 0 : return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
103 : }
104 :
105 0 : int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
106 : unsigned long cflag)
107 : {
108 : long l;
109 : int ret = 0, i;
110 : char *m = NULL, mlch = ' ';
111 : int nmindent = 0;
112 : X509_CINF *ci;
113 : ASN1_INTEGER *bs;
114 : EVP_PKEY *pkey = NULL;
115 : const char *neg;
116 :
117 0 : if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
118 : mlch = '\n';
119 : nmindent = 12;
120 : }
121 :
122 0 : if (nmflags == X509_FLAG_COMPAT)
123 : nmindent = 16;
124 :
125 0 : ci = x->cert_info;
126 0 : if (!(cflag & X509_FLAG_NO_HEADER)) {
127 0 : if (BIO_write(bp, "Certificate:\n", 13) <= 0)
128 : goto err;
129 0 : if (BIO_write(bp, " Data:\n", 10) <= 0)
130 : goto err;
131 : }
132 0 : if (!(cflag & X509_FLAG_NO_VERSION)) {
133 0 : l = X509_get_version(x);
134 0 : if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0)
135 : goto err;
136 : }
137 0 : if (!(cflag & X509_FLAG_NO_SERIAL)) {
138 :
139 0 : if (BIO_write(bp, " Serial Number:", 22) <= 0)
140 : goto err;
141 :
142 0 : bs = X509_get_serialNumber(x);
143 0 : if (bs->length <= (int)sizeof(long)) {
144 0 : l = ASN1_INTEGER_get(bs);
145 0 : if (bs->type == V_ASN1_NEG_INTEGER) {
146 0 : l = -l;
147 : neg = "-";
148 : } else
149 : neg = "";
150 0 : if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0)
151 : goto err;
152 : } else {
153 0 : neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
154 0 : if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
155 : goto err;
156 :
157 0 : for (i = 0; i < bs->length; i++) {
158 0 : if (BIO_printf(bp, "%02x%c", bs->data[i],
159 0 : ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
160 : goto err;
161 : }
162 : }
163 :
164 : }
165 :
166 0 : if (!(cflag & X509_FLAG_NO_SIGNAME)) {
167 0 : if (X509_signature_print(bp, ci->signature, NULL) <= 0)
168 : goto err;
169 : #if 0
170 : if (BIO_printf(bp, "%8sSignature Algorithm: ", "") <= 0)
171 : goto err;
172 : if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
173 : goto err;
174 : if (BIO_puts(bp, "\n") <= 0)
175 : goto err;
176 : #endif
177 : }
178 :
179 0 : if (!(cflag & X509_FLAG_NO_ISSUER)) {
180 0 : if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
181 : goto err;
182 0 : if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
183 : < 0)
184 : goto err;
185 0 : if (BIO_write(bp, "\n", 1) <= 0)
186 : goto err;
187 : }
188 0 : if (!(cflag & X509_FLAG_NO_VALIDITY)) {
189 0 : if (BIO_write(bp, " Validity\n", 17) <= 0)
190 : goto err;
191 0 : if (BIO_write(bp, " Not Before: ", 24) <= 0)
192 : goto err;
193 0 : if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
194 : goto err;
195 0 : if (BIO_write(bp, "\n Not After : ", 25) <= 0)
196 : goto err;
197 0 : if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
198 : goto err;
199 0 : if (BIO_write(bp, "\n", 1) <= 0)
200 : goto err;
201 : }
202 0 : if (!(cflag & X509_FLAG_NO_SUBJECT)) {
203 0 : if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
204 : goto err;
205 0 : if (X509_NAME_print_ex
206 0 : (bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
207 : goto err;
208 0 : if (BIO_write(bp, "\n", 1) <= 0)
209 : goto err;
210 : }
211 0 : if (!(cflag & X509_FLAG_NO_PUBKEY)) {
212 0 : if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
213 : goto err;
214 0 : if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
215 : goto err;
216 0 : if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
217 : goto err;
218 0 : if (BIO_puts(bp, "\n") <= 0)
219 : goto err;
220 :
221 0 : pkey = X509_get_pubkey(x);
222 0 : if (pkey == NULL) {
223 0 : BIO_printf(bp, "%12sUnable to load Public Key\n", "");
224 0 : ERR_print_errors(bp);
225 : } else {
226 0 : EVP_PKEY_print_public(bp, pkey, 16, NULL);
227 0 : EVP_PKEY_free(pkey);
228 : }
229 : }
230 :
231 0 : if (!(cflag & X509_FLAG_NO_IDS)) {
232 0 : if (ci->issuerUID) {
233 0 : if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0)
234 : goto err;
235 0 : if (!X509_signature_dump(bp, ci->issuerUID, 12))
236 : goto err;
237 : }
238 0 : if (ci->subjectUID) {
239 0 : if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0)
240 : goto err;
241 0 : if (!X509_signature_dump(bp, ci->subjectUID, 12))
242 : goto err;
243 : }
244 : }
245 :
246 0 : if (!(cflag & X509_FLAG_NO_EXTENSIONS))
247 0 : X509V3_extensions_print(bp, "X509v3 extensions",
248 : ci->extensions, cflag, 8);
249 :
250 0 : if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
251 0 : if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
252 : goto err;
253 : }
254 0 : if (!(cflag & X509_FLAG_NO_AUX)) {
255 0 : if (!X509_CERT_AUX_print(bp, x->aux, 0))
256 : goto err;
257 : }
258 : ret = 1;
259 : err:
260 : if (m != NULL)
261 : OPENSSL_free(m);
262 0 : return (ret);
263 : }
264 :
265 0 : int X509_ocspid_print(BIO *bp, X509 *x)
266 : {
267 : unsigned char *der = NULL;
268 : unsigned char *dertmp;
269 : int derlen;
270 : int i;
271 : unsigned char SHA1md[SHA_DIGEST_LENGTH];
272 :
273 : /*
274 : * display the hash of the subject as it would appear in OCSP requests
275 : */
276 0 : if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
277 : goto err;
278 0 : derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
279 0 : if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL)
280 : goto err;
281 0 : i2d_X509_NAME(x->cert_info->subject, &dertmp);
282 :
283 0 : if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
284 : goto err;
285 0 : for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
286 0 : if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
287 : goto err;
288 : }
289 0 : OPENSSL_free(der);
290 : der = NULL;
291 :
292 : /*
293 : * display the hash of the public key as it would appear in OCSP requests
294 : */
295 0 : if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0)
296 : goto err;
297 :
298 0 : if (!EVP_Digest(x->cert_info->key->public_key->data,
299 0 : x->cert_info->key->public_key->length,
300 : SHA1md, NULL, EVP_sha1(), NULL))
301 : goto err;
302 0 : for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
303 0 : if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
304 : goto err;
305 : }
306 0 : BIO_printf(bp, "\n");
307 :
308 0 : return (1);
309 : err:
310 0 : if (der != NULL)
311 0 : OPENSSL_free(der);
312 : return (0);
313 : }
314 :
315 0 : int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
316 : {
317 : const unsigned char *s;
318 : int i, n;
319 :
320 0 : n = sig->length;
321 0 : s = sig->data;
322 0 : for (i = 0; i < n; i++) {
323 0 : if ((i % 18) == 0) {
324 0 : if (BIO_write(bp, "\n", 1) <= 0)
325 : return 0;
326 0 : if (BIO_indent(bp, indent, indent) <= 0)
327 : return 0;
328 : }
329 0 : if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0)
330 : return 0;
331 : }
332 0 : if (BIO_write(bp, "\n", 1) != 1)
333 : return 0;
334 :
335 0 : return 1;
336 : }
337 :
338 0 : int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
339 : {
340 : int sig_nid;
341 0 : if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
342 : return 0;
343 0 : if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
344 : return 0;
345 :
346 0 : sig_nid = OBJ_obj2nid(sigalg->algorithm);
347 0 : if (sig_nid != NID_undef) {
348 : int pkey_nid, dig_nid;
349 : const EVP_PKEY_ASN1_METHOD *ameth;
350 0 : if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
351 0 : ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
352 0 : if (ameth && ameth->sig_print)
353 0 : return ameth->sig_print(bp, sigalg, sig, 9, 0);
354 : }
355 : }
356 0 : if (sig)
357 0 : return X509_signature_dump(bp, sig, 9);
358 0 : else if (BIO_puts(bp, "\n") <= 0)
359 : return 0;
360 0 : return 1;
361 : }
362 :
363 0 : int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
364 : {
365 : int i, n;
366 : char buf[80];
367 : const char *p;
368 :
369 0 : if (v == NULL)
370 : return (0);
371 : n = 0;
372 0 : p = (const char *)v->data;
373 0 : for (i = 0; i < v->length; i++) {
374 0 : if ((p[i] > '~') || ((p[i] < ' ') &&
375 0 : (p[i] != '\n') && (p[i] != '\r')))
376 0 : buf[n] = '.';
377 : else
378 0 : buf[n] = p[i];
379 0 : n++;
380 0 : if (n >= 80) {
381 0 : if (BIO_write(bp, buf, n) <= 0)
382 : return (0);
383 : n = 0;
384 : }
385 : }
386 0 : if (n > 0)
387 0 : if (BIO_write(bp, buf, n) <= 0)
388 : return (0);
389 : return (1);
390 : }
391 :
392 0 : int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
393 : {
394 0 : if (tm->type == V_ASN1_UTCTIME)
395 0 : return ASN1_UTCTIME_print(bp, tm);
396 0 : if (tm->type == V_ASN1_GENERALIZEDTIME)
397 0 : return ASN1_GENERALIZEDTIME_print(bp, tm);
398 0 : BIO_write(bp, "Bad time value", 14);
399 0 : return (0);
400 : }
401 :
402 : static const char *mon[12] = {
403 : "Jan", "Feb", "Mar", "Apr", "May", "Jun",
404 : "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
405 : };
406 :
407 0 : int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
408 : {
409 : char *v;
410 : int gmt = 0;
411 : int i;
412 : int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
413 : char *f = NULL;
414 : int f_len = 0;
415 :
416 0 : i = tm->length;
417 0 : v = (char *)tm->data;
418 :
419 0 : if (i < 12)
420 : goto err;
421 0 : if (v[i - 1] == 'Z')
422 : gmt = 1;
423 0 : for (i = 0; i < 12; i++)
424 0 : if ((v[i] > '9') || (v[i] < '0'))
425 : goto err;
426 0 : y = (v[0] - '0') * 1000 + (v[1] - '0') * 100
427 0 : + (v[2] - '0') * 10 + (v[3] - '0');
428 0 : M = (v[4] - '0') * 10 + (v[5] - '0');
429 0 : if ((M > 12) || (M < 1))
430 : goto err;
431 0 : d = (v[6] - '0') * 10 + (v[7] - '0');
432 0 : h = (v[8] - '0') * 10 + (v[9] - '0');
433 0 : m = (v[10] - '0') * 10 + (v[11] - '0');
434 0 : if (tm->length >= 14 &&
435 0 : (v[12] >= '0') && (v[12] <= '9') &&
436 0 : (v[13] >= '0') && (v[13] <= '9')) {
437 0 : s = (v[12] - '0') * 10 + (v[13] - '0');
438 : /* Check for fractions of seconds. */
439 0 : if (tm->length >= 15 && v[14] == '.') {
440 : int l = tm->length;
441 0 : f = &v[14]; /* The decimal point. */
442 : f_len = 1;
443 0 : while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
444 0 : ++f_len;
445 : }
446 : }
447 :
448 0 : if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
449 0 : mon[M - 1], d, h, m, s, f_len, f, y,
450 : (gmt) ? " GMT" : "") <= 0)
451 : return (0);
452 : else
453 0 : return (1);
454 : err:
455 0 : BIO_write(bp, "Bad time value", 14);
456 0 : return (0);
457 : }
458 :
459 0 : int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
460 : {
461 : const char *v;
462 : int gmt = 0;
463 : int i;
464 : int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
465 :
466 0 : i = tm->length;
467 0 : v = (const char *)tm->data;
468 :
469 0 : if (i < 10)
470 : goto err;
471 0 : if (v[i - 1] == 'Z')
472 : gmt = 1;
473 0 : for (i = 0; i < 10; i++)
474 0 : if ((v[i] > '9') || (v[i] < '0'))
475 : goto err;
476 0 : y = (v[0] - '0') * 10 + (v[1] - '0');
477 0 : if (y < 50)
478 0 : y += 100;
479 0 : M = (v[2] - '0') * 10 + (v[3] - '0');
480 0 : if ((M > 12) || (M < 1))
481 : goto err;
482 0 : d = (v[4] - '0') * 10 + (v[5] - '0');
483 0 : h = (v[6] - '0') * 10 + (v[7] - '0');
484 0 : m = (v[8] - '0') * 10 + (v[9] - '0');
485 0 : if (tm->length >= 12 &&
486 0 : (v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
487 0 : s = (v[10] - '0') * 10 + (v[11] - '0');
488 :
489 0 : if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
490 0 : mon[M - 1], d, h, m, s, y + 1900,
491 : (gmt) ? " GMT" : "") <= 0)
492 : return (0);
493 : else
494 0 : return (1);
495 : err:
496 0 : BIO_write(bp, "Bad time value", 14);
497 0 : return (0);
498 : }
499 :
500 0 : int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
501 : {
502 : char *s, *c, *b;
503 : int ret = 0, l, i;
504 :
505 : l = 80 - 2 - obase;
506 :
507 0 : b = X509_NAME_oneline(name, NULL, 0);
508 0 : if (!b)
509 : return 0;
510 0 : if (!*b) {
511 0 : OPENSSL_free(b);
512 0 : return 1;
513 : }
514 0 : s = b + 1; /* skip the first slash */
515 :
516 : c = s;
517 : for (;;) {
518 : #ifndef CHARSET_EBCDIC
519 0 : if (((*s == '/') &&
520 0 : ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
521 : ((s[2] >= 'A')
522 0 : && (s[2] <= 'Z')
523 0 : && (s[3] == '='))
524 0 : ))) || (*s == '\0'))
525 : #else
526 : if (((*s == '/') &&
527 : (isupper(s[1]) && ((s[2] == '=') ||
528 : (isupper(s[2]) && (s[3] == '='))
529 : ))) || (*s == '\0'))
530 : #endif
531 : {
532 0 : i = s - c;
533 0 : if (BIO_write(bp, c, i) != i)
534 : goto err;
535 0 : c = s + 1; /* skip following slash */
536 0 : if (*s != '\0') {
537 0 : if (BIO_write(bp, ", ", 2) != 2)
538 : goto err;
539 : }
540 : l--;
541 : }
542 0 : if (*s == '\0')
543 : break;
544 0 : s++;
545 : l--;
546 0 : }
547 :
548 : ret = 1;
549 : if (0) {
550 : err:
551 0 : X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB);
552 : }
553 0 : OPENSSL_free(b);
554 0 : return (ret);
555 : }
|