Coverage Report

Created: 2026-06-30 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/plugins/x509/x509_ac.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2017 Tobias Brunner
3
 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
4
 * Copyright (C) 2003 Martin Berner, Lukas Suter
5
 * Copyright (C) 2002-2022 Andreas Steffen
6
 * Copyright (C) 2009 Martin Willi
7
 *
8
 * Copyright (C) secunet Security Networks AG
9
 *
10
 * This program is free software; you can redistribute it and/or modify it
11
 * under the terms of the GNU General Public License as published by the
12
 * Free Software Foundation; either version 2 of the License, or (at your
13
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
14
 *
15
 * This program is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
 * for more details.
19
 */
20
21
#include "x509_ac.h"
22
23
#include <time.h>
24
25
#include <library.h>
26
#include <utils/debug.h>
27
#include <asn1/oid.h>
28
#include <asn1/asn1.h>
29
#include <asn1/asn1_parser.h>
30
#include <utils/identification.h>
31
#include <collections/linked_list.h>
32
#include <credentials/certificates/x509.h>
33
#include <credentials/keys/private_key.h>
34
35
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
36
                  int level0, chunk_t *authKeySerialNumber);
37
38
typedef struct private_x509_ac_t private_x509_ac_t;
39
40
/**
41
 * private data of x509_ac_t object
42
 */
43
struct private_x509_ac_t {
44
45
  /**
46
   * public functions
47
   */
48
  x509_ac_t public;
49
50
  /**
51
   * X.509 attribute certificate encoding in ASN.1 DER format
52
   */
53
  chunk_t encoding;
54
55
  /**
56
   * X.509 attribute certificate body over which signature is computed
57
   */
58
  chunk_t certificateInfo;
59
60
  /**
61
   * Version of the X.509 attribute certificate
62
   */
63
  u_int version;
64
65
  /**
66
   * Serial number of the X.509 attribute certificate
67
   */
68
  chunk_t serialNumber;
69
70
  /**
71
   * ID representing the issuer of the holder certificate
72
   */
73
  identification_t *holderIssuer;
74
75
  /**
76
   * Serial number of the holder certificate
77
   */
78
  identification_t *holderSerial;
79
80
  /**
81
   * ID representing the holder
82
   */
83
  identification_t *entityName;
84
85
  /**
86
   * ID representing the attribute certificate issuer
87
   */
88
  identification_t *issuerName;
89
90
  /**
91
   * Start time of certificate validity
92
   */
93
  time_t notBefore;
94
95
  /**
96
   * End time of certificate validity
97
   */
98
  time_t notAfter;
99
100
  /**
101
   * List of group attributes, as group_t
102
   */
103
  linked_list_t *groups;
104
105
  /**
106
   * Authority Key Identifier
107
   */
108
  chunk_t authKeyIdentifier;
109
110
  /**
111
   * Authority Key Serial Number
112
   */
113
  chunk_t authKeySerialNumber;
114
115
  /**
116
   * No revocation information available
117
   */
118
  bool noRevAvail;
119
120
  /**
121
   * Signature scheme
122
   */
123
  signature_params_t *scheme;
124
125
  /**
126
   * Signature
127
   */
128
  chunk_t signature;
129
130
  /**
131
   * Holder certificate
132
   */
133
  certificate_t *holderCert;
134
135
  /**
136
   * Signer certificate
137
   */
138
  certificate_t *signerCert;
139
140
  /**
141
  * Signer private key;
142
  */
143
  private_key_t *signerKey;
144
145
  /**
146
   * reference count
147
   */
148
  refcount_t ref;
149
};
150
151
/**
152
 * Group definition, an IETF attribute
153
 */
154
typedef struct {
155
  /** Attribute type */
156
  ac_group_type_t type;
157
  /* attribute value */
158
  chunk_t value;
159
} group_t;
160
161
/**
162
 * Clean up a group entry
163
 */
164
static void group_destroy(group_t *group)
165
0
{
166
0
  free(group->value.ptr);
167
0
  free(group);
168
0
}
169
170
static chunk_t ASN1_noRevAvail_ext = chunk_from_chars(
171
  0x30, 0x09,
172
      0x06, 0x03,
173
        0x55, 0x1d, 0x38,
174
      0x04, 0x02,
175
        0x05, 0x00
176
);
177
178
/**
179
 * declaration of function implemented in x509_cert.c
180
 */
181
extern bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
182
                  linked_list_t *list);
183
/**
184
 * parses a directoryName
185
 */
186
static bool parse_directoryName(chunk_t blob, int level, bool implicit,
187
                identification_t **name)
188
0
{
189
0
  identification_t *directoryName;
190
0
  enumerator_t *enumerator;
191
0
  bool first = TRUE;
192
0
  linked_list_t *list;
193
194
0
  list = linked_list_create();
195
0
  if (!x509_parse_generalNames(blob, level, implicit, list))
196
0
  {
197
0
    list->destroy(list);
198
0
    return FALSE;
199
0
  }
200
201
0
  enumerator = list->create_enumerator(list);
202
0
  while (enumerator->enumerate(enumerator, &directoryName))
203
0
  {
204
0
    if (first)
205
0
    {
206
0
      *name = directoryName;
207
0
      first = FALSE;
208
0
    }
209
0
    else
210
0
    {
211
0
      DBG1(DBG_ASN, "more than one directory name - first selected");
212
0
      directoryName->destroy(directoryName);
213
0
      break;
214
0
    }
215
0
  }
216
0
  enumerator->destroy(enumerator);
217
0
  list->destroy(list);
218
219
0
  if (first)
220
0
  {
221
0
    DBG1(DBG_ASN, "no directoryName found");
222
0
    return FALSE;
223
0
  }
224
0
  return TRUE;
225
0
}
226
227
/**
228
 * ASN.1 definition of roleSyntax
229
 */
