Return to x509_ocsp_request.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-2014 Andreas Steffen 5: * HSR Hochschule fuer Technik Rapperswil 6: * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen 7: * 8: * This program is free software; you can redistribute it and/or modify it 9: * under the terms of the GNU General Public License as published by the 10: * Free Software Foundation; either version 2 of the License, or (at your 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 12: * 13: * This program is distributed in the hope that it will be useful, but 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16: * for more details. 17: */ 18: 19: #include "x509_ocsp_request.h" 20: 21: #include <library.h> 22: #include <asn1/oid.h> 23: #include <asn1/asn1.h> 24: #include <utils/identification.h> 25: #include <collections/linked_list.h> 26: #include <utils/debug.h> 27: #include <credentials/certificates/x509.h> 28: #include <credentials/keys/private_key.h> 29: 30: #define NONCE_LEN 16 31: 32: typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t; 33: 34: /** 35: * private data of x509_ocsp_request 36: */ 37: struct private_x509_ocsp_request_t { 38: 39: /** 40: * public functions 41: */ 42: x509_ocsp_request_t public; 43: 44: /** 45: * CA the candidates belong to 46: */ 47: x509_t *ca; 48: 49: /** 50: * Requestor name, subject of cert used if not set 51: */ 52: identification_t *requestor; 53: 54: /** 55: * Requestor certificate, included in request 56: */ 57: certificate_t *cert; 58: 59: /** 60: * Requestor private key to sign request 61: */ 62: private_key_t *key; 63: 64: /** 65: * list of certificates to check, x509_t 66: */ 67: linked_list_t *candidates; 68: 69: /** 70: * nonce used in request 71: */ 72: chunk_t nonce; 73: 74: /** 75: * encoded OCSP request 76: */ 77: chunk_t encoding; 78: 79: /** 80: * reference count 81: */ 82: refcount_t ref; 83: }; 84: 85: static const chunk_t ASN1_nonce_oid = chunk_from_chars( 86: 0x06, 0x09, 87: 0x2B, 0x06, 88: 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 89: ); 90: static const chunk_t ASN1_response_oid = chunk_from_chars( 91: 0x06, 0x09, 92: 0x2B, 0x06, 93: 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04 94: ); 95: static const chunk_t ASN1_response_content = chunk_from_chars( 96: 0x04, 0x0D, 97: 0x30, 0x0B, 98: 0x06, 0x09, 99: 0x2B, 0x06, 100: 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 101: ); 102: 103: /** 104: * build requestorName 105: */ 106: static chunk_t build_requestorName(private_x509_ocsp_request_t *this) 107: { 108: if (this->requestor || this->cert) 109: { /* use requestor name, fallback to his cert subject */ 110: if (!this->requestor) 111: { 112: this->requestor = this->cert->get_subject(this->cert); 113: this->requestor = this->requestor->clone(this->requestor); 114: } 115: return asn1_wrap(ASN1_CONTEXT_C_1, "m", 116: asn1_simple_object(ASN1_CONTEXT_C_4, 117: this->requestor->get_encoding(this->requestor))); 118: 119: } 120: return chunk_empty; 121: } 122: 123: /** 124: * build Request, not using singleRequestExtensions 125: */ 126: static chunk_t build_Request(private_x509_ocsp_request_t *this, 127: chunk_t issuerNameHash, chunk_t issuerKeyHash, 128: chunk_t serialNumber) 129: { 130: return asn1_wrap(ASN1_SEQUENCE, "m", 131: asn1_wrap(ASN1_SEQUENCE, "mmmm", 132: asn1_algorithmIdentifier(OID_SHA1), 133: asn1_simple_object(ASN1_OCTET_STRING, issuerNameHash), 134: asn1_simple_object(ASN1_OCTET_STRING, issuerKeyHash), 135: asn1_simple_object(ASN1_INTEGER, serialNumber))); 136: } 137: 138: /** 139: * build requestList 140: */ 141: static chunk_t build_requestList(private_x509_ocsp_request_t *this) 142: { 143: chunk_t issuerNameHash, issuerKeyHash; 144: identification_t *issuer; 145: x509_t *x509; 146: certificate_t *cert; 147: chunk_t list = chunk_empty; 148: public_key_t *public; 149: 150: cert = (certificate_t*)this->ca; 151: public = cert->get_public_key(cert); 152: if (public) 153: { 154: hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 155: if (hasher) 156: { 157: if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, 158: &issuerKeyHash)) 159: { 160: enumerator_t *enumerator; 161: 162: issuer = cert->get_subject(cert); 163: if (hasher->allocate_hash(hasher, issuer->get_encoding(issuer), 164: &issuerNameHash)) 165: { 166: enumerator = this->candidates->create_enumerator( 167: this->candidates); 168: while (enumerator->enumerate(enumerator, &x509)) 169: { 170: chunk_t request, serialNumber; 171: 172: serialNumber = x509->get_serial(x509); 173: request = build_Request(this, issuerNameHash, 174: issuerKeyHash, serialNumber); 175: list = chunk_cat("mm", list, request); 176: } 177: enumerator->destroy(enumerator); 178: chunk_free(&issuerNameHash); 179: } 180: hasher->destroy(hasher); 181: } 182: } 183: else 184: { 185: DBG1(DBG_LIB, "creating OCSP request failed, SHA1 not supported"); 186: } 187: public->destroy(public); 188: } 189: else 190: { 191: DBG1(DBG_LIB, "creating OCSP request failed, CA certificate has " 192: "no public key"); 193: } 194: return asn1_wrap(ASN1_SEQUENCE, "m", list); 195: } 196: 197: /** 198: * build nonce extension 199: */ 200: static chunk_t build_nonce(private_x509_ocsp_request_t *this) 201: { 202: rng_t *rng; 203: 204: rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); 205: if (!rng || !rng->allocate_bytes(rng, NONCE_LEN, &this->nonce)) 206: { 207: DBG1(DBG_LIB, "creating OCSP request nonce failed, no RNG found"); 208: DESTROY_IF(rng); 209: return chunk_empty; 210: } 211: rng->destroy(rng); 212: return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid, 213: asn1_wrap(ASN1_OCTET_STRING, "m", 214: asn1_simple_object(ASN1_OCTET_STRING, this->nonce))); 215: } 216: 217: /** 218: * build acceptableResponses extension 219: */ 220: static chunk_t build_acceptableResponses(private_x509_ocsp_request_t *this) 221: { 222: return asn1_wrap(ASN1_SEQUENCE, "cc", 223: ASN1_response_oid, 224: ASN1_response_content); 225: } 226: 227: /** 228: * build requestExtensions 229: */ 230: static chunk_t build_requestExtensions(private_x509_ocsp_request_t *this) 231: { 232: return asn1_wrap(ASN1_CONTEXT_C_2, "m", 233: asn1_wrap(ASN1_SEQUENCE, "mm", 234: build_nonce(this), 235: build_acceptableResponses(this))); 236: } 237: 238: /** 239: * build tbsRequest 240: */ 241: static chunk_t build_tbsRequest(private_x509_ocsp_request_t *this) 242: { 243: return asn1_wrap(ASN1_SEQUENCE, "mmm", 244: build_requestorName(this), 245: build_requestList(this), 246: build_requestExtensions(this)); 247: } 248: 249: /** 250: * Build the optionalSignature 251: */ 252: static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this, 253: chunk_t tbsRequest) 254: { 255: int oid; 256: signature_scheme_t scheme; 257: chunk_t certs = chunk_empty, signature, encoding; 258: 259: switch (this->key->get_type(this->key)) 260: { 261: /* TODO: use a generic mapping function */ 262: case KEY_RSA: 263: oid = OID_SHA1_WITH_RSA; 264: scheme = SIGN_RSA_EMSA_PKCS1_SHA1; 265: break; 266: case KEY_ECDSA: 267: oid = OID_ECDSA_WITH_SHA1; 268: scheme = SIGN_ECDSA_WITH_SHA1_DER; 269: break; 270: case KEY_BLISS: 271: oid = OID_BLISS_WITH_SHA2_512; 272: scheme = SIGN_BLISS_WITH_SHA2_512; 273: break; 274: default: 275: DBG1(DBG_LIB, "unable to sign OCSP request, %N signature not " 276: "supported", key_type_names, this->key->get_type(this->key)); 277: return chunk_empty; 278: } 279: 280: if (!this->key->sign(this->key, scheme, NULL, tbsRequest, &signature)) 281: { 282: DBG1(DBG_LIB, "creating OCSP signature failed, skipped"); 283: return chunk_empty; 284: } 285: if (this->cert && 286: this->cert->get_encoding(this->cert, CERT_ASN1_DER, &encoding)) 287: { 288: certs = asn1_wrap(ASN1_CONTEXT_C_0, "m", 289: asn1_wrap(ASN1_SEQUENCE, "m", encoding)); 290: } 291: return asn1_wrap(ASN1_CONTEXT_C_0, "m", 292: asn1_wrap(ASN1_SEQUENCE, "cmm", 293: asn1_algorithmIdentifier(oid), 294: asn1_bitstring("m", signature), 295: certs)); 296: } 297: 298: /** 299: * Build the OCSPRequest data 300: * 301: */ 302: static chunk_t build_OCSPRequest(private_x509_ocsp_request_t *this) 303: { 304: chunk_t tbsRequest, optionalSignature = chunk_empty; 305: 306: tbsRequest = build_tbsRequest(this); 307: if (this->key) 308: { 309: optionalSignature = build_optionalSignature(this, tbsRequest); 310: } 311: return asn1_wrap(ASN1_SEQUENCE, "mm", tbsRequest, optionalSignature); 312: } 313: 314: 315: METHOD(certificate_t, get_type, certificate_type_t, 316: private_x509_ocsp_request_t *this) 317: { 318: return CERT_X509_OCSP_REQUEST; 319: } 320: 321: METHOD(certificate_t, get_subject, identification_t*, 322: private_x509_ocsp_request_t *this) 323: { 324: certificate_t *ca = (certificate_t*)this->ca; 325: 326: if (this->requestor) 327: { 328: return this->requestor; 329: } 330: if (this->cert) 331: { 332: return this->cert->get_subject(this->cert); 333: } 334: return ca->get_subject(ca); 335: } 336: 337: METHOD(certificate_t, get_issuer, identification_t*, 338: private_x509_ocsp_request_t *this) 339: { 340: certificate_t *ca = (certificate_t*)this->ca; 341: 342: return ca->get_subject(ca); 343: } 344: 345: METHOD(certificate_t, has_subject, id_match_t, 346: private_x509_ocsp_request_t *this, identification_t *subject) 347: { 348: certificate_t *current; 349: enumerator_t *enumerator; 350: id_match_t match, best = ID_MATCH_NONE; 351: 352: enumerator = this->candidates->create_enumerator(this->candidates); 353: while (enumerator->enumerate(enumerator, ¤t)) 354: { 355: match = current->has_subject(current, subject); 356: if (match > best) 357: { 358: best = match; 359: } 360: } 361: enumerator->destroy(enumerator); 362: return best; 363: } 364: 365: METHOD(certificate_t, has_issuer, id_match_t, 366: private_x509_ocsp_request_t *this, 367: identification_t *issuer) 368: { 369: certificate_t *ca = (certificate_t*)this->ca; 370: 371: return ca->has_subject(ca, issuer); 372: } 373: 374: METHOD(certificate_t, issued_by, bool, 375: private_x509_ocsp_request_t *this, certificate_t *issuer, 376: signature_params_t **scheme) 377: { 378: DBG1(DBG_LIB, "OCSP request validation not implemented!"); 379: return FALSE; 380: } 381: 382: METHOD(certificate_t, get_public_key, public_key_t*, 383: private_x509_ocsp_request_t *this) 384: { 385: return NULL; 386: } 387: 388: METHOD(certificate_t, get_validity, bool, 389: private_x509_ocsp_request_t *this, time_t *when, time_t *not_before, 390: time_t *not_after) 391: { 392: certificate_t *cert; 393: 394: if (this->cert) 395: { 396: cert = this->cert; 397: } 398: else 399: { 400: cert = (certificate_t*)this->ca; 401: } 402: return cert->get_validity(cert, when, not_before, not_after); 403: } 404: 405: METHOD(certificate_t, get_encoding, bool, 406: private_x509_ocsp_request_t *this, cred_encoding_type_t type, 407: chunk_t *encoding) 408: { 409: if (type == CERT_ASN1_DER) 410: { 411: *encoding = chunk_clone(this->encoding); 412: return TRUE; 413: } 414: return lib->encoding->encode(lib->encoding, type, NULL, encoding, 415: CRED_PART_X509_OCSP_REQ_ASN1_DER, this->encoding, CRED_PART_END); 416: } 417: 418: METHOD(certificate_t, equals, bool, 419: private_x509_ocsp_request_t *this, certificate_t *other) 420: { 421: chunk_t encoding; 422: bool equal; 423: 424: if (this == (private_x509_ocsp_request_t*)other) 425: { 426: return TRUE; 427: } 428: if (other->get_type(other) != CERT_X509_OCSP_REQUEST) 429: { 430: return FALSE; 431: } 432: if (other->equals == (void*)equals) 433: { /* skip allocation if we have the same implementation */ 434: return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding); 435: } 436: if (!other->get_encoding(other, CERT_ASN1_DER, &encoding)) 437: { 438: return FALSE; 439: } 440: equal = chunk_equals(this->encoding, encoding); 441: free(encoding.ptr); 442: return equal; 443: } 444: 445: METHOD(certificate_t, get_ref, certificate_t*, 446: private_x509_ocsp_request_t *this) 447: { 448: ref_get(&this->ref); 449: return &this->public.interface.interface; 450: } 451: 452: METHOD(certificate_t, destroy, void, 453: private_x509_ocsp_request_t *this) 454: { 455: if (ref_put(&this->ref)) 456: { 457: DESTROY_IF((certificate_t*)this->ca); 458: DESTROY_IF(this->requestor); 459: DESTROY_IF(this->cert); 460: DESTROY_IF(this->key); 461: this->candidates->destroy_offset(this->candidates, offsetof(certificate_t, destroy)); 462: chunk_free(&this->nonce); 463: chunk_free(&this->encoding); 464: free(this); 465: } 466: } 467: 468: METHOD(ocsp_request_t, get_nonce, chunk_t, 469: private_x509_ocsp_request_t *this) 470: { 471: return this->nonce; 472: } 473: 474: /** 475: * create an empty but initialized OCSP request 476: */ 477: static private_x509_ocsp_request_t *create_empty() 478: { 479: private_x509_ocsp_request_t *this; 480: 481: INIT(this, 482: .public = { 483: .interface = { 484: .interface = { 485: .get_type = _get_type, 486: .get_subject = _get_subject, 487: .get_issuer = _get_issuer, 488: .has_subject = _has_subject, 489: .has_issuer = _has_issuer, 490: .issued_by = _issued_by, 491: .get_public_key = _get_public_key, 492: .get_validity = _get_validity, 493: .get_encoding = _get_encoding, 494: .equals = _equals, 495: .get_ref = _get_ref, 496: .destroy = _destroy, 497: }, 498: .get_nonce = _get_nonce, 499: }, 500: }, 501: .candidates = linked_list_create(), 502: .ref = 1, 503: ); 504: 505: return this; 506: } 507: 508: /** 509: * See header. 510: */ 511: x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args) 512: { 513: private_x509_ocsp_request_t *req; 514: certificate_t *cert; 515: private_key_t *private; 516: identification_t *subject; 517: 518: req = create_empty(); 519: while (TRUE) 520: { 521: switch (va_arg(args, builder_part_t)) 522: { 523: case BUILD_CA_CERT: 524: cert = va_arg(args, certificate_t*); 525: if (cert->get_type(cert) == CERT_X509) 526: { 527: req->ca = (x509_t*)cert->get_ref(cert); 528: } 529: continue; 530: case BUILD_CERT: 531: cert = va_arg(args, certificate_t*); 532: if (cert->get_type(cert) == CERT_X509) 533: { 534: req->candidates->insert_last(req->candidates, 535: cert->get_ref(cert)); 536: } 537: continue; 538: case BUILD_SIGNING_CERT: 539: cert = va_arg(args, certificate_t*); 540: req->cert = cert->get_ref(cert); 541: continue; 542: case BUILD_SIGNING_KEY: 543: private = va_arg(args, private_key_t*); 544: req->key = private->get_ref(private); 545: continue; 546: case BUILD_SUBJECT: 547: subject = va_arg(args, identification_t*); 548: req->requestor = subject->clone(subject); 549: continue; 550: case BUILD_END: 551: break; 552: default: 553: destroy(req); 554: return NULL; 555: } 556: break; 557: } 558: if (req->ca) 559: { 560: req->encoding = build_OCSPRequest(req); 561: return &req->public; 562: } 563: destroy(req); 564: return NULL; 565: } 566: