Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_ocsp_request.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-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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>