Coverage Report

Created: 2025-12-01 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/plugins/openssl/openssl_x509.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2011-2023 Tobias Brunner
3
 * Copyright (C) 2010 Martin Willi
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
/*
19
 * Copyright (C) 2013 Michael Rossberg
20
 * Copyright (C) 2013 Technische Universität Ilmenau
21
 *
22
 * Copyright (C) 2010 Thomas Egerer
23
 *
24
 * Permission is hereby granted, free of charge, to any person obtaining a copy
25
 * of this software and associated documentation files (the "Software"), to deal
26
 * in the Software without restriction, including without limitation the rights
27
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28
 * copies of the Software, and to permit persons to whom the Software is
29
 * furnished to do so, subject to the following conditions:
30
 *
31
 * The above copyright notice and this permission notice shall be included in
32
 * all copies or substantial portions of the Software.
33
 *
34
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40
 * THE SOFTWARE.
41
 */
42
43
#define _GNU_SOURCE
44
#include <stdio.h>
45
#include <openssl/x509.h>
46
#include <openssl/x509v3.h>
47
48
#include "openssl_x509.h"
49
#include "openssl_util.h"
50
51
#include <utils/debug.h>
52
#include <asn1/oid.h>
53
#include <collections/linked_list.h>
54
#include <selectors/traffic_selector.h>
55
56
/* IP Addr block extension support was introduced with 0.9.8e */
57
#if OPENSSL_VERSION_NUMBER < 0x0090805fL
58
#define OPENSSL_NO_RFC3779
59
#endif
60
61
/* added with 1.0.2 */
62
#if OPENSSL_VERSION_NUMBER < 0x10002000L
63
static inline void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) {
64
  if (psig) { *psig = x->signature; }
65
  if (palg) { *palg = x->sig_alg; }
66
}
67
#endif
68
69
/* added with 1.1.0 when X509 etc. was made opaque */
70
#if OPENSSL_VERSION_NUMBER < 0x10100000L
71
#define X509_get0_extensions(x509) ({ (x509)->cert_info->extensions; })
72
#define X509_get0_tbs_sigalg(x509) ({ (x509)->cert_info->signature; })
73
#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
74
#define X509_PUBKEY_get0_param(oid, pk, len, pa, pub) X509_ALGOR_get0(oid, NULL, NULL, (pub)->algor)
75
#define X509v3_addr_get_afi v3_addr_get_afi
76
#define X509v3_addr_get_range v3_addr_get_range
77
#define X509v3_addr_is_canonical v3_addr_is_canonical
78
#define X509_get0_notBefore X509_get_notBefore
79
#define X509_get0_notAfter X509_get_notAfter
80
#endif
81
82
typedef struct private_openssl_x509_t private_openssl_x509_t;
83
84
/**
85
 * Private data of an openssl_x509_t object.
86
 */
87
struct private_openssl_x509_t {
88
89
  /**
90
   * Public openssl_x509_t interface.
91
   */
92
  openssl_x509_t public;
93
94
  /**
95
   * OpenSSL certificate representation
96
   */
97
  X509 *x509;
98
99
  /**
100
   * DER encoded certificate
101
   */
102
  chunk_t encoding;
103
104
  /**
105
   * SHA1 hash of the certificate
106
   */
107
  chunk_t hash;
108
109
  /**
110
   * X509 flags
111
   */
112
  x509_flag_t flags;
113
114
  /**
115
   * Pathlen constraint
116
   */
117
  u_char pathlen;
118
119
  /**
120
   * certificate subject
121
   */
122
  identification_t *subject;
123
124
  /**
125
   * certificate issuer
126
   */
127
  identification_t *issuer;
128
129
  /**
130
   * Certificates public key
131
   */
132
  public_key_t *pubkey;
133
134
  /**
135
   * subjectKeyIdentifier as read from cert
136
   */
137
  chunk_t subjectKeyIdentifier;
138
139
  /**
140
   * authorityKeyIdentifier as read from cert
141
   */
142
  chunk_t authKeyIdentifier;
143
144
  /**
145
   * Start time of certificate validity
146
   */
147
  time_t notBefore;
148
149
  /**
150
   * End time of certificate validity
151
   */
152
  time_t notAfter;
153
154
  /**
155
   * Signature scheme of the certificate
156
   */
157
  signature_params_t *scheme;
158
159
  /**
160
   * subjectAltNames
161
   */
162
  linked_list_t *subjectAltNames;
163
164
  /**
165
   * issuerAltNames
166
   */
167
  linked_list_t *issuerAltNames;
168
169
  /**
170
   * List of CRL URIs, as x509_cdp_t
171
   */
172
  linked_list_t *crl_uris;
173
174
  /**
175
   * List of OCSP URIs
176
   */
177
  linked_list_t *ocsp_uris;
178
179
  /**
180
   * List of ipAddrBlocks as traffic_selector_t
181
   */
182
  linked_list_t *ipAddrBlocks;
183
184
  /**
185
   * List of permitted name constraints
186
   */
187
  linked_list_t *permitted_names;
188
189
  /**
190
   * List of excluded name constraints
191
   */
192
  linked_list_t *excluded_names;
193
194
  /**
195
   * References to this cert
196
   */
197
  refcount_t ref;
198
};
199
200
/**
201
 * Convert a GeneralName to an identification_t.
202
 */