230
static const asn1Object_t roleSyntaxObjects[] =
231
{
232
  { 0, "roleSyntax",    ASN1_SEQUENCE,    ASN1_NONE }, /* 0 */
233
  { 1,   "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
234
                        ASN1_OBJ  }, /* 1 */
235
  { 1,   "end opt",   ASN1_EOC,     ASN1_END  }, /* 2 */
236
  { 1,   "roleName",    ASN1_CONTEXT_C_1, ASN1_OBJ  }, /* 3 */
237
  { 0, "exit",      ASN1_EOC,     ASN1_EXIT }
238
};
239
240
/**
241
 * Parses roleSyntax
242
 */
243
static void parse_roleSyntax(chunk_t blob, int level0)
244
0
{
245
0
  asn1_parser_t *parser;
246
0
  chunk_t object;
247
0
  int objectID;
248
249
0
  parser = asn1_parser_create(roleSyntaxObjects, blob);
250
0
  parser->set_top_level(parser, level0);
251
252
0
  while (parser->iterate(parser, &objectID, &object))
253
0
  {
254
0
    switch (objectID)
255
0
    {
256
0
      default:
257
0
        break;
258
0
    }
259
0
  }
260
0
  parser->destroy(parser);
261
0
}
262
263
/**
264
 * ASN.1 definition of ietfAttrSyntax
265
 */
266
static const asn1Object_t ietfAttrSyntaxObjects[] =
267
{
268
  { 0, "ietfAttrSyntax",    ASN1_SEQUENCE,    ASN1_NONE }, /*  0 */
269
  { 1,   "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
270
                          ASN1_BODY }, /*  1 */
271
  { 1,   "end opt",     ASN1_EOC,     ASN1_END  }, /*  2 */
272
  { 1,   "values",      ASN1_SEQUENCE,    ASN1_LOOP }, /*  3 */
273
  { 2,     "octets",      ASN1_OCTET_STRING,  ASN1_OPT |
274
                          ASN1_BODY }, /*  4 */
275
  { 2,     "end choice",    ASN1_EOC,     ASN1_END  }, /*  5 */
276
  { 2,     "oid",       ASN1_OID,     ASN1_OPT |
277
                          ASN1_BODY }, /*  6 */
278
  { 2,     "end choice",    ASN1_EOC,     ASN1_END  }, /*  7 */
279
  { 2,     "string",      ASN1_UTF8STRING,  ASN1_OPT |
280
                          ASN1_BODY }, /*  8 */
281
  { 2,     "end choice",    ASN1_EOC,     ASN1_END  }, /*  9 */
282
  { 1,   "end loop",      ASN1_EOC,     ASN1_END  }, /* 10 */
283
  { 0, "exit",        ASN1_EOC,     ASN1_EXIT }
284
};
285
0
#define IETF_ATTR_OCTETS   4
286
0
#define IETF_ATTR_OID    6
287
0
#define IETF_ATTR_STRING   8
288
289
/**
290
 * Parse group memberships, IETF attributes
291
 */
292
static bool parse_groups(private_x509_ac_t *this, chunk_t encoded, int level0)
293
0
{
294
0
  ac_group_type_t type;
295
0
  group_t *group;
296
0
  asn1_parser_t *parser;
297
0
  chunk_t object;
298
0
  int objectID;
299
0
  bool success;
300
301
0
  parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded);
302
0
  parser->set_top_level(parser, level0);
303
0
  while (parser->iterate(parser, &objectID, &object))
304
0
  {
305
0
    switch (objectID)
306
0
    {
307
0
      case IETF_ATTR_OCTETS:
308
0
        type = AC_GROUP_TYPE_OCTETS;
309
0
        break;
310
0
      case IETF_ATTR_OID:
311
0
        type = AC_GROUP_TYPE_OID;
312
0
        break;
313
0
      case IETF_ATTR_STRING:
314
0
        type = AC_GROUP_TYPE_STRING;
315
0
        break;
316
0
      default:
317
0
        continue;
318
0
    }
319
0
    INIT(group,
320
0
      .type = type,
321
0
      .value = chunk_clone(object),
322
0
    );
323
0
    this->groups->insert_last(this->groups, group);
324
0
  }
325
0
  success = parser->success(parser);
326
0
  parser->destroy(parser);
327
328
0
  return success;
329
0
}
330
331
/**
332
 * ASN.1 definition of an X509 attribute certificate
333
 */
