1 /*
2 * Copyright (C) 2007-2016 Free Software Foundation, Inc.
3 * Copyright (C) 2015-2017 Red Hat, Inc.
4 *
5 * Author: Simon Josefsson, Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 /* Functions for printing X.509 Certificate structures
25 */
26
27 #include "gnutls_int.h"
28 #include <common.h>
29 #include <x509.h>
30 #include <x509_int.h>
31 #include <num.h>
32 #include "errors.h"
33 #include "hello_ext.h"
34 #include "ip.h"
35
36 #define addf _gnutls_buffer_append_printf
37 #define adds _gnutls_buffer_append_str
38
39 #define NON_NULL(x) (((x)!=NULL)?((char*)(x)):"")
40 #define ERROR_STR (char*) "(error)"
41
print_idn_name(gnutls_buffer_st * str,const char * prefix,const char * type,gnutls_datum_t * name)42 static void print_idn_name(gnutls_buffer_st *str, const char *prefix, const char *type, gnutls_datum_t *name)
43 {
44 unsigned printable = 1;
45 unsigned is_printed = 0;
46 gnutls_datum_t out = {NULL, 0};
47 int ret;
48
49 if (!_gnutls_str_is_print((char*)name->data, name->size))
50 printable = 0;
51
52 is_printed = 0;
53 if (!printable) {
54 addf(str, _("%s%s: %.*s (contains illegal chars)\n"), prefix, type, name->size, NON_NULL(name->data));
55 is_printed = 1;
56 } else if (name->data != NULL) {
57 if (strstr((char*)name->data, "xn--") != NULL) {
58 ret = gnutls_idna_reverse_map((char*)name->data, name->size, &out, 0);
59 if (ret >= 0) {
60 addf(str, _("%s%s: %.*s (%s)\n"), prefix, type, name->size, NON_NULL(name->data), out.data);
61 is_printed = 1;
62 gnutls_free(out.data);
63 }
64 }
65 }
66
67 if (is_printed == 0) {
68 addf(str, _("%s%s: %.*s\n"), prefix, type, name->size, NON_NULL(name->data));
69 }
70 }
71
print_idn_email(gnutls_buffer_st * str,const char * prefix,const char * type,gnutls_datum_t * name)72 static void print_idn_email(gnutls_buffer_st *str, const char *prefix, const char *type, gnutls_datum_t *name)
73 {
74 unsigned printable = 1;
75 unsigned is_printed = 0;
76 gnutls_datum_t out = {NULL, 0};
77 int ret;
78
79 if (!_gnutls_str_is_print((char*)name->data, name->size))
80 printable = 0;
81
82 is_printed = 0;
83 if (!printable) {
84 addf(str, _("%s%s: %.*s (contains illegal chars)\n"), prefix, type, name->size, NON_NULL(name->data));
85 is_printed = 1;
86 } else if (name->data != NULL) {
87 if (strstr((char*)name->data, "xn--") != NULL) {
88 ret = _gnutls_idna_email_reverse_map((char*)name->data, name->size, &out);
89 if (ret >= 0) {
90 addf(str, _("%s%s: %.*s (%s)\n"), prefix, type, name->size, NON_NULL(name->data), out.data);
91 is_printed = 1;
92 gnutls_free(out.data);
93 }
94 }
95 }
96
97 if (is_printed == 0) {
98 addf(str, _("%s%s: %.*s\n"), prefix, type, name->size, NON_NULL(name->data));
99 }
100 }
101
102 static void
print_name(gnutls_buffer_st * str,const char * prefix,unsigned type,gnutls_datum_t * name,unsigned ip_is_cidr)103 print_name(gnutls_buffer_st *str, const char *prefix, unsigned type, gnutls_datum_t *name, unsigned ip_is_cidr)
104 {
105 char *sname = (char*)name->data;
106 char str_ip[64];
107 const char *p;
108
109 if ((type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_OTHERNAME_XMPP
110 || type == GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL
111 || type == GNUTLS_SAN_RFC822NAME
112 || type == GNUTLS_SAN_URI) && sname != NULL && strlen(sname) != name->size) {
113 adds(str,
114 _("warning: SAN contains an embedded NUL, "
115 "replacing with '!'\n"));
116 while (strlen(sname) < name->size)
117 name->data[strlen(sname)] = '!';
118 }
119
120 switch (type) {
121 case GNUTLS_SAN_DNSNAME:
122 print_idn_name(str, prefix, "DNSname", name);
123 break;
124
125 case GNUTLS_SAN_RFC822NAME:
126 print_idn_email(str, prefix, "RFC822Name", name);
127 break;
128
129 case GNUTLS_SAN_URI:
130 addf(str, _("%sURI: %.*s\n"), prefix, name->size, NON_NULL(name->data));
131 break;
132
133 case GNUTLS_SAN_IPADDRESS:
134 if (!ip_is_cidr)
135 p = _gnutls_ip_to_string(name->data, name->size, str_ip, sizeof(str_ip));
136 else
137 p = _gnutls_cidr_to_string(name->data, name->size, str_ip, sizeof(str_ip));
138 if (p == NULL)
139 p = ERROR_STR;
140 addf(str, "%sIPAddress: %s\n", prefix, p);
141 break;
142
143 case GNUTLS_SAN_DN:
144 addf(str, _("%sdirectoryName: %.*s\n"), prefix, name->size, NON_NULL(name->data));
145 break;
146
147 case GNUTLS_SAN_REGISTERED_ID:
148 addf(str, _("%sRegistered ID: %.*s\n"), prefix, name->size, NON_NULL(name->data));
149 break;
150
151 case GNUTLS_SAN_OTHERNAME_XMPP:
152 addf(str, _("%sXMPP Address: %.*s\n"), prefix, name->size, NON_NULL(name->data));
153 break;
154
155 case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
156 addf(str, _("%sKRB5Principal: %.*s\n"), prefix, name->size, NON_NULL(name->data));
157 break;
158
159 default:
160 addf(str, _("%sUnknown name: "), prefix);
161 _gnutls_buffer_hexprint(str, name->data, name->size);
162 adds(str, "\n");
163 break;
164 }
165 }
166
get_pk_name(gnutls_x509_crt_t cert,unsigned * bits)167 static char *get_pk_name(gnutls_x509_crt_t cert, unsigned *bits)
168 {
169 char oid[MAX_OID_SIZE];
170 size_t oid_size;
171 oid_size = sizeof(oid);
172 int ret;
173
174 ret = gnutls_x509_crt_get_pk_algorithm(cert, bits);
175 if (ret > 0) {
176 const char *name = gnutls_pk_algorithm_get_name(ret);
177
178 if (name != NULL)
179 return gnutls_strdup(name);
180 }
181
182 ret = gnutls_x509_crt_get_pk_oid(cert, oid, &oid_size);
183 if (ret < 0)
184 return NULL;
185
186 return gnutls_strdup(oid);
187 }
188
crq_get_pk_name(gnutls_x509_crq_t crq)189 static char *crq_get_pk_name(gnutls_x509_crq_t crq)
190 {
191 char oid[MAX_OID_SIZE];
192 size_t oid_size;
193 oid_size = sizeof(oid);
194 int ret;
195
196 ret = gnutls_x509_crq_get_pk_algorithm(crq, NULL);
197 if (ret > 0) {
198 const char *name = gnutls_pk_algorithm_get_name(ret);
199
200 if (name != NULL)
201 return gnutls_strdup(name);
202 }
203
204 ret = gnutls_x509_crq_get_pk_oid(crq, oid, &oid_size);
205 if (ret < 0)
206 return NULL;
207
208 return gnutls_strdup(oid);
209 }
210
get_sign_name(gnutls_x509_crt_t cert,int * algo)211 static char *get_sign_name(gnutls_x509_crt_t cert, int *algo)
212 {
213 char oid[MAX_OID_SIZE];
214 size_t oid_size;
215 oid_size = sizeof(oid);
216 int ret;
217
218 *algo = 0;
219
220 ret = gnutls_x509_crt_get_signature_algorithm(cert);
221 if (ret > 0) {
222 const char *name = gnutls_sign_get_name(ret);
223
224 *algo = ret;
225
226 if (name != NULL)
227 return gnutls_strdup(name);
228 }
229
230 ret = gnutls_x509_crt_get_signature_oid(cert, oid, &oid_size);
231 if (ret < 0)
232 return NULL;
233
234 return gnutls_strdup(oid);
235 }
236
crq_get_sign_name(gnutls_x509_crq_t crq)237 static char *crq_get_sign_name(gnutls_x509_crq_t crq)
238 {
239 char oid[MAX_OID_SIZE];
240 size_t oid_size;
241 oid_size = sizeof(oid);
242 int ret;
243
244 ret = gnutls_x509_crq_get_signature_algorithm(crq);
245 if (ret > 0) {
246 const char *name = gnutls_sign_get_name(ret);
247
248 if (name != NULL)
249 return gnutls_strdup(name);
250 }
251
252 ret = gnutls_x509_crq_get_signature_oid(crq, oid, &oid_size);
253 if (ret < 0)
254 return NULL;
255
256 return gnutls_strdup(oid);
257 }
258
crl_get_sign_name(gnutls_x509_crl_t crl,int * algo)259 static char *crl_get_sign_name(gnutls_x509_crl_t crl, int *algo)
260 {
261 char oid[MAX_OID_SIZE];
262 size_t oid_size;
263 oid_size = sizeof(oid);
264 int ret;
265
266 *algo = 0;
267
268 ret = gnutls_x509_crl_get_signature_algorithm(crl);
269 if (ret > 0) {
270 const char *name = gnutls_sign_get_name(ret);
271
272 *algo = ret;
273
274 if (name != NULL)
275 return gnutls_strdup(name);
276 }
277
278 ret = gnutls_x509_crl_get_signature_oid(crl, oid, &oid_size);
279 if (ret < 0)
280 return NULL;
281
282 return gnutls_strdup(oid);
283 }
284
285
print_proxy(gnutls_buffer_st * str,gnutls_datum_t * der)286 static void print_proxy(gnutls_buffer_st * str, gnutls_datum_t *der)
287 {
288 int pathlen;
289 char *policyLanguage;
290 char *policy;
291 size_t npolicy;
292 int err;
293
294 err = gnutls_x509_ext_import_proxy(der, &pathlen, &policyLanguage,
295 &policy, &npolicy);
296 if (err < 0) {
297 addf(str, "error: get_proxy: %s\n", gnutls_strerror(err));
298 return;
299 }
300
301 if (pathlen >= 0)
302 addf(str, _("\t\t\tPath Length Constraint: %d\n"),
303 pathlen);
304 addf(str, _("\t\t\tPolicy Language: %s"), policyLanguage);
305 if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
306 adds(str, " (id-ppl-inheritALL)\n");
307 else if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.2") == 0)
308 adds(str, " (id-ppl-independent)\n");
309 else
310 adds(str, "\n");
311 if (npolicy) {
312 adds(str, _("\t\t\tPolicy:\n\t\t\t\tASCII: "));
313 _gnutls_buffer_asciiprint(str, policy, npolicy);
314 adds(str, _("\n\t\t\t\tHexdump: "));
315 _gnutls_buffer_hexprint(str, policy, npolicy);
316 adds(str, "\n");
317 }
318 gnutls_free(policy);
319 gnutls_free(policyLanguage);
320 }
321
322
print_nc(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)323 static void print_nc(gnutls_buffer_st * str, const char* prefix, gnutls_datum_t *der)
324 {
325 gnutls_x509_name_constraints_t nc;
326 int ret;
327 unsigned idx = 0;
328 gnutls_datum_t name;
329 unsigned type;
330 char new_prefix[16];
331
332 ret = gnutls_x509_name_constraints_init(&nc);
333 if (ret < 0)
334 return;
335
336 ret = gnutls_x509_ext_import_name_constraints(der, nc, 0);
337 if (ret < 0)
338 goto cleanup;
339
340 snprintf(new_prefix, sizeof(new_prefix), "%s\t\t\t\t", prefix);
341
342 do {
343 ret = gnutls_x509_name_constraints_get_permitted(nc, idx++, &type, &name);
344
345 if (ret >= 0) {
346 if (idx == 1)
347 addf(str, _("%s\t\t\tPermitted:\n"), prefix);
348
349 print_name(str, new_prefix, type, &name, 1);
350 }
351 } while (ret == 0);
352
353 idx = 0;
354 do {
355 ret = gnutls_x509_name_constraints_get_excluded(nc, idx++, &type, &name);
356
357 if (ret >= 0) {
358 if (idx == 1)
359 addf(str, _("%s\t\t\tExcluded:\n"), prefix);
360
361 print_name(str, new_prefix, type, &name, 1);
362 }
363 } while (ret == 0);
364
365 cleanup:
366 gnutls_x509_name_constraints_deinit(nc);
367 }
368
print_aia(gnutls_buffer_st * str,const gnutls_datum_t * der)369 static void print_aia(gnutls_buffer_st * str, const gnutls_datum_t *der)
370 {
371 int err;
372 int seq;
373 gnutls_datum_t san = { NULL, 0 }, oid = {NULL, 0};
374 gnutls_x509_aia_t aia;
375 unsigned int san_type;
376
377 err = gnutls_x509_aia_init(&aia);
378 if (err < 0)
379 return;
380
381 err = gnutls_x509_ext_import_aia(der, aia, 0);
382 if (err < 0) {
383 addf(str, "error: get_aia: %s\n",
384 gnutls_strerror(err));
385 goto cleanup;
386 }
387
388 for (seq=0;;seq++) {
389 err = gnutls_x509_aia_get(aia, seq, &oid, &san_type, &san);
390 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
391 goto cleanup;
392 if (err < 0) {
393 addf(str, "error: aia_get: %s\n",
394 gnutls_strerror(err));
395 goto cleanup;
396 }
397
398 if (strcmp((char*)oid.data, GNUTLS_OID_AD_OCSP) == 0)
399 addf(str, _("\t\t\tAccess Method: %s (%s)\n"), GNUTLS_OID_AD_OCSP, "id-ad-ocsp");
400 else if (strcmp((char*)oid.data, GNUTLS_OID_AD_CAISSUERS) == 0)
401 addf(str, _("\t\t\tAccess Method: %s (%s)\n"), GNUTLS_OID_AD_CAISSUERS, "id-ad-caIssuers");
402 else {
403 addf(str, _("\t\t\tAccess Method: %s (%s)\n"), (char*)oid.data, "UNKNOWN");
404 }
405
406 adds(str, "\t\t\tAccess Location ");
407 print_name(str, "", san_type, &san, 0);
408 }
409
410 cleanup:
411 gnutls_x509_aia_deinit(aia);
412 }
413
print_ski(gnutls_buffer_st * str,gnutls_datum_t * der)414 static void print_ski(gnutls_buffer_st * str, gnutls_datum_t *der)
415 {
416 gnutls_datum_t id = {NULL, 0};
417 int err;
418
419 err = gnutls_x509_ext_import_subject_key_id(der, &id);
420 if (err < 0) {
421 addf(str, "error: get_subject_key_id: %s\n",
422 gnutls_strerror(err));
423 return;
424 }
425
426 adds(str, "\t\t\t");
427 _gnutls_buffer_hexprint(str, id.data, id.size);
428 adds(str, "\n");
429
430 gnutls_free(id.data);
431 }
432
433 #define TYPE_CRT 2
434 #define TYPE_CRQ 3
435
436 typedef union {
437 gnutls_x509_crt_t crt;
438 gnutls_x509_crq_t crq;
439 } cert_type_t;
440
441 static void
print_aki_gn_serial(gnutls_buffer_st * str,gnutls_x509_aki_t aki)442 print_aki_gn_serial(gnutls_buffer_st * str, gnutls_x509_aki_t aki)
443 {
444 gnutls_datum_t san, other_oid, serial;
445 unsigned int alt_type;
446 int err;
447
448 err =
449 gnutls_x509_aki_get_cert_issuer(aki,
450 0, &alt_type, &san, &other_oid, &serial);
451 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
452 return;
453 } else if (err < 0) {
454 addf(str, "error: gnutls_x509_aki_get_cert_issuer: %s\n",
455 gnutls_strerror(err));
456 return;
457 }
458
459 print_name(str, "\t\t\t", alt_type, &san, 0);
460
461 adds(str, "\t\t\tserial: ");
462 _gnutls_buffer_hexprint(str, serial.data, serial.size);
463 adds(str, "\n");
464 }
465
print_aki(gnutls_buffer_st * str,gnutls_datum_t * der)466 static void print_aki(gnutls_buffer_st * str, gnutls_datum_t *der)
467 {
468 int err;
469 gnutls_x509_aki_t aki;
470 gnutls_datum_t id;
471
472 err = gnutls_x509_aki_init(&aki);
473 if (err < 0) {
474 addf(str, "error: gnutls_x509_aki_init: %s\n",
475 gnutls_strerror(err));
476 return;
477 }
478
479 err = gnutls_x509_ext_import_authority_key_id(der, aki, 0);
480 if (err < 0) {
481 addf(str, "error: gnutls_x509_ext_import_authority_key_id: %s\n",
482 gnutls_strerror(err));
483 goto cleanup;
484 }
485
486 /* Check if an alternative name is there */
487 print_aki_gn_serial(str, aki);
488
489 err = gnutls_x509_aki_get_id(aki, &id);
490 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
491 goto cleanup;
492 } else if (err < 0) {
493 addf(str, "error: gnutls_x509_aki_get_id: %s\n",
494 gnutls_strerror(err));
495 goto cleanup;
496 }
497
498 adds(str, "\t\t\t");
499 _gnutls_buffer_hexprint(str, id.data, id.size);
500 adds(str, "\n");
501
502 cleanup:
503 gnutls_x509_aki_deinit(aki);
504 }
505
506 static void
print_key_usage2(gnutls_buffer_st * str,const char * prefix,unsigned int key_usage)507 print_key_usage2(gnutls_buffer_st * str, const char *prefix, unsigned int key_usage)
508 {
509 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
510 addf(str, _("%sDigital signature.\n"), prefix);
511 if (key_usage & GNUTLS_KEY_NON_REPUDIATION)
512 addf(str, _("%sNon repudiation.\n"), prefix);
513 if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
514 addf(str, _("%sKey encipherment.\n"), prefix);
515 if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
516 addf(str, _("%sData encipherment.\n"), prefix);
517 if (key_usage & GNUTLS_KEY_KEY_AGREEMENT)
518 addf(str, _("%sKey agreement.\n"), prefix);
519 if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN)
520 addf(str, _("%sCertificate signing.\n"), prefix);
521 if (key_usage & GNUTLS_KEY_CRL_SIGN)
522 addf(str, _("%sCRL signing.\n"), prefix);
523 if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY)
524 addf(str, _("%sKey encipher only.\n"), prefix);
525 if (key_usage & GNUTLS_KEY_DECIPHER_ONLY)
526 addf(str, _("%sKey decipher only.\n"), prefix);
527 }
528
529 static void
print_key_usage(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)530 print_key_usage(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
531 {
532 unsigned int key_usage;
533 int err;
534
535 err = gnutls_x509_ext_import_key_usage(der, &key_usage);
536 if (err < 0) {
537 addf(str, "error: get_key_usage: %s\n",
538 gnutls_strerror(err));
539 return;
540 }
541
542 print_key_usage2(str, prefix, key_usage);
543 }
544
545 static void
print_private_key_usage_period(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)546 print_private_key_usage_period(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
547 {
548 time_t activation, expiration;
549 int err;
550 char s[42];
551 struct tm t;
552 size_t max;
553
554 err = gnutls_x509_ext_import_private_key_usage_period(der, &activation, &expiration);
555 if (err < 0) {
556 addf(str, "error: get_private_key_usage_period: %s\n",
557 gnutls_strerror(err));
558 return;
559 }
560
561 max = sizeof(s);
562
563 if (gmtime_r(&activation, &t) == NULL)
564 addf(str, "error: gmtime_r (%ld)\n",
565 (unsigned long) activation);
566 else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
567 addf(str, "error: strftime (%ld)\n",
568 (unsigned long) activation);
569 else
570 addf(str, _("\t\t\tNot Before: %s\n"), s);
571
572 if (gmtime_r(&expiration, &t) == NULL)
573 addf(str, "error: gmtime_r (%ld)\n",
574 (unsigned long) expiration);
575 else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
576 addf(str, "error: strftime (%ld)\n",
577 (unsigned long) expiration);
578 else
579 addf(str, _("\t\t\tNot After: %s\n"), s);
580
581 }
582
print_crldist(gnutls_buffer_st * str,gnutls_datum_t * der)583 static void print_crldist(gnutls_buffer_st * str, gnutls_datum_t *der)
584 {
585 int err;
586 int indx;
587 gnutls_x509_crl_dist_points_t dp;
588 unsigned int flags, type;
589 gnutls_datum_t dist;
590
591 err = gnutls_x509_crl_dist_points_init(&dp);
592 if (err < 0) {
593 addf(str, "error: gnutls_x509_crl_dist_points_init: %s\n",
594 gnutls_strerror(err));
595 return;
596 }
597
598 err = gnutls_x509_ext_import_crl_dist_points(der, dp, 0);
599 if (err < 0) {
600 addf(str, "error: gnutls_x509_ext_import_crl_dist_points: %s\n",
601 gnutls_strerror(err));
602 goto cleanup;
603 }
604
605 for (indx = 0;; indx++) {
606 err =
607 gnutls_x509_crl_dist_points_get(dp, indx, &type, &dist, &flags);
608 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
609 goto cleanup;
610 else if (err < 0) {
611 addf(str, "error: get_crl_dist_points: %s\n",
612 gnutls_strerror(err));
613 return;
614 }
615
616 print_name(str, "\t\t\t", type, &dist, 0);
617 }
618 cleanup:
619 gnutls_x509_crl_dist_points_deinit(dp);
620 }
621
622 static void
print_key_purpose(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)623 print_key_purpose(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
624 {
625 int indx;
626 gnutls_datum_t oid;
627 char *p;
628 int err;
629 gnutls_x509_key_purposes_t purposes;
630
631 err = gnutls_x509_key_purpose_init(&purposes);
632 if (err < 0) {
633 addf(str, "error: gnutls_x509_key_purpose_init: %s\n",
634 gnutls_strerror(err));
635 return;
636 }
637
638 err = gnutls_x509_ext_import_key_purposes(der, purposes, 0);
639 if (err < 0) {
640 addf(str, "error: gnutls_x509_ext_import_key_purposes: %s\n",
641 gnutls_strerror(err));
642 goto cleanup;
643 }
644
645 for (indx = 0;; indx++) {
646 err = gnutls_x509_key_purpose_get(purposes, indx, &oid);
647 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
648 goto cleanup;
649 else if (err < 0) {
650 addf(str, "error: gnutls_x509_key_purpose_get: %s\n",
651 gnutls_strerror(err));
652 goto cleanup;
653 }
654
655 p = (void*)oid.data;
656 if (strcmp(p, GNUTLS_KP_TLS_WWW_SERVER) == 0)
657 addf(str, _("%s\t\t\tTLS WWW Server.\n"), prefix);
658 else if (strcmp(p, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
659 addf(str, _("%s\t\t\tTLS WWW Client.\n"), prefix);
660 else if (strcmp(p, GNUTLS_KP_CODE_SIGNING) == 0)
661 addf(str, _("%s\t\t\tCode signing.\n"), prefix);
662 else if (strcmp(p, GNUTLS_KP_EMAIL_PROTECTION) == 0)
663 addf(str, _("%s\t\t\tEmail protection.\n"),
664 prefix);
665 else if (strcmp(p, GNUTLS_KP_TIME_STAMPING) == 0)
666 addf(str, _("%s\t\t\tTime stamping.\n"), prefix);
667 else if (strcmp(p, GNUTLS_KP_OCSP_SIGNING) == 0)
668 addf(str, _("%s\t\t\tOCSP signing.\n"), prefix);
669 else if (strcmp(p, GNUTLS_KP_IPSEC_IKE) == 0)
670 addf(str, _("%s\t\t\tIpsec IKE.\n"), prefix);
671 else if (strcmp(p, GNUTLS_KP_ANY) == 0)
672 addf(str, _("%s\t\t\tAny purpose.\n"), prefix);
673 else
674 addf(str, "%s\t\t\t%s\n", prefix, p);
675 }
676 cleanup:
677 gnutls_x509_key_purpose_deinit(purposes);
678 }
679
680 static void
print_basic(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)681 print_basic(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
682 {
683 int pathlen;
684 unsigned ca;
685 int err;
686
687 err = gnutls_x509_ext_import_basic_constraints(der, &ca, &pathlen);
688 if (err < 0) {
689 addf(str, "error: get_basic_constraints: %s\n",
690 gnutls_strerror(err));
691 return;
692 }
693
694 if (ca == 0)
695 addf(str, _("%s\t\t\tCertificate Authority (CA): FALSE\n"),
696 prefix);
697 else
698 addf(str, _("%s\t\t\tCertificate Authority (CA): TRUE\n"),
699 prefix);
700
701 if (pathlen >= 0)
702 addf(str, _("%s\t\t\tPath Length Constraint: %d\n"),
703 prefix, pathlen);
704 }
705
706
707 static void
print_altname(gnutls_buffer_st * str,const char * prefix,gnutls_datum_t * der)708 print_altname(gnutls_buffer_st * str, const char *prefix, gnutls_datum_t *der)
709 {
710 unsigned int altname_idx;
711 gnutls_subject_alt_names_t names;
712 unsigned int type;
713 gnutls_datum_t san;
714 gnutls_datum_t othername;
715 char pfx[16];
716 int err;
717
718 err = gnutls_subject_alt_names_init(&names);
719 if (err < 0) {
720 addf(str, "error: gnutls_subject_alt_names_init: %s\n",
721 gnutls_strerror(err));
722 return;
723 }
724
725 err = gnutls_x509_ext_import_subject_alt_names(der, names, 0);
726 if (err < 0) {
727 addf(str, "error: gnutls_x509_ext_import_subject_alt_names: %s\n",
728 gnutls_strerror(err));
729 goto cleanup;
730 }
731
732 for (altname_idx = 0;; altname_idx++) {
733 err = gnutls_subject_alt_names_get(names, altname_idx,
734 &type, &san, &othername);
735 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
736 break;
737 else if (err < 0) {
738 addf(str,
739 "error: gnutls_subject_alt_names_get: %s\n",
740 gnutls_strerror(err));
741 break;
742 }
743
744
745 if (type == GNUTLS_SAN_OTHERNAME) {
746 unsigned vtype;
747 gnutls_datum_t virt;
748
749 err = gnutls_x509_othername_to_virtual((char*)othername.data, &san, &vtype, &virt);
750 if (err >= 0) {
751 snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
752 print_name(str, pfx, vtype, &virt, 0);
753 gnutls_free(virt.data);
754 continue;
755 }
756
757 addf(str,
758 _("%s\t\t\totherName OID: %.*s\n"),
759 prefix, (int)othername.size, (char*)othername.data);
760 addf(str, _("%s\t\t\totherName DER: "),
761 prefix);
762 _gnutls_buffer_hexprint(str, san.data, san.size);
763 addf(str, _("\n%s\t\t\totherName ASCII: "),
764 prefix);
765 _gnutls_buffer_asciiprint(str, (char*)san.data, san.size);
766 addf(str, "\n");
767 } else {
768
769 snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
770 print_name(str, pfx, type, &san, 0);
771 }
772 }
773
774 cleanup:
775 gnutls_subject_alt_names_deinit(names);
776 }
777
778 static void
guiddump(gnutls_buffer_st * str,const char * data,size_t len,const char * spc)779 guiddump(gnutls_buffer_st * str, const char *data, size_t len,
780 const char *spc)
781 {
782 size_t j;
783
784 if (spc)
785 adds(str, spc);
786 addf(str, "{");
787 addf(str, "%.2X", (unsigned char) data[3]);
788 addf(str, "%.2X", (unsigned char) data[2]);
789 addf(str, "%.2X", (unsigned char) data[1]);
790 addf(str, "%.2X", (unsigned char) data[0]);
791 addf(str, "-");
792 addf(str, "%.2X", (unsigned char) data[5]);
793 addf(str, "%.2X", (unsigned char) data[4]);
794 addf(str, "-");
795 addf(str, "%.2X", (unsigned char) data[7]);
796 addf(str, "%.2X", (unsigned char) data[6]);
797 addf(str, "-");
798 addf(str, "%.2X", (unsigned char) data[8]);
799 addf(str, "%.2X", (unsigned char) data[9]);
800 addf(str, "-");
801 for (j = 10; j < 16; j++) {
802 addf(str, "%.2X", (unsigned char) data[j]);
803 }
804 addf(str, "}\n");
805 }
806
807 static void
print_unique_ids(gnutls_buffer_st * str,const gnutls_x509_crt_t cert)808 print_unique_ids(gnutls_buffer_st * str, const gnutls_x509_crt_t cert)
809 {
810 int result;
811 char buf[256]; /* if its longer, we won't bother to print it */
812 size_t buf_size = 256;
813
814 result =
815 gnutls_x509_crt_get_issuer_unique_id(cert, buf, &buf_size);
816 if (result >= 0) {
817 addf(str, ("\tIssuer Unique ID:\n"));
818 _gnutls_buffer_hexdump(str, buf, buf_size, "\t\t\t");
819 if (buf_size == 16) { /* this could be a GUID */
820 guiddump(str, buf, buf_size, "\t\t\t");
821 }
822 }
823
824 buf_size = 256;
825 result =
826 gnutls_x509_crt_get_subject_unique_id(cert, buf, &buf_size);
827 if (result >= 0) {
828 addf(str, ("\tSubject Unique ID:\n"));
829 _gnutls_buffer_hexdump(str, buf, buf_size, "\t\t\t");
830 if (buf_size == 16) { /* this could be a GUID */
831 guiddump(str, buf, buf_size, "\t\t\t");
832 }
833 }
834 }
835
print_tlsfeatures(gnutls_buffer_st * str,const char * prefix,const gnutls_datum_t * der)836 static void print_tlsfeatures(gnutls_buffer_st * str, const char *prefix, const gnutls_datum_t *der)
837 {
838 int err;
839 int seq;
840 gnutls_x509_tlsfeatures_t features;
841 const char *name;
842 unsigned int feature;
843
844 err = gnutls_x509_tlsfeatures_init(&features);
845 if (err < 0)
846 return;
847
848 err = gnutls_x509_ext_import_tlsfeatures(der, features, 0);
849 if (err < 0) {
850 addf(str, "error: get_tlsfeatures: %s\n",
851 gnutls_strerror(err));
852 goto cleanup;
853 }
854
855 for (seq=0;;seq++) {
856 err = gnutls_x509_tlsfeatures_get(features, seq, &feature);
857 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
858 goto cleanup;
859 if (err < 0) {
860 addf(str, "error: get_tlsfeatures: %s\n",
861 gnutls_strerror(err));
862 goto cleanup;
863 }
864
865 name = gnutls_ext_get_name(feature);
866 if (name == NULL)
867 addf(str, "%s\t\t\t%u\n", prefix, feature);
868 else
869 addf(str, "%s\t\t\t%s(%u)\n", prefix, name, feature);
870 }
871
872 cleanup:
873 gnutls_x509_tlsfeatures_deinit(features);
874 }
875
print_subject_sign_tool(gnutls_buffer_st * str,const char * prefix,const gnutls_datum_t * der)876 static void print_subject_sign_tool(gnutls_buffer_st * str, const char *prefix, const gnutls_datum_t *der)
877 {
878 int ret;
879 gnutls_datum_t tmp = {NULL, 0};
880
881 ret = _gnutls_x509_decode_string(ASN1_ETYPE_UTF8_STRING, der->data, der->size, &tmp, 0);
882 if (ret < 0) {
883 addf(str, _("%s\t\t\tASCII: "), prefix);
884 _gnutls_buffer_asciiprint(str, (char*)der->data, der->size);
885
886 addf(str, "\n");
887 addf(str, _("%s\t\t\tHexdump: "), prefix);
888 _gnutls_buffer_hexprint(str, (char*)der->data, der->size);
889 adds(str, "\n");
890
891 return;
892 }
893
894 addf(str, _("%s\t\t\t%.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
895 _gnutls_free_datum(&tmp);
896 }
897
print_issuer_sign_tool(gnutls_buffer_st * str,const char * prefix,const gnutls_datum_t * der)898 static void print_issuer_sign_tool(gnutls_buffer_st * str, const char *prefix, const gnutls_datum_t *der)
899 {
900 int ret, result;
901 ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY;
902 char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
903 gnutls_datum_t tmp;
904
905 if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.IssuerSignTool",
906 &tmpasn)) != ASN1_SUCCESS) {
907 gnutls_assert();
908 goto hexdump;
909 }
910
911 if ((result = _asn1_strict_der_decode(&tmpasn, der->data, der->size, asn1_err)) != ASN1_SUCCESS) {
912 gnutls_assert();
913 _gnutls_debug_log("_asn1_strict_der_decode: %s\n", asn1_err);
914 goto hexdump;
915 }
916
917 ret = _gnutls_x509_read_value(tmpasn, "signTool", &tmp);
918 if (ret < 0) {
919 gnutls_assert();
920 goto hexdump;
921 }
922 addf(str, _("%s\t\t\tSignTool: %.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
923 _gnutls_free_datum(&tmp);
924
925 ret = _gnutls_x509_read_value(tmpasn, "cATool", &tmp);
926 if (ret < 0) {
927 gnutls_assert();
928 goto hexdump;
929 }
930 addf(str, _("%s\t\t\tCATool: %.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
931 _gnutls_free_datum(&tmp);
932
933 ret = _gnutls_x509_read_value(tmpasn, "signToolCert", &tmp);
934 if (ret < 0) {
935 gnutls_assert();
936 goto hexdump;
937 }
938 addf(str, _("%s\t\t\tSignToolCert: %.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
939 _gnutls_free_datum(&tmp);
940
941 ret = _gnutls_x509_read_value(tmpasn, "cAToolCert", &tmp);
942 if (ret < 0) {
943 gnutls_assert();
944 goto hexdump;
945 }
946 addf(str, _("%s\t\t\tCAToolCert: %.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
947 _gnutls_free_datum(&tmp);
948
949 asn1_delete_structure(&tmpasn);
950
951 return;
952
953 hexdump:
954 asn1_delete_structure(&tmpasn);
955
956 addf(str, _("%s\t\t\tASCII: "), prefix);
957 _gnutls_buffer_asciiprint(str, (char*)der->data, der->size);
958
959 addf(str, "\n");
960 addf(str, _("%s\t\t\tHexdump: "), prefix);
961 _gnutls_buffer_hexprint(str, (char*)der->data, der->size);
962 adds(str, "\n");
963 }
964
965 #define ENTRY(oid, name) {oid, sizeof(oid)-1, name, sizeof(name)-1, NULL, 0}
966
967 static const struct oid_to_string cp_oid2str[] = {
968 ENTRY("2.5.29.32.0", "anyPolicy"),
969
970 ENTRY("2.23.140.1.2.1", "CA/B Domain Validated"),
971 ENTRY("2.23.140.1.2.2", "CA/B Organization Validated"),
972 ENTRY("2.23.140.1.2.3", "CA/B Individual Validated"),
973 ENTRY("2.23.140.1.1", "CA/B Extended Validation"),
974
975 /* draft-deremin-rfc4491-bis */
976 ENTRY("1.2.643.100.113.1", "Russian security class KC1"),
977 ENTRY("1.2.643.100.113.2", "Russian security class KC2"),
978 ENTRY("1.2.643.100.113.3", "Russian security class KC3"),
979 ENTRY("1.2.643.100.113.4", "Russian security class KB1"),
980 ENTRY("1.2.643.100.113.5", "Russian security class KB2"),
981 ENTRY("1.2.643.100.113.6", "Russian security class KA1"),
982
983 {NULL, 0, NULL, 0},
984 };
985
986 struct ext_indexes_st {
987 int san;
988 int ian;
989 int proxy;
990 int basic;
991 int keyusage;
992 int keypurpose;
993 int ski;
994 int aki, nc;
995 int crldist, pkey_usage_period;
996 int tlsfeatures;
997 };
998
print_extension(gnutls_buffer_st * str,const char * prefix,struct ext_indexes_st * idx,const char * oid,unsigned critical,gnutls_datum_t * der)999 static void print_extension(gnutls_buffer_st * str, const char *prefix,
1000 struct ext_indexes_st *idx, const char *oid,
1001 unsigned critical, gnutls_datum_t *der)
1002 {
1003 int err;
1004 unsigned j;
1005 char pfx[16];
1006
1007 if (strcmp(oid, "2.5.29.19") == 0) {
1008 if (idx->basic) {
1009 addf(str,
1010 "warning: more than one basic constraint\n");
1011 }
1012
1013 addf(str, _("%s\t\tBasic Constraints (%s):\n"),
1014 prefix,
1015 critical ? _("critical") : _("not critical"));
1016
1017 print_basic(str, prefix, der);
1018 idx->basic++;
1019
1020 } else if (strcmp(oid, "2.5.29.14") == 0) {
1021 if (idx->ski) {
1022 addf(str,
1023 "warning: more than one SKI extension\n");
1024 }
1025
1026 addf(str,
1027 _("%s\t\tSubject Key Identifier (%s):\n"),
1028 prefix,
1029 critical ? _("critical") : _("not critical"));
1030
1031 print_ski(str, der);
1032
1033 idx->ski++;
1034 } else if (strcmp(oid, "2.5.29.32") == 0) {
1035 struct gnutls_x509_policy_st policy;
1036 gnutls_x509_policies_t policies;
1037 const char *name;
1038 const struct oid_to_string *entry;
1039 int x;
1040
1041 err = gnutls_x509_policies_init(&policies);
1042 if (err < 0) {
1043 addf(str,
1044 "error: certificate policies: %s\n",
1045 gnutls_strerror(err));
1046 return;
1047 }
1048
1049 err = gnutls_x509_ext_import_policies(der, policies, 0);
1050 if (err < 0) {
1051 addf(str,
1052 "error: certificate policies import: %s\n",
1053 gnutls_strerror(err));
1054 gnutls_x509_policies_deinit(policies);
1055 return;
1056 }
1057
1058 for (x = 0;; x++) {
1059 err = gnutls_x509_policies_get(policies, x, &policy);
1060 if (err ==
1061 GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1062 break;
1063
1064 if (err < 0) {
1065 addf(str,
1066 "error: certificate policy: %s\n",
1067 gnutls_strerror(err));
1068 break;
1069 }
1070
1071 if (x == 0)
1072 addf(str,
1073 "%s\t\tCertificate Policies (%s):\n",
1074 prefix,
1075 critical ? _("critical") :
1076 _("not critical"));
1077
1078 entry = _gnutls_oid_get_entry(cp_oid2str, policy.oid);
1079 if (entry != NULL && entry->name_desc != NULL)
1080 addf(str, "%s\t\t\t%s (%s)\n", prefix, policy.oid, entry->name_desc);
1081 else
1082 addf(str, "%s\t\t\t%s\n", prefix, policy.oid);
1083 for (j = 0; j < policy.qualifiers; j++) {
1084 if (policy.qualifier[j].type ==
1085 GNUTLS_X509_QUALIFIER_URI)
1086 name = "URI";
1087 else if (policy.qualifier[j].
1088 type ==
1089 GNUTLS_X509_QUALIFIER_NOTICE)
1090 name = "Note";
1091 else
1092 name = "Unknown qualifier";
1093 addf(str, "%s\t\t\t\t%s: %s\n",
1094 prefix, name,
1095 policy.qualifier[j].data);
1096 }
1097 }
1098 gnutls_x509_policies_deinit(policies);
1099 } else if (strcmp(oid, "2.5.29.54") == 0) {
1100 unsigned int skipcerts;
1101
1102 err = gnutls_x509_ext_import_inhibit_anypolicy(der, &skipcerts);
1103 if (err < 0) {
1104 addf(str,
1105 "error: certificate inhibit any policy import: %s\n",
1106 gnutls_strerror(err));
1107 return;
1108 }
1109
1110 addf(str,
1111 "%s\t\tInhibit anyPolicy skip certs: %u (%s)\n",
1112 prefix, skipcerts,
1113 critical ? _("critical") :
1114 _("not critical"));
1115
1116 } else if (strcmp(oid, "2.5.29.35") == 0) {
1117
1118 if (idx->aki) {
1119 addf(str,
1120 "warning: more than one AKI extension\n");
1121 }
1122
1123 addf(str,
1124 _("%s\t\tAuthority Key Identifier (%s):\n"),
1125 prefix,
1126 critical ? _("critical") : _("not critical"));
1127
1128 print_aki(str, der);
1129
1130 idx->aki++;
1131 } else if (strcmp(oid, "2.5.29.15") == 0) {
1132 if (idx->keyusage) {
1133 addf(str,
1134 "warning: more than one key usage extension\n");
1135 }
1136
1137 addf(str, _("%s\t\tKey Usage (%s):\n"), prefix,
1138 critical ? _("critical") : _("not critical"));
1139
1140 snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
1141 print_key_usage(str, pfx, der);
1142
1143 idx->keyusage++;
1144 } else if (strcmp(oid, "2.5.29.16") == 0) {
1145 if (idx->pkey_usage_period) {
1146 addf(str,
1147 "warning: more than one private key usage period extension\n");
1148 }
1149
1150 addf(str,
1151 _("%s\t\tPrivate Key Usage Period (%s):\n"),
1152 prefix,
1153 critical ? _("critical") : _("not critical"));
1154
1155 print_private_key_usage_period(str, prefix, der);
1156
1157 idx->pkey_usage_period++;
1158 } else if (strcmp(oid, "2.5.29.37") == 0) {
1159 if (idx->keypurpose) {
1160 addf(str,
1161 "warning: more than one key purpose extension\n");
1162 }
1163
1164 addf(str, _("%s\t\tKey Purpose (%s):\n"), prefix,
1165 critical ? _("critical") : _("not critical"));
1166
1167 print_key_purpose(str, prefix, der);
1168 idx->keypurpose++;
1169 } else if (strcmp(oid, "2.5.29.17") == 0) {
1170 if (idx->san) {
1171 addf(str,
1172 "warning: more than one SKI extension\n");
1173 }
1174
1175 addf(str,
1176 _("%s\t\tSubject Alternative Name (%s):\n"),
1177 prefix,
1178 critical ? _("critical") : _("not critical"));
1179 print_altname(str, prefix, der);
1180 idx->san++;
1181 } else if (strcmp(oid, "2.5.29.18") == 0) {
1182 if (idx->ian) {
1183 addf(str,
1184 "warning: more than one Issuer AltName extension\n");
1185 }
1186
1187 addf(str,
1188 _("%s\t\tIssuer Alternative Name (%s):\n"),
1189 prefix,
1190 critical ? _("critical") : _("not critical"));
1191
1192 print_altname(str, prefix, der);
1193
1194 idx->ian++;
1195 } else if (strcmp(oid, "2.5.29.31") == 0) {
1196 if (idx->crldist) {
1197 addf(str,
1198 "warning: more than one CRL distribution point\n");
1199 }
1200
1201 addf(str,
1202 _("%s\t\tCRL Distribution points (%s):\n"),
1203 prefix,
1204 critical ? _("critical") : _("not critical"));
1205
1206 print_crldist(str, der);
1207 idx->crldist++;
1208 } else if (strcmp(oid, "1.3.6.1.5.5.7.1.14") == 0) {
1209 if (idx->proxy) {
1210 addf(str,
1211 "warning: more than one proxy extension\n");
1212 }
1213
1214 addf(str,
1215 _
1216 ("%s\t\tProxy Certificate Information (%s):\n"),
1217 prefix,
1218 critical ? _("critical") : _("not critical"));
1219
1220 print_proxy(str, der);
1221
1222 idx->proxy++;
1223 } else if (strcmp(oid, "1.3.6.1.5.5.7.1.1") == 0) {
1224 addf(str, _("%s\t\tAuthority Information "
1225 "Access (%s):\n"), prefix,
1226 critical ? _("critical") : _("not critical"));
1227
1228 print_aia(str, der);
1229 } else if (strcmp(oid, "2.5.29.30") == 0) {
1230 if (idx->nc) {
1231 addf(str,
1232 "warning: more than one name constraints extension\n");
1233 }
1234 idx->nc++;
1235
1236 addf(str, _("%s\t\tName Constraints (%s):\n"), prefix,
1237 critical ? _("critical") : _("not critical"));
1238
1239 print_nc(str, prefix, der);
1240 } else if (strcmp(oid, GNUTLS_X509EXT_OID_TLSFEATURES) == 0) {
1241 if (idx->tlsfeatures) {
1242 addf(str,
1243 "warning: more than one tlsfeatures extension\n");
1244 }
1245
1246 addf(str, _("%s\t\tTLS Features (%s):\n"),
1247 prefix,
1248 critical ? _("critical") : _("not critical"));
1249
1250 print_tlsfeatures(str, prefix, der);
1251
1252 idx->tlsfeatures++;
1253 } else if (strcmp(oid, "1.2.643.100.111") == 0) {
1254 addf(str, _("%s\t\tSubject Signing Tool(%s):\n"),
1255 prefix,
1256 critical ? _("critical") : _("not critical"));
1257
1258 print_subject_sign_tool(str, prefix, der);
1259 } else if (strcmp(oid, "1.2.643.100.112") == 0) {
1260 addf(str, _("%s\t\tIssuer Signing Tool(%s):\n"),
1261 prefix,
1262 critical ? _("critical") : _("not critical"));
1263
1264 print_issuer_sign_tool(str, prefix, der);
1265 } else if (strcmp(oid, "2.5.4.3") == 0) {
1266 int ret;
1267 gnutls_datum_t tmp = {NULL, 0};
1268
1269 addf(str, _("%s\t\tCommon Name (%s):\n"),
1270 prefix,
1271 critical ? _("critical") : _("not critical"));
1272
1273 ret = _gnutls_x509_decode_string(ASN1_ETYPE_PRINTABLE_STRING, der->data, der->size, &tmp, 0);
1274 if (ret < 0) {
1275 addf(str, "error: x509_decode_string: %s\n",
1276 gnutls_strerror(ret));
1277 } else {
1278 addf(str, "%s\t\t\t%s\n", prefix, tmp.data);
1279 gnutls_free(tmp.data);
1280 }
1281 } else {
1282 addf(str, _("%s\t\tUnknown extension %s (%s):\n"),
1283 prefix, oid,
1284 critical ? _("critical") : _("not critical"));
1285
1286 addf(str, _("%s\t\t\tASCII: "), prefix);
1287 _gnutls_buffer_asciiprint(str, (char*)der->data, der->size);
1288
1289 addf(str, "\n");
1290 addf(str, _("%s\t\t\tHexdump: "), prefix);
1291 _gnutls_buffer_hexprint(str, (char*)der->data, der->size);
1292 adds(str, "\n");
1293 }
1294 }
1295
1296 static void
print_extensions(gnutls_buffer_st * str,const char * prefix,int type,cert_type_t cert)1297 print_extensions(gnutls_buffer_st * str, const char *prefix, int type,
1298 cert_type_t cert)
1299 {
1300 unsigned i;
1301 int err;
1302 gnutls_datum_t der = {NULL, 0};
1303 struct ext_indexes_st idx;
1304
1305 memset(&idx, 0, sizeof(idx));
1306
1307 for (i = 0;; i++) {
1308 char oid[MAX_OID_SIZE] = "";
1309 size_t sizeof_oid = sizeof(oid);
1310 unsigned int critical;
1311
1312 if (type == TYPE_CRT)
1313 err =
1314 gnutls_x509_crt_get_extension_info(cert.crt, i,
1315 oid,
1316 &sizeof_oid,
1317 &critical);
1318
1319 else if (type == TYPE_CRQ)
1320 err =
1321 gnutls_x509_crq_get_extension_info(cert.crq, i,
1322 oid,
1323 &sizeof_oid,
1324 &critical);
1325 else {
1326 gnutls_assert();
1327 return;
1328 }
1329
1330 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1331 break;
1332 if (err < 0) {
1333 addf(str, "error: get_extension_info: %s\n",
1334 gnutls_strerror(err));
1335 break;
1336 }
1337
1338 if (i == 0)
1339 addf(str, _("%s\tExtensions:\n"), prefix);
1340
1341 if (type == TYPE_CRT)
1342 err = gnutls_x509_crt_get_extension_data2(cert.crt, i, &der);
1343 else
1344 err = gnutls_x509_crq_get_extension_data2(cert.crq, i, &der);
1345
1346 if (err < 0) {
1347 der.data = NULL;
1348 der.size = 0;
1349 }
1350
1351 print_extension(str, prefix, &idx, oid, critical, &der);
1352 gnutls_free(der.data);
1353 }
1354 }
1355
reverse_datum(gnutls_datum_t * d)1356 static void reverse_datum(gnutls_datum_t *d)
1357 {
1358 unsigned int i;
1359 unsigned char c;
1360
1361 for (i = 0; i < d->size / 2; i++) {
1362 c = d->data[i];
1363 d->data[i] = d->data[d->size - i - 1];
1364 d->data[d->size - i - 1] = c;
1365 }
1366 }
1367
1368 static void
print_pubkey(gnutls_buffer_st * str,const char * key_name,gnutls_pubkey_t pubkey,gnutls_x509_spki_st * spki,gnutls_certificate_print_formats_t format)1369 print_pubkey(gnutls_buffer_st * str, const char *key_name,
1370 gnutls_pubkey_t pubkey, gnutls_x509_spki_st *spki,
1371 gnutls_certificate_print_formats_t format)
1372 {
1373 int err;
1374 const char *name;
1375 unsigned bits;
1376 unsigned pk;
1377
1378 err = gnutls_pubkey_get_pk_algorithm(pubkey, &bits);
1379 if (err < 0) {
1380 addf(str, "error: get_pk_algorithm: %s\n",
1381 gnutls_strerror(err));
1382 return;
1383 }
1384
1385 pk = err;
1386
1387 name = gnutls_pk_algorithm_get_name(pk);
1388 if (name == NULL)
1389 name = _("unknown");
1390
1391 addf(str, _("\t%sPublic Key Algorithm: %s\n"), key_name, name);
1392
1393 addf(str, _("\tAlgorithm Security Level: %s (%d bits)\n"),
1394 gnutls_sec_param_get_name(gnutls_pk_bits_to_sec_param
1395 (err, bits)), bits);
1396
1397 if (spki && pk == GNUTLS_PK_RSA_PSS && spki->pk == pk) {
1398 addf(str, _("\t\tParameters:\n"));
1399 addf(str, "\t\t\tHash Algorithm: %s\n",
1400 gnutls_digest_get_name(spki->rsa_pss_dig));
1401 addf(str, "\t\t\tSalt Length: %d\n", spki->salt_size);
1402 }
1403
1404 switch (pk) {
1405 case GNUTLS_PK_RSA:
1406 case GNUTLS_PK_RSA_PSS:
1407 {
1408 gnutls_datum_t m, e;
1409
1410 err = gnutls_pubkey_get_pk_rsa_raw(pubkey, &m, &e);
1411 if (err < 0)
1412 addf(str, "error: get_pk_rsa_raw: %s\n",
1413 gnutls_strerror(err));
1414 else {
1415 if (format ==
1416 GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1417 addf(str,
1418 _("\t\tModulus (bits %d): "),
1419 bits);
1420 _gnutls_buffer_hexprint(str,
1421 m.data,
1422 m.size);
1423 adds(str, "\n");
1424 addf(str,
1425 _("\t\tExponent (bits %d): "),
1426 e.size * 8);
1427 _gnutls_buffer_hexprint(str,
1428 e.data,
1429 e.size);
1430 adds(str, "\n");
1431 } else {
1432 addf(str,
1433 _("\t\tModulus (bits %d):\n"),
1434 bits);
1435 _gnutls_buffer_hexdump(str, m.data,
1436 m.size,
1437 "\t\t\t");
1438 addf(str,
1439 _
1440 ("\t\tExponent (bits %d):\n"),
1441 e.size * 8);
1442 _gnutls_buffer_hexdump(str, e.data,
1443 e.size,
1444 "\t\t\t");
1445 }
1446
1447 gnutls_free(m.data);
1448 gnutls_free(e.data);
1449 }
1450
1451 }
1452 break;
1453
1454 case GNUTLS_PK_EDDSA_ED25519:
1455 case GNUTLS_PK_EDDSA_ED448:
1456 case GNUTLS_PK_ECDSA:
1457 {
1458 gnutls_datum_t x, y;
1459 gnutls_ecc_curve_t curve;
1460
1461 err =
1462 gnutls_pubkey_get_pk_ecc_raw(pubkey, &curve,
1463 &x, &y);
1464 if (err < 0) {
1465 addf(str, "error: get_pk_ecc_raw: %s\n",
1466 gnutls_strerror(err));
1467 } else {
1468 addf(str, _("\t\tCurve:\t%s\n"),
1469 gnutls_ecc_curve_get_name(curve));
1470 if (format ==
1471 GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1472 adds(str, _("\t\tX: "));
1473 _gnutls_buffer_hexprint(str,
1474 x.data,
1475 x.size);
1476 adds(str, "\n");
1477 if (y.size > 0) {
1478 adds(str, _("\t\tY: "));
1479 _gnutls_buffer_hexprint(str,
1480 y.data,
1481 y.size);
1482 adds(str, "\n");
1483 }
1484 } else {
1485 adds(str, _("\t\tX:\n"));
1486 _gnutls_buffer_hexdump(str, x.data,
1487 x.size,
1488 "\t\t\t");
1489 if (y.size > 0) {
1490 adds(str, _("\t\tY:\n"));
1491 _gnutls_buffer_hexdump(str, y.data,
1492 y.size,
1493 "\t\t\t");
1494 }
1495 }
1496
1497 gnutls_free(x.data);
1498 gnutls_free(y.data);
1499
1500 }
1501 }
1502 break;
1503 case GNUTLS_PK_DSA:
1504 {
1505 gnutls_datum_t p, q, g, y;
1506
1507 err =
1508 gnutls_pubkey_get_pk_dsa_raw(pubkey, &p, &q,
1509 &g, &y);
1510 if (err < 0)
1511 addf(str, "error: get_pk_dsa_raw: %s\n",
1512 gnutls_strerror(err));
1513 else {
1514 if (format ==
1515 GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1516 addf(str,
1517 _
1518 ("\t\tPublic key (bits %d): "),
1519 bits);
1520 _gnutls_buffer_hexprint(str,
1521 y.data,
1522 y.size);
1523 adds(str, "\n");
1524 adds(str, _("\t\tP: "));
1525 _gnutls_buffer_hexprint(str,
1526 p.data,
1527 p.size);
1528 adds(str, "\n");
1529 adds(str, _("\t\tQ: "));
1530 _gnutls_buffer_hexprint(str,
1531 q.data,
1532 q.size);
1533 adds(str, "\n");
1534 adds(str, _("\t\tG: "));
1535 _gnutls_buffer_hexprint(str,
1536 g.data,
1537 g.size);
1538 adds(str, "\n");
1539 } else {
1540 addf(str,
1541 _
1542 ("\t\tPublic key (bits %d):\n"),
1543 bits);
1544 _gnutls_buffer_hexdump(str, y.data,
1545 y.size,
1546 "\t\t\t");
1547 adds(str, _("\t\tP:\n"));
1548 _gnutls_buffer_hexdump(str, p.data,
1549 p.size,
1550 "\t\t\t");
1551 adds(str, _("\t\tQ:\n"));
1552 _gnutls_buffer_hexdump(str, q.data,
1553 q.size,
1554 "\t\t\t");
1555 adds(str, _("\t\tG:\n"));
1556 _gnutls_buffer_hexdump(str, g.data,
1557 g.size,
1558 "\t\t\t");
1559 }
1560
1561 gnutls_free(p.data);
1562 gnutls_free(q.data);
1563 gnutls_free(g.data);
1564 gnutls_free(y.data);
1565
1566 }
1567 }
1568 break;
1569
1570 case GNUTLS_PK_GOST_01:
1571 case GNUTLS_PK_GOST_12_256:
1572 case GNUTLS_PK_GOST_12_512:
1573 {
1574 gnutls_datum_t x, y;
1575 gnutls_ecc_curve_t curve;
1576 gnutls_digest_algorithm_t digest;
1577 gnutls_gost_paramset_t param;
1578
1579 err =
1580 gnutls_pubkey_export_gost_raw2(pubkey, &curve,
1581 &digest,
1582 ¶m,
1583 &x, &y, 0);
1584 if (err < 0)
1585 addf(str, "error: get_pk_gost_raw: %s\n",
1586 gnutls_strerror(err));
1587 else {
1588 addf(str, _("\t\tCurve:\t%s\n"),
1589 gnutls_ecc_curve_get_name(curve));
1590 addf(str, _("\t\tDigest:\t%s\n"),
1591 gnutls_digest_get_name(digest));
1592 addf(str, _("\t\tParamSet: %s\n"),
1593 gnutls_gost_paramset_get_name(param));
1594 reverse_datum(&x);
1595 reverse_datum(&y);
1596 if (format ==
1597 GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1598 adds(str, _("\t\tX: "));
1599 _gnutls_buffer_hexprint(str,
1600 x.data,
1601 x.size);
1602 adds(str, "\n");
1603 adds(str, _("\t\tY: "));
1604 _gnutls_buffer_hexprint(str,
1605 y.data,
1606 y.size);
1607 adds(str, "\n");
1608 } else {
1609 adds(str, _("\t\tX:\n"));
1610 _gnutls_buffer_hexdump(str, x.data,
1611 x.size,
1612 "\t\t\t");
1613 adds(str, _("\t\tY:\n"));
1614 _gnutls_buffer_hexdump(str, y.data,
1615 y.size,
1616 "\t\t\t");
1617 }
1618
1619 gnutls_free(x.data);
1620 gnutls_free(y.data);
1621
1622 }
1623 }
1624 break;
1625
1626 default:
1627 break;
1628 }
1629 }
1630
1631 static int
print_crt_sig_params(gnutls_buffer_st * str,gnutls_x509_crt_t crt,gnutls_certificate_print_formats_t format)1632 print_crt_sig_params(gnutls_buffer_st * str, gnutls_x509_crt_t crt,
1633 gnutls_certificate_print_formats_t format)
1634 {
1635 int ret;
1636 gnutls_pk_algorithm_t pk;
1637 gnutls_x509_spki_st params;
1638 gnutls_sign_algorithm_t sign;
1639
1640 sign = gnutls_x509_crt_get_signature_algorithm(crt);
1641 pk = gnutls_sign_get_pk_algorithm(sign);
1642 if (pk == GNUTLS_PK_RSA_PSS) {
1643 ret = _gnutls_x509_read_sign_params(crt->cert,
1644 "signatureAlgorithm",
1645 ¶ms);
1646 if (ret < 0) {
1647 addf(str, "error: read_pss_params: %s\n",
1648 gnutls_strerror(ret));
1649 } else
1650 addf(str, "\t\tSalt Length: %d\n", params.salt_size);
1651 }
1652
1653 return 0;
1654 }
1655
print_pk_name(gnutls_buffer_st * str,gnutls_x509_crt_t crt)1656 static void print_pk_name(gnutls_buffer_st * str, gnutls_x509_crt_t crt)
1657 {
1658 const char *p;
1659 char *name = get_pk_name(crt, NULL);
1660 if (name == NULL)
1661 p = _("unknown");
1662 else
1663 p = name;
1664
1665 addf(str, "\tSubject Public Key Algorithm: %s\n", p);
1666 gnutls_free(name);
1667 }
1668
1669 static int
print_crt_pubkey(gnutls_buffer_st * str,gnutls_x509_crt_t crt,gnutls_certificate_print_formats_t format)1670 print_crt_pubkey(gnutls_buffer_st * str, gnutls_x509_crt_t crt,
1671 gnutls_certificate_print_formats_t format)
1672 {
1673 gnutls_pubkey_t pubkey = NULL;
1674 gnutls_x509_spki_st params;
1675 int ret, pk;
1676
1677 ret = _gnutls_x509_crt_read_spki_params(crt, ¶ms);
1678 if (ret < 0)
1679 return ret;
1680
1681 pk = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
1682 if (pk < 0) {
1683 gnutls_assert();
1684 pk = GNUTLS_PK_UNKNOWN;
1685 }
1686
1687 if (pk == GNUTLS_PK_UNKNOWN) {
1688 print_pk_name(str, crt); /* print basic info only */
1689 return 0;
1690 }
1691
1692 ret = gnutls_pubkey_init(&pubkey);
1693 if (ret < 0)
1694 return ret;
1695
1696 ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
1697 if (ret < 0) {
1698 if (ret != GNUTLS_E_UNIMPLEMENTED_FEATURE)
1699 addf(str, "error importing public key: %s\n", gnutls_strerror(ret));
1700 print_pk_name(str, crt); /* print basic info only */
1701 ret = 0;
1702 goto cleanup;
1703 }
1704
1705 print_pubkey(str, _("Subject "), pubkey, ¶ms, format);
1706 ret = 0;
1707
1708 cleanup:
1709 gnutls_pubkey_deinit(pubkey);
1710
1711 return ret;
1712 }
1713
1714 static void
print_cert(gnutls_buffer_st * str,gnutls_x509_crt_t cert,gnutls_certificate_print_formats_t format)1715 print_cert(gnutls_buffer_st * str, gnutls_x509_crt_t cert,
1716 gnutls_certificate_print_formats_t format)
1717 {
1718 /* Version. */
1719 {
1720 int version = gnutls_x509_crt_get_version(cert);
1721 if (version < 0)
1722 addf(str, "error: get_version: %s\n",
1723 gnutls_strerror(version));
1724 else
1725 addf(str, _("\tVersion: %d\n"), version);
1726 }
1727
1728 /* Serial. */
1729 {
1730 char serial[128];
1731 size_t serial_size = sizeof(serial);
1732 int err;
1733
1734 err =
1735 gnutls_x509_crt_get_serial(cert, serial, &serial_size);
1736 if (err < 0)
1737 addf(str, "error: get_serial: %s\n",
1738 gnutls_strerror(err));
1739 else {
1740 adds(str, _("\tSerial Number (hex): "));
1741 _gnutls_buffer_hexprint(str, serial, serial_size);
1742 adds(str, "\n");
1743 }
1744 }
1745
1746 /* Issuer. */
1747 if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1748 gnutls_datum_t dn;
1749 int err;
1750
1751 err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
1752 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1753 addf(str, _("\tIssuer:\n"));
1754 } else if (err < 0) {
1755 addf(str, "error: get_issuer_dn: %s\n",
1756 gnutls_strerror(err));
1757 } else {
1758 addf(str, _("\tIssuer: %s\n"), dn.data);
1759 gnutls_free(dn.data);
1760 }
1761 }
1762
1763 /* Validity. */
1764 {
1765 time_t tim;
1766
1767 adds(str, _("\tValidity:\n"));
1768
1769 tim = gnutls_x509_crt_get_activation_time(cert);
1770 if (tim != -1) {
1771 char s[42];
1772 size_t max = sizeof(s);
1773 struct tm t;
1774
1775 if (gmtime_r(&tim, &t) == NULL)
1776 addf(str, "error: gmtime_r (%ld)\n",
1777 (unsigned long) tim);
1778 else if (strftime
1779 (s, max, "%a %b %d %H:%M:%S UTC %Y",
1780 &t) == 0)
1781 addf(str, "error: strftime (%ld)\n",
1782 (unsigned long) tim);
1783 else
1784 addf(str, _("\t\tNot Before: %s\n"), s);
1785 } else {
1786 addf(str, _("\t\tNot Before: %s\n"), _("unknown"));
1787 }
1788
1789 tim = gnutls_x509_crt_get_expiration_time(cert);
1790 if (tim != -1) {
1791 char s[42];
1792 size_t max = sizeof(s);
1793 struct tm t;
1794
1795 if (gmtime_r(&tim, &t) == NULL)
1796 addf(str, "error: gmtime_r (%ld)\n",
1797 (unsigned long) tim);
1798 else if (strftime
1799 (s, max, "%a %b %d %H:%M:%S UTC %Y",
1800 &t) == 0)
1801 addf(str, "error: strftime (%ld)\n",
1802 (unsigned long) tim);
1803 else
1804 addf(str, _("\t\tNot After: %s\n"), s);
1805 } else {
1806 addf(str, _("\t\tNot After: %s\n"), _("unknown"));
1807 }
1808 }
1809
1810 /* Subject. */
1811 {
1812 gnutls_datum_t dn;
1813 int err;
1814
1815 err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
1816 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1817 addf(str, _("\tSubject:\n"));
1818 } else if (err < 0) {
1819 addf(str, "error: get_dn: %s\n",
1820 gnutls_strerror(err));
1821 } else {
1822 addf(str, _("\tSubject: %s\n"), dn.data);
1823 gnutls_free(dn.data);
1824 }
1825 }
1826
1827 /* SubjectPublicKeyInfo. */
1828 print_crt_pubkey(str, cert, format);
1829
1830 print_unique_ids(str, cert);
1831
1832 /* Extensions. */
1833 if (gnutls_x509_crt_get_version(cert) >= 3) {
1834 cert_type_t ccert;
1835
1836 ccert.crt = cert;
1837 print_extensions(str, "", TYPE_CRT, ccert);
1838 }
1839
1840 /* Signature. */
1841 if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1842 int err;
1843 size_t size = 0;
1844 char *buffer = NULL;
1845 char *name;
1846 const char *p;
1847
1848 name = get_sign_name(cert, &err);
1849 if (name == NULL)
1850 p = _("unknown");
1851 else
1852 p = name;
1853
1854 addf(str, _("\tSignature Algorithm: %s\n"), p);
1855 gnutls_free(name);
1856
1857 print_crt_sig_params(str, cert, format);
1858
1859 if (err != GNUTLS_SIGN_UNKNOWN && gnutls_sign_is_secure2(err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
1860 adds(str,
1861 _("warning: signed using a broken signature "
1862 "algorithm that can be forged.\n"));
1863 }
1864
1865 err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1866 if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
1867 addf(str, "error: get_signature: %s\n",
1868 gnutls_strerror(err));
1869 return;
1870 }
1871
1872 buffer = gnutls_malloc(size);
1873 if (!buffer) {
1874 addf(str, "error: malloc: %s\n",
1875 gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
1876 return;
1877 }
1878
1879 err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1880 if (err < 0) {
1881 gnutls_free(buffer);
1882 addf(str, "error: get_signature2: %s\n",
1883 gnutls_strerror(err));
1884 return;
1885 }
1886
1887 adds(str, _("\tSignature:\n"));
1888 _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
1889
1890 gnutls_free(buffer);
1891 }
1892 }
1893
1894 static void
print_fingerprint(gnutls_buffer_st * str,gnutls_x509_crt_t cert)1895 print_fingerprint(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
1896 {
1897 int err;
1898 char buffer[MAX_HASH_SIZE];
1899 size_t size = sizeof(buffer);
1900
1901 adds(str, _("\tFingerprint:\n"));
1902
1903 err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer, &size);
1904 if (err < 0) {
1905 addf(str, "error: get_fingerprint: %s\n",
1906 gnutls_strerror(err));
1907 return;
1908 }
1909
1910 adds(str, _("\t\tsha1:"));
1911 _gnutls_buffer_hexprint(str, buffer, size);
1912 adds(str, "\n");
1913
1914 size = sizeof(buffer);
1915 err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, buffer, &size);
1916 if (err < 0) {
1917 addf(str, "error: get_fingerprint: %s\n",
1918 gnutls_strerror(err));
1919 return;
1920 }
1921 adds(str, _("\t\tsha256:"));
1922 _gnutls_buffer_hexprint(str, buffer, size);
1923 adds(str, "\n");
1924 }
1925
1926 typedef int get_id_func(void *obj, unsigned, unsigned char*, size_t*);
1927
print_obj_id(gnutls_buffer_st * str,const char * prefix,void * obj,get_id_func * get_id)1928 static void print_obj_id(gnutls_buffer_st *str, const char *prefix, void *obj, get_id_func *get_id)
1929 {
1930 unsigned char sha1_buffer[MAX_HASH_SIZE];
1931 unsigned char sha2_buffer[MAX_HASH_SIZE];
1932 int err;
1933 size_t sha1_size, sha2_size;
1934
1935 sha1_size = sizeof(sha1_buffer);
1936 err = get_id(obj, GNUTLS_KEYID_USE_SHA1, sha1_buffer, &sha1_size);
1937 if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1938 return;
1939
1940 if (err < 0) {
1941 addf(str, "error: get_key_id(sha1): %s\n", gnutls_strerror(err));
1942 return;
1943 }
1944
1945 sha2_size = sizeof(sha2_buffer);
1946 err = get_id(obj, GNUTLS_KEYID_USE_SHA256, sha2_buffer, &sha2_size);
1947 if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1948 return;
1949
1950 if (err < 0) {
1951 addf(str, "error: get_key_id(sha256): %s\n", gnutls_strerror(err));
1952 return;
1953 }
1954
1955 addf(str, _("%sPublic Key ID:\n%s\tsha1:"), prefix, prefix);
1956 _gnutls_buffer_hexprint(str, sha1_buffer, sha1_size);
1957 addf(str, "\n%s\tsha256:", prefix);
1958 _gnutls_buffer_hexprint(str, sha2_buffer, sha2_size);
1959 adds(str, "\n");
1960
1961 addf(str, _("%sPublic Key PIN:\n%s\tpin-sha256:"), prefix, prefix);
1962 _gnutls_buffer_base64print(str, sha2_buffer, sha2_size);
1963 adds(str, "\n");
1964
1965 return;
1966 }
1967
print_keyid(gnutls_buffer_st * str,gnutls_x509_crt_t cert)1968 static void print_keyid(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
1969 {
1970 int err;
1971 const char *name;
1972 unsigned int bits;
1973 unsigned char sha1_buffer[MAX_HASH_SIZE];
1974 size_t sha1_size;
1975
1976 err = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
1977 if (err < 0)
1978 return;
1979
1980 print_obj_id(str, "\t", cert, (get_id_func*)gnutls_x509_crt_get_key_id);
1981
1982 if (IS_EC(err)) {
1983 gnutls_ecc_curve_t curve;
1984
1985 err = gnutls_x509_crt_get_pk_ecc_raw(cert, &curve, NULL, NULL);
1986 if (err < 0)
1987 return;
1988
1989 name = gnutls_ecc_curve_get_name(curve);
1990 bits = 0;
1991 } else if (IS_GOSTEC(err)) {
1992 gnutls_ecc_curve_t curve;
1993
1994 err = gnutls_x509_crt_get_pk_gost_raw(cert, &curve, NULL, NULL, NULL, NULL);
1995 if (err < 0)
1996 return;
1997
1998 name = gnutls_ecc_curve_get_name(curve);
1999 bits = 0;
2000 } else {
2001 name = gnutls_pk_get_name(err);
2002 }
2003
2004 if (name == NULL)
2005 return;
2006
2007 sha1_size = sizeof(sha1_buffer);
2008 err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA1, sha1_buffer, &sha1_size);
2009 if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
2010 return;
2011 }
2012
2013 static void
print_other(gnutls_buffer_st * str,gnutls_x509_crt_t cert,gnutls_certificate_print_formats_t format)2014 print_other(gnutls_buffer_st * str, gnutls_x509_crt_t cert,
2015 gnutls_certificate_print_formats_t format)
2016 {
2017 if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
2018 print_fingerprint(str, cert);
2019 }
2020 print_keyid(str, cert);
2021 }
2022
print_oneline(gnutls_buffer_st * str,gnutls_x509_crt_t cert)2023 static void print_oneline(gnutls_buffer_st * str, gnutls_x509_crt_t cert)
2024 {
2025 int err;
2026
2027 /* Subject. */
2028 {
2029 gnutls_datum_t dn;
2030
2031 err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
2032 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2033 addf(str, _("no subject,"));
2034 } else if (err < 0) {
2035 addf(str, "unknown subject (%s), ",
2036 gnutls_strerror(err));
2037 } else {
2038 addf(str, "subject `%s', ", dn.data);
2039 gnutls_free(dn.data);
2040 }
2041 }
2042
2043 /* Issuer. */
2044 {
2045 gnutls_datum_t dn;
2046
2047 err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
2048 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2049 addf(str, _("no issuer,"));
2050 } else if (err < 0) {
2051 addf(str, "unknown issuer (%s), ",
2052 gnutls_strerror(err));
2053 } else {
2054 addf(str, "issuer `%s', ", dn.data);
2055 gnutls_free(dn.data);
2056 }
2057 }
2058
2059 {
2060 char serial[128];
2061 size_t serial_size = sizeof(serial);
2062
2063 err =
2064 gnutls_x509_crt_get_serial(cert, serial, &serial_size);
2065 if (err >= 0) {
2066 adds(str, "serial 0x");
2067 _gnutls_buffer_hexprint(str, serial, serial_size);
2068 adds(str, ", ");
2069 }
2070 }
2071
2072 /* Key algorithm and size. */
2073 {
2074 unsigned int bits;
2075 const char *p;
2076 char *name = get_pk_name(cert, &bits);
2077 if (name == NULL)
2078 p = _("unknown");
2079 else
2080 p = name;
2081 addf(str, "%s key %d bits, ", p, bits);
2082 gnutls_free(name);
2083 }
2084
2085 /* Signature Algorithm. */
2086 {
2087 char *name = get_sign_name(cert, &err);
2088 const char *p;
2089
2090 if (name == NULL)
2091 p = _("unknown");
2092 else
2093 p = name;
2094
2095 if (err != GNUTLS_SIGN_UNKNOWN && gnutls_sign_is_secure2(err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0)
2096 addf(str, _("signed using %s (broken!), "), p);
2097 else
2098 addf(str, _("signed using %s, "), p);
2099 gnutls_free(name);
2100 }
2101
2102 /* Validity. */
2103 {
2104 time_t tim;
2105
2106 tim = gnutls_x509_crt_get_activation_time(cert);
2107 {
2108 char s[42];
2109 size_t max = sizeof(s);
2110 struct tm t;
2111
2112 if (gmtime_r(&tim, &t) == NULL)
2113 addf(str, "unknown activation (%ld), ",
2114 (unsigned long) tim);
2115 else if (strftime
2116 (s, max, "%Y-%m-%d %H:%M:%S UTC",
2117 &t) == 0)
2118 addf(str, "failed activation (%ld), ",
2119 (unsigned long) tim);
2120 else
2121 addf(str, "activated `%s', ", s);
2122 }
2123
2124 tim = gnutls_x509_crt_get_expiration_time(cert);
2125 {
2126 char s[42];
2127 size_t max = sizeof(s);
2128 struct tm t;
2129
2130 if (gmtime_r(&tim, &t) == NULL)
2131 addf(str, "unknown expiry (%ld), ",
2132 (unsigned long) tim);
2133 else if (strftime
2134 (s, max, "%Y-%m-%d %H:%M:%S UTC",
2135 &t) == 0)
2136 addf(str, "failed expiry (%ld), ",
2137 (unsigned long) tim);
2138 else
2139 addf(str, "expires `%s', ", s);
2140 }
2141 }
2142
2143 {
2144 int pathlen;
2145 char *policyLanguage;
2146
2147 err = gnutls_x509_crt_get_proxy(cert, NULL,
2148 &pathlen, &policyLanguage,
2149 NULL, NULL);
2150 if (err == 0) {
2151 addf(str, "proxy certificate (policy=");
2152 if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.1") ==
2153 0)
2154 addf(str, "id-ppl-inheritALL");
2155 else if (strcmp
2156 (policyLanguage,
2157 "1.3.6.1.5.5.7.21.2") == 0)
2158 addf(str, "id-ppl-independent");
2159 else
2160 addf(str, "%s", policyLanguage);
2161 if (pathlen >= 0)
2162 addf(str, ", pathlen=%d), ", pathlen);
2163 else
2164 addf(str, "), ");
2165 gnutls_free(policyLanguage);
2166 }
2167 }
2168
2169 {
2170 unsigned char buffer[MAX_HASH_SIZE];
2171 size_t size = sizeof(buffer);
2172
2173 err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256,
2174 buffer, &size);
2175 if (err >= 0) {
2176 addf(str, "pin-sha256=\"");
2177 _gnutls_buffer_base64print(str, buffer, size);
2178 adds(str, "\"");
2179 }
2180 }
2181
2182 }
2183
2184 /**
2185 * gnutls_x509_crt_print:
2186 * @cert: The data to be printed
2187 * @format: Indicate the format to use
2188 * @out: Newly allocated datum with null terminated string.
2189 *
2190 * This function will pretty print a X.509 certificate, suitable for
2191 * display to a human.
2192 *
2193 * If the format is %GNUTLS_CRT_PRINT_FULL then all fields of the
2194 * certificate will be output, on multiple lines. The
2195 * %GNUTLS_CRT_PRINT_ONELINE format will generate one line with some
2196 * selected fields, which is useful for logging purposes.
2197 *
2198 * The output @out needs to be deallocated using gnutls_free().
2199 *
2200 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2201 * negative error value.
2202 **/
2203 int
gnutls_x509_crt_print(gnutls_x509_crt_t cert,gnutls_certificate_print_formats_t format,gnutls_datum_t * out)2204 gnutls_x509_crt_print(gnutls_x509_crt_t cert,
2205 gnutls_certificate_print_formats_t format,
2206 gnutls_datum_t * out)
2207 {
2208 gnutls_buffer_st str;
2209 int ret;
2210
2211 if (format == GNUTLS_CRT_PRINT_COMPACT) {
2212 _gnutls_buffer_init(&str);
2213
2214 print_oneline(&str, cert);
2215
2216 ret = _gnutls_buffer_append_data(&str, "\n", 1);
2217 if (ret < 0)
2218 return gnutls_assert_val(ret);
2219
2220 print_keyid(&str, cert);
2221
2222 return _gnutls_buffer_to_datum(&str, out, 1);
2223 } else if (format == GNUTLS_CRT_PRINT_ONELINE) {
2224 _gnutls_buffer_init(&str);
2225
2226 print_oneline(&str, cert);
2227
2228 return _gnutls_buffer_to_datum(&str, out, 1);
2229 } else {
2230 _gnutls_buffer_init(&str);
2231
2232 _gnutls_buffer_append_str(&str,
2233 _
2234 ("X.509 Certificate Information:\n"));
2235
2236 print_cert(&str, cert, format);
2237
2238 _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2239
2240 print_other(&str, cert, format);
2241
2242 return _gnutls_buffer_to_datum(&str, out, 1);
2243 }
2244 }
2245
2246 static void
print_crl(gnutls_buffer_st * str,gnutls_x509_crl_t crl,int notsigned)2247 print_crl(gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
2248 {
2249 /* Version. */
2250 {
2251 int version = gnutls_x509_crl_get_version(crl);
2252 if (version < 0)
2253 addf(str, "error: get_version: %s\n",
2254 gnutls_strerror(version));
2255 else
2256 addf(str, _("\tVersion: %d\n"), version);
2257 }
2258
2259 /* Issuer. */
2260 if (!notsigned) {
2261 gnutls_datum_t dn;
2262 int err;
2263
2264 err = gnutls_x509_crl_get_issuer_dn3(crl, &dn, 0);
2265 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2266 addf(str, _("\tIssuer:\n"));
2267 } else if (err < 0) {
2268 addf(str, "error: get_issuer_dn: %s\n",
2269 gnutls_strerror(err));
2270 } else {
2271 addf(str, _("\tIssuer: %s\n"), dn.data);
2272 gnutls_free(dn.data);
2273 }
2274 }
2275
2276 /* Validity. */
2277 {
2278 time_t tim;
2279
2280 adds(str, _("\tUpdate dates:\n"));
2281
2282 tim = gnutls_x509_crl_get_this_update(crl);
2283 {
2284 char s[42];
2285 size_t max = sizeof(s);
2286 struct tm t;
2287
2288 if (gmtime_r(&tim, &t) == NULL)
2289 addf(str, "error: gmtime_r (%ld)\n",
2290 (unsigned long) tim);
2291 else if (strftime
2292 (s, max, "%a %b %d %H:%M:%S UTC %Y",
2293 &t) == 0)
2294 addf(str, "error: strftime (%ld)\n",
2295 (unsigned long) tim);
2296 else
2297 addf(str, _("\t\tIssued: %s\n"), s);
2298 }
2299
2300 tim = gnutls_x509_crl_get_next_update(crl);
2301 {
2302 char s[42];
2303 size_t max = sizeof(s);
2304 struct tm t;
2305
2306 if (tim == -1)
2307 addf(str, "\t\tNo next update time.\n");
2308 else if (gmtime_r(&tim, &t) == NULL)
2309 addf(str, "error: gmtime_r (%ld)\n",
2310 (unsigned long) tim);
2311 else if (strftime
2312 (s, max, "%a %b %d %H:%M:%S UTC %Y",
2313 &t) == 0)
2314 addf(str, "error: strftime (%ld)\n",
2315 (unsigned long) tim);
2316 else
2317 addf(str, _("\t\tNext at: %s\n"), s);
2318 }
2319 }
2320
2321 /* Extensions. */
2322 if (gnutls_x509_crl_get_version(crl) >= 2) {
2323 size_t i;
2324 int err = 0;
2325 int aki_idx = 0;
2326 int crl_nr = 0;
2327
2328 for (i = 0;; i++) {
2329 char oid[MAX_OID_SIZE] = "";
2330 size_t sizeof_oid = sizeof(oid);
2331 unsigned int critical;
2332
2333 err = gnutls_x509_crl_get_extension_info(crl, i,
2334 oid,
2335 &sizeof_oid,
2336 &critical);
2337 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2338 break;
2339 if (err < 0) {
2340 addf(str,
2341 "error: get_extension_info: %s\n",
2342 gnutls_strerror(err));
2343 break;
2344 }
2345
2346 if (i == 0)
2347 adds(str, _("\tExtensions:\n"));
2348
2349 if (strcmp(oid, "2.5.29.20") == 0) {
2350 char nr[128];
2351 size_t nr_size = sizeof(nr);
2352
2353 if (crl_nr) {
2354 addf(str,
2355 "warning: more than one CRL number\n");
2356 }
2357
2358 err =
2359 gnutls_x509_crl_get_number(crl, nr,
2360 &nr_size,
2361 &critical);
2362
2363 addf(str, _("\t\tCRL Number (%s): "),
2364 critical ? _("critical") :
2365 _("not critical"));
2366
2367 if (err < 0)
2368 addf(str,
2369 "error: get_number: %s\n",
2370 gnutls_strerror(err));
2371 else {
2372 _gnutls_buffer_hexprint(str, nr,
2373 nr_size);
2374 addf(str, "\n");
2375 }
2376
2377 crl_nr++;
2378 } else if (strcmp(oid, "2.5.29.35") == 0) {
2379 gnutls_datum_t der;
2380
2381 if (aki_idx) {
2382 addf(str,
2383 "warning: more than one AKI extension\n");
2384 }
2385
2386 addf(str,
2387 _
2388 ("\t\tAuthority Key Identifier (%s):\n"),
2389 critical ? _("critical") :
2390 _("not critical"));
2391
2392 err = gnutls_x509_crl_get_extension_data2(crl, i, &der);
2393 if (err < 0) {
2394 addf(str,
2395 "error: get_extension_data2: %s\n",
2396 gnutls_strerror(err));
2397 continue;
2398 }
2399 print_aki(str, &der);
2400 gnutls_free(der.data);
2401
2402 aki_idx++;
2403 } else {
2404 gnutls_datum_t der;
2405
2406 addf(str,
2407 _("\t\tUnknown extension %s (%s):\n"),
2408 oid,
2409 critical ? _("critical") :
2410 _("not critical"));
2411
2412 err =
2413 gnutls_x509_crl_get_extension_data2(crl,
2414 i,
2415 &der);
2416 if (err < 0) {
2417 addf(str,
2418 "error: get_extension_data2: %s\n",
2419 gnutls_strerror(err));
2420 continue;
2421 }
2422
2423 adds(str, _("\t\t\tASCII: "));
2424 _gnutls_buffer_asciiprint(str, (char*)der.data, der.size);
2425 adds(str, "\n");
2426
2427 adds(str, _("\t\t\tHexdump: "));
2428 _gnutls_buffer_hexprint(str, der.data, der.size);
2429 adds(str, "\n");
2430
2431 gnutls_free(der.data);
2432 }
2433 }
2434 }
2435
2436
2437 /* Revoked certificates. */
2438 {
2439 int num = gnutls_x509_crl_get_crt_count(crl);
2440 gnutls_x509_crl_iter_t iter = NULL;
2441 int j;
2442
2443 if (num)
2444 addf(str, _("\tRevoked certificates (%d):\n"),
2445 num);
2446 else
2447 adds(str, _("\tNo revoked certificates.\n"));
2448
2449 for (j = 0; j < num; j++) {
2450 unsigned char serial[128];
2451 size_t serial_size = sizeof(serial);
2452 int err;
2453 time_t tim;
2454
2455 err =
2456 gnutls_x509_crl_iter_crt_serial(crl, &iter, serial,
2457 &serial_size,
2458 &tim);
2459 if (err < 0) {
2460 addf(str, "error: iter_crt_serial: %s\n",
2461 gnutls_strerror(err));
2462 break;
2463 } else {
2464 char s[42];
2465 size_t max = sizeof(s);
2466 struct tm t;
2467
2468 adds(str, _("\t\tSerial Number (hex): "));
2469 _gnutls_buffer_hexprint(str, serial,
2470 serial_size);
2471 adds(str, "\n");
2472
2473 if (gmtime_r(&tim, &t) == NULL)
2474 addf(str,
2475 "error: gmtime_r (%ld)\n",
2476 (unsigned long) tim);
2477 else if (strftime
2478 (s, max,
2479 "%a %b %d %H:%M:%S UTC %Y",
2480 &t) == 0)
2481 addf(str,
2482 "error: strftime (%ld)\n",
2483 (unsigned long) tim);
2484 else
2485 addf(str,
2486 _("\t\tRevoked at: %s\n"), s);
2487 }
2488 }
2489 gnutls_x509_crl_iter_deinit(iter);
2490 }
2491
2492 /* Signature. */
2493 if (!notsigned) {
2494 int err;
2495 size_t size = 0;
2496 char *buffer = NULL;
2497 char *name;
2498 const char *p;
2499
2500 name = crl_get_sign_name(crl, &err);
2501 if (name == NULL)
2502 p = _("unknown");
2503 else
2504 p = name;
2505
2506 addf(str, _("\tSignature Algorithm: %s\n"), p);
2507 gnutls_free(name);
2508
2509 if (err != GNUTLS_SIGN_UNKNOWN && gnutls_sign_is_secure2(err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
2510 adds(str,
2511 _("warning: signed using a broken signature "
2512 "algorithm that can be forged.\n"));
2513 }
2514
2515 err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2516 if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
2517 addf(str, "error: get_signature: %s\n",
2518 gnutls_strerror(err));
2519 return;
2520 }
2521
2522 buffer = gnutls_malloc(size);
2523 if (!buffer) {
2524 addf(str, "error: malloc: %s\n",
2525 gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
2526 return;
2527 }
2528
2529 err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2530 if (err < 0) {
2531 gnutls_free(buffer);
2532 addf(str, "error: get_signature2: %s\n",
2533 gnutls_strerror(err));
2534 return;
2535 }
2536
2537 adds(str, _("\tSignature:\n"));
2538 _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
2539
2540 gnutls_free(buffer);
2541 }
2542 }
2543
2544 /**
2545 * gnutls_x509_crl_print:
2546 * @crl: The data to be printed
2547 * @format: Indicate the format to use
2548 * @out: Newly allocated datum with null terminated string.
2549 *
2550 * This function will pretty print a X.509 certificate revocation
2551 * list, suitable for display to a human.
2552 *
2553 * The output @out needs to be deallocated using gnutls_free().
2554 *
2555 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2556 * negative error value.
2557 **/
2558 int
gnutls_x509_crl_print(gnutls_x509_crl_t crl,gnutls_certificate_print_formats_t format,gnutls_datum_t * out)2559 gnutls_x509_crl_print(gnutls_x509_crl_t crl,
2560 gnutls_certificate_print_formats_t format,
2561 gnutls_datum_t * out)
2562 {
2563 gnutls_buffer_st str;
2564
2565 _gnutls_buffer_init(&str);
2566
2567 _gnutls_buffer_append_str
2568 (&str, _("X.509 Certificate Revocation List Information:\n"));
2569
2570 print_crl(&str, crl, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
2571
2572 return _gnutls_buffer_to_datum(&str, out, 1);
2573 }
2574
2575 static int
print_crq_sig_params(gnutls_buffer_st * str,gnutls_x509_crq_t crt,gnutls_certificate_print_formats_t format)2576 print_crq_sig_params(gnutls_buffer_st * str, gnutls_x509_crq_t crt,
2577 gnutls_certificate_print_formats_t format)
2578 {
2579 int ret;
2580 gnutls_pk_algorithm_t pk;
2581 gnutls_x509_spki_st params;
2582 gnutls_sign_algorithm_t sign;
2583
2584 sign = gnutls_x509_crq_get_signature_algorithm(crt);
2585 pk = gnutls_sign_get_pk_algorithm(sign);
2586 if (pk == GNUTLS_PK_RSA_PSS) {
2587 ret = _gnutls_x509_read_sign_params(crt->crq,
2588 "signatureAlgorithm",
2589 ¶ms);
2590 if (ret < 0) {
2591 addf(str, "error: read_pss_params: %s\n",
2592 gnutls_strerror(ret));
2593 } else
2594 addf(str, "\t\tSalt Length: %d\n", params.salt_size);
2595 }
2596
2597 return 0;
2598 }
2599
2600 static int
print_crq_pubkey(gnutls_buffer_st * str,gnutls_x509_crq_t crq,gnutls_certificate_print_formats_t format)2601 print_crq_pubkey(gnutls_buffer_st * str, gnutls_x509_crq_t crq,
2602 gnutls_certificate_print_formats_t format)
2603 {
2604 gnutls_pubkey_t pubkey;
2605 gnutls_x509_spki_st params;
2606 int ret;
2607
2608 ret = _gnutls_x509_crq_read_spki_params(crq, ¶ms);
2609 if (ret < 0)
2610 return ret;
2611
2612 ret = gnutls_pubkey_init(&pubkey);
2613 if (ret < 0)
2614 return ret;
2615
2616 ret = gnutls_pubkey_import_x509_crq(pubkey, crq, 0);
2617 if (ret < 0)
2618 goto cleanup;
2619
2620 print_pubkey(str, _("Subject "), pubkey, ¶ms, format);
2621 ret = 0;
2622
2623 cleanup:
2624 gnutls_pubkey_deinit(pubkey);
2625
2626 if (ret < 0) { /* print only name */
2627 const char *p;
2628 char *name = crq_get_pk_name(crq);
2629 if (name == NULL)
2630 p = _("unknown");
2631 else
2632 p = name;
2633
2634 addf(str, "\tSubject Public Key Algorithm: %s\n", p);
2635 gnutls_free(name);
2636 ret = 0;
2637 }
2638
2639 return ret;
2640 }
2641
2642 static void
print_crq(gnutls_buffer_st * str,gnutls_x509_crq_t cert,gnutls_certificate_print_formats_t format)2643 print_crq(gnutls_buffer_st * str, gnutls_x509_crq_t cert,
2644 gnutls_certificate_print_formats_t format)
2645 {
2646 /* Version. */
2647 {
2648 int version = gnutls_x509_crq_get_version(cert);
2649 if (version < 0)
2650 addf(str, "error: get_version: %s\n",
2651 gnutls_strerror(version));
2652 else
2653 addf(str, _("\tVersion: %d\n"), version);
2654 }
2655
2656 /* Subject */
2657 {
2658 gnutls_datum_t dn;
2659 int err;
2660
2661 err = gnutls_x509_crq_get_dn3(cert, &dn, 0);
2662 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2663 addf(str, _("\tSubject:\n"));
2664 } else if (err < 0) {
2665 addf(str, "error: get_dn: %s\n",
2666 gnutls_strerror(err));
2667 } else {
2668 addf(str, _("\tSubject: %s\n"), dn.data);
2669 gnutls_free(dn.data);
2670 }
2671 }
2672
2673 {
2674 char *name;
2675 const char *p;
2676
2677 print_crq_pubkey(str, cert, format);
2678
2679 name = crq_get_sign_name(cert);
2680 if (name == NULL)
2681 p = _("unknown");
2682 else
2683 p = name;
2684
2685 addf(str, _("\tSignature Algorithm: %s\n"), p);
2686
2687 gnutls_free(name);
2688
2689 print_crq_sig_params(str, cert, format);
2690 }
2691
2692 /* parse attributes */
2693 {
2694 size_t i;
2695 int err = 0;
2696 int extensions = 0;
2697 int challenge = 0;
2698
2699 for (i = 0;; i++) {
2700 char oid[MAX_OID_SIZE] = "";
2701 size_t sizeof_oid = sizeof(oid);
2702
2703 err =
2704 gnutls_x509_crq_get_attribute_info(cert, i,
2705 oid,
2706 &sizeof_oid);
2707 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2708 break;
2709 if (err < 0) {
2710 addf(str,
2711 "error: get_extension_info: %s\n",
2712 gnutls_strerror(err));
2713 break;
2714 }
2715
2716 if (i == 0)
2717 adds(str, _("\tAttributes:\n"));
2718
2719 if (strcmp(oid, "1.2.840.113549.1.9.14") == 0) {
2720 cert_type_t ccert;
2721
2722 if (extensions) {
2723 addf(str,
2724 "warning: more than one extensionsRequest\n");
2725 }
2726
2727 ccert.crq = cert;
2728 print_extensions(str, "\t", TYPE_CRQ,
2729 ccert);
2730
2731 extensions++;
2732 } else if (strcmp(oid, "1.2.840.113549.1.9.7") ==
2733 0) {
2734 char *pass;
2735 size_t size;
2736
2737 if (challenge) {
2738 adds(str,
2739 "warning: more than one Challenge password attribute\n");
2740 }
2741
2742 err =
2743 gnutls_x509_crq_get_challenge_password
2744 (cert, NULL, &size);
2745 if (err < 0
2746 && err !=
2747 GNUTLS_E_SHORT_MEMORY_BUFFER) {
2748 addf(str,
2749 "error: get_challenge_password: %s\n",
2750 gnutls_strerror(err));
2751 continue;
2752 }
2753
2754 size++;
2755
2756 pass = gnutls_malloc(size);
2757 if (!pass) {
2758 addf(str, "error: malloc: %s\n",
2759 gnutls_strerror
2760 (GNUTLS_E_MEMORY_ERROR));
2761 continue;
2762 }
2763
2764 err =
2765 gnutls_x509_crq_get_challenge_password
2766 (cert, pass, &size);
2767 if (err < 0)
2768 addf(str,
2769 "error: get_challenge_password: %s\n",
2770 gnutls_strerror(err));
2771 else
2772 addf(str,
2773 _
2774 ("\t\tChallenge password: %s\n"),
2775 pass);
2776
2777 gnutls_free(pass);
2778
2779 challenge++;
2780 } else {
2781 char *buffer;
2782 size_t extlen = 0;
2783
2784 addf(str, _("\t\tUnknown attribute %s:\n"),
2785 oid);
2786
2787 err =
2788 gnutls_x509_crq_get_attribute_data
2789 (cert, i, NULL, &extlen);
2790 if (err < 0) {
2791 addf(str,
2792 "error: get_attribute_data: %s\n",
2793 gnutls_strerror(err));
2794 continue;
2795 }
2796
2797 buffer = gnutls_malloc(extlen);
2798 if (!buffer) {
2799 addf(str, "error: malloc: %s\n",
2800 gnutls_strerror
2801 (GNUTLS_E_MEMORY_ERROR));
2802 continue;
2803 }
2804
2805 err =
2806 gnutls_x509_crq_get_attribute_data
2807 (cert, i, buffer, &extlen);
2808 if (err < 0) {
2809 gnutls_free(buffer);
2810 addf(str,
2811 "error: get_attribute_data2: %s\n",
2812 gnutls_strerror(err));
2813 continue;
2814 }
2815
2816 adds(str, _("\t\t\tASCII: "));
2817 _gnutls_buffer_asciiprint(str, buffer,
2818 extlen);
2819 adds(str, "\n");
2820
2821 adds(str, _("\t\t\tHexdump: "));
2822 _gnutls_buffer_hexprint(str, buffer,
2823 extlen);
2824 adds(str, "\n");
2825
2826 gnutls_free(buffer);
2827 }
2828 }
2829 }
2830 }
2831
print_crq_other(gnutls_buffer_st * str,gnutls_x509_crq_t crq)2832 static void print_crq_other(gnutls_buffer_st * str, gnutls_x509_crq_t crq)
2833 {
2834 int ret;
2835
2836 /* on unknown public key algorithms don't print the key ID */
2837 ret = gnutls_x509_crq_get_pk_algorithm(crq, NULL);
2838 if (ret < 0)
2839 return;
2840
2841 print_obj_id(str, "\t", crq, (get_id_func*)gnutls_x509_crq_get_key_id);
2842 }
2843
2844 /**
2845 * gnutls_x509_crq_print:
2846 * @crq: The data to be printed
2847 * @format: Indicate the format to use
2848 * @out: Newly allocated datum with null terminated string.
2849 *
2850 * This function will pretty print a certificate request, suitable for
2851 * display to a human.
2852 *
2853 * The output @out needs to be deallocated using gnutls_free().
2854 *
2855 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2856 * negative error value.
2857 *
2858 * Since: 2.8.0
2859 **/
2860 int
gnutls_x509_crq_print(gnutls_x509_crq_t crq,gnutls_certificate_print_formats_t format,gnutls_datum_t * out)2861 gnutls_x509_crq_print(gnutls_x509_crq_t crq,
2862 gnutls_certificate_print_formats_t format,
2863 gnutls_datum_t * out)
2864 {
2865 gnutls_buffer_st str;
2866
2867 _gnutls_buffer_init(&str);
2868
2869 _gnutls_buffer_append_str
2870 (&str, _("PKCS #10 Certificate Request Information:\n"));
2871
2872 print_crq(&str, crq, format);
2873
2874 _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2875
2876 print_crq_other(&str, crq);
2877
2878 return _gnutls_buffer_to_datum(&str, out, 1);
2879 }
2880
2881 static void
print_pubkey_other(gnutls_buffer_st * str,gnutls_pubkey_t pubkey,gnutls_certificate_print_formats_t format)2882 print_pubkey_other(gnutls_buffer_st * str, gnutls_pubkey_t pubkey,
2883 gnutls_certificate_print_formats_t format)
2884 {
2885 int ret;
2886 unsigned int usage;
2887
2888 ret = gnutls_pubkey_get_key_usage(pubkey, &usage);
2889 if (ret < 0) {
2890 addf(str, "error: get_key_usage: %s\n",
2891 gnutls_strerror(ret));
2892 return;
2893 }
2894
2895 adds(str, "\n");
2896 if (pubkey->key_usage) {
2897 adds(str, _("Public Key Usage:\n"));
2898 print_key_usage2(str, "\t", pubkey->key_usage);
2899 }
2900
2901 /* on unknown public key algorithms don't print the key ID */
2902 ret = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
2903 if (ret < 0)
2904 return;
2905
2906 print_obj_id(str, "", pubkey, (get_id_func*)gnutls_pubkey_get_key_id);
2907 }
2908
2909 /**
2910 * gnutls_pubkey_print:
2911 * @pubkey: The data to be printed
2912 * @format: Indicate the format to use
2913 * @out: Newly allocated datum with null terminated string.
2914 *
2915 * This function will pretty print public key information, suitable for
2916 * display to a human.
2917 *
2918 * Only %GNUTLS_CRT_PRINT_FULL and %GNUTLS_CRT_PRINT_FULL_NUMBERS
2919 * are implemented.
2920 *
2921 * The output @out needs to be deallocated using gnutls_free().
2922 *
2923 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2924 * negative error value.
2925 *
2926 * Since: 3.1.5
2927 **/
2928 int
gnutls_pubkey_print(gnutls_pubkey_t pubkey,gnutls_certificate_print_formats_t format,gnutls_datum_t * out)2929 gnutls_pubkey_print(gnutls_pubkey_t pubkey,
2930 gnutls_certificate_print_formats_t format,
2931 gnutls_datum_t * out)
2932 {
2933 gnutls_buffer_st str;
2934
2935 _gnutls_buffer_init(&str);
2936
2937 _gnutls_buffer_append_str(&str, _("Public Key Information:\n"));
2938
2939 print_pubkey(&str, "", pubkey, NULL, format);
2940 print_pubkey_other(&str, pubkey, format);
2941
2942 return _gnutls_buffer_to_datum(&str, out, 1);
2943 }
2944
2945 /**
2946 * gnutls_x509_ext_print:
2947 * @exts: The data to be printed
2948 * @exts_size: the number of available structures
2949 * @format: Indicate the format to use
2950 * @out: Newly allocated datum with null terminated string.
2951 *
2952 * This function will pretty print X.509 certificate extensions,
2953 * suitable for display to a human.
2954 *
2955 * The output @out needs to be deallocated using gnutls_free().
2956 *
2957 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2958 * negative error value.
2959 **/
2960 int
gnutls_x509_ext_print(gnutls_x509_ext_st * exts,unsigned int exts_size,gnutls_certificate_print_formats_t format,gnutls_datum_t * out)2961 gnutls_x509_ext_print(gnutls_x509_ext_st *exts, unsigned int exts_size,
2962 gnutls_certificate_print_formats_t format,
2963 gnutls_datum_t * out)
2964 {
2965 gnutls_buffer_st str;
2966 struct ext_indexes_st idx;
2967 unsigned i;
2968
2969 memset(&idx, 0, sizeof(idx));
2970 _gnutls_buffer_init(&str);
2971
2972 for (i=0;i<exts_size;i++)
2973 print_extension(&str, "", &idx, (char*)exts[i].oid, exts[i].critical, &exts[i].data);
2974
2975 return _gnutls_buffer_to_datum(&str, out, 1);
2976 }
2977