Coverage Report

Created: 2026-06-10 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/p11-kit/trust/parser.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2012 Red Hat Inc.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 *     * Redistributions of source code must retain the above
9
 *       copyright notice, this list of conditions and the
10
 *       following disclaimer.
11
 *     * Redistributions in binary form must reproduce the
12
 *       above copyright notice, this list of conditions and
13
 *       the following disclaimer in the documentation and/or
14
 *       other materials provided with the distribution.
15
 *     * The names of contributors to this software may not be
16
 *       used to endorse or promote products derived from this
17
 *       software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30
 * DAMAGE.
31
 *
32
 * Author: Stef Walter <stefw@redhat.com>
33
 */
34
35
#include "config.h"
36
37
#include "array.h"
38
#include "asn1.h"
39
#include "attrs.h"
40
4.96k
#define P11_DEBUG_FLAG P11_DEBUG_TRUST
41
#include "debug.h"
42
#include "dict.h"
43
#include "digest.h"
44
#include "message.h"
45
#include "module.h"
46
#include "oid.h"
47
#include "parser.h"
48
#include "path.h"
49
#include "pem.h"
50
#include "pkcs11x.h"
51
#include "persist.h"
52
#include "types.h"
53
#include "x509.h"
54
55
#include <libtasn1.h>
56
57
#include <sys/types.h>
58
#include <sys/stat.h>
59
60
#include <assert.h>
61
#include <errno.h>
62
#include <fcntl.h>
63
#include <stdarg.h>
64
#include <stdlib.h>
65
#include <string.h>
66
#include <unistd.h>
67
68
#ifdef ENABLE_NLS
69
#include <libintl.h>
70
2.29k
#define _(x) dgettext(PACKAGE_NAME, x)
71
#else
72
#define _(x) (x)
73
#endif
74
75
struct _p11_parser {
76
  p11_asn1_cache *asn1_cache;
77
  p11_dict *asn1_defs;
78
  bool asn1_owned;
79
  p11_persist *persist;
80
  char *basename;
81
  p11_array *parsed;
82
  p11_array *formats;
83
  int flags;
84
};
85
86
#define ID_LENGTH P11_DIGEST_SHA1_LEN
87
88
typedef int (* parser_func)   (p11_parser *parser,
89
                               const unsigned char *data,
90
                               size_t length);
91
92
static CK_ATTRIBUTE *
93
populate_trust (p11_parser *parser,
94
                CK_ATTRIBUTE *attrs)
95
4.00k
{
96
4.00k
  CK_BBOOL trustedv;
97
4.00k
  CK_BBOOL distrustv;
98
99
4.00k
  CK_ATTRIBUTE trusted = { CKA_TRUSTED, &trustedv, sizeof (trustedv) };
100
4.00k
  CK_ATTRIBUTE distrust = { CKA_X_DISTRUSTED, &distrustv, sizeof (distrustv) };
101
102
  /*
103
   * If we're are parsing an anchor location, then warn about any ditsrusted
104
   * certificates there, but don't go ahead and automatically make them
105
   * trusted anchors.
106
   */
107
4.00k
  if (parser->flags & P11_PARSE_FLAG_ANCHOR) {
108
0
    if (p11_attrs_find_bool (attrs, CKA_X_DISTRUSTED, &distrustv) && distrustv) {
109
0
      p11_message (_("certificate with distrust in location for anchors: %s"), parser->basename);
110
0
      return attrs;
111
112
0
    }
113
114
0
    trustedv = CK_TRUE;
115
0
    distrustv = CK_FALSE;
116
117
  /*
118
   * If we're parsing a blocklist location, then force all certificates to
119
   * be distrusted, regardless of whether they contain anchor information.
120
   */
121
4.00k
  } else if (parser->flags & P11_PARSE_FLAG_BLOCKLIST) {
122
0
    if (p11_attrs_find_bool (attrs, CKA_TRUSTED, &trustedv) && trustedv)
123
0
      p11_message (_("overriding trust for anchor in blocklist: %s"), parser->basename);
124
125
0
    trustedv = CK_FALSE;
126
0
    distrustv = CK_TRUE;
127
128
  /*
129
   * If the location doesn't have a flag, then fill in trust attributes
130
   * if they are missing: neither an anchor or blocklist.
131
   */
132
4.00k
  } else {
133
4.00k
    trustedv = CK_FALSE;
134
4.00k
    distrustv = CK_FALSE;
135
136
4.00k
    if (p11_attrs_find_valid (attrs, CKA_TRUSTED))
137
1.82k
      trusted.type = CKA_INVALID;
138
4.00k
    if (p11_attrs_find_valid (attrs, CKA_X_DISTRUSTED))
139
1.75k
      distrust.type = CKA_INVALID;
140
4.00k
  }
141
142
4.00k
  return p11_attrs_build (attrs, &trusted, &distrust, NULL);
143
4.00k
}
144
145
static void
146
sink_object (p11_parser *parser,
147
             CK_ATTRIBUTE *attrs)