203
static identification_t *general_name2id(GENERAL_NAME *name)
204
0
{
205
0
  if (!name)
206
0
  {
207
0
    return NULL;
208
0
  }
209
0
  switch (name->type)
210
0
  {
211
0
    case GEN_EMAIL:
212
0
      return identification_create_from_encoding(ID_RFC822_ADDR,
213
0
          openssl_asn1_str2chunk(name->d.rfc822Name));
214
0
    case GEN_DNS:
215
0
      return identification_create_from_encoding(ID_FQDN,
216
0
          openssl_asn1_str2chunk(name->d.dNSName));
217
0
    case GEN_URI:
218
0
      return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
219
0
          openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
220
0
    case GEN_IPADD:
221
0
    {
222
0
      chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
223
0
      if (chunk.len == 4)
224
0
      {
225
0
        return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
226
0
      }
227
0
      if (chunk.len == 8)
228
0
      {
229
0
        return identification_create_from_encoding(ID_IPV4_ADDR_SUBNET,
230
0
                               chunk);
231
0
      }
232
0
      if (chunk.len == 16)
233
0
      {
234
0
        return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
235
0
      }
236
0
      if (chunk.len == 32)
237
0
      {
238
0
        return identification_create_from_encoding(ID_IPV6_ADDR_SUBNET,
239
0
                               chunk);
240
0
      }
241
0
      return NULL;
242
0
    }
243
0
    case GEN_DIRNAME :
244
0
      return openssl_x509_name2id(name->d.directoryName);
245
0
    case GEN_OTHERNAME:
246
0
      if (OBJ_obj2nid(name->d.otherName->type_id) == NID_ms_upn &&
247
0
        name->d.otherName->value->type == V_ASN1_UTF8STRING)
248
0
      {
249
0
        return identification_create_from_encoding(ID_RFC822_ADDR,
250
0
              openssl_asn1_str2chunk(
251
0
                name->d.otherName->value->value.utf8string));
252
0
      }
253
0
      return NULL;
254
0
    default:
255
0
      return NULL;
256
0
  }
257
0
}
258
259
METHOD(x509_t, get_flags, x509_flag_t,
260
  private_openssl_x509_t *this)
261
0
{
262
0
  return this->flags;
263
0
}
264
265
METHOD(x509_t, get_serial, chunk_t,
266
  private_openssl_x509_t *this)
267
0
{
268
0
  return openssl_asn1_int2chunk(X509_get_serialNumber(this->x509));
269
0
}
270
271
METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
272
  private_openssl_x509_t *this)
273
0
{
274
0
  chunk_t fingerprint;
275
276
0
  if (this->subjectKeyIdentifier.len)
277
0
  {
278
0
    return this->subjectKeyIdentifier;
279
0
  }
280
0
  if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
281
0
                    &fingerprint))
282
0
  {
283
0
    return fingerprint;
284
0
  }
285
0
  return chunk_empty;
286
0
}
287
288
METHOD(x509_t, get_authKeyIdentifier, chunk_t,
289
  private_openssl_x509_t *this)
290
0
{
291
0
  if (this->authKeyIdentifier.len)
292
0
  {
293
0
    return this->authKeyIdentifier;
294
0
  }
295
0
  return chunk_empty;
296
0
}
297
298
METHOD(x509_t, get_constraint, u_int,
299
  private_openssl_x509_t *this, x509_constraint_t type)
300
0
{
301
0
  switch (type)
302
0
  {
303
0
    case X509_PATH_LEN:
304
0
      return this->pathlen;
305
0
    default:
306
0
      return X509_NO_CONSTRAINT;
307
0
  }
308
0
}
309
310
METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
311
  private_openssl_x509_t *this)
312
0
{
313
0
  return this->subjectAltNames->create_enumerator(this->subjectAltNames);
314
0
}
315
316
METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
317
  private_openssl_x509_t *this)
318
0
{
319
0
  return this->crl_uris->create_enumerator(this->crl_uris);
320
0
}
321
322
METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
323
  private_openssl_x509_t *this)
324
0
{
325
0
  return this->ocsp_uris->create_enumerator(this->ocsp_uris);
326
0
}
327
328
METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
329
  private_openssl_x509_t *this)
330
0
{
331
0
  return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
332
0
}
333
334
METHOD(x509_t, create_name_constraint_enumerator, enumerator_t*,
335
  private_openssl_x509_t *this, bool perm)
336
0
{
337
0
  if (perm)
338
0
  {
339
0
    return this->permitted_names->create_enumerator(this->permitted_names);
340
0
  }
341
0
  return this->excluded_names->create_enumerator(this->excluded_names);
342
0
}
343
344
METHOD(certificate_t, get_type, certificate_type_t,
345
  private_openssl_x509_t *this)
346
0
{
347
0
  return CERT_X509;
348
0
}
349
350
METHOD(certificate_t, get_subject, identification_t*,
351
  private_openssl_x509_t *this)
352
0
{
353
0
  return this->subject;
354
0
}
355
356
METHOD(certificate_t, get_issuer, identification_t*,
357
  private_openssl_x509_t *this)
358
0
{
359
0
  return this->issuer;
360
0
}
361
362
METHOD(certificate_t, has_subject, id_match_t,
363
  private_openssl_x509_t *this, identification_t *subject)
364
0
{
365
0
  identification_t *current;
366
0
  enumerator_t *enumerator;
367
0
  id_match_t match, best;
368
0
  chunk_t encoding;
369
370
0
  if (subject->get_type(subject) == ID_KEY_ID)
371
0
  {
372
0
    encoding = subject->get_encoding(subject);
373
374
0
    if (chunk_equals(this->hash, encoding))
375
0
    {
376
0
      return ID_MATCH_PERFECT;
377
0
    }
378
0
    if (this->subjectKeyIdentifier.len &&
379
0
      chunk_equals(this->subjectKeyIdentifier, encoding))
380
0
    {
381
0
      return ID_MATCH_PERFECT;
382
0
    }
383
0
    if (this->pubkey &&
384
0
      this->pubkey->has_fingerprint(this->pubkey, encoding))
385
0
    {
386
0
      return ID_MATCH_PERFECT;
387
0
    }
388
0
    if (chunk_equals(get_serial(this), encoding))
389
0
    {
390
0
      return ID_MATCH_PERFECT;
391
0
    }
392
0
  }
393
0
  best = this->subject->matches(this->subject, subject);
394
0
  enumerator = create_subjectAltName_enumerator(this);
395
0
  while (enumerator->enumerate(enumerator, &current))
396
0
  {
397
0
    match = current->matches(current, subject);
398
0
    if (match > best)
399
0
    {
400
0
      best = match;
401
0
    }
402
0
  }
403
0
  enumerator->destroy(enumerator);
404
0
  return best;
405
0
}
406
407
METHOD(certificate_t, has_issuer, id_match_t,
408
  private_openssl_x509_t *this, identification_t *issuer)