334
static const asn1Object_t acObjects[] =
335
{
336
  { 0, "AttributeCertificate",      ASN1_SEQUENCE,      ASN1_OBJ  }, /*  0 */
337
  { 1,   "AttributeCertificateInfo",    ASN1_SEQUENCE,      ASN1_OBJ  }, /*  1 */
338
  { 2,     "version",           ASN1_INTEGER,     ASN1_DEF |
339
                                  ASN1_BODY }, /*  2 */
340
  { 2,     "holder",            ASN1_SEQUENCE,      ASN1_NONE }, /*  3 */
341
  { 3,       "baseCertificateID",     ASN1_CONTEXT_C_0,   ASN1_OPT  }, /*  4 */
342
  { 4,         "issuer",          ASN1_SEQUENCE,      ASN1_OBJ  }, /*  5 */
343
  { 4,         "serial",          ASN1_INTEGER,     ASN1_BODY }, /*  6 */
344
  { 4,         "issuerUID",       ASN1_BIT_STRING,    ASN1_OPT |
345
                                  ASN1_BODY }, /*  7 */
346
  { 4,         "end opt",         ASN1_EOC,       ASN1_END  }, /*  8 */
347
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /*  9 */
348
  { 3,       "entityName",        ASN1_CONTEXT_C_1,   ASN1_OPT |
349
                                  ASN1_OBJ  }, /* 10 */
350
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /* 11 */
351
  { 3,       "objectDigestInfo",      ASN1_CONTEXT_C_2,   ASN1_OPT  }, /* 12 */
352
  { 4,         "digestedObjectType",    ASN1_ENUMERATED,    ASN1_BODY }, /* 13 */
353
  { 4,         "otherObjectTypeID",   ASN1_OID,       ASN1_OPT |
354
                                  ASN1_BODY }, /* 14 */
355
  { 4,         "end opt",         ASN1_EOC,       ASN1_END  }, /* 15 */
356
  { 4,         "digestAlgorithm",     ASN1_EOC,       ASN1_RAW  }, /* 16 */
357
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /* 17 */
358
  { 2,     "v2Form",            ASN1_CONTEXT_C_0,   ASN1_NONE }, /* 18 */
359
  { 3,       "issuerName",        ASN1_SEQUENCE,      ASN1_OPT |
360
                                  ASN1_OBJ  }, /* 19 */
361
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /* 20 */
362
  { 3,       "baseCertificateID",     ASN1_CONTEXT_C_0,   ASN1_OPT  }, /* 21 */
363
  { 4,         "issuerSerial",      ASN1_SEQUENCE,      ASN1_NONE }, /* 22 */
364
  { 5,           "issuer",        ASN1_SEQUENCE,      ASN1_OBJ  }, /* 23 */
365
  { 5,           "serial",        ASN1_INTEGER,     ASN1_BODY }, /* 24 */
366
  { 5,           "issuerUID",       ASN1_BIT_STRING,    ASN1_OPT |
367
                                  ASN1_BODY }, /* 25 */
368
  { 5,           "end opt",       ASN1_EOC,       ASN1_END  }, /* 26 */
369
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /* 27 */
370
  { 3,       "objectDigestInfo",      ASN1_CONTEXT_C_1,   ASN1_OPT  }, /* 28 */
371
  { 4,         "digestInfo",        ASN1_SEQUENCE,      ASN1_OBJ  }, /* 29 */
372
  { 5,           "digestedObjectType",  ASN1_ENUMERATED,    ASN1_BODY }, /* 30 */
373
  { 5,           "otherObjectTypeID",   ASN1_OID,       ASN1_OPT |
374
                                  ASN1_BODY }, /* 31 */
375
  { 5,           "end opt",       ASN1_EOC,       ASN1_END  }, /* 32 */
376
  { 5,           "digestAlgorithm",   ASN1_EOC,       ASN1_RAW  }, /* 33 */
377
  { 3,       "end opt",         ASN1_EOC,       ASN1_END  }, /* 34 */
378
  { 2,     "signature",         ASN1_EOC,       ASN1_RAW  }, /* 35 */
379
  { 2,     "serialNumber",        ASN1_INTEGER,     ASN1_BODY }, /* 36 */
380
  { 2,     "attrCertValidityPeriod",    ASN1_SEQUENCE,      ASN1_NONE }, /* 37 */
381
  { 3,       "notBeforeTime",       ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
382
  { 3,       "notAfterTime",        ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
383
  { 2,     "attributes",          ASN1_SEQUENCE,      ASN1_LOOP }, /* 40 */
384
  { 3,       "attribute",         ASN1_SEQUENCE,      ASN1_NONE }, /* 41 */
385
  { 4,         "type",          ASN1_OID,       ASN1_BODY }, /* 42 */
386
  { 4,         "values",          ASN1_SET,         ASN1_LOOP }, /* 43 */
387
  { 5,           "value",         ASN1_EOC,         ASN1_RAW  }, /* 44 */
388
  { 4,         "end loop",        ASN1_EOC,       ASN1_END  }, /* 45 */
389
  { 2,     "end loop",          ASN1_EOC,       ASN1_END  }, /* 46 */
390
  { 2,     "extensions",          ASN1_SEQUENCE,      ASN1_LOOP }, /* 47 */
391
  { 3,       "extension",         ASN1_SEQUENCE,      ASN1_NONE }, /* 48 */
392
  { 4,         "extnID",          ASN1_OID,       ASN1_BODY }, /* 49 */
393
  { 4,         "critical",        ASN1_BOOLEAN,     ASN1_DEF |
394
                                  ASN1_BODY }, /* 50 */
395
  { 4,         "extnValue",       ASN1_OCTET_STRING,    ASN1_BODY }, /* 51 */
396
  { 2,     "end loop",          ASN1_EOC,       ASN1_END  }, /* 52 */
397
  { 1,   "signatureAlgorithm",      ASN1_EOC,       ASN1_RAW  }, /* 53 */
398
  { 1,   "signatureValue",        ASN1_BIT_STRING,    ASN1_BODY }, /* 54 */
399
  { 0, "exit",              ASN1_EOC,       ASN1_EXIT }
400
};
401
0
#define AC_OBJ_CERTIFICATE_INFO    1
402
0
#define AC_OBJ_VERSION         2
403
0
#define AC_OBJ_HOLDER_ISSUER     5
404
0
#define AC_OBJ_HOLDER_SERIAL     6
405
0
#define AC_OBJ_ENTITY_NAME      10
406
0
#define AC_OBJ_ISSUER_NAME      19
407
#define AC_OBJ_ISSUER       23
408
0
#define AC_OBJ_SIG_ALG        35
409
0
#define AC_OBJ_SERIAL_NUMBER    36
410
0
#define AC_OBJ_NOT_BEFORE     38
411
0
#define AC_OBJ_NOT_AFTER      39
412
0
#define AC_OBJ_ATTRIBUTE_TYPE   42
413
0
#define AC_OBJ_ATTRIBUTE_VALUE    44
414
0
#define AC_OBJ_EXTN_ID        49
415
0
#define AC_OBJ_CRITICAL       50
416
0
#define AC_OBJ_EXTN_VALUE     51
417
0
#define AC_OBJ_ALGORITHM      53
418
0
#define AC_OBJ_SIGNATURE      54
419
420
/**
421
 * Parses an X.509 attribute certificate
422
 */
423
static bool parse_certificate(private_x509_ac_t *this)
424
0
{
425
0
  asn1_parser_t *parser;
426
0
  chunk_t object;
427
0
  int objectID;
428
0
  int type     = OID_UNKNOWN;
429
0
  int extn_oid = OID_UNKNOWN;
430
0
  signature_params_t sig_alg = {};
431
0
  bool success = FALSE;
432
433
0
  parser = asn1_parser_create(acObjects, this->encoding);
434
435
0
  while (parser->iterate(parser, &objectID, &object))
436
0
  {
437
0
    u_int level = parser->get_level(parser)+1;
438
439
0
    switch (objectID)
440
0
    {
441
0
      case AC_OBJ_CERTIFICATE_INFO:
442
0
        this->certificateInfo = object;
443
0
        break;
444
0
      case AC_OBJ_VERSION:
445
0
        this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
446
0
        DBG2(DBG_ASN, "  v%d", this->version);
447
0
        if (this->version != 2)
448
0
        {
449
0
          DBG1(DBG_ASN, "v%d attribute certificates are not "
450
0
             "supported", this->version);
451
0
          goto end;
452
0
        }
453
0
        break;
454
0
      case AC_OBJ_HOLDER_ISSUER:
455
0
        if (!parse_directoryName(object, level, FALSE,
456
0
                     &this->holderIssuer))
457
0
        {
458
0
          goto end;
459
0
        }
460
0
        break;
461
0
      case AC_OBJ_HOLDER_SERIAL:
462
0
        this->holderSerial = identification_create_from_encoding(
463
0
                    ID_KEY_ID, chunk_skip_zero(object));
464
0
        break;
465
0
      case AC_OBJ_ENTITY_NAME:
466
0
        if (!parse_directoryName(object, level, TRUE,
467
0
                     &this->entityName))
468
0
        {
469
0
          goto end;
470
0
        }
471
0
        break;
472
0
      case AC_OBJ_ISSUER_NAME:
473
0
        if (!parse_directoryName(object, level, FALSE,
474
0
                     &this->issuerName))
475
0
        {
476
0
          goto end;
477
0
        }
478
0
        break;
479
0
      case AC_OBJ_SIG_ALG:
480
0
        if (!signature_params_parse(object, level, &sig_alg))
481
0
        {
482
0
          DBG1(DBG_ASN, "  unable to parse signature algorithm");
483
0
          goto end;
484
0
        }
485
0
        break;
486
0
      case AC_OBJ_SERIAL_NUMBER:
487
0
        this->serialNumber = chunk_clone(object);
488
0
        break;
489
0
      case AC_OBJ_NOT_BEFORE:
490
0
        this->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
491
0
        break;
492
0
      case AC_OBJ_NOT_AFTER:
493
0
        this->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
494
0
        break;
495
0
      case AC_OBJ_ATTRIBUTE_TYPE:
496
0
        type = asn1_known_oid(object);
497
0
        break;
498
0
      case AC_OBJ_ATTRIBUTE_VALUE:
499
0
      {
500
0
        switch (type)
501
0
        {
502
0
          case OID_AUTHENTICATION_INFO:
503
0
            DBG2(DBG_ASN, "  need to parse authenticationInfo");
504
0
            break;
505
0
          case OID_ACCESS_IDENTITY:
506
0
            DBG2(DBG_ASN, "  need to parse accessIdentity");
507
0
            break;
508
0
          case OID_CHARGING_IDENTITY:
509
0
            DBG2(DBG_ASN, "  need to parse chargingIdentity");
510
0
            break;
511
0
          case OID_GROUP:
512
0
            DBG2(DBG_ASN, "-- > --");
513
0
            if (!parse_groups(this, object, level))
514
0
            {
515
0
              goto end;
516
0
            }
517
0
            DBG2(DBG_ASN, "-- < --");
518
0
            break;
519
0
          case OID_ROLE:
520
0
            parse_roleSyntax(object, level);
521
0
            break;
522
0
          default:
523
0
            break;
524
0
        }
525
0
        break;
526
0
      }
527
0
      case AC_OBJ_EXTN_ID:
528
0
        extn_oid = asn1_known_oid(object);
529
0
        break;
530
0
      case AC_OBJ_CRITICAL:
531
0
        DBG2(DBG_ASN, "  %s",
532
0
           object.len && *object.ptr ? "TRUE" : "FALSE");
533
0
        break;
534
0
      case AC_OBJ_EXTN_VALUE:
535
0
      {
536
0
        switch (extn_oid)
537
0
        {
538
0
          case OID_CRL_DISTRIBUTION_POINTS:
539
0
            DBG2(DBG_ASN, "  need to parse crlDistributionPoints");
540
0
            break;
541
0
          case OID_AUTHORITY_KEY_ID:
542
0
            this->authKeyIdentifier =
543
0
                x509_parse_authorityKeyIdentifier(object,
544
0
                      level, &this->authKeySerialNumber);
545
0
            break;
546
0
          case OID_TARGET_INFORMATION:
547
0
            DBG2(DBG_ASN, "  need to parse targetInformation");
548
0
            break;
549
0
          case OID_NO_REV_AVAIL:
550
0
            this->noRevAvail = TRUE;
551
0
            break;
552
0
          default:
553
0
            break;
554
0
        }
555
0
        break;
556
0
      }
557
0
      case AC_OBJ_ALGORITHM:
558
0
        INIT(this->scheme);
559
0
        if (!signature_params_parse(object, level, this->scheme))
560
0
        {
561
0
          DBG1(DBG_ASN, "  unable to parse signature algorithm");
562
0
          goto end;
563
0
        }
564
0
        if (!signature_params_equal(this->scheme, &sig_alg))
565
0
        {
566
0
          DBG1(DBG_ASN, "  signature algorithms do not agree");
567
0
          goto end;
568
0
        }
569
0
        break;
570
0
      case AC_OBJ_SIGNATURE:
571
0
        this->signature = chunk_skip(object, 1);
572
0
        break;
573
0
      default:
574
0
        break;
575
0
    }
576
0
  }
577
0
  success = parser->success(parser);
578
579
0
end:
580
0
  parser->destroy(parser);
581
0
  signature_params_clear(&sig_alg);
582
0
  return success;
583
0
}
584
585
/**
586
 * build directoryName
587
 */
588
static chunk_t build_directoryName(asn1_t tag, chunk_t name)
589
0
{
590
0
  return asn1_wrap(tag, "m",
591
0
        asn1_simple_object(ASN1_CONTEXT_C_4, name));
592
0
}
593
594
/**
595
 * build holder
596
 */
597
static chunk_t build_holder(private_x509_ac_t *this)
598
0
{
599
0
  x509_t* x509 = (x509_t*)this->holderCert;
600
0
  identification_t *issuer, *subject;
601
602
0
  this->holderSerial = identification_create_from_encoding(
603
0
              ID_KEY_ID, x509->get_serial(x509));
604
605
0
  issuer = this->holderCert->get_issuer(this->holderCert);
606
0
  subject = this->holderCert->get_subject(this->holderCert);
607
608
0
  return asn1_wrap(ASN1_SEQUENCE, "mm",
609
0
    asn1_wrap(ASN1_CONTEXT_C_0, "mm",
610
0
      build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
611
0
      asn1_integer("c", x509->get_serial(x509))),
612
0
    build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
613
0
}
614
615
/**
616
 * build v2Form
617
 */
618
static chunk_t build_v2_form(private_x509_ac_t *this)
619
0
{
620
0
  identification_t *subject;
621
622
0
  subject = this->signerCert->get_subject(this->signerCert);
623
0
  return asn1_wrap(ASN1_CONTEXT_C_0, "m",
624
0
        build_directoryName(ASN1_SEQUENCE,
625
0
          subject->get_encoding(subject)));
626
0
}
627
628
/**
629
 * build attrCertValidityPeriod
630
 */
631
static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
632
0
{
633
0
  return asn1_wrap(ASN1_SEQUENCE, "mm",
634
0
        asn1_from_time(&this->notBefore, ASN1_GENERALIZEDTIME),
635
0
        asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
636
0
}
637
638
/**
639
 * build attribute type
640
 */
641
static chunk_t build_attribute_type(int type, chunk_t content)
642
0
{
643
0
  return asn1_wrap(ASN1_SEQUENCE, "mm",
644
0
        asn1_build_known_oid(type),
645
0
        asn1_wrap(ASN1_SET, "m", content));
646
0
}
647
648
/**
649
 * build attributes
650
 */
651
static chunk_t build_attributes(private_x509_ac_t *this)
652
0
{
653
0
  enumerator_t *enumerator;
654
0
  group_t *group;
655
0
  chunk_t values;
656
0
  size_t size = 0, len;
657
0
  u_char *pos;
658
659
  /* precalculate the total size of all values */
660
0
  enumerator = this->groups->create_enumerator(this->groups);
661
0
  while (enumerator->enumerate(enumerator, &group))
662
0
  {
663
0
    len = group->value.len;
664
0
    size += 1 + (len > 0) + (len >= 128) +
665
0
        (len >= 256) + (len >= 65536) + len;
666
0
  }
667
0
  enumerator->destroy(enumerator);
668
669
0
  pos = asn1_build_object(&values, ASN1_SEQUENCE, size);
670
671
0
  enumerator = this->groups->create_enumerator(this->groups);
672
0
  while (enumerator->enumerate(enumerator, &group))
673
0
  {
674
0
    chunk_t attr;
675
0
    asn1_t type;
676
677
0
    switch (group->type)
678
0
    {
679
0
      case AC_GROUP_TYPE_OCTETS:
680
0
        type = ASN1_OCTET_STRING;
681
0
        break;
682
0
      case AC_GROUP_TYPE_STRING:
683
0
        type = ASN1_UTF8STRING;
684
0
        break;
685
0
      case AC_GROUP_TYPE_OID:
686
0
        type = ASN1_OID;
687
0
        break;
688
0
      default:
689
0
        continue;
690
0
    }
691
0
    attr = asn1_simple_object(type, group->value);
692
693
0
    memcpy(pos, attr.ptr, attr.len);
694
0
    pos += attr.len;
695
0
    free(attr.ptr);
696
0
  }
697
0
  enumerator->destroy(enumerator);
698
699
0
  return asn1_wrap(ASN1_SEQUENCE, "m",
700
0
        build_attribute_type(OID_GROUP,
701
0
          asn1_wrap(ASN1_SEQUENCE, "m", values)));
702
0
}
703
704
/**
705
 * build authorityKeyIdentifier
706
 */
707
static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
708
0
{
709
0
  chunk_t keyIdentifier = chunk_empty;
710
0
  chunk_t authorityCertIssuer;
711
0
  chunk_t authorityCertSerialNumber;
712
0
  identification_t *issuer;
713
0
  public_key_t *public;
714
0
  x509_t *x509;
715
716
0
  x509 = (x509_t*)this->signerCert;
717
0
  issuer = this->signerCert->get_issuer(this->signerCert);
718
0
  public = this->signerCert->get_public_key(this->signerCert);
719
0
  if (public)
720
0
  {
721
0
    if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyIdentifier))
722
0
    {
723
0
      this->authKeyIdentifier = chunk_clone(keyIdentifier);
724
0
      keyIdentifier = asn1_simple_object(ASN1_CONTEXT_S_0, keyIdentifier);
725
0
    }
726
0
    public->destroy(public);
727
0
  }
728
0
  authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
729
0
                      issuer->get_encoding(issuer));
730
0
  authorityCertSerialNumber = asn1_integer("c", x509->get_serial(x509));
731
0
  authorityCertSerialNumber.ptr[0] = ASN1_CONTEXT_S_2;
732
0
  return asn1_wrap(ASN1_SEQUENCE, "mm",
733
0
        asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
734
0
        asn1_wrap(ASN1_OCTET_STRING, "m",
735
0
          asn1_wrap(ASN1_SEQUENCE, "mmm",
736
0
            keyIdentifier,
737
0
            authorityCertIssuer,
738
0
            authorityCertSerialNumber
739
0
          )
740
0
        )
741
0
       );
742
0
}
743
744
/**
745
 * build extensions
746
 */
747
static chunk_t build_extensions(private_x509_ac_t *this)
748
0
{
749
0
  return asn1_wrap(ASN1_SEQUENCE, "mc",
750
0
        build_authorityKeyIdentifier(this),
751
0
        ASN1_noRevAvail_ext);
752
0
}
753
754
/**
755
 * build attributeCertificateInfo
756
 */
757
static chunk_t build_attr_cert_info(private_x509_ac_t *this, chunk_t sig_scheme)
758
0
{
759
0
  return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
760
0
        ASN1_INTEGER_1,
761
0
        build_holder(this),
762
0
        build_v2_form(this),
763
0
        sig_scheme,
764
0
        asn1_integer("c", this->serialNumber),
765
0
        build_attr_cert_validity(this),
766
0
        build_attributes(this),
767
0
        build_extensions(this));
768
0
}
769
770
/**
771
 * build an X.509 attribute certificate
772
 */