148
83.2k
{
149
83.2k
  CK_OBJECT_CLASS klass;
150
151
83.2k
  if (p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
152
7.79k
      klass == CKO_CERTIFICATE) {
153
4.00k
    attrs = populate_trust (parser, attrs);
154
4.00k
    return_if_fail (attrs != NULL);
155
4.00k
  }
156
157
83.2k
  if (!p11_array_push (parser->parsed, attrs))
158
0
    return_if_reached ();
159
83.2k
}
160
161
static CK_ATTRIBUTE *
162
certificate_attrs (p11_parser *parser,
163
                   const unsigned char *der,
164
                   size_t der_len)
165
2.62k
{
166
2.62k
  CK_OBJECT_CLASS klassv = CKO_CERTIFICATE;
167
2.62k
  CK_CERTIFICATE_TYPE x509 = CKC_X_509;
168
2.62k
  CK_BBOOL modifiablev = CK_FALSE;
169
170
2.62k
  CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
171
2.62k
  CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
172
2.62k
  CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) };
173
2.62k
  CK_ATTRIBUTE value = { CKA_VALUE, (void *)der, der_len };
174
175
2.62k
  return p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, NULL);
176
2.62k
}
177
178
int
179
p11_parser_format_x509 (p11_parser *parser,
180
                        const unsigned char *data,
181
                        size_t length)
182
2.26k
{
183
2.26k
  char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
184
2.26k
  CK_ATTRIBUTE *attrs;
185
2.26k
  CK_ATTRIBUTE *value;
186
2.26k
  asn1_node cert;
187
188
2.26k
  cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, length, message);
189
2.26k
  if (cert == NULL)
190
2.25k
    return P11_PARSE_UNRECOGNIZED;
191
192
9
  attrs = certificate_attrs (parser, data, length);
193
9
  return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
194
195
9
  value = p11_attrs_find_valid (attrs, CKA_VALUE);
196
9
  return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
197
9
  p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
198
9
                       value->pValue, value->ulValueLen);
199
200
9
  sink_object (parser, attrs);
201
9
  return P11_PARSE_SUCCESS;
202
9
}
203
204
static CK_ATTRIBUTE *
205
extension_attrs (p11_parser *parser,
206
                 CK_ATTRIBUTE *public_key_info,
207
                 const char *oid_str,
208
                 const unsigned char *oid_der,
209
                 bool critical,
210
                 const unsigned char *value,
211
                 int length)
212
3.12k
{
213
3.12k
  CK_OBJECT_CLASS klassv = CKO_X_CERTIFICATE_EXTENSION;
214
3.12k
  CK_BBOOL modifiablev = CK_FALSE;
215
216
3.12k
  CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
217
3.12k
  CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
218
3.12k
  CK_ATTRIBUTE oid = { CKA_OBJECT_ID, (void *)oid_der, p11_oid_length (oid_der) };
219
220
3.12k
  CK_ATTRIBUTE *attrs;
221
3.12k
  asn1_node dest;
222
3.12k
  unsigned char *der;
223
3.12k
  size_t len;
224
3.12k
  int ret;
225
226
3.12k
  attrs = p11_attrs_build (NULL, public_key_info, &klass, &modifiable, &oid, NULL);
227
3.12k
  return_val_if_fail (attrs != NULL, NULL);
228
229
3.12k
  dest = p11_asn1_create (parser->asn1_defs, "PKIX1.Extension");
230
3.12k
  return_val_if_fail (dest != NULL, NULL);
231
232
3.12k
  ret = asn1_write_value (dest, "extnID", oid_str, 1);
233
3.12k
  return_val_if_fail (ret == ASN1_SUCCESS, NULL);
234
235
3.12k
  if (critical)
236
1.75k
    ret = asn1_write_value (dest, "critical", "TRUE", 1);
237
3.12k
  return_val_if_fail (ret == ASN1_SUCCESS, NULL);
238
239
3.12k
  ret = asn1_write_value (dest, "extnValue", value, length);
240
3.12k
  return_val_if_fail (ret == ASN1_SUCCESS, NULL);
241
242
3.12k
  der = p11_asn1_encode (dest, &len);
243
3.12k
  return_val_if_fail (der != NULL, NULL);
244
245
3.12k
  attrs = p11_attrs_take (attrs, CKA_VALUE, der, len);
246
3.12k
  return_val_if_fail (attrs != NULL, NULL);
247
248
  /* An opmitization so that the builder can get at this without parsing */
249
3.12k
  p11_asn1_cache_take (parser->asn1_cache, dest, "PKIX1.Extension", der, len);
250
3.12k
  return attrs;
251
3.12k
}
252
253
static CK_ATTRIBUTE *
254
attached_attrs (p11_parser *parser,
255
                CK_ATTRIBUTE *public_key_info,
256
                const char *oid_str,
257
                const unsigned char *oid_der,
258
                bool critical,
259
                asn1_node ext)
260
2.25k
{
261
2.25k
  CK_ATTRIBUTE *attrs;
262
2.25k
  unsigned char *der;
263
2.25k
  size_t len;
264
265
2.25k
  der = p11_asn1_encode (ext, &len);
266
2.25k
  return_val_if_fail (der != NULL, NULL);
267
268
2.25k
  attrs = extension_attrs (parser, public_key_info, oid_str, oid_der,
269
2.25k
                           critical, der, len);
270
2.25k
  return_val_if_fail (attrs != NULL, NULL);
271
272
2.25k
  free (der);
273
2.25k
  return attrs;
274
2.25k
}
275
276
static p11_dict *
277
load_seq_of_oid_str (asn1_node node,
278
                     const char *seqof)
279
2.34k
{
280
2.34k
  p11_dict *oids;
281
2.34k
  char field[128];
282
2.34k
  char *oid;
283
2.34k
  size_t len;
284
2.34k
  int i;
285
286
2.34k
  oids = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
287
288
5.50k
  for (i = 1; ; i++) {
289
5.50k
    if (snprintf (field, sizeof (field), "%s.?%u", seqof, i) < 0)
290
0
      return_val_if_reached (NULL);
291
292
5.50k
    oid = p11_asn1_read (node, field, &len);
293
5.50k
    if (oid == NULL)
294
2.34k
      break;
295
296
3.16k
    if (!p11_dict_set (oids, oid, oid))
297
0
      return_val_if_reached (NULL);
298
3.16k
  }
299
300
2.34k
  return oids;
301
2.34k
}
302
303
static CK_ATTRIBUTE *
304
attached_eku_attrs (p11_parser *parser,
305
                    CK_ATTRIBUTE *public_key_info,
306
                    const char *oid_str,
307
                    const unsigned char *oid_der,
308
                    bool critical,
309
                    p11_dict *oid_strs)