409
0
{
410
  /* issuerAltNames currently not supported */
411
0
  return this->issuer->matches(this->issuer, issuer);
412
0
}
413
414
METHOD(certificate_t, issued_by, bool,
415
  private_openssl_x509_t *this, certificate_t *issuer,
416
  signature_params_t **scheme)
417
0
{
418
0
  public_key_t *key;
419
0
  bool valid;
420
0
  x509_t *x509 = (x509_t*)issuer;
421
0
  chunk_t keyid = chunk_empty;
422
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
423
0
  const ASN1_BIT_STRING *sig;
424
#else
425
  ASN1_BIT_STRING *sig;
426
#endif
427
0
  chunk_t tbs;
428
429
0
  if (&this->public.x509.interface == issuer)
430
0
  {
431
0
    if (this->flags & X509_SELF_SIGNED)
432
0
    {
433
0
      valid = TRUE;
434
0
      goto out;
435
0
    }
436
0
  }
437
0
  else
438
0
  {
439
0
    if (issuer->get_type(issuer) != CERT_X509)
440
0
    {
441
0
      return FALSE;
442
0
    }
443
0
    if (!(x509->get_flags(x509) & X509_CA))
444
0
    {
445
0
      return FALSE;
446
0
    }
447
0
  }
448
449
  /* compare keyIdentifiers if available, otherwise use DNs */
450
0
  if (this->authKeyIdentifier.ptr)
451
0
  {
452
0
    keyid = x509->get_subjectKeyIdentifier(x509);
453
0
    if (keyid.len && !chunk_equals(keyid, this->authKeyIdentifier))
454
0
    {
455
0
      return FALSE;
456
0
    }
457
0
  }
458
0
  if (!keyid.len)
459
0
  {
460
0
    if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
461
0
    {
462
0
      return FALSE;
463
0
    }
464
0
  }
465
466
0
  key = issuer->get_public_key(issuer);
467
0
  if (!key)
468
0
  {
469
0
    return FALSE;
470
0
  }
471
  /* i2d_re_X509_tbs() was added with 1.1.0 when X509 was made opaque */
472
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
473
0
  tbs = openssl_i2chunk(re_X509_tbs, this->x509);
474
#else
475
  tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
476
#endif
477
0
  X509_get0_signature(&sig, NULL, this->x509);
478
0
  valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs,
479
0
            openssl_asn1_str2chunk(sig));
480
0
  free(tbs.ptr);
481
0
  key->destroy(key);
482
483
0
out:
484
0
  if (valid && scheme)
485
0
  {
486
0
    *scheme = signature_params_clone(this->scheme);
487
0
  }
488
0
  return valid;
489
0
}
490
491
METHOD(certificate_t, get_public_key, public_key_t*,
492
  private_openssl_x509_t *this)
493
0
{
494
0
  return this->pubkey->get_ref(this->pubkey);
495
0
}
496
497
METHOD(certificate_t, get_validity, bool,
498
  private_openssl_x509_t *this,
499
  time_t *when, time_t *not_before, time_t *not_after)
