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
20 #include "x509_ocsp_request.h"
24 #include <asn1/asn1.h>
25 #include <utils/identification.h>
26 #include <utils/linked_list.h>
28 #include <credentials/certificates/x509.h>
32 typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t
;
35 * private data of x509_ocsp_request
37 struct private_x509_ocsp_request_t
{
42 x509_ocsp_request_t
public;
45 * CA the candidates belong to
50 * Requestor name, subject of cert used if not set
52 identification_t
*requestor
;
55 * Requestor certificate, included in request
60 * Requestor private key to sign request
65 * list of certificates to check, x509_t
67 linked_list_t
*candidates
;
70 * nonce used in request
75 * encoded OCSP request
85 static u_char ASN1_nonce_oid_str
[] = {
88 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
91 static u_char ASN1_response_oid_str
[] = {
94 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
97 static u_char ASN1_response_content_str
[] = {
102 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
105 static const chunk_t ASN1_nonce_oid
= chunk_from_buf(ASN1_nonce_oid_str
);
106 static const chunk_t ASN1_response_oid
= chunk_from_buf(ASN1_response_oid_str
);
107 static const chunk_t ASN1_response_content
= chunk_from_buf(ASN1_response_content_str
);
110 * build requestorName
112 static chunk_t
build_requestorName(private_x509_ocsp_request_t
*this)
114 if (this->requestor
|| this->cert
)
115 { /* use requestor name, fallback to his cert subject */
116 if (!this->requestor
)
118 this->requestor
= this->cert
->get_subject(this->cert
);
119 this->requestor
= this->requestor
->clone(this->requestor
);
121 return asn1_wrap(ASN1_CONTEXT_C_1
, "m",
122 asn1_simple_object(ASN1_CONTEXT_C_4
,
123 this->requestor
->get_encoding(this->requestor
)));
130 * build Request, not using singleRequestExtensions
132 static chunk_t
build_Request(private_x509_ocsp_request_t
*this,
133 chunk_t issuerNameHash
, chunk_t issuerKeyHash
,
134 chunk_t serialNumber
)
136 return asn1_wrap(ASN1_SEQUENCE
, "m",
137 asn1_wrap(ASN1_SEQUENCE
, "cmmm",
138 asn1_algorithmIdentifier(OID_SHA1
),
139 asn1_simple_object(ASN1_OCTET_STRING
, issuerNameHash
),
140 asn1_simple_object(ASN1_OCTET_STRING
, issuerKeyHash
),
141 asn1_simple_object(ASN1_INTEGER
, serialNumber
)));
147 static chunk_t
build_requestList(private_x509_ocsp_request_t
*this)
149 chunk_t issuerNameHash
, issuerKeyHash
;
150 identification_t
*issuer
;
153 chunk_t list
= chunk_empty
;
154 public_key_t
*public;
156 cert
= (certificate_t
*)this->ca
;
157 public = cert
->get_public_key(cert
);
160 hasher_t
*hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
163 identification_t
*keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
166 enumerator_t
*enumerator
;
168 issuerKeyHash
= keyid
->get_encoding(keyid
);
170 issuer
= cert
->get_subject(cert
);
171 hasher
->allocate_hash(hasher
, issuer
->get_encoding(issuer
),
173 hasher
->destroy(hasher
);
175 enumerator
= this->candidates
->create_enumerator(this->candidates
);
176 while (enumerator
->enumerate(enumerator
, &x509
))
178 chunk_t request
, serialNumber
;
180 serialNumber
= x509
->get_serial(x509
);
181 request
= build_Request(this, issuerNameHash
, issuerKeyHash
,
183 list
= chunk_cat("mm", list
, request
);
185 enumerator
->destroy(enumerator
);
186 chunk_free(&issuerNameHash
);
191 DBG1("creating OCSP request failed, SHA1 not supported");
193 public->destroy(public);
197 DBG1("creating OCSP request failed, CA certificate has no public key");
199 return asn1_wrap(ASN1_SEQUENCE
, "m", list
);
203 * build nonce extension
205 static chunk_t
build_nonce(private_x509_ocsp_request_t
*this)
209 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
212 rng
->allocate_bytes(rng
, NONCE_LEN
, &this->nonce
);
214 return asn1_wrap(ASN1_SEQUENCE
, "cm", ASN1_nonce_oid
,
215 asn1_simple_object(ASN1_OCTET_STRING
, this->nonce
));
217 DBG1("creating OCSP request nonce failed, no RNG found");
222 * build acceptableResponses extension
224 static chunk_t
build_acceptableResponses(private_x509_ocsp_request_t
*this)
226 return asn1_wrap(ASN1_SEQUENCE
, "cc",
228 ASN1_response_content
);
232 * build requestExtensions
234 static chunk_t
build_requestExtensions(private_x509_ocsp_request_t
*this)
236 return asn1_wrap(ASN1_CONTEXT_C_2
, "m",
237 asn1_wrap(ASN1_SEQUENCE
, "mm",
239 build_acceptableResponses(this)));
245 static chunk_t
build_tbsRequest(private_x509_ocsp_request_t
*this)
247 return asn1_wrap(ASN1_SEQUENCE
, "mmm",
248 build_requestorName(this),
249 build_requestList(this),
250 build_requestExtensions(this));
254 * Build the optionalSignature
256 static chunk_t
build_optionalSignature(private_x509_ocsp_request_t
*this,
260 signature_scheme_t scheme
;
261 chunk_t certs
, signature
;
263 switch (this->key
->get_type(this->key
))
265 /* TODO: use a generic mapping function */
267 oid
= OID_SHA1_WITH_RSA
;
268 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
271 oid
= OID_ECDSA_WITH_SHA1
;
272 scheme
= SIGN_ECDSA_WITH_SHA1
;
275 DBG1("unable to sign OCSP request, %N signature not supported",
276 key_type_names
, this->key
->get_type(this->key
));
280 if (!this->key
->sign(this->key
, scheme
, tbsRequest
, &signature
))
282 DBG1("creating OCSP signature failed, skipped");
287 certs
= asn1_wrap(ASN1_CONTEXT_C_0
, "m",
288 asn1_wrap(ASN1_SEQUENCE
, "m",
289 this->cert
->get_encoding(this->cert
)));
291 return asn1_wrap(ASN1_CONTEXT_C_0
, "m",
292 asn1_wrap(ASN1_SEQUENCE
, "cmm",
293 asn1_algorithmIdentifier(oid
),
294 asn1_bitstring("m", signature
),
299 * Build the OCSPRequest data
302 static chunk_t
build_OCSPRequest(private_x509_ocsp_request_t
*this)
304 chunk_t tbsRequest
, optionalSignature
= chunk_empty
;
306 tbsRequest
= build_tbsRequest(this);
309 optionalSignature
= build_optionalSignature(this, tbsRequest
);
311 return asn1_wrap(ASN1_SEQUENCE
, "mm", tbsRequest
, optionalSignature
);
316 * Implementation of certificate_t.get_type
318 static certificate_type_t
get_type(private_x509_ocsp_request_t
*this)
320 return CERT_X509_OCSP_REQUEST
;
324 * Implementation of certificate_t.get_subject
326 static identification_t
* get_subject(private_x509_ocsp_request_t
*this)
328 certificate_t
*ca
= (certificate_t
*)this->ca
;
332 return this->requestor
;
336 return this->cert
->get_subject(this->cert
);
338 return ca
->get_subject(ca
);
342 * Implementation of certificate_t.get_issuer
344 static identification_t
* get_issuer(private_x509_ocsp_request_t
*this)
346 certificate_t
*ca
= (certificate_t
*)this->ca
;
348 return ca
->get_subject(ca
);
352 * Implementation of certificate_t.has_subject.
354 static id_match_t
has_subject(private_x509_ocsp_request_t
*this,
355 identification_t
*subject
)
357 certificate_t
*current
;
358 enumerator_t
*enumerator
;
359 id_match_t match
, best
= ID_MATCH_NONE
;
361 enumerator
= this->candidates
->create_enumerator(this->candidates
);
362 while (enumerator
->enumerate(enumerator
, ¤t
))
364 match
= current
->has_subject(current
, subject
);
370 enumerator
->destroy(enumerator
);
375 * Implementation of certificate_t.has_subject.
377 static id_match_t
has_issuer(private_x509_ocsp_request_t
*this,
378 identification_t
*issuer
)
380 certificate_t
*ca
= (certificate_t
*)this->ca
;
382 return ca
->has_subject(ca
, issuer
);
386 * Implementation of certificate_t.issued_by
388 static bool issued_by(private_x509_ocsp_request_t
*this, certificate_t
*issuer
)
390 DBG1("OCSP request validation not implemented!");
395 * Implementation of certificate_t.get_public_key
397 static public_key_t
* get_public_key(private_x509_ocsp_request_t
*this)
403 * Implementation of x509_cert_t.get_validity.
405 static bool get_validity(private_x509_ocsp_request_t
*this, time_t *when
,
406 time_t *not_before
, time_t *not_after
)
416 cert
= (certificate_t
*)this->ca
;
418 return cert
->get_validity(cert
, when
, not_before
, not_after
);
422 * Implementation of certificate_t.get_encoding.
424 static chunk_t
get_encoding(private_x509_ocsp_request_t
*this)
426 return chunk_clone(this->encoding
);
430 * Implementation of certificate_t.equals.
432 static bool equals(private_x509_ocsp_request_t
*this, certificate_t
*other
)
437 if (this == (private_x509_ocsp_request_t
*)other
)
441 if (other
->get_type(other
) != CERT_X509_OCSP_REQUEST
)
445 if (other
->equals
== (void*)equals
)
446 { /* skip allocation if we have the same implementation */
447 return chunk_equals(this->encoding
, ((private_x509_ocsp_request_t
*)other
)->encoding
);
449 encoding
= other
->get_encoding(other
);
450 equal
= chunk_equals(this->encoding
, encoding
);
456 * Implementation of certificate_t.asdf
458 static private_x509_ocsp_request_t
* get_ref(private_x509_ocsp_request_t
*this)
465 * Implementation of x509_ocsp_request_t.destroy
467 static void destroy(private_x509_ocsp_request_t
*this)
469 if (ref_put(&this->ref
))
471 DESTROY_IF((certificate_t
*)this->ca
);
472 DESTROY_IF(this->requestor
);
473 DESTROY_IF(this->cert
);
474 DESTROY_IF(this->key
);
475 this->candidates
->destroy_offset(this->candidates
, offsetof(certificate_t
, destroy
));
476 chunk_free(&this->nonce
);
477 chunk_free(&this->encoding
);
483 * create an empty but initialized OCSP request
485 static private_x509_ocsp_request_t
*create_empty()
487 private_x509_ocsp_request_t
*this = malloc_thing(private_x509_ocsp_request_t
);
489 this->public.interface
.interface
.get_type
= (certificate_type_t (*)(certificate_t
*this))get_type
;
490 this->public.interface
.interface
.get_subject
= (identification_t
* (*)(certificate_t
*this))get_subject
;
491 this->public.interface
.interface
.get_issuer
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
492 this->public.interface
.interface
.has_subject
= (id_match_t(*)(certificate_t
*, identification_t
*subject
))has_subject
;
493 this->public.interface
.interface
.has_issuer
= (id_match_t(*)(certificate_t
*, identification_t
*issuer
))has_issuer
;
494 this->public.interface
.interface
.issued_by
= (bool (*)(certificate_t
*this, certificate_t
*issuer
))issued_by
;
495 this->public.interface
.interface
.get_public_key
= (public_key_t
* (*)(certificate_t
*this))get_public_key
;
496 this->public.interface
.interface
.get_validity
= (bool(*)(certificate_t
*, time_t *when
, time_t *, time_t*))get_validity
;
497 this->public.interface
.interface
.get_encoding
= (chunk_t(*)(certificate_t
*))get_encoding
;
498 this->public.interface
.interface
.equals
= (bool(*)(certificate_t
*, certificate_t
*other
))equals
;
499 this->public.interface
.interface
.get_ref
= (certificate_t
* (*)(certificate_t
*this))get_ref
;
500 this->public.interface
.interface
.destroy
= (void (*)(certificate_t
*this))destroy
;
503 this->requestor
= NULL
;
506 this->nonce
= chunk_empty
;
507 this->encoding
= chunk_empty
;
508 this->candidates
= linked_list_create();
514 typedef struct private_builder_t private_builder_t
;
516 * Builder implementation for certificate loading
518 struct private_builder_t
{
519 /** implements the builder interface */
521 /** OCSP request to build */
522 private_x509_ocsp_request_t
*req
;
526 * Implementation of builder_t.build
528 static x509_ocsp_request_t
*build(private_builder_t
*this)
530 private_x509_ocsp_request_t
*req
;
536 req
->encoding
= build_OCSPRequest(req
);
544 * Implementation of builder_t.add
546 static void add(private_builder_t
*this, builder_part_t part
, ...)
551 va_start(args
, part
);
555 cert
= va_arg(args
, certificate_t
*);
556 if (cert
->get_type(cert
) == CERT_X509
)
558 this->req
->ca
= (x509_t
*)cert
;
566 cert
= va_arg(args
, certificate_t
*);
567 if (cert
->get_type(cert
) == CERT_X509
)
569 this->req
->candidates
->insert_last(this->req
->candidates
, cert
);
576 case BUILD_SIGNING_CERT
:
577 this->req
->cert
= va_arg(args
, certificate_t
*);
579 case BUILD_SIGNING_KEY
:
580 this->req
->key
= va_arg(args
, private_key_t
*);
583 this->req
->requestor
= va_arg(args
, identification_t
*);
586 DBG1("ignoring unsupported build part %N", builder_part_names
, part
);
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;