310
2.25k
{
311
2.25k
  CK_ATTRIBUTE *attrs;
312
2.25k
  p11_dictiter iter;
313
2.25k
  asn1_node dest;
314
2.25k
  int count = 0;
315
2.25k
  void *value;
316
2.25k
  int ret;
317
318
2.25k
  dest = p11_asn1_create (parser->asn1_defs, "PKIX1.ExtKeyUsageSyntax");
319
2.25k
  return_val_if_fail (dest != NULL, NULL);
320
321
2.25k
  p11_dict_iterate (oid_strs, &iter);
322
5.41k
  while (p11_dict_next (&iter, NULL, &value)) {
323
3.15k
    ret = asn1_write_value (dest, "", "NEW", 1);
324
3.15k
    return_val_if_fail (ret == ASN1_SUCCESS, NULL);
325
326
3.15k
    ret = asn1_write_value (dest, "?LAST", value, -1);
327
3.15k
    return_val_if_fail (ret == ASN1_SUCCESS, NULL);
328
329
3.15k
    count++;
330
3.15k
  }
331
332
  /*
333
   * If no oids have been written, then we have to put in a reserved
334
   * value, due to the way that ExtendedKeyUsage is defined in RFC 5280.
335
   * There must be at least one purpose. This is important since *not*
336
   * having an ExtendedKeyUsage is very different than having one without
337
   * certain usages.
338
   *
339
   * We account for this in p11_parse_extended_key_usage(). However for
340
   * most callers this should not matter, as they only check whether a
341
   * given purpose is present, and don't make assumptions about ones
342
   * that they don't know about.
343
   */
344
345
2.25k
  if (count == 0) {
346
1.61k
    ret = asn1_write_value (dest, "", "NEW", 1);
347
1.61k
    return_val_if_fail (ret == ASN1_SUCCESS, NULL);
348
349
1.61k
    ret = asn1_write_value (dest, "?LAST", P11_OID_RESERVED_PURPOSE_STR, -1);
350
1.61k
    return_val_if_fail (ret == ASN1_SUCCESS, NULL);
351
1.61k
  }
352
353
354
2.25k
  attrs = attached_attrs (parser, public_key_info, oid_str, oid_der, critical, dest);
355
2.25k
  asn1_delete_structure (&dest);
356
357
2.25k
  return attrs;
358
2.25k
}
359
360
static CK_ATTRIBUTE *
361
build_openssl_extensions (p11_parser *parser,
362
                          CK_ATTRIBUTE *cert,
363
                          CK_ATTRIBUTE *public_key_info,
364
                          asn1_node aux,
365
                          const unsigned char *aux_der,
366
                          size_t aux_len)
