Updated x509 plugin to the new builder API
[strongswan.git] / src / libstrongswan / plugins / x509 / x509_ocsp_request.c
index ce77359..e0d9905 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
  * Copyright (C) 2007 Andreas Steffen
  * Hochschule fuer Technik Rapperswil
  * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
@@ -13,8 +13,6 @@
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
- *
- * $Id$
  */
 
 #include "x509_ocsp_request.h"
 #include <asn1/oid.h>
 #include <asn1/asn1.h>
 #include <utils/identification.h>
-#include <utils/randomizer.h>
 #include <utils/linked_list.h>
 #include <debug.h>
 #include <credentials/certificates/x509.h>
+#include <credentials/keys/private_key.h>
 
 #define NONCE_LEN              16
 
@@ -41,12 +39,12 @@ struct private_x509_ocsp_request_t {
         * public functions
         */
        x509_ocsp_request_t public;
-       
+
        /**
         * CA the candidates belong to
         */
        x509_t *ca;
-       
+
        /**
         * Requestor name, subject of cert used if not set
         */
@@ -56,27 +54,27 @@ struct private_x509_ocsp_request_t {
         * Requestor certificate, included in request
         */
        certificate_t *cert;
-       
+
        /**
         * Requestor private key to sign request
         */
        private_key_t *key;
-       
+
        /**
         * list of certificates to check, x509_t
         */
        linked_list_t *candidates;
-       
+
        /**
         * nonce used in request
         */
        chunk_t nonce;
-       
+
        /**
         * encoded OCSP request
         */
        chunk_t encoding;
-       
+
        /**
         * reference count
         */
@@ -122,7 +120,7 @@ static chunk_t build_requestorName(private_x509_ocsp_request_t *this)
                return asn1_wrap(ASN1_CONTEXT_C_1, "m",
                                        asn1_simple_object(ASN1_CONTEXT_C_4,
                                                this->requestor->get_encoding(this->requestor)));
-       
+
        }
        return chunk_empty;
 }
