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/randomizer.h>
27 #include <utils/linked_list.h>
29 #include <credentials/certificates/x509.h>
33 typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t
;
36 * private data of x509_ocsp_request
38 struct private_x509_ocsp_request_t
{
43 x509_ocsp_request_t
public;
46 * CA the candidates belong to
51 * Requestor name, subject of cert used if not set
53 identification_t
*requestor
;
56 * Requestor certificate, included in request
61 * Requestor private key to sign request
66 * list of certificates to check, x509_t
68 linked_list_t
*candidates
;
71 * nonce used in request
76 * encoded OCSP request
86 static u_char ASN1_nonce_oid_str
[] = {
89 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
92 static u_char ASN1_response_oid_str
[] = {
95 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
98 static u_char ASN1_response_content_str
[] = {
103 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
106 static const chunk_t ASN1_nonce_oid
= chunk_from_buf(ASN1_nonce_oid_str
);
107 static const chunk_t ASN1_response_oid
= chunk_from_buf(ASN1_response_oid_str
);
108 static const chunk_t ASN1_response_content
= chunk_from_buf(ASN1_response_content_str
);
111 * build requestorName
113 static chunk_t
build_requestorName(private_x509_ocsp_request_t
*this)
115 if (this->requestor
|| this->cert
)
116 { /* use requestor name, fallback to his cert subject */
117 if (!this->requestor
)
119 this->requestor
= this->cert
->get_subject(this->cert
);
120 this->requestor
= this->requestor
->clone(this->requestor
);
122 return asn1_wrap(ASN1_CONTEXT_C_1
, "m",
123 asn1_simple_object(ASN1_CONTEXT_C_4
,
124 this->requestor
->get_encoding(this->requestor
)));
131 * build Request, not using singleRequestExtensions
133 static chunk_t
build_Request(private_x509_ocsp_request_t
*this,
134 chunk_t issuerNameHash
, chunk_t issuerKeyHash
,
135 chunk_t serialNumber
)
137 return asn1_wrap(ASN1_SEQUENCE
, "m",
138 asn1_wrap(ASN1_SEQUENCE
, "cmmm",
139 asn1_algorithmIdentifier(OID_SHA1
),
140 asn1_simple_object(ASN1_OCTET_STRING
, issuerNameHash
),
141 asn1_simple_object(ASN1_OCTET_STRING
, issuerKeyHash
),
142 asn1_simple_object(ASN1_INTEGER
, serialNumber
)));
148 static chunk_t
build_requestList(private_x509_ocsp_request_t
*this)
150 chunk_t issuerNameHash
, issuerKeyHash
;
151 identification_t
*issuer
;
154 chunk_t list
= chunk_empty
;
155 public_key_t
*public;
157 cert
= (certificate_t
*)this->ca
;
158 public = cert
->get_public_key(cert
);
161 hasher_t
*hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
164 identification_t
*keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
167 enumerator_t
*enumerator
;
169 issuerKeyHash
= keyid
->get_encoding(keyid
);
171 issuer
= cert
->get_subject(cert
);
172 hasher
->allocate_hash(hasher
, issuer
->get_encoding(issuer
),
174 hasher
->destroy(hasher
);
176 enumerator
= this->candidates
->create_enumerator(this->candidates
);
177 while (enumerator
->enumerate(enumerator
, &x509
))
179 chunk_t request
, serialNumber
;
181 serialNumber
= x509
->get_serial(x509
);
182 request
= build_Request(this, issuerNameHash
, issuerKeyHash
,
184 list
= chunk_cat("mm", list
, request
);
186 enumerator
->destroy(enumerator
);
187 chunk_free(&issuerNameHash
);
192 DBG1("creating OCSP request failed, SHA1 not supported");
194 public->destroy(public);
198 DBG1("creating OCSP request failed, CA certificate has no public key");
200 return asn1_wrap(ASN1_SEQUENCE
, "m", list
);
204 * build nonce extension
206 static chunk_t
build_nonce(private_x509_ocsp_request_t
*this)
208 randomizer_t
*randomizer
;
210 randomizer
= randomizer_create();
211 randomizer
->allocate_pseudo_random_bytes(randomizer
, NONCE_LEN
, &this->nonce
);
212 randomizer
->destroy(randomizer
);
214 return asn1_wrap(ASN1_SEQUENCE
, "cm", ASN1_nonce_oid
,
215 asn1_simple_object(ASN1_OCTET_STRING
, this->nonce
));
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 DBG1("unable to sign OCSP request, %N signature not supported",
269 key_type_names
, this->key
->get_type(this->key
));
273 if (!this->key
->sign(this->key
, scheme
, tbsRequest
, &signature
))
275 DBG1("creating OCSP signature failed, skipped");
280 certs
= asn1_wrap(ASN1_CONTEXT_C_0
, "m",
281 asn1_wrap(ASN1_SEQUENCE
, "m",
282 this->cert
->get_encoding(this->cert
)));
284 return asn1_wrap(ASN1_CONTEXT_C_0
, "m",
285 asn1_wrap(ASN1_SEQUENCE
, "cmm",
286 asn1_algorithmIdentifier(oid
),
287 asn1_bitstring("m", signature
),
292 * Build the OCSPRequest data
295 static chunk_t
build_OCSPRequest(private_x509_ocsp_request_t
*this)
297 chunk_t tbsRequest
, optionalSignature
= chunk_empty
;
299 tbsRequest
= build_tbsRequest(this);
302 optionalSignature
= build_optionalSignature(this, tbsRequest
);
304 return asn1_wrap(ASN1_SEQUENCE
, "mm", tbsRequest
, optionalSignature
);
309 * Implementation of certificate_t.get_type
311 static certificate_type_t
get_type(private_x509_ocsp_request_t
*this)
313 return CERT_X509_OCSP_REQUEST
;
317 * Implementation of certificate_t.get_subject
319 static identification_t
* get_subject(private_x509_ocsp_request_t
*this)
321 certificate_t
*ca
= (certificate_t
*)this->ca
;
325 return this->requestor
;
329 return this->cert
->get_subject(this->cert
);
331 return ca
->get_subject(ca
);
335 * Implementation of certificate_t.get_issuer
337 static identification_t
* get_issuer(private_x509_ocsp_request_t
*this)
339 certificate_t
*ca
= (certificate_t
*)this->ca
;
341 return ca
->get_subject(ca
);
345 * Implementation of certificate_t.has_subject.
347 static id_match_t
has_subject(private_x509_ocsp_request_t
*this,
348 identification_t
*subject
)
350 certificate_t
*current
;
351 enumerator_t
*enumerator
;
352 id_match_t match
, best
= ID_MATCH_NONE
;
354 enumerator
= this->candidates
->create_enumerator(this->candidates
);
355 while (enumerator
->enumerate(enumerator
, ¤t
))
357 match
= current
->has_subject(current
, subject
);
363 enumerator
->destroy(enumerator
);
368 * Implementation of certificate_t.has_subject.
370 static id_match_t
has_issuer(private_x509_ocsp_request_t
*this,
371 identification_t
*issuer
)
373 certificate_t
*ca
= (certificate_t
*)this->ca
;
375 return ca
->has_subject(ca
, issuer
);
379 * Implementation of certificate_t.issued_by
381 static bool issued_by(private_x509_ocsp_request_t
*this, certificate_t
*issuer
,
384 DBG1("OCSP request validation not implemented!");
389 * Implementation of certificate_t.get_public_key
391 static public_key_t
* get_public_key(private_x509_ocsp_request_t
*this)
397 * Implementation of x509_cert_t.get_validity.
399 static bool get_validity(private_x509_ocsp_request_t
*this, time_t *when
,
400 time_t *not_before
, time_t *not_after
)
410 cert
= (certificate_t
*)this->ca
;
412 return cert
->get_validity(cert
, when
, not_before
, not_after
);
416 * Implementation of certificate_t.get_encoding.
418 static chunk_t
get_encoding(private_x509_ocsp_request_t
*this)
420 return chunk_clone(this->encoding
);
424 * Implementation of certificate_t.equals.
426 static bool equals(private_x509_ocsp_request_t
*this, certificate_t
*other
)
428 if (this == (private_x509_ocsp_request_t
*)other
)
432 if (other
->get_type(other
) != CERT_X509_OCSP_REQUEST
)
436 /* check if we have the same X509 implementation */
437 if (other
->equals
== (void*)equals
)
439 return chunk_equals(this->encoding
,
440 ((private_x509_ocsp_request_t
*)other
)->encoding
);
442 /* TODO: compare against other implementation */
447 * Implementation of certificate_t.asdf
449 static private_x509_ocsp_request_t
* get_ref(private_x509_ocsp_request_t
*this)
456 * Implementation of x509_ocsp_request_t.destroy
458 static void destroy(private_x509_ocsp_request_t
*this)
460 if (ref_put(&this->ref
))
462 DESTROY_IF((certificate_t
*)this->ca
);
463 DESTROY_IF(this->requestor
);
464 DESTROY_IF(this->cert
);
465 DESTROY_IF(this->key
);
466 this->candidates
->destroy_offset(this->candidates
, offsetof(certificate_t
, destroy
));
467 chunk_free(&this->nonce
);
468 chunk_free(&this->encoding
);
474 * create an empty but initialized OCSP request
476 static private_x509_ocsp_request_t
*create_empty()
478 private_x509_ocsp_request_t
*this = malloc_thing(private_x509_ocsp_request_t
);
480 this->public.interface
.interface
.get_type
= (certificate_type_t (*)(certificate_t
*this))get_type
;
481 this->public.interface
.interface
.get_subject
= (identification_t
* (*)(certificate_t
*this))get_subject
;
482 this->public.interface
.interface
.get_issuer
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
483 this->public.interface
.interface
.has_subject
= (id_match_t(*)(certificate_t
*, identification_t
*subject
))has_subject
;
484 this->public.interface
.interface
.has_issuer
= (id_match_t(*)(certificate_t
*, identification_t
*issuer
))has_issuer
;
485 this->public.interface
.interface
.issued_by
= (bool (*)(certificate_t
*this, certificate_t
*issuer
,bool))issued_by
;
486 this->public.interface
.interface
.get_public_key
= (public_key_t
* (*)(certificate_t
*this))get_public_key
;
487 this->public.interface
.interface
.get_validity
= (bool(*)(certificate_t
*, time_t *when
, time_t *, time_t*))get_validity
;
488 this->public.interface
.interface
.get_encoding
= (chunk_t(*)(certificate_t
*))get_encoding
;
489 this->public.interface
.interface
.equals
= (bool(*)(certificate_t
*, certificate_t
*other
))equals
;
490 this->public.interface
.interface
.get_ref
= (certificate_t
* (*)(certificate_t
*this))get_ref
;
491 this->public.interface
.interface
.destroy
= (void (*)(certificate_t
*this))destroy
;
494 this->requestor
= NULL
;
497 this->nonce
= chunk_empty
;
498 this->encoding
= chunk_empty
;
499 this->candidates
= linked_list_create();
505 typedef struct private_builder_t private_builder_t
;
507 * Builder implementation for certificate loading
509 struct private_builder_t
{
510 /** implements the builder interface */
512 /** OCSP request to build */
513 private_x509_ocsp_request_t
*req
;
517 * Implementation of builder_t.build
519 static x509_ocsp_request_t
*build(private_builder_t
*this)
521 private_x509_ocsp_request_t
*req
;
527 req
->encoding
= build_OCSPRequest(req
);
535 * Implementation of builder_t.add
537 static void add(private_builder_t
*this, builder_part_t part
, ...)
542 va_start(args
, part
);
546 cert
= va_arg(args
, certificate_t
*);
547 if (cert
->get_type(cert
) == CERT_X509
)
549 this->req
->ca
= (x509_t
*)cert
;
557 cert
= va_arg(args
, certificate_t
*);
558 if (cert
->get_type(cert
) == CERT_X509
)
560 this->req
->candidates
->insert_last(this->req
->candidates
, cert
);
567 case BUILD_SIGNING_CERT
:
568 this->req
->cert
= va_arg(args
, certificate_t
*);
570 case BUILD_SIGNING_KEY
:
571 this->req
->key
= va_arg(args
, private_key_t
*);
574 this->req
->requestor
= va_arg(args
, identification_t
*);
577 DBG1("ignoring unsupported build part %N", builder_part_names
, part
);
584 * Builder construction function
586 builder_t
*x509_ocsp_request_builder(certificate_type_t type
)
588 private_builder_t
*this;
590 if (type
!= CERT_X509_OCSP_REQUEST
)
595 this = malloc_thing(private_builder_t
);
597 this->req
= create_empty();
598 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
599 this->public.build
= (void*(*)(builder_t
*this))build
;
601 return &this->public;