367
1.75k
{
368
1.75k
  CK_BBOOL trusted = CK_FALSE;
369
1.75k
  CK_BBOOL distrust = CK_FALSE;
370
371
1.75k
  CK_ATTRIBUTE trust_attrs[] = {
372
1.75k
    { CKA_TRUSTED, &trusted, sizeof (trusted) },
373
1.75k
    { CKA_X_DISTRUSTED, &distrust, sizeof (distrust) },
374
1.75k
    { CKA_INVALID },
375
1.75k
  };
376
377
1.75k
  CK_ATTRIBUTE *attrs;
378
1.75k
  p11_dict *trust = NULL;
379
1.75k
  p11_dict *reject = NULL;
380
1.75k
  p11_dictiter iter;
381
1.75k
  void *key;
382
1.75k
  int start;
383
1.75k
  int end;
384
1.75k
  int ret;
385
1.75k
  int num;
386
387
  /*
388
   * This will load an empty list if there is no OPTIONAL trust field.
389
   * OpenSSL assumes that for a TRUSTED CERTIFICATE a missing trust field
390
   * is identical to untrusted for all purposes.
391
   *
392
   * This is different from ExtendedKeyUsage, where a missing certificate
393
   * extension means that it is trusted for all purposes.
394
   */
395
1.75k
  trust = load_seq_of_oid_str (aux, "trust");
396
397
1.75k
  ret = asn1_number_of_elements (aux, "reject", &num);
398
1.75k
  return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
399
1.75k
  if (ret == ASN1_SUCCESS)
400
589
    reject = load_seq_of_oid_str (aux, "reject");
401
402
  /* Remove all rejected oids from the trust set */
403
1.75k
  if (trust && reject) {
404
589
    p11_dict_iterate (reject, &iter);
405
3.57k
    while (p11_dict_next (&iter, &key, NULL))
406
2.99k
      p11_dict_remove (trust, key);
407
589
  }
408
409
  /*
410
   * The trust field (or lack of it) becomes a standard ExtKeyUsageSyntax.
411
   *
412
   * critical: require that this is enforced
413
   */
414
415
1.75k
  if (trust) {
416
1.75k
    attrs = attached_eku_attrs (parser, public_key_info,
417
1.75k
                                P11_OID_EXTENDED_KEY_USAGE_STR,
418
1.75k
                                P11_OID_EXTENDED_KEY_USAGE,
419
1.75k
                                true, trust);
420
1.75k
    return_val_if_fail (attrs != NULL, NULL);
421
1.75k
    sink_object (parser, attrs);
422
1.75k
  }
423
424
  /*
425
   * For the reject field we use a custom defined extension. We track this
426
   * for completeness, although the above ExtendedKeyUsage extension handles
427
   * this data fine. See oid.h for more details. It uses ExtKeyUsageSyntax structure.
428
   *
429
   * non-critical: non-standard, and also covered by trusts
430
   */
431
432
1.75k
  if (reject && p11_dict_size (reject) > 0) {
433
502
    attrs = attached_eku_attrs (parser, public_key_info,
434
502
                                P11_OID_OPENSSL_REJECT_STR,
435
502
                                P11_OID_OPENSSL_REJECT,
436
502
                                false, reject);
437
502
    return_val_if_fail (attrs != NULL, NULL);
438
502
    sink_object (parser, attrs);
439
502
  }
440
441
  /*
442
   * OpenSSL model blocklists as anchors with all purposes being removed/rejected,
443
   * we account for that here. If there is an ExtendedKeyUsage without any
444
   * useful purposes, then treat like a blocklist.
445
   */
446
1.75k
  if (trust && p11_dict_size (trust) == 0) {
447
1.61k
    trusted = CK_FALSE;
448
1.61k
    distrust = CK_TRUE;
449
450
  /*
451
   * Otherwise a 'TRUSTED CERTIFICATE' in an input directory is enough to
452
   * mark this as a trusted certificate.
453
   */
454
1.61k
  } else if (trust && p11_dict_size (trust) > 0) {
455
145
    trusted = CK_TRUE;
456
145
    distrust = CK_FALSE;
457
145
  }
458
459
  /*
460
   * OpenSSL model blocklists as anchors with all purposes being removed/rejected,
461
   * we account for that here. If there is an ExtendedKeyUsage without any
462
   * useful purposes, then treat like a blocklist.
463
   */
464
465
1.75k
  cert = p11_attrs_merge (cert, p11_attrs_dup (trust_attrs), true);
466
1.75k
  return_val_if_fail (cert != NULL, NULL);
467
468
1.75k
  p11_dict_free (trust);
469
1.75k
  p11_dict_free (reject);
470
471
  /*
472
   * For the keyid field we use the SubjectKeyIdentifier extension. It
473
   * is already in the correct form, an OCTET STRING.
474
   *
475
   * non-critical: as recommended in RFC 5280
476
   */
477
478
1.75k
  ret = asn1_der_decoding_startEnd (aux, aux_der, aux_len, "keyid", &start, &end);
479
1.75k
  return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
480
481
1.75k
  if (ret == ASN1_SUCCESS) {
482
870
    attrs = extension_attrs (parser, public_key_info,
483
870
                             P11_OID_SUBJECT_KEY_IDENTIFIER_STR,
484
870
                             P11_OID_SUBJECT_KEY_IDENTIFIER,
485
870
                             false, aux_der + start, (end - start) + 1);
486
870
    return_val_if_fail (attrs != NULL, NULL);
487
870
    sink_object (parser, attrs);
488
870
  }
489
490
491
1.75k
  return cert;
492
1.75k
}
493
494
static int
495
parse_openssl_trusted_certificate (p11_parser *parser,
496
                                   const unsigned char *data,
497
                                   size_t length)