773
static bool build_ac(private_x509_ac_t *this, hash_algorithm_t digest_alg)
774
0
{
775
0
  chunk_t signatureValue, attributeCertificateInfo, sig_scheme;
776
0
  private_key_t *key = this->signerKey;
777
778
0
  if (!this->scheme)
779
0
  {
780
0
    INIT(this->scheme,
781
0
      .scheme = signature_scheme_from_oid(
782
0
                hasher_signature_algorithm_to_oid(digest_alg,
783
0
                        key->get_type(key))),
784
0
    );
785
0
  }
786
0
  if (this->scheme->scheme == SIGN_UNKNOWN)
787
0
  {
788
0
    return FALSE;
789
0
  }
790
0
  if (!signature_params_build(this->scheme, &sig_scheme))
791
0
  {
792
0
    return FALSE;
793
0
  }
794
795
0
  attributeCertificateInfo = build_attr_cert_info(this, sig_scheme);
796
0
  if (!key->sign(key, this->scheme->scheme, this->scheme->params,
797
0
           attributeCertificateInfo, &signatureValue))
798
0
  {
799
0
    free(attributeCertificateInfo.ptr);
800
0
    free(sig_scheme.ptr);
801
0
    return FALSE;
802
0
  }
803
0
  this->encoding = asn1_wrap(ASN1_SEQUENCE, "mmm",
804
0
            attributeCertificateInfo,
805
0
            sig_scheme,
806
0
            asn1_bitstring("m", signatureValue));
807
0
  return TRUE;
808
0
}
809
810
METHOD(ac_t, get_serial, chunk_t,
811
  private_x509_ac_t *this)