@@ -135,7 +133,7 @@ static chunk_t build_Request(private_x509_ocsp_request_t *this,
                                                         chunk_t serialNumber)
 {
        return asn1_wrap(ASN1_SEQUENCE, "m",
-                               asn1_wrap(ASN1_SEQUENCE, "cmmm",
+                               asn1_wrap(ASN1_SEQUENCE, "mmmm",
                                        asn1_algorithmIdentifier(OID_SHA1),
                                        asn1_simple_object(ASN1_OCTET_STRING, issuerNameHash),
                                        asn1_simple_object(ASN1_OCTET_STRING, issuerKeyHash),
@@ -153,7 +151,7 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
        certificate_t *cert;
        chunk_t list = chunk_empty;
        public_key_t *public;
-       
+
        cert = (certificate_t*)this->ca;
        public = cert->get_public_key(cert);
        if (public)
@@ -161,23 +159,21 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
                hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                if (hasher)
                {
-                       identification_t *keyid = public->get_id(public, ID_PUBKEY_SHA1);       
-                       if (keyid)
+                       if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1,
+                                                                               &issuerKeyHash))
                        {
                                enumerator_t *enumerator;
-                       
-                               issuerKeyHash = keyid->get_encoding(keyid);
-               
+
                                issuer = cert->get_subject(cert);
                                hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
                                                                          &issuerNameHash);
                                hasher->destroy(hasher);
-       
+
                                enumerator = this->candidates->create_enumerator(this->candidates);
                                while (enumerator->enumerate(enumerator, &x509))
                                {
                                        chunk_t request, serialNumber;
-                       
+
                                        serialNumber = x509->get_serial(x509);
                                        request = build_Request(this, issuerNameHash, issuerKeyHash,
                                                                                        serialNumber);
@@ -205,14 +201,18 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
  */
 static chunk_t build_nonce(private_x509_ocsp_request_t *this)
 {
-       randomizer_t *randomizer;
-       
-       randomizer = randomizer_create();
-       randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, &this->nonce);
-       randomizer->destroy(randomizer);
-       
-    return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
-                               asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
+       rng_t *rng;
+
+       rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+       if (rng)
+       {
+               rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+               rng->destroy(rng);
+               return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
+                                       asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
+       }
+       DBG1("creating OCSP request nonce failed, no RNG found");
+       return chunk_empty;
 }
 
 /**
@@ -230,7 +230,7 @@ static chunk_t build_acceptableResponses(private_x509_ocsp_request_t *this)
  */
 static chunk_t build_requestExtensions(private_x509_ocsp_request_t *this)
 {
-    return asn1_wrap(ASN1_CONTEXT_C_2, "m",
+       return asn1_wrap(ASN1_CONTEXT_C_2, "m",
                                asn1_wrap(ASN1_SEQUENCE, "mm",
                                        build_nonce(this),
                                        build_acceptableResponses(this)));
@@ -256,7 +256,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
        int oid;
        signature_scheme_t scheme;
        chunk_t certs, signature;
-       
+
        switch (this->key->get_type(this->key))
        {
                /* TODO: use a generic mapping function */
@@ -264,12 +264,16 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
                        oid = OID_SHA1_WITH_RSA;
                        scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
                        break;
+               case KEY_ECDSA:
+                       oid = OID_ECDSA_WITH_SHA1;
+                       scheme = SIGN_ECDSA_WITH_SHA1_DER;
+                       break;
                default:
                        DBG1("unable to sign OCSP request, %N signature not supported",
                                 key_type_names, this->key->get_type(this->key));
                        return chunk_empty;
        }
-       
+
        if (!this->key->sign(this->key, scheme, tbsRequest, &signature))
        {
                DBG1("creating OCSP signature failed, skipped");
@@ -282,7 +286,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
                                                this->cert->get_encoding(this->cert)));
        }
        return asn1_wrap(ASN1_CONTEXT_C_0, "m",
-                               asn1_wrap(ASN1_SEQUENCE, "cmm", 
+                               asn1_wrap(ASN1_SEQUENCE, "cmm",
                                        asn1_algorithmIdentifier(oid),
                                        asn1_bitstring("m", signature),
                                        certs));
@@ -295,7 +299,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
 static chunk_t build_OCSPRequest(private_x509_ocsp_request_t *this)
 {
        chunk_t tbsRequest, optionalSignature = chunk_empty;
-       
+
        tbsRequest = build_tbsRequest(this);
        if (this->key)
        {
@@ -319,7 +323,7 @@ static certificate_type_t get_type(private_x509_ocsp_request_t *this)
 static identification_t* get_subject(private_x509_ocsp_request_t *this)
 {
        certificate_t *ca = (certificate_t*)this->ca;
-       
+
        if (this->requestor)
        {
                return this->requestor;
@@ -337,7 +341,7 @@ static identification_t* get_subject(private_x509_ocsp_request_t *this)
 static identification_t* get_issuer(private_x509_ocsp_request_t *this)
 {
        certificate_t *ca = (certificate_t*)this->ca;
-       
+
        return ca->get_subject(ca);
 }
 
@@ -357,11 +361,11 @@ static id_match_t has_subject(private_x509_ocsp_request_t *this,
                match = current->has_subject(current, subject);
                if (match > best)
                {
-                       best = match;   
+                       best = match;
                }
        }
        enumerator->destroy(enumerator);
-       return best;    
+       return best;
 }
 
 /**
@@ -410,7 +414,7 @@ static bool get_validity(private_x509_ocsp_request_t *this, time_t *when,
        }
        return cert->get_validity(cert, when, not_before, not_after);
 }
-       
+
 /**
  * Implementation of certificate_t.get_encoding.
  */
@@ -426,7 +430,7 @@ static bool equals(private_x509_ocsp_request_t *this, certificate_t *other)
 {
        chunk_t encoding;
        bool equal;
-       
+
        if (this == (private_x509_ocsp_request_t*)other)
        {
                return TRUE;
@@ -437,7 +441,7 @@ static bool equals(private_x509_ocsp_request_t *this, certificate_t *other)
        }
        if (other->equals == (void*)equals)
        {       /* skip allocation if we have the same implementation */
-               return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding); 
+               return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding);
        }
        encoding = other->get_encoding(other);
        equal = chunk_equals(this->encoding, encoding);
@@ -478,7 +482,7 @@ static void destroy(private_x509_ocsp_request_t *this)
 static private_x509_ocsp_request_t *create_empty()
 {
        private_x509_ocsp_request_t *this = malloc_thing(private_x509_ocsp_request_t);
-       
+
        this->public.interface.interface.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
        this->public.interface.interface.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
        this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
@@ -491,7 +495,7 @@ static private_x509_ocsp_request_t *create_empty()
        this->public.interface.interface.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
        this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
        this->public.interface.interface.destroy = (void (*)(certificate_t *this))destroy;
-       
+
        this->ca = NULL;
        this->requestor = NULL;
        this->cert = NULL;
@@ -500,30 +504,60 @@ static private_x509_ocsp_request_t *create_empty()
        this->encoding = chunk_empty;
        this->candidates = linked_list_create();
        this->ref = 1;
-       
+
        return this;
 }
 
-typedef struct private_builder_t private_builder_t;
 /**
- * Builder implementation for certificate loading
+ * See header.
  */
-struct private_builder_t {
-       /** implements the builder interface */
-       builder_t public;
-       /** OCSP request to build */
-       private_x509_ocsp_request_t *req;
-};
-
-/**
- * Implementation of builder_t.build
- */
-static x509_ocsp_request_t *build(private_builder_t *this)
+x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args)
 {
        private_x509_ocsp_request_t *req;
-       
-       req = this->req;
-       free(this);
+       certificate_t *cert;
+       private_key_t *private;
+       identification_t *subject;
+
+       req = create_empty();
+       while (TRUE)
+       {
+               switch (va_arg(args, builder_part_t))
+               {
+                       case BUILD_CA_CERT:
+                               cert = va_arg(args, certificate_t*);
+                               if (cert->get_type(cert) == CERT_X509)
+                               {
+                                       req->ca = (x509_t*)cert->get_ref(cert);
+                               }
+                               continue;
+                       case BUILD_CERT:
+                               cert = va_arg(args, certificate_t*);
+                               if (cert->get_type(cert) == CERT_X509)
+                               {
+                                       req->candidates->insert_last(req->candidates,
+                                                                                                cert->get_ref(cert));
+                               }
+                               continue;
+                       case BUILD_SIGNING_CERT:
+                               cert = va_arg(args, certificate_t*);
+                               req->cert = cert->get_ref(cert);
+                               continue;
+                       case BUILD_SIGNING_KEY:
+                               private = va_arg(args, private_key_t*);
+                               req->key = private->get_ref(private);
+                               continue;
+                       case BUILD_SUBJECT:
+                               subject = va_arg(args, identification_t*);
+                               req->requestor = subject->clone(subject);
+                               continue;
+                       case BUILD_END:
+                               break;
+                       default:
+                               destroy(req);
+                               return NULL;
+               }
+               break;
+       }
        if (req->ca)
        {
                req->encoding = build_OCSPRequest(req);
@@ -533,73 +567,3 @@ static x509_ocsp_request_t *build(private_builder_t *this)
        return NULL;
 }
 
-/**
- * Implementation of builder_t.add
- */
-static void add(private_builder_t *this, builder_part_t part, ...)
-{
-       va_list args;
-       certificate_t *cert;
-       
-       va_start(args, part);
-       switch (part)
-       {
-               case BUILD_CA_CERT:
-                       cert = va_arg(args, certificate_t*);
-                       if (cert->get_type(cert) == CERT_X509)
-                       {
-                               this->req->ca = (x509_t*)cert;
-                       }
-                       else
-                       {
-                               cert->destroy(cert);
-                       }
-                       break;
-               case BUILD_CERT:
-                       cert = va_arg(args, certificate_t*);
-                       if (cert->get_type(cert) == CERT_X509)
-                       {
-                               this->req->candidates->insert_last(this->req->candidates, cert);
-                       }
-                       else
-                       {
-                               cert->destroy(cert);
-                       }
-                       break;
-               case BUILD_SIGNING_CERT:
-                       this->req->cert = va_arg(args, certificate_t*);
-                       break;
-               case BUILD_SIGNING_KEY:
-                       this->req->key = va_arg(args, private_key_t*);
-                       break;
-               case BUILD_SUBJECT:
-                       this->req->requestor = va_arg(args, identification_t*);
-                       break;
-               default:
-                       DBG1("ignoring unsupported build part %N", builder_part_names, part);
-                       break;
-       }
-       va_end(args);
-}
-
-/**
- * Builder construction function
- */
-builder_t *x509_ocsp_request_builder(certificate_type_t type)
-{
-       private_builder_t *this;
-       
-       if (type != CERT_X509_OCSP_REQUEST)
-       {
-               return NULL;
-       }
-       
-       this = malloc_thing(private_builder_t);
-       
-       this->req = create_empty();
-       this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
-       this->public.build = (void*(*)(builder_t *this))build;
-       
-       return &this->public;
-}
-