Return to x509_ocsp_response.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / x509 |
1.1 misho 1: /* 2: * Copyright (C) 2017-2019 Tobias Brunner 3: * Copyright (C) 2008-2009 Martin Willi 4: * Copyright (C) 2007-2015 Andreas Steffen 5: * HSR Hochschule fuer Technik Rapperswil 6: * 7: * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen 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_ocsp_response.h" 21: 22: #include <time.h> 23: 24: #include <asn1/oid.h> 25: #include <asn1/asn1.h> 26: #include <asn1/asn1_parser.h> 27: #include <utils/identification.h> 28: #include <collections/linked_list.h> 29: #include <utils/debug.h> 30: 31: #include <library.h> 32: #include <credentials/certificates/x509.h> 33: #include <credentials/certificates/crl.h> 34: 35: /** 36: * how long do we use an OCSP response without a nextUpdate 37: */ 38: #define OCSP_DEFAULT_LIFETIME 30 39: 40: /* defined in wincrypt.h */ 41: #ifdef OCSP_RESPONSE 42: # undef OCSP_RESPONSE 43: #endif 44: 45: typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t; 46: 47: /** 48: * Private data of a ocsp_t object. 49: */ 50: struct private_x509_ocsp_response_t { 51: /** 52: * Public interface for this ocsp object. 53: */ 54: x509_ocsp_response_t public; 55: 56: /** 57: * complete encoded OCSP response 58: */ 59: chunk_t encoding; 60: 61: /** 62: * data for signature verification 63: */ 64: chunk_t tbsResponseData; 65: 66: /** 67: * signature scheme 68: */ 69: signature_params_t *scheme; 70: 71: /** 72: * signature 73: */ 74: chunk_t signature; 75: 76: /** 77: * name or keyid of the responder 78: */ 79: identification_t *responderId; 80: 81: /** 82: * time of response production 83: */ 84: time_t producedAt; 85: 86: /** 87: * latest nextUpdate in this OCSP response 88: */ 89: time_t usableUntil; 90: 91: /** 92: * list of included certificates 93: */ 94: linked_list_t *certs; 95: 96: /** 97: * Linked list of OCSP responses, single_response_t 98: */ 99: linked_list_t *responses; 100: 101: /** 102: * Nonce required for ocsp request and response 103: */ 104: chunk_t nonce; 105: 106: /** 107: * reference counter 108: */ 109: refcount_t ref; 110: }; 111: 112: /** 113: * single response contained in OCSP response 114: */ 115: typedef struct { 116: /** hash algorithm OID to for the two hashes */ 117: int hashAlgorithm; 118: /** hash of issuer DN */ 119: chunk_t issuerNameHash; 120: /** issuerKeyID */ 121: chunk_t issuerKeyHash; 122: /** serial number of certificate */ 123: chunk_t serialNumber; 124: /** OCSP certificate status */ 125: cert_validation_t status; 126: /** time of revocation, if revoked */ 127: time_t revocationTime; 128: /** revocation reason, if revoked */ 129: crl_reason_t revocationReason; 130: /** creation of associated CRL */ 131: time_t thisUpdate; 132: /** creation of next CRL */ 133: time_t nextUpdate; 134: } single_response_t; 135: 136: /* our OCSP response version implementation */ 137: #define OCSP_BASIC_RESPONSE_VERSION 1 138: 139: METHOD(ocsp_response_t, get_status, cert_validation_t, 140: private_x509_ocsp_response_t *this, x509_t *subject, x509_t *issuer, 141: time_t *revocation_time, crl_reason_t *revocation_reason, 142: time_t *this_update, time_t *next_update) 143: { 144: enumerator_t *enumerator; 145: single_response_t *response; 146: cert_validation_t status = VALIDATION_FAILED; 147: certificate_t *issuercert = &issuer->interface; 148: 149: enumerator = this->responses->create_enumerator(this->responses); 150: while (enumerator->enumerate(enumerator, &response)) 151: { 152: hasher_t *hasher; 153: identification_t *id; 154: cred_encoding_type_t type; 155: chunk_t hash, fingerprint; 156: 157: /* check serial first, is cheaper */ 158: if (!chunk_equals(subject->get_serial(subject), response->serialNumber)) 159: { 160: continue; 161: } 162: /* check issuerKeyHash if available */ 163: if (response->issuerKeyHash.ptr) 164: { 165: public_key_t *public; 166: 167: public = issuercert->get_public_key(issuercert); 168: if (!public) 169: { 170: continue; 171: } 172: switch (response->hashAlgorithm) 173: { 174: case OID_SHA1: 175: type = KEYID_PUBKEY_SHA1; 176: break; 177: default: 178: public->destroy(public); 179: continue; 180: } 181: if (!public->get_fingerprint(public, type, &fingerprint) || 182: !chunk_equals(response->issuerKeyHash, fingerprint)) 183: { 184: public->destroy(public); 185: continue; 186: } 187: public->destroy(public); 188: } 189: /* check issuerNameHash, if available */ 190: else if (response->issuerNameHash.ptr) 191: { 192: id = issuercert->get_subject(issuercert); 193: hasher = lib->crypto->create_hasher(lib->crypto, 194: hasher_algorithm_from_oid(response->hashAlgorithm)); 195: if (!hasher || 196: !hasher->allocate_hash(hasher, id->get_encoding(id), &hash)) 197: { 198: DESTROY_IF(hasher); 199: continue; 200: } 201: hasher->destroy(hasher); 202: if (!chunk_equals(hash, response->issuerNameHash)) 203: { 204: free(hash.ptr); 205: continue; 206: } 207: free(hash.ptr); 208: } 209: else 210: { 211: continue; 212: } 213: /* got a match */ 214: status = response->status; 215: *revocation_time = response->revocationTime; 216: *revocation_reason = response->revocationReason; 217: *this_update = response->thisUpdate; 218: *next_update = response->nextUpdate; 219: 220: break; 221: } 222: enumerator->destroy(enumerator); 223: return status; 224: } 225: 226: METHOD(ocsp_response_t, create_cert_enumerator, enumerator_t*, 227: private_x509_ocsp_response_t *this) 228: { 229: return this->certs->create_enumerator(this->certs); 230: } 231: 232: CALLBACK(filter, bool, 233: void *data, enumerator_t *orig, va_list args) 234: { 235: single_response_t *response; 236: cert_validation_t *status; 237: crl_reason_t *revocationReason; 238: chunk_t *serialNumber; 239: time_t *revocationTime; 240: 241: VA_ARGS_VGET(args, serialNumber, status, revocationTime, revocationReason); 242: 243: if (orig->enumerate(orig, &response)) 244: { 245: if (serialNumber) 246: { 247: *serialNumber = response->serialNumber; 248: } 249: if (status) 250: { 251: *status = response->status; 252: } 253: if (revocationTime) 254: { 255: *revocationTime = response->revocationTime; 256: } 257: if (revocationReason) 258: { 259: *revocationReason = response->revocationReason; 260: } 261: return TRUE; 262: } 263: return FALSE; 264: } 265: 266: METHOD(ocsp_response_t, create_response_enumerator, enumerator_t*, 267: private_x509_ocsp_response_t *this) 268: { 269: return enumerator_create_filter( 270: this->responses->create_enumerator(this->responses), 271: filter, NULL, NULL); 272: } 273: 274: METHOD(ocsp_response_t, get_nonce, chunk_t, 275: private_x509_ocsp_response_t *this) 276: { 277: return this->nonce; 278: } 279: 280: /** 281: * ASN.1 definition of singleResponse 282: */ 283: static const asn1Object_t singleResponseObjects[] = { 284: { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */ 285: { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ 286: { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */ 287: { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ 288: { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */ 289: { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */ 290: { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */ 291: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ 292: { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */ 293: { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */ 294: { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */ 295: { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */ 296: { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */ 297: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */ 298: { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */ 299: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ 300: { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */ 301: { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */ 302: { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */ 303: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ 304: { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */ 305: { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */ 306: { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ 307: { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */ 308: { 4, "critical", ASN1_BOOLEAN, ASN1_BODY | 309: ASN1_DEF }, /* 24 */ 310: { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */ 311: { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */ 312: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ 313: { 0, "exit", ASN1_EOC, ASN1_EXIT } 314: }; 315: #define SINGLE_RESPONSE_ALGORITHM 2 316: #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 317: #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 318: #define SINGLE_RESPONSE_SERIAL_NUMBER 5 319: #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 320: #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 321: #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 322: #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 323: #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 324: #define SINGLE_RESPONSE_THIS_UPDATE 16 325: #define SINGLE_RESPONSE_NEXT_UPDATE 18 326: #define SINGLE_RESPONSE_EXT_ID 23 327: #define SINGLE_RESPONSE_CRITICAL 24 328: #define SINGLE_RESPONSE_EXT_VALUE 25 329: 330: /** 331: * Parse a single OCSP response 332: */ 333: static bool parse_singleResponse(private_x509_ocsp_response_t *this, 334: chunk_t blob, int level0) 335: { 336: asn1_parser_t *parser; 337: chunk_t object; 338: int objectID; 339: bool success = FALSE; 340: 341: single_response_t *response; 342: 343: response = malloc_thing(single_response_t); 344: response->hashAlgorithm = OID_UNKNOWN; 345: response->issuerNameHash = chunk_empty; 346: response->issuerKeyHash = chunk_empty; 347: response->serialNumber = chunk_empty; 348: response->status = VALIDATION_FAILED; 349: response->revocationTime = 0; 350: response->revocationReason = CRL_REASON_UNSPECIFIED; 351: response->thisUpdate = UNDEFINED_TIME; 352: /* if nextUpdate is missing, we give it a short lifetime */ 353: response->nextUpdate = this->producedAt + OCSP_DEFAULT_LIFETIME; 354: 355: parser = asn1_parser_create(singleResponseObjects, blob); 356: parser->set_top_level(parser, level0); 357: 358: while (parser->iterate(parser, &objectID, &object)) 359: { 360: switch (objectID) 361: { 362: case SINGLE_RESPONSE_ALGORITHM: 363: response->hashAlgorithm = asn1_parse_algorithmIdentifier(object, 364: parser->get_level(parser)+1, NULL); 365: break; 366: case SINGLE_RESPONSE_ISSUER_NAME_HASH: 367: response->issuerNameHash = object; 368: break; 369: case SINGLE_RESPONSE_ISSUER_KEY_HASH: 370: response->issuerKeyHash = object; 371: break; 372: case SINGLE_RESPONSE_SERIAL_NUMBER: 373: response->serialNumber = object; 374: break; 375: case SINGLE_RESPONSE_CERT_STATUS_GOOD: 376: response->status = VALIDATION_GOOD; 377: break; 378: case SINGLE_RESPONSE_CERT_STATUS_REVOKED: 379: response->status = VALIDATION_REVOKED; 380: break; 381: case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: 382: response->revocationTime = asn1_to_time(&object, ASN1_GENERALIZEDTIME); 383: break; 384: case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: 385: if (object.len == 1) 386: { 387: response->revocationReason = *object.ptr; 388: } 389: break; 390: case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: 391: response->status = VALIDATION_FAILED; 392: break; 393: case SINGLE_RESPONSE_THIS_UPDATE: 394: response->thisUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME); 395: break; 396: case SINGLE_RESPONSE_NEXT_UPDATE: 397: response->nextUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME); 398: if (response->nextUpdate > this->usableUntil) 399: { 400: this->usableUntil = response->nextUpdate; 401: } 402: break; 403: } 404: } 405: success = parser->success(parser); 406: parser->destroy(parser); 407: if (success) 408: { 409: if (this->usableUntil == UNDEFINED_TIME) 410: { 411: this->usableUntil = this->producedAt + OCSP_DEFAULT_LIFETIME; 412: } 413: this->responses->insert_last(this->responses, response); 414: } 415: else 416: { 417: free(response); 418: } 419: return success; 420: } 421: 422: /** 423: * ASN.1 definition of responses 424: */ 425: static const asn1Object_t responsesObjects[] = { 426: { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ 427: { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */ 428: { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ 429: { 0, "exit", ASN1_EOC, ASN1_EXIT } 430: }; 431: #define RESPONSES_SINGLE_RESPONSE 1 432: 433: /** 434: * Parse all responses 435: */ 436: static bool parse_responses(private_x509_ocsp_response_t *this, 437: chunk_t blob, int level0) 438: { 439: asn1_parser_t *parser; 440: chunk_t object; 441: int objectID; 442: bool success = FALSE; 443: 444: parser = asn1_parser_create(responsesObjects, blob); 445: parser->set_top_level(parser, level0); 446: 447: while (parser->iterate(parser, &objectID, &object)) 448: { 449: switch (objectID) 450: { 451: case RESPONSES_SINGLE_RESPONSE: 452: if (!parse_singleResponse(this, object, 453: parser->get_level(parser)+1)) 454: { 455: goto end; 456: } 457: break; 458: default: 459: break; 460: } 461: } 462: success = parser->success(parser); 463: 464: end: 465: parser->destroy(parser); 466: return success; 467: } 468: 469: /** 470: * ASN.1 definition of basicResponse 471: */ 472: static const asn1Object_t basicResponseObjects[] = { 473: { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 474: { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ 475: { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | 476: ASN1_DEF }, /* 2 */ 477: { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ 478: { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ 479: { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ 480: { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ 481: { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */ 482: { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */ 483: { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ 484: { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */ 485: { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ 486: { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ 487: { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */ 488: { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ 489: { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ 490: { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | 491: ASN1_DEF }, /* 16 */ 492: { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ 493: { 3, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ 494: { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ 495: { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */ 496: { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */ 497: { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ 498: { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ 499: { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */ 500: { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ 501: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ 502: { 0, "exit", ASN1_EOC, ASN1_EXIT } 503: }; 504: #define BASIC_RESPONSE_TBS_DATA 1 505: #define BASIC_RESPONSE_VERSION 3 506: #define BASIC_RESPONSE_ID_BY_NAME 5 507: #define BASIC_RESPONSE_ID_BY_KEY 8 508: #define BASIC_RESPONSE_PRODUCED_AT 10 509: #define BASIC_RESPONSE_RESPONSES 11 510: #define BASIC_RESPONSE_EXT_ID 15 511: #define BASIC_RESPONSE_CRITICAL 16 512: #define BASIC_RESPONSE_EXT_VALUE 17 513: #define BASIC_RESPONSE_ALGORITHM 20 514: #define BASIC_RESPONSE_SIGNATURE 21 515: #define BASIC_RESPONSE_CERTIFICATE 24 516: 517: /** 518: * Parse a basicOCSPResponse 519: */ 520: static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, 521: chunk_t blob, int level0) 522: { 523: asn1_parser_t *parser; 524: chunk_t object; 525: chunk_t responses = chunk_empty; 526: int objectID; 527: int extn_oid = OID_UNKNOWN; 528: u_int responses_level = level0; 529: certificate_t *cert; 530: bool success = FALSE; 531: bool critical; 532: 533: parser = asn1_parser_create(basicResponseObjects, blob); 534: parser->set_top_level(parser, level0); 535: 536: while (parser->iterate(parser, &objectID, &object)) 537: { 538: switch (objectID) 539: { 540: case BASIC_RESPONSE_TBS_DATA: 541: this->tbsResponseData = object; 542: break; 543: case BASIC_RESPONSE_VERSION: 544: { 545: u_int version = (object.len)? (1 + (u_int)*object.ptr) : 1; 546: 547: if (version != OCSP_BASIC_RESPONSE_VERSION) 548: { 549: DBG1(DBG_ASN, " ocsp ResponseData version %d not " 550: "supported", version); 551: goto end; 552: } 553: break; 554: } 555: case BASIC_RESPONSE_ID_BY_NAME: 556: this->responderId = identification_create_from_encoding( 557: ID_DER_ASN1_DN, object); 558: DBG2(DBG_ASN, " '%Y'", this->responderId); 559: break; 560: case BASIC_RESPONSE_ID_BY_KEY: 561: this->responderId = identification_create_from_encoding( 562: ID_KEY_ID, object); 563: DBG2(DBG_ASN, " '%Y'", this->responderId); 564: break; 565: case BASIC_RESPONSE_PRODUCED_AT: 566: this->producedAt = asn1_to_time(&object, ASN1_GENERALIZEDTIME); 567: break; 568: case BASIC_RESPONSE_RESPONSES: 569: responses = object; 570: responses_level = parser->get_level(parser)+1; 571: break; 572: case BASIC_RESPONSE_EXT_ID: 573: extn_oid = asn1_known_oid(object); 574: break; 575: case BASIC_RESPONSE_CRITICAL: 576: critical = object.len && *object.ptr; 577: DBG2(DBG_ASN, " %s", critical ? "TRUE" : "FALSE"); 578: break; 579: case BASIC_RESPONSE_EXT_VALUE: 580: if (extn_oid == OID_NONCE && 581: asn1_parse_simple_object(&object, ASN1_OCTET_STRING, 582: parser->get_level(parser)+1, "nonce")) 583: { 584: this->nonce = object; 585: } 586: break; 587: case BASIC_RESPONSE_ALGORITHM: 588: INIT(this->scheme); 589: if (!signature_params_parse(object, parser->get_level(parser)+1, 590: this->scheme)) 591: { 592: DBG1(DBG_ASN, " unable to parse signature algorithm"); 593: goto end; 594: } 595: break; 596: case BASIC_RESPONSE_SIGNATURE: 597: this->signature = chunk_skip(object, 1); 598: break; 599: case BASIC_RESPONSE_CERTIFICATE: 600: { 601: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,CERT_X509, 602: BUILD_BLOB_ASN1_DER, object, 603: BUILD_END); 604: if (cert) 605: { 606: this->certs->insert_last(this->certs, cert); 607: } 608: break; 609: } 610: } 611: } 612: success = parser->success(parser); 613: 614: end: 615: parser->destroy(parser); 616: if (success) 617: { 618: if (!this->responderId) 619: { 620: this->responderId = identification_create_from_encoding(ID_ANY, 621: chunk_empty); 622: } 623: success = parse_responses(this, responses, responses_level); 624: } 625: return success; 626: } 627: 628: /** 629: * ASN.1 definition of ocspResponse 630: */ 631: static const asn1Object_t ocspResponseObjects[] = { 632: { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 633: { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */ 634: { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */ 635: { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ 636: { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */ 637: { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */ 638: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */ 639: { 0, "exit", ASN1_EOC, ASN1_EXIT } 640: }; 641: #define OCSP_RESPONSE_STATUS 1 642: #define OCSP_RESPONSE_TYPE 4 643: #define OCSP_RESPONSE 5 644: 645: /** 646: * Parse OCSPResponse object 647: */ 648: static bool parse_OCSPResponse(private_x509_ocsp_response_t *this) 649: { 650: asn1_parser_t *parser; 651: chunk_t object; 652: int objectID; 653: int responseType = OID_UNKNOWN; 654: bool success = FALSE; 655: ocsp_status_t status; 656: 657: parser = asn1_parser_create(ocspResponseObjects, this->encoding); 658: 659: while (parser->iterate(parser, &objectID, &object)) 660: { 661: switch (objectID) 662: { 663: case OCSP_RESPONSE_STATUS: 664: status = (ocsp_status_t)*object.ptr; 665: switch (status) 666: { 667: case OCSP_SUCCESSFUL: 668: break; 669: default: 670: DBG1(DBG_LIB, " ocsp response status: %N", 671: ocsp_status_names, status); 672: goto end; 673: } 674: break; 675: case OCSP_RESPONSE_TYPE: 676: responseType = asn1_known_oid(object); 677: break; 678: case OCSP_RESPONSE: 679: switch (responseType) 680: { 681: case OID_BASIC: 682: success = parse_basicOCSPResponse(this, object, 683: parser->get_level(parser)+1); 684: break; 685: default: 686: DBG1(DBG_LIB, " ocsp response type %#B not supported", 687: &object); 688: goto end; 689: } 690: break; 691: } 692: } 693: success &= parser->success(parser); 694: 695: end: 696: parser->destroy(parser); 697: return success; 698: } 699: 700: METHOD(certificate_t, get_type, certificate_type_t, 701: private_x509_ocsp_response_t *this) 702: { 703: return CERT_X509_OCSP_RESPONSE; 704: } 705: 706: METHOD(certificate_t, get_issuer, identification_t*, 707: private_x509_ocsp_response_t *this) 708: { 709: return this->responderId; 710: } 711: 712: METHOD(certificate_t, has_issuer, id_match_t, 713: private_x509_ocsp_response_t *this, identification_t *issuer) 714: { 715: return this->responderId->matches(this->responderId, issuer); 716: } 717: 718: METHOD(certificate_t, issued_by, bool, 719: private_x509_ocsp_response_t *this, certificate_t *issuer, 720: signature_params_t **scheme) 721: { 722: public_key_t *key; 723: bool valid; 724: x509_t *x509 = (x509_t*)issuer; 725: 726: if (issuer->get_type(issuer) != CERT_X509) 727: { 728: return FALSE; 729: } 730: if (this->responderId->get_type(this->responderId) == ID_KEY_ID) 731: { 732: chunk_t fingerprint; 733: 734: key = issuer->get_public_key(issuer); 735: if (!key || 736: !key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) || 737: !chunk_equals(fingerprint, 738: this->responderId->get_encoding(this->responderId))) 739: { 740: DESTROY_IF(key); 741: return FALSE; 742: } 743: key->destroy(key); 744: } 745: else 746: { 747: if (!this->responderId->equals(this->responderId, 748: issuer->get_subject(issuer))) 749: { 750: return FALSE; 751: } 752: } 753: if (!(x509->get_flags(x509) & X509_OCSP_SIGNER) && 754: !(x509->get_flags(x509) & X509_CA)) 755: { 756: return FALSE; 757: } 758: 759: key = issuer->get_public_key(issuer); 760: if (!key) 761: { 762: return FALSE; 763: } 764: valid = key->verify(key, this->scheme->scheme, this->scheme->params, 765: this->tbsResponseData, this->signature); 766: key->destroy(key); 767: if (valid && scheme) 768: { 769: *scheme = signature_params_clone(this->scheme); 770: } 771: return valid; 772: } 773: 774: METHOD(certificate_t, get_public_key, public_key_t*, 775: private_x509_ocsp_response_t *this) 776: { 777: return NULL; 778: } 779: 780: METHOD(certificate_t, get_validity, bool, 781: private_x509_ocsp_response_t *this, time_t *when, 782: time_t *not_before, time_t *not_after) 783: { 784: time_t t = when ? *when : time(NULL); 785: 786: if (not_before) 787: { 788: *not_before = this->producedAt; 789: } 790: if (not_after) 791: { 792: *not_after = this->usableUntil; 793: } 794: return (t < this->usableUntil); 795: } 796: 797: METHOD(certificate_t, get_encoding, bool, 798: private_x509_ocsp_response_t *this, cred_encoding_type_t type, 799: chunk_t *encoding) 800: { 801: if (type == CERT_ASN1_DER) 802: { 803: *encoding = chunk_clone(this->encoding); 804: return TRUE; 805: } 806: return lib->encoding->encode(lib->encoding, type, NULL, encoding, 807: CRED_PART_X509_OCSP_RES_ASN1_DER, this->encoding, CRED_PART_END); 808: } 809: 810: METHOD(certificate_t, equals, bool, 811: private_x509_ocsp_response_t *this, certificate_t *other) 812: { 813: chunk_t encoding; 814: bool equal; 815: 816: if (this == (private_x509_ocsp_response_t*)other) 817: { 818: return TRUE; 819: } 820: if (other->get_type(other) != CERT_X509_OCSP_RESPONSE) 821: { 822: return FALSE; 823: } 824: if (other->equals == (void*)equals) 825: { /* skip allocation if we have the same implementation */ 826: return chunk_equals(this->encoding, ((private_x509_ocsp_response_t*)other)->encoding); 827: } 828: if (!other->get_encoding(other, CERT_ASN1_DER, &encoding)) 829: { 830: return FALSE; 831: } 832: equal = chunk_equals(this->encoding, encoding); 833: free(encoding.ptr); 834: return equal; 835: } 836: 837: METHOD(certificate_t, get_ref, certificate_t*, 838: private_x509_ocsp_response_t *this) 839: { 840: ref_get(&this->ref); 841: return &this->public.interface.certificate; 842: } 843: 844: METHOD(certificate_t, destroy, void, 845: private_x509_ocsp_response_t *this) 846: { 847: if (ref_put(&this->ref)) 848: { 849: this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy)); 850: this->responses->destroy_function(this->responses, free); 851: signature_params_destroy(this->scheme); 852: DESTROY_IF(this->responderId); 853: free(this->encoding.ptr); 854: free(this); 855: } 856: } 857: 858: /** 859: * load an OCSP response 860: */ 861: static x509_ocsp_response_t *load(chunk_t blob) 862: { 863: private_x509_ocsp_response_t *this; 864: 865: INIT(this, 866: .public = { 867: .interface = { 868: .certificate = { 869: .get_type = _get_type, 870: .get_subject = _get_issuer, 871: .get_issuer = _get_issuer, 872: .has_subject = _has_issuer, 873: .has_issuer = _has_issuer, 874: .issued_by = _issued_by, 875: .get_public_key = _get_public_key, 876: .get_validity = _get_validity, 877: .get_encoding = _get_encoding, 878: .equals = _equals, 879: .get_ref = _get_ref, 880: .destroy = _destroy, 881: }, 882: .get_nonce = _get_nonce, 883: .get_status = _get_status, 884: .create_cert_enumerator = _create_cert_enumerator, 885: .create_response_enumerator = _create_response_enumerator, 886: }, 887: }, 888: .ref = 1, 889: .encoding = chunk_clone(blob), 890: .producedAt = UNDEFINED_TIME, 891: .usableUntil = UNDEFINED_TIME, 892: .responses = linked_list_create(), 893: .certs = linked_list_create(), 894: ); 895: 896: if (!parse_OCSPResponse(this)) 897: { 898: destroy(this); 899: return NULL; 900: } 901: return &this->public; 902: } 903: 904: /** 905: * See header. 906: */ 907: x509_ocsp_response_t *x509_ocsp_response_load(certificate_type_t type, 908: va_list args) 909: { 910: chunk_t blob = chunk_empty; 911: 912: while (TRUE) 913: { 914: switch (va_arg(args, builder_part_t)) 915: { 916: case BUILD_BLOB_ASN1_DER: 917: blob = va_arg(args, chunk_t); 918: continue; 919: case BUILD_END: 920: break; 921: default: 922: return NULL; 923: } 924: break; 925: } 926: if (blob.ptr) 927: { 928: return load(blob); 929: } 930: return NULL; 931: }