812
0
{
813
0
  return chunk_skip_zero(this->serialNumber);
814
0
}
815
816
METHOD(ac_t, get_holderSerial, chunk_t,
817
  private_x509_ac_t *this)
818
0
{
819
0
  if (this->holderSerial)
820
0
  {
821
0
    return this->holderSerial->get_encoding(this->holderSerial);
822
0
  }
823
0
  return chunk_empty;
824
0
}
825
826
METHOD(ac_t, get_holderIssuer, identification_t*,
827
  private_x509_ac_t *this)
828
0
{
829
0
  return this->holderIssuer;
830
0
}
831
832
METHOD(ac_t, get_authKeyIdentifier, chunk_t,
833
  private_x509_ac_t *this)
834
0
{
835
0
  return this->authKeyIdentifier;
836
0
}
837
838
CALLBACK(attr_filter, bool,
839
  void *null, enumerator_t *orig, va_list args)
840
0
{
841
0
  group_t *group;
842
0
  ac_group_type_t *type;
843
0
  chunk_t *out;
844
845
0
  VA_ARGS_VGET(args, type, out);
846
847
0
  while (orig->enumerate(orig, &group))
848
0
  {
849
0
    if (group->type == AC_GROUP_TYPE_STRING &&
850
0
      !chunk_printable(group->value, NULL, 0))
851
0
    { /* skip non-printable strings */
852
0
      continue;
853
0
    }
854
0
    *type = group->type;
855
0
    *out = group->value;
856
0
    return TRUE;
857
0
  }
858
0
  return FALSE;
859
0
}
860
861
METHOD(ac_t, create_group_enumerator, enumerator_t*,
862
  private_x509_ac_t *this)
