Coverage Report

Created: 2025-07-23 07:07

/src/strongswan/src/libstrongswan/plugins/x509/x509_crl.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2014-2017 Tobias Brunner
3
 * Copyright (C) 2008-2009 Martin Willi
4
 * Copyright (C) 2017-2022 Andreas Steffen
5
 *
6
 * Copyright (C) secunet Security Networks AG
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU General Public License as published by the
10
 * Free Software Foundation; either version 2 of the License, or (at your
11
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
 * for more details.
17
 */
18
19
#include "x509_crl.h"
20
21
typedef struct private_x509_crl_t private_x509_crl_t;
22
23
#include <time.h>
24
25
#include <utils/debug.h>
26
#include <library.h>
27
#include <asn1/oid.h>
28
#include <asn1/asn1.h>
29
#include <asn1/asn1_parser.h>
30
#include <credentials/certificates/x509.h>
31
#include <credentials/keys/private_key.h>
32
#include <collections/linked_list.h>
33
34
/**
35
 * private data of x509_crl
36
 */
37
struct private_x509_crl_t {
38
39
  /**
40
   * public functions
41
   */
42
  x509_crl_t public;
43
44
  /**
45
   * X.509 crl encoding in ASN.1 DER format
46
   */
47
  chunk_t encoding;
48
49
  /**
50
   * X.509 crl body over which signature is computed
51
   */
52
  chunk_t tbsCertList;
53
54
  /**
55
   * Version of the X.509 crl
56
   */
57
  u_int version;
58
59
  /**
60
   * ID representing the crl issuer
61
   */
62
  identification_t *issuer;
63
64
  /**
65
   * CRL number
66
   */
67
  chunk_t crlNumber;
68
69
  /**
70
   * Time when the crl was generated
71
   */
72
  time_t thisUpdate;
73
74
  /**
75
   * Time when an update crl will be available
76
   */
77
  time_t nextUpdate;
78
79
  /**
80
   * list of revoked certificates as crl_revoked_t
81
   */
82
  linked_list_t *revoked;
83
84
  /**
85
   * List of Freshest CRL distribution points
86
   */
87
  linked_list_t *crl_uris;
88
89
  /**
90
   * Authority Key Identifier
91
   */
92
  chunk_t authKeyIdentifier;
93
94
  /**
95
   * Authority Key Serial Number
96
   */
97
  chunk_t authKeySerialNumber;
98
99
  /**
100
   * Optional OID of an [unsupported] critical extension
101
   */
102
  chunk_t critical_extension_oid;
103
104
  /**
105
   * Number of BaseCRL, if a delta CRL
106
   */
107
  chunk_t baseCrlNumber;
108
109
  /**
110
   * Signature scheme
111
   */
112
  signature_params_t *scheme;
113
114
  /**
115
   * Signature
116
   */
117
  chunk_t signature;
118
119
  /**
120
   * has this CRL been generated
121
   */
122
  bool generated;
123
124
  /**
125
   * reference counter
126
   */
127
  refcount_t ref;
128
};
129
130
/**
131
 * from x509_cert
132
 */
133
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
134
                         chunk_t *authKeySerialNumber);
135
136
/**
137
 * from x509_cert
138
 */
139
extern bool x509_parse_crlDistributionPoints(chunk_t blob, int level0,
140
                       linked_list_t *list);
141
142
/**
143
 * from x509_cert
144
 */
145
extern chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn);
146
147
/**
148
  * ASN.1 definition of an X.509 certificate revocation list
149
 */