498
4.14k
{
499
4.14k
  char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
500
4.14k
  CK_ATTRIBUTE *attrs;
501
4.14k
  CK_ATTRIBUTE public_key_info = { CKA_PUBLIC_KEY_INFO };
502
4.14k
  CK_ATTRIBUTE *value;
503
4.14k
  char *label = NULL;
504
4.14k
  asn1_node cert;
505
4.14k
  asn1_node aux = NULL;
506
4.14k
  ssize_t cert_len;
507
4.14k
  size_t len;
508
4.14k
  int start;
509
4.14k
  int end;
510
4.14k
  int ret;
511
512
  /*
513
   * This OpenSSL format is weird. It's just two DER structures
514
   * placed end to end without any wrapping SEQ. So calculate the
515
   * length of the first DER TLV we see and try to parse that as
516
   * the X.509 certificate.
517
   */
518
519
4.14k
  cert_len = p11_asn1_tlv_length (data, length);
520
4.14k
  if (cert_len <= 0)
521
956
    return P11_PARSE_UNRECOGNIZED;
522
523
3.19k
  cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, cert_len, message);
524
3.19k
  if (cert == NULL)
525
363
    return P11_PARSE_UNRECOGNIZED;
526
527
  /* OpenSSL sometimes outputs TRUSTED CERTIFICATE format without the CertAux supplement */
528
2.83k
  if (cert_len < length) {
529
1.97k
    aux = p11_asn1_decode (parser->asn1_defs, "OPENSSL.CertAux", data + cert_len,
530
1.97k
                           length - cert_len, message);
531
1.97k
    if (aux == NULL) {
532
215
      asn1_delete_structure (&cert);
533
215
      return P11_PARSE_UNRECOGNIZED;
534
215
    }
535
1.97k
  }
536
537
2.61k
  attrs = certificate_attrs (parser, data, cert_len);
538
2.61k
  return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
539
540
  /* Cache the parsed certificate ASN.1 for later use by the builder */
541
2.61k
  value = p11_attrs_find_valid (attrs, CKA_VALUE);
542
2.61k
  return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
543
544
  /* Pull out the subject public key info */
545
2.61k
  ret = asn1_der_decoding_startEnd (cert, data, cert_len,
546
2.61k
                                    "tbsCertificate.subjectPublicKeyInfo", &start, &end);
547
2.61k
  return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
548
549
1.97k
  public_key_info.pValue = (char *)data + start;
550
1.97k
  public_key_info.ulValueLen = (end - start) + 1;
551
552
1.97k
  p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
553
1.97k
                       value->pValue, value->ulValueLen);
554
555
  /* Pull the label out of the CertAux */
556
1.97k
  if (aux) {
557
1.75k
    len = 0;
558
1.75k
    label = p11_asn1_read (aux, "alias", &len);
559
1.75k
    if (label != NULL) {
560
363
      attrs = p11_attrs_take (attrs, CKA_LABEL, label, strlen (label));
561
363
      return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
562
363
    }
563
564
1.75k
    attrs = build_openssl_extensions (parser, attrs, &public_key_info, aux,
565
1.75k
                                      data + cert_len, length - cert_len);
566
1.75k
    return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
567
1.75k
  }
568
569
1.97k
  sink_object (parser, attrs);
