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