150
static const asn1Object_t crlObjects[] = {
151
  { 0, "certificateList",       ASN1_SEQUENCE,     ASN1_OBJ  }, /*  0 */
152
  { 1,   "tbsCertList",       ASN1_SEQUENCE,     ASN1_OBJ  }, /*  1 */
153
  { 2,     "version",         ASN1_INTEGER,      ASN1_OPT |
154
                               ASN1_BODY }, /*  2 */
155
  { 2,     "end opt",         ASN1_EOC,          ASN1_END  }, /*  3 */
156
  { 2,     "signature",       ASN1_EOC,          ASN1_RAW  }, /*  4 */
157
  { 2,     "issuer",          ASN1_SEQUENCE,     ASN1_OBJ  }, /*  5 */
158
  { 2,     "thisUpdate",        ASN1_EOC,          ASN1_RAW  }, /*  6 */
159
  { 2,     "nextUpdate",        ASN1_EOC,          ASN1_RAW  }, /*  7 */
160
  { 2,     "revokedCertificates",   ASN1_SEQUENCE,     ASN1_OPT |
161
                               ASN1_LOOP }, /*  8 */
162
  { 3,       "certList",        ASN1_SEQUENCE,     ASN1_NONE }, /*  9 */
163
  { 4,         "userCertificate",   ASN1_INTEGER,      ASN1_BODY }, /* 10 */
164
  { 4,         "revocationDate",    ASN1_EOC,          ASN1_RAW  }, /* 11 */
165
  { 4,         "crlEntryExtensions",  ASN1_SEQUENCE,     ASN1_OPT |
166
                               ASN1_LOOP }, /* 12 */
167
  { 5,           "extension",     ASN1_SEQUENCE,     ASN1_NONE }, /* 13 */
168
  { 6,             "extnID",      ASN1_OID,          ASN1_BODY }, /* 14 */
169
  { 6,             "critical",    ASN1_BOOLEAN,      ASN1_DEF |
170
                               ASN1_BODY }, /* 15 */
171
  { 6,             "extnValue",   ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
172
  { 4,         "end opt or loop",   ASN1_EOC,          ASN1_END  }, /* 17 */
173
  { 2,     "end opt or loop",     ASN1_EOC,          ASN1_END  }, /* 18 */
174
  { 2,     "optional extensions",   ASN1_CONTEXT_C_0,  ASN1_OPT  }, /* 19 */
175
  { 3,       "crlExtensions",     ASN1_SEQUENCE,     ASN1_LOOP }, /* 20 */
176
  { 4,         "extension",     ASN1_SEQUENCE,     ASN1_NONE }, /* 21 */
177
  { 5,           "extnID",      ASN1_OID,          ASN1_BODY }, /* 22 */
178
  { 5,           "critical",      ASN1_BOOLEAN,      ASN1_DEF |
179
                               ASN1_BODY }, /* 23 */
180
  { 5,           "extnValue",     ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
181
  { 3,       "end loop",        ASN1_EOC,          ASN1_END  }, /* 25 */
182
  { 2,     "end opt",         ASN1_EOC,          ASN1_END  }, /* 26 */
183
  { 1,   "signatureAlgorithm",    ASN1_EOC,          ASN1_RAW  }, /* 27 */
184
  { 1,   "signatureValue",      ASN1_BIT_STRING,   ASN1_BODY }, /* 28 */
185
  { 0, "exit",            ASN1_EOC,      ASN1_EXIT }
186
};
187
1.51k
#define CRL_OBJ_TBS_CERT_LIST      1
188
941
#define CRL_OBJ_VERSION          2
189
1.48k
#define CRL_OBJ_SIG_ALG          4
190
741
#define CRL_OBJ_ISSUER           5
191
740
#define CRL_OBJ_THIS_UPDATE        6
192
669
#define CRL_OBJ_NEXT_UPDATE        7
193
22.8k
#define CRL_OBJ_USER_CERTIFICATE    10
194
22.8k
#define CRL_OBJ_REVOCATION_DATE     11
195
3.45k
#define CRL_OBJ_CRL_ENTRY_EXTN_ID   14
196
3.45k
#define CRL_OBJ_CRL_ENTRY_CRITICAL    15
197
3.44k
#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE  16
198
5.23k
#define CRL_OBJ_EXTN_ID         22
199
5.23k
#define CRL_OBJ_CRITICAL        23
200
5.20k
#define CRL_OBJ_EXTN_VALUE        24
201
231
#define CRL_OBJ_ALGORITHM       27
202
26
#define CRL_OBJ_SIGNATURE       28
203
204
/**
205
 *  Parses an X.509 Certificate Revocation List (CRL)
206
 */
207
static bool parse(private_x509_crl_t *this)
208
1.75k
{
209
1.75k
  asn1_parser_t *parser;
210
1.75k
  chunk_t object;
211
1.75k
  chunk_t extnID = chunk_empty;
212
1.75k
  chunk_t userCertificate = chunk_empty;
213
1.75k
  int objectID;
214
1.75k
  signature_params_t sig_alg = {};
215
1.75k
  bool success = FALSE;
216
1.75k
  bool critical = FALSE;
217
1.75k
  crl_revoked_t *revoked = NULL;
218
219
1.75k
  parser = asn1_parser_create(crlObjects, this->encoding);
220
221
127k
  while (parser->iterate(parser, &objectID, &object))
222
126k
  {
223
126k
    u_int level = parser->get_level(parser)+1;
224
225
126k
    switch (objectID)
226
126k
    {
227
1.51k
      case CRL_OBJ_TBS_CERT_LIST:
228
1.51k
        this->tbsCertList = object;
229
1.51k
        break;
230
941
      case CRL_OBJ_VERSION:
231
941
        this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
232
941
        DBG2(DBG_ASN, "  v%d", this->version);
233
941
        break;
234
1.48k
      case CRL_OBJ_SIG_ALG:
235
1.48k
        if (!signature_params_parse(object, level, &sig_alg))
236
664
        {
237
664
          DBG1(DBG_ASN, "  unable to parse signature algorithm");
238
664
          goto end;
239
664
        }
240
821
        break;
241
821
      case CRL_OBJ_ISSUER:
242
741
        this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
243
741
        DBG2(DBG_ASN, "  '%Y'", this->issuer);
244
741
        break;
245
740
      case CRL_OBJ_THIS_UPDATE:
246
740
        this->thisUpdate = asn1_parse_time(object, level);
247
740
        break;
248
669
      case CRL_OBJ_NEXT_UPDATE:
249
669
        this->nextUpdate = asn1_parse_time(object, level);
250
669
        break;
251
22.8k
      case CRL_OBJ_USER_CERTIFICATE:
252
22.8k
        userCertificate = object;
253
22.8k
        break;
254
22.8k
      case CRL_OBJ_REVOCATION_DATE:
255
22.8k
        revoked = malloc_thing(crl_revoked_t);
256
22.8k
        revoked->serial = chunk_clone(userCertificate);
257
22.8k
        revoked->date = asn1_parse_time(object, level);
258
22.8k
        revoked->reason = CRL_REASON_UNSPECIFIED;
259
22.8k
        this->revoked->insert_last(this->revoked, (void *)revoked);
260
22.8k
        break;
261
3.45k
      case CRL_OBJ_CRL_ENTRY_EXTN_ID:
262
5.23k
      case CRL_OBJ_EXTN_ID:
263
5.23k
        extnID = object;
264
5.23k
        break;
265
3.45k
      case CRL_OBJ_CRL_ENTRY_CRITICAL:
266
5.23k
      case CRL_OBJ_CRITICAL:
267
5.23k
        critical = object.len && *object.ptr;
268
5.23k
        DBG2(DBG_ASN, "  %s", critical ? "TRUE" : "FALSE");
269
5.23k
        break;
270
3.44k
      case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
271
5.20k
      case CRL_OBJ_EXTN_VALUE:
272
5.20k
      {
273
5.20k
        int extn_oid = asn1_known_oid(extnID);
274
275
5.20k
        switch (extn_oid)
276
5.20k
        {
277
2.95k
          case OID_CRL_REASON_CODE:
278
2.95k
            if (revoked)
279
2.91k
            {
280
2.91k
              if (object.len && *object.ptr == ASN1_ENUMERATED &&
281
2.91k
                asn1_length(&object) == 1)
282
2.30k
              {
283
2.30k
                revoked->reason = *object.ptr;
284
2.30k
              }
285
2.91k
              DBG2(DBG_ASN, "  '%N'", crl_reason_names,
286
2.91k
                 revoked->reason);
287
2.91k
            }
288
2.95k
            break;
289
504
          case OID_AUTHORITY_KEY_ID:
290
504
            chunk_free(&this->authKeyIdentifier);
291
504
            this->authKeyIdentifier =
292
504
              x509_parse_authorityKeyIdentifier(
293
504
                  object, level, &this->authKeySerialNumber);
294
504
            break;
295
49
          case OID_CRL_NUMBER:
296
49
            if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
297
49
                            level, "crlNumber"))
298
5
            {
299
5
              goto end;
300
5
            }
301
44
            this->crlNumber = object;
302
44
            break;
303
179
          case OID_FRESHEST_CRL:
304
179
            if (!x509_parse_crlDistributionPoints(object, level,
305
179
                                this->crl_uris))
306
62
            {
307
62
              goto end;
308
62
            }
309
117
            break;
310
117
          case OID_DELTA_CRL_INDICATOR:
311
30
            if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
312
30
                          level, "deltaCrlIndicator"))
313
6
            {
314
6
              goto end;
315
6
            }
316
24
            this->baseCrlNumber = object;
317
24
            break;
318
146
          case OID_ISSUING_DIST_POINT:
319
            /* TODO support of IssuingDistributionPoints */
320
146
            break;
321
1.34k
          default:
322
1.34k
            if (critical && lib->settings->get_bool(lib->settings,
323
12
              "%s.x509.enforce_critical", TRUE, lib->ns))
324
12
            {
325
12
              DBG1(DBG_ASN, "critical '%s' extension not supported",
326
12
                 (extn_oid == OID_UNKNOWN) ? "unknown" :
327
12
                 (char*)oid_names[extn_oid].name);
328
12
              goto end;
329
12
            }
330
1.32k
            break;
331
5.20k
        }
332
5.11k
        break;
333
5.20k
      }
334
5.11k
      case CRL_OBJ_ALGORITHM:
335
231
      {
336
231
        INIT(this->scheme);
337
231
        if (!signature_params_parse(object, level, this->scheme))
338
56
        {
339
56
          DBG1(DBG_ASN, "  unable to parse signature algorithm");
340
56
          goto end;
341
56
        }
342
175
        if (!signature_params_equal(this->scheme, &sig_alg))
343
118
        {
344
118
          DBG1(DBG_ASN, "  signature algorithms do not agree");
345
118
          goto end;
346
118
        }
347
57
        break;
348
175
      }
349
57
      case CRL_OBJ_SIGNATURE:
350
26
        this->signature = chunk_skip(object, 1);
351
26
        break;
352
59.1k
      default:
353
59.1k
        break;
354
126k
    }
