botan: Fixes, code style changes plus some refactorings
authorTobias Brunner <tobias@strongswan.org>
Mon, 6 Aug 2018 15:46:54 +0000 (17:46 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 12 Sep 2018 14:25:00 +0000 (16:25 +0200)
Some changes rely on newly added FFI functions in Botan's master
branch.

19 files changed:
src/libstrongswan/plugins/botan/Makefile.am
src/libstrongswan/plugins/botan/botan_crypter.c
src/libstrongswan/plugins/botan/botan_diffie_hellman.c
src/libstrongswan/plugins/botan/botan_diffie_hellman.h
src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.c
src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.h
src/libstrongswan/plugins/botan/botan_ec_private_key.c
src/libstrongswan/plugins/botan/botan_ec_private_key.h
src/libstrongswan/plugins/botan/botan_ec_public_key.c
src/libstrongswan/plugins/botan/botan_gcm.c
src/libstrongswan/plugins/botan/botan_gcm.h
src/libstrongswan/plugins/botan/botan_hasher.c
src/libstrongswan/plugins/botan/botan_hmac.c
src/libstrongswan/plugins/botan/botan_plugin.c
src/libstrongswan/plugins/botan/botan_rng.c
src/libstrongswan/plugins/botan/botan_rsa_private_key.c
src/libstrongswan/plugins/botan/botan_rsa_public_key.c
src/libstrongswan/plugins/botan/botan_util.c
src/libstrongswan/plugins/botan/botan_util.h

index 95df441..bbad715 100644 (file)
@@ -23,7 +23,7 @@ libstrongswan_botan_la_SOURCES = \
        botan_ec_diffie_hellman.h botan_ec_diffie_hellman.c \
        botan_ec_public_key.h botan_ec_public_key.c \
        botan_ec_private_key.h botan_ec_private_key.c \
-       botan_util.c \
+       botan_util.h botan_util.c \
        botan_gcm.h botan_gcm.c
 
 libstrongswan_botan_la_LDFLAGS = -module -avoid-version
index af8fe4c..002be6e 100644 (file)
@@ -65,7 +65,7 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
        in = data.ptr;
        if (dst)
        {
-               *dst= chunk_alloc(data.len);
+               *dst = chunk_alloc(data.len);
                out = dst->ptr;
        }
        else
@@ -77,13 +77,13 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
        {
                return FALSE;
        }
-       
-       if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len)
-               && !botan_cipher_start(cipher, iv.ptr, iv.len)
-               && !botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out,
-                                                          data.len, &output_written, in, data.len,
-                                                          &input_consumed)
-               && (output_written == input_consumed))
+
+       if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len) &&
+               !botan_cipher_start(cipher, iv.ptr, iv.len) &&
+               !botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out,
+                                                        data.len, &output_written, in, data.len,
+                                                        &input_consumed) &&
+               (output_written == input_consumed))
        {
                success = TRUE;
        }
@@ -93,38 +93,38 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
 }
 
 METHOD(crypter_t, decrypt, bool,
-               private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
+       private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
 {
        return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT);
 }
 
 
 METHOD(crypter_t, encrypt, bool,
-               private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
+       private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
 {
        return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
 }
 
 METHOD(crypter_t, get_block_size, size_t,
-               private_botan_crypter_t *this)
+       private_botan_crypter_t *this)
 {
        return AES_BLOCK_SIZE;
 }
 
 METHOD(crypter_t, get_iv_size, size_t,
-               private_botan_crypter_t *this)
+       private_botan_crypter_t *this)
 {
        return AES_BLOCK_SIZE;
 }
 
 METHOD(crypter_t, get_key_size, size_t,
-               private_botan_crypter_t *this)
+       private_botan_crypter_t *this)
 {
        return this->key.len;
 }
 
 METHOD(crypter_t, set_key, bool,
-               private_botan_crypter_t *this, chunk_t key)
+       private_botan_crypter_t *this, chunk_t key)
 {
        memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
        return TRUE;
@@ -159,7 +159,6 @@ botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
                },
        );
 
-
        switch (algo)
        {
                case ENCR_AES_CBC:
@@ -183,11 +182,8 @@ botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
                        }
                        break;
                default:
-               {
                        free(this);
                        return NULL;
-
-               }
        }
 
        this->key = chunk_alloc(key_size);
index 2ca14f3..422b4ae 100644 (file)
@@ -70,22 +70,27 @@ struct private_botan_diffie_hellman_t {
         * Modulus
         */
        botan_mp_t p;
-
 };
 
+/**
+ * Load a DH private key
+ */
 bool load_private_key(private_botan_diffie_hellman_t *this, chunk_t value)
 {
        botan_mp_t xa;
-       if (chunk_to_botan_mp(value, &xa))
+
+       if (!chunk_to_botan_mp(value, &xa))
        {
                return FALSE;
        }
 
        if (botan_privkey_destroy(this->dh_key) ||
-               botan_privkey_load_dh (&this->dh_key, this->p, this->g, xa))
+               botan_privkey_load_dh(&this->dh_key, this->p, this->g, xa))
        {
+               botan_mp_destroy(xa);
                return FALSE;
        }
+       botan_mp_destroy(xa);
        return TRUE;
 }
 
@@ -99,25 +104,29 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
                return FALSE;
        }
 
+       if (botan_pk_op_key_agreement_create(&op, this->dh_key, "Raw", 0))
+       {
+               return FALSE;
+       }
+
        chunk_clear(&this->shared_secret);
-       botan_pk_op_key_agreement_create(&op, this->dh_key, "Raw", 0);
 
-       /* get shared secret key size */
-       if (botan_pk_op_key_agreement(op, NULL, &this->shared_secret.len, value.ptr,
-                                     value.len, NULL, 0)
-           != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+       if (botan_pk_op_key_agreement_size(op, &this->shared_secret.len))
        {
+               botan_pk_op_key_agreement_destroy(op);
                return FALSE;
        }
 
        this->shared_secret = chunk_alloc(this->shared_secret.len);
        if (botan_pk_op_key_agreement(op, this->shared_secret.ptr,
-                                     &this->shared_secret.len, value.ptr,
-                                     value.len, NULL, 0))
+                                                                 &this->shared_secret.len, value.ptr,
+                                                                 value.len, NULL, 0))
        {
+               chunk_clear(&this->shared_secret);
+               botan_pk_op_key_agreement_destroy(op);
                return FALSE;
        }
-
+       botan_pk_op_key_agreement_destroy(op);
        return TRUE;
 }
 
@@ -128,36 +137,35 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
 
        /* get key size of public key first */
        if (botan_pk_op_key_agreement_export_public(this->dh_key, NULL, &value->len)
-           != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
        {
                return FALSE;
        }
 
        *value = chunk_alloc(value->len);
        if (botan_pk_op_key_agreement_export_public(this->dh_key, value->ptr,
-                                                   &value->len))
+                                                                                               &value->len))
        {
                chunk_clear(value);
                return FALSE;
        }
-
        return TRUE;
 }
 
 METHOD(diffie_hellman_t, set_private_value, bool,
        private_botan_diffie_hellman_t *this, chunk_t value)
 {
+       chunk_clear(&this->shared_secret);
        return load_private_key(this, value);
 }
 
 METHOD(diffie_hellman_t, get_shared_secret, bool,
        private_botan_diffie_hellman_t *this, chunk_t *secret)
 {
-       if (this->shared_secret.len == 0)
+       if (!this->shared_secret.len)
        {
                return FALSE;
        }
-
        *secret = chunk_clone(this->shared_secret);
        return TRUE;
 }
