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