2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "x509_ocsp_request.h"
22 #include <asn1/asn1.h>
23 #include <utils/identification.h>
24 #include <utils/linked_list.h>
26 #include <credentials/certificates/x509.h>
27 #include <credentials/keys/private_key.h>
31 typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t
;
34 * private data of x509_ocsp_request
36 struct private_x509_ocsp_request_t
{
41 x509_ocsp_request_t
public;
44 * CA the candidates belong to
49 * Requestor name, subject of cert used if not set
51 identification_t
*requestor
;
54 * Requestor certificate, included in request
59 * Requestor private key to sign request
64 * list of certificates to check, x509_t
66 linked_list_t
*candidates
;
69 * nonce used in request
74 * encoded OCSP request
84 static u_char ASN1_nonce_oid_str
[] = {
87 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
90 static u_char ASN1_response_oid_str
[] = {
93 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
96 static u_char ASN1_response_content_str
[] = {
101 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
104 static const chunk_t ASN1_nonce_oid
= chunk_from_buf(ASN1_nonce_oid_str
);
105 static const chunk_t ASN1_response_oid
= chunk_from_buf(ASN1_response_oid_str
);
106 static const chunk_t ASN1_response_content
= chunk_from_buf(ASN1_response_content_str
);
109 * build requestorName
111 static chunk_t
build_requestorName(private_x509_ocsp_request_t
*this)
113 if (this->requestor
|| this->cert
)
114 { /* use requestor name, fallback to his cert subject */
115 if (!this->requestor
)
117 this->requestor
= this->cert
->get_subject(this->cert
);
118 this->requestor
= this->requestor
->clone(this->requestor
);
120 return asn1_wrap(ASN1_CONTEXT_C_1
, "m",
121 asn1_simple_object(ASN1_CONTEXT_C_4
,
122 this->requestor
->get_encoding(this->requestor
)));
129 * build Request, not using singleRequestExtensions
131 static chunk_t
build_Request(private_x509_ocsp_request_t
*this,
132 chunk_t issuerNameHash
, chunk_t issuerKeyHash
,
133 chunk_t serialNumber
)
135 return asn1_wrap(ASN1_SEQUENCE
, "m",
136 asn1_wrap(ASN1_SEQUENCE
, "mmmm",
137 asn1_algorithmIdentifier(OID_SHA1
),
138 asn1_simple_object(ASN1_OCTET_STRING
, issuerNameHash
),
139 asn1_simple_object(ASN1_OCTET_STRING
, issuerKeyHash
),
140 asn1_simple_object(ASN1_INTEGER
, serialNumber
)));
146 static chunk_t
build_requestList(private_x509_ocsp_request_t
*this)
148 chunk_t issuerNameHash
, issuerKeyHash
;
149 identification_t
*issuer
;
152 chunk_t list
= chunk_empty
;
153 public_key_t
*public;
155 cert
= (certificate_t
*)this->ca
;
156 public = cert
->get_public_key(cert
);
159 hasher_t
*hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
162 if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1
,
165 enumerator_t
*enumerator
;
167 issuer
= cert
->get_subject(cert
);
168 hasher
->allocate_hash(hasher
, issuer
->get_encoding(issuer
),
170 hasher
->destroy(hasher
);
172 enumerator
= this->candidates
->create_enumerator(this->candidates
);
173 while (enumerator
->enumerate(enumerator
, &x509
))
175 chunk_t request
, serialNumber
;
177 serialNumber
= x509
->get_serial(x509
);
178 request
= build_Request(this, issuerNameHash
, issuerKeyHash
,
180 list
= chunk_cat("mm", list
, request
);
182 enumerator
->destroy(enumerator
);
183 chunk_free(&issuerNameHash
);
188 DBG1("creating OCSP request failed, SHA1 not supported");
190 public->destroy(public);
194 DBG1("creating OCSP request failed, CA certificate has no public key");
196 return asn1_wrap(ASN1_SEQUENCE
, "m", list
);
200 * build nonce extension
202 static chunk_t
build_nonce(private_x509_ocsp_request_t
*this)
206 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
209 rng
->allocate_bytes(rng
, NONCE_LEN
, &this->nonce
);
211 return asn1_wrap(ASN1_SEQUENCE
, "cm", ASN1_nonce_oid
,
212 asn1_simple_object(ASN1_OCTET_STRING
, this->nonce
));
214 DBG1("creating OCSP request nonce failed, no RNG found");
219 * build acceptableResponses extension
221 static chunk_t
build_acceptableResponses(private_x509_ocsp_request_t
*this)
223 return asn1_wrap(ASN1_SEQUENCE
, "cc",
225 ASN1_response_content
);
229 * build requestExtensions
231 static chunk_t
build_requestExtensions(private_x509_ocsp_request_t
*this)
233 return asn1_wrap(ASN1_CONTEXT_C_2
, "m",
234 asn1_wrap(ASN1_SEQUENCE
, "mm",
236 build_acceptableResponses(this)));
242 static chunk_t
build_tbsRequest(private_x509_ocsp_request_t
*this)
244 return asn1_wrap(ASN1_SEQUENCE
, "mmm",
245 build_requestorName(this),
246 build_requestList(this),
247 build_requestExtensions(this));
251 * Build the optionalSignature
253 static chunk_t
build_optionalSignature(private_x509_ocsp_request_t
*this,
257 signature_scheme_t scheme
;
258 chunk_t certs
, signature
;
260 switch (this->key
->get_type(this->key
))
262 /* TODO: use a generic mapping function */
264 oid
= OID_SHA1_WITH_RSA
;
265 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
268 oid
= OID_ECDSA_WITH_SHA1
;
269 scheme
= SIGN_ECDSA_WITH_SHA1
;
272 DBG1("unable to sign OCSP request, %N signature not supported",
273 key_type_names
, this->key
->get_type(this->key
));
277 if (!this->key
->sign(this->key
, scheme
, tbsRequest
, &signature
))
279 DBG1("creating OCSP signature failed, skipped");
284 certs
= asn1_wrap(ASN1_CONTEXT_C_0
, "m",
285 asn1_wrap(ASN1_SEQUENCE
, "m",
286 this->cert
->get_encoding(this->cert
)));
288 return asn1_wrap(ASN1_CONTEXT_C_0
, "m",
289 asn1_wrap(ASN1_SEQUENCE
, "cmm",
290 asn1_algorithmIdentifier(oid
),
291 asn1_bitstring("m", signature
),
296 * Build the OCSPRequest data
299 static chunk_t
build_OCSPRequest(private_x509_ocsp_request_t
*this)
301 chunk_t tbsRequest
, optionalSignature
= chunk_empty
;
303 tbsRequest
= build_tbsRequest(this);
306 optionalSignature
= build_optionalSignature(this, tbsRequest
);
308 return asn1_wrap(ASN1_SEQUENCE
, "mm", tbsRequest
, optionalSignature
);
313 * Implementation of certificate_t.get_type
315 static certificate_type_t
get_type(private_x509_ocsp_request_t
*this)
317 return CERT_X509_OCSP_REQUEST
;
321 * Implementation of certificate_t.get_subject
323 static identification_t
* get_subject(private_x509_ocsp_request_t
*this)
325 certificate_t
*ca
= (certificate_t
*)this->ca
;
329 return this->requestor
;
333 return this->cert
->get_subject(this->cert
);
335 return ca
->get_subject(ca
);
339 * Implementation of certificate_t.get_issuer
341 static identification_t
* get_issuer(private_x509_ocsp_request_t
*this)
343 certificate_t
*ca
= (certificate_t
*)this->ca
;
345 return ca
->get_subject(ca
);
349 * Implementation of certificate_t.has_subject.
351 static id_match_t
has_subject(private_x509_ocsp_request_t
*this,
352 identification_t
*subject
)
354 certificate_t
*current
;
355 enumerator_t
*enumerator
;
356 id_match_t match
, best
= ID_MATCH_NONE
;
358 enumerator
= this->candidates
->create_enumerator(this->candidates
);
359 while (enumerator
->enumerate(enumerator
, ¤t
))
361 match
= current
->has_subject(current
, subject
);
367 enumerator
->destroy(enumerator
);
372 * Implementation of certificate_t.has_subject.
374 static id_match_t
has_issuer(private_x509_ocsp_request_t
*this,
375 identification_t
*issuer
)
377 certificate_t
*ca
= (certificate_t
*)this->ca
;
379 return ca
->has_subject(ca
, issuer
);
383 * Implementation of certificate_t.issued_by
385 static bool issued_by(private_x509_ocsp_request_t
*this, certificate_t
*issuer
)
387 DBG1("OCSP request validation not implemented!");
392 * Implementation of certificate_t.get_public_key
394 static public_key_t
* get_public_key(private_x509_ocsp_request_t
*this)
400 * Implementation of x509_cert_t.get_validity.
402 static bool get_validity(private_x509_ocsp_request_t
*this, time_t *when
,
403 time_t *not_before
, time_t *not_after
)
413 cert
= (certificate_t
*)this->ca
;
415 return cert
->get_validity(cert
, when
, not_before
, not_after
);
419 * Implementation of certificate_t.get_encoding.
421 static chunk_t
get_encoding(private_x509_ocsp_request_t
*this)
423 return chunk_clone(this->encoding
);
427 * Implementation of certificate_t.equals.
429 static bool equals(private_x509_ocsp_request_t
*this, certificate_t
*other
)
434 if (this == (private_x509_ocsp_request_t
*)other
)
438 if (other
->get_type(other
) != CERT_X509_OCSP_REQUEST
)
442 if (other
->equals
== (void*)equals
)
443 { /* skip allocation if we have the same implementation */
444 return chunk_equals(this->encoding
, ((private_x509_ocsp_request_t
*)other
)->encoding
);
446 encoding
= other
->get_encoding(other
);
447 equal
= chunk_equals(this->encoding
, encoding
);
453 * Implementation of certificate_t.asdf
455 static private_x509_ocsp_request_t
* get_ref(private_x509_ocsp_request_t
*this)
462 * Implementation of x509_ocsp_request_t.destroy
464 static void destroy(private_x509_ocsp_request_t
*this)
466 if (ref_put(&this->ref
))
468 DESTROY_IF((certificate_t
*)this->ca
);
469 DESTROY_IF(this->requestor
);
470 DESTROY_IF(this->cert
);
471 DESTROY_IF(this->key
);
472 this->candidates
->destroy_offset(this->candidates
, offsetof(certificate_t
, destroy
));
473 chunk_free(&this->nonce
);
474 chunk_free(&this->encoding
);
480 * create an empty but initialized OCSP request
482 static private_x509_ocsp_request_t
*create_empty()
484 private_x509_ocsp_request_t
*this = malloc_thing(private_x509_ocsp_request_t
);
486 this->public.interface
.interface
.get_type
= (certificate_type_t (*)(certificate_t
*this))get_type
;
487 this->public.interface
.interface
.get_subject
= (identification_t
* (*)(certificate_t
*this))get_subject
;
488 this->public.interface
.interface
.get_issuer
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
489 this->public.interface
.interface
.has_subject
= (id_match_t(*)(certificate_t
*, identification_t
*subject
))has_subject
;
490 this->public.interface
.interface
.has_issuer
= (id_match_t(*)(certificate_t
*, identification_t
*issuer
))has_issuer
;
491 this->public.interface
.interface
.issued_by
= (bool (*)(certificate_t
*this, certificate_t
*issuer
))issued_by
;
492 this->public.interface
.interface
.get_public_key
= (public_key_t
* (*)(certificate_t
*this))get_public_key
;
493 this->public.interface
.interface
.get_validity
= (bool(*)(certificate_t
*, time_t *when
, time_t *, time_t*))get_validity
;
494 this->public.interface
.interface
.get_encoding
= (chunk_t(*)(certificate_t
*))get_encoding
;
495 this->public.interface
.interface
.equals
= (bool(*)(certificate_t
*, certificate_t
*other
))equals
;
496 this->public.interface
.interface
.get_ref
= (certificate_t
* (*)(certificate_t
*this))get_ref
;
497 this->public.interface
.interface
.destroy
= (void (*)(certificate_t
*this))destroy
;
500 this->requestor
= NULL
;
503 this->nonce
= chunk_empty
;
504 this->encoding
= chunk_empty
;
505 this->candidates
= linked_list_create();
511 typedef struct private_builder_t private_builder_t
;
513 * Builder implementation for certificate loading
515 struct private_builder_t
{
516 /** implements the builder interface */
518 /** OCSP request to build */
519 private_x509_ocsp_request_t
*req
;
523 * Implementation of builder_t.build
525 static x509_ocsp_request_t
*build(private_builder_t
*this)
527 private_x509_ocsp_request_t
*req
;
533 req
->encoding
= build_OCSPRequest(req
);
541 * Implementation of builder_t.add
543 static void add(private_builder_t
*this, builder_part_t part
, ...)
547 identification_t
*subject
;
548 private_key_t
*private;
550 va_start(args
, part
);
554 cert
= va_arg(args
, certificate_t
*);
555 if (cert
->get_type(cert
) == CERT_X509
)
557 this->req
->ca
= (x509_t
*)cert
->get_ref(cert
);
561 cert
= va_arg(args
, certificate_t
*);
562 if (cert
->get_type(cert
) == CERT_X509
)
564 this->req
->candidates
->insert_last(this->req
->candidates
,
565 cert
->get_ref(cert
));
568 case BUILD_SIGNING_CERT
:
569 cert
= va_arg(args
, certificate_t
*);
570 this->req
->cert
= cert
->get_ref(cert
);
572 case BUILD_SIGNING_KEY
:
573 private = va_arg(args
, private_key_t
*);
574 this->req
->key
= private->get_ref(private);
577 subject
= va_arg(args
, identification_t
*);
578 this->req
->requestor
= subject
->clone(subject
);
581 /* cancel if option not supported */
586 builder_cancel(&this->public);
593 * Builder construction function
595 builder_t
*x509_ocsp_request_builder(certificate_type_t type
)
597 private_builder_t
*this;
599 if (type
!= CERT_X509_OCSP_REQUEST
)
604 this = malloc_thing(private_builder_t
);
606 this->req
= create_empty();
607 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
608 this->public.build
= (void*(*)(builder_t
*this))build
;
610 return &this->public;