863
0
{
864
0
  return enumerator_create_filter(
865
0
              this->groups->create_enumerator(this->groups),
866
0
              attr_filter, NULL, NULL);
867
0
}
868
869
METHOD(certificate_t, get_type, certificate_type_t,
870
  private_x509_ac_t *this)
871
0
{
872
0
  return CERT_X509_AC;
873
0
}
874
875
METHOD(certificate_t, get_subject, identification_t*,
876
  private_x509_ac_t *this)
877
0
{
878
0
  if (this->entityName)
879
0
  {
880
0
    return this->entityName;
881
0
  }
882
0
  return this->holderSerial;
883
0
}
884
885
METHOD(certificate_t, get_issuer, identification_t*,
886
  private_x509_ac_t *this)
887
0
{
888
0
  return this->issuerName;
889
0
}
890
891
METHOD(certificate_t, has_subject, id_match_t,
892
  private_x509_ac_t *this, identification_t *subject)
893
0
{
894
0
  id_match_t entity = ID_MATCH_NONE, serial = ID_MATCH_NONE;
895
896
0
  if (this->entityName)
897
0
  {
898
0
    entity = this->entityName->matches(this->entityName, subject);
899
0
  }
900
0
  if (this->holderSerial)
901
0
  {
902
0
    serial = this->holderSerial->matches(this->holderSerial, subject);
903
0
  }
904
0
  return max(entity, serial);
905
0
}
906
907
METHOD(certificate_t, has_issuer, id_match_t,
908
  private_x509_ac_t *this, identification_t *issuer)
