]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/x509/x509_ac.c
Support different encoding types in certificate.get_encoding()
[thirdparty/strongswan.git] / src / libstrongswan / plugins / x509 / x509_ac.c
CommitLineData
bdec2e4f
AS
1/*
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2003 Martin Berner, Lukas Suter
fc12e3cd 4 * Copyright (C) 2002-2009 Andreas Steffen
d73f453c 5 * Copyright (C) 2009 Martin Willi
bdec2e4f 6 *
fc12e3cd 7 * HSR Hochschule fuer Technik Rapperswil
bdec2e4f
AS
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
bdec2e4f
AS
18 */
19
20#include "x509_ac.h"
bdec2e4f 21
e13389a7
MW
22#include <time.h>
23
bdec2e4f
AS
24#include <library.h>
25#include <debug.h>
26#include <asn1/oid.h>
27#include <asn1/asn1.h>
d3d7e46b 28#include <asn1/asn1_parser.h>
bdec2e4f
AS
29#include <utils/identification.h>
30#include <utils/linked_list.h>
31#include <credentials/certificates/x509.h>
fc12e3cd 32#include <credentials/ietf_attributes/ietf_attributes.h>
e24aaddd 33#include <credentials/keys/private_key.h>
bdec2e4f 34
6b6ece63
MW
35extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
36 int level0, chunk_t *authKeySerialNumber);
26930a8c 37
bdec2e4f
AS
38typedef struct private_x509_ac_t private_x509_ac_t;
39
40/**
41 * private data of x509_ac_t object
42 */
43struct private_x509_ac_t {
7daf5226 44
bdec2e4f
AS
45 /**
46 * public functions
47 */
48 x509_ac_t public;
7daf5226 49
bdec2e4f 50 /**
26930a8c 51 * X.509 attribute certificate encoding in ASN.1 DER format
bdec2e4f
AS
52 */
53 chunk_t encoding;
7daf5226 54
bdec2e4f
AS
55 /**
56 * X.509 attribute certificate body over which signature is computed
57 */
58 chunk_t certificateInfo;
7daf5226 59
bdec2e4f
AS
60 /**
61 * Version of the X.509 attribute certificate
62 */
63 u_int version;
7daf5226 64
bdec2e4f
AS
65 /**
66 * Serial number of the X.509 attribute certificate
67 */
68 chunk_t serialNumber;
7daf5226 69
bdec2e4f
AS
70 /**
71 * ID representing the issuer of the holder certificate
72 */
73 identification_t *holderIssuer;
7daf5226 74
bdec2e4f
AS
75 /**
76 * Serial number of the holder certificate
77 */
78 chunk_t holderSerial;
7daf5226 79
bdec2e4f
AS
80 /**
81 * ID representing the holder
82 */
83 identification_t *entityName;
7daf5226 84
bdec2e4f
AS
85 /**
86 * ID representing the attribute certificate issuer
87 */
88 identification_t *issuerName;
7daf5226 89
bdec2e4f
AS
90 /**
91 * Start time of certificate validity
92 */
93 time_t notBefore;
7daf5226 94
bdec2e4f
AS
95 /**
96 * End time of certificate validity
97 */
98 time_t notAfter;
7daf5226 99
bdec2e4f
AS
100 /**
101 * List of charging attributes
102 */
fc12e3cd 103 ietf_attributes_t *charging;
7daf5226 104
bdec2e4f
AS
105 /**
106 * List of groub attributes
107 */
fc12e3cd 108 ietf_attributes_t *groups;
7daf5226 109
bdec2e4f
AS
110 /**
111 * Authority Key Identifier
112 */
6b6ece63 113 chunk_t authKeyIdentifier;
7daf5226 114
bdec2e4f
AS
115 /**
116 * Authority Key Serial Number
117 */
118 chunk_t authKeySerialNumber;
7daf5226 119
bdec2e4f
AS
120 /**
121 * No revocation information available
122 */
123 bool noRevAvail;
7daf5226 124
26930a8c
AS
125 /**
126 * Signature algorithm
127 */
128 int algorithm;
7daf5226 129
bdec2e4f
AS
130 /**
131 * Signature
132 */
133 chunk_t signature;
7daf5226 134
6b6ece63
MW
135 /**
136 * Holder certificate
137 */
6ac3a7ac 138 certificate_t *holderCert;
7daf5226 139
6b6ece63
MW
140 /**
141 * Signer certificate
142 */
6ac3a7ac 143 certificate_t *signerCert;
7daf5226 144
6b6ece63
MW
145 /**
146 * Signer private key;
147 */
6ac3a7ac 148 private_key_t *signerKey;
7daf5226 149
bdec2e4f
AS
150 /**
151 * reference count
152 */
153 refcount_t ref;
154};
155
3b878dae 156static chunk_t ASN1_noRevAvail_ext = chunk_from_chars(
bdec2e4f
AS
157 0x30, 0x09,
158 0x06, 0x03,
159 0x55, 0x1d, 0x38,
160 0x04, 0x02,
161 0x05, 0x00
3b878dae 162);
bdec2e4f 163
d3d7e46b
AS
164/**
165 * declaration of function implemented in x509_cert.c
166 */
167extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
168 linked_list_t *list);
169/**
170 * parses a directoryName
171 */
172static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name)
173{
174 bool has_directoryName;
175 linked_list_t *list = linked_list_create();
176
177 x509_parse_generalNames(blob, level, implicit, list);
178 has_directoryName = list->get_count(list) > 0;
179
180 if (has_directoryName)
181 {
182 iterator_t *iterator = list->create_iterator(list, TRUE);
183 identification_t *directoryName;
184 bool first = TRUE;
185
186 while (iterator->iterate(iterator, (void**)&directoryName))
187 {
188 if (first)
189 {
190 *name = directoryName;
191 first = FALSE;
192 }
193 else
194 {
8b0e0910 195 DBG1(DBG_LIB, "more than one directory name - first selected");
d3d7e46b
AS
196 directoryName->destroy(directoryName);
197 }
198 }
199 iterator->destroy(iterator);
200 }
201 else
202 {
8b0e0910 203 DBG1(DBG_LIB, "no directoryName found");
d3d7e46b
AS
204 }
205
206 list->destroy(list);
207 return has_directoryName;
208}
209
bdec2e4f
AS
210/**
211 * ASN.1 definition of roleSyntax
212 */
213static const asn1Object_t roleSyntaxObjects[] =
214{
460025e2
AS
215 { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
216 { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
217 ASN1_OBJ }, /* 1 */
218 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
219 { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */
220 { 0, "exit", ASN1_EOC, ASN1_EXIT }
bdec2e4f 221};
bdec2e4f 222
d3d7e46b
AS
223/**
224 * Parses roleSyntax
225 */
226static void parse_roleSyntax(chunk_t blob, int level0)
227{
228 asn1_parser_t *parser;
229 chunk_t object;
230 int objectID;
231
460025e2 232 parser = asn1_parser_create(roleSyntaxObjects, blob);
d3d7e46b
AS
233 parser->set_top_level(parser, level0);
234
235 while (parser->iterate(parser, &objectID, &object))
236 {
237 switch (objectID)
238 {
239 default:
240 break;
241 }
242 }
243 parser->destroy(parser);
244}
245
bdec2e4f
AS
246/**
247 * ASN.1 definition of an X509 attribute certificate
248 */
249static const asn1Object_t acObjects[] =
250{
251 { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
252 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
253 { 2, "version", ASN1_INTEGER, ASN1_DEF |
254 ASN1_BODY }, /* 2 */
255 { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
256 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
257 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
258 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
259 { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
260 ASN1_BODY }, /* 7 */
261 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
262 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
0672aa7b 263 { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
bdec2e4f
AS
264 ASN1_OBJ }, /* 10 */
265 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
266 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
0672aa7b 267 { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
bdec2e4f
AS
268 { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
269 ASN1_BODY }, /* 14 */
0672aa7b 270 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
bdec2e4f
AS
271 { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
272 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
273 { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
274 { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
275 ASN1_OBJ }, /* 19 */
276 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
277 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
278 { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
279 { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
b9b8a98f 280 { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
bdec2e4f
AS
281 { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
282 ASN1_BODY }, /* 25 */
283 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
284 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
285 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
286 { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
287 { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
b9b8a98f 288 { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
bdec2e4f
AS
289 ASN1_BODY }, /* 31 */
290 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
291 { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
292 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
293 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
294 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
295 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
296 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
297 { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
298 { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
299 { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
300 { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
301 { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
302 { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
303 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
304 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
305 { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
306 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
307 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
308 { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
309 ASN1_BODY }, /* 50 */
310 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
311 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
312 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
460025e2
AS
313 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */
314 { 0, "exit", ASN1_EOC, ASN1_EXIT }
bdec2e4f 315};
bdec2e4f
AS
316#define AC_OBJ_CERTIFICATE_INFO 1
317#define AC_OBJ_VERSION 2
318#define AC_OBJ_HOLDER_ISSUER 5
319#define AC_OBJ_HOLDER_SERIAL 6
320#define AC_OBJ_ENTITY_NAME 10
321#define AC_OBJ_ISSUER_NAME 19
322#define AC_OBJ_ISSUER 23
323#define AC_OBJ_SIG_ALG 35
324#define AC_OBJ_SERIAL_NUMBER 36
325#define AC_OBJ_NOT_BEFORE 38
326#define AC_OBJ_NOT_AFTER 39
327#define AC_OBJ_ATTRIBUTE_TYPE 42
328#define AC_OBJ_ATTRIBUTE_VALUE 44
329#define AC_OBJ_EXTN_ID 49
330#define AC_OBJ_CRITICAL 50
331#define AC_OBJ_EXTN_VALUE 51
332#define AC_OBJ_ALGORITHM 53
333#define AC_OBJ_SIGNATURE 54
bdec2e4f 334
26930a8c
AS
335/**
336 * Parses an X.509 attribute certificate
337 */
338static bool parse_certificate(private_x509_ac_t *this)
339{
d3d7e46b 340 asn1_parser_t *parser;
26930a8c 341 chunk_t object;
d3d7e46b
AS
342 int objectID;
343 int type = OID_UNKNOWN;
26930a8c 344 int extn_oid = OID_UNKNOWN;
d3d7e46b 345 int sig_alg = OID_UNKNOWN;
c3628ebc 346 bool success = FALSE;
d3d7e46b 347 bool critical;
26930a8c 348
460025e2 349 parser = asn1_parser_create(acObjects, this->encoding);
26930a8c 350
d3d7e46b
AS
351 while (parser->iterate(parser, &objectID, &object))
352 {
353 u_int level = parser->get_level(parser)+1;
26930a8c
AS
354
355 switch (objectID)
356 {
357 case AC_OBJ_CERTIFICATE_INFO:
358 this->certificateInfo = object;
359 break;
360 case AC_OBJ_VERSION:
361 this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
8b0e0910 362 DBG2(DBG_LIB, " v%d", this->version);
26930a8c
AS
363 if (this->version != 2)
364 {
8b0e0910
TB
365 DBG1(DBG_LIB, "v%d attribute certificates are not "
366 "supported", this->version);
d3d7e46b 367 goto end;
26930a8c
AS
368 }
369 break;
370 case AC_OBJ_HOLDER_ISSUER:
371 if (!parse_directoryName(object, level, FALSE, &this->holderIssuer))
372 {
d3d7e46b 373 goto end;
26930a8c
AS
374 }
375 break;
376 case AC_OBJ_HOLDER_SERIAL:
377 this->holderSerial = object;
378 break;
379 case AC_OBJ_ENTITY_NAME:
380 if (!parse_directoryName(object, level, TRUE, &this->entityName))
381 {
d3d7e46b 382 goto end;
26930a8c
AS
383 }
384 break;
385 case AC_OBJ_ISSUER_NAME:
386 if (!parse_directoryName(object, level, FALSE, &this->issuerName))
387 {
d3d7e46b 388 goto end;
26930a8c
AS
389 }
390 break;
391 case AC_OBJ_SIG_ALG:
d3d7e46b 392 sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
26930a8c
AS
393 break;
394 case AC_OBJ_SERIAL_NUMBER:
9c674e72 395 this->serialNumber = chunk_clone(object);
26930a8c
AS
396 break;
397 case AC_OBJ_NOT_BEFORE:
d3d7e46b 398 this->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
26930a8c
AS
399 break;
400 case AC_OBJ_NOT_AFTER:
d3d7e46b 401 this->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
26930a8c
AS
402 break;
403 case AC_OBJ_ATTRIBUTE_TYPE:
d3d7e46b 404 type = asn1_known_oid(object);
26930a8c
AS
405 break;
406 case AC_OBJ_ATTRIBUTE_VALUE:
d3d7e46b
AS
407 {
408 switch (type)
26930a8c 409 {
d3d7e46b 410 case OID_AUTHENTICATION_INFO:
8b0e0910 411 DBG2(DBG_LIB, " need to parse authenticationInfo");
d3d7e46b
AS
412 break;
413 case OID_ACCESS_IDENTITY:
8b0e0910 414 DBG2(DBG_LIB, " need to parse accessIdentity");
d3d7e46b
AS
415 break;
416 case OID_CHARGING_IDENTITY:
8b0e0910 417 DBG2(DBG_LIB, "-- > --");
fc12e3cd 418 this->charging = ietf_attributes_create_from_encoding(object);
8b0e0910 419 DBG2(DBG_LIB, "-- < --");
d3d7e46b
AS
420 break;
421 case OID_GROUP:
8b0e0910 422 DBG2(DBG_LIB, "-- > --");
fc12e3cd 423 this->groups = ietf_attributes_create_from_encoding(object);
8b0e0910 424 DBG2(DBG_LIB, "-- < --");
d3d7e46b
AS
425 break;
426 case OID_ROLE:
427 parse_roleSyntax(object, level);
428 break;
429 default:
430 break;
26930a8c
AS
431 }
432 break;
d3d7e46b 433 }
26930a8c 434 case AC_OBJ_EXTN_ID:
d3d7e46b 435 extn_oid = asn1_known_oid(object);
26930a8c
AS
436 break;
437 case AC_OBJ_CRITICAL:
438 critical = object.len && *object.ptr;
8b0e0910 439 DBG2(DBG_LIB, " %s",(critical)?"TRUE":"FALSE");
26930a8c
AS
440 break;
441 case AC_OBJ_EXTN_VALUE:
d3d7e46b
AS
442 {
443 switch (extn_oid)
26930a8c 444 {
d3d7e46b 445 case OID_CRL_DISTRIBUTION_POINTS:
8b0e0910 446 DBG2(DBG_LIB, " need to parse crlDistributionPoints");
d3d7e46b
AS
447 break;
448 case OID_AUTHORITY_KEY_ID:
449 this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
6b6ece63 450 level, &this->authKeySerialNumber);
d3d7e46b
AS
451 break;
452 case OID_TARGET_INFORMATION:
8b0e0910 453 DBG2(DBG_LIB, " need to parse targetInformation");
d3d7e46b
AS
454 break;
455 case OID_NO_REV_AVAIL:
456 this->noRevAvail = TRUE;
457 break;
458 default:
26930a8c 459 break;
26930a8c
AS
460 }
461 break;
d3d7e46b 462 }
26930a8c 463 case AC_OBJ_ALGORITHM:
d3d7e46b
AS
464 this->algorithm = asn1_parse_algorithmIdentifier(object, level,
465 NULL);
5298777a
AS
466 if (this->algorithm != sig_alg)
467 {
8b0e0910 468 DBG1(DBG_LIB, " signature algorithms do not agree");
d3d7e46b
AS
469 success = FALSE;
470 goto end;
5298777a 471 }
26930a8c
AS
472 break;
473 case AC_OBJ_SIGNATURE:
474 this->signature = object;
475 break;
476 default:
477 break;
478 }
26930a8c 479 }
c3628ebc 480 success = parser->success(parser);
d3d7e46b
AS
481
482end:
d3d7e46b
AS
483 parser->destroy(parser);
484 return success;
26930a8c
AS
485}
486
bdec2e4f
AS
487/**
488 * build directoryName
489 */
490static chunk_t build_directoryName(asn1_t tag, chunk_t name)
491{
492 return asn1_wrap(tag, "m",
493 asn1_simple_object(ASN1_CONTEXT_C_4, name));
494}
495
496/**
497 * build holder
498 */
499static chunk_t build_holder(private_x509_ac_t *this)
500{
6ac3a7ac
AS
501 x509_t* x509 = (x509_t*)this->holderCert;
502 identification_t *issuer = this->holderCert->get_issuer(this->holderCert);
503 identification_t *subject = this->holderCert->get_subject(this->holderCert);
bdec2e4f
AS
504
505 return asn1_wrap(ASN1_SEQUENCE, "mm",
506 asn1_wrap(ASN1_CONTEXT_C_0, "mm",
507 build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
508 asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))
509 ),
510 build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
511}
512
513/**
514 * build v2Form
515 */
516static chunk_t build_v2_form(private_x509_ac_t *this)
517{
6ac3a7ac 518 identification_t *subject = this->signerCert->get_subject(this->signerCert);
bdec2e4f
AS
519
520 return asn1_wrap(ASN1_CONTEXT_C_0, "m",
521 build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject)));
522}
523
524/**
525 * build attrCertValidityPeriod
526 */
527static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
528{
529 return asn1_wrap(ASN1_SEQUENCE, "mm",
d3d7e46b
AS
530 asn1_from_time(&this->notBefore, ASN1_GENERALIZEDTIME),
531 asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
bdec2e4f
AS
532}
533
534
535/**
536 * build attribute type
537 */
70e81857 538static chunk_t build_attribute_type(int type, chunk_t content)
bdec2e4f 539{
70e81857
AS
540 return asn1_wrap(ASN1_SEQUENCE, "mm",
541 asn1_build_known_oid(type),
bdec2e4f
AS
542 asn1_wrap(ASN1_SET, "m", content));
543}
544
545/**
546 * build attributes
547 */
548static chunk_t build_attributes(private_x509_ac_t *this)
549{
550 return asn1_wrap(ASN1_SEQUENCE, "m",
fc12e3cd 551 build_attribute_type(OID_GROUP, this->groups->get_encoding(this->groups)));
bdec2e4f
AS
552}
553
554/**
555 * build authorityKeyIdentifier
556 */
557static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
558{
6b6ece63 559 chunk_t keyIdentifier = chunk_empty;
bdec2e4f
AS
560 chunk_t authorityCertIssuer;
561 chunk_t authorityCertSerialNumber;
6b6ece63
MW
562 identification_t *issuer;
563 public_key_t *public;
564 x509_t *x509;
7daf5226 565
6b6ece63
MW
566 x509 = (x509_t*)this->signerCert;
567 issuer = this->signerCert->get_issuer(this->signerCert);
568 public = this->signerCert->get_public_key(this->signerCert);
bdec2e4f
AS
569 if (public)
570 {
da9724e6 571 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyIdentifier))
6b6ece63
MW
572 {
573 this->authKeyIdentifier = chunk_clone(keyIdentifier);
574 }
bdec2e4f 575 public->destroy(public);
bdec2e4f 576 }
bdec2e4f 577 authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
6b6ece63 578 issuer->get_encoding(issuer));
bdec2e4f 579 authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
6b6ece63 580 x509->get_serial(x509));
70e81857
AS
581 return asn1_wrap(ASN1_SEQUENCE, "mm",
582 asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
bdec2e4f 583 asn1_wrap(ASN1_OCTET_STRING, "m",
93da2684 584 asn1_wrap(ASN1_SEQUENCE, "cmm",
bdec2e4f
AS
585 keyIdentifier,
586 authorityCertIssuer,
587 authorityCertSerialNumber
588 )
589 )
590 );
591}
592
593/**
594 * build extensions
595 */
596static chunk_t build_extensions(private_x509_ac_t *this)
597{
598 return asn1_wrap(ASN1_SEQUENCE, "mc",
104c96a6 599 build_authorityKeyIdentifier(this),
bdec2e4f
AS
600 ASN1_noRevAvail_ext);
601}
602
603/**
604 * build attributeCertificateInfo
605 */
606static chunk_t build_attr_cert_info(private_x509_ac_t *this)
607{
eb73685d 608 return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmm",
bdec2e4f
AS
609 ASN1_INTEGER_1,
610 build_holder(this),
611 build_v2_form(this),
612 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
613 asn1_simple_object(ASN1_INTEGER, this->serialNumber),
614 build_attr_cert_validity(this),
615 build_attributes(this),
616 build_extensions(this));
617}
618
619
620/**
621 * build an X.509 attribute certificate
622 */
623static chunk_t build_ac(private_x509_ac_t *this)
624{
625 chunk_t signatureValue;
323f9f99 626 chunk_t attributeCertificateInfo;
104c96a6 627
104c96a6
AS
628 attributeCertificateInfo = build_attr_cert_info(this);
629
630 this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
631 attributeCertificateInfo, &signatureValue);
632
eb73685d 633 return asn1_wrap(ASN1_SEQUENCE, "mmm",
bdec2e4f
AS
634 attributeCertificateInfo,
635 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
636 asn1_bitstring("m", signatureValue));
637}
638
0672aa7b
AS
639/**
640 * Implementation of ac_t.get_serial.
641 */
642static chunk_t get_serial(private_x509_ac_t *this)
643{
644 return this->serialNumber;
645}
646
647/**
648 * Implementation of ac_t.get_holderSerial.
649 */
650static chunk_t get_holderSerial(private_x509_ac_t *this)
651{
652 return this->holderSerial;
653}
654
655/**
656 * Implementation of ac_t.get_holderIssuer.
657 */
658static identification_t* get_holderIssuer(private_x509_ac_t *this)
659{
660 return this->holderIssuer;
661}
662
663/**
664 * Implementation of ac_t.get_authKeyIdentifier.
665 */
6b6ece63 666static chunk_t get_authKeyIdentifier(private_x509_ac_t *this)
0672aa7b
AS
667{
668 return this->authKeyIdentifier;
669}
670
fc12e3cd
AS
671/**
672 * Implementation of certificate_t.get_groups.
673 */
674static ietf_attributes_t* get_groups(private_x509_ac_t *this)
675{
676 return this->groups ? this->groups->get_ref(this->groups) : NULL;
677}
678
bdec2e4f
AS
679/**
680 * Implementation of certificate_t.get_type
681 */
682static certificate_type_t get_type(private_x509_ac_t *this)
683{
684 return CERT_X509_AC;
685}
686
687/**
688 * Implementation of certificate_t.get_subject
689 */
690static identification_t* get_subject(private_x509_ac_t *this)
691{
692 return this->entityName;
693}
694
695/**
696 * Implementation of certificate_t.get_issuer
697 */
698static identification_t* get_issuer(private_x509_ac_t *this)
699{
700 return this->issuerName;
701}
702
703/**
704 * Implementation of certificate_t.has_subject.
705 */
706static id_match_t has_subject(private_x509_ac_t *this, identification_t *subject)
707{
6b6ece63 708 return ID_MATCH_NONE;
bdec2e4f
AS
709}
710
711/**
712 * Implementation of certificate_t.has_issuer.
713 */
714static id_match_t has_issuer(private_x509_ac_t *this, identification_t *issuer)
715{
6b6ece63
MW
716 if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
717 chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
bdec2e4f 718 {
6b6ece63 719 return ID_MATCH_PERFECT;
bdec2e4f 720 }
6b6ece63 721 return this->issuerName->matches(this->issuerName, issuer);
bdec2e4f
AS
722}
723
724/**
725 * Implementation of certificate_t.issued_by
726 */
7b88a983 727static bool issued_by(private_x509_ac_t *this, certificate_t *issuer)
bdec2e4f
AS
728{
729 public_key_t *key;
730 signature_scheme_t scheme;
731 bool valid;
732 x509_t *x509 = (x509_t*)issuer;
7daf5226 733
bdec2e4f
AS
734 /* check if issuer is an X.509 AA certificate */
735 if (issuer->get_type(issuer) != CERT_X509)
736 {
737 return FALSE;
738 }
739 if (!(x509->get_flags(x509) & X509_AA))
740 {
741 return FALSE;
742 }
7daf5226 743
bdec2e4f
AS
744 /* get the public key of the issuer */
745 key = issuer->get_public_key(issuer);
7daf5226 746
bdec2e4f 747 /* compare keyIdentifiers if available, otherwise use DNs */
6b6ece63 748 if (this->authKeyIdentifier.ptr && key)
bdec2e4f 749 {
6b6ece63 750 chunk_t fingerprint;
7daf5226 751
da9724e6 752 if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
6b6ece63 753 !chunk_equals(fingerprint, this->authKeyIdentifier))
bdec2e4f
AS
754 {
755 return FALSE;
756 }
757 }
7daf5226 758 else
bdec2e4f 759 {
6b6ece63
MW
760 if (!this->issuerName->equals(this->issuerName,
761 issuer->get_subject(issuer)))
bdec2e4f
AS
762 {
763 return FALSE;
764 }
765 }
7daf5226 766
f3e87f59
AS
767 /* determine signature scheme */
768 scheme = signature_scheme_from_oid(this->algorithm);
7daf5226 769
f3e87f59 770 if (scheme == SIGN_UNKNOWN || key == NULL)
bdec2e4f
AS
771 {
772 return FALSE;
773 }
774 valid = key->verify(key, scheme, this->certificateInfo, this->signature);
775 key->destroy(key);
776 return valid;
777}
778
779/**
780 * Implementation of certificate_t.get_public_key.
781 */
782static public_key_t* get_public_key(private_x509_ac_t *this)
783{
784 return NULL;
785}
786
787/**
788 * Implementation of certificate_t.get_ref.
789 */
790static private_x509_ac_t* get_ref(private_x509_ac_t *this)
791{
792 ref_get(&this->ref);
793 return this;
794}
795
796/**
797 * Implementation of certificate_t.get_validity.
798 */
799static bool get_validity(private_x509_ac_t *this, time_t *when,
800 time_t *not_before, time_t *not_after)
801{
cf85e131 802 time_t t = when ? *when : time(NULL);
7daf5226 803
bdec2e4f
AS
804 if (not_before)
805 {
806 *not_before = this->notBefore;
807 }
808 if (not_after)
809 {
810 *not_after = this->notAfter;
811 }
cf85e131 812 return (t >= this->notBefore && t <= this->notAfter);
bdec2e4f
AS
813}
814
bdec2e4f
AS
815/**
816 * Implementation of certificate_t.get_encoding.
817 */
0406eeaa
MW
818static bool get_encoding(private_x509_ac_t *this, cred_encoding_type_t type,
819 chunk_t *encoding)
bdec2e4f 820{
0406eeaa
MW
821 if (type == CERT_ASN1_DER)
822 {
823 *encoding = chunk_clone(this->encoding);
824 return TRUE;
825 }
826 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
827 CRED_PART_X509_AC_ASN1_DER, this->encoding, CRED_PART_END);
bdec2e4f
AS
828}
829
830/**
831 * Implementation of certificate_t.equals.
832 */
833static bool equals(private_x509_ac_t *this, certificate_t *other)
834{
b5dbcc62
MW
835 chunk_t encoding;
836 bool equal;
7daf5226 837
bdec2e4f
AS
838 if ((certificate_t*)this == other)
839 {
840 return TRUE;
841 }
842 if (other->equals == (void*)equals)
b5dbcc62 843 { /* skip allocation if we have the same implementation */
7daf5226 844 return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding);
bdec2e4f 845 }
0406eeaa
MW
846 if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
847 {
848 return FALSE;
849 }
b5dbcc62
MW
850 equal = chunk_equals(this->encoding, encoding);
851 free(encoding.ptr);
852 return equal;
bdec2e4f
AS
853}
854
855/**
856 * Implementation of x509_ac_t.destroy
857 */
858static void destroy(private_x509_ac_t *this)
859{
860 if (ref_put(&this->ref))
861 {
862 DESTROY_IF(this->holderIssuer);
863 DESTROY_IF(this->entityName);
864 DESTROY_IF(this->issuerName);
63cb8a7f
AS
865 DESTROY_IF(this->holderCert);
866 DESTROY_IF(this->signerCert);
867 DESTROY_IF(this->signerKey);
fc12e3cd
AS
868 DESTROY_IF(this->charging);
869 DESTROY_IF(this->groups);
9c674e72 870 free(this->serialNumber.ptr);
6b6ece63 871 free(this->authKeyIdentifier.ptr);
bdec2e4f
AS
872 free(this->encoding.ptr);
873 free(this);
874 }
875}
876
877/**
878 * create an empty but initialized X.509 attribute certificate
879 */
26930a8c 880static private_x509_ac_t *create_empty(void)
bdec2e4f
AS
881{
882 private_x509_ac_t *this = malloc_thing(private_x509_ac_t);
7daf5226 883
bdec2e4f 884 /* public functions */
0672aa7b
AS
885 this->public.interface.get_serial = (chunk_t (*)(ac_t*))get_serial;
886 this->public.interface.get_holderSerial = (chunk_t (*)(ac_t*))get_holderSerial;
887 this->public.interface.get_holderIssuer = (identification_t* (*)(ac_t*))get_holderIssuer;
fc12e3cd
AS
888 this->public.interface.get_authKeyIdentifier = (chunk_t (*)(ac_t*))get_authKeyIdentifier;
889 this->public.interface.get_groups = (ietf_attributes_t* (*)(ac_t*))get_groups;
bdec2e4f
AS
890 this->public.interface.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
891 this->public.interface.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
892 this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
893 this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
894 this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
7b88a983 895 this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
bdec2e4f
AS
896 this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
897 this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
0406eeaa 898 this->public.interface.certificate.get_encoding = (bool(*)(certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
bdec2e4f
AS
899 this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
900 this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
901 this->public.interface.certificate.destroy = (void (*)(certificate_t *this))destroy;
902
903 /* initialize */
93da2684 904 this->encoding = chunk_empty;
9c674e72 905 this->serialNumber = chunk_empty;
0672aa7b 906 this->holderSerial = chunk_empty;
6b6ece63 907 this->authKeyIdentifier = chunk_empty;
bdec2e4f
AS
908 this->holderIssuer = NULL;
909 this->entityName = NULL;
910 this->issuerName = NULL;
6ac3a7ac
AS
911 this->holderCert = NULL;
912 this->signerCert = NULL;
913 this->signerKey = NULL;
fc12e3cd
AS
914 this->charging = NULL;
915 this->groups = NULL;
104c96a6 916 this->ref = 1;
bdec2e4f
AS
917
918 return this;
919}
920
26930a8c 921/**
d73f453c 922 * See header.
26930a8c 923 */
d73f453c 924x509_ac_t *x509_ac_load(certificate_type_t type, va_list args)
26930a8c 925{
d73f453c 926 chunk_t blob = chunk_empty;
26930a8c 927
d73f453c 928 while (TRUE)
26930a8c 929 {
d73f453c
MW
930 switch (va_arg(args, builder_part_t))
931 {
932 case BUILD_BLOB_ASN1_DER:
933 blob = va_arg(args, chunk_t);
934 continue;
935 case BUILD_END:
936 break;
937 default:
938 return NULL;
939 }
940 break;
26930a8c 941 }
d73f453c 942 if (blob.ptr)
bdec2e4f 943 {
d73f453c
MW
944 private_x509_ac_t *ac = create_empty();
945
946 ac->encoding = chunk_clone(blob);
947 if (parse_certificate(ac))
26930a8c 948 {
d73f453c 949 return &ac->public;
26930a8c
AS
950 }
951 destroy(ac);
a852928a 952 }
d73f453c 953 return NULL;
bdec2e4f
AS
954}
955
956/**
d73f453c 957 * See header.
bdec2e4f 958 */
d73f453c 959x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
bdec2e4f 960{
d73f453c 961 private_x509_ac_t *ac;
6ac3a7ac 962
d73f453c
MW
963 ac = create_empty();
964 while (TRUE)
bdec2e4f 965 {
d73f453c
MW
966 switch (va_arg(args, builder_part_t))
967 {
968 case BUILD_NOT_BEFORE_TIME:
969 ac->notBefore = va_arg(args, time_t);
970 continue;
971 case BUILD_NOT_AFTER_TIME:
972 ac->notAfter = va_arg(args, time_t);
973 continue;
974 case BUILD_SERIAL:
975 ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
976 continue;
977 case BUILD_IETF_GROUP_ATTR:
fc12e3cd 978 ac->groups = ietf_attributes_create_from_string(va_arg(args, char*));
d73f453c
MW
979 continue;
980 case BUILD_CERT:
981 ac->holderCert = va_arg(args, certificate_t*);
982 ac->holderCert->get_ref(ac->holderCert);
983 continue;
984 case BUILD_SIGNING_CERT:
985 ac->signerCert = va_arg(args, certificate_t*);
986 ac->signerCert->get_ref(ac->signerCert);
987 continue;
988 case BUILD_SIGNING_KEY:
989 ac->signerKey = va_arg(args, private_key_t*);
990 ac->signerKey->get_ref(ac->signerKey);
991 continue;
992 case BUILD_END:
993 break;
994 default:
995 destroy(ac);
996 return NULL;
997 }
998 break;
bdec2e4f 999 }
bdec2e4f 1000
d73f453c
MW
1001 if (ac->signerKey && ac->holderCert && ac->signerCert &&
1002 ac->holderCert->get_type(ac->holderCert) == CERT_X509 &&
1003 ac->signerCert->get_type(ac->signerCert) == CERT_X509)
bdec2e4f 1004 {
d73f453c
MW
1005 ac->encoding = build_ac(ac);
1006 return &ac->public;
bdec2e4f 1007 }
d73f453c
MW
1008 destroy(ac);
1009 return NULL;
bdec2e4f
AS
1010}
1011