Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_ocsp_response.c, revision 1.1.1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>