909
0
{
910
0
  if (issuer->get_type(issuer) == ID_KEY_ID &&
911
0
    this->authKeyIdentifier.ptr &&
912
0
    chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
913
0
  {
914
0
    return ID_MATCH_PERFECT;
915
0
  }
916
0
  return this->issuerName->matches(this->issuerName, issuer);
917
0
}
918
919
METHOD(certificate_t, issued_by, bool,
920
  private_x509_ac_t *this, certificate_t *issuer,
921
  signature_params_t **scheme)
922
0
{
923
0
  public_key_t *key;
924
0
  bool valid;
925
0
  x509_t *x509 = (x509_t*)issuer;
926
927
  /* check if issuer is an X.509 AA certificate */
928
0
  if (issuer->get_type(issuer) != CERT_X509)
929
0
  {
930
0
    return FALSE;
931
0
  }
932
0
  if (!(x509->get_flags(x509) & X509_AA))
933
0
  {
934
0
    return FALSE;
935
0
  }
936
937
  /* get the public key of the issuer */
938
0
  key = issuer->get_public_key(issuer);
939
940
  /* compare keyIdentifiers if available, otherwise use DNs */
941
0
  if (this->authKeyIdentifier.ptr && key)
942
0
  {
943
0
    chunk_t fingerprint;
944
945
0
    if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
946
0
      !chunk_equals(fingerprint, this->authKeyIdentifier))
947
0
    {
948
0
      return FALSE;
949
0
    }
950
0
  }
951
0
  else
952
0
  {
953
0
    if (!this->issuerName->equals(this->issuerName,
954
0
                    issuer->get_subject(issuer)))
955
0
    {
956
0
      return FALSE;
957
0
    }
958
0
  }
959
960
0
  if (!key)
961
0
  {
962
0
    return FALSE;
963
0
  }
964
0
  valid = key->verify(key, this->scheme->scheme, this->scheme->params,
965
0
            this->certificateInfo, this->signature);
966
0
  key->destroy(key);
967
0
  if (valid && scheme)
968
0
  {
969
0
    *scheme = signature_params_clone(this->scheme);
970
0
  }
971
0
  return valid;
972
0
}
973
974
METHOD(certificate_t, get_public_key, public_key_t*,
975
  private_x509_ac_t *this)
976
0
{
977
0
  return NULL;
978
0
}
979
980
METHOD(certificate_t, get_ref, certificate_t*,
981
  private_x509_ac_t *this)
982
0
{
983
0
  ref_get(&this->ref);
984
0
  return &this->public.interface.certificate;
985
0
}
986
987
METHOD(certificate_t, get_validity, bool,
988
  private_x509_ac_t *this, time_t *when, time_t *not_before, time_t *not_after)
989
0
{
990
0
  time_t t = when ? *when : time(NULL);
991
992
0
  if (not_before)
993
0
  {
994
0
    *not_before = this->notBefore;
995
0
  }
996
0
  if (not_after)
997
0
  {
998
0
    *not_after = this->notAfter;
999
0
  }
1000
0
  return (t >= this->notBefore && t <= this->notAfter);
1001
0
}
1002
1003
METHOD(certificate_t, get_encoding, bool,
1004
  private_x509_ac_t *this, cred_encoding_type_t type, chunk_t *encoding)
1005
0
{
1006
0
  if (type == CERT_ASN1_DER)
1007
0
  {
1008
0
    *encoding = chunk_clone(this->encoding);
1009
0
    return TRUE;
1010
0
  }
1011
0
  return lib->encoding->encode(lib->encoding, type, NULL, encoding,
1012
0
          CRED_PART_X509_AC_ASN1_DER, this->encoding, CRED_PART_END);
1013
0
}
1014
1015
METHOD(certificate_t, equals, bool,
1016
  private_x509_ac_t *this, certificate_t *other)
1017
0
{
1018
0
  chunk_t encoding;
1019
0
  bool equal;
1020
1021
0
  if ((certificate_t*)this == other)
1022
0
  {
1023
0
    return TRUE;
1024
0
  }
1025
0
  if (other->equals == _equals)
1026
0
  { /* skip allocation if we have the same implementation */
1027
0
    return chunk_equals(this->encoding,
1028
0
              ((private_x509_ac_t*)other)->encoding);
1029
0
  }
1030
0
  if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
1031
0
  {
1032
0
    return FALSE;
1033
0
  }
1034
0
  equal = chunk_equals(this->encoding, encoding);
1035
0
  free(encoding.ptr);
1036
0
  return equal;
1037
0
}
1038
1039
METHOD(certificate_t, destroy, void,
1040
  private_x509_ac_t *this)
1041
0
{
1042
0
  if (ref_put(&this->ref))
1043
0
  {
1044
0
    DESTROY_IF(this->holderIssuer);
1045
0
    DESTROY_IF(this->holderSerial);
1046
0
    DESTROY_IF(this->entityName);
1047
0
    DESTROY_IF(this->issuerName);
1048
0
    DESTROY_IF(this->holderCert);
1049
0
    DESTROY_IF(this->signerCert);
1050
0
    DESTROY_IF(this->signerKey);
1051
0
    this->groups->destroy_function(this->groups, (void*)group_destroy);
1052
0
    signature_params_destroy(this->scheme);
1053
0
    free(this->serialNumber.ptr);
1054
0
    free(this->authKeyIdentifier.ptr);
1055
0
    free(this->encoding.ptr);
1056
0
    free(this);
1057
0
  }
1058
0
}
1059
1060
/**
1061
 * create an empty but initialized X.509 attribute certificate
1062
 */
