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
in = data.ptr;
if (dst)
{
- *dst= chunk_alloc(data.len);
+ *dst = chunk_alloc(data.len);
out = dst->ptr;
}
else
{
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;
}
}
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;
},
);
-
switch (algo)
{
case ENCR_AES_CBC:
}
break;
default:
- {
free(this);
return NULL;
-
- }
}
this->key = chunk_alloc(key_size);
* 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;
}
return FALSE;
}
+ if (botan_pk_op_key_agreement_create(&op, this->dh_key, "Raw", 0))
+ {
+ return FALSE;
+ }
+
chunk_clear(&this->shared_secret);
- botan_pk_op_key_agreement_create(&op, this->dh_key, "Raw", 0);
- /* get shared secret key size */
- if (botan_pk_op_key_agreement(op, NULL, &this->shared_secret.len, value.ptr,
- value.len, NULL, 0)
- != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+ if (botan_pk_op_key_agreement_size(op, &this->shared_secret.len))
{
+ botan_pk_op_key_agreement_destroy(op);
return FALSE;
}
this->shared_secret = chunk_alloc(this->shared_secret.len);
if (botan_pk_op_key_agreement(op, this->shared_secret.ptr,
- &this->shared_secret.len, value.ptr,
- value.len, NULL, 0))
+ &this->shared_secret.len, value.ptr,
+ value.len, NULL, 0))
{
+ chunk_clear(&this->shared_secret);
+ botan_pk_op_key_agreement_destroy(op);
return FALSE;
}
-
+ botan_pk_op_key_agreement_destroy(op);
return TRUE;
}
/* 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;
}
/*
* 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 = {
.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)
{
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
* 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_ @}*/
-
#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;
* Shared secret
*/
chunk_t shared_secret;
-
- /**
- * True if shared secret is computed
- */
- bool computed;
};
METHOD(diffie_hellman_t, set_other_public_value, bool,
private_botan_ec_diffie_hellman_t *this, chunk_t value)
{
+ botan_pk_op_ka_t ka;
+
if (!diffie_hellman_verify_value(this->group, value))
{
return FALSE;
}
- botan_pk_op_ka_t ka;
if (botan_pk_op_key_agreement_create(&ka, this->key, "Raw", 0))
{
return FALSE;
}
- /* prepend 0x04 to indicate uncompressed point format */
- uint8_t indic = 0x04;
- value = chunk_cata("cc", chunk_from_thing(indic), value);
- size_t out_len = 0;
- if (botan_pk_op_key_agreement(ka, NULL, &out_len, value.ptr, value.len,
- NULL, 0)
- != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
- {
- botan_pk_op_key_agreement_destroy(ka);
- return FALSE;
- }
+ chunk_clear(&this->shared_secret);
- if (out_len == 0)
+ if (botan_pk_op_key_agreement_size(ka, &this->shared_secret.len))
{
botan_pk_op_key_agreement_destroy(ka);
return FALSE;
}
- chunk_clear(&this->shared_secret);
- this->shared_secret = chunk_alloc(out_len);
+ /* prepend 0x04 to indicate uncompressed point format */
+ value = chunk_cata("cc", chunk_from_chars(0x04), value);
+
+ this->shared_secret = chunk_alloc(this->shared_secret.len);
if (botan_pk_op_key_agreement(ka, this->shared_secret.ptr,
&this->shared_secret.len, value.ptr,
value.len, NULL, 0))
botan_pk_op_key_agreement_destroy(ka);
return FALSE;
}
-
botan_pk_op_key_agreement_destroy(ka);
- this->computed = TRUE;
return TRUE;
}
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)
{
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;
}
}
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;
}
/*
* 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 = {
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;
}
* @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_ @}*/
-
#include "botan_ec_private_key.h"
+#include "botan_util.h"
#include <botan/build.h>
* 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;
#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
*/
int signature_format, chunk_t data,
chunk_t *signature)
{
- if (!hash_and_padding || !signature)
- {
- return FALSE;
- }
-
- botan_pk_op_sign_t sign_op;
-
- if (botan_pk_op_sign_create(&sign_op, key, hash_and_padding, 0))
+ if (!botan_get_signature(key, hash_and_padding, data, signature))
{
return FALSE;
}
- botan_rng_t rng;
- if (botan_rng_init(&rng, "user"))
- {
- return FALSE;
- }
-
- /* get size of signature first */
- if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- signature->len = 0;
- if (botan_pk_op_sign_finish(sign_op, rng, NULL, &signature->len)
- != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- /* now get the signature */
- *signature = chunk_alloc(signature->len);
- if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
-
if (signature_format == SIG_FORMAT_DER_SEQUENCE)
{
/* format as ASN.1 sequence of two integers r,s */
- chunk_t r, s = chunk_empty;
+ chunk_t r = chunk_empty, s = chunk_empty;
+
chunk_split(*signature, "aa", signature->len / 2, &r,
- signature->len / 2, &s);
+ signature->len / 2, &s);
chunk_free(signature);
- *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("c", r),
- asn1_integer("c", s));
+ *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("m", r),
+ asn1_integer("m", s));
}
-
return TRUE;
}
{
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:
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:
private_botan_ec_private_key_t *this)
{
botan_mp_t p;
- if(botan_mp_init(&p))
- {
- return 0;
- }
+ size_t bits = 0;
- if(botan_privkey_get_field(p, this->key, "p"))
+ if (botan_mp_init(&p))
{
- botan_mp_destroy(p);
return 0;
}
- size_t bits = 0;
- if(botan_mp_num_bits(p, &bits))
+ if (botan_privkey_get_field(p, this->key, "p") ||
+ botan_mp_num_bits(p, &bits))
{
botan_mp_destroy(p);
return 0;
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;
}
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);
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;
}
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;
return FALSE;
}
- chunk_t pval = chunk_empty;
if (botan_mp_num_bytes(x, &pval.len))
{
botan_mp_destroy(x);
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)
{
{
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);
}
}
}
/*
- * 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)
{
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;
}
* 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)
{
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
{
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;
}
{
chunk_clear(&pkcs8);
botan_rng_destroy(rng);
- destroy(this);
+ free(this);
return NULL;
}
return &this->public;
}
-#endif
\ No newline at end of file
+#endif
#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>
botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type,
va_list args);
-#endif
-
#endif /** BOTAN_EC_PRIVATE_KEY_H_ @}*/
*/
#include "botan_ec_public_key.h"
+#include "botan_util.h"
#include <botan/build.h>
* Private data structure with signing context.
*/
struct private_botan_ec_public_key_t {
+
/**
* Public interface for this signer
*/
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)
{
* 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;
}
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,
private_botan_ec_public_key_t *this)
{
botan_mp_t p;
- if(botan_mp_init(&p))
- {
- return 0;
- }
+ size_t bits = 0;
- if(botan_pubkey_get_field(p, this->key, "p"))
+ if (botan_mp_init(&p))
{
- botan_mp_destroy(p);
return 0;
}
- size_t bits = 0;
- if(botan_mp_num_bits(p, &bits))
+ if (botan_pubkey_get_field(p, this->key, "p") ||
+ botan_mp_num_bits(p, &bits))
{
botan_mp_destroy(p);
return 0;
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;
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;
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*,
{
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)
{
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;
}
{
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);
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;
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;
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;
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;
},
);
- 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 */
{
case 0:
key_size = 16;
+ /* FALL */
case 16:
this->cipher_name = "AES-128/GCM(8)";
break;
free(this);
return NULL;
}
+ this->icv_size = 8;
break;
case ENCR_AES_GCM_ICV12:
switch (key_size)
free(this);
return NULL;
}
+ this->icv_size = 12;
break;
case ENCR_AES_GCM_ICV16:
switch (key_size)
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();
}
#endif
-#endif
\ No newline at end of file
+#endif
#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_ @}*/
*/
#include "botan_hasher.h"
+#include "botan_util.h"
#include <utils/debug.h>
private_botan_hasher_t *this)
{
size_t len = 0;
+
if (botan_hash_output_length(this->hash, &len))
{
return 0;
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;
}
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,
{
return NULL;
}
-
return &this->public;
}
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;
}
private_botan_mac_t *this)
{
size_t len = 0;
+
if (botan_mac_output_length(this->hmac, &len))
{
return 0;
free(this);
return NULL;
}
-
return &this->public;
}
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 */
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 */
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
}
/*
- * see header file
+ * Described in header
*/
plugin_t *botan_plugin_create()
{
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,
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)
{
{
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";
},
},
.quality = quality,
- .rng_name = rng_name,
);
+ if (botan_rng_init(&this->rng, rng_name))
+ {
+ free(this);
+ return NULL;
+ }
return &this->public;
}
* Private data of a botan_rsa_private_key_t object.
*/
struct private_botan_rsa_private_key_t {
+
/**
* Public interface for this signer.
*/
*/
botan_privkey_t key;
-
/**
* reference count
*/
/**
* Get the binary representation of a named RSA parameter
*/
-static int botan_rsa_get_field(botan_privkey_t *key, const char *field_name,
- chunk_t *value)
+static bool get_rsa_field(botan_privkey_t *key, const char *field_name,
+ chunk_t *value)
{
botan_mp_t field;
- if (botan_mp_init(&field))
- {
- return -1;
- }
-
- if (botan_privkey_get_field(field, *key, field_name))
- {
- botan_mp_destroy(field);
- return -1;
- }
-
size_t field_size = 0;
- if (botan_mp_num_bytes(field, &field_size))
+
+ if (botan_mp_init(&field))
{
- botan_mp_destroy(field);
- return -1;
+ return FALSE;
}
- if (field_size == 0)
+ if (botan_privkey_get_field(field, *key, field_name) ||
+ botan_mp_num_bytes(field, &field_size) ||
+ !field_size)
{
botan_mp_destroy(field);
- return -1;
+ return FALSE;
}
*value = chunk_alloc(field_size);
{
botan_mp_destroy(field);
chunk_clear(value);
- return -1;
- }
-
- botan_mp_destroy(field);
- return 0;
-}
-
-/**
- * Build RSA signature
- */
-static bool build_rsa_signature(private_botan_rsa_private_key_t *this,
- const char* hash_and_padding, chunk_t data, chunk_t* signature)
-{
- botan_pk_op_sign_t sign_op;
-
- if (botan_pk_op_sign_create(&sign_op, this->key, hash_and_padding, 0))
- {
- return FALSE;
- }
-
- botan_rng_t rng;
- if (botan_rng_init(&rng, "user"))
- {
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- /* get size of signature first */
- if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- signature->len = 0;
- if (botan_pk_op_sign_finish(sign_op, rng, NULL, &signature->len)
- != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
- {
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- /* now get the signature */
- *signature = chunk_alloc(signature->len);
- if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
- {
- chunk_free(signature);
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
return FALSE;
}
-
- if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
- {
- chunk_free(signature);
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return FALSE;
- }
-
- botan_rng_destroy(rng);
- botan_pk_op_sign_destroy(sign_op);
- return TRUE;
-}
-
-/**
- * Build an EMSA PKCS1 signature described in PKCS#1
- */
-static bool build_emsa_pkcs1_signature(private_botan_rsa_private_key_t *this,
- const char* hash_and_padding, chunk_t data, chunk_t* signature)
-{
- return build_rsa_signature(this, hash_and_padding, data, signature);
-}
-
-static bool botan_get_hash(hash_algorithm_t hash, char* hash_str)
-{
- switch (hash)
- {
- case HASH_SHA1:
- sprintf(hash_str, "SHA-1");
- break;
- case HASH_SHA224:
- sprintf(hash_str, "SHA-224");
- break;
- case HASH_SHA256:
- sprintf(hash_str, "SHA-256");
- break;
- case HASH_SHA384:
- sprintf(hash_str, "SHA-384");
- break;
- case HASH_SHA512:
- sprintf(hash_str, "SHA-512");
- break;
- default:
- return FALSE;
- }
-
+ botan_mp_destroy(field);
return TRUE;
}
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)
{
return FALSE;
}
- hash = malloc(8);
- if (!botan_get_hash(params->hash, hash))
- {
- free(hash);
- return FALSE;
- }
-
- mgf1_hash = malloc(8);
- if (!botan_get_hash(params->mgf1_hash, mgf1_hash))
+ hash = botan_get_hash(params->hash);
+ if (!hash)
{
- free(hash);
- free(mgf1_hash);
return FALSE;
}
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
- salt_len = malloc(6);
- snprintf(salt_len, 5, "%d", params->salt_len);
- }
-
- len = 24 + strlen(hash) + strlen(mgf1_hash);
- hash_and_padding = malloc(len+1);
-
- if (salt_len)
- {
- snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1,%s)", hash, salt_len);
+ snprintf(hash_and_padding, sizeof(hash_and_padding),
+ "EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
}
else
{
- snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1)", hash);
+ snprintf(hash_and_padding, sizeof(hash_and_padding),
+ "EMSA-PSS(%s,MGF1)", hash);
}
-
- if (build_rsa_signature(this, hash_and_padding, data, sig))
- {
- success = TRUE;
- }
-
- if (salt_len)
- free(salt_len);
- free(hash);
- free(mgf1_hash);
- free(hash_and_padding);
- return success;
+ return botan_get_signature(this->key, hash_and_padding, data, sig);
}
METHOD(private_key_t, get_type, key_type_t,
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:
}
}
-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)
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))
botan_pk_op_decrypt_destroy(decrypt_op);
return FALSE;
}
-
botan_pk_op_decrypt_destroy(decrypt_op);
return TRUE;
}
private_botan_rsa_private_key_t *this)
{
botan_mp_t n;
- if (botan_mp_init(&n))
- {
- return -1;
- }
+ size_t bits = 0;
- if (botan_privkey_rsa_get_n(n, this->key))
+ if (botan_mp_init(&n))
{
- return -1;
+ return 0;
}
- size_t bits = 0;
- if (botan_mp_num_bits(n, &bits))
+ if (botan_privkey_rsa_get_n(n, this->key) ||
+ botan_mp_num_bits(n, &bits))
{
botan_mp_destroy(n);
- return -1;
+ return 0;
}
botan_mp_destroy(n);
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);
private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
chunk_t *fingerprint)
{
- chunk_t n, e;
- bool success;
+ botan_pubkey_t pubkey;
+ bool success = FALSE;
- if (lib->encoding->get_cache(lib->encoding, type, &this->key, fingerprint))
+ /* check the cache before doing the export */
+ if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
{
return TRUE;
}
- if (botan_rsa_get_field(&this->key, "n", &n))
- {
- return FALSE;
- }
-
- if (botan_rsa_get_field(&this->key, "e", &e))
+ if (botan_privkey_export_pubkey(&pubkey, this->key))
{
- chunk_clear(&n);
return FALSE;
}
-
- success = lib->encoding->encode(lib->encoding, type, &this->key,
- fingerprint, CRED_PART_RSA_MODULUS, n,
- CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
- chunk_free(&n);
- chunk_free(&e);
+ success = botan_get_fingerprint(pubkey, this, type, fingerprint);
+ botan_pubkey_destroy(pubkey);
return success;
-
}
METHOD(private_key_t, get_encoding, bool,
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:
{
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);
}
}
}
/*
- * 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)
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;
}
static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
botan_mp_t *p, botan_mp_t *q)
{
- botan_mp_t k, one, r, zero, two, n1, x, y, g, rem;
+ botan_mp_t k = NULL, one = NULL, r = NULL, zero = NULL, two = NULL;
+ botan_mp_t n1 = NULL, x = NULL, y = NULL, g = NULL, rem = NULL;
+ botan_rng_t rng = NULL;
int i, t, j;
- bool success = TRUE;
-
- if (botan_mp_init(&k))
- {
- success = FALSE;
- goto error;
- }
-
- if (botan_mp_init(&one))
- {
- success = FALSE;
- goto error;
- }
+ bool success = FALSE;
- if (botan_mp_set_from_int(one, 1))
+ if (botan_mp_init(&k) ||
+ botan_mp_init(&one) ||
+ botan_mp_set_from_int(one, 1))
{
- success = FALSE;
goto error;
}
- /* 1. k = de - 1 */
+ /* 1. k = d * e - 1 */
if (botan_mp_mul(k, *d, *e) || botan_mp_sub(k, k, one))
{
- success = FALSE;
goto error;
}
/* k must be even */
if (!botan_mp_is_even(k))
{
- success = FALSE;
goto error;
}
/* 2. k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
- if (botan_mp_init(&r))
- {
- success = FALSE;
- goto error;
- }
-
- if (botan_mp_set_from_mp(r, k))
+ if (botan_mp_init(&r) ||
+ botan_mp_set_from_mp(r, k))
{
- success = FALSE;
goto error;
}
{
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;
}
/* 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;
}
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;
}
}
/* let y = x */
- if(botan_mp_set_from_mp(y, x))
+ if (botan_mp_set_from_mp(y, x))
{
- success = FALSE;
goto error;
}
}
/* 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);
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)
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);
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);
}
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);
return NULL;
}
}
+ botan_mp_destroy(n_mp);
+ botan_mp_destroy(d_mp);
this = create_empty();
botan_mp_destroy(e_mp);
botan_mp_destroy(p_mp);
botan_mp_destroy(q_mp);
- destroy(this);
+ free(this);
return NULL;
}
* Private data structure with signing context.
*/
struct private_botan_rsa_public_key_t {
+
/**
* Public interface for this signer
*/
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;
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
*/
rsa_pss_params_t *params, chunk_t data,
chunk_t signature)
{
- char* hash_and_padding, *hash, *mgf1_hash;
- char* salt_len = NULL;
- size_t len;
- bool success = FALSE;
+ const char *hash;
+ char hash_and_padding[BUF_LEN];
if (!params)
{
return FALSE;
}
- // botan currently does not support passing the mgf1 hash
+ /* botan currently does not support passing the mgf1 hash */
if (params->hash != params->mgf1_hash)
{
DBG1(DBG_LIB, "passing mgf1 hash not supported via botan");
return FALSE;
}
- hash = malloc(8);
- if(!botan_get_hash(params->hash, hash))
- {
- free(hash);
- return FALSE;
- }
-
- mgf1_hash = malloc(8);
- if(!botan_get_hash(params->mgf1_hash, mgf1_hash))
+ hash = botan_get_hash(params->hash);
+ if (!hash)
{
- free(hash);
- free(mgf1_hash);
return FALSE;
}
- if(params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
+ if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
- salt_len = malloc(6);
- snprintf(salt_len, 5, "%d", params->salt_len);
- }
-
- len = 24 + strlen(hash) + strlen(mgf1_hash);
- hash_and_padding = malloc(len+1);
-
- if(salt_len)
- {
- snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1,%s)", hash, salt_len);
+ snprintf(hash_and_padding, sizeof(hash_and_padding),
+ "EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
}
else
{
- snprintf(hash_and_padding, len, "EMSA-PSS(%s,MGF1)", hash);
+ snprintf(hash_and_padding, sizeof(hash_and_padding),
+ "EMSA-PSS(%s,MGF1)", hash);
}
-
- if (verify_rsa_signature(this, hash_and_padding, data, signature))
- {
- success = TRUE;
- }
-
- if(salt_len)
- free(salt_len);
- free(hash);
- free(mgf1_hash);
- free(hash_and_padding);
- return success;
+ return verify_rsa_signature(this, hash_and_padding, data, signature);
}
METHOD(public_key_t, get_type, key_type_t,
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:
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)
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))
botan_pk_op_encrypt_destroy(encrypt_op);
return FALSE;
}
-
botan_rng_destroy(rng);
botan_pk_op_encrypt_destroy(encrypt_op);
return TRUE;
if (botan_mp_init(&n))
{
- return -1;
- }
-
- if (botan_pubkey_rsa_get_n(n, this->key))
- {
- return -1;
+ return 0;
}
- if (botan_mp_num_bits(n, &bits))
+ if (botan_pubkey_rsa_get_n(n, this->key) ||
+ botan_mp_num_bits(n, &bits))
{
botan_mp_destroy(n);
- return -1;
+ return 0;
}
botan_mp_destroy(n);
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*,
{
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);
}
}
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;
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;
}
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;
{
botan_mp_destroy(mp_n);
botan_mp_destroy(mp_e);
- destroy(this);
+ free(this);
return NULL;
}
botan_mp_destroy(mp_n);
botan_mp_destroy(mp_e);
}
- if (this != NULL)
- {
- return &this->public;
- }
- return NULL;
+
+ return &this->public;
}
-#endif
\ No newline at end of file
+#endif
/*
+ * Copyright (C) 2018 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2018 René Korthaus
* Rohde & Schwarz Cybersecurity GmbH
*
#include <botan/ffi.h>
-int chunk_to_botan_mp(chunk_t value, botan_mp_t *mp)
+/*
+ * Described in header
+ */
+bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp)
{
if (botan_mp_init(mp))
{
- return -1;
+ return FALSE;
}
if (botan_mp_from_bin(*mp, value.ptr, value.len))
{
botan_mp_destroy(*mp);
- return -1;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Described in header
+ */
+const char *botan_get_hash(hash_algorithm_t hash)
+{
+ switch (hash)
+ {
+ case HASH_MD5:
+ return "MD5";
+ case HASH_SHA1:
+ return "SHA-1";
+ case HASH_SHA224:
+ return "SHA-224";
+ case HASH_SHA256:
+ return "SHA-256";
+ case HASH_SHA384:
+ return "SHA-384";
+ case HASH_SHA512:
+ return "SHA-512";
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
+ chunk_t *encoding)
+{
+ bool success = TRUE;
+
+ encoding->len = 0;
+ if (botan_pubkey_export(pubkey, NULL, &encoding->len,
+ BOTAN_PRIVKEY_EXPORT_FLAG_DER)
+ != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+ {
+ return FALSE;
+ }
+
+ *encoding = chunk_alloc(encoding->len);
+ if (botan_pubkey_export(pubkey, encoding->ptr, &encoding->len,
+ BOTAN_PRIVKEY_EXPORT_FLAG_DER))
+ {
+ chunk_free(encoding);
+ return FALSE;
+ }
+
+ if (type != PUBKEY_SPKI_ASN1_DER)
+ {
+ chunk_t asn1_encoding = *encoding;
+
+ success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_ECDSA_PUB_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
+ chunk_free(&asn1_encoding);
+ }
+ return success;
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
+ cred_encoding_type_t type, chunk_t *fp)
+{
+ hasher_t *hasher;
+ chunk_t key;
+
+ if (cache &&
+ lib->encoding->get_cache(lib->encoding, type, cache, fp))
+ {
+ return TRUE;
}
- return 0;
+
+ switch (type)
+ {
+ case KEYID_PUBKEY_SHA1:
+ {
+ /* subjectPublicKey -> use botan_pubkey_fingerprint() */
+ fp->len = 0;
+ if (botan_pubkey_fingerprint(pubkey, "SHA-1", NULL, &fp->len)
+ != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+ {
+ return FALSE;
+ }
+
+ *fp = chunk_alloc(fp->len);
+ if (botan_pubkey_fingerprint(pubkey, "SHA-1", fp->ptr, &fp->len))
+ {
+ chunk_free(fp);
+ return FALSE;
+ }
+ break;
+ }
+ case KEYID_PUBKEY_INFO_SHA1:
+ {
+ /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */
+ if (!botan_get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &key))
+ {
+ return FALSE;
+ }
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher || !hasher->allocate_hash(hasher, key, fp))
+ {
+ DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
+ "fingerprinting failed");
+ DESTROY_IF(hasher);
+ chunk_free(&key);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+ chunk_free(&key);
+ break;
+ }
+ default:
+ return FALSE;
+ }
+
+ if (cache)
+ {
+ lib->encoding->cache(lib->encoding, type, cache, *fp);
+ }
+ return TRUE;
+}
+
+/*
+ * Described in header
+ */
+bool botan_get_signature(botan_privkey_t key, const char *scheme,
+ chunk_t data, chunk_t *signature)
+{
+ botan_pk_op_sign_t sign_op;
+ botan_rng_t rng;
+
+ if (!scheme || !signature)
+ {
+ return FALSE;
+ }
+
+ if (botan_pk_op_sign_create(&sign_op, key, scheme, 0))
+ {
+ return FALSE;
+ }
+
+ if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
+ {
+ botan_pk_op_sign_destroy(sign_op);
+ return FALSE;
+ }
+
+ signature->len = 0;
+ if (botan_pk_op_sign_output_length(sign_op, &signature->len))
+ {
+ botan_pk_op_sign_destroy(sign_op);
+ return FALSE;
+ }
+
+ if (botan_rng_init(&rng, "user"))
+ {
+ botan_pk_op_sign_destroy(sign_op);
+ return FALSE;
+ }
+
+ *signature = chunk_alloc(signature->len);
+ if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
+ {
+ chunk_free(signature);
+ botan_rng_destroy(rng);
+ botan_pk_op_sign_destroy(sign_op);
+ return FALSE;
+ }
+
+ botan_rng_destroy(rng);
+ botan_pk_op_sign_destroy(sign_op);
+ return TRUE;
}
/*
+ * Copyright (C) 2018 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2018 René Korthaus
* Rohde & Schwarz Cybersecurity GmbH
*
#include <botan/ffi.h>
/**
- * Converts chunk_t to botan_mp_t
+ * Converts chunk_t to botan_mp_t.
+ *
+ * @param value chunk to convert
+ * @param mp allocated botan_mp_t
+ * @return TRUE if conversion successful
+ */
+bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
+
+/**
+ * Get the Botan string identifier for the given hash algorithm.
+ *
+ * @param hash hash algorithm
+ * @return Botan string identifier, NULL if not found
+ */
+const char *botan_get_hash(hash_algorithm_t hash);
+
+/**
+ * Get the encoding of a botan_pubkey_t.
+ *
+ * @param pubkey public key object
+ * @param type encoding type
+ * @param encoding allocated encoding
+ * @return TRUE if encoding successful
+ */
+bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
+ chunk_t *encoding);
+
+/**
+ * Get the fingerprint of a botan_pubkey_t.
+ *
+ * @param pubkey public key object
+ * @param cache key to use for caching, NULL to not cache
+ * @param type fingerprint type
+ * @param fp allocated fingerprint
+ * @return TRUE if fingerprinting successful
+ */
+bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
+ cred_encoding_type_t type, chunk_t *fp);
+
+/**
+ * Sign the given data using the provided key with the specified signature
+ * scheme (hash/padding).
+ *
+ * @param key private key object
+ * @param scheme hash/padding algorithm
+ * @param data data to sign
+ * @param signature allocated signature
+ * @return TRUE if signature successfully created
*/
-int chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
+bool botan_get_signature(botan_privkey_t key, const char *scheme,
+ chunk_t data, chunk_t *signature);
#endif /** BOTAN_UTIL_H_ @}*/