570
1.97k
  asn1_delete_structure (&aux);
571
572
1.97k
  return P11_PARSE_SUCCESS;
573
1.97k
}
574
575
static void
576
on_pem_block (const char *type,
577
              const unsigned char *contents,
578
              size_t length,
579
              void *user_data)
580
6.74k
{
581
6.74k
  p11_parser *parser = user_data;
582
6.74k
  int ret;
583
584
6.74k
  if (strcmp (type, "CERTIFICATE") == 0) {
585
116
    ret = p11_parser_format_x509 (parser, contents, length);
586
587
6.63k
  } else if (strcmp (type, "TRUSTED CERTIFICATE") == 0) {
588
4.14k
    ret = parse_openssl_trusted_certificate (parser, contents, length);
589
590
4.14k
  } else {
591
2.48k
    p11_debug ("Saw unsupported or unrecognized PEM block of type %s", type);
592
2.48k
    ret = P11_PARSE_SUCCESS;
593
2.48k
  }
594
595
6.74k
  if (ret != P11_PARSE_SUCCESS)
596
2.29k
    p11_message (_("Couldn't parse PEM block of type %s"), type);
597
6.74k
}
598
599
int
600
p11_parser_format_pem (p11_parser *parser,
601
                       const unsigned char *data,
602
                       size_t length)
603
2.13k
{
604
2.13k
  int num;
605
606
2.13k
  num = p11_pem_parse ((const char *)data, length, on_pem_block, parser);
607
608
2.13k
  if (num == 0)
609
1.83k
    return P11_PARSE_UNRECOGNIZED;
610
611
306
  return P11_PARSE_SUCCESS;
612
2.13k
}
613
614
int
615
p11_parser_format_persist (p11_parser *parser,
616
                           const unsigned char *data,
617
                           size_t length)
618
1.83k
{
619
1.83k
  CK_BBOOL modifiablev = CK_TRUE;
620
1.83k
  CK_ATTRIBUTE *attrs;
621
1.83k
  p11_array *objects;
622
1.83k
  bool ret;
623
1.83k
  int i;
624
625
1.83k
  CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
626
627
1.83k
  if (!p11_persist_magic (data, length))
628
487
    return P11_PARSE_UNRECOGNIZED;
629
630
1.34k
  if (!parser->persist) {
631
1.34k
    parser->persist = p11_persist_new ();
632
1.34k
    return_val_if_fail (parser->persist != NULL, P11_PARSE_UNRECOGNIZED);
633
1.34k
  }
634
635
1.34k
  objects = p11_array_new (NULL);
636
1.34k
  return_val_if_fail (objects != NULL, P11_PARSE_FAILURE);
637
638
1.34k
  ret = p11_persist_read (parser->persist, parser->basename, data, length, objects);
639
1.34k
  if (ret) {
640
754
    if (!p11_persist_is_generated (data, length))
641
753
      modifiablev = CK_FALSE;
642
78.8k
    for (i = 0; i < objects->num; i++) {
643
78.1k
      attrs = p11_attrs_build (objects->elem[i], &modifiable, NULL);
644
78.1k
      sink_object (parser, attrs);
645
78.1k
    }
646
754
  }
647
648
1.34k
  p11_array_free (objects);
649
1.34k
  return ret ? P11_PARSE_SUCCESS : P11_PARSE_UNRECOGNIZED;
650
1.34k
}
651
652
p11_parser *
653
p11_parser_new (p11_asn1_cache *asn1_cache)
654
2.14k
{
655
2.14k
  p11_parser parser = { 0, };
656
657
2.14k
  if (asn1_cache == NULL) {
658
2.14k
    parser.asn1_owned = true;
659
2.14k
    parser.asn1_defs = p11_asn1_defs_load ();
660
2.14k
  } else {
661
0
    parser.asn1_defs = p11_asn1_cache_defs (asn1_cache);
662
0
    parser.asn1_cache = asn1_cache;
663
0
    parser.asn1_owned = false;
664
0
  }
665
666
2.14k
  parser.parsed = p11_array_new (p11_attrs_free);
667
2.14k
  return_val_if_fail (parser.parsed != NULL, NULL);
668
669
2.14k
  return memdup (&parser, sizeof (parser));
670
2.14k
}
671
672
void
673
p11_parser_free (p11_parser *parser)
674
2.14k
{
675
2.14k
  return_if_fail (parser != NULL);
676
2.14k
  p11_persist_free (parser->persist);
677
2.14k
  p11_array_free (parser->parsed);
678
2.14k
  p11_array_free (parser->formats);
679
2.14k
  if (parser->asn1_owned)
680
2.14k
    p11_dict_free (parser->asn1_defs);
681
2.14k
  free (parser);
682
2.14k
}
683
684
p11_array *
685
p11_parser_parsed (p11_parser *parser)
686
0
{
687
0
  return_val_if_fail (parser != NULL, NULL);
688
0
  return parser->parsed;
689
0
}
690
691
void
692
p11_parser_formats (p11_parser *parser,
693
                    ...)