355
126k
  }
356
830
  success = parser->success(parser);
357
358
1.75k
end:
359
1.75k
  parser->destroy(parser);
360
1.75k
  signature_params_clear(&sig_alg);
361
1.75k
  return success;
362
830
}
363
364
CALLBACK(filter, bool,
365
  void *data, enumerator_t *orig, va_list args)
366
0
{
367
0
  crl_revoked_t *revoked;
368
0
  crl_reason_t *reason;
369
0
  chunk_t *serial;
370
0
  time_t *date;
371
372
0
  VA_ARGS_VGET(args, serial, date, reason);
373
374
0
  if (orig->enumerate(orig, &revoked))
375
0
  {
376
0
    if (serial)
377
0
    {
378
0
      *serial = chunk_skip_zero(revoked->serial);
379
0
    }
380
0
    if (date)
381
0
    {
382
0
      *date = revoked->date;
383
0
    }
384
0
    if (reason)
385
0
    {
386
0
      *reason = revoked->reason;
387
0
    }
388
0
    return TRUE;
389
0
  }
390
0
  return FALSE;
391
0
}
392
393
METHOD(crl_t, get_serial, chunk_t,
394
  private_x509_crl_t *this)
395
0
{
396
0
  return chunk_skip_zero(this->crlNumber);
397
0
}
398
399
METHOD(crl_t, get_authKeyIdentifier, chunk_t,
400
  private_x509_crl_t *this)
