Coverage Report

Created: 2026-05-16 07:57

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