1063
static private_x509_ac_t *create_empty(void)
1064
0
{
1065
0
  private_x509_ac_t *this;
1066
1067
0
  INIT(this,
1068
0
    .public = {
1069
0
      .interface = {
1070
0
        .certificate = {
1071
0
          .get_type = _get_type,
1072
0
          .get_subject = _get_subject,
1073
0
          .get_issuer = _get_issuer,
1074
0
          .has_subject = _has_subject,
1075
0
          .has_issuer = _has_issuer,
1076
0
          .issued_by = _issued_by,
1077
0
          .get_public_key = _get_public_key,
1078
0
          .get_validity = _get_validity,
1079
0
          .get_encoding = _get_encoding,
1080
0
          .equals = _equals,
1081
0
          .get_ref = _get_ref,
1082
0
          .destroy = _destroy,
1083
0
        },
1084
0
        .get_serial = _get_serial,
1085
0
        .get_holderSerial = _get_holderSerial,
1086
0
        .get_holderIssuer = _get_holderIssuer,
1087
0
        .get_authKeyIdentifier = _get_authKeyIdentifier,
1088
0
        .create_group_enumerator = _create_group_enumerator,
1089
0
      },
1090
0
    },
1091
0
    .groups = linked_list_create(),
1092
0
    .ref = 1,
1093
0
  );
1094
1095
0
  return this;
1096
0
}
1097
1098
/**
1099
 * See header.
1100
 */
1101
x509_ac_t *x509_ac_load(certificate_type_t type, va_list args)
1102
0
{
1103
0
  chunk_t blob = chunk_empty;
1104
1105
0
  while (TRUE)
1106
0
  {
1107
0
    switch (va_arg(args, builder_part_t))
1108
0
    {
1109
0
      case BUILD_BLOB_ASN1_DER:
1110
0
        blob = va_arg(args, chunk_t);
1111
0
        continue;
1112
0
      case BUILD_END:
1113
0
        break;
1114
0
      default:
1115
0
        return NULL;
1116
0
    }
1117
0
    break;
1118
0
  }
1119
0
  if (blob.ptr)
1120
0
  {
1121
0
    private_x509_ac_t *ac = create_empty();
1122
1123
0
    ac->encoding = chunk_clone(blob);
1124
0
    if (parse_certificate(ac))
1125
0
    {
1126
0
      return &ac->public;
1127
0
    }
1128
0
    destroy(ac);
1129
0
  }
1130
0
  return NULL;
1131
0
}
1132
1133
/**
1134
 * Add groups from a list into AC group memberships
1135
 */
1136
static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list)
1137
0
{
1138
0
  enumerator_t *enumerator;
1139
0
  group_t *group;
1140
0
  char *name;
1141
1142
0
  enumerator = list->create_enumerator(list);
1143
0
  while (enumerator->enumerate(enumerator, &name))
1144
0
  {
1145
0
    INIT(group,
1146
0
      .type = AC_GROUP_TYPE_STRING,
1147
0
      .value = chunk_clone(chunk_from_str(name)),
1148
0
    );
1149
0
    this->groups->insert_last(this->groups, group);
1150
0
  }
1151
0
  enumerator->destroy(enumerator);
1152
0
}
1153
1154
/**
1155
 * See header.
1156
 */
1157
x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
1158
0
{
1159
0
  hash_algorithm_t digest_alg = HASH_SHA256;
1160
0
  private_x509_ac_t *ac;
1161
1162
0
  ac = create_empty();
1163
0
  while (TRUE)
1164
0
  {
1165
0
    switch (va_arg(args, builder_part_t))
1166
0
    {
1167
0
      case BUILD_NOT_BEFORE_TIME:
1168
0
        ac->notBefore = va_arg(args, time_t);
1169
0
        continue;
1170
0
      case BUILD_NOT_AFTER_TIME:
1171
0
        ac->notAfter = va_arg(args, time_t);
1172
0
        continue;
1173
0
      case BUILD_SERIAL:
1174
0
        ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
1175
0
        continue;
1176
0
      case BUILD_AC_GROUP_STRINGS:
1177
0
        add_groups_from_list(ac, va_arg(args, linked_list_t*));
1178
0
        continue;
1179
0
      case BUILD_CERT:
1180
0
        ac->holderCert = va_arg(args, certificate_t*);
1181
0
        ac->holderCert->get_ref(ac->holderCert);
1182
0
        continue;
1183
0
      case BUILD_SIGNING_CERT:
1184
0
        ac->signerCert = va_arg(args, certificate_t*);
1185
0
        ac->signerCert->get_ref(ac->signerCert);
1186
0
        continue;
1187
0
      case BUILD_SIGNING_KEY:
1188
0
        ac->signerKey = va_arg(args, private_key_t*);
1189
0
        ac->signerKey->get_ref(ac->signerKey);
1190
0
        continue;
1191
0
      case BUILD_SIGNATURE_SCHEME:
1192
0
        ac->scheme = va_arg(args, signature_params_t*);
1193
0
        ac->scheme = signature_params_clone(ac->scheme);
1194
0
        continue;
1195
0
      case BUILD_DIGEST_ALG:
1196
0
        digest_alg = va_arg(args, int);
1197
0
        continue;
1198
0
      case BUILD_END:
1199
0
        break;
1200
0
      default:
1201
0
        destroy(ac);
1202
0
        return NULL;
1203
0
    }
1204
0
    break;
1205
0
  }
1206
1207
0
  if (ac->signerKey && ac->holderCert && ac->signerCert &&
1208
0
    ac->holderCert->get_type(ac->holderCert) == CERT_X509 &&
1209
0
    ac->signerCert->get_type(ac->signerCert) == CERT_X509)
1210
0
  {
1211
0
    if (build_ac(ac, digest_alg))
1212
0
    {
1213
0
      return &ac->public;
1214
0
    }
1215
0
  }
1216
0
  destroy(ac);
1217
  return NULL;
1218
0
}