401
0
{
402
0
  return this->authKeyIdentifier;
403
0
}
404
405
METHOD(crl_t, is_delta_crl, bool,
406
  private_x509_crl_t *this, chunk_t *base_crl)
407
0
{
408
0
  if (this->baseCrlNumber.len)
409
0
  {
410
0
    if (base_crl)
411
0
    {
412
0
      *base_crl = chunk_skip_zero(this->baseCrlNumber);
413
0
    }
414
0
    return TRUE;
415
0
  }
416
0
  return FALSE;
417
0
}
418
419
METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*,
420
  private_x509_crl_t *this)
421
0
{
422
0
  return this->crl_uris->create_enumerator(this->crl_uris);
423
0
}
424
425
METHOD(crl_t, create_enumerator, enumerator_t*,
426
  private_x509_crl_t *this)
427
0
{
428
0
  return enumerator_create_filter(
429
0
                this->revoked->create_enumerator(this->revoked),
430
0
                filter, NULL, NULL);
431
0
}
432
433
METHOD(certificate_t, get_type, certificate_type_t,
434
  private_x509_crl_t *this)
435
0
{
436
0
  return CERT_X509_CRL;
437
0
}
438
439
METHOD(certificate_t, get_issuer, identification_t*,
440
  private_x509_crl_t *this)
441
0
{
442
0
  return this->issuer;
443
0
}
444
445
METHOD(certificate_t, has_issuer, id_match_t,
446
  private_x509_crl_t *this, identification_t *issuer)
447
0
{
448
0
  if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
449
0
    chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
450
0
  {
451
0
    return ID_MATCH_PERFECT;
452
0
  }
453
0
  return this->issuer->matches(this->issuer, issuer);
454
0
}
455
456
METHOD(certificate_t, issued_by, bool,
457
  private_x509_crl_t *this, certificate_t *issuer,
458
  signature_params_t **scheme)
