botan: Fixes, code style changes plus some refactorings
Some changes rely on newly added FFI functions in Botan's master branch.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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_create(&op, this->dh_key, "Raw", 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
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
|
||||
|
||||
@@ -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_ @}*/
|
||||
|
||||
|
||||
@@ -27,19 +27,21 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
if (out_len == 0)
|
||||
{
|
||||
botan_pk_op_key_agreement_destroy(ka);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
this->shared_secret = chunk_alloc(out_len);
|
||||
|
||||
if (botan_pk_op_key_agreement_size(ka, &this->shared_secret.len))
|
||||
{
|
||||
botan_pk_op_key_agreement_destroy(ka);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ @}*/
|
||||
|
||||
|
||||
@@ -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)
|
||||
if (!botan_get_signature(key, hash_and_padding, data, signature))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
botan_pk_op_sign_t sign_op;
|
||||
|
||||
if (botan_pk_op_sign_create(&sign_op, key, hash_and_padding, 0))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if(botan_privkey_get_field(p, this->key, "p"))
|
||||
{
|
||||
botan_mp_destroy(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bits = 0;
|
||||
if(botan_mp_num_bits(p, &bits))
|
||||
|
||||
if (botan_mp_init(&p))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
#endif
|
||||
|
||||
@@ -30,10 +30,6 @@
|
||||
#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_ @}*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
if(botan_pubkey_get_field(p, this->key, "p"))
|
||||
{
|
||||
botan_mp_destroy(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bits = 0;
|
||||
if(botan_mp_num_bits(p, &bits))
|
||||
|
||||
if (botan_mp_init(&p))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
@@ -31,23 +31,17 @@
|
||||
#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_ @}*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
size_t field_size = 0;
|
||||
|
||||
if (botan_mp_init(&field))
|
||||
{
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_get_field(field, *key, field_name))
|
||||
if (botan_privkey_get_field(field, *key, field_name) ||
|
||||
botan_mp_num_bytes(field, &field_size) ||
|
||||
!field_size)
|
||||
{
|
||||
botan_mp_destroy(field);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t field_size = 0;
|
||||
if (botan_mp_num_bytes(field, &field_size))
|
||||
{
|
||||
botan_mp_destroy(field);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (field_size == 0)
|
||||
{
|
||||
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;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
hash = botan_get_hash(params->hash);
|
||||
if (!hash)
|
||||
{
|
||||
free(hash);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mgf1_hash = malloc(8);
|
||||
if (!botan_get_hash(params->mgf1_hash, mgf1_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;
|
||||
size_t bits = 0;
|
||||
|
||||
if (botan_mp_init(&n))
|
||||
{
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_privkey_rsa_get_n(n, this->key))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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))
|
||||
if (botan_privkey_export_pubkey(&pubkey, this->key))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_rsa_get_field(&this->key, "e", &e))
|
||||
{
|
||||
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;
|
||||
bool success = FALSE;
|
||||
|
||||
if (botan_mp_init(&k))
|
||||
if (botan_mp_init(&k) ||
|
||||
botan_mp_init(&one) ||
|
||||
botan_mp_set_from_int(one, 1))
|
||||
{
|
||||
success = FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(&one))
|
||||
{
|
||||
success = FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (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))
|
||||
if (botan_mp_init(&r) ||
|
||||
botan_mp_set_from_mp(r, k))
|
||||
{
|
||||
success = FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
hash = botan_get_hash(params->hash);
|
||||
if (!hash)
|
||||
{
|
||||
free(hash);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mgf1_hash = malloc(8);
|
||||
if(!botan_get_hash(params->mgf1_hash, mgf1_hash))
|
||||
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
|
||||
{
|
||||
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 (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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_pubkey_rsa_get_n(n, this->key))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
||||
#endif
|
||||
|
||||
@@ -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 <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 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 <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
|
||||
*/
|
||||
int chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
|
||||
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
|
||||
*/
|
||||
bool botan_get_signature(botan_privkey_t key, const char *scheme,
|
||||
chunk_t data, chunk_t *signature);
|
||||
|
||||
#endif /** BOTAN_UTIL_H_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user