500
0
{
501
0
  time_t t;
502
503
0
  if (when)
504
0
  {
505
0
    t = *when;
506
0
  }
507
0
  else
508
0
  {
509
0
    t = time(NULL);
510
0
  }
511
0
  if (not_before)
512
0
  {
513
0
    *not_before = this->notBefore;
514
0
  }
515
0
  if (not_after)
516
0
  {
517
0
    *not_after = this->notAfter;
518
0
  }
519
0
  return (t >= this->notBefore && t <= this->notAfter);
520
0
}
521
522
METHOD(certificate_t, get_encoding, bool,
523
  private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
524
0
{
525
0
  if (type == CERT_ASN1_DER)
526
0
  {
527
0
    *encoding = chunk_clone(this->encoding);
528
0
    return TRUE;
529
0
  }
530
0
  return lib->encoding->encode(lib->encoding, type, NULL, encoding,
531
0
            CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
532
0
}
533
534
535
METHOD(certificate_t, equals, bool,
536
  private_openssl_x509_t *this, certificate_t *other)
537
0
{
538
0
  chunk_t encoding;
539
0
  bool equal;
540
541
0
  if (this == (private_openssl_x509_t*)other)
542
0
  {
543
0
    return TRUE;
544
0
  }
545
0
  if (other->get_type(other) != CERT_X509)
546
0
  {
547
0
    return FALSE;
548
0
  }
549
0
  if (other->equals == (void*)equals)
550
0
  { /* skip allocation if we have the same implementation */
551
0
    encoding = ((private_openssl_x509_t*)other)->encoding;
552
0
    return chunk_equals(this->encoding, encoding);
553
0
  }
554
0
  if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
555
0
  {
556
0
    return FALSE;
557
0
  }
558
0
  equal = chunk_equals(this->encoding, encoding);
559
0
  free(encoding.ptr);
560
0
  return equal;
561
0
}
562
563
METHOD(certificate_t, get_ref, certificate_t*,
564
  private_openssl_x509_t *this)
565
0
{
566
0
  ref_get(&this->ref);
567
0
  return &this->public.x509.interface;
568
0
}
569
570
METHOD(certificate_t, destroy, void,
571
  private_openssl_x509_t *this)
572
0
{
573
0
  if (ref_put(&this->ref))
574
0
  {
575
0
    if (this->x509)
576
0
    {
577
0
      X509_free(this->x509);
578
0
    }
579
0
    signature_params_destroy(this->scheme);
580
0
    DESTROY_IF(this->subject);
581
0
    DESTROY_IF(this->issuer);
582
0
    DESTROY_IF(this->pubkey);
583
0
    free(this->subjectKeyIdentifier.ptr);
584
0
    free(this->authKeyIdentifier.ptr);
585
0
    free(this->encoding.ptr);
586
0
    free(this->hash.ptr);
587
0
    this->subjectAltNames->destroy_offset(this->subjectAltNames,
588
0
                    offsetof(identification_t, destroy));
589
0
    this->issuerAltNames->destroy_offset(this->issuerAltNames,
590
0
                    offsetof(identification_t, destroy));
591
0
    this->crl_uris->destroy_function(this->crl_uris,
592
0
                     (void*)x509_cdp_destroy);
593
0
    this->ocsp_uris->destroy_function(this->ocsp_uris, free);
594
0
    this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
595
0
                    offsetof(traffic_selector_t, destroy));
596
0
    this->permitted_names->destroy_offset(this->permitted_names,
597
0
                    offsetof(identification_t, destroy));
598
0
    this->excluded_names->destroy_offset(this->excluded_names,
599
0
                    offsetof(identification_t, destroy));
600
0
    free(this);
601
0
  }
602
0
}
603
604
/**
605
 * Create an empty certificate
606
 */
607
static private_openssl_x509_t *create_empty()
608
0
{
609
0
  private_openssl_x509_t *this;
610
611
0
  INIT(this,
612
0
    .public = {
613
0
      .x509 = {
614
0
        .interface = {
615
0
          .get_type = _get_type,
616
0
          .get_subject = _get_subject,
617
0
          .get_issuer = _get_issuer,
618
0
          .has_subject = _has_subject,
619
0
          .has_issuer = _has_issuer,
620
0
          .issued_by = _issued_by,
621
0
          .get_public_key = _get_public_key,
622
0
          .get_validity = _get_validity,
623
0
          .get_encoding = _get_encoding,
624
0
          .equals = _equals,
625
0
          .get_ref = _get_ref,
626
0
          .destroy = _destroy,
627
0
        },
628
0
        .get_flags = _get_flags,
629
0
        .get_serial = _get_serial,
630
0
        .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
631
0
        .get_authKeyIdentifier = _get_authKeyIdentifier,
632
0
        .get_constraint = _get_constraint,
633
0
        .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
634
0
        .create_crl_uri_enumerator = _create_crl_uri_enumerator,
635
0
        .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
636
0
        .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
637
0
        .create_name_constraint_enumerator = _create_name_constraint_enumerator,
638
0
        .create_cert_policy_enumerator = (void*)enumerator_create_empty,
639
0
        .create_policy_mapping_enumerator = (void*)enumerator_create_empty,
640
0
      },
641
0
    },
642
0
    .subjectAltNames = linked_list_create(),
643
0
    .issuerAltNames = linked_list_create(),
644
0
    .crl_uris = linked_list_create(),
645
0
    .ocsp_uris = linked_list_create(),
646
0
    .ipAddrBlocks = linked_list_create(),
647
0
    .permitted_names = linked_list_create(),
648
0
    .excluded_names = linked_list_create(),
649
0
    .pathlen = X509_NO_CONSTRAINT,
650
0
    .ref = 1,
651
0
  );
652
653
0
  return this;
654
0
}
655
656
/**
657
 * parse an extension containing GENERAL_NAMES into a list
658
 */
659
static bool parse_generalNames_ext(linked_list_t *list,
660
                   X509_EXTENSION *ext)
661
0
{
662
0
  GENERAL_NAMES *names;
663
0
  GENERAL_NAME *name;
664
0
  identification_t *id;
665
0
  int i, num;
666
667
0
  names = X509V3_EXT_d2i(ext);
668
0
  if (!names)
669
0
  {
670
0
    return FALSE;
671
0
  }
672
673
0
  num = sk_GENERAL_NAME_num(names);
674
0
  for (i = 0; i < num; i++)
675
0
  {
676
0
    name = sk_GENERAL_NAME_value(names, i);
677
0
    id = general_name2id(name);
678
0
    if (id)
679
0
    {
680
0
      list->insert_last(list, id);
681
0
    }
682
0
    GENERAL_NAME_free(name);
683
0
  }
684
0
  sk_GENERAL_NAME_free(names);
685
0
  return TRUE;
686
0
}
687
688
/**
689
 * parse basic constraints
690
 */
691
static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
692
                     X509_EXTENSION *ext)
693
0
{
694
0
  BASIC_CONSTRAINTS *constraints;
695
0
  long pathlen;
696
697
0
  constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
698
0
  if (constraints)
699
0
  {
700
0
    if (constraints->ca)
701
0
    {
702
0
      this->flags |= X509_CA;
703
0
    }
704
0
    if (constraints->pathlen)
705
0
    {
706
707
0
      pathlen = ASN1_INTEGER_get(constraints->pathlen);
708
0
      this->pathlen = (pathlen >= 0 && pathlen < 128) ?
709
0
               pathlen : X509_NO_CONSTRAINT;
710
0
    }
711
0
    BASIC_CONSTRAINTS_free(constraints);
712
0
    return TRUE;
713
0
  }
714
0
  return FALSE;
715
0
}
716
717
/**
718
 * parse key usage
719
 */