459
0
{
460
0
  public_key_t *key;
461
0
  bool valid;
462
0
  x509_t *x509 = (x509_t*)issuer;
463
0
  chunk_t keyid = chunk_empty;
464
465
  /* check if issuer is an X.509 certificate with cRLSign keyUsage bit set */
466
0
  if (issuer->get_type(issuer) != CERT_X509)
467
0
  {
468
0
    return FALSE;
469
0
  }
470
0
  if (!(x509->get_flags(x509) & X509_CRL_SIGN))
471
0
  {
472
0
    return FALSE;
473
0
  }
474
475
  /* compare keyIdentifiers if available, otherwise use DNs */
476
0
  if (this->authKeyIdentifier.ptr)
477
0
  {
478
0
    keyid = x509->get_subjectKeyIdentifier(x509);
479
0
    if (keyid.len && !chunk_equals(keyid, this->authKeyIdentifier))
480
0
    {
481
0
      return FALSE;
482
0
    }
483
0
  }
484
0
  if (!keyid.len)
485
0
  {
486
0
    if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
487
0
    {
488
0
      return FALSE;
489
0
    }
490
0
  }
491
492
0
  key = issuer->get_public_key(issuer);
493
0
  if (!key)
494
0
  {
495
0
    return FALSE;
496
0
  }
497
0
  valid = key->verify(key, this->scheme->scheme, this->scheme->params,
498
0
            this->tbsCertList, this->signature);
499
0
  key->destroy(key);
500
0
  if (valid && scheme)
501
0
  {
502
0
    *scheme = signature_params_clone(this->scheme);
503
0
  }
504
0
  return valid;
505
0
}
506
507
METHOD(certificate_t, get_public_key, public_key_t*,
508
  private_x509_crl_t *this)
509
0
{
510
0
  return NULL;
511
0
}
512
513
METHOD(certificate_t, get_ref, certificate_t*,
514
  private_x509_crl_t *this)
515
0
{
516
0
  ref_get(&this->ref);
517
0
  return &this->public.crl.certificate;
518
0
}
519
520
METHOD(certificate_t, get_validity, bool,
521
  private_x509_crl_t *this, time_t *when,
522
  time_t *not_before, time_t *not_after)