694
2.14k
{
695
2.14k
  p11_array *formats;
696
2.14k
  parser_func func;
697
2.14k
  va_list va;
698
699
2.14k
  formats = p11_array_new (NULL);
700
2.14k
  return_if_fail (formats != NULL);
701
702
2.14k
  va_start (va, parser);
703
8.58k
  for (;;) {
704
8.58k
    func = va_arg (va, parser_func);
705
8.58k
    if (func == NULL)
706
2.14k
      break;
707
6.43k
    if (!p11_array_push (formats, func)) {
708
0
      va_end (va);
709
0
      return_if_reached ();
710
0
    }
711
6.43k
  }
712
2.14k
  va_end (va);
713
714
2.14k
  p11_array_free (parser->formats);
715
2.14k
  parser->formats = formats;
716
2.14k
}
717
718
int
719
p11_parse_memory (p11_parser *parser,
720
                  const char *filename,
721
                  int flags,
722
                  const unsigned char *data,
723
                  size_t length)
724
2.14k
{
725
2.14k
  int ret = P11_PARSE_UNRECOGNIZED;
726
2.14k
  char *base;
727
2.14k
  int i;
728
729
2.14k
  return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
730
2.14k
  return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
731
2.14k
  return_val_if_fail (parser->formats != NULL, P11_PARSE_FAILURE);
732
733
2.14k
  p11_array_clear (parser->parsed);
734
2.14k
  base = p11_path_base (filename);
735
2.14k
  parser->basename = base;
736
2.14k
  parser->flags = flags;
737
738
8.26k
  for (i = 0; ret == P11_PARSE_UNRECOGNIZED && i < parser->formats->num; i++)
739
6.11k
    ret = ((parser_func)parser->formats->elem[i]) (parser, data, length);
740
741
2.14k
  p11_asn1_cache_flush (parser->asn1_cache);
742
743
2.14k
  free (base);
744
2.14k
  parser->basename = NULL;
745
2.14k
  parser->flags = 0;
746
747
2.14k
  return ret;
748
2.14k
}
749
750
int
751
p11_parse_file (p11_parser *parser,
752
                const char *filename,
753
                struct stat *sb,
754
                int flags)
755
0
{
756
0
  p11_mmap *map;
757
0
  void *data;
758
0
  size_t size;
759
0
  int ret;
760
761
0
  return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
762
0
  return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
763
764
0
  map = p11_mmap_open (filename, sb, &data, &size);
765
0
  if (map == NULL) {
766
0
    p11_message_err (errno, _("couldn't open and map file: %s"), filename);
767
0
    return P11_PARSE_FAILURE;
768
0
  }
769
770
0
  ret = p11_parse_memory (parser, filename, flags, data, size);
771
772
0
  p11_mmap_close (map);
773
0
  return ret;
774
0
}