720
static bool parse_keyUsage_ext(private_openssl_x509_t *this,
721
                 X509_EXTENSION *ext)
722
0
{
723
0
  ASN1_BIT_STRING *usage;
724
725
0
  usage = X509V3_EXT_d2i(ext);
726
0
  if (usage)
727
0
  {
728
0
    if (usage->length > 0)
729
0
    {
730
0
      int flags = usage->data[0];
731
0
      if (usage->length > 1)
732
0
      {
733
0
        flags |= usage->data[1] << 8;
734
0
      }
735
0
      if (flags & X509v3_KU_CRL_SIGN)
736
0
      {
737
0
        this->flags |= X509_CRL_SIGN;
738
0
      }
739
0
      if (flags & X509v3_KU_DIGITAL_SIGNATURE ||
740
0
        flags & X509v3_KU_NON_REPUDIATION)
741
0
      {
742
0
        this->flags |= X509_IKE_COMPLIANT;
743
0
      }
744
0
      if (flags & X509v3_KU_KEY_CERT_SIGN)
745
0
      {
746
        /* we use the caBasicConstraint, MUST be set */
747
0
      }
748
0
    }
749
0
    ASN1_BIT_STRING_free(usage);
750
0
    return TRUE;
751
0
  }
752
0
  return FALSE;
753
0
}
754
755
/**
756
 * Parse ExtendedKeyUsage
757
 */
758
static bool parse_extKeyUsage_ext(private_openssl_x509_t *this,
759
                  X509_EXTENSION *ext)
760
0
{
761
0
  EXTENDED_KEY_USAGE *usage;
762
0
  int i;
763
764
0
  usage = X509V3_EXT_d2i(ext);
765
0
  if (usage)
766
0
  {
767
0
    for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
768
0
    {
769
0
      switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
770
0
      {
771
0
        case NID_server_auth:
772
0
          this->flags |= X509_SERVER_AUTH;
773
0
          break;
774
0
        case NID_client_auth:
775
0
          this->flags |= X509_CLIENT_AUTH;
776
0
          break;
777
0
        case NID_OCSP_sign:
778
0
          this->flags |= X509_OCSP_SIGNER;
779
0
          break;
780
0
        default:
781
0
          break;
782
0
      }
783
0
    }
784
0
    sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
785
0
    return TRUE;
786
0
  }
787
0
  return FALSE;
788
0
}
789
790
/**
791
 * Parse CRL distribution points
792
 */
793
bool openssl_parse_crlDistributionPoints(X509_EXTENSION *ext,
794
                     linked_list_t *list)
795
0
{
796
0
  CRL_DIST_POINTS *cdps;
797
0
  DIST_POINT *cdp;
798
0
  identification_t *id, *issuer;
799
0
  x509_cdp_t *entry;
800
0
  char *uri;
801
0
  int i, j, k, point_num, name_num, issuer_num, len;
802
803
0
  cdps = X509V3_EXT_d2i(ext);
804
0
  if (!cdps)
805
0
  {
806
0
    return FALSE;
807
0
  }
808
0
  point_num = sk_DIST_POINT_num(cdps);
809
0
  for (i = 0; i < point_num; i++)
810
0
  {
811
0
    cdp = sk_DIST_POINT_value(cdps, i);
812
0
    if (cdp)
813
0
    {
814
0
      if (cdp->distpoint && cdp->distpoint->type == 0 &&
815
0
        cdp->distpoint->name.fullname)
816
0
      {
817
0
        name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
818
0
        for (j = 0; j < name_num; j++)
819
0
        {
820
0
          id = general_name2id(sk_GENERAL_NAME_value(
821
0
                      cdp->distpoint->name.fullname, j));
822
0
          if (id)
823
0
          {
824
0
            len = asprintf(&uri, "%Y", id);
825
0
            if (!len)
826
0
            {
827
0
              free(uri);
828
0
            }
829
0
            else if (len > 0)
830
0
            {
831
0
              if (cdp->CRLissuer)
832
0
              {
833
0
                issuer_num = sk_GENERAL_NAME_num(cdp->CRLissuer);
834
0
                for (k = 0; k < issuer_num; k++)
835
0
                {
836
0
                  issuer = general_name2id(
837
0
                    sk_GENERAL_NAME_value(cdp->CRLissuer, k));
838
0
                  if (issuer)
839
0
                  {
840
0
                    INIT(entry,
841
0
                      .uri = strdup(uri),
842
0
                      .issuer = issuer,
843
0
                    );
844
0
                    list->insert_last(list, entry);
845
0
                  }
846
0
                }
847
0
                free(uri);
848
0
              }
849
0
              else
850
0
              {
851
0
                INIT(entry,
852
0
                  .uri = uri,
853
0
                );
854
0
                list->insert_last(list, entry);
855
0
              }
856
0
            }
857
0
            id->destroy(id);
858
0
          }
859
0
        }
860
0
      }
861
862
0
      DIST_POINT_free(cdp);
863
0
    }
864
0
  }
865
0
  sk_DIST_POINT_free(cdps);
866
0
  return TRUE;
867
0
}
868
869
/**
870
 * Parse authorityInfoAccess with OCSP URIs
871
 */
872
static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
873
                      X509_EXTENSION *ext)
