From: Tobias Brunner Date: Mon, 6 Aug 2018 15:46:54 +0000 (+0200) Subject: botan: Fixes, code style changes plus some refactorings X-Git-Tag: 5.7.0rc1~4^2~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de2a24310c1b86f6652560f927b77d5e724730cb;p=thirdparty%2Fstrongswan.git botan: Fixes, code style changes plus some refactorings Some changes rely on newly added FFI functions in Botan's master branch. --- diff --git a/src/libstrongswan/plugins/botan/Makefile.am b/src/libstrongswan/plugins/botan/Makefile.am index 95df441308..bbad715410 100644 --- a/src/libstrongswan/plugins/botan/Makefile.am +++ b/src/libstrongswan/plugins/botan/Makefile.am @@ -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 diff --git a/src/libstrongswan/plugins/botan/botan_crypter.c b/src/libstrongswan/plugins/botan/botan_crypter.c index af8fe4c437..002be6ea81 100644 --- a/src/libstrongswan/plugins/botan/botan_crypter.c +++ b/src/libstrongswan/plugins/botan/botan_crypter.c @@ -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); diff --git a/src/libstrongswan/plugins/botan/botan_diffie_hellman.c b/src/libstrongswan/plugins/botan/botan_diffie_hellman.c index 2ca14f35a3..422b4aea14 100644 --- a/src/libstrongswan/plugins/botan/botan_diffie_hellman.c +++ b/src/libstrongswan/plugins/botan/botan_diffie_hellman.c @@ -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 diff --git a/src/libstrongswan/plugins/botan/botan_diffie_hellman.h b/src/libstrongswan/plugins/botan/botan_diffie_hellman.h index 88f221d343..84408229fa 100644 --- a/src/libstrongswan/plugins/botan/botan_diffie_hellman.h +++ b/src/libstrongswan/plugins/botan/botan_diffie_hellman.h @@ -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_ @}*/ - diff --git a/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.c b/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.c index 48b231f88b..a482bc0289 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.c +++ b/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.c @@ -27,19 +27,21 @@ #ifdef BOTAN_HAS_ECDH +#include "botan_util.h" + #include #include -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; } diff --git a/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.h b/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.h index f4751de01a..0ba832ed35 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.h +++ b/src/libstrongswan/plugins/botan/botan_ec_diffie_hellman.h @@ -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_ @}*/ - diff --git a/src/libstrongswan/plugins/botan/botan_ec_private_key.c b/src/libstrongswan/plugins/botan/botan_ec_private_key.c index abb4597ad3..e5a6c7c4d6 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_private_key.c +++ b/src/libstrongswan/plugins/botan/botan_ec_private_key.c @@ -24,6 +24,7 @@ #include "botan_ec_private_key.h" +#include "botan_util.h" #include @@ -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 char* curve; + 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 diff --git a/src/libstrongswan/plugins/botan/botan_ec_private_key.h b/src/libstrongswan/plugins/botan/botan_ec_private_key.h index 0fcfda25e6..9450331a45 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_private_key.h +++ b/src/libstrongswan/plugins/botan/botan_ec_private_key.h @@ -30,10 +30,6 @@ #ifndef BOTAN_EC_PRIVATE_KEY_H_ #define BOTAN_EC_PRIVATE_KEY_H_ -#include - -#ifdef BOTAN_HAS_ECDSA - #include #include @@ -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_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_ec_public_key.c b/src/libstrongswan/plugins/botan/botan_ec_public_key.c index abc513b709..54782bcbff 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_ec_public_key.c @@ -23,6 +23,7 @@ */ #include "botan_ec_public_key.h" +#include "botan_util.h" #include @@ -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; } diff --git a/src/libstrongswan/plugins/botan/botan_gcm.c b/src/libstrongswan/plugins/botan/botan_gcm.c index 7fc59bdc17..7e0fc1468a 100644 --- a/src/libstrongswan/plugins/botan/botan_gcm.c +++ b/src/libstrongswan/plugins/botan/botan_gcm.c @@ -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 diff --git a/src/libstrongswan/plugins/botan/botan_gcm.h b/src/libstrongswan/plugins/botan/botan_gcm.h index 600e60b0e4..b2053cb4d9 100644 --- a/src/libstrongswan/plugins/botan/botan_gcm.h +++ b/src/libstrongswan/plugins/botan/botan_gcm.h @@ -31,23 +31,17 @@ #ifndef BOTAN_GCM_H_ #define BOTAN_GCM_H_ -#include - -#ifdef BOTAN_HAS_AEAD_GCM - #include /** * 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_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_hasher.c b/src/libstrongswan/plugins/botan/botan_hasher.c index 06b2ad9b2d..3a8fcd8020 100644 --- a/src/libstrongswan/plugins/botan/botan_hasher.c +++ b/src/libstrongswan/plugins/botan/botan_hasher.c @@ -22,6 +22,7 @@ */ #include "botan_hasher.h" +#include "botan_util.h" #include @@ -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; } diff --git a/src/libstrongswan/plugins/botan/botan_hmac.c b/src/libstrongswan/plugins/botan/botan_hmac.c index a1e3514d8e..367d27f24c 100644 --- a/src/libstrongswan/plugins/botan/botan_hmac.c +++ b/src/libstrongswan/plugins/botan/botan_hmac.c @@ -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; } diff --git a/src/libstrongswan/plugins/botan/botan_plugin.c b/src/libstrongswan/plugins/botan/botan_plugin.c index 0fb9159c19..bce6b8fee5 100644 --- a/src/libstrongswan/plugins/botan/botan_plugin.c +++ b/src/libstrongswan/plugins/botan/botan_plugin.c @@ -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 */ @@ -156,7 +156,6 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(DH, ECP_256_BP), PLUGIN_PROVIDE(DH, ECP_384_BP), PLUGIN_PROVIDE(DH, ECP_512_BP), -#endif #endif /* RSA */ #ifdef BOTAN_HAS_RSA @@ -265,7 +264,7 @@ METHOD(plugin_t, destroy, void, } /* - * see header file + * Described in header */ plugin_t *botan_plugin_create() { diff --git a/src/libstrongswan/plugins/botan/botan_rng.c b/src/libstrongswan/plugins/botan/botan_rng.c index f398f9fb7c..c49225c3c2 100644 --- a/src/libstrongswan/plugins/botan/botan_rng.c +++ b/src/libstrongswan/plugins/botan/botan_rng.c @@ -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; } diff --git a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c index c35e0c2b66..29f6923337 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c @@ -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; } diff --git a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c index b2445b5f92..617fad5d1c 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c @@ -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 */ @@ -59,54 +60,12 @@ struct private_botan_rsa_public_key_t { refcount_t ref; }; -/** - * 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,48 +81,12 @@ 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 */ @@ -171,67 +94,38 @@ 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 diff --git a/src/libstrongswan/plugins/botan/botan_util.c b/src/libstrongswan/plugins/botan/botan_util.c index d69e29e625..9dcf592c54 100644 --- a/src/libstrongswan/plugins/botan/botan_util.c +++ b/src/libstrongswan/plugins/botan/botan_util.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Rohde & Schwarz Cybersecurity GmbH * @@ -27,17 +30,199 @@ #include -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; } diff --git a/src/libstrongswan/plugins/botan/botan_util.h b/src/libstrongswan/plugins/botan/botan_util.h index d19658740a..1f4b96f6e6 100644 --- a/src/libstrongswan/plugins/botan/botan_util.h +++ b/src/libstrongswan/plugins/botan/botan_util.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Rohde & Schwarz Cybersecurity GmbH * @@ -34,8 +37,56 @@ #include /** - * 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_ @}*/