Return to x509_ac.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / x509 |
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: }