874
0
{
875
0
  AUTHORITY_INFO_ACCESS *infos;
876
0
  ACCESS_DESCRIPTION *desc;
877
0
  identification_t *id;
878
0
  int i, num, len;
879
0
  char *uri;
880
881
0
  infos = X509V3_EXT_d2i(ext);
882
0
  if (!infos)
883
0
  {
884
0
    return FALSE;
885
0
  }
886
0
  num = sk_ACCESS_DESCRIPTION_num(infos);
887
0
  for (i = 0; i < num; i++)
888
0
  {
889
0
    desc = sk_ACCESS_DESCRIPTION_value(infos, i);
890
0
    if (desc)
891
0
    {
892
0
      if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
893
0
      {
894
0
        id = general_name2id(desc->location);
895
0
        if (id)
896
0
        {
897
0
          len = asprintf(&uri, "%Y", id);
898
0
          if (!len)
899
0
          {
900
0
            free(uri);
901
0
          }
902
0
          else if (len > 0)
903
0
          {
904
0
            this->ocsp_uris->insert_last(this->ocsp_uris, uri);
905
0
          }
906
0
          id->destroy(id);
907
0
        }
908
0
      }
909
0
      ACCESS_DESCRIPTION_free(desc);
910
0
    }
911
0
  }
912
0
  sk_ACCESS_DESCRIPTION_free(infos);
913
0
  return TRUE;
914
0
}
915
916
#ifndef OPENSSL_NO_RFC3779
917
918
/**
919
 * Parse a single block of ipAddrBlock extension
920
 */
921
static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
922
                    IPAddressFamily *fam)
923
0
{
924
0
  const IPAddressOrRanges *list;
925
0
  IPAddressOrRange *aor;
926
0
  traffic_selector_t *ts;
927
0
  ts_type_t type;
928
0
  chunk_t from, to;
929
0
  int i, afi;
930
931
0
  if (fam->ipAddressChoice->type != IPAddressChoice_addressesOrRanges)
932
0
  {
933
0
    return;
934
0
  }
935
936
0
  afi = X509v3_addr_get_afi(fam);
937
0
  switch (afi)
938
0
  {
939
0
    case IANA_AFI_IPV4:
940
0
      from = chunk_alloca(4);
941
0
      to = chunk_alloca(4);
942
0
      type = TS_IPV4_ADDR_RANGE;
943
0
      break;
944
0
    case IANA_AFI_IPV6:
945
0
      from = chunk_alloca(16);
946
0
      to = chunk_alloca(16);
947
0
      type = TS_IPV6_ADDR_RANGE;
948
0
      break;
949
0
    default:
950
0
      return;
951
0
  }
952
953
0
  list = fam->ipAddressChoice->u.addressesOrRanges;
954
0
  for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
955
0
  {
956
0
    aor = sk_IPAddressOrRange_value(list, i);
957
0
    if (X509v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
958
0
    {
959
0
      ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
960
0
      if (ts)
961
0
      {
962
0
        this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
963
0
      }
964
0
    }
965
0
  }
966
0
}
967
968
/**
969
 * Parse ipAddrBlock extension
970
 */
971
static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
972
                  X509_EXTENSION *ext)
973
0
{
974
0
  STACK_OF(IPAddressFamily) *blocks;
975
0
  IPAddressFamily *fam;
976
977
0
  blocks = (STACK_OF(IPAddressFamily)*)X509V3_EXT_d2i(ext);
978
0
  if (!blocks)
979
0
  {
980
0
    return FALSE;
981
0
  }
982
983
0
  if (!X509v3_addr_is_canonical(blocks))
984
0
  {
985
0
    sk_IPAddressFamily_free(blocks);
986
0
    return FALSE;
987
0
  }
988
989
0
  while (sk_IPAddressFamily_num(blocks) > 0)
990
0
  {
991
0
    fam = sk_IPAddressFamily_pop(blocks);
992
0
    parse_ipAddrBlock_ext_fam(this, fam);
993
0
    IPAddressFamily_free(fam);
994
0
  }
995
0
  sk_IPAddressFamily_free(blocks);
996
997
0
  this->flags |= X509_IP_ADDR_BLOCKS;
998
0
  return TRUE;
999
0
}
1000
#endif /* !OPENSSL_NO_RFC3779 */
1001
1002
/**
1003
 * Parse a "generalSubtree" structure (sequence of generalNames)
1004
 */
1005
static bool parse_generalSubtrees(linked_list_t *list,
1006
                  STACK_OF(GENERAL_SUBTREE) *subtrees)
1007
0
{
1008
0
  GENERAL_SUBTREE *subtree;
1009
0
  identification_t *id;
1010
0
  int i;
1011
1012
0
  for (i = 0; i < sk_GENERAL_SUBTREE_num(subtrees); i++)
1013
0
  {
1014
0
    subtree = sk_GENERAL_SUBTREE_value(subtrees, i);
1015
0
    id = general_name2id(subtree->base);
1016
0
    if (id)
1017
0
    {
1018
0
      list->insert_last(list, id);
1019
0
    }
1020
0
    else
1021
0
    {
1022
0
      return FALSE;
1023
0
    }
1024
0
  }
1025
0
  return TRUE;
1026
0
}
1027
1028
/**
1029
 * Parse permitted/excluded nameConstraints
1030
 */
1031
static bool parse_nameConstraints_ext(private_openssl_x509_t *this,
1032
                    X509_EXTENSION *ext)
1033
0
{
1034
0
  NAME_CONSTRAINTS *nc;
1035
0
  bool ok = FALSE;
1036
1037
0
  nc = (NAME_CONSTRAINTS*)X509V3_EXT_d2i(ext);
1038
0
  if (nc)
1039
0
  {
1040
0
    ok = parse_generalSubtrees(this->permitted_names, nc->permittedSubtrees) &&
1041
0
       parse_generalSubtrees(this->excluded_names, nc->excludedSubtrees);
1042
0
    NAME_CONSTRAINTS_free(nc);
1043
0
  }
1044
0
  return ok;
1045
0
}
1046
1047
/**
1048
 * Parse authorityKeyIdentifier extension
1049
 */