523
0
{
524
0
  time_t t = when ? *when : time(NULL);
525
526
0
  if (not_before)
527
0
  {
528
0
    *not_before = this->thisUpdate;
529
0
  }
530
0
  if (not_after)
531
0
  {
532
0
    *not_after = this->nextUpdate;
533
0
  }
534
0
  return (t >= this->thisUpdate && t <= this->nextUpdate);
535
0
}
536
537
METHOD(certificate_t, get_encoding, bool,
538
  private_x509_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
539
0
{
540
0
  if (type == CERT_ASN1_DER)
541
0
  {
542
0
    *encoding = chunk_clone(this->encoding);
543
0
    return TRUE;
544
0
  }
545
0
  return lib->encoding->encode(lib->encoding, type, NULL, encoding,
546
0
          CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
547
0
}
548
549
METHOD(certificate_t, equals, bool,
550
  private_x509_crl_t *this, certificate_t *other)
551
0
{
552
0
  chunk_t encoding;
553
0
  bool equal;
554
555
0
  if ((certificate_t*)this == other)
556
0
  {
557
0
    return TRUE;
558
0
  }
559
0
  if (other->equals == (void*)equals)
560
0
  { /* skip allocation if we have the same implementation */
561
0
    return chunk_equals(this->encoding, ((private_x509_crl_t*)other)->encoding);
562
0
  }
563
0
  if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
564
0
  {
565
0
    return FALSE;
566
0
  }
567
0
  equal = chunk_equals(this->encoding, encoding);
568
0
  free(encoding.ptr);
569
0
  return equal;
570
0
}
571
572
/**
573
 * Destroy a revoked_t entry
574
 */
575
static void revoked_destroy(crl_revoked_t *revoked)
576
22.8k
{
577
22.8k
  free(revoked->serial.ptr);
578
22.8k
  free(revoked);
579
22.8k
}
580
581
METHOD(certificate_t, destroy, void,
582
  private_x509_crl_t *this)
583
6.66k
{
584
6.66k
  if (ref_put(&this->ref))
585
6.66k
  {
586
6.66k
    this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
587
6.66k
    this->crl_uris->destroy_function(this->crl_uris,
588
6.66k
                     (void*)x509_cdp_destroy);
589
6.66k
    signature_params_destroy(this->scheme);
590
6.66k
    DESTROY_IF(this->issuer);
591
6.66k
    free(this->authKeyIdentifier.ptr);
592
6.66k
    free(this->encoding.ptr);
593
6.66k
    free(this->critical_extension_oid.ptr);
594
6.66k
    if (this->generated)
595
4.91k
    {
596
4.91k
      free(this->crlNumber.ptr);
597
4.91k
      free(this->baseCrlNumber.ptr);
598
4.91k
      free(this->signature.ptr);
599
4.91k
      free(this->tbsCertList.ptr);
600
4.91k
    }
601
6.66k
    free(this);
602
6.66k
  }
603
6.66k
}
604
605
/**
606
 * create an empty but initialized X.509 crl
607
 */
608
static private_x509_crl_t* create_empty(void)
609
6.66k
{
610
6.66k
  private_x509_crl_t *this;
611
612
6.66k
  INIT(this,
613
6.66k
    .public = {
614
6.66k
      .crl = {
615
6.66k
        .certificate = {
616
6.66k
          .get_type = _get_type,
617
6.66k
          .get_subject = _get_issuer,
618
6.66k
          .get_issuer = _get_issuer,
619
6.66k
          .has_subject = _has_issuer,
620
6.66k
          .has_issuer = _has_issuer,
621
6.66k
          .issued_by = _issued_by,
622
6.66k
          .get_public_key = _get_public_key,
623
6.66k
          .get_validity = _get_validity,
624
6.66k
          .get_encoding = _get_encoding,
625
6.66k
          .equals = _equals,
626
6.66k
          .get_ref = _get_ref,
627
6.66k
          .destroy = _destroy,
628
6.66k
        },
629
6.66k
        .get_serial = _get_serial,
630
6.66k
        .get_authKeyIdentifier = _get_authKeyIdentifier,
631
6.66k
        .is_delta_crl = _is_delta_crl,
632
6.66k
        .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator,
633
6.66k
        .create_enumerator = _create_enumerator,
634
6.66k
      },
635
6.66k
    },
636
6.66k
    .revoked = linked_list_create(),
637
6.66k
    .crl_uris = linked_list_create(),
638
6.66k
    .ref = 1,
639
6.66k
  );
640
6.66k
  return this;
641
6.66k
}
642
643
/**
644
 * See header.
645
 */
646
x509_crl_t *x509_crl_load(certificate_type_t type, va_list args)
647
4.91k
{
648
4.91k
  chunk_t blob = chunk_empty;
649
650
4.91k
  while (TRUE)
651
6.66k
  {
652
6.66k
    switch (va_arg(args, builder_part_t))
653
6.66k
    {
654
1.75k
      case BUILD_BLOB_ASN1_DER:
655
1.75k
        blob = va_arg(args, chunk_t);
656
1.75k
        continue;
657
1.75k
      case BUILD_END:
658
1.75k
        break;
659
3.15k
      default:
660
3.15k
        return NULL;
661
6.66k
    }
662
1.75k
    break;
663
6.66k
  }
664
1.75k
  if (blob.ptr)
665
1.75k
  {
666
1.75k
    private_x509_crl_t *crl = create_empty();
667
668
1.75k
    crl->encoding = chunk_clone(blob);
669
1.75k
    if (parse(crl))
670
26
    {
671
26
      return &crl->public;
672
26
    }
673
1.72k
    destroy(crl);
674
1.72k
  }
675
1.72k
  return NULL;
676
1.75k
};
677
678
/**
679
 * Read certificate status from enumerator, copy to crl
680
 */
681
static void read_revoked(private_x509_crl_t *crl, enumerator_t *enumerator)
682
0
{
683
0
  crl_revoked_t *revoked;
684
0
  chunk_t serial;
685
0
  time_t date;
686
0
  crl_reason_t reason;
687
688
0
  while (enumerator->enumerate(enumerator, &serial, &date, &reason))
689
0
  {
690
0
    INIT(revoked,
691
0
      .serial = chunk_clone(serial),
692
0
      .date = date,
693
0
      .reason = reason,
694
0
    );
695
0
    crl->revoked->insert_last(crl->revoked, revoked);
696
0
  }
697
0
}
698
699
/**
700
 * Generate CRL encoding, sign CRL
701
 */
702
static bool generate(private_x509_crl_t *this, certificate_t *cert,
703
           private_key_t *key, hash_algorithm_t digest_alg)
704
0
{
705
0
  chunk_t extensions = chunk_empty, certList = chunk_empty, serial;
706
0
  chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty;
707
0
  chunk_t sig_scheme = chunk_empty, criticalExtension = chunk_empty;
708
0
  enumerator_t *enumerator;
709
0
  crl_reason_t reason;
710
0
  time_t date;
711
0
  x509_t *x509;
712
713
0
  x509 = (x509_t*)cert;
714
715
0
  this->issuer = cert->get_subject(cert);
716
0
  this->issuer = this->issuer->clone(this->issuer);
717
718
0
  this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509));
719
720
  /* select signature scheme, if not already specified */
721
0
  if (!this->scheme)
722
0
  {
723
0
    INIT(this->scheme,
724
0
      .scheme = signature_scheme_from_oid(
725
0
                hasher_signature_algorithm_to_oid(digest_alg,
726
0
                        key->get_type(key))),
727
0
    );
728
0
  }
729
0
  if (this->scheme->scheme == SIGN_UNKNOWN)
730
0
  {
731
0
    return FALSE;
732
0
  }
733
0
  if (!signature_params_build(this->scheme, &sig_scheme))
734
0
  {
735
0
    return FALSE;
736
0
  }
737
738
0
  enumerator = create_enumerator(this);
739
0
  while (enumerator->enumerate(enumerator, &serial, &date, &reason))
740
0
  {
741
0
    chunk_t revoked, entry_ext = chunk_empty;
742
743
0
    if (reason != CRL_REASON_UNSPECIFIED)
744
0
    {
745
0
      entry_ext = asn1_wrap(ASN1_SEQUENCE, "m",
746
0
              asn1_wrap(ASN1_SEQUENCE, "mm",
747
0
                asn1_build_known_oid(OID_CRL_REASON_CODE),
748
0
                asn1_wrap(ASN1_OCTET_STRING, "m",
749
0
                  asn1_wrap(ASN1_ENUMERATED, "c",
750
0
                    chunk_from_chars(reason)))));
751
0
    }
752
0
    revoked = asn1_wrap(ASN1_SEQUENCE, "mmm",
753
0
              asn1_integer("c", serial),
754
0
              asn1_from_time(&date, ASN1_UTCTIME),
755
0
              entry_ext);
756
0
    certList = chunk_cat("mm", certList, revoked);
757
0
  }
758
0
  enumerator->destroy(enumerator);
759
760
0
  crlDistributionPoints = x509_build_crlDistributionPoints(this->crl_uris,
761
0
                               OID_FRESHEST_CRL);
762
763
0
  if (this->baseCrlNumber.len)
764
0
  {
765
0
    baseCrlNumber =  asn1_wrap(ASN1_SEQUENCE, "mmm",
766
0
              asn1_build_known_oid(OID_DELTA_CRL_INDICATOR),
767
0
              asn1_wrap(ASN1_BOOLEAN, "c",
768
0
                chunk_from_chars(0xFF)),
769
0
              asn1_wrap(ASN1_OCTET_STRING, "m",
770
0
                asn1_integer("c", this->baseCrlNumber)));
771
0
  }
772
773
0
  if (this->critical_extension_oid.len > 0)
774
0
  {
775
0
    criticalExtension = asn1_wrap(ASN1_SEQUENCE, "mmm",
776
0
          asn1_simple_object(ASN1_OID, this->critical_extension_oid),
777
0
          asn1_simple_object(ASN1_BOOLEAN, chunk_from_chars(0xFF)),
778
0
          asn1_simple_object(ASN1_OCTET_STRING, chunk_empty));
779
0
  }
780
781
0
  extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
782
0
          asn1_wrap(ASN1_SEQUENCE, "mmmmm",
783
0
            asn1_wrap(ASN1_SEQUENCE, "mm",
784
0
              asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
785
0
              asn1_wrap(ASN1_OCTET_STRING, "m",
786
0
                asn1_wrap(ASN1_SEQUENCE, "m",
787
0
                  asn1_wrap(ASN1_CONTEXT_S_0, "c",
788
0
                        this->authKeyIdentifier)))),
789
0
            asn1_wrap(ASN1_SEQUENCE, "mm",
790
0
              asn1_build_known_oid(OID_CRL_NUMBER),
791
0
              asn1_wrap(ASN1_OCTET_STRING, "m",
792
0
                asn1_integer("c", this->crlNumber))),
793
0
            crlDistributionPoints, baseCrlNumber,
794
0
            criticalExtension));