@@ -181,10 +189,12 @@ METHOD(diffie_hellman_t, destroy, void,
 /*
  * Generic internal constructor
  */
-botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
-                                                       chunk_t g, chunk_t p)
+static botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
+                                                                               chunk_t g, chunk_t p, size_t exp_len)
 {
        private_botan_diffie_hellman_t *this;
+       chunk_t random;
+       rng_t *rng;
 
        INIT(this,
                .public = {
@@ -200,42 +210,52 @@ botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
                .group = group,
        );
 
-       if (chunk_to_botan_mp(p, &this->p))
+       if (!chunk_to_botan_mp(p, &this->p))
        {
                destroy(this);
                return NULL;
        }
 
-       if (chunk_to_botan_mp(g, &this->g))
+       if (!chunk_to_botan_mp(g, &this->g))
        {
                destroy(this);
                return NULL;
        }
 
-       chunk_t random;
-       rng_t *rng;
        rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
-       if (rng && rng->allocate_bytes(rng, p.len, &random))
+       if (!rng || !rng->allocate_bytes(rng, p.len, &random))
        {
-               rng->destroy(rng);
-               if (!load_private_key(this, random))
-               {
-                       destroy(this);
-                       chunk_clear(&random);
-                       return NULL;
-               }
+               DESTROY_IF(rng);
+               destroy(this);
+               return NULL;
        }
+       rng->destroy(rng);
 
+       if (!load_private_key(this, random))
+       {
+               chunk_clear(&random);
+               destroy(this);
+               return NULL;
+       }
+       chunk_clear(&random);
        return &this->public;
 }
 
 /*
  * Described in header.
  */
-botan_diffie_hellman_t *
-botan_diffie_hellman_create(diffie_hellman_group_t group)
+botan_diffie_hellman_t *botan_diffie_hellman_create(
+                                                                                       diffie_hellman_group_t group, ...)
 {
        diffie_hellman_params_t *params;
+       chunk_t g, p;
+
+       if (group == MODP_CUSTOM)
+       {
+               VA_ARGS_GET(group, g, p);
+               return create_generic(group, g, p);
+       }
+
        params = diffie_hellman_get_params(group);
        if (!params)
        {
@@ -244,18 +264,4 @@ botan_diffie_hellman_create(diffie_hellman_group_t group)
        return create_generic(group, params->generator, params->prime);
 }
 
-/*
- * Described in header.
- */
-botan_diffie_hellman_t *
-botan_diffie_hellman_create_custom(diffie_hellman_group_t group, chunk_t g,
-                                                                  chunk_t p)
-{
-       if (group == MODP_CUSTOM)
-       {
-               return create_generic(group, g, p);
-       }
-       return NULL;
-}
-
 #endif
index 88f221d..8440822 100644 (file)
@@ -49,24 +49,11 @@ struct botan_diffie_hellman_t {
  * Creates a new botan_diffie_hellman_t object.
  *
  * @param group                        Diffie Hellman group number to use
+ * @param ...                  expects generator and prime as chunk_t if MODP_CUSTOM
  * @return                             botan_diffie_hellman_t object,
  *                                             NULL if not supported
  */
-botan_diffie_hellman_t *
-botan_diffie_hellman_create(diffie_hellman_group_t group);
-
-/**
- * Creates a new botan_diffie_hellman_t object for MODP_CUSTOM.
- *
- * @param group                        MODP_CUSTOM
- * @param g                            generator
- * @param p                            prime
- * @return                             botan_diffie_hellman_t object,
- *                                             NULL if not supported
- */
-botan_diffie_hellman_t *
-botan_diffie_hellman_create_custom(diffie_hellman_group_t group, chunk_t g,
-                                                                  chunk_t p);
+botan_diffie_hellman_t *botan_diffie_hellman_create(
+                                                                                       diffie_hellman_group_t group, ...);
 
 #endif /** BOTAN_DIFFIE_HELLMAN_H_ @}*/
-
index 48b231f..a482bc0 100644 (file)
 
 #ifdef BOTAN_HAS_ECDH
 
+#include "botan_util.h"
+
 #include <utils/debug.h>
 
 #include <botan/ffi.h>
 
-typedef struct private_botan_ec_diffie_hellman_t
-       private_botan_ec_diffie_hellman_t;
+typedef struct private_botan_ec_diffie_hellman_t private_botan_ec_diffie_hellman_t;
 
 /**
  * Private data of a botan_ec_diffie_hellman_t object.
  */
 struct private_botan_ec_diffie_hellman_t {
+
        /**
-        * Public botan_ec_diffie_hellman_t interface
+        * Public interface
         */
        botan_ec_diffie_hellman_t public;
 
@@ -62,47 +64,35 @@ struct private_botan_ec_diffie_hellman_t {
         * Shared secret
         */
        chunk_t shared_secret;
-
-       /**
-        * True if shared secret is computed
-        */
-       bool computed;
 };
 
 METHOD(diffie_hellman_t, set_other_public_value, bool,
        private_botan_ec_diffie_hellman_t *this, chunk_t value)
 {
+       botan_pk_op_ka_t ka;
+
        if (!diffie_hellman_verify_value(this->group, value))
        {
                return FALSE;
        }
 
-       botan_pk_op_ka_t ka;
        if (botan_pk_op_key_agreement_create(&ka, this->key, "Raw", 0))
        {
                return FALSE;
        }
 
-       /* prepend 0x04 to indicate uncompressed point format */
-       uint8_t indic = 0x04;
-       value = chunk_cata("cc", chunk_from_thing(indic), value);
-       size_t out_len = 0;
-       if (botan_pk_op_key_agreement(ka, NULL, &out_len, value.ptr, value.len,
-                                                                 NULL, 0)
-               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
-       {
-               botan_pk_op_key_agreement_destroy(ka);
-               return FALSE;
-       }
+       chunk_clear(&this->shared_secret);
 
-       if (out_len == 0)
+       if (botan_pk_op_key_agreement_size(ka, &this->shared_secret.len))
        {
                botan_pk_op_key_agreement_destroy(ka);
                return FALSE;
        }
 
-       chunk_clear(&this->shared_secret);
-       this->shared_secret = chunk_alloc(out_len);
+       /* prepend 0x04 to indicate uncompressed point format */
+       value = chunk_cata("cc", chunk_from_chars(0x04), value);
+
+       this->shared_secret = chunk_alloc(this->shared_secret.len);
        if (botan_pk_op_key_agreement(ka, this->shared_secret.ptr,
                                                                  &this->shared_secret.len, value.ptr,
                                                                  value.len, NULL, 0))
@@ -111,9 +101,7 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
                botan_pk_op_key_agreement_destroy(ka);
                return FALSE;
        }
-
        botan_pk_op_key_agreement_destroy(ka);
-       this->computed = TRUE;
        return TRUE;
 }
 
@@ -121,6 +109,7 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
        private_botan_ec_diffie_hellman_t *this, chunk_t *value)
 {
        chunk_t pkey = chunk_empty;
+
        if (botan_pk_op_key_agreement_export_public(this->key, NULL, &pkey.len)
                != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
        {
@@ -142,14 +131,11 @@ METHOD(diffie_hellman_t, set_private_value, bool,
        private_botan_ec_diffie_hellman_t *this, chunk_t value)
 {
        botan_mp_t scalar;
-       if (botan_mp_init(&scalar))
-       {
-               return FALSE;
-       }
 
-       if (botan_mp_from_bin(scalar, value.ptr, value.len))
+       chunk_clear(&this->shared_secret);
+
+       if (!chunk_to_botan_mp(value, &scalar))
        {
-               botan_mp_destroy(scalar);
                return FALSE;
        }
 
@@ -166,14 +152,13 @@ METHOD(diffie_hellman_t, set_private_value, bool,
        }
 
        botan_mp_destroy(scalar);
-       this->computed = FALSE;
        return TRUE;
 }
 
 METHOD(diffie_hellman_t, get_shared_secret, bool,
        private_botan_ec_diffie_hellman_t *this, chunk_t *secret)
 {
-       if (!this->computed)
+       if (!this->shared_secret.len)
        {
                return FALSE;
        }
@@ -198,10 +183,11 @@ METHOD(diffie_hellman_t, destroy, void,
 /*
  * Described in header.
  */
-botan_ec_diffie_hellman_t *
-botan_ec_diffie_hellman_create(diffie_hellman_group_t group)
+botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
+                                                                                               diffie_hellman_group_t group)
 {
        private_botan_ec_diffie_hellman_t *this;
+       botan_rng_t rng;
 
        INIT(this,
                .public = {
@@ -242,6 +228,21 @@ botan_ec_diffie_hellman_create(diffie_hellman_group_t group)
                        return NULL;
        }
 
+       if (botan_rng_init(&rng, "user"))
+       {
+               free(this);
+               return NULL;
+       }
+
+       if (botan_privkey_create_ecdh(&this->key, rng, this->curve_name))
+       {
+               DBG1(DBG_LIB, "ECDH private key generation failed");
+               botan_rng_destroy(rng);
+               free(this);
+               return NULL;
+       }
+
+       botan_rng_destroy(rng);
        return &this->public;
 }
 
index f4751de..0ba832e 100644 (file)
@@ -50,8 +50,7 @@ struct botan_ec_diffie_hellman_t {
  * @param group                EC Diffie Hellman group number to use
  * @return                     botan_ec_diffie_hellman_t object, NULL if not supported
  */
-botan_ec_diffie_hellman_t *
-botan_ec_diffie_hellman_create(diffie_hellman_group_t group);
+botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
+                                                                                               diffie_hellman_group_t group);
 
 #endif /** BOTAN_EC_DIFFIE_HELLMAN_H_ @}*/
-
index abb4597..e5a6c7c 100644 (file)
@@ -24,6 +24,7 @@
 
 
 #include "botan_ec_private_key.h"
+#include "botan_util.h"
 
 #include <botan/build.h>
 
@@ -43,8 +44,9 @@ typedef struct private_botan_ec_private_key_t private_botan_ec_private_key_t;
  * Private data of a botan_ec_private_key_t object.
  */
 struct private_botan_ec_private_key_t {
+
        /**
-        * Public interface for this signer.
+        * Public interface
         */
        botan_ec_private_key_t public;
 
@@ -62,10 +64,6 @@ struct private_botan_ec_private_key_t {
 #define SIG_FORMAT_IEEE_1363 0
 #define SIG_FORMAT_DER_SEQUENCE 1
 
-/* implemented in ec public key */
-bool botan_ec_fingerprint(botan_pubkey_t *ec, cred_encoding_type_t type,
-                                                 chunk_t *fp);
-
 /**
  * Build a DER encoded signature as in RFC 3279 or as in RFC 4754
  */
@@ -73,72 +71,23 @@ static bool build_signature(botan_privkey_t key, const char *hash_and_padding,
                                                        int signature_format, chunk_t data,
                                                        chunk_t *signature)
 {
-       if (!hash_and_padding || !signature)
-       {
-               return FALSE;
-       }
-
-       botan_pk_op_sign_t sign_op;
-
-       if (botan_pk_op_sign_create(&sign_op, key, hash_and_padding, 0))
+       if (!botan_get_signature(key, hash_and_padding, data, signature))
        {
                return FALSE;
        }
 
-       botan_rng_t rng;
-       if (botan_rng_init(&rng, "user"))
-       {
-               return FALSE;
-       }
-
-       /* get size of signature first */
-       if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       signature->len = 0;
-       if (botan_pk_op_sign_finish(sign_op, rng, NULL, &signature->len)
-               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       /* now get the signature */
-       *signature = chunk_alloc(signature->len);
-       if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       botan_rng_destroy(rng);
-       botan_pk_op_sign_destroy(sign_op);
-
        if (signature_format == SIG_FORMAT_DER_SEQUENCE)
        {
                /* format as ASN.1 sequence of two integers r,s */
-               chunk_t r, s = chunk_empty;
+               chunk_t r = chunk_empty, s = chunk_empty;
+
                chunk_split(*signature, "aa", signature->len / 2, &r,
-                           signature->len / 2, &s);
+                                       signature->len / 2, &s);
 
                chunk_free(signature);
-               *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("c", r),
-                                                          asn1_integer("c", s));
+               *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("m", r),
+                                                          asn1_integer("m", s));
        }
-
        return TRUE;
 }
 
@@ -148,12 +97,12 @@ METHOD(private_key_t, sign, bool,
 {
        switch (scheme)
        {
+               /* r||s -> Botan::IEEE_1363, data is the hash already */
                case SIGN_ECDSA_WITH_NULL:
-                       /* r||s -> Botan::IEEE_1363, data is the hash already */
                        return build_signature(this->key, "Raw",
-                                       SIG_FORMAT_IEEE_1363, data, signature);
+                                                                  SIG_FORMAT_IEEE_1363, data, signature);
+               /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
                case SIGN_ECDSA_WITH_SHA1_DER:
-                       /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
                        return build_signature(this->key, "EMSA1(SHA-1)",
                                                                   SIG_FORMAT_DER_SEQUENCE, data, signature);
                case SIGN_ECDSA_WITH_SHA256_DER:
@@ -165,16 +114,14 @@ METHOD(private_key_t, sign, bool,
                case SIGN_ECDSA_WITH_SHA512_DER:
                        return build_signature(this->key, "EMSA1(SHA-512)",
                                                                   SIG_FORMAT_DER_SEQUENCE, data, signature);
+               /* r||s -> Botan::IEEE_1363 */
                case SIGN_ECDSA_256:
-                       /* r||s -> Botan::IEEE_1363 */
                        return build_signature(this->key, "EMSA1(SHA-256)",
                                                                   SIG_FORMAT_IEEE_1363, data, signature);
                case SIGN_ECDSA_384:
-                       /* r||s -> Botan::IEEE_1363 */
                        return build_signature(this->key, "EMSA1(SHA-384)",
                                                                   SIG_FORMAT_IEEE_1363, data, signature);
                case SIGN_ECDSA_521:
-                       /* r||s -> Botan::IEEE_1363 */
                        return build_signature(this->key, "EMSA1(SHA-512)",
                                                                   SIG_FORMAT_IEEE_1363, data, signature);
                default:
@@ -196,19 +143,15 @@ METHOD(private_key_t, get_keysize, int,
        private_botan_ec_private_key_t *this)
 {
        botan_mp_t p;
-       if(botan_mp_init(&p))
-       {
-               return 0;
-       }
+       size_t bits = 0;
 
-       if(botan_privkey_get_field(p, this->key, "p"))
+       if (botan_mp_init(&p))
        {
-               botan_mp_destroy(p);
                return 0;
        }
 
-       size_t bits = 0;
-       if(botan_mp_num_bits(p, &bits))
+       if (botan_privkey_get_field(p, this->key, "p") ||
+               botan_mp_num_bits(p, &bits))
        {
                botan_mp_destroy(p);
                return 0;
@@ -228,9 +171,9 @@ METHOD(private_key_t, get_public_key, public_key_t*,
        private_botan_ec_private_key_t *this)
 {
        public_key_t *public;
+       botan_pubkey_t pubkey;
        chunk_t key = chunk_empty;
 
-       botan_pubkey_t pubkey;
        if (botan_privkey_export_pubkey(&pubkey, this->key))
        {
                return FALSE;
@@ -255,7 +198,7 @@ METHOD(private_key_t, get_public_key, public_key_t*,
        }
 
        public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
-                       BUILD_BLOB_ASN1_DER, key, BUILD_END);
+                                                               BUILD_BLOB_ASN1_DER, key, BUILD_END);
 
        chunk_free(&key);
        botan_pubkey_destroy(pubkey);
@@ -266,15 +209,20 @@ METHOD(private_key_t, get_fingerprint, bool,
        private_botan_ec_private_key_t *this, cred_encoding_type_t type,
        chunk_t *fingerprint)
 {
+       botan_pubkey_t pubkey;
        bool success = FALSE;
 
-       botan_pubkey_t pubkey;
+       /* check the cache before doing the export */
+       if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
+       {
+               return TRUE;
+       }
+
        if (botan_privkey_export_pubkey(&pubkey, this->key))
        {
                return FALSE;
        }
-
-       success = botan_ec_fingerprint(&pubkey, type, fingerprint);
+       success = botan_get_fingerprint(pubkey, this, type, fingerprint);
        botan_pubkey_destroy(pubkey);
        return success;
 }
@@ -288,9 +236,10 @@ METHOD(private_key_t, get_encoding, bool,
                case PRIVKEY_ASN1_DER:
                case PRIVKEY_PEM:
                {
+                       botan_mp_t x;
+                       chunk_t pval = chunk_empty;
                        bool success = TRUE;
 
-                       botan_mp_t x;
                        if (botan_mp_init(&x))
                        {
                                return FALSE;
@@ -302,7 +251,6 @@ METHOD(private_key_t, get_encoding, bool,
                                return FALSE;
                        }
 
-                       chunk_t pval = chunk_empty;
                        if (botan_mp_num_bytes(x, &pval.len))
                        {
                                botan_mp_destroy(x);
@@ -317,10 +265,12 @@ METHOD(private_key_t, get_encoding, bool,
                                return FALSE;
                        }
 
-                       chunk_t version = chunk_from_chars( 0x01 );
-                       *encoding =
-                               asn1_wrap(ASN1_SEQUENCE, "ms", asn1_integer("c", version),
-                                                 asn1_wrap(ASN1_OCTET_STRING, "s", pval));
+                       /* FIXME: this does not include the params, which the parser/loader
+                        * below actually requires (and is mandated by RFC 5915). we might
+                        * have to store/parse the OID so we can add it here. */
+                       *encoding = asn1_wrap(ASN1_SEQUENCE, "ms",
+                                                                 asn1_integer("c", chunk_from_chars(0x01)),
+                                                                 asn1_wrap(ASN1_OCTET_STRING, "s", pval));
 
                        if (type == PRIVKEY_PEM)
                        {
@@ -353,11 +303,8 @@ METHOD(private_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
-               if (&this->key)
-               {
-                       lib->encoding->clear_cache(lib->encoding, &this->key);
-                       botan_privkey_destroy(this->key);
-               }
+               lib->encoding->clear_cache(lib->encoding, this);
+               botan_privkey_destroy(this->key);
                free(this);
        }
 }
@@ -393,13 +340,14 @@ static private_botan_ec_private_key_t *create_empty()
 }
 
 /*
- * See header.
+ * Described in header
  */
 botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args)
 {
        private_botan_ec_private_key_t *this;
+       botan_rng_t rng;
        u_int key_size = 0;
-       const charcurve;
+       const char *curve;
 
        while (TRUE)
        {
@@ -438,19 +386,18 @@ botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args)
                        return NULL;
        }
 
-       botan_rng_t rng;
-       if (botan_rng_init(&rng, "user"))
+       if (botan_rng_init(&rng, "system"))
        {
                return NULL;
        }
 
        this = create_empty();
 
-       if(botan_privkey_create_ecdsa(&this->key, rng, curve))
+       if (botan_privkey_create_ecdsa(&this->key, rng, curve))
        {
-               DBG1(DBG_LIB, "EC private key generation failed", key_size);
+               DBG1(DBG_LIB, "EC private key generation failed");
                botan_rng_destroy(rng);
-               destroy(this);
+               free(this);
                return NULL;
        }
 
@@ -462,25 +409,26 @@ botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args)
  * ASN.1 definition of a ECPrivateKey structure (RFC 5915)
  */
 static const asn1Object_t ecPrivateKeyObjects[] = {
-       { 0, "ECPrivateKey",    ASN1_SEQUENCE,      ASN1_NONE   }, /* 0 */
-       { 1,   "version",       ASN1_INTEGER,       ASN1_BODY   }, /* 1 */
-       { 1,   "privateKey",    ASN1_OCTET_STRING,  ASN1_BODY   }, /* 2 */
-       { 1,   "parameters",    ASN1_EOC,           ASN1_RAW    }, /* 3 */
-       { 1,   "publicKey",     ASN1_BIT_STRING,    ASN1_OPT    }, /* 4 */
-       { 0, "exit",            ASN1_EOC,           ASN1_EXIT   }
+       { 0, "ECPrivateKey",    ASN1_SEQUENCE,          ASN1_NONE       }, /* 0 */
+       { 1,   "version",               ASN1_INTEGER,           ASN1_BODY       }, /* 1 */
+       { 1,   "privateKey",    ASN1_OCTET_STRING,      ASN1_BODY       }, /* 2 */
+       { 1,   "parameters",    ASN1_EOC,                       ASN1_RAW        }, /* 3 */
+       { 1,   "publicKey",             ASN1_BIT_STRING,        ASN1_OPT        }, /* 4 */
+       { 0, "exit",                    ASN1_EOC,                       ASN1_EXIT       }
 };
 
 #define ECPK_PRIVATE_KEY 2
 #define ECPK_PRIVATE_KEY_PARAMS 3
 
-/**
- * See header.
+/*
+ * Described in header
  */
 botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
 {
        private_botan_ec_private_key_t *this;
        chunk_t params = chunk_empty, key = chunk_empty;
-       chunk_t object, pkcs8 = chunk_empty;
+       chunk_t object, alg_id = chunk_empty, pkcs8 = chunk_empty;
+       botan_rng_t rng;
 
        while (TRUE)
        {
@@ -500,18 +448,15 @@ botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
                break;
        }
 
-       this = create_empty();
-
        /*
         * botan expects a PKCS#8 private key, so we build one
         * RFC 5282 mandates ECParameters as part of the algorithmIdentifier
         */
-       chunk_t alg_id = chunk_empty;
-       if(params.len != 0)
+       if (params.len != 0)
        {
                /* if ECDomainParameters is passed, just append it */
-               alg_id = asn1_wrap(ASN1_SEQUENCE, "mc",
-                                                  asn1_build_known_oid(OID_EC_PUBLICKEY), params);
+               alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
+                                                                                                chunk_clone(params));
        }
        else
        {
@@ -541,27 +486,26 @@ botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
                                        parser->destroy(parser);
                                        return NULL;
                                }
-
                                break;
                        }
                }
 
                parser->destroy(parser);
-               alg_id = asn1_wrap(ASN1_SEQUENCE, "mc",
-                                                  asn1_build_known_oid(OID_EC_PUBLICKEY),
-                                                  asn1_simple_object(ASN1_OID, params));
+               alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
+                                                                               asn1_simple_object(ASN1_OID, params));
        }
 
-       pkcs8 = asn1_wrap(ASN1_SEQUENCE, "cms",
+       pkcs8 = asn1_wrap(ASN1_SEQUENCE, "mms",
                                          asn1_integer("c", chunk_from_chars(0x00)),
                                          alg_id,
                                          asn1_wrap(ASN1_OCTET_STRING, "c", key));
 
-       botan_rng_t rng;
+       this = create_empty();
+
        if (botan_rng_init(&rng, "user"))
        {
                chunk_clear(&pkcs8);
-               destroy(this);
+               free(this);
                return NULL;
        }
 
@@ -569,7 +513,7 @@ botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
        {
                chunk_clear(&pkcs8);
                botan_rng_destroy(rng);
-               destroy(this);
+               free(this);
                return NULL;
        }
 
@@ -578,4 +522,4 @@ botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
        return &this->public;
 }
 
-#endif
\ No newline at end of file
+#endif
index 0fcfda2..9450331 100644 (file)
 #ifndef BOTAN_EC_PRIVATE_KEY_H_
 #define BOTAN_EC_PRIVATE_KEY_H_
 
-#include <botan/build.h>
-
-#ifdef BOTAN_HAS_ECDSA
-
 #include <credentials/builder.h>
 #include <credentials/keys/private_key.h>
 
@@ -73,6 +69,4 @@ botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args);
 botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type,
                                                                                                  va_list args);
 
-#endif
-
 #endif /** BOTAN_EC_PRIVATE_KEY_H_ @}*/
index abc513b..54782bc 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "botan_ec_public_key.h"
+#include "botan_util.h"
 
 #include <botan/build.h>
 
@@ -41,6 +42,7 @@ typedef struct private_botan_ec_public_key_t private_botan_ec_public_key_t;
  * Private data structure with signing context.
  */
 struct private_botan_ec_public_key_t {
+
        /**
         * Public interface for this signer
         */
@@ -67,7 +69,9 @@ static bool verify_signature(private_botan_ec_public_key_t *this,
        const char* hash_and_padding, int signature_format, size_t keylen,
        chunk_t data, chunk_t signature)
 {
-       chunk_t sig;
+       botan_pk_op_verify_t verify_op;
+       chunk_t sig = signature;
+       bool valid = FALSE;
 
        if (signature_format == SIG_FORMAT_DER_SEQUENCE)
        {
@@ -75,12 +79,11 @@ static bool verify_signature(private_botan_ec_public_key_t *this,
                 * botan requires a signature in IEEE 1363 format (r||s)
                 * re-encode from ASN.1 sequence of two integers r,s
                 */
-               chunk_t parse, r, s;
-               parse = signature;
+               chunk_t parse = signature, r, s;
 
-               if (asn1_unwrap(&parse, &parse) != ASN1_SEQUENCE
-                   || asn1_unwrap(&parse, &r) != ASN1_INTEGER
-                   || asn1_unwrap(&parse, &s) != ASN1_INTEGER)
+               if (asn1_unwrap(&parse, &parse) != ASN1_SEQUENCE ||
+                       asn1_unwrap(&parse, &r) != ASN1_INTEGER ||
+                       asn1_unwrap(&parse, &s) != ASN1_INTEGER)
                {
                        return FALSE;
                }
@@ -101,34 +104,22 @@ static bool verify_signature(private_botan_ec_public_key_t *this,
                memcpy(sig.ptr + (keylen - r.len), r.ptr, r.len);
                memcpy(sig.ptr + keylen + (keylen - s.len), s.ptr, s.len);
        }
-       else
+
+       if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding, 0))
        {
-               sig.ptr = signature.ptr;
-               sig.len = signature.len;
+               return FALSE;
        }
 
+       if (botan_pk_op_verify_update(verify_op, data.ptr, data.len))
        {
-               botan_pk_op_verify_t verify_op;
-               bool valid = FALSE;
-
-               if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding,
-                                                                         0))
-               {
-                       return FALSE;
-               }
-
-               if (botan_pk_op_verify_update(verify_op, data.ptr, data.len))
-               {
-                       botan_pk_op_verify_destroy(verify_op);
-                       return FALSE;
-               }
-
-               valid = !(botan_pk_op_verify_finish(verify_op, sig.ptr, sig.len));
-
                botan_pk_op_verify_destroy(verify_op);
-
-               return valid;
+               return FALSE;
        }
+
+       valid = !(botan_pk_op_verify_finish(verify_op, sig.ptr, sig.len));
+
+       botan_pk_op_verify_destroy(verify_op);
+       return valid;
 }
 
 METHOD(public_key_t, get_type, key_type_t,
@@ -141,19 +132,15 @@ METHOD(public_key_t, get_keysize, int,
        private_botan_ec_public_key_t *this)
 {
        botan_mp_t p;
-       if(botan_mp_init(&p))
-       {
-               return 0;
-       }
+       size_t bits = 0;
 
-       if(botan_pubkey_get_field(p, this->key, "p"))
+       if (botan_mp_init(&p))
        {
-               botan_mp_destroy(p);
                return 0;
        }
 
-       size_t bits = 0;
-       if(botan_mp_num_bits(p, &bits))
+       if (botan_pubkey_get_field(p, this->key, "p") ||
+               botan_mp_num_bits(p, &bits))
        {
                botan_mp_destroy(p);
                return 0;
@@ -173,13 +160,13 @@ METHOD(public_key_t, verify, bool,
 
        switch (scheme)
        {
+               /* r||s -> Botan::IEEE_1363, data is the hash already */
                case SIGN_ECDSA_WITH_NULL:
-                       /* r||s -> Botan::IEEE_1363, data is the hash already */
                        hash_and_padding = "Raw";
                        sig_format = SIG_FORMAT_IEEE_1363;
                        break;
+               /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
                case SIGN_ECDSA_WITH_SHA1_DER:
-                       /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
                        hash_and_padding = "EMSA1(SHA-1)";
                        sig_format = SIG_FORMAT_DER_SEQUENCE;
                        break;
@@ -195,18 +182,16 @@ METHOD(public_key_t, verify, bool,
                        hash_and_padding = "EMSA1(SHA-512)";
                        sig_format = SIG_FORMAT_DER_SEQUENCE;
                        break;
+               /* r||s -> Botan::IEEE_1363 */
                case SIGN_ECDSA_256:
-                       /* r||s -> Botan::IEEE_1363 */
                        hash_and_padding = "EMSA1(SHA-256)";
                        sig_format = SIG_FORMAT_IEEE_1363;
                        break;
                case SIGN_ECDSA_384:
-                       /* r||s -> Botan::IEEE_1363 */
                        hash_and_padding = "EMSA1(SHA-384)";
                        sig_format = SIG_FORMAT_IEEE_1363;
                        break;
                case SIGN_ECDSA_521:
-                       /* r||s -> Botan::IEEE_1363 */
                        hash_and_padding = "EMSA1(SHA-512)";
                        sig_format = SIG_FORMAT_IEEE_1363;
                        break;
@@ -228,119 +213,18 @@ METHOD(public_key_t, encrypt, bool,
        return FALSE;
 }
 
-/**
- * Calculate fingerprint from a botan_pubkey_t, also used in ec private key.
- */
-bool botan_ec_fingerprint(botan_pubkey_t *ec, cred_encoding_type_t type,
-                                                 chunk_t *fp)
-{
-       hasher_t *hasher;
-       chunk_t key;
-
-       if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
-       {
-               return TRUE;
-       }
-
-       switch (type)
-       {
-               case KEYID_PUBKEY_SHA1:
-                       /* subjectPublicKey -> use botan_pubkey_fingerprint() */
-                       {
-                               if (botan_pubkey_fingerprint(*ec, "SHA-1", NULL, &fp->len))
-                               {
-                                       return FALSE;
-                               }
-
-                               *fp = chunk_alloc(fp->len);
-
-                               if (botan_pubkey_fingerprint(*ec, "SHA-1", fp->ptr, &fp->len))
-                               {
-                                       chunk_free(fp);
-                                       return FALSE;
-                               }
-
-                               break;
-                       }
-               case KEYID_PUBKEY_INFO_SHA1:
-                       /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */
-                       {
-                               if (botan_pubkey_export(*ec, NULL, &key.len,
-                                                                               BOTAN_PRIVKEY_EXPORT_FLAG_DER))
-                               {
-                                       return FALSE;
-                               }
-
-                               key = chunk_alloc(key.len);
-
-                               if (botan_pubkey_export(*ec, key.ptr, &key.len,
-                                                                               BOTAN_PRIVKEY_EXPORT_FLAG_DER))
-                               {
-                                       chunk_free(&key);
-                                       return FALSE;
-                               }
-
-                               hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
-                               if (!hasher || !hasher->allocate_hash(hasher, key, fp))
-                               {
-                                       DBG1(DBG_LIB, "SHA1 hash algorithm not supported,"
-                                                " fingerprinting failed");
-                                       DESTROY_IF(hasher);
-                                       chunk_free(&key);
-                                       return FALSE;
-                               }
-
-                               hasher->destroy(hasher);
-                               chunk_free(&key);
-                               break;
-                       }
-               default:
-                       return FALSE;
-       }
-
-       lib->encoding->cache(lib->encoding, type, ec, *fp);
-       return TRUE;
-}
-
 METHOD(public_key_t, get_fingerprint, bool,
        private_botan_ec_public_key_t *this, cred_encoding_type_t type,
        chunk_t *fingerprint)
 {
-       return botan_ec_fingerprint(&this->key, type, fingerprint);
+       return botan_get_fingerprint(this->key, this, type, fingerprint);
 }
 
 METHOD(public_key_t, get_encoding, bool,
        private_botan_ec_public_key_t *this, cred_encoding_type_t type,
        chunk_t *encoding)
 {
-       bool success = TRUE;
-
-       if (botan_pubkey_export(this->key, NULL, &encoding->len,
-                                                       BOTAN_PRIVKEY_EXPORT_FLAG_DER))
-       {
-               return FALSE;
-       }
-
-       *encoding = chunk_alloc(encoding->len);
-
-       if (botan_pubkey_export(this->key, encoding->ptr, &encoding->len,
-                                                       BOTAN_PRIVKEY_EXPORT_FLAG_DER))
-       {
-               chunk_free(encoding);
-               return FALSE;
-       }
-
-       if (type != PUBKEY_SPKI_ASN1_DER)
-       {
-               chunk_t asn1_encoding = *encoding;
-
-               success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
-                                                                               CRED_PART_ECDSA_PUB_ASN1_DER,
-                                                                               asn1_encoding, CRED_PART_END);
-               chunk_free(&asn1_encoding);
-       }
-
-       return success;
+       return botan_get_encoding(this->key, type, encoding);
 }
 
 METHOD(public_key_t, get_ref, public_key_t*,
@@ -355,18 +239,22 @@ METHOD(public_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
+               lib->encoding->clear_cache(lib->encoding, this);
                botan_pubkey_destroy(this->key);
                free(this);
        }
 }
 
-/**
- * See header.
+/*
+ * Described in header
  */
 botan_ec_public_key_t *botan_ec_public_key_load(key_type_t type, va_list args)
 {
        private_botan_ec_public_key_t *this;
        chunk_t blob = chunk_empty;
+       botan_rng_t rng;
+       size_t namesize = 0;
+       char *namebuf;
 
        if (type != KEY_ECDSA)
        {
@@ -408,49 +296,42 @@ botan_ec_public_key_t *botan_ec_public_key_load(key_type_t type, va_list args)
 
        if (botan_pubkey_load(&this->key, blob.ptr, blob.len))
        {
-               destroy(this);
+               free(this);
                return NULL;
        }
 
-       size_t namesize = 0;
-       if (botan_pubkey_algo_name(this->key, NULL, &namesize) !=
-                                                          BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+       if (botan_pubkey_algo_name(this->key, NULL, &namesize)
+               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
        {
-               botan_pubkey_destroy(this->key);
                destroy(this);
                return NULL;
        }
 
-       char* namebuf = malloc(namesize);
+       namebuf = malloc(namesize);
        if (botan_pubkey_algo_name(this->key, namebuf, &namesize))
        {
                free(namebuf);
-               botan_pubkey_destroy(this->key);
                destroy(this);
                return NULL;
        }
 
-       const char* algo_name = "ECDSA";
-       if (!strneq(namebuf, algo_name, sizeof(algo_name)))
+       if (!strneq(namebuf, "ECDSA", namesize))
        {
                free(namebuf);
-               botan_pubkey_destroy(this->key);
                destroy(this);
                return NULL;
        }
        free(namebuf);
 
-       botan_rng_t rng;
        if (botan_rng_init(&rng, "user"))
        {
-               return FALSE;
+               return NULL;
        }
 
        if (botan_pubkey_check_key(this->key, rng, BOTAN_CHECK_KEY_EXPENSIVE_TESTS))
        {
                DBG1(DBG_LIB, "public key failed key checks");
                botan_rng_destroy(rng);
-               botan_pubkey_destroy(this->key);
                destroy(this);
                return NULL;
        }
index 7fc59bd..7e0fc14 100644 (file)
@@ -82,8 +82,7 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
 {
        botan_cipher_t cipher;
        uint8_t nonce[NONCE_LEN];
-       size_t output_written = 0;
-       size_t input_consumed = 0;
+       size_t output_written = 0, input_consumed = 0;
 
        memcpy(nonce, this->salt, SALT_LEN);
        memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN);
@@ -99,8 +98,8 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
                return FALSE;
        }
 
-       if (assoc.len
-               && botan_cipher_set_associated_data(cipher, assoc.ptr, assoc.len))
+       if (assoc.len &&
+               botan_cipher_set_associated_data(cipher, assoc.ptr, assoc.len))
        {
                botan_cipher_destroy(cipher);
                return FALSE;
@@ -115,8 +114,8 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
        if (init_flag == BOTAN_CIPHER_INIT_FLAG_ENCRYPT)
        {
                if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
-                               out, data.len + this->icv_size, &output_written,
-                               data.ptr, data.len, &input_consumed))
+                                                               out, data.len + this->icv_size, &output_written,
+                                                               data.ptr, data.len, &input_consumed))
                {
                        botan_cipher_destroy(cipher);
                        return FALSE;
@@ -125,8 +124,8 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
        else if (init_flag == BOTAN_CIPHER_INIT_FLAG_DECRYPT)
        {
                if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
-                               out, data.len, &output_written,
-                               data.ptr, data.len + this->icv_size, &input_consumed))
+                                                               out, data.len, &output_written, data.ptr,
+                                                               data.len + this->icv_size, &input_consumed))
                {
                        botan_cipher_destroy(cipher);
                        return FALSE;
@@ -225,8 +224,11 @@ METHOD(aead_t, destroy, void,
        free(this);
 }
 
-aead_t *botan_gcm_create(encryption_algorithm_t algo,
-                                                  size_t key_size, size_t salt_size)
+/*
+ * Described in header
+ */
+aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size,
+                                                size_t salt_size)
 {
        private_aead_t *this;
 
@@ -244,22 +246,6 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
                },
        );
 
-       switch (algo)
-       {
-               case ENCR_AES_GCM_ICV8:
-                       this->icv_size = 8;
-                       break;
-               case ENCR_AES_GCM_ICV12:
-                       this->icv_size = 12;
-                       break;
-               case ENCR_AES_GCM_ICV16:
-                       this->icv_size = 16;
-                       break;
-               default:
-                       free(this);
-                       return NULL;
-       }
-
        if (salt_size && salt_size != SALT_LEN)
        {
                /* currently not supported */
@@ -274,6 +260,7 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
                        {
                                case 0:
                                        key_size = 16;
+                                       /* FALL */
                                case 16:
                                        this->cipher_name = "AES-128/GCM(8)";
                                        break;
@@ -287,6 +274,7 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
                                        free(this);
                                        return NULL;
                        }
+                       this->icv_size = 8;
                        break;
                case ENCR_AES_GCM_ICV12:
                        switch (key_size)
@@ -307,6 +295,7 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
                                        free(this);
                                        return NULL;
                        }
+                       this->icv_size = 12;
                        break;
                case ENCR_AES_GCM_ICV16:
                        switch (key_size)
@@ -327,18 +316,13 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
                                        free(this);
                                        return NULL;
                        }
+                       this->icv_size = 16;
                        break;
                default:
                        free(this);
                        return NULL;
        }
 
-       if (!this->cipher_name)
-       {
-               free(this);
-               return NULL;
-       }
-
        this->key = chunk_alloc(key_size);
        this->iv_gen = iv_gen_seq_create();
 
@@ -346,4 +330,4 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo,
 }
 
 #endif
-#endif
\ No newline at end of file
+#endif
index 600e60b..b2053cb 100644 (file)
 #ifndef BOTAN_GCM_H_
 #define BOTAN_GCM_H_
 
-#include <botan/build.h>
-
-#ifdef BOTAN_HAS_AEAD_GCM
-
 #include <crypto/aead.h>
 
 /**
  * Constructor to create aead_t implementation.
  *
- * @param algo          algorithm to implement
- * @param key_size      key size in bytes
- * @param salt_size     size of implicit salt length
- * @return              aead_t object, NULL if not supported
+ * @param algo                 algorithm to implement
+ * @param key_size             key size in bytes
+ * @param salt_size            size of implicit salt length
+ * @return                             aead_t object, NULL if not supported
  */
 aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size,
                                                 size_t salt_size);
 
-#endif
-
 #endif /** BOTAN_GCM_H_ @}*/
index 06b2ad9..3a8fcd8 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "botan_hasher.h"
+#include "botan_util.h"
 
 #include <utils/debug.h>
 
@@ -49,6 +50,7 @@ METHOD(hasher_t, get_hash_size, size_t,
        private_botan_hasher_t *this)
 {
        size_t len = 0;
+
        if (botan_hash_output_length(this->hash, &len))
        {
                return 0;
@@ -74,12 +76,9 @@ METHOD(hasher_t, get_hash, bool,
                return FALSE;
        }
 
-       if (hash)
+       if (hash && botan_hash_final(this->hash, hash))
        {
-               if (botan_hash_final(this->hash, hash))
-               {
-                       return FALSE;
-               }
+               return FALSE;
        }
        return TRUE;
 }
@@ -110,28 +109,10 @@ botan_hasher_t *botan_hasher_create(hash_algorithm_t algo)
        private_botan_hasher_t *this;
        const char* hash_name;
 
-       switch (algo)
+       hash_name = botan_get_hash(algo);
+       if (!hash_name)
        {
-               case HASH_MD5:
-                       hash_name = "MD5";
-                       break;
-               case HASH_SHA1:
-                       hash_name = "SHA-1";
-                       break;
-               case HASH_SHA224:
-                       hash_name = "SHA-224";
-                       break;
-               case HASH_SHA256:
-                       hash_name = "SHA-256";
-                       break;
-               case HASH_SHA384:
-                       hash_name = "SHA-384";
-                       break;
-               case HASH_SHA512:
-                       hash_name = "SHA-512";
-                       break;
-               default:
-                       return NULL;
+               return FALSE;
        }
 
        INIT(this,
@@ -150,6 +131,5 @@ botan_hasher_t *botan_hasher_create(hash_algorithm_t algo)
        {
                return NULL;
        }
-
        return &this->public;
 }
index a1e3514..367d27f 100644 (file)
@@ -69,16 +69,10 @@ METHOD(mac_t, get_mac, bool,
                return FALSE;
        }
 
-       if ( out == NULL)
-       {
-               return TRUE;
-       }
-
-       if (botan_mac_final(this->hmac, out))
+       if (out && botan_mac_final(this->hmac, out))
        {
                return FALSE;
        }
-
        return TRUE;
 }
 
@@ -86,6 +80,7 @@ METHOD(mac_t, get_mac_size, size_t,
        private_botan_mac_t *this)
 {
        size_t len = 0;
+
        if (botan_mac_output_length(this->hmac, &len))
        {
                return 0;
@@ -140,7 +135,6 @@ static mac_t *hmac_create(hash_algorithm_t algo)
                free(this);
                return NULL;
        }
-
        return &this->public;
 }
 
index 0fb9159..bce6b8f 100644 (file)
@@ -78,7 +78,6 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(DH, MODP_1024_BIT),
                        PLUGIN_PROVIDE(DH, MODP_1024_160),
                        PLUGIN_PROVIDE(DH, MODP_768_BIT),
-               PLUGIN_REGISTER(DH, botan_diffie_hellman_create_custom),
                        PLUGIN_PROVIDE(DH, MODP_CUSTOM),
 #endif
                /* crypters */
@@ -146,6 +145,7 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
                        PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
 #endif
+#endif /* BOTAN_HAS_HMAC */
 
 #ifdef BOTAN_HAS_ECDH
                /* EC DH groups */
@@ -157,7 +157,6 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(DH, ECP_384_BP),
                        PLUGIN_PROVIDE(DH, ECP_512_BP),
 #endif
-#endif
                /* RSA */
 #ifdef BOTAN_HAS_RSA
                /* public/private key loading/generation */
@@ -265,7 +264,7 @@ METHOD(plugin_t, destroy, void,
 }
 
 /*
- * see header file
+ * Described in header
  */
 plugin_t *botan_plugin_create()
 {
index f398f9f..c49225c 100644 (file)
@@ -47,28 +47,15 @@ struct private_botan_random_t {
        rng_quality_t quality;
 
        /**
-        * RNG type
+        * RNG instance
         */
-       const char* rng_name;
+       botan_rng_t rng;
 };
 
 METHOD(rng_t, get_bytes, bool,
        private_botan_random_t *this, size_t bytes, uint8_t *buffer)
 {
-       botan_rng_t rng;
-       if (botan_rng_init(&rng, this->rng_name))
-       {
-               return FALSE;
-       }
-
-       if (botan_rng_get(rng, buffer, bytes))
-       {
-               botan_rng_destroy(rng);
-               return FALSE;
-       }
-
-       botan_rng_destroy(rng);
-       return TRUE;
+       return botan_rng_get(this->rng, buffer, bytes) == 0;
 }
 
 METHOD(rng_t, allocate_bytes, bool,
@@ -86,11 +73,12 @@ METHOD(rng_t, allocate_bytes, bool,
 METHOD(rng_t, destroy, void,
        private_botan_random_t *this)
 {
+       botan_rng_destroy(this->rng);
        free(this);
 }
 
 /*
- * Described in header.
+ * Described in header
  */
 botan_random_t *botan_rng_create(rng_quality_t quality)
 {
@@ -101,7 +89,17 @@ botan_random_t *botan_rng_create(rng_quality_t quality)
        {
                case RNG_WEAK:
                case RNG_STRONG:
+                       /* some rng_t instances of this class (e.g. in the ike-sa-manager)
+                        * may be called concurrently by different threads. the Botan RNGs
+                        * are not reentrant, by default, so use the threadsafe version.
+                        * because we build without threading support when running tests
+                        * with leak-detective (lots of reports of frees of unknown memory)
+                        * there is a fallback to the default */
+#ifdef BOTAN_TARGET_OS_HAS_THREADS
+                       rng_name = "user-threadsafe";
+#else
                        rng_name = "user";
+#endif
                        break;
                case RNG_TRUE:
                        rng_name = "system";
@@ -119,9 +117,13 @@ botan_random_t *botan_rng_create(rng_quality_t quality)
                        },
                },
                .quality = quality,
-               .rng_name = rng_name,
        );
 
+       if (botan_rng_init(&this->rng, rng_name))
+       {
+               free(this);
+               return NULL;
+       }
        return &this->public;
 }
 
index c35e0c2..29f6923 100644 (file)
@@ -39,6 +39,7 @@ typedef struct private_botan_rsa_private_key_t private_botan_rsa_private_key_t;
  * Private data of a botan_rsa_private_key_t object.
  */
 struct private_botan_rsa_private_key_t {
+
        /**
         * Public interface for this signer.
         */
@@ -49,7 +50,6 @@ struct private_botan_rsa_private_key_t {
         */
        botan_privkey_t key;
 
-
        /**
         * reference count
         */
@@ -59,32 +59,23 @@ struct private_botan_rsa_private_key_t {
 /**
  * Get the binary representation of a named RSA parameter
  */
-static int botan_rsa_get_field(botan_privkey_t *key, const char *field_name,
-                                                          chunk_t *value)
+static bool get_rsa_field(botan_privkey_t *key, const char *field_name,
+                                                 chunk_t *value)
 {
        botan_mp_t field;
-       if (botan_mp_init(&field))
-       {
-               return -1;
-       }
-
-       if (botan_privkey_get_field(field, *key, field_name))
-       {
-               botan_mp_destroy(field);
-               return -1;
-       }
-
        size_t field_size = 0;
-       if (botan_mp_num_bytes(field, &field_size))
+
+       if (botan_mp_init(&field))
        {
-               botan_mp_destroy(field);
-               return -1;
+               return FALSE;
        }
 
-       if (field_size == 0)
+       if (botan_privkey_get_field(field, *key, field_name) ||
+               botan_mp_num_bytes(field, &field_size) ||
+               !field_size)
        {
                botan_mp_destroy(field);
-               return -1;
+               return FALSE;
        }
 
        *value = chunk_alloc(field_size);
@@ -92,105 +83,9 @@ static int botan_rsa_get_field(botan_privkey_t *key, const char *field_name,
        {
                botan_mp_destroy(field);
                chunk_clear(value);
-               return -1;
-       }
-
-       botan_mp_destroy(field);
-       return 0;
-}
-
-/**
- * Build RSA signature
- */
-static bool build_rsa_signature(private_botan_rsa_private_key_t *this,
-               const char* hash_and_padding, chunk_t data, chunk_t* signature)
-{
-       botan_pk_op_sign_t sign_op;
-
-       if (botan_pk_op_sign_create(&sign_op, this->key, hash_and_padding, 0))
-       {
-               return FALSE;
-       }
-
-       botan_rng_t rng;
-       if (botan_rng_init(&rng, "user"))
-       {
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       /* get size of signature first */
-       if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       signature->len = 0;
-       if (botan_pk_op_sign_finish(sign_op, rng, NULL, &signature->len)
-           != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
-       {
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       /* now get the signature */
-       *signature = chunk_alloc(signature->len);
-       if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
-       {
-               chunk_free(signature);
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
                return FALSE;
        }
-
-       if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
-       {
-               chunk_free(signature);
-               botan_rng_destroy(rng);
-               botan_pk_op_sign_destroy(sign_op);
-               return FALSE;
-       }
-
-       botan_rng_destroy(rng);
-       botan_pk_op_sign_destroy(sign_op);
-       return TRUE;
-}
-
-/**
- * Build an EMSA PKCS1 signature described in PKCS#1
- */
-static bool build_emsa_pkcs1_signature(private_botan_rsa_private_key_t *this,
-               const char* hash_and_padding, chunk_t data, chunk_t* signature)
-{
-       return build_rsa_signature(this, hash_and_padding, data, signature);
-}
-
-static bool botan_get_hash(hash_algorithm_t hash, char* hash_str)
-{
-       switch (hash)
-       {
-               case HASH_SHA1:
-                       sprintf(hash_str, "SHA-1");
-                       break;
-               case HASH_SHA224:
-                       sprintf(hash_str, "SHA-224");
-                       break;
-               case HASH_SHA256:
-                       sprintf(hash_str, "SHA-256");
-                       break;
-               case HASH_SHA384:
-                       sprintf(hash_str, "SHA-384");
-                       break;
-               case HASH_SHA512:
-                       sprintf(hash_str, "SHA-512");
-                       break;
-               default:
-                       return FALSE;
-       }
-
+       botan_mp_destroy(field);
        return TRUE;
 }
 
@@ -201,10 +96,8 @@ static bool build_emsa_pss_signature(private_botan_rsa_private_key_t *this,
                                                                         rsa_pss_params_t *params, chunk_t data,
                                                                         chunk_t *sig)
 {
-       char* hash_and_padding, *hash, *mgf1_hash;
-       char* salt_len = NULL;
-       size_t len;
-       bool success = FALSE;
+       const char *hash;
+       char hash_and_padding[BUF_LEN];
 
        if (!params)
        {
@@ -218,50 +111,23 @@ static bool build_emsa_pss_signature(private_botan_rsa_private_key_t *this,
                return FALSE;
        }
 
-       hash = malloc(8);
-       if (!botan_get_hash(params->hash, hash))
-       {
-               free(hash);
-               return FALSE;
-       }
-
-       mgf1_hash = malloc(8);
-       if (!botan_get_hash(params->mgf1_hash, mgf1_hash))
+       hash = botan_get_hash(params->hash);
+       if (!hash)
        {
-               free(hash);
-               free(mgf1_hash);
                return FALSE;
        }
 
        if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
        {
-               salt_len = malloc(6);
-               snprintf(salt_len, 5, "%d", params->salt_len);
-       }
-
-       len = 24 + strlen(hash) + strlen(mgf1_hash);
-       hash_and_padding = malloc(len+1);
-
-       if (salt_len)
-       {
-               snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1,%s)", hash, salt_len);
+               snprintf(hash_and_padding, sizeof(hash_and_padding),
+                                "EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
        }
        else
        {
-               snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1)", hash);
+               snprintf(hash_and_padding, sizeof(hash_and_padding),
+                                "EMSA-PSS(%s,MGF1)", hash);
        }
-
-       if (build_rsa_signature(this, hash_and_padding, data, sig))
-       {
-               success = TRUE;
-       }
-
-       if (salt_len)
-               free(salt_len);
-       free(hash);
-       free(mgf1_hash);
-       free(hash_and_padding);
-       return success;
+       return botan_get_signature(this->key, hash_and_padding, data, sig);
 }
 
 METHOD(private_key_t, get_type, key_type_t,
@@ -277,23 +143,23 @@ METHOD(private_key_t, sign, bool,
        switch (scheme)
        {
                case SIGN_RSA_EMSA_PKCS1_NULL:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(Raw)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(Raw)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PKCS1_SHA1:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-1)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(SHA-1)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_224:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-224)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(SHA-224)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_256:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-256)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(SHA-256)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_384:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-384)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(SHA-384)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_512:
-                       return build_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-512)", data,
-                                                                                         signature);
+                       return botan_get_signature(this->key, "EMSA_PKCS1(SHA-512)", data,
+                                                                          signature);
                case SIGN_RSA_EMSA_PSS:
                        return build_emsa_pss_signature(this, params, data, signature);
                default:
@@ -303,9 +169,11 @@ METHOD(private_key_t, sign, bool,
        }
 }
 
-METHOD(private_key_t, decrypt, bool, private_botan_rsa_private_key_t *this,
-          encryption_scheme_t scheme, chunk_t crypto, chunk_t *plain)
+METHOD(private_key_t, decrypt, bool,
+       private_botan_rsa_private_key_t *this, encryption_scheme_t scheme,
+       chunk_t crypto, chunk_t *plain)
 {
+       botan_pk_op_decrypt_t decrypt_op;
        const char *padding;
 
        switch (scheme)
@@ -334,26 +202,18 @@ METHOD(private_key_t, decrypt, bool, private_botan_rsa_private_key_t *this,
                        return FALSE;
        }
 
-       botan_pk_op_decrypt_t decrypt_op;
        if (botan_pk_op_decrypt_create(&decrypt_op, this->key, padding, 0))
        {
                return FALSE;
        }
 
-       /*
-        * get size of plaintext first
-        */
-       if (botan_pk_op_decrypt(decrypt_op, NULL, &plain->len, crypto.ptr,
-                                                       crypto.len)
-               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+       plain->len = 0;
+       if (botan_pk_op_decrypt_output_length(decrypt_op, crypto.len, &plain->len))
        {
                botan_pk_op_decrypt_destroy(decrypt_op);
                return FALSE;
        }
 
-       /*
-        *  now get the plaintext
-        */
        *plain = chunk_alloc(plain->len);
        if (botan_pk_op_decrypt(decrypt_op, plain->ptr, &plain->len, crypto.ptr,
                                                        crypto.len))
@@ -362,7 +222,6 @@ METHOD(private_key_t, decrypt, bool, private_botan_rsa_private_key_t *this,
                botan_pk_op_decrypt_destroy(decrypt_op);
                return FALSE;
        }
-
        botan_pk_op_decrypt_destroy(decrypt_op);
        return TRUE;
 }
@@ -371,21 +230,18 @@ METHOD(private_key_t, get_keysize, int,
        private_botan_rsa_private_key_t *this)
 {
        botan_mp_t n;
-       if (botan_mp_init(&n))
-       {
-               return -1;
-       }
+       size_t bits = 0;
 
-       if (botan_privkey_rsa_get_n(n, this->key))
+       if (botan_mp_init(&n))
        {
-               return -1;
+               return 0;
        }
 
-       size_t bits = 0;
-       if (botan_mp_num_bits(n, &bits))
+       if (botan_privkey_rsa_get_n(n, this->key) ||
+               botan_mp_num_bits(n, &bits))
        {
                botan_mp_destroy(n);
-               return -1;
+               return 0;
        }
 
        botan_mp_destroy(n);
@@ -395,22 +251,23 @@ METHOD(private_key_t, get_keysize, int,
 METHOD(private_key_t, get_public_key, public_key_t*,
        private_botan_rsa_private_key_t *this)
 {
+       public_key_t *pub_key;
        chunk_t n, e;
 
-       if (botan_rsa_get_field(&this->key, "n", &n))
+       if (!get_rsa_field(&this->key, "n", &n))
        {
                return NULL;
        }
 
-       if (botan_rsa_get_field(&this->key, "e", &e))
+       if (!get_rsa_field(&this->key, "e", &e))
        {
-               chunk_clear(&n);
+               chunk_free(&n);
                return NULL;
        }
 
-       public_key_t *pub_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
-                                                                                          KEY_RSA, BUILD_RSA_MODULUS, n,
-                                                                                          BUILD_RSA_PUB_EXP, e, BUILD_END);
+       pub_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+                                                                BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e,
+                                                                BUILD_END);
 
        chunk_free(&n);
        chunk_free(&e);
@@ -421,32 +278,22 @@ METHOD(private_key_t, get_fingerprint, bool,
        private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
        chunk_t *fingerprint)
 {
-       chunk_t n, e;
-       bool success;
+       botan_pubkey_t pubkey;
+       bool success = FALSE;
 
-       if (lib->encoding->get_cache(lib->encoding, type, &this->key, fingerprint))
+       /* check the cache before doing the export */
+       if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
        {
                return TRUE;
        }
 
-       if (botan_rsa_get_field(&this->key, "n", &n))
-       {
-               return FALSE;
-       }
-
-       if (botan_rsa_get_field(&this->key, "e", &e))
+       if (botan_privkey_export_pubkey(&pubkey, this->key))
        {
-               chunk_clear(&n);
                return FALSE;
        }
-
-       success = lib->encoding->encode(lib->encoding, type, &this->key,
-                                                                       fingerprint, CRED_PART_RSA_MODULUS, n,
-                                                                       CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
-       chunk_free(&n);
-       chunk_free(&e);
+       success = botan_get_fingerprint(pubkey, this, type, fingerprint);
+       botan_pubkey_destroy(pubkey);
        return success;
-
 }
 
 METHOD(private_key_t, get_encoding, bool,
@@ -458,27 +305,28 @@ METHOD(private_key_t, get_encoding, bool,
                case PRIVKEY_ASN1_DER:
                case PRIVKEY_PEM:
                {
+                       uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER;
+                       size_t len = 0;
                        bool success = TRUE;
 
-                       uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER;
                        if (type == PRIVKEY_PEM)
                        {
                                format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM;
                        }
 
-                       size_t bits = 0;
-                       if(botan_privkey_rsa_get_privkey(this->key, NULL, &bits, format))
+                       if (botan_privkey_rsa_get_privkey(this->key, NULL, &len, format)
+                               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
                        {
                                return FALSE;
                        }
 
-                       *encoding = chunk_alloc(bits);
-                       if(botan_privkey_rsa_get_privkey(this->key, encoding->ptr, &bits, format))
+                       *encoding = chunk_alloc(len);
+                       if (botan_privkey_rsa_get_privkey(this->key, encoding->ptr, &len,
+                                                                                         format))
                        {
                                chunk_clear(encoding);
                                return FALSE;
                        }
-
                        return success;
                }
                default:
@@ -498,11 +346,8 @@ METHOD(private_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
-               if (&this->key)
-               {
-                       lib->encoding->clear_cache(lib->encoding, &this->key);
-                       botan_privkey_destroy(this->key);
-               }
+               lib->encoding->clear_cache(lib->encoding, this);
+               botan_privkey_destroy(this->key);
                free(this);
        }
 }
@@ -538,13 +383,13 @@ static private_botan_rsa_private_key_t *create_empty()
 }
 
 /*
- * See header.
+ * Described in header
  */
 botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
                                                                                                   va_list args)
 {
        private_botan_rsa_private_key_t *this;
-
+       botan_rng_t rng;
        u_int key_size = 0;
 
        while (TRUE)
@@ -567,21 +412,19 @@ botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
                return NULL;
        }
 
-       botan_rng_t rng;
-       if (botan_rng_init(&rng, "user"))
+       if (botan_rng_init(&rng, "system"))
        {
                return NULL;
        }
 
        this = create_empty();
 
-       if(botan_privkey_create_rsa(&this->key, rng, key_size))
+       if (botan_privkey_create_rsa(&this->key, rng, key_size))
        {
                botan_rng_destroy(rng);
-               destroy(this);
+               free(this);
                return NULL;
        }
-
        botan_rng_destroy(rng);
        return &this->public;
 }
@@ -593,52 +436,35 @@ botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
 static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
                                                 botan_mp_t *p, botan_mp_t *q)
 {
-       botan_mp_t k, one, r, zero, two, n1, x, y, g, rem;
+       botan_mp_t k = NULL, one = NULL, r = NULL, zero = NULL, two = NULL;
+       botan_mp_t n1 = NULL, x = NULL, y = NULL, g = NULL, rem = NULL;
+       botan_rng_t rng = NULL;
        int i, t, j;
-       bool success = TRUE;
-
-       if (botan_mp_init(&k))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_init(&one))
-       {
-               success = FALSE;
-               goto error;
-       }
+       bool success = FALSE;
 
-       if (botan_mp_set_from_int(one, 1))
+       if (botan_mp_init(&k) ||
+               botan_mp_init(&one) ||
+               botan_mp_set_from_int(one, 1))
        {
-               success = FALSE;
                goto error;
        }
 
-       /* 1. k = de - 1 */
+       /* 1. k = d * e - 1 */
        if (botan_mp_mul(k, *d, *e) || botan_mp_sub(k, k, one))
        {
-               success = FALSE;
                goto error;
        }
 
        /* k must be even */
        if (!botan_mp_is_even(k))
        {
-               success = FALSE;
                goto error;
        }
 
        /* 2. k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
-       if (botan_mp_init(&r))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_set_from_mp(r, k))
+       if (botan_mp_init(&r) ||
+               botan_mp_set_from_mp(r, k))
        {
-               success = FALSE;
                goto error;
        }
 
@@ -646,58 +472,41 @@ static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
        {
                if (botan_mp_rshift(r, r, 1))
                {
-                       success = FALSE;
                        goto error;
                }
        }
 
-       /* need 0, 2, n-1 below */
-       if (botan_mp_init(&zero))
+       /* need 0 and n-1 below */
+       if (botan_mp_init(&zero) ||
+               botan_mp_init(&n1) ||
+               botan_mp_sub(n1, *n, one))
        {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_set_from_int(zero, 0))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_init(&n1))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_sub(n1, *n, one))
-       {
-               success = FALSE;
                goto error;
        }
 
        if (botan_mp_init(&g))
        {
-               success = FALSE;
                goto error;
        }
 
-       botan_rng_t rng;
        if (botan_rng_init(&rng, "user"))
        {
-               success = FALSE;
                goto error;
        }
 
        if (botan_mp_init(&two))
        {
-               success = FALSE;
                goto error;
        }
 
        if (botan_mp_set_from_int(two, 2))
        {
-               success = FALSE;
+               goto error;
+       }
+
+       if (botan_mp_init(&y) ||
+               botan_mp_init(&x))
+       {
                goto error;
        }
 
@@ -706,20 +515,11 @@ static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
                /* 3a. generate a random integer g in the range [0, n-1] */
                if (botan_mp_rand_range(g, rng, zero, n1))
                {
-                       success = FALSE;
                        goto error;
                }
-
                /* 3b. y = g^r mod n */
-               if (botan_mp_init(&y))
-               {
-                       success = FALSE;
-                       goto error;
-               }
-
                if (botan_mp_powmod(y, g, r, *n))
                {
-                       success = FALSE;
                        goto error;
                }
 
@@ -729,18 +529,11 @@ static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
                        continue;
                }
 
-               if (botan_mp_init(&x))
-               {
-                       success = FALSE;
-                       goto error;
-               }
-
                for (j = 0; j < t; j++)
                {
                        /* x = y^2 mod n */
                        if (botan_mp_powmod(x, y, two, *n))
                        {
-                               success = FALSE;
                                goto error;
                        }
 
@@ -757,9 +550,8 @@ static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
                        }
 
                        /* let y = x */
-                       if(botan_mp_set_from_mp(y, x))
+                       if (botan_mp_set_from_mp(y, x))
                        {
-                               success = FALSE;
                                goto error;
                        }
                }
@@ -769,53 +561,36 @@ done:
        /* 5. p = GCD(y – 1, n) and q = n/p */
        if (botan_mp_sub(y, y, one))
        {
-               success = FALSE;
                goto error;
        }
 
-       if (botan_mp_init(p))
+       if (botan_mp_init(p) ||
+               botan_mp_gcd(*p, y, *n))
        {
-               success = FALSE;
                goto error;
        }
 
-       if (botan_mp_gcd(*p, y, *n))
+       if (botan_mp_init(q) ||
+               botan_mp_init(&rem) ||
+               botan_mp_div(*q, rem, *n, *p))
        {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_init(q))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_init(&rem))
-       {
-               success = FALSE;
-               goto error;
-       }
-
-       if (botan_mp_div(*q, rem, *n, *p))
-       {
-               success = FALSE;
                goto error;
        }
 
        if (!botan_mp_is_zero(rem))
        {
-               success = FALSE;
                goto error;
        }
 
+       success = TRUE;
+
 error:
        if (!success)
        {
                botan_mp_destroy(*p);
                botan_mp_destroy(*q);
        }
-
+       botan_rng_destroy(rng);
        botan_mp_destroy(k);
        botan_mp_destroy(one);
        botan_mp_destroy(r);
@@ -824,12 +599,13 @@ error:
        botan_mp_destroy(n1);
        botan_mp_destroy(x);
        botan_mp_destroy(y);
+       botan_mp_destroy(g);
        botan_mp_destroy(rem);
        return success;
 }
 
 /*
- * See header
+ * Described in header
  */
 botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
                                                                                                        va_list args)
@@ -880,38 +656,37 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
 
                if (botan_privkey_load_rsa_pkcs1(&this->key, blob.ptr, blob.len))
                {
-                       destroy(this);
+                       free(this);
                        return NULL;
                }
-
                return &this->public;
        }
 
        if (n.ptr && e.ptr && d.ptr)
        {
-               botan_mp_t n_mp, e_mp, d_mp;
-               if (chunk_to_botan_mp(n, &n_mp))
+               botan_mp_t n_mp, e_mp, d_mp, p_mp, q_mp;
+
+               if (!chunk_to_botan_mp(n, &n_mp))
                {
                        return NULL;
                }
 
-               if (chunk_to_botan_mp(e, &e_mp))
+               if (!chunk_to_botan_mp(e, &e_mp))
                {
                        botan_mp_destroy(n_mp);
                        return NULL;
                }
 
-               if (chunk_to_botan_mp(d, &d_mp))
+               if (!chunk_to_botan_mp(d, &d_mp))
                {
                        botan_mp_destroy(n_mp);
                        botan_mp_destroy(e_mp);
                        return NULL;
                }
 
-               botan_mp_t p_mp, q_mp;
                if (p.ptr && q.ptr)
                {
-                       if (chunk_to_botan_mp(p, &p_mp))
+                       if (!chunk_to_botan_mp(p, &p_mp))
                        {
                                botan_mp_destroy(n_mp);
                                botan_mp_destroy(e_mp);
@@ -919,7 +694,7 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
                                return NULL;
                        }
 
-                       if (chunk_to_botan_mp(q, &q_mp))
+                       if (!chunk_to_botan_mp(q, &q_mp))
                        {
                                botan_mp_destroy(n_mp);
                                botan_mp_destroy(e_mp);
@@ -930,7 +705,7 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
                }
                else
                {
-                       // calculate p,q from n, e, d
+                       /* calculate p,q from n, e, d */
                        if (!calculate_pq(&n_mp, &e_mp, &d_mp, &p_mp, &q_mp))
                        {
                                botan_mp_destroy(n_mp);
@@ -939,6 +714,8 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
                                return NULL;
                        }
                }
+               botan_mp_destroy(n_mp);
+               botan_mp_destroy(d_mp);
 
                this = create_empty();
 
@@ -947,7 +724,7 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
                        botan_mp_destroy(e_mp);
                        botan_mp_destroy(p_mp);
                        botan_mp_destroy(q_mp);
-                       destroy(this);
+                       free(this);
                        return NULL;
                }
 
index b2445b5..617fad5 100644 (file)
@@ -43,6 +43,7 @@ typedef struct private_botan_rsa_public_key_t private_botan_rsa_public_key_t;
  * Private data structure with signing context.
  */
 struct private_botan_rsa_public_key_t {
+
        /**
         * Public interface for this signer
         */
@@ -60,53 +61,11 @@ struct private_botan_rsa_public_key_t {
 };
 
 /**
- * Get the binary representation of a named RSA parameter
- */
-static int botan_rsa_get_field(botan_pubkey_t *key, const char *field_name,
-                                                          chunk_t *value)
-{
-       botan_mp_t field;
-       size_t field_size = 0;
-
-       if (botan_mp_init(&field))
-       {
-               return -1;
-       }
-
-       if (botan_pubkey_get_field(field, *key, field_name))
-       {
-               return -1;
-       }
-
-       if (botan_mp_num_bytes(field, &field_size))
-       {
-               botan_mp_destroy(field);
-               return -1;
-       }
-
-       if (field_size == 0)
-       {
-               botan_mp_destroy(field);
-               return -1;
-       }
-
-       *value = chunk_empty;
-       *value = chunk_alloc(field_size);
-       if (botan_mp_to_bin(field, value->ptr))
-       {
-               botan_mp_destroy(field);
-               chunk_clear(value);
-               return -1;
-       }
-
-       return 0;
-}
-
-/**
  * Verify RSA signature
  */
 static bool verify_rsa_signature(private_botan_rsa_public_key_t *this,
-               const char* hash_and_padding, chunk_t data, chunk_t signature)
+                                                                const char* hash_and_padding, chunk_t data,
+                                                                chunk_t signature)
 {
        botan_pk_op_verify_t verify_op;
        bool valid = FALSE;
@@ -122,116 +81,51 @@ static bool verify_rsa_signature(private_botan_rsa_public_key_t *this,
                return FALSE;
        }
 
-       valid =
-               !(botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len));
+       valid = !botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len);
 
        botan_pk_op_verify_destroy(verify_op);
        return valid;
 }
 
 /**
- * Verification of an EMSA PKCS1 signature described in PKCS#1
- */
-static bool verify_emsa_pkcs1_signature(private_botan_rsa_public_key_t *this,
-               const char* hash_and_padding, chunk_t data, chunk_t signature)
-{
-       return verify_rsa_signature(this, hash_and_padding, data, signature);
-}
-
-static bool botan_get_hash(hash_algorithm_t hash, char* hash_str)
-{
-       switch (hash)
-       {
-               case HASH_SHA1:
-                       sprintf(hash_str, "SHA-1");
-                       break;
-               case HASH_SHA224:
-                       sprintf(hash_str, "SHA-224");
-                       break;
-               case HASH_SHA256:
-                       sprintf(hash_str, "SHA-256");
-                       break;
-               case HASH_SHA384:
-                       sprintf(hash_str, "SHA-384");
-                       break;
-               case HASH_SHA512:
-                       sprintf(hash_str, "SHA-512");
-                       break;
-               default:
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-/**
  * Verification of an EMSA PSS signature described in PKCS#1
  */
 static bool verify_emsa_pss_signature(private_botan_rsa_public_key_t *this,
                                                                          rsa_pss_params_t *params, chunk_t data,
                                                                          chunk_t signature)
 {
-       char* hash_and_padding, *hash, *mgf1_hash;
-       char* salt_len = NULL;
-       size_t len;
-       bool success = FALSE;
+       const char *hash;
+       char hash_and_padding[BUF_LEN];
 
        if (!params)
        {
                return FALSE;
        }
 
-       // botan currently does not support passing the mgf1 hash
+       /* botan currently does not support passing the mgf1 hash */
        if (params->hash != params->mgf1_hash)
        {
                DBG1(DBG_LIB, "passing mgf1 hash not supported via botan");
                return FALSE;
        }
 
-       hash = malloc(8);
-       if(!botan_get_hash(params->hash, hash))
-       {
-               free(hash);
-               return FALSE;
-       }
-
-       mgf1_hash = malloc(8);
-       if(!botan_get_hash(params->mgf1_hash, mgf1_hash))
+       hash = botan_get_hash(params->hash);
+       if (!hash)
        {
-               free(hash);
-               free(mgf1_hash);
                return FALSE;
        }
 
-       if(params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
+       if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
        {
-               salt_len = malloc(6);
-               snprintf(salt_len, 5, "%d", params->salt_len);
-       }
-
-       len = 24 + strlen(hash) + strlen(mgf1_hash);
-       hash_and_padding = malloc(len+1);
-
-       if(salt_len)
-       {
-               snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1,%s)", hash, salt_len);
+               snprintf(hash_and_padding, sizeof(hash_and_padding),
+                                "EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
        }
        else
        {
-               snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1)", hash);
+               snprintf(hash_and_padding, sizeof(hash_and_padding),
+                                "EMSA-PSS(%s,MGF1)", hash);
        }
-
-       if (verify_rsa_signature(this, hash_and_padding, data, signature))
-       {
-               success = TRUE;
-       }
-
-       if(salt_len)
-               free(salt_len);
-       free(hash);
-       free(mgf1_hash);
-       free(hash_and_padding);
-       return success;
+       return verify_rsa_signature(this, hash_and_padding, data, signature);
 }
 
 METHOD(public_key_t, get_type, key_type_t,
@@ -247,23 +141,23 @@ METHOD(public_key_t, verify, bool,
        switch (scheme)
        {
                case SIGN_RSA_EMSA_PKCS1_NULL:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(Raw)", data,
-                                                                                          signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(Raw)", data,
+                                                                               signature);
                case SIGN_RSA_EMSA_PKCS1_SHA1:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-1)", data,
-                                                                                          signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(SHA-1)", data,
+                                                                               signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_224:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-224)",
-                                                                                          data, signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(SHA-224)",
+                                                                               data, signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_256:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-256)",
-                                                                                          data, signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(SHA-256)",
+                                                                               data, signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_384:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-384)",
-                                                                                          data, signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(SHA-384)",
+                                                                               data, signature);
                case SIGN_RSA_EMSA_PKCS1_SHA2_512:
-                       return verify_emsa_pkcs1_signature(this, "EMSA_PKCS1(SHA-512)",
-                                                                                          data, signature);
+                       return verify_rsa_signature(this, "EMSA_PKCS1(SHA-512)",
+                                                                               data, signature);
                case SIGN_RSA_EMSA_PSS:
                        return verify_emsa_pss_signature(this, params, data, signature);
                default:
@@ -277,6 +171,8 @@ METHOD(public_key_t, encrypt, bool,
        private_botan_rsa_public_key_t *this, encryption_scheme_t scheme,
        chunk_t plain, chunk_t *crypto)
 {
+       botan_pk_op_encrypt_t encrypt_op;
+       botan_rng_t rng;
        const char* padding;
 
        switch (scheme)
@@ -305,34 +201,25 @@ METHOD(public_key_t, encrypt, bool,
                        return FALSE;
        }
 
-       botan_rng_t rng;
        if (botan_rng_init(&rng, "user"))
        {
                return FALSE;
        }
 
-       botan_pk_op_encrypt_t encrypt_op;
        if (botan_pk_op_encrypt_create(&encrypt_op, this->key, padding, 0))
        {
                botan_rng_destroy(rng);
                return FALSE;
        }
 
-       /*
-        *  get size of ciphertext first
-        */
-       if (botan_pk_op_encrypt(encrypt_op, rng, NULL, &crypto->len, plain.ptr,
-                                                       plain.len)
-               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+       crypto->len = 0;
+       if (botan_pk_op_encrypt_output_length(encrypt_op, plain.len, &crypto->len))
        {
                botan_rng_destroy(rng);
                botan_pk_op_encrypt_destroy(encrypt_op);
                return FALSE;
        }
 
-       /*
-        * now get the ciphertext
-        */
        *crypto = chunk_alloc(crypto->len);
        if (botan_pk_op_encrypt(encrypt_op, rng, crypto->ptr, &crypto->len,
                                                        plain.ptr, plain.len))
@@ -342,7 +229,6 @@ METHOD(public_key_t, encrypt, bool,
                botan_pk_op_encrypt_destroy(encrypt_op);
                return FALSE;
        }
-
        botan_rng_destroy(rng);
        botan_pk_op_encrypt_destroy(encrypt_op);
        return TRUE;
@@ -356,18 +242,14 @@ METHOD(public_key_t, get_keysize, int,
 
        if (botan_mp_init(&n))
        {
-               return -1;
-       }
-
-       if (botan_pubkey_rsa_get_n(n, this->key))
-       {
-               return -1;
+               return 0;
        }
 
-       if (botan_mp_num_bits(n, &bits))
+       if (botan_pubkey_rsa_get_n(n, this->key) ||
+               botan_mp_num_bits(n, &bits))
        {
                botan_mp_destroy(n);
-               return -1;
+               return 0;
        }
 
        botan_mp_destroy(n);
@@ -378,59 +260,14 @@ METHOD(public_key_t, get_fingerprint, bool,
        private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
        chunk_t *fp)
 {
-       chunk_t n, e;
-       bool success = FALSE;
-
-       if (lib->encoding->get_cache(lib->encoding, type, &this->key, fp))
-       {
-               return TRUE;
-       }
-
-       if (botan_rsa_get_field(&this->key, "n", &n))
-       {
-               return FALSE;
-       }
-
-       if (botan_rsa_get_field(&this->key, "e", &e))
-       {
-               chunk_free(&n);
-               return FALSE;
-       }
-
-       success = lib->encoding->encode(lib->encoding, type, &this->key, fp,
-                                                                       CRED_PART_RSA_MODULUS, n,
-                                                                       CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
-
-       chunk_free(&n);
-       chunk_free(&e);
-       return success;
+       return botan_get_fingerprint(this->key, this, type, fp);
 }
 
 METHOD(public_key_t, get_encoding, bool,
        private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
        chunk_t *encoding)
 {
-       chunk_t n, e;
-       bool success = FALSE;
-
-       if (botan_rsa_get_field(&this->key, "n", &n))
-       {
-               return FALSE;
-       }
-
-       if (botan_rsa_get_field(&this->key, "e", &e))
-       {
-               chunk_free(&n);
-               return FALSE;
-       }
-
-       success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
-                                                                       CRED_PART_RSA_MODULUS, n,
-                                                                       CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
-
-       chunk_free(&n);
-       chunk_free(&e);
-       return success;
+       return botan_get_encoding(this->key, type, encoding);
 }
 
 METHOD(public_key_t, get_ref, public_key_t*,
@@ -445,11 +282,8 @@ METHOD(public_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
-               if (&this->key)
-               {
-                       lib->encoding->clear_cache(lib->encoding, &this->key);
-                       botan_pubkey_destroy(this->key);
-               }
+               lib->encoding->clear_cache(lib->encoding, this);
+               botan_pubkey_destroy(this->key);
                free(this);
        }
 }
@@ -482,14 +316,13 @@ static private_botan_rsa_public_key_t *create_empty()
        return this;
 }
 
-/**
- * See header.
+/*
+ * Described in header
  */
 botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
-               va_list args)
+                                                                                                 va_list args)
 {
        private_botan_rsa_public_key_t *this = NULL;
-
        chunk_t blob, n, e;
 
        n = e = blob = chunk_empty;
@@ -519,43 +352,41 @@ botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
                switch (type)
                {
                        /* SubjectPublicKeyInfo */
+                       case KEY_RSA:
                        case KEY_ANY:
                        {
+                               size_t namesize = 0;
+                               char *namebuf;
+
                                this = create_empty();
 
                                if (botan_pubkey_load(&this->key, blob.ptr, blob.len))
                                {
-                                       destroy(this);
+                                       free(this);
                                        return NULL;
                                }
 
-                               size_t namesize = 0;
                                if (botan_pubkey_algo_name(this->key, NULL, &namesize)
                                        != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
                                {
-                                       botan_pubkey_destroy(this->key);
                                        destroy(this);
                                        return NULL;
                                }
 
-                               char* namebuf = malloc(namesize);
+                               namebuf = malloc(namesize);
                                if (botan_pubkey_algo_name(this->key, namebuf, &namesize))
                                {
                                        free(namebuf);
-                                       botan_pubkey_destroy(this->key);
                                        destroy(this);
                                        return NULL;
                                }
 
-                               const char* algo_name = "RSA";
-                               if (!strneq(namebuf, algo_name, sizeof(algo_name)))
+                               if (!strneq(namebuf, "RSA", namesize))
                                {
                                        free(namebuf);
-                                       botan_pubkey_destroy(this->key);
                                        destroy(this);
                                        return NULL;
                                }
-
                                free(namebuf);
                                break;
                        }
@@ -563,16 +394,16 @@ botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
                                return NULL;
                }
        }
-       else if(n.ptr && e.ptr && type == KEY_RSA)
+       else if (n.ptr && e.ptr && type == KEY_RSA)
        {
-
                botan_mp_t mp_n, mp_e;
-               if (chunk_to_botan_mp(n, &mp_n))
+
+               if (!chunk_to_botan_mp(n, &mp_n))
                {
                        return NULL;
                }
 
-               if (chunk_to_botan_mp(e, &mp_e))
+               if (!chunk_to_botan_mp(e, &mp_e))
                {
                        botan_mp_destroy(mp_n);
                        return NULL;
@@ -584,18 +415,15 @@ botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
                {
                        botan_mp_destroy(mp_n);
                        botan_mp_destroy(mp_e);
-                       destroy(this);
+                       free(this);
                        return NULL;
                }
 
                botan_mp_destroy(mp_n);
                botan_mp_destroy(mp_e);
        }
-       if (this != NULL)
-       {
-               return &this->public;
-       }
-       return NULL;
+
+       return &this->public;
 }
 
-#endif
\ No newline at end of file
+#endif
index d69e29e..9dcf592 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2018 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2018 René Korthaus
  * Rohde & Schwarz Cybersecurity GmbH
  *
 
 #include <botan/ffi.h>
 
-int chunk_to_botan_mp(chunk_t value, botan_mp_t *mp)
+/*
+ * Described in header
+ */
+bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp)
 {
        if (botan_mp_init(mp))
        {
-               return -1;
+               return FALSE;
        }
 
        if (botan_mp_from_bin(*mp, value.ptr, value.len))
        {
                botan_mp_destroy(*mp);
-               return -1;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+/*
+ * Described in header
+ */
+const char *botan_get_hash(hash_algorithm_t hash)
+{
+       switch (hash)
+       {
+               case HASH_MD5:
+                       return "MD5";
+               case HASH_SHA1:
+                       return "SHA-1";
+               case HASH_SHA224:
+                       return "SHA-224";
+               case HASH_SHA256:
+                       return "SHA-256";
+               case HASH_SHA384:
+                       return "SHA-384";
+               case HASH_SHA512:
+                       return "SHA-512";
+               default:
+                       return NULL;
+       }
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
+                                               chunk_t *encoding)
+{
+       bool success = TRUE;
+
+       encoding->len = 0;
+       if (botan_pubkey_export(pubkey, NULL, &encoding->len,
+                                                       BOTAN_PRIVKEY_EXPORT_FLAG_DER)
+               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+       {
+               return FALSE;
+       }
+
+       *encoding = chunk_alloc(encoding->len);
+       if (botan_pubkey_export(pubkey, encoding->ptr, &encoding->len,
+                                                       BOTAN_PRIVKEY_EXPORT_FLAG_DER))
+       {
+               chunk_free(encoding);
+               return FALSE;
+       }
+
+       if (type != PUBKEY_SPKI_ASN1_DER)
+       {
+               chunk_t asn1_encoding = *encoding;
+
+               success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
+                                                                               CRED_PART_ECDSA_PUB_ASN1_DER,
+                                                                               asn1_encoding, CRED_PART_END);
+               chunk_free(&asn1_encoding);
+       }
+       return success;
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
+                                                  cred_encoding_type_t type, chunk_t *fp)
+{
+       hasher_t *hasher;
+       chunk_t key;
+
+       if (cache &&
+               lib->encoding->get_cache(lib->encoding, type, cache, fp))
+       {
+               return TRUE;
        }
-       return 0;
+
+       switch (type)
+       {
+               case KEYID_PUBKEY_SHA1:
+               {
+                       /* subjectPublicKey -> use botan_pubkey_fingerprint() */
+                       fp->len = 0;
+                       if (botan_pubkey_fingerprint(pubkey, "SHA-1", NULL, &fp->len)
+                               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+                       {
+                               return FALSE;
+                       }
+
+                       *fp = chunk_alloc(fp->len);
+                       if (botan_pubkey_fingerprint(pubkey, "SHA-1", fp->ptr, &fp->len))
+                       {
+                               chunk_free(fp);
+                               return FALSE;
+                       }
+                       break;
+               }
+               case KEYID_PUBKEY_INFO_SHA1:
+               {
+                       /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */
+                       if (!botan_get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &key))
+                       {
+                               return FALSE;
+                       }
+
+                       hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+                       if (!hasher || !hasher->allocate_hash(hasher, key, fp))
+                       {
+                               DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
+                                        "fingerprinting failed");
+                               DESTROY_IF(hasher);
+                               chunk_free(&key);
+                               return FALSE;
+                       }
+                       hasher->destroy(hasher);
+                       chunk_free(&key);
+                       break;
+               }
+               default:
+                       return FALSE;
+       }
+
+       if (cache)
+       {
+               lib->encoding->cache(lib->encoding, type, cache, *fp);
+       }
+       return TRUE;
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_signature(botan_privkey_t key, const char *scheme,
+                                                chunk_t data, chunk_t *signature)
+{
+       botan_pk_op_sign_t sign_op;
+       botan_rng_t rng;
+
+       if (!scheme || !signature)
+       {
+               return FALSE;
+       }
+
+       if (botan_pk_op_sign_create(&sign_op, key, scheme, 0))
+       {
+               return FALSE;
+       }
+
+       if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
+       {
+               botan_pk_op_sign_destroy(sign_op);
+               return FALSE;
+       }
+
+       signature->len = 0;
+       if (botan_pk_op_sign_output_length(sign_op, &signature->len))
+       {
+               botan_pk_op_sign_destroy(sign_op);
+               return FALSE;
+       }
+
+       if (botan_rng_init(&rng, "user"))
+       {
+               botan_pk_op_sign_destroy(sign_op);
+               return FALSE;
+       }
+
+       *signature = chunk_alloc(signature->len);
+       if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
+       {
+               chunk_free(signature);
+               botan_rng_destroy(rng);
+               botan_pk_op_sign_destroy(sign_op);
+               return FALSE;
+       }
+
+       botan_rng_destroy(rng);
+       botan_pk_op_sign_destroy(sign_op);
+       return TRUE;
 }
index d196587..1f4b96f 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2018 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2018 René Korthaus
  * Rohde & Schwarz Cybersecurity GmbH
  *
 #include <botan/ffi.h>
 
 /**
- * Converts chunk_t to botan_mp_t
+ * Converts chunk_t to botan_mp_t.
+ *
+ * @param value                chunk to convert
+ * @param mp           allocated botan_mp_t
+ * @return                     TRUE if conversion successful
+ */
+bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
+
+/**
+ * Get the Botan string identifier for the given hash algorithm.
+ *
+ * @param hash         hash algorithm
+ * @return                     Botan string identifier, NULL if not found
+ */
+const char *botan_get_hash(hash_algorithm_t hash);
+
+/**
+ * Get the encoding of a botan_pubkey_t.
+ *
+ * @param pubkey       public key object
+ * @param type         encoding type
+ * @param encoding     allocated encoding
+ * @return                     TRUE if encoding successful
+ */
+bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
+                                               chunk_t *encoding);
+
+/**
+ * Get the fingerprint of a botan_pubkey_t.
+ *
+ * @param pubkey       public key object
+ * @param cache                key to use for caching, NULL to not cache
+ * @param type         fingerprint type
+ * @param fp           allocated fingerprint
+ * @return                     TRUE if fingerprinting successful
+ */
+bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
+                                                  cred_encoding_type_t type, chunk_t *fp);
+
+/**
+ * Sign the given data using the provided key with the specified signature
+ * scheme (hash/padding).
+ *
+ * @param key          private key object
+ * @param scheme       hash/padding algorithm
+ * @param data         data to sign
+ * @param signature    allocated signature
+ * @return                     TRUE if signature successfully created
  */
-int chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
+bool botan_get_signature(botan_privkey_t key, const char *scheme,
+                                                chunk_t data, chunk_t *signature);
 
 #endif /** BOTAN_UTIL_H_ @}*/