1050
static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
1051
                    X509_EXTENSION *ext)
1052
0
{
1053
0
  AUTHORITY_KEYID *keyid;
1054
1055
0
  keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
1056
0
  if (keyid)
1057
0
  {
1058
0
    free(this->authKeyIdentifier.ptr);
1059
0
    this->authKeyIdentifier = chunk_clone(
1060
0
                    openssl_asn1_str2chunk(keyid->keyid));
1061
0
    AUTHORITY_KEYID_free(keyid);
1062
0
    return TRUE;
1063
0
  }
1064
0
  return FALSE;
1065
0
}
1066
1067
/**
1068
 * Parse subjectKeyIdentifier extension
1069
 */
1070
static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
1071
                       X509_EXTENSION *ext)
1072
0
{
1073
0
  chunk_t ostr;
1074
1075
0
  ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
1076
  /* quick and dirty unwrap of octet string */
1077
0
  if (ostr.len > 2 &&
1078
0
    ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
1079
0
  {
1080
0
    free(this->subjectKeyIdentifier.ptr);
1081
0
    this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
1082
0
    return TRUE;
1083
0
  }
1084
0
  return FALSE;
1085
0
}
1086
1087
/**
1088
 * Parse X509 extensions we are interested in
1089
 */
1090
static bool parse_extensions(private_openssl_x509_t *this)
1091
0
{
1092
0
  const STACK_OF(X509_EXTENSION) *extensions;
1093
0
  bool key_usage_parsed = FALSE;
1094
0
  int i, num;
1095
1096
0
  extensions = X509_get0_extensions(this->x509);
1097
0
  if (extensions)
1098
0
  {
1099
0
    num = sk_X509_EXTENSION_num(extensions);
1100
1101
0
    for (i = 0; i < num; i++)
1102
0
    {
1103
0
      X509_EXTENSION *ext;
1104
0
      bool ok;
1105
1106
0
      ext = sk_X509_EXTENSION_value(extensions, i);
1107
0
      switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
1108
0
      {
1109
0
        case NID_info_access:
1110
0
          ok = parse_authorityInfoAccess_ext(this, ext);
1111
0
          break;
1112
0
        case NID_authority_key_identifier:
1113
0
          ok = parse_authKeyIdentifier_ext(this, ext);
1114
0
          break;
1115
0
        case NID_subject_key_identifier:
1116
0
          ok = parse_subjectKeyIdentifier_ext(this, ext);
1117
0
          break;
1118
0
        case NID_subject_alt_name:
1119
0
          ok = parse_generalNames_ext(this->subjectAltNames, ext);
1120
0
          break;
1121
0
        case NID_issuer_alt_name:
1122
0
          ok = parse_generalNames_ext(this->issuerAltNames, ext);
1123
0
          break;
1124
0
        case NID_basic_constraints:
1125
0
          ok = parse_basicConstraints_ext(this, ext);
1126
0
          break;
1127
0
        case NID_key_usage:
1128
0
          ok = parse_keyUsage_ext(this, ext);
1129
0
          key_usage_parsed = TRUE;
1130
0
          break;
1131
0
        case NID_ext_key_usage:
1132
0
          ok = parse_extKeyUsage_ext(this, ext);
1133
0
          break;
1134
0
        case NID_crl_distribution_points:
1135
0
          ok = openssl_parse_crlDistributionPoints(ext, this->crl_uris);
1136
0
          break;
1137
0
#ifndef OPENSSL_NO_RFC3779
1138
0
        case NID_sbgp_ipAddrBlock:
1139
0
          ok = parse_ipAddrBlock_ext(this, ext);
1140
0
          break;
1141
0
#endif /* !OPENSSL_NO_RFC3779 */
1142
0
        case NID_name_constraints:
1143
0
          ok = parse_nameConstraints_ext(this, ext);
1144
0
          break;
1145
0
        default:
1146
0
          ok = X509_EXTENSION_get_critical(ext) == 0 ||
1147
0
             !lib->settings->get_bool(lib->settings,
1148
0
                  "%s.x509.enforce_critical", TRUE, lib->ns);
1149
0
          if (!ok)
1150
0
          {
1151
0
            char buf[80] = "";
1152
1153
0
            OBJ_obj2txt(buf, sizeof(buf),
1154
0
                  X509_EXTENSION_get_object(ext), 0);
1155
0
            DBG1(DBG_LIB, "found unsupported critical X.509 "
1156
0
               "extension: %s", buf);
1157
0
          }
1158
0
          break;
1159
0
      }
1160
0
      if (!ok)
1161
0
      {
1162
0
        return FALSE;
1163
0
      }
1164
0
    }
1165
0
  }
1166
0
  if (!key_usage_parsed)
1167
0
  {
1168
    /* we are compliant with RFC 4945 without keyUsage extension */
1169
0
    this->flags |= X509_IKE_COMPLIANT;
1170
    /* allow CA certificates without keyUsage extension to sign CRLs */
1171
0
    if (this->flags & X509_CA)
1172
0
    {
1173
0
      this->flags |= X509_CRL_SIGN;
1174
0
    }
1175
0
  }
1176
0
  return TRUE;
1177
0
}
1178
1179
/**
1180
 * Parse a DER encoded x509 certificate
1181
 */
1182
static bool parse_certificate(private_openssl_x509_t *this)
1183
0
{
1184
0
  const unsigned char *ptr = this->encoding.ptr;
1185
0
  hasher_t *hasher;
1186
0
  chunk_t chunk, sig_scheme, sig_scheme_tbs;
1187
0
  ASN1_OBJECT *oid;
1188
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
1189
0
  const X509_ALGOR *alg;
1190
#else
1191
  X509_ALGOR *alg;
1192
#endif
1193
0
  key_type_t ed_type = KEY_ED448;
1194
1195
0
  this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
1196
0
  if (!this->x509)
1197
0
  {
1198
0
    return FALSE;
1199
0
  }
1200
0
  if (X509_get_version(this->x509) < 0 || X509_get_version(this->x509) > 2)
1201
0
  {
1202
0
    DBG1(DBG_LIB, "unsupported x509 version: %d",
1203
0
       X509_get_version(this->x509) + 1);
1204
0
    return FALSE;
1205
0
  }
1206
1207
0
  this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
1208
0
  this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
1209
1210
0
  if (!X509_PUBKEY_get0_param(&oid, NULL, NULL, NULL,
1211
0
                  X509_get_X509_PUBKEY(this->x509)))
1212
0
  {
1213
0
    return FALSE;
1214
0
  }
1215
0
  switch (openssl_asn1_known_oid(oid))
1216
0
  {
1217
0
    case OID_RSASSA_PSS:
1218
      /* TODO: we should treat such keys special and use the params as
1219
       * restrictions regarding the use of this key (or rather the
1220
       * associated private key) */
1221
0
    case OID_RSA_ENCRYPTION:
1222
0
      this->pubkey = lib->creds->create(lib->creds,
1223
0
          CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
1224
0
          openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
1225
0
          BUILD_END);
1226
0
      break;
1227
0
    case OID_EC_PUBLICKEY:
1228
      /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
1229
       * the curve parameters. */
1230
0
      chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
1231
0
      this->pubkey = lib->creds->create(lib->creds,
1232
0
          CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
1233
0
          chunk, BUILD_END);
1234
0
      free(chunk.ptr);
1235
0
      break;
1236
0
    case OID_ED25519:
1237
0
      ed_type = KEY_ED25519;
1238
      /* fall-through */
1239
0
    case OID_ED448:
1240
      /* for EdDSA, the parsers expect the full subjectPublicKeyInfo */
1241
0
      chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
1242
0
      this->pubkey = lib->creds->create(lib->creds,
1243
0
          CRED_PUBLIC_KEY, ed_type, BUILD_BLOB_ASN1_DER,
1244
0
          chunk, BUILD_END);
1245
0
      free(chunk.ptr);
1246
0
      break;
1247
0
    default:
1248
0
      DBG1(DBG_LIB, "unsupported public key algorithm");
1249
0
      break;
1250
0
  }
1251
0
  if (!this->subject || !this->issuer || !this->pubkey)
1252
0
  {
1253
0
    return FALSE;
1254
0
  }
1255
1256
0
  this->notBefore = openssl_asn1_to_time(X509_get0_notBefore(this->x509));
1257
0
  this->notAfter = openssl_asn1_to_time(X509_get0_notAfter(this->x509));
1258
1259
  /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL
1260
   * versions, at least on Ubuntu 14.04 it is not actually defined */
1261
0
  X509_get0_signature(NULL, &alg, this->x509);
1262
0
  sig_scheme = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
1263
0
  alg = X509_get0_tbs_sigalg(this->x509);
1264
0
  sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
1265
0
  if (!chunk_equals(sig_scheme, sig_scheme_tbs))
1266
0
  {
1267
0
    free(sig_scheme_tbs.ptr);
1268
0
    free(sig_scheme.ptr);
1269
0
    return FALSE;
1270
0
  }
1271
0
  free(sig_scheme_tbs.ptr);
1272
1273
0
  INIT(this->scheme);
1274
0
  if (!signature_params_parse(sig_scheme, 0, this->scheme))
1275
0
  {
1276
0
    DBG1(DBG_ASN, "unable to parse signature algorithm");
1277
0
    free(sig_scheme.ptr);
1278
0
    return FALSE;
1279
0
  }
1280
0
  free(sig_scheme.ptr);
1281
1282
0
  if (!parse_extensions(this))
1283
0
  {
1284
0
    return FALSE;
1285
0
  }
1286
1287
0
  hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
1288
0
  if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))