795
796
0
  this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cccmmmm",
797
0
              ASN1_INTEGER_1,
798
0
              sig_scheme,
799
0
              this->issuer->get_encoding(this->issuer),
800
0
              asn1_from_time(&this->thisUpdate, ASN1_UTCTIME),
801
0
              asn1_from_time(&this->nextUpdate, ASN1_UTCTIME),
802
0
              asn1_wrap(ASN1_SEQUENCE, "m", certList),
803
0
              extensions);
804
805
0
  if (!key->sign(key, this->scheme->scheme, this->scheme->params,
806
0
           this->tbsCertList, &this->signature))
807
0
  {
808
0
    chunk_free(&sig_scheme);
809
0
    return FALSE;
810
0
  }
811
0
  this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
812
0
              this->tbsCertList,
813
0
              sig_scheme,
814
0
              asn1_bitstring("c", this->signature));
815
0
  return TRUE;
816
0
}
817
818
/**
819
 * See header.
820
 */
821
x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
822
4.91k
{
823
4.91k
  hash_algorithm_t digest_alg = HASH_SHA256;
824
4.91k
  private_x509_crl_t *crl;
825
4.91k
  certificate_t *cert = NULL;
826
4.91k
  private_key_t *key = NULL;
827
828
4.91k
  crl = create_empty();
829
4.91k
  crl->generated = TRUE;
830
4.91k
  while (TRUE)
831
4.91k
  {
832
4.91k
    builder_part_t part = va_arg(args, builder_part_t);
833
834
4.91k
    switch (part)
835
4.91k
    {
836
0
      case BUILD_SIGNING_KEY:
837
0
        key = va_arg(args, private_key_t*);
838
0
        continue;
839
0
      case BUILD_SIGNING_CERT:
840
0
        cert = va_arg(args, certificate_t*);
841
0
        continue;
842
0
      case BUILD_NOT_BEFORE_TIME:
843
0
        crl->thisUpdate = va_arg(args, time_t);
844
0
        continue;
845
0
      case BUILD_NOT_AFTER_TIME:
846
0
        crl->nextUpdate = va_arg(args, time_t);
847
0
        continue;
848
0
      case BUILD_SERIAL:
849
0
        crl->crlNumber = va_arg(args, chunk_t);
850
0
        crl->crlNumber = chunk_clone(crl->crlNumber);
851
0
        continue;
852
0
      case BUILD_SIGNATURE_SCHEME:
853
0
        crl->scheme = va_arg(args, signature_params_t*);
854
0
        crl->scheme = signature_params_clone(crl->scheme);
855
0
        continue;
856
0
      case BUILD_DIGEST_ALG:
857
0
        digest_alg = va_arg(args, int);
858
0
        continue;
859
0
      case BUILD_REVOKED_ENUMERATOR:
860
0
        read_revoked(crl, va_arg(args, enumerator_t*));
861
0
        continue;
862
0
      case BUILD_BASE_CRL:
863
0
        crl->baseCrlNumber = va_arg(args, chunk_t);
864
0
        crl->baseCrlNumber = chunk_clone(crl->baseCrlNumber);
865
0
        continue;
866
0
      case BUILD_CRL_DISTRIBUTION_POINTS:
867
0
      {
868
0
        enumerator_t *enumerator;
869
0
        linked_list_t *list;
870
0
        x509_cdp_t *in, *cdp;
871
872
0
        list = va_arg(args, linked_list_t*);
873
0
        enumerator = list->create_enumerator(list);
874
0
        while (enumerator->enumerate(enumerator, &in))
875
0
        {
876
0
          INIT(cdp,
877
0
            .uri = strdup(in->uri),
878
0
            .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL,
879
0
          );
880
0
          crl->crl_uris->insert_last(crl->crl_uris, cdp);
881
0
        }
882
0
        enumerator->destroy(enumerator);
883
0
        continue;
884
0
      }
885
0
      case BUILD_CRITICAL_EXTENSION:
886
0
        crl->critical_extension_oid = chunk_clone(va_arg(args, chunk_t));
887
0
        continue;
888
0
      case BUILD_END:
889
0
        break;
890
4.91k
      default:
891
4.91k
        destroy(crl);
892
4.91k
        return NULL;
893
4.91k
    }
894
0
    break;
895
4.91k
  }
896
897
0
  if (key && cert && cert->get_type(cert) == CERT_X509 &&
898
0
    generate(crl, cert, key, digest_alg))
899
0
  {
900
0
    return &crl->public;
901
0
  }
902
0
  destroy(crl);
903
0
  return NULL;
904
0
}