1289
0
  {
1290
0
    DESTROY_IF(hasher);
1291
0
    return FALSE;
1292
0
  }
1293
0
  hasher->destroy(hasher);
1294
1295
0
  if (issued_by(this, &this->public.x509.interface, NULL))
1296
0
  {
1297
0
    this->flags |= X509_SELF_SIGNED;
1298
0
  }
1299
0
  return TRUE;
1300
0
}
1301
1302
openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
1303
0
{
1304
0
  chunk_t blob = chunk_empty;
1305
0
  x509_flag_t flags = 0;
1306
1307
0
  while (TRUE)
1308
0
  {
1309
0
    switch (va_arg(args, builder_part_t))
1310
0
    {
1311
0
      case BUILD_BLOB_ASN1_DER:
1312
0
        blob = va_arg(args, chunk_t);
1313
0
        continue;
1314
0
      case BUILD_X509_FLAG:
1315
0
        flags |= va_arg(args, x509_flag_t);
1316
0
        continue;
1317
0
      case BUILD_END:
1318
0
        break;
1319
0
      default:
1320
0
        return NULL;
1321
0
    }
1322
0
    break;
1323
0
  }
1324
1325
0
  if (blob.ptr)
1326
0
  {
1327
0
    private_openssl_x509_t *this;
1328
1329
0
    this = create_empty();
1330
0
    this->encoding = chunk_clone(blob);
1331
0
    this->flags |= flags;
1332
0
    if (parse_certificate(this))
1333
0
    {
1334
0
      return &this->public;
1335
0
    }
1336
0
    DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
1337
0
    destroy(this);
1338
0
  }
1339
0
  return NULL;
1340
0
}