wolfssl: Fixes, code style changes and some refactorings

The main fixes are

 * the generation of fingerprints for RSA, ECDSA, and EdDSA
 * the encoding of ECDSA private keys
 * calculating p and q for RSA private keys
 * deriving the public key for raw Ed25519 private keys

Also, instead of numeric literals for buffer lengths ASN.1 related
constants are used.
This commit is contained in:
Tobias Brunner
2019-04-24 12:26:08 +02:00
parent 59be02519a
commit d3329ee540
24 changed files with 646 additions and 798 deletions
+1
View File
@@ -101,6 +101,7 @@ plugins = \
plugins/updown.opt \ plugins/updown.opt \
plugins/vici.opt \ plugins/vici.opt \
plugins/whitelist.opt \ plugins/whitelist.opt \
plugins/wolfssl.opt \
plugins/xauth-eap.opt \ plugins/xauth-eap.opt \
plugins/xauth-pam.opt plugins/xauth-pam.opt
+2
View File
@@ -0,0 +1,2 @@
charon.plugins.wolfssl.fips_mode = no
Enable to prevent loading the plugin if wolfSSL is not in FIPS mode.
@@ -1,6 +1,5 @@
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/libstrongswan
-DFIPS_MODE=${fips_mode}
AM_CFLAGS = \ AM_CFLAGS = \
$(PLUGIN_CFLAGS) $(PLUGIN_CFLAGS)
@@ -40,17 +40,6 @@
#define CCM_SALT_LEN 3 #define CCM_SALT_LEN 3
#define CCM_NONCE_LEN (CCM_SALT_LEN + IV_LEN) #define CCM_NONCE_LEN (CCM_SALT_LEN + IV_LEN)
#if !defined(NO_AES) && defined(HAVE_AESGCM)
#define MAX_NONCE_LEN GCM_NONCE_LEN
#define MAX_SALT_LEN GCM_SALT_LEN
#elif defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
#define MAX_NONCE_LEN 12
#define MAX_SALT_LEN 4
#elif !defined(NO_AES) && defined(HAVE_AESCCM)
#define MAX_NONCE_LEN CCM_NONCE_LEN
#define MAX_SALT_LEN GCM_SALT_LEN
#endif
typedef struct private_aead_t private_aead_t; typedef struct private_aead_t private_aead_t;
/** /**
@@ -71,23 +60,13 @@ struct private_aead_t {
/** /**
* Salt value * Salt value
*/ */
char salt[MAX_SALT_LEN]; chunk_t salt;
/**
* Length of the salt
*/
size_t salt_len;
/** /**
* Size of the integrity check value * Size of the integrity check value
*/ */
size_t icv_size; size_t icv_size;
/**
* Size of the IV
*/
size_t iv_size;
/** /**
* IV generator * IV generator
*/ */
@@ -96,8 +75,7 @@ struct private_aead_t {
/** /**
* The cipher to use * The cipher to use
*/ */
union union {
{
#if !defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AESCCM)) #if !defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AESCCM))
Aes aes; Aes aes;
#endif #endif
@@ -109,15 +87,14 @@ struct private_aead_t {
encryption_algorithm_t alg; encryption_algorithm_t alg;
}; };
METHOD(aead_t, encrypt, bool, METHOD(aead_t, encrypt, bool,
private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
chunk_t *encrypted) chunk_t *encrypted)
{ {
bool success = FALSE; chunk_t nonce;
int ret = 0;
u_char *out; u_char *out;
u_char nonce[MAX_NONCE_LEN]; bool success = FALSE;
int ret;
out = plain.ptr; out = plain.ptr;
if (encrypted) if (encrypted)
@@ -126,8 +103,7 @@ METHOD(aead_t, encrypt, bool,
out = encrypted->ptr; out = encrypted->ptr;
} }
memcpy(nonce, this->salt, this->salt_len); nonce = chunk_cata("cc", this->salt, iv);
memcpy(nonce + this->salt_len, iv.ptr, IV_LEN);
switch (this->alg) switch (this->alg)
{ {
@@ -140,8 +116,8 @@ METHOD(aead_t, encrypt, bool,
if (ret == 0) if (ret == 0)
{ {
ret = wc_AesGcmEncrypt(&this->cipher.aes, out, plain.ptr, ret = wc_AesGcmEncrypt(&this->cipher.aes, out, plain.ptr,
plain.len, nonce, GCM_NONCE_LEN, out + plain.len, plain.len, nonce.ptr, GCM_NONCE_LEN, out + plain.len,
this->icv_size, assoc.ptr, assoc.len); this->icv_size, assoc.ptr, assoc.len);
} }
success = (ret == 0); success = (ret == 0);
break; break;
@@ -150,23 +126,27 @@ METHOD(aead_t, encrypt, bool,
case ENCR_AES_CCM_ICV8: case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV12: case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16: case ENCR_AES_CCM_ICV16:
if (plain.ptr == NULL && plain.len == 0) /* wc_AesCcmEncrypt fails if the pointer is NULL */
plain.ptr = nonce; if (!plain.ptr && !plain.len)
{
plain.ptr = nonce.ptr;
}
ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr, ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr,
this->key.len); this->key.len);
if (ret == 0) if (ret == 0)
{ {
ret = wc_AesCcmEncrypt(&this->cipher.aes, out, plain.ptr, ret = wc_AesCcmEncrypt(&this->cipher.aes, out, plain.ptr,
plain.len, nonce, CCM_NONCE_LEN, out + plain.len, plain.len, nonce.ptr, CCM_NONCE_LEN, out + plain.len,
this->icv_size, assoc.ptr, assoc.len); this->icv_size, assoc.ptr, assoc.len);
} }
success = (ret == 0); success = (ret == 0);
break; break;
#endif #endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case ENCR_CHACHA20_POLY1305: case ENCR_CHACHA20_POLY1305:
ret = wc_ChaCha20Poly1305_Encrypt(this->key.ptr, nonce, assoc.ptr, ret = wc_ChaCha20Poly1305_Encrypt(this->key.ptr, nonce.ptr,
assoc.len, plain.ptr, plain.len, out, out + plain.len); assoc.ptr, assoc.len, plain.ptr, plain.len, out,
out + plain.len);
success = (ret == 0); success = (ret == 0);
break; break;
#endif #endif
@@ -174,6 +154,7 @@ METHOD(aead_t, encrypt, bool,
break; break;
} }
memwipe(nonce.ptr, nonce.len);
return success; return success;
} }
@@ -181,10 +162,10 @@ METHOD(aead_t, decrypt, bool,
private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
chunk_t *plain) chunk_t *plain)
{ {
chunk_t nonce;
u_char *out;
bool success = FALSE; bool success = FALSE;
int ret = 0; int ret = 0;
u_char *out;
u_char nonce[MAX_NONCE_LEN];
if (encrypted.len < this->icv_size) if (encrypted.len < this->icv_size)
{ {
@@ -199,8 +180,7 @@ METHOD(aead_t, decrypt, bool,
out = plain->ptr; out = plain->ptr;
} }
memcpy(nonce, this->salt, this->salt_len); nonce = chunk_cata("cc", this->salt, iv);
memcpy(nonce + this->salt_len, iv.ptr, IV_LEN);
switch (this->alg) switch (this->alg)
{ {
@@ -209,13 +189,13 @@ METHOD(aead_t, decrypt, bool,
case ENCR_AES_GCM_ICV12: case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16: case ENCR_AES_GCM_ICV16:
ret = wc_AesGcmSetKey(&this->cipher.aes, this->key.ptr, ret = wc_AesGcmSetKey(&this->cipher.aes, this->key.ptr,
this->key.len); this->key.len);
if (ret == 0) if (ret == 0)
{ {
ret = wc_AesGcmDecrypt(&this->cipher.aes, out, encrypted.ptr, ret = wc_AesGcmDecrypt(&this->cipher.aes, out, encrypted.ptr,
encrypted.len, nonce, GCM_NONCE_LEN, encrypted.len, nonce.ptr, GCM_NONCE_LEN,
encrypted.ptr + encrypted.len, this->icv_size, assoc.ptr, encrypted.ptr + encrypted.len, this->icv_size,
assoc.len); assoc.ptr, assoc.len);
} }
success = (ret == 0); success = (ret == 0);
break; break;
@@ -224,27 +204,32 @@ METHOD(aead_t, decrypt, bool,
case ENCR_AES_CCM_ICV8: case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV12: case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16: case ENCR_AES_CCM_ICV16:
if (encrypted.ptr == NULL && encrypted.len == 0) /* wc_AesCcmDecrypt() fails if the pointers are NULL */
encrypted.ptr = nonce; if (!encrypted.ptr && !encrypted.len)
if (out == NULL && encrypted.len == 0) {
out = nonce; encrypted.ptr = nonce.ptr;
}
if (!out && !encrypted.len)
{
out = nonce.ptr;
}
ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr, ret = wc_AesCcmSetKey(&this->cipher.aes, this->key.ptr,
this->key.len); this->key.len);
if (ret == 0) if (ret == 0)
{ {
ret = wc_AesCcmDecrypt(&this->cipher.aes, out, encrypted.ptr, ret = wc_AesCcmDecrypt(&this->cipher.aes, out, encrypted.ptr,
encrypted.len, nonce, CCM_NONCE_LEN, encrypted.len, nonce.ptr, CCM_NONCE_LEN,
encrypted.ptr + encrypted.len, this->icv_size, assoc.ptr, encrypted.ptr + encrypted.len, this->icv_size,
assoc.len); assoc.ptr, assoc.len);
} }
success = (ret == 0); success = (ret == 0);
break; break;
#endif #endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case ENCR_CHACHA20_POLY1305: case ENCR_CHACHA20_POLY1305:
ret = wc_ChaCha20Poly1305_Decrypt(this->key.ptr, nonce, assoc.ptr, ret = wc_ChaCha20Poly1305_Decrypt(this->key.ptr, nonce.ptr,
assoc.len, encrypted.ptr, encrypted.len, assoc.ptr, assoc.len, encrypted.ptr, encrypted.len,
encrypted.ptr + encrypted.len, out); encrypted.ptr + encrypted.len, out);
success = (ret == 0); success = (ret == 0);
break; break;
#endif #endif
@@ -252,13 +237,14 @@ METHOD(aead_t, decrypt, bool,
break; break;
} }
memwipe(nonce.ptr, nonce.len);
return success; return success;
} }
METHOD(aead_t, get_block_size, size_t, METHOD(aead_t, get_block_size, size_t,
private_aead_t *this) private_aead_t *this)
{ {
/* All AEAD algorithms are streaming. */ /* all AEAD algorithms are streaming */
return 1; return 1;
} }
@@ -283,7 +269,7 @@ METHOD(aead_t, get_iv_gen, iv_gen_t*,
METHOD(aead_t, get_key_size, size_t, METHOD(aead_t, get_key_size, size_t,
private_aead_t *this) private_aead_t *this)
{ {
return this->key.len + this->salt_len; return this->key.len + this->salt.len;
} }
METHOD(aead_t, set_key, bool, METHOD(aead_t, set_key, bool,
@@ -293,7 +279,7 @@ METHOD(aead_t, set_key, bool,
{ {
return FALSE; return FALSE;
} }
memcpy(this->salt, key.ptr + key.len - this->salt_len, this->salt_len); memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len);
memcpy(this->key.ptr, key.ptr, this->key.len); memcpy(this->key.ptr, key.ptr, this->key.len);
return TRUE; return TRUE;
} }
@@ -302,6 +288,7 @@ METHOD(aead_t, destroy, void,
private_aead_t *this) private_aead_t *this)
{ {
chunk_clear(&this->key); chunk_clear(&this->key);
chunk_clear(&this->salt);
switch (this->alg) switch (this->alg)
{ {
#if !defined(NO_AES) && defined(HAVE_AESGCM) #if !defined(NO_AES) && defined(HAVE_AESGCM)
@@ -317,10 +304,6 @@ METHOD(aead_t, destroy, void,
case ENCR_AES_CCM_ICV16: case ENCR_AES_CCM_ICV16:
wc_AesFree(&this->cipher.aes); wc_AesFree(&this->cipher.aes);
break; break;
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case ENCR_CHACHA20_POLY1305:
break;
#endif #endif
default: default:
break; break;
@@ -336,6 +319,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
size_t key_size, size_t salt_size) size_t key_size, size_t salt_size)
{ {
private_aead_t *this; private_aead_t *this;
size_t expected_salt_size;
INIT(this, INIT(this,
.public = { .public = {
@@ -404,8 +388,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
case 16: case 16:
case 24: case 24:
case 32: case 32:
this->iv_size = GCM_NONCE_LEN; expected_salt_size = GCM_SALT_LEN;
this->salt_len = GCM_SALT_LEN;
if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0) if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0)
{ {
DBG1(DBG_LIB, "AES Init failed, aead create failed"); DBG1(DBG_LIB, "AES Init failed, aead create failed");
@@ -431,8 +414,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
case 16: case 16:
case 24: case 24:
case 32: case 32:
this->iv_size = CCM_NONCE_LEN; expected_salt_size = CCM_SALT_LEN;
this->salt_len = CCM_SALT_LEN;
if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0) if (wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID) != 0)
{ {
DBG1(DBG_LIB, "AES Init failed, aead create failed"); DBG1(DBG_LIB, "AES Init failed, aead create failed");
@@ -454,8 +436,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
key_size = 32; key_size = 32;
/* FALL */ /* FALL */
case 32: case 32:
this->iv_size = CHACHA_IV_BYTES; expected_salt_size = 4;
this->salt_len = 4;
break; break;
default: default:
free(this); free(this);
@@ -468,7 +449,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
return NULL; return NULL;
} }
if (salt_size && salt_size != this->salt_len) if (salt_size && salt_size != expected_salt_size)
{ {
/* currently not supported */ /* currently not supported */
free(this); free(this);
@@ -476,6 +457,7 @@ aead_t *wolfssl_aead_create(encryption_algorithm_t algo,
} }
this->key = chunk_alloc(key_size); this->key = chunk_alloc(key_size);
this->salt = chunk_alloc(expected_salt_size);
this->iv_gen = iv_gen_seq_create(); this->iv_gen = iv_gen_seq_create();
return &this->public; return &this->public;
@@ -46,8 +46,7 @@ struct private_wolfssl_crypter_t {
/** /**
* wolfSSL cipher * wolfSSL cipher
*/ */
union union {
{
#if !defined(NO_AES) && (!defined(NO_AES_CBC) || defined(WOLFSSL_AES_COUNTER)) #if !defined(NO_AES) && (!defined(NO_AES_CBC) || defined(WOLFSSL_AES_COUNTER))
Aes aes; Aes aes;
#endif #endif
@@ -73,17 +72,7 @@ struct private_wolfssl_crypter_t {
/** /**
* Salt value * Salt value
*/ */
char salt[CTR_SALT_LEN]; chunk_t salt;
/**
* Length of the salt
*/
size_t salt_len;
/**
* Size of key
*/
size_t key_size;
/** /**
* Size of block * Size of block
@@ -114,10 +103,10 @@ METHOD(crypter_t, decrypt, bool,
out = dst->ptr; out = dst->ptr;
} }
if (this->salt_len > 0) if (this->salt.len > 0)
{ {
memcpy(nonce, this->salt, this->salt_len); memcpy(nonce, this->salt.ptr, this->salt.len);
memcpy(nonce + this->salt_len, iv.ptr, this->iv_size); memcpy(nonce + this->salt.len, iv.ptr, this->iv_size);
nonce[AES_BLOCK_SIZE - 1] = 1; nonce[AES_BLOCK_SIZE - 1] = 1;
} }
@@ -212,6 +201,7 @@ METHOD(crypter_t, decrypt, bool,
break; break;
} }
memwipe(nonce, sizeof(nonce));
return success; return success;
} }
@@ -233,10 +223,10 @@ METHOD(crypter_t, encrypt, bool,
out = dst->ptr; out = dst->ptr;
} }
if (this->salt_len > 0) if (this->salt.len > 0)
{ {
memcpy(nonce, this->salt, this->salt_len); memcpy(nonce, this->salt.ptr, this->salt.len);
memcpy(nonce + this->salt_len, iv.ptr, this->iv_size); memcpy(nonce + this->salt.len, iv.ptr, this->iv_size);
nonce[AES_BLOCK_SIZE - 1] = 1; nonce[AES_BLOCK_SIZE - 1] = 1;
} }
@@ -348,7 +338,7 @@ METHOD(crypter_t, get_iv_size, size_t,
METHOD(crypter_t, get_key_size, size_t, METHOD(crypter_t, get_key_size, size_t,
private_wolfssl_crypter_t *this) private_wolfssl_crypter_t *this)
{ {
return this->key.len + this->salt_len; return this->key.len + this->salt.len;
} }
METHOD(crypter_t, set_key, bool, METHOD(crypter_t, set_key, bool,
@@ -358,7 +348,7 @@ METHOD(crypter_t, set_key, bool,
{ {
return FALSE; return FALSE;
} }
memcpy(this->salt, key.ptr + key.len - this->salt_len, this->salt_len); memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len);
memcpy(this->key.ptr, key.ptr, this->key.len); memcpy(this->key.ptr, key.ptr, this->key.len);
return TRUE; return TRUE;
} }
@@ -367,6 +357,7 @@ METHOD(crypter_t, destroy, void,
private_wolfssl_crypter_t *this) private_wolfssl_crypter_t *this)
{ {
chunk_clear(&this->key); chunk_clear(&this->key);
chunk_clear(&this->salt);
switch (this->alg) switch (this->alg)
{ {
#if !defined(NO_AES) && !defined(NO_AES_CBC) #if !defined(NO_AES) && !defined(NO_AES_CBC)
@@ -379,19 +370,10 @@ METHOD(crypter_t, destroy, void,
wc_AesFree(&this->cipher.aes); wc_AesFree(&this->cipher.aes);
break; break;
#endif #endif
#ifdef HAVE_CAMELLIA
case ENCR_CAMELLIA_CBC:
break;
#endif
#ifndef NO_DES3 #ifndef NO_DES3
case ENCR_3DES: case ENCR_3DES:
wc_Des3Free(&this->cipher.des3); wc_Des3Free(&this->cipher.des3);
break; break;
case ENCR_DES:
#ifdef WOLFSSL_DES_ECB
case ENCR_DES_ECB:
#endif
break;
#endif #endif
default: default:
break; break;
@@ -424,6 +406,7 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
{ {
case 0: case 0:
key_size = 16; key_size = 16;
/* fall-through */
case 16: case 16:
case 24: case 24:
case 32: case 32:
@@ -441,6 +424,7 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
{ {
case 0: case 0:
key_size = 16; key_size = 16;
/* fall-through */
case 16: case 16:
case 24: case 24:
case 32: case 32:
@@ -459,6 +443,7 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
{ {
case 0: case 0:
key_size = 16; key_size = 16;
/* fall-through */
case 16: case 16:
case 24: case 24:
case 32: case 32:
@@ -480,24 +465,16 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
iv_size = DES_BLOCK_SIZE; iv_size = DES_BLOCK_SIZE;
break; break;
case ENCR_DES: case ENCR_DES:
if (key_size != 8)
{
return NULL;
}
block_size = DES_BLOCK_SIZE;
iv_size = DES_BLOCK_SIZE;
break;
#ifdef WOLFSSL_DES_ECB #ifdef WOLFSSL_DES_ECB
case ENCR_DES_ECB: case ENCR_DES_ECB:
#endif
if (key_size != 8) if (key_size != 8)
{ {
return NULL; return NULL;
} }
key_size = DES_BLOCK_SIZE;
block_size = DES_BLOCK_SIZE; block_size = DES_BLOCK_SIZE;
iv_size = DES_BLOCK_SIZE; iv_size = DES_BLOCK_SIZE;
break; break;
#endif
#endif #endif
default: default:
return NULL; return NULL;
@@ -516,10 +493,8 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
}, },
}, },
.alg = algo, .alg = algo,
.key_size = key_size,
.block_size = block_size, .block_size = block_size,
.iv_size = iv_size, .iv_size = iv_size,
.salt_len = salt_len,
); );
switch (algo) switch (algo)
@@ -534,19 +509,10 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID); ret = wc_AesInit(&this->cipher.aes, NULL, INVALID_DEVID);
break; break;
#endif #endif
#ifdef HAVE_CAMELLIA
case ENCR_CAMELLIA_CBC:
break;
#endif
#ifndef NO_DES3 #ifndef NO_DES3
case ENCR_3DES: case ENCR_3DES:
ret = wc_Des3Init(&this->cipher.des3, NULL, INVALID_DEVID); ret = wc_Des3Init(&this->cipher.des3, NULL, INVALID_DEVID);
break; break;
case ENCR_DES:
#ifdef WOLFSSL_DES_ECB
case ENCR_DES_ECB:
#endif
break;
#endif #endif
default: default:
break; break;
@@ -558,7 +524,7 @@ wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
} }
this->key = chunk_alloc(key_size); this->key = chunk_alloc(key_size);
this->salt = chunk_alloc(salt_len);
return &this->public; return &this->public;
} }
@@ -33,7 +33,7 @@ typedef struct wolfssl_crypter_t wolfssl_crypter_t;
#include <crypto/crypters/crypter.h> #include <crypto/crypters/crypter.h>
/** /**
* Implementation of crypters using wolfssl. * Implementation of crypters using wolfSSL.
*/ */
struct wolfssl_crypter_t { struct wolfssl_crypter_t {
@@ -51,6 +51,6 @@ struct wolfssl_crypter_t {
* @return wolfssl_crypter_t, NULL if not supported * @return wolfssl_crypter_t, NULL if not supported
*/ */
wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo, wolfssl_crypter_t *wolfssl_crypter_create(encryption_algorithm_t algo,
size_t key_size); size_t key_size);
#endif /** WOLFSSL_CRYPTER_H_ @}*/ #endif /** WOLFSSL_CRYPTER_H_ @}*/
@@ -37,6 +37,7 @@ typedef struct private_wolfssl_diffie_hellman_t private_wolfssl_diffie_hellman_t
* Private data of an wolfssl_diffie_hellman_t object. * Private data of an wolfssl_diffie_hellman_t object.
*/ */
struct private_wolfssl_diffie_hellman_t { struct private_wolfssl_diffie_hellman_t {
/** /**
* Public wolfssl_diffie_hellman_t interface. * Public wolfssl_diffie_hellman_t interface.
*/ */
@@ -52,11 +53,6 @@ struct private_wolfssl_diffie_hellman_t {
*/ */
DhKey dh; DhKey dh;
/**
* Random number generator to use with RSA operations.
*/
WC_RNG rng;
/** /**
* Length of public values * Length of public values
*/ */
@@ -76,41 +72,26 @@ struct private_wolfssl_diffie_hellman_t {
* Shared secret * Shared secret
*/ */
chunk_t shared_secret; chunk_t shared_secret;
/**
* True if shared secret is computed
*/
bool computed;
}; };
METHOD(diffie_hellman_t, get_my_public_value, bool, METHOD(diffie_hellman_t, get_my_public_value, bool,
private_wolfssl_diffie_hellman_t *this, chunk_t *value) private_wolfssl_diffie_hellman_t *this, chunk_t *value)
{ {
/* Front pad the value with zeros to length of prime */ *value = chunk_copy_pad(chunk_alloc(this->len), this->pub, 0x00);
*value = chunk_alloc(this->len);
memset(value->ptr, 0, value->len - this->pub.len);
memcpy(value->ptr + value->len - this->pub.len, this->pub.ptr,
this->pub.len);
return TRUE; return TRUE;
} }
METHOD(diffie_hellman_t, get_shared_secret, bool, METHOD(diffie_hellman_t, get_shared_secret, bool,
private_wolfssl_diffie_hellman_t *this, chunk_t *secret) private_wolfssl_diffie_hellman_t *this, chunk_t *secret)
{ {
if (!this->computed) if (!this->shared_secret.len)
{ {
return FALSE; return FALSE;
} }
*secret = chunk_copy_pad(chunk_alloc(this->len), this->shared_secret, 0x00);
/* Front pad with zeros to length of prime */
*secret = chunk_alloc(this->len);
memset(secret->ptr, 0, secret->len);
memcpy(secret->ptr + secret->len - this->shared_secret.len,
this->shared_secret.ptr, this->shared_secret.len);
return TRUE; return TRUE;
} }
METHOD(diffie_hellman_t, set_other_public_value, bool, METHOD(diffie_hellman_t, set_other_public_value, bool,
private_wolfssl_diffie_hellman_t *this, chunk_t value) private_wolfssl_diffie_hellman_t *this, chunk_t value)
{ {
@@ -122,17 +103,15 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
} }
chunk_clear(&this->shared_secret); chunk_clear(&this->shared_secret);
this->shared_secret.ptr = malloc(this->len); this->shared_secret = chunk_alloc(this->len);
memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
len = this->shared_secret.len;
if (wc_DhAgree(&this->dh, this->shared_secret.ptr, &len, this->priv.ptr, if (wc_DhAgree(&this->dh, this->shared_secret.ptr, &len, this->priv.ptr,
this->priv.len, value.ptr, value.len) != 0) this->priv.len, value.ptr, value.len) != 0)
{ {
DBG1(DBG_LIB, "DH shared secret computation failed"); DBG1(DBG_LIB, "DH shared secret computation failed");
chunk_free(&this->shared_secret);
return FALSE; return FALSE;
} }
this->shared_secret.len = len; this->shared_secret.len = len;
this->computed = TRUE;
return TRUE; return TRUE;
} }
@@ -142,18 +121,17 @@ METHOD(diffie_hellman_t, set_private_value, bool,
bool success = FALSE; bool success = FALSE;
chunk_t g; chunk_t g;
word32 len; word32 len;
int ret;
chunk_clear(&this->priv); chunk_clear(&this->priv);
this->priv = chunk_clone(value); this->priv = chunk_clone(value);
/* Calculate public value - g^priv mod p */ /* calculate public value - g^priv mod p */
if (wolfssl_mp2chunk(&this->dh.g, &g)) if (wolfssl_mp2chunk(&this->dh.g, &g))
{ {
len = this->pub.len; len = this->pub.len;
ret = wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr, if (wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr,
this->priv.len, g.ptr, g.len); this->priv.len, g.ptr, g.len) == 0)
if (ret == 0) { {
this->pub.len = len; this->pub.len = len;
success = TRUE; success = TRUE;
} }
@@ -169,31 +147,9 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
return this->group; return this->group;
} }
/**
* Lookup the modulus in modulo table
*/
static status_t set_modulus(private_wolfssl_diffie_hellman_t *this)
{
diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
if (!params)
{
return NOT_FOUND;
}
this->len = params->prime.len;
if (wc_DhSetKey(&this->dh, params->prime.ptr, params->prime.len,
params->generator.ptr, params->generator.len) != 0)
{
return FAILED;
}
return SUCCESS;
}
METHOD(diffie_hellman_t, destroy, void, METHOD(diffie_hellman_t, destroy, void,
private_wolfssl_diffie_hellman_t *this) private_wolfssl_diffie_hellman_t *this)
{ {
wc_FreeRng(&this->rng);
wc_FreeDhKey(&this->dh); wc_FreeDhKey(&this->dh);
chunk_clear(&this->pub); chunk_clear(&this->pub);
chunk_clear(&this->priv); chunk_clear(&this->priv);
@@ -241,14 +197,15 @@ static int wolfssl_priv_key_size(int len)
return len / 20; return len / 20;
} }
/* /**
* Described in header. * Generic internal constructor
*/ */
wolfssl_diffie_hellman_t *wolfssl_diffie_hellman_create( static wolfssl_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
diffie_hellman_group_t group, ...) chunk_t g, chunk_t p)
{ {
private_wolfssl_diffie_hellman_t *this; private_wolfssl_diffie_hellman_t *this;
word32 privLen, pubLen; word32 privLen, pubLen;
WC_RNG rng;
INIT(this, INIT(this,
.public = { .public = {
@@ -261,47 +218,26 @@ wolfssl_diffie_hellman_t *wolfssl_diffie_hellman_create(
.destroy = _destroy, .destroy = _destroy,
}, },
}, },
.group = group,
.len = p.len,
); );
if (wc_InitRng(&this->rng) != 0)
{
free(this);
return NULL;
}
if (wc_InitDhKey(&this->dh) != 0) if (wc_InitDhKey(&this->dh) != 0)
{ {
wc_FreeRng(&this->rng);
free(this); free(this);
return NULL; return NULL;
} }
this->group = group; if (wc_DhSetKey(&this->dh, p.ptr, p.len, g.ptr, g.len) != 0)
this->computed = FALSE;
this->priv = chunk_empty;
this->pub = chunk_empty;
this->shared_secret = chunk_empty;
if (group == MODP_CUSTOM)
{ {
chunk_t g, p; destroy(this);
return NULL;
VA_ARGS_GET(group, g, p);
this->len = p.len;
if (wc_DhSetKey(&this->dh, p.ptr, p.len, g.ptr, g.len) != 0)
{
destroy(this);
return NULL;
}
} }
else
if (wc_InitRng(&rng) != 0)
{ {
/* find a modulus according to group */ destroy(this);
if (set_modulus(this) != SUCCESS) return NULL;
{
destroy(this);
return NULL;
}
} }
this->priv = chunk_alloc(wolfssl_priv_key_size(this->len)); this->priv = chunk_alloc(wolfssl_priv_key_size(this->len));
@@ -309,16 +245,41 @@ wolfssl_diffie_hellman_t *wolfssl_diffie_hellman_create(
privLen = this->priv.len; privLen = this->priv.len;
pubLen = this->pub.len; pubLen = this->pub.len;
/* generate my public and private values */ /* generate my public and private values */
if (wc_DhGenerateKeyPair(&this->dh, &this->rng, this->priv.ptr, &privLen, if (wc_DhGenerateKeyPair(&this->dh, &rng, this->priv.ptr, &privLen,
this->pub.ptr, &pubLen) != 0) this->pub.ptr, &pubLen) != 0)
{ {
wc_FreeRng(&rng);
destroy(this); destroy(this);
return NULL; return NULL;
} }
this->pub.len = pubLen; this->pub.len = pubLen;
this->priv.len = privLen; this->priv.len = privLen;
wc_FreeRng(&rng);
return &this->public; return &this->public;
} }
/*
* Described in header
*/
wolfssl_diffie_hellman_t *wolfssl_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 NULL;
}
/* wolfSSL doesn't support optimized exponent sizes according to RFC 3526 */
return create_generic(group, params->generator, params->prime);
}
#endif /* NO_DH */ #endif /* NO_DH */
@@ -62,25 +62,10 @@ struct private_wolfssl_ec_diffie_hellman_t {
*/ */
ecc_key key; ecc_key key;
/**
* Other public key
*/
ecc_point *pub_key;
/** /**
* Shared secret * Shared secret
*/ */
chunk_t shared_secret; chunk_t shared_secret;
/**
* Random number generator
*/
WC_RNG rng;
/**
* True if shared secret is computed
*/
bool computed;
}; };
/** /**
@@ -90,9 +75,13 @@ struct private_wolfssl_ec_diffie_hellman_t {
static bool chunk2ecp(chunk_t chunk, ecc_point *point) static bool chunk2ecp(chunk_t chunk, ecc_point *point)
{ {
if (!wolfssl_mp_split(chunk, point->x, point->y)) if (!wolfssl_mp_split(chunk, point->x, point->y))
{
return FALSE; return FALSE;
}
if (mp_set(point->z, 1) != 0) if (mp_set(point->z, 1) != 0)
{
return FALSE; return FALSE;
}
return TRUE; return TRUE;
} }
@@ -113,23 +102,20 @@ static bool ecp2chunk(int keysize, ecc_point *point, chunk_t *chunk,
return wolfssl_mp_cat(keysize, point->x, y, chunk); return wolfssl_mp_cat(keysize, point->x, y, chunk);
} }
/** /**
* Perform the elliptic curve scalar multiplication. * Perform the elliptic curve scalar multiplication.
*/ */
static bool wolfssl_ecc_multiply(const ecc_set_type *ecc_set, mp_int *scalar, static bool wolfssl_ecc_multiply(const ecc_set_type *ecc_set, mp_int *scalar,
ecc_point* point, ecc_point* r) ecc_point *point, ecc_point *r)
{ {
int ret;
mp_int a, prime; mp_int a, prime;
int ret;
ret = mp_init(&a); if (mp_init(&a) != 0)
if (ret != 0)
{ {
return FALSE; return FALSE;
} }
ret = mp_init(&prime); if (mp_init(&prime) != 0)
if (ret != 0)
{ {
mp_free(&a); mp_free(&a);
return FALSE; return FALSE;
@@ -142,7 +128,7 @@ static bool wolfssl_ecc_multiply(const ecc_set_type *ecc_set, mp_int *scalar,
} }
if (ret == 0) if (ret == 0)
{ {
/* Multiply the point by our secret */ /* multiply the point by our secret */
ret = wc_ecc_mulmod(scalar, point, r, &a, &prime, 1); ret = wc_ecc_mulmod(scalar, point, r, &a, &prime, 1);
} }
@@ -164,24 +150,24 @@ static bool wolfssl_ecc_multiply(const ecc_set_type *ecc_set, mp_int *scalar,
* Diffie-Hellman public value." * Diffie-Hellman public value."
*/ */
static bool compute_shared_key(private_wolfssl_ec_diffie_hellman_t *this, static bool compute_shared_key(private_wolfssl_ec_diffie_hellman_t *this,
chunk_t *shared_secret) ecc_point *pub_key, chunk_t *shared_secret)
{ {
bool success = FALSE;
ecc_point* secret; ecc_point* secret;
bool x_coordinate_only; bool x_coordinate_only;
bool success = FALSE;
if ((secret = wc_ecc_new_point()) == NULL) if ((secret = wc_ecc_new_point()) == NULL)
{ {
return FALSE; return FALSE;
} }
if (wolfssl_ecc_multiply(this->key.dp, &this->key.k, this->pub_key, secret)) if (wolfssl_ecc_multiply(this->key.dp, &this->key.k, pub_key, secret))
{ {
/* /*
* The default setting ecp_x_coordinate_only = TRUE * The default setting ecp_x_coordinate_only = TRUE
* applies the following errata for RFC 4753: * applies the following errata for RFC 4753:
* http://www.rfc-editor.org/errata_search.php?eid=9 * http://www.rfc-editor.org/errata_search.php?eid=9
*/ */
x_coordinate_only = lib->settings->get_bool(lib->settings, x_coordinate_only = lib->settings->get_bool(lib->settings,
"%s.ecp_x_coordinate_only", TRUE, lib->ns); "%s.ecp_x_coordinate_only", TRUE, lib->ns);
success = ecp2chunk(this->keysize, secret, shared_secret, success = ecp2chunk(this->keysize, secret, shared_secret,
@@ -195,26 +181,35 @@ static bool compute_shared_key(private_wolfssl_ec_diffie_hellman_t *this,
METHOD(diffie_hellman_t, set_other_public_value, bool, METHOD(diffie_hellman_t, set_other_public_value, bool,
private_wolfssl_ec_diffie_hellman_t *this, chunk_t value) private_wolfssl_ec_diffie_hellman_t *this, chunk_t value)
{ {
ecc_point *pub_key;
if (!diffie_hellman_verify_value(this->group, value)) if (!diffie_hellman_verify_value(this->group, value))
{ {
return FALSE; return FALSE;
} }
if (!chunk2ecp(value, this->pub_key)) if ((pub_key = wc_ecc_new_point()) == NULL)
{
return FALSE;
}
if (!chunk2ecp(value, pub_key))
{ {
DBG1(DBG_LIB, "ECDH public value is malformed"); DBG1(DBG_LIB, "ECDH public value is malformed");
wc_ecc_del_point(pub_key);
return FALSE; return FALSE;
} }
chunk_clear(&this->shared_secret); chunk_clear(&this->shared_secret);
if (!compute_shared_key(this, &this->shared_secret)) if (!compute_shared_key(this, pub_key, &this->shared_secret))
{ {
DBG1(DBG_LIB, "ECDH shared secret computation failed"); DBG1(DBG_LIB, "ECDH shared secret computation failed");
chunk_clear(&this->shared_secret);
wc_ecc_del_point(pub_key);
return FALSE; return FALSE;
} }
wc_ecc_del_point(pub_key);
this->computed = TRUE;
return TRUE; return TRUE;
} }
@@ -237,7 +232,7 @@ METHOD(diffie_hellman_t, set_private_value, bool,
} }
ret = mp_read_unsigned_bin(&this->key.k, value.ptr, value.len); ret = mp_read_unsigned_bin(&this->key.k, value.ptr, value.len);
/* Get base point */ /* get base point */
if (ret == 0) if (ret == 0)
{ {
ret = mp_read_radix(base->x, this->key.dp->Gx, MP_RADIX_HEX); ret = mp_read_radix(base->x, this->key.dp->Gx, MP_RADIX_HEX);
@@ -252,7 +247,7 @@ METHOD(diffie_hellman_t, set_private_value, bool,
} }
if (ret == 0) if (ret == 0)
{ {
/* Calculate public key */ /* calculate public key */
success = wolfssl_ecc_multiply(this->key.dp, &this->key.k, base, success = wolfssl_ecc_multiply(this->key.dp, &this->key.k, base,
&this->key.pubkey); &this->key.pubkey);
} }
@@ -265,7 +260,7 @@ METHOD(diffie_hellman_t, set_private_value, bool,
METHOD(diffie_hellman_t, get_shared_secret, bool, METHOD(diffie_hellman_t, get_shared_secret, bool,
private_wolfssl_ec_diffie_hellman_t *this, chunk_t *secret) private_wolfssl_ec_diffie_hellman_t *this, chunk_t *secret)
{ {
if (!this->computed) if (!this->shared_secret.len)
{ {
return FALSE; return FALSE;
} }
@@ -282,19 +277,18 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
METHOD(diffie_hellman_t, destroy, void, METHOD(diffie_hellman_t, destroy, void,
private_wolfssl_ec_diffie_hellman_t *this) private_wolfssl_ec_diffie_hellman_t *this)
{ {
wc_FreeRng(&this->rng);
wc_ecc_del_point(this->pub_key);
wc_ecc_free(&this->key); wc_ecc_free(&this->key);
chunk_clear(&this->shared_secret); chunk_clear(&this->shared_secret);
free(this); free(this);
} }
/* /*
* Described in header. * Described in header
*/ */
wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(diffie_hellman_group_t group) wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(diffie_hellman_group_t group)
{ {
private_wolfssl_ec_diffie_hellman_t *this; private_wolfssl_ec_diffie_hellman_t *this;
WC_RNG rng;
INIT(this, INIT(this,
.public = { .public = {
@@ -316,21 +310,6 @@ wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(diffie_hellman_gro
free(this); free(this);
return NULL; return NULL;
} }
if ((this->pub_key = wc_ecc_new_point()) == NULL)
{
wc_ecc_free(&this->key);
DBG1(DBG_LIB, "pub_key init failed, ecdh create failed");
free(this);
return NULL;
}
if (wc_InitRng(&this->rng) != 0)
{
wc_ecc_del_point(this->pub_key);
wc_ecc_free(&this->key);
DBG1(DBG_LIB, "RNG init failed, ecdh create failed");
free(this);
return NULL;
}
switch (group) switch (group)
{ {
@@ -373,20 +352,27 @@ wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(diffie_hellman_gro
break; break;
#endif #endif
default: default:
DBG1(DBG_LIB, "EC group not supported");
destroy(this); destroy(this);
return NULL; return NULL;
} }
/* generate an EC private (public) key */ if (wc_InitRng(&rng) != 0)
if (wc_ecc_make_key_ex(&this->rng, this->keysize, &this->key,
this->curve_id) != 0)
{ {
DBG1(DBG_LIB, "Make key failed, wolfssl ECDH create failed"); DBG1(DBG_LIB, "RNG init failed, ecdh create failed");
destroy(this); destroy(this);
return NULL; return NULL;
} }
/* generate an EC private (public) key */
if (wc_ecc_make_key_ex(&rng, this->keysize, &this->key,
this->curve_id) != 0)
{
DBG1(DBG_LIB, "make key failed, wolfssl ECDH create failed");
destroy(this);
return NULL;
}
wc_FreeRng(&rng);
return &this->public; return &this->public;
} }
#endif /* HAVE_ECC_DHE */ #endif /* HAVE_ECC_DHE */
@@ -47,9 +47,10 @@ struct wolfssl_ec_diffie_hellman_t {
* Creates a new wolfssl_ec_diffie_hellman_t object. * Creates a new wolfssl_ec_diffie_hellman_t object.
* *
* @param group EC Diffie Hellman group number to use * @param group EC Diffie Hellman group number to use
* @return wolfssl_ec_diffie_hellman_t object, NULL if not supported * @return wolfssl_ec_diffie_hellman_t object, NULL if not
* supported
*/ */
wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(diffie_hellman_group_t group); wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(
diffie_hellman_group_t group);
#endif /** WOLFSSL_EC_DIFFIE_HELLMAN_H_ @}*/ #endif /** WOLFSSL_EC_DIFFIE_HELLMAN_H_ @}*/
@@ -34,7 +34,7 @@
#include <utils/debug.h> #include <utils/debug.h>
#include <wolfssl/wolfcrypt/ecc.h> #include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t; typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t;
@@ -42,8 +42,9 @@ typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t
* Private data of a wolfssl_ec_private_key_t object. * Private data of a wolfssl_ec_private_key_t object.
*/ */
struct private_wolfssl_ec_private_key_t { struct private_wolfssl_ec_private_key_t {
/** /**
* Public interface for this signer. * Public interface
*/ */
wolfssl_ec_private_key_t public; wolfssl_ec_private_key_t public;
@@ -63,7 +64,7 @@ struct private_wolfssl_ec_private_key_t {
WC_RNG rng; WC_RNG rng;
/** /**
* reference count * Reference count
*/ */
refcount_t ref; refcount_t ref;
}; };
@@ -97,7 +98,6 @@ static bool build_signature(private_wolfssl_ec_private_key_t *this,
mp_free(&s); mp_free(&s);
mp_free(&r); mp_free(&r);
return success; return success;
} }
@@ -105,16 +105,17 @@ static bool build_signature(private_wolfssl_ec_private_key_t *this,
* Build a RFC 4754 signature for a specified curve and hash algorithm * Build a RFC 4754 signature for a specified curve and hash algorithm
*/ */
static bool build_curve_signature(private_wolfssl_ec_private_key_t *this, static bool build_curve_signature(private_wolfssl_ec_private_key_t *this,
signature_scheme_t scheme, enum wc_HashType hash, ecc_curve_id curve_id, signature_scheme_t scheme,
chunk_t data, chunk_t *signature) enum wc_HashType hash, ecc_curve_id curve_id,
chunk_t data, chunk_t *signature)
{ {
bool success = FALSE;
chunk_t dgst = chunk_empty; chunk_t dgst = chunk_empty;
bool success = FALSE;
if (curve_id != this->ec.dp->id) if (curve_id != this->ec.dp->id)
{ {
DBG1(DBG_LIB, "signature scheme %N not supported by private key", DBG1(DBG_LIB, "signature scheme %N not supported by private key",
signature_scheme_names, scheme); signature_scheme_names, scheme);
return FALSE; return FALSE;
} }
if (wolfssl_hash_chunk(hash, data, &dgst)) if (wolfssl_hash_chunk(hash, data, &dgst))
@@ -129,20 +130,19 @@ static bool build_curve_signature(private_wolfssl_ec_private_key_t *this,
* Build a DER encoded signature as in RFC 3279 * Build a DER encoded signature as in RFC 3279
*/ */
static bool build_der_signature(private_wolfssl_ec_private_key_t *this, static bool build_der_signature(private_wolfssl_ec_private_key_t *this,
enum wc_HashType hash, chunk_t data, chunk_t *signature) enum wc_HashType hash, chunk_t data,
chunk_t *signature)
{ {
bool success = FALSE;
chunk_t dgst = chunk_empty; chunk_t dgst = chunk_empty;
int ret; bool success = FALSE;
word32 len; word32 len;
if (wolfssl_hash_chunk(hash, data, &dgst)) if (wolfssl_hash_chunk(hash, data, &dgst))
{ {
*signature = chunk_alloc(this->ec.dp->size * 2 + 10); *signature = chunk_alloc(wc_ecc_sig_size(&this->ec));
len = signature->len; len = signature->len;
ret = wc_ecc_sign_hash(dgst.ptr, dgst.len, signature->ptr, &len, if (wc_ecc_sign_hash(dgst.ptr, dgst.len, signature->ptr, &len,
&this->rng, &this->ec); &this->rng, &this->ec) == 0)
if (ret == 0)
{ {
signature->len = len; signature->len = len;
success = TRUE; success = TRUE;
@@ -152,7 +152,6 @@ static bool build_der_signature(private_wolfssl_ec_private_key_t *this,
chunk_free(signature); chunk_free(signature);
} }
} }
chunk_free(&dgst); chunk_free(&dgst);
return success; return success;
} }
@@ -165,40 +164,40 @@ METHOD(private_key_t, sign, bool,
{ {
case SIGN_ECDSA_WITH_NULL: case SIGN_ECDSA_WITH_NULL:
return build_signature(this, data, signature); return build_signature(this, data, signature);
#ifndef NO_SHA #ifndef NO_SHA
case SIGN_ECDSA_WITH_SHA1_DER: case SIGN_ECDSA_WITH_SHA1_DER:
return build_der_signature(this, WC_HASH_TYPE_SHA, data, signature); return build_der_signature(this, WC_HASH_TYPE_SHA, data, signature);
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case SIGN_ECDSA_WITH_SHA256_DER: case SIGN_ECDSA_WITH_SHA256_DER:
return build_der_signature(this, WC_HASH_TYPE_SHA256, data, return build_der_signature(this, WC_HASH_TYPE_SHA256, data,
signature); signature);
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case SIGN_ECDSA_WITH_SHA384_DER: case SIGN_ECDSA_WITH_SHA384_DER:
return build_der_signature(this, WC_HASH_TYPE_SHA384, data, return build_der_signature(this, WC_HASH_TYPE_SHA384, data,
signature); signature);
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case SIGN_ECDSA_WITH_SHA512_DER: case SIGN_ECDSA_WITH_SHA512_DER:
return build_der_signature(this, WC_HASH_TYPE_SHA512, data, return build_der_signature(this, WC_HASH_TYPE_SHA512, data,
signature); signature);
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case SIGN_ECDSA_256: case SIGN_ECDSA_256:
return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA256, return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
ECC_SECP256R1, data, signature); ECC_SECP256R1, data, signature);
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case SIGN_ECDSA_384: case SIGN_ECDSA_384:
return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA384, return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
ECC_SECP384R1, data, signature); ECC_SECP384R1, data, signature);
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case SIGN_ECDSA_521: case SIGN_ECDSA_521:
return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA512, return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
ECC_SECP521R1, data, signature); ECC_SECP521R1, data, signature);
#endif #endif
default: default:
DBG1(DBG_LIB, "signature scheme %N not supported", DBG1(DBG_LIB, "signature scheme %N not supported",
signature_scheme_names, scheme); signature_scheme_names, scheme);
@@ -231,16 +230,18 @@ METHOD(private_key_t, get_public_key, public_key_t*,
{ {
public_key_t *public; public_key_t *public;
chunk_t key; chunk_t key;
int ret; int len;
key = chunk_alloc((this->keysize + 7) / 8 * 5); /* space for algorithmIdentifier/bitString + one byte for the point type */
ret = wc_EccPublicKeyToDer(&this->ec, key.ptr, key.len, 1); key = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ +
if (ret < 0) TRAILING_ZERO + 1);
len = wc_EccPublicKeyToDer(&this->ec, key.ptr, key.len, 1);
if (len < 0)
{ {
chunk_free(&key); chunk_free(&key);
return NULL; return NULL;
} }
key.len = ret; key.len = len;
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, 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);
@@ -259,20 +260,23 @@ METHOD(private_key_t, get_encoding, bool,
private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type, private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type,
chunk_t *encoding) chunk_t *encoding)
{ {
bool success = TRUE;
int len;
switch (type) switch (type)
{ {
case PRIVKEY_ASN1_DER: case PRIVKEY_ASN1_DER:
case PRIVKEY_PEM: case PRIVKEY_PEM:
{ /* include space for parameters, public key and contexts */
bool success = TRUE; *encoding = chunk_alloc(3 * this->ec.dp->size + 4 * MAX_SEQ_SZ +
MAX_VERSION_SZ + MAX_ALGO_SZ);
*encoding = chunk_alloc(this->keysize * 4 + 30); len = wc_EccKeyToDer(&this->ec, encoding->ptr, encoding->len);
if (wc_EccPrivateKeyToDer(&this->ec, encoding->ptr, if (len < 0)
encoding->len) < 0)
{ {
chunk_free(encoding); chunk_free(encoding);
return FALSE; return FALSE;
} }
encoding->len = len;
if (type == PRIVKEY_PEM) if (type == PRIVKEY_PEM)
{ {
@@ -284,7 +288,6 @@ METHOD(private_key_t, get_encoding, bool,
chunk_clear(&asn1_encoding); chunk_clear(&asn1_encoding);
} }
return success; return success;
}
default: default:
return FALSE; return FALSE;
} }
@@ -338,16 +341,15 @@ static private_wolfssl_ec_private_key_t *create_empty(void)
if (wc_InitRng(&this->rng) < 0) if (wc_InitRng(&this->rng) < 0)
{ {
DBG1(DBG_LIB, "Random number generation init failed"); DBG1(DBG_LIB, "RNG init failed");
free(this); free(this);
return NULL; return NULL;
} }
return this; return this;
} }
/* /*
* See header. * Described in header
*/ */
wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type, wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type,
va_list args) va_list args)
@@ -375,6 +377,11 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type,
return NULL; return NULL;
} }
this = create_empty(); this = create_empty();
if (!this)
{
return NULL;
}
this->keysize = key_size; this->keysize = key_size;
switch (key_size) switch (key_size)
{ {
@@ -396,25 +403,23 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type,
if (wc_ecc_make_key_ex(&this->rng, (key_size + 7) / 8, &this->ec, if (wc_ecc_make_key_ex(&this->rng, (key_size + 7) / 8, &this->ec,
curve_id) < 0) curve_id) < 0)
{ {
DBG1(DBG_LIB, "EC private key generation failed", key_size); DBG1(DBG_LIB, "EC private key generation failed");
destroy(this); destroy(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
} }
/** /*
* See header. * Described in header
*/ */
wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type, wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
va_list args) va_list args)
{ {
private_wolfssl_ec_private_key_t *this; private_wolfssl_ec_private_key_t *this;
chunk_t params = chunk_empty; chunk_t params = chunk_empty, key = chunk_empty;
chunk_t key = chunk_empty;
chunk_t alg_id = chunk_empty;
word32 idx; word32 idx;
int oid; int oid = OID_UNKNOWN;
while (TRUE) while (TRUE)
{ {
@@ -433,12 +438,15 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
} }
break; break;
} }
if (key.ptr == NULL) if (!key.ptr)
{ {
return NULL; return NULL;
} }
this = create_empty(); this = create_empty();
if (!this)
{
return NULL;
}
idx = 0; idx = 0;
if (wc_EccPrivateKeyDecode(key.ptr, &idx, &this->ec, key.len) < 0) if (wc_EccPrivateKeyDecode(key.ptr, &idx, &this->ec, key.len) < 0)
@@ -463,9 +471,7 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
if (params.ptr) if (params.ptr)
{ {
/* if ECParameters is passed, check we guessed correct */ /* if ECParameters is passed, ensure we guessed correctly */
alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
chunk_clone(params));
if (asn1_unwrap(&params, &params) == ASN1_OID) if (asn1_unwrap(&params, &params) == ASN1_OID)
{ {
oid = asn1_known_oid(params); oid = asn1_known_oid(params);
@@ -494,7 +500,6 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
break; break;
} }
} }
chunk_free(&alg_id);
if (oid == OID_UNKNOWN) if (oid == OID_UNKNOWN)
{ {
DBG1(DBG_LIB, "parameters do not match private key data"); DBG1(DBG_LIB, "parameters do not match private key data");
@@ -502,7 +507,7 @@ wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
return NULL; return NULL;
} }
} }
return &this->public; return &this->public;
} }
#endif /* HAVE_ECC_SIGN */ #endif /* HAVE_ECC_SIGN */
@@ -31,7 +31,7 @@
#include <wolfssl/wolfcrypt/ecc.h> #include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/hash.h> #include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t; typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t;
@@ -39,8 +39,9 @@ typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t;
* Private data structure with signing context. * Private data structure with signing context.
*/ */
struct private_wolfssl_ec_public_key_t { struct private_wolfssl_ec_public_key_t {
/** /**
* Public interface for this signer. * Public interface
*/ */
wolfssl_ec_public_key_t public; wolfssl_ec_public_key_t public;
@@ -55,7 +56,7 @@ struct private_wolfssl_ec_public_key_t {
ecc_key ec; ecc_key ec;
/** /**
* reference counter * Reference count
*/ */
refcount_t ref; refcount_t ref;
}; };
@@ -66,8 +67,7 @@ struct private_wolfssl_ec_public_key_t {
static bool verify_signature(private_wolfssl_ec_public_key_t *this, static bool verify_signature(private_wolfssl_ec_public_key_t *this,
chunk_t hash, chunk_t signature) chunk_t hash, chunk_t signature)
{ {
int stat = 1; int stat = 1, ret = -1;
int ret = -1;
mp_int r, s; mp_int r, s;
if (mp_init(&r) < 0) if (mp_init(&r) < 0)
@@ -85,10 +85,8 @@ static bool verify_signature(private_wolfssl_ec_public_key_t *this,
ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat, ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat,
&this->ec); &this->ec);
} }
mp_free(&s); mp_free(&s);
mp_free(&r); mp_free(&r);
return ret == 0 && stat == 1; return ret == 0 && stat == 1;
} }
@@ -96,8 +94,9 @@ static bool verify_signature(private_wolfssl_ec_public_key_t *this,
* Verify a RFC 4754 signature for a specified curve and hash algorithm * Verify a RFC 4754 signature for a specified curve and hash algorithm
*/ */
static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this, static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this,
signature_scheme_t scheme, enum wc_HashType hash, ecc_curve_id curve_id, signature_scheme_t scheme,
chunk_t data, chunk_t signature) enum wc_HashType hash, ecc_curve_id curve_id,
chunk_t data, chunk_t signature)
{ {
bool success = FALSE; bool success = FALSE;
chunk_t dgst; chunk_t dgst;
@@ -122,30 +121,20 @@ static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this,
* Verification of a DER encoded signature as in RFC 3279 * Verification of a DER encoded signature as in RFC 3279
*/ */
static bool verify_der_signature(private_wolfssl_ec_public_key_t *this, static bool verify_der_signature(private_wolfssl_ec_public_key_t *this,
enum wc_HashType hash, chunk_t data, chunk_t signature) enum wc_HashType hash, chunk_t data,
chunk_t signature)
{ {
bool success = FALSE;
chunk_t dgst; chunk_t dgst;
int stat = 1; int stat = 1, ret = -1;
int ret;
/* remove any preceding 0-bytes from signature */ signature = chunk_skip_zero(signature);
while (signature.len && signature.ptr[0] == 0x00)
{
signature = chunk_skip(signature, 1);
}
if (wolfssl_hash_chunk(hash, data, &dgst)) if (wolfssl_hash_chunk(hash, data, &dgst))
{ {
ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr, ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr,
dgst.len, &stat, &this->ec); dgst.len, &stat, &this->ec);
if (ret == 0 && stat == 1)
{
success = TRUE;
}
} }
chunk_free(&dgst); chunk_free(&dgst);
return success; return ret == 0 && stat == 1;
} }
METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, get_type, key_type_t,
@@ -160,45 +149,45 @@ METHOD(public_key_t, verify, bool,
{ {
switch (scheme) switch (scheme)
{ {
#ifndef NO_SHA #ifndef NO_SHA
case SIGN_ECDSA_WITH_SHA1_DER: case SIGN_ECDSA_WITH_SHA1_DER:
return verify_der_signature(this, WC_HASH_TYPE_SHA, data, return verify_der_signature(this, WC_HASH_TYPE_SHA, data,
signature); signature);
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case SIGN_ECDSA_WITH_SHA256_DER: case SIGN_ECDSA_WITH_SHA256_DER:
return verify_der_signature(this, WC_HASH_TYPE_SHA256, data, return verify_der_signature(this, WC_HASH_TYPE_SHA256, data,
signature); signature);
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case SIGN_ECDSA_WITH_SHA384_DER: case SIGN_ECDSA_WITH_SHA384_DER:
return verify_der_signature(this, WC_HASH_TYPE_SHA384, data, return verify_der_signature(this, WC_HASH_TYPE_SHA384, data,
signature); signature);
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case SIGN_ECDSA_WITH_SHA512_DER: case SIGN_ECDSA_WITH_SHA512_DER:
return verify_der_signature(this, WC_HASH_TYPE_SHA512, data, return verify_der_signature(this, WC_HASH_TYPE_SHA512, data,
signature); signature);
#endif #endif
case SIGN_ECDSA_WITH_NULL: case SIGN_ECDSA_WITH_NULL:
return verify_signature(this, data, signature); return verify_signature(this, data, signature);
#ifndef NO_SHA256 #ifndef NO_SHA256
case SIGN_ECDSA_256: case SIGN_ECDSA_256:
return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256, return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
ECC_SECP256R1, data, signature); ECC_SECP256R1, data, signature);
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case SIGN_ECDSA_384: case SIGN_ECDSA_384:
return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384, return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
ECC_SECP384R1, data, signature); ECC_SECP384R1, data, signature);
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case SIGN_ECDSA_521: case SIGN_ECDSA_521:
return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512, return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
ECC_SECP521R1, data, signature); ECC_SECP521R1, data, signature);
#endif #endif
default: default:
DBG1(DBG_LIB, "signature scheme %N not supported in EC", DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
signature_scheme_names, scheme); signature_scheme_names, scheme);
return FALSE; return FALSE;
} }
@@ -219,51 +208,51 @@ METHOD(public_key_t, get_keysize, int,
} }
/** /**
* Calculate fingerprint from a EC_KEY, also used in ec private key. * Calculate fingerprint from an EC key, also used in ec private key.
*/ */
bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp) bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp)
{ {
hasher_t *hasher; hasher_t *hasher;
chunk_t key; chunk_t key;
int ret; int len;
bool success;
if (lib->encoding->get_cache(lib->encoding, type, ec, fp)) if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
{ {
return TRUE; return TRUE;
} }
key = chunk_alloc(ec->dp->size * 4 + 30);
ret = wc_EccPublicKeyToDer(ec, key.ptr, key.len, 1);
if (ret < 0)
{
free(key.ptr);
return FALSE;
}
key.len = ret;
switch (type) switch (type)
{ {
case KEYID_PUBKEY_SHA1: case KEYID_PUBKEY_SHA1:
case KEYID_PUBKEY_INFO_SHA1:
/* need an additional byte for the point type */
len = ec->dp->size * 2 + 1;
if (type == KEYID_PUBKEY_INFO_SHA1)
{
/* additional space for algorithmIdentifier/bitString */
len += 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + TRAILING_ZERO;
}
key = chunk_alloca(len);
len = wc_EccPublicKeyToDer(ec, key.ptr, key.len,
type == KEYID_PUBKEY_INFO_SHA1);
break; break;
default: default:
success = lib->encoding->encode(lib->encoding, type, ec, fp, return FALSE;
CRED_PART_ECDSA_PUB_ASN1_DER, key,
CRED_PART_END);
chunk_free(&key);
return success;
} }
if (len < 0)
{
return FALSE;
}
key.len = len;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher || !hasher->allocate_hash(hasher, key, fp)) if (!hasher || !hasher->allocate_hash(hasher, key, fp))
{ {
DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed"); DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
DESTROY_IF(hasher); DESTROY_IF(hasher);
free(key.ptr);
return FALSE; return FALSE;
} }
hasher->destroy(hasher); hasher->destroy(hasher);
free(key.ptr);
lib->encoding->cache(lib->encoding, type, ec, *fp); lib->encoding->cache(lib->encoding, type, ec, *fp);
return TRUE; return TRUE;
} }
@@ -280,18 +269,20 @@ METHOD(public_key_t, get_encoding, bool,
chunk_t *encoding) chunk_t *encoding)
{ {
bool success = TRUE; bool success = TRUE;
int ret; int len;
*encoding = chunk_alloc(this->ec.dp->size * 2 + 30); /* space for algorithmIdentifier/bitString + one byte for the point type */
ret = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1); *encoding = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ +
if (ret < 0) 2 * MAX_ALGO_SZ + TRAILING_ZERO + 1);
len = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1);
if (len < 0)
{ {
chunk_free(encoding); chunk_free(encoding);
return FALSE; return FALSE;
} }
encoding->len = ret; encoding->len = len;
if (type != PUBKEY_ASN1_DER) if (type != PUBKEY_SPKI_ASN1_DER)
{ {
chunk_t asn1_encoding = *encoding; chunk_t asn1_encoding = *encoding;
@@ -351,12 +342,11 @@ static private_wolfssl_ec_public_key_t *create_empty()
free(this); free(this);
return NULL; return NULL;
} }
return this; return this;
} }
/** /*
* See header. * Described in header
*/ */
wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type, wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
va_list args) va_list args)
@@ -366,11 +356,6 @@ wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
word32 idx; word32 idx;
int ret; int ret;
if (type != KEY_ECDSA)
{
return NULL;
}
while (TRUE) while (TRUE)
{ {
switch (va_arg(args, builder_part_t)) switch (va_arg(args, builder_part_t))
@@ -386,6 +371,11 @@ wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
break; break;
} }
this = create_empty(); this = create_empty();
if (!this)
{
return NULL;
}
idx = 0; idx = 0;
ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len); ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len);
if (ret < 0) if (ret < 0)
@@ -409,5 +399,5 @@ wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
} }
return &this->public; return &this->public;
} }
#endif /* HAVE_ECC_VERIFY */
#endif /* HAVE_ECC_VERIFY */
@@ -29,6 +29,7 @@
#include <utils/debug.h> #include <utils/debug.h>
#include <wolfssl/wolfcrypt/ed25519.h> #include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_private_key_t private_private_key_t; typedef struct private_private_key_t private_private_key_t;
@@ -48,17 +49,11 @@ struct private_private_key_t {
ed25519_key key; ed25519_key key;
/** /**
* Key type * Reference count
*/
key_type_t type;
/**
* reference count
*/ */
refcount_t ref; refcount_t ref;
}; };
/* from ed public key */ /* from ed public key */
bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type, bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
chunk_t *fp); chunk_t *fp);
@@ -68,17 +63,17 @@ METHOD(private_key_t, sign, bool,
void *params, chunk_t data, chunk_t *signature) void *params, chunk_t data, chunk_t *signature)
{ {
word32 len; word32 len;
int ret;
byte dummy[1]; byte dummy[1];
int ret;
if (this->type == KEY_ED25519 && scheme != SIGN_ED25519) if (scheme != SIGN_ED25519)
{ {
DBG1(DBG_LIB, "signature scheme %N not supported by %N key", DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
signature_scheme_names, scheme, key_type_names, this->type); signature_scheme_names, scheme, key_type_names, KEY_ED25519);
return FALSE; return FALSE;
} }
if (data.ptr == NULL && data.len == 0) if (!data.ptr && !data.len)
{ {
data.ptr = dummy; data.ptr = dummy;
} }
@@ -86,7 +81,7 @@ METHOD(private_key_t, sign, bool,
len = ED25519_SIG_SIZE; len = ED25519_SIG_SIZE;
*signature = chunk_alloc(len); *signature = chunk_alloc(len);
ret = wc_ed25519_sign_msg(data.ptr, data.len, signature->ptr, &len, ret = wc_ed25519_sign_msg(data.ptr, data.len, signature->ptr, &len,
&this->key); &this->key);
return ret == 0; return ret == 0;
} }
@@ -107,7 +102,7 @@ METHOD(private_key_t, get_keysize, int,
METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, get_type, key_type_t,
private_private_key_t *this) private_private_key_t *this)
{ {
return this->type; return KEY_ED25519;
} }
METHOD(private_key_t, get_public_key, public_key_t*, METHOD(private_key_t, get_public_key, public_key_t*,
@@ -117,14 +112,12 @@ METHOD(private_key_t, get_public_key, public_key_t*,
chunk_t key; chunk_t key;
word32 len = ED25519_PUB_KEY_SIZE; word32 len = ED25519_PUB_KEY_SIZE;
/* Allocate on stack */
key = chunk_alloca(len); key = chunk_alloca(len);
if (wc_ed25519_export_public(&this->key, key.ptr, &len) != 0) if (wc_ed25519_export_public(&this->key, key.ptr, &len) != 0)
{ {
chunk_free(&key);
return NULL; return NULL;
} }
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, this->type, public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED25519,
BUILD_EDDSA_PUB, key, BUILD_END); BUILD_EDDSA_PUB, key, BUILD_END);
return public; return public;
} }
@@ -148,7 +141,9 @@ METHOD(private_key_t, get_encoding, bool,
{ {
bool success = TRUE; bool success = TRUE;
*encoding = chunk_alloc(ED25519_PRV_KEY_SIZE + 20); /* +4 is for the two octet strings */
*encoding = chunk_alloc(ED25519_PRV_KEY_SIZE + 2 * MAX_SEQ_SZ +
MAX_VERSION_SZ + MAX_ALGO_SZ + 4);
ret = wc_Ed25519PrivateKeyToDer(&this->key, encoding->ptr, ret = wc_Ed25519PrivateKeyToDer(&this->key, encoding->ptr,
encoding->len); encoding->len);
if (ret < 0) if (ret < 0)
@@ -195,7 +190,7 @@ METHOD(private_key_t, destroy, void,
/** /**
* Internal generic constructor * Internal generic constructor
*/ */
static private_private_key_t *create_internal(key_type_t type) static private_private_key_t *create_internal()
{ {
private_private_key_t *this; private_private_key_t *this;
@@ -214,7 +209,6 @@ static private_private_key_t *create_internal(key_type_t type)
.get_ref = _get_ref, .get_ref = _get_ref,
.destroy = _destroy, .destroy = _destroy,
}, },
.type = type,
.ref = 1, .ref = 1,
); );
@@ -235,12 +229,6 @@ private_key_t *wolfssl_ed_private_key_gen(key_type_t type, va_list args)
WC_RNG rng; WC_RNG rng;
int ret; int ret;
if (wc_InitRng(&rng) != 0)
{
DBG1(DBG_LIB, "initializing random failed");
return NULL;
}
while (TRUE) while (TRUE)
{ {
switch (va_arg(args, builder_part_t)) switch (va_arg(args, builder_part_t))
@@ -257,31 +245,52 @@ private_key_t *wolfssl_ed_private_key_gen(key_type_t type, va_list args)
break; break;
} }
switch (type) this = create_internal();
{ if (!this)
case KEY_ED25519:
break;
default:
return NULL;
}
this = create_internal(type);
if (this == NULL)
{ {
return NULL; return NULL;
} }
if (wc_InitRng(&rng) != 0)
{
DBG1(DBG_LIB, "initializing random failed");
destroy(this);
return NULL;
}
ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &this->key); ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &this->key);
wc_FreeRng(&rng); wc_FreeRng(&rng);
if (ret < 0) if (ret < 0)
{ {
DBG1(DBG_LIB, "generating %N key failed", key_type_names, type); DBG1(DBG_LIB, "generating %N key failed", key_type_names, type);
destroy(this); destroy(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
} }
/**
* Fix the internal state if only the private key is set
*/
static int set_public_key(private_private_key_t *this)
{
int ret = 0;
if (!this->key.pubKeySet)
{
ret = wc_ed25519_make_public(&this->key, this->key.p,
ED25519_PUB_KEY_SIZE);
if (ret == 0)
{
/* put public key after private key in the same buffer */
memmove(this->key.k + ED25519_KEY_SIZE, this->key.p,
ED25519_PUB_KEY_SIZE);
this->key.pubKeySet = 1;
}
}
return ret;
}
/* /*
* Described in header * Described in header
*/ */
@@ -309,40 +318,31 @@ private_key_t *wolfssl_ed_private_key_load(key_type_t type, va_list args)
} }
break; break;
} }
this = create_internal(type); this = create_internal();
if (this == NULL) if (!this)
{ {
return NULL; return NULL;
} }
if (priv.len) if (priv.len)
{ {
/* Check for ASN.1 wrapped key (Octet String == 0x04) */ /* check for ASN.1 wrapped key (Octet String == 0x04) */
if (priv.len == ED25519_KEY_SIZE + 2 && priv.ptr[0] == 0x04 && if (priv.len == ED25519_KEY_SIZE + 2 && priv.ptr[0] == 0x04 &&
priv.ptr[1] == ED25519_KEY_SIZE) priv.ptr[1] == ED25519_KEY_SIZE)
{ {
priv = chunk_skip(priv, 2); priv = chunk_skip(priv, 2);
} }
ret = wc_ed25519_import_private_only(priv.ptr, priv.len, &this->key); ret = wc_ed25519_import_private_only(priv.ptr, priv.len, &this->key);
if (ret == 0)
{
ret = wc_ed25519_make_public(&this->key, this->key.p,
ED25519_PUB_KEY_SIZE);
}
if (ret == 0)
{
/* Fix internal state now public key set */
memmove(this->key.k + ED25519_KEY_SIZE, this->key.p,
ED25519_PUB_KEY_SIZE);
this->key.pubKeySet = 1;
}
} }
else if (blob.len) else if (blob.len)
{ {
idx = 0; idx = 0;
ret = wc_Ed25519PrivateKeyDecode(blob.ptr, &idx, &this->key, blob.len); ret = wc_Ed25519PrivateKeyDecode(blob.ptr, &idx, &this->key, blob.len);
} }
if (ret == 0)
{
ret = set_public_key(this);
}
if (ret != 0) if (ret != 0)
{ {
destroy(this); destroy(this);
@@ -27,8 +27,10 @@
#include "wolfssl_ed_public_key.h" #include "wolfssl_ed_public_key.h"
#include <utils/debug.h> #include <utils/debug.h>
#include <asn1/asn1.h>
#include <wolfssl/wolfcrypt/ed25519.h> #include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_public_key_t private_public_key_t; typedef struct private_public_key_t private_public_key_t;
@@ -48,39 +50,32 @@ struct private_public_key_t {
ed25519_key key; ed25519_key key;
/** /**
* Key type * Reference count
*/
key_type_t type;
/**
* Reference counter
*/ */
refcount_t ref; refcount_t ref;
}; };
METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, get_type, key_type_t,
private_public_key_t *this) private_public_key_t *this)
{ {
return this->type; return KEY_ED25519;
} }
METHOD(public_key_t, verify, bool, METHOD(public_key_t, verify, bool,
private_public_key_t *this, signature_scheme_t scheme, private_public_key_t *this, signature_scheme_t scheme,
void *params, chunk_t data, chunk_t signature) void *params, chunk_t data, chunk_t signature)
{ {
int ret;
int res;
byte dummy[1]; byte dummy[1];
int ret, res;
if (this->type == KEY_ED25519 && scheme != SIGN_ED25519) if (scheme != SIGN_ED25519)
{ {
DBG1(DBG_LIB, "signature scheme %N not supported by %N key", DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
signature_scheme_names, scheme, key_type_names, this->type); signature_scheme_names, scheme, key_type_names, KEY_ED25519);
return FALSE; return FALSE;
} }
if (data.ptr == NULL && data.len == 0) if (!data.ptr && !data.len)
{ {
data.ptr = dummy; data.ptr = dummy;
} }
@@ -105,6 +100,25 @@ METHOD(public_key_t, get_keysize, int,
return ED25519_KEY_SIZE * 8; return ED25519_KEY_SIZE * 8;
} }
/**
* Encode the given public key as ASN.1 DER with algorithm identifier
*/
static bool encode_pubkey(ed25519_key *key, chunk_t *encoding)
{
int ret;
/* account for algorithmIdentifier/bitString */
*encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
MAX_ALGO_SZ + TRAILING_ZERO);
ret = wc_Ed25519PublicKeyToDer(key, encoding->ptr, encoding->len, 1);
if (ret < 0)
{
return FALSE;
}
encoding->len = ret;
return TRUE;
}
/** /**
* Calculate fingerprint from an EdDSA key, also used in ed private key. * Calculate fingerprint from an EdDSA key, also used in ed private key.
*/ */
@@ -114,7 +128,7 @@ bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
hasher_t *hasher; hasher_t *hasher;
chunk_t blob; chunk_t blob;
word32 len; word32 len;
int ret; bool success = FALSE;
if (lib->encoding->get_cache(lib->encoding, type, key, fp)) if (lib->encoding->get_cache(lib->encoding, type, key, fp))
{ {
@@ -124,21 +138,17 @@ bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
{ {
case KEYID_PUBKEY_SHA1: case KEYID_PUBKEY_SHA1:
len = ED25519_PUB_KEY_SIZE; len = ED25519_PUB_KEY_SIZE;
blob = chunk_alloca(len); blob = chunk_alloc(len);
if (wc_ed25519_export_public(key, blob.ptr, &len) != 0) if (wc_ed25519_export_public(key, blob.ptr, &len) != 0)
{ {
return FALSE; return FALSE;
} }
break; break;
case KEYID_PUBKEY_INFO_SHA1: case KEYID_PUBKEY_INFO_SHA1:
len = ED25519_PUB_KEY_SIZE + 40; if (!encode_pubkey(key, &blob))
blob = chunk_alloca(len);
ret = wc_Ed25519PublicKeyToDer(key, blob.ptr, blob.len, 1);
if (ret < 0)
{ {
return FALSE; return FALSE;
} }
blob.len = ret;
break; break;
default: default:
return FALSE; return FALSE;
@@ -147,12 +157,15 @@ bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
if (!hasher || !hasher->allocate_hash(hasher, blob, fp)) if (!hasher || !hasher->allocate_hash(hasher, blob, fp))
{ {
DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed"); DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
DESTROY_IF(hasher);
return FALSE;
} }
hasher->destroy(hasher); else
lib->encoding->cache(lib->encoding, type, key, *fp); {
return TRUE; lib->encoding->cache(lib->encoding, type, key, *fp);
success = TRUE;
}
DESTROY_IF(hasher);
chunk_free(&blob);
return success;
} }
METHOD(public_key_t, get_fingerprint, bool, METHOD(public_key_t, get_fingerprint, bool,
@@ -165,15 +178,11 @@ METHOD(public_key_t, get_encoding, bool,
private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding) private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
{ {
bool success = TRUE; bool success = TRUE;
int ret;
*encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 32); if (!encode_pubkey(&this->key, encoding))
ret = wc_Ed25519PublicKeyToDer(&this->key, encoding->ptr, encoding->len, 1);
if (ret < 0)
{ {
return FALSE; return FALSE;
} }
encoding->len = ret;
if (type != PUBKEY_SPKI_ASN1_DER) if (type != PUBKEY_SPKI_ASN1_DER)
{ {
@@ -182,7 +191,7 @@ METHOD(public_key_t, get_encoding, bool,
success = lib->encoding->encode(lib->encoding, type, success = lib->encoding->encode(lib->encoding, type,
NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER, NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER,
asn1_encoding, CRED_PART_END); asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding); chunk_free(&asn1_encoding);
} }
return success; return success;
} }
@@ -208,7 +217,7 @@ METHOD(public_key_t, destroy, void,
/** /**
* Generic private constructor * Generic private constructor
*/ */
static private_public_key_t *create_empty(key_type_t type) static private_public_key_t *create_empty()
{ {
private_public_key_t *this; private_public_key_t *this;
@@ -225,15 +234,14 @@ static private_public_key_t *create_empty(key_type_t type)
.get_ref = _get_ref, .get_ref = _get_ref,
.destroy = _destroy, .destroy = _destroy,
}, },
.type = type,
.ref = 1, .ref = 1,
); );
if (wc_ed25519_init(&this->key) != 0) if (wc_ed25519_init(&this->key) != 0)
{ {
free(this); free(this);
return NULL; return NULL;
} }
return this; return this;
} }
@@ -265,8 +273,8 @@ public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args)
break; break;
} }
this = create_empty(type); this = create_empty();
if (this == NULL) if (!this)
{ {
return NULL; return NULL;
} }
@@ -34,17 +34,17 @@ typedef struct private_wolfssl_hasher_t private_wolfssl_hasher_t;
struct private_wolfssl_hasher_t { struct private_wolfssl_hasher_t {
/** /**
* Public part of this class. * Public interface
*/ */
wolfssl_hasher_t public; wolfssl_hasher_t public;
/** /**
* the hasher to use * The hasher to use
*/ */
wc_HashAlg hasher; wc_HashAlg hasher;
/** /**
* the hash algiorithm * The hash algorithm
*/ */
enum wc_HashType type; enum wc_HashType type;
}; };
@@ -128,6 +128,5 @@ wolfssl_hasher_t *wolfssl_hasher_create(hash_algorithm_t algo)
destroy(this); destroy(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
} }
@@ -77,10 +77,10 @@ METHOD(mac_t, get_mac, bool,
if (this->key_set) if (this->key_set)
{ {
ret = wc_HmacUpdate(&this->hmac, data.ptr, data.len); ret = wc_HmacUpdate(&this->hmac, data.ptr, data.len);
} if (ret == 0 && out)
if (ret == 0 && out != NULL) {
{ ret = wc_HmacFinal(&this->hmac, out);
ret = wc_HmacFinal(&this->hmac, out); }
} }
return ret == 0; return ret == 0;
} }
@@ -121,14 +121,12 @@ static mac_t *hmac_create(hash_algorithm_t algo)
.type = type, .type = type,
); );
if (wc_HmacInit(&this->hmac, NULL, INVALID_DEVID) != 0) if (wc_HmacInit(&this->hmac, NULL, INVALID_DEVID) != 0)
{ {
DBG1(DBG_LIB, "HMAC init failed, hmac create failed\n"); DBG1(DBG_LIB, "HMAC init failed, hmac create failed\n");
free(this); free(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
} }
@@ -45,21 +45,19 @@
#define FIPS_MODE 0 #define FIPS_MODE 0
#endif #endif
typedef struct private_wolfssl_plugin_t private_wolfssl_plugin_t; typedef struct private_wolfssl_plugin_t private_wolfssl_plugin_t;
/** /**
* private data of wolfssl_plugin * Private data of wolfssl_plugin
*/ */
struct private_wolfssl_plugin_t { struct private_wolfssl_plugin_t {
/** /**
* public functions * Public interface
*/ */
wolfssl_plugin_t public; wolfssl_plugin_t public;
}; };
METHOD(plugin_t, get_name, char*, METHOD(plugin_t, get_name, char*,
private_wolfssl_plugin_t *this) private_wolfssl_plugin_t *this)
{ {
@@ -424,30 +422,29 @@ METHOD(plugin_t, destroy, void,
} }
/* /*
* see header file * Described in header
*/ */
plugin_t *wolfssl_plugin_create() plugin_t *wolfssl_plugin_create()
{ {
private_wolfssl_plugin_t *this; private_wolfssl_plugin_t *this;
int fips_mode; bool fips_mode;
fips_mode = lib->settings->get_int(lib->settings, fips_mode = lib->settings->get_bool(lib->settings,
"%s.plugins.wolfssl.fips_mode", FIPS_MODE, lib->ns); "%s.plugins.wolfssl.fips_mode", FALSE, lib->ns);
#ifdef HAVE_FIPS #ifdef HAVE_FIPS
if (fips_mode) if (fips_mode)
{ {
int ret = wolfCrypt_GetStatus_fips(); int ret = wolfCrypt_GetStatus_fips();
if (ret != 0) if (ret != 0)
{ {
DBG1(DBG_LIB, "wolfssl FIPS mode(%d) unavailable (%d)", fips_mode, DBG1(DBG_LIB, "wolfssl FIPS mode unavailable (%d)", ret);
ret);
return NULL; return NULL;
} }
} }
#else #else
if (fips_mode) if (fips_mode)
{ {
DBG1(DBG_LIB, "wolfssl FIPS mode(%d) unavailable", fips_mode); DBG1(DBG_LIB, "wolfssl FIPS mode unavailable");
return NULL; return NULL;
} }
#endif #endif
+10 -11
View File
@@ -37,7 +37,7 @@ typedef struct private_wolfssl_rng_t private_wolfssl_rng_t;
wolfSSL_Mutex globalRngMutex; wolfSSL_Mutex globalRngMutex;
#endif #endif
static WC_RNG globalRng; static WC_RNG globalRng;
static int globalRngInit = 0; static bool globalRngInit;
/** /**
* Private data of wolfssl_rng_t * Private data of wolfssl_rng_t
@@ -67,7 +67,7 @@ METHOD(rng_t, get_bytes, bool,
ret = wc_LockMutex(&globalRngMutex); ret = wc_LockMutex(&globalRngMutex);
if (ret != 0) if (ret != 0)
{ {
DBG1(DBG_LIB, "Locking failed, get bytes failed"); DBG1(DBG_LIB, "locking failed, get bytes failed");
return FALSE; return FALSE;
} }
} }
@@ -107,7 +107,7 @@ METHOD(rng_t, destroy, void,
} }
/* /*
* Described in header. * Described in header
*/ */
wolfssl_rng_t *wolfssl_rng_create(rng_quality_t quality) wolfssl_rng_t *wolfssl_rng_create(rng_quality_t quality)
{ {
@@ -129,7 +129,7 @@ wolfssl_rng_t *wolfssl_rng_create(rng_quality_t quality)
this->rng = malloc(sizeof(*this->rng)); this->rng = malloc(sizeof(*this->rng));
if (wc_InitRng(this->rng) != 0) if (wc_InitRng(this->rng) != 0)
{ {
DBG1(DBG_LIB, "Init RNG failed, rng create failed"); DBG1(DBG_LIB, "init RNG failed, rng create failed");
free(this->rng); free(this->rng);
free(this); free(this);
return NULL; return NULL;
@@ -139,7 +139,7 @@ wolfssl_rng_t *wolfssl_rng_create(rng_quality_t quality)
} }
/* /*
* Described in header. * Described in header
*/ */
int wolfssl_rng_global_init() int wolfssl_rng_global_init()
{ {
@@ -150,25 +150,24 @@ int wolfssl_rng_global_init()
ret = wc_InitRng(&globalRng); ret = wc_InitRng(&globalRng);
if (ret != 0) if (ret != 0)
{ {
DBG1(DBG_LIB, "Init RNG failed, rng global init failed"); DBG1(DBG_LIB, "init RNG failed, rng global init failed");
} }
#ifndef SINGLE_THREADED #ifndef SINGLE_THREADED
else if ((ret = wc_InitMutex(&globalRngMutex)) != 0) else if ((ret = wc_InitMutex(&globalRngMutex)) != 0)
{ {
DBG1(DBG_LIB, "Init Mutex failed, rng global init failed"); DBG1(DBG_LIB, "init Mutex failed, rng global init failed");
} }
#endif #endif
else else
{ {
globalRngInit = 1; globalRngInit = TRUE;
} }
} }
return ret == 0; return ret == 0;
} }
/* /*
* Described in header. * Described in header
*/ */
void wolfssl_rng_global_final() void wolfssl_rng_global_final()
{ {
@@ -178,7 +177,7 @@ void wolfssl_rng_global_final()
wc_FreeMutex(&globalRngMutex); wc_FreeMutex(&globalRngMutex);
#endif #endif
wc_FreeRng(&globalRng); wc_FreeRng(&globalRng);
globalRngInit = 0; globalRngInit = FALSE;
} }
} }
@@ -28,20 +28,22 @@
#include "wolfssl_rsa_public_key.h" #include "wolfssl_rsa_public_key.h"
#include "wolfssl_util.h" #include "wolfssl_util.h"
#include <crypto/hashers/hasher.h>
#include <utils/debug.h> #include <utils/debug.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/signature_params.h> #include <credentials/keys/signature_params.h>
#include <wolfssl/wolfcrypt/rsa.h> #include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_wolfssl_rsa_private_key_t private_wolfssl_rsa_private_key_t; typedef struct private_wolfssl_rsa_private_key_t private_wolfssl_rsa_private_key_t;
/** /**
* Private data of a wolfssl_rsa_private_key_t object. * Private data of a wolfssl_rsa_private_key_t object
*/ */
struct private_wolfssl_rsa_private_key_t { struct private_wolfssl_rsa_private_key_t {
/** /**
* Public interface for this signer. * Public interface
*/ */
wolfssl_rsa_private_key_t public; wolfssl_rsa_private_key_t public;
@@ -56,15 +58,15 @@ struct private_wolfssl_rsa_private_key_t {
WC_RNG rng; WC_RNG rng;
/** /**
* reference count * Reference count
*/ */
refcount_t ref; refcount_t ref;
}; };
/* implemented in rsa public key */ /* implemented in rsa public key */
bool wolfssl_rsa_encode_public(RsaKey *rsa, chunk_t *encoding);
bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type, chunk_t *fp); bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type, chunk_t *fp);
/** /**
* Build RSA signature * Build RSA signature
*/ */
@@ -88,8 +90,8 @@ static bool build_emsa_pkcs1_signature(private_wolfssl_rsa_private_key_t *this,
chunk_t *sig) chunk_t *sig)
{ {
bool success = FALSE; bool success = FALSE;
chunk_t dgst, encDgst; chunk_t dgst, digestInfo;
int ret; int len;
*sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa)); *sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa));
@@ -99,16 +101,15 @@ static bool build_emsa_pkcs1_signature(private_wolfssl_rsa_private_key_t *this,
} }
else if (wolfssl_hash_chunk(hash, data, &dgst)) else if (wolfssl_hash_chunk(hash, data, &dgst))
{ {
encDgst = chunk_alloc(dgst.len + 20); digestInfo = chunk_alloc(MAX_DER_DIGEST_SZ);
ret = wc_EncodeSignature(encDgst.ptr, dgst.ptr, dgst.len, len = wc_EncodeSignature(digestInfo.ptr, dgst.ptr, dgst.len,
wc_HashGetOID(hash)); wc_HashGetOID(hash));
if (ret > 0) if (len > 0)
{ {
encDgst.len = ret; digestInfo.len = len;
success = build_signature(this, hash, encDgst, sig); success = build_signature(this, hash, digestInfo, sig);
} }
chunk_free(&digestInfo);
chunk_free(&encDgst);
chunk_free(&dgst); chunk_free(&dgst);
} }
@@ -130,8 +131,7 @@ static bool build_emsa_pss_signature(private_wolfssl_rsa_private_key_t *this,
bool success = FALSE; bool success = FALSE;
chunk_t dgst = chunk_empty; chunk_t dgst = chunk_empty;
enum wc_HashType hash; enum wc_HashType hash;
int mgf; int mgf, ret;
int ret;
if (!wolfssl_hash2type(params->hash, &hash)) if (!wolfssl_hash2type(params->hash, &hash))
{ {
@@ -215,7 +215,7 @@ METHOD(private_key_t, sign, bool,
return build_emsa_pss_signature(this, params, data, signature); return build_emsa_pss_signature(this, params, data, signature);
#endif #endif
default: default:
DBG1(DBG_LIB, "signature scheme %N not supported in RSA", DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
signature_scheme_names, scheme); signature_scheme_names, scheme);
return FALSE; return FALSE;
} }
@@ -227,7 +227,6 @@ METHOD(private_key_t, decrypt, bool,
{ {
int padding, mgf, len; int padding, mgf, len;
enum wc_HashType hash; enum wc_HashType hash;
char *decrypted;
switch (scheme) switch (scheme)
{ {
@@ -279,16 +278,16 @@ METHOD(private_key_t, decrypt, bool,
return FALSE; return FALSE;
} }
len = wc_RsaEncryptSize(&this->rsa); len = wc_RsaEncryptSize(&this->rsa);
decrypted = malloc(len); *plain = chunk_alloc(len);
len = wc_RsaPrivateDecrypt_ex(crypto.ptr, crypto.len, decrypted, len, len = wc_RsaPrivateDecrypt_ex(crypto.ptr, crypto.len, plain->ptr, len,
&this->rsa, padding, hash, mgf, NULL, 0); &this->rsa, padding, hash, mgf, NULL, 0);
if (len < 0) if (len < 0)
{ {
DBG1(DBG_LIB, "RSA decryption failed"); DBG1(DBG_LIB, "RSA decryption failed");
free(decrypted); chunk_free(plain);
return FALSE; return FALSE;
} }
*plain = chunk_create(decrypted, len); plain->len = len;
return TRUE; return TRUE;
} }
@@ -301,15 +300,16 @@ METHOD(private_key_t, get_keysize, int,
METHOD(private_key_t, get_public_key, public_key_t*, METHOD(private_key_t, get_public_key, public_key_t*,
private_wolfssl_rsa_private_key_t *this) private_wolfssl_rsa_private_key_t *this)
{ {
chunk_t enc;
public_key_t *key; public_key_t *key;
int len = wc_RsaEncryptSize(&this->rsa) * 2 + 20; chunk_t enc;
enc = chunk_alloc(len); if (!wolfssl_rsa_encode_public(&this->rsa, &enc))
enc.len = wc_RsaKeyToPublicDer(&this->rsa, enc.ptr, len); {
return NULL;
}
key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
BUILD_BLOB_ASN1_DER, enc, BUILD_END); BUILD_BLOB_ASN1_DER, enc, BUILD_END);
free(enc.ptr); chunk_free(&enc);
return key; return key;
} }
@@ -330,8 +330,11 @@ METHOD(private_key_t, get_encoding, bool,
case PRIVKEY_PEM: case PRIVKEY_PEM:
{ {
bool success = TRUE; bool success = TRUE;
int len = wc_RsaEncryptSize(&this->rsa) * 5 + 20; int len;
/* n and d are of keysize length, p and q plus the three CRT
* params roughtly half that, the version and e are small */
len = wc_RsaEncryptSize(&this->rsa) * 5 + MAX_SEQ_SZ;
*encoding = chunk_alloc(len); *encoding = chunk_alloc(len);
len = wc_RsaKeyToDer(&this->rsa, encoding->ptr, len); len = wc_RsaKeyToDer(&this->rsa, encoding->ptr, len);
if (len < 0) if (len < 0)
@@ -405,13 +408,13 @@ static private_wolfssl_rsa_private_key_t *create_empty()
if (wc_InitRng(&this->rng) != 0) if (wc_InitRng(&this->rng) != 0)
{ {
DBG1(DBG_LIB, "Init RNG failed, rsa private key create failed\n"); DBG1(DBG_LIB, "init RNG failed, rsa private key create failed");
free(this); free(this);
return NULL; return NULL;
} }
if (wc_InitRsaKey(&this->rsa, NULL) != 0) if (wc_InitRsaKey(&this->rsa, NULL) != 0)
{ {
DBG1(DBG_LIB, "Init RSA failed, rsa private key create failed\n"); DBG1(DBG_LIB, "init RSA failed, rsa private key create failed");
wc_FreeRng(&this->rng); wc_FreeRng(&this->rng);
free(this); free(this);
return NULL; return NULL;
@@ -422,7 +425,7 @@ static private_wolfssl_rsa_private_key_t *create_empty()
} }
/* /*
* See header. * Described in header
*/ */
wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type, wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type,
va_list args) va_list args)
@@ -450,7 +453,7 @@ wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type,
} }
this = create_empty(); this = create_empty();
if (this == NULL) if (!this)
{ {
return NULL; return NULL;
} }
@@ -463,12 +466,14 @@ wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type,
return &this->public; return &this->public;
} }
static bool wolfssl_mp_rand(mp_int* n, WC_RNG* rng, mp_int* r) /**
* Allocate a random number in the range [0, n-1]
*/
static bool wolfssl_mp_rand(mp_int *n, WC_RNG *rng, mp_int *r)
{ {
int len; int len, ret;
int ret;
/* Ensure the number has enough memory. */ /* ensure the number has enough memory. */
ret = mp_set_bit(r, mp_count_bits(n)); ret = mp_set_bit(r, mp_count_bits(n));
if (ret == 0) if (ret == 0)
{ {
@@ -479,7 +484,6 @@ static bool wolfssl_mp_rand(mp_int* n, WC_RNG* rng, mp_int* r)
{ {
ret = mp_mod(r, n, r); ret = mp_mod(r, n, r);
} }
return ret == 0; return ret == 0;
} }
@@ -492,16 +496,15 @@ static bool calculate_pq(mp_int *n, mp_int *e, mp_int *d, mp_int *p, mp_int *q,
{ {
int i, t, j; int i, t, j;
bool success = FALSE; bool success = FALSE;
mp_int* k = p; mp_int *k = p;
mp_int* r = p; mp_int *r = p;
mp_int* n1 = q; mp_int *n1 = q;
mp_int* g = t2; mp_int *g = t2;
mp_int* y = t2; mp_int *y = t2;
mp_int* x = t1; mp_int *x = t1;
/* k = (d * e) - 1 */ /* k = (d * e) - 1 */
if (mp_mul(k, d, e) != 0) if (mp_mul(d, e, k) != 0)
{ {
goto error; goto error;
} }
@@ -515,7 +518,7 @@ static bool calculate_pq(mp_int *n, mp_int *e, mp_int *d, mp_int *p, mp_int *q,
goto error; goto error;
} }
/* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
if (mp_copy(r, k) != 0) if (mp_copy(k, r) != 0)
{ {
goto error; goto error;
} }
@@ -562,7 +565,7 @@ static bool calculate_pq(mp_int *n, mp_int *e, mp_int *d, mp_int *p, mp_int *q,
break; break;
} }
/* y = x */ /* y = x */
if (mp_copy(y, x) != 0) if (mp_copy(x, y) != 0)
{ {
goto error; goto error;
} }
@@ -596,20 +599,12 @@ error:
* Calculates dp = d (mod p-1) or dq = d (mod q-1) for the Chinese remainder * Calculates dp = d (mod p-1) or dq = d (mod q-1) for the Chinese remainder
* algorithm. * algorithm.
*/ */
static int dmodpq1(mp_int *d, mp_int *pq, mp_int *res) static bool dmodpq1(mp_int *d, mp_int *pq, mp_int *res)
{ {
/* p|q - 1 */ /* p|q - 1
if (mp_sub_d(pq, 1, res) != 0) * d (mod p|q -1) */
{ return mp_sub_d(pq, 1, res) == 0 &&
return FALSE; mp_mod(d, res, res) == 0;
}
/* d (mod p|q -1) */
if (mp_mod(d, res, res) != 0)
{
return FALSE;
}
return TRUE;
} }
/** /**
@@ -622,7 +617,7 @@ static int qinv(mp_int *q, mp_int *p, mp_int *res)
} }
/* /*
* See header * Described in header
*/ */
wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type, wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type,
va_list args) va_list args)
@@ -673,7 +668,7 @@ wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type,
} }
this = create_empty(); this = create_empty();
if (this == NULL) if (!this)
{ {
return NULL; return NULL;
} }
@@ -716,7 +711,6 @@ wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type,
&this->rsa.p, &this->rsa.q, &this->rsa.dP, &this->rsa.p, &this->rsa.q, &this->rsa.dP,
&this->rsa.dQ, &this->rng)) &this->rsa.dQ, &this->rng))
{ {
DBG1(DBG_LIB, "calculate pq failed, rsa private key load failed\n");
goto error; goto error;
} }
if (exp1.ptr) if (exp1.ptr)
@@ -27,21 +27,23 @@
#include "wolfssl_rsa_public_key.h" #include "wolfssl_rsa_public_key.h"
#include "wolfssl_util.h" #include "wolfssl_util.h"
#include <crypto/hashers/hasher.h>
#include <utils/debug.h> #include <utils/debug.h>
#include <asn1/asn1.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/signature_params.h> #include <credentials/keys/signature_params.h>
#include <wolfssl/wolfcrypt/rsa.h> #include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/asn.h>
typedef struct private_wolfssl_rsa_public_key_t private_wolfssl_rsa_public_key_t; typedef struct private_wolfssl_rsa_public_key_t private_wolfssl_rsa_public_key_t;
/** /**
* Private data structure with signing context. * Private data
*/ */
struct private_wolfssl_rsa_public_key_t { struct private_wolfssl_rsa_public_key_t {
/** /**
* Public interface for this signer. * Public interface
*/ */
wolfssl_rsa_public_key_t public; wolfssl_rsa_public_key_t public;
@@ -56,12 +58,11 @@ struct private_wolfssl_rsa_public_key_t {
WC_RNG rng; WC_RNG rng;
/** /**
* reference counter * Reference counter
*/ */
refcount_t ref; refcount_t ref;
}; };
/** /**
* Verify RSA signature * Verify RSA signature
*/ */
@@ -70,7 +71,7 @@ static bool verify_signature(private_wolfssl_rsa_public_key_t *this,
{ {
bool success = FALSE; bool success = FALSE;
int len = wc_RsaEncryptSize(&this->rsa); int len = wc_RsaEncryptSize(&this->rsa);
u_char *buf; chunk_t padded;
u_char *p; u_char *p;
if (signature.len > len) if (signature.len > len)
@@ -78,17 +79,13 @@ static bool verify_signature(private_wolfssl_rsa_public_key_t *this,
signature = chunk_skip(signature, signature.len - len); signature = chunk_skip(signature, signature.len - len);
} }
buf = malloc(len); padded = chunk_copy_pad(chunk_alloca(len), signature, 0x00);
memcpy(buf + len - signature.len, signature.ptr, signature.len);
memset(buf, 0, len - signature.len);
len = wc_RsaSSL_VerifyInline(buf, len, &p, &this->rsa); len = wc_RsaSSL_VerifyInline(padded.ptr, len, &p, &this->rsa);
if (len > 0) if (len > 0)
{ {
success = chunk_equals_const(data, chunk_create(p, len)); success = chunk_equals_const(data, chunk_create(p, len));
} }
free(buf);
return success; return success;
} }
@@ -99,24 +96,23 @@ static bool verify_emsa_pkcs1_signature(private_wolfssl_rsa_public_key_t *this,
enum wc_HashType hash, chunk_t data, enum wc_HashType hash, chunk_t data,
chunk_t signature) chunk_t signature)
{ {
chunk_t dgst, digestInfo;
bool success = FALSE; bool success = FALSE;
chunk_t dgst = chunk_empty, encDgst;
int len; int len;
encDgst = chunk_alloc(wc_HashGetDigestSize(hash) + 20);
if (wolfssl_hash_chunk(hash, data, &dgst)) if (wolfssl_hash_chunk(hash, data, &dgst))
{ {
len = wc_EncodeSignature(encDgst.ptr, dgst.ptr, dgst.len, digestInfo = chunk_alloc(MAX_DER_DIGEST_SZ);
len = wc_EncodeSignature(digestInfo.ptr, dgst.ptr, dgst.len,
wc_HashGetOID(hash)); wc_HashGetOID(hash));
if (len > 0) if (len > 0)
{ {
encDgst.len = len; digestInfo.len = len;
success = verify_signature(this, encDgst, signature); success = verify_signature(this, digestInfo, signature);
} }
chunk_free(&digestInfo);
chunk_free(&dgst);
} }
chunk_free(&encDgst);
chunk_free(&dgst);
return success; return success;
} }
@@ -128,13 +124,11 @@ static bool verify_emsa_pss_signature(private_wolfssl_rsa_public_key_t *this,
rsa_pss_params_t *params, chunk_t data, rsa_pss_params_t *params, chunk_t data,
chunk_t signature) chunk_t signature)
{ {
chunk_t dgst = chunk_empty; chunk_t dgst, padded;
enum wc_HashType hash; enum wc_HashType hash;
int mgf;
bool success = FALSE;
int len = 0;
u_char *buf = NULL;
u_char *p; u_char *p;
int mgf, len = 0;
bool success = FALSE;
if (!wolfssl_hash2type(params->hash, &hash)) if (!wolfssl_hash2type(params->hash, &hash))
{ {
@@ -144,34 +138,25 @@ static bool verify_emsa_pss_signature(private_wolfssl_rsa_public_key_t *this,
{ {
return FALSE; return FALSE;
} }
if (!wolfssl_hash_chunk(hash, data, &dgst))
if (wolfssl_hash_chunk(hash, data, &dgst))
{ {
len = wc_RsaEncryptSize(&this->rsa); return FALSE;
if (signature.len > len)
{
signature = chunk_skip(signature, signature.len - len);
}
buf = malloc(len);
memcpy(buf + len - signature.len, signature.ptr, signature.len);
memset(buf, 0, len - signature.len);
len = wc_RsaPSS_VerifyInline_ex(buf, len, &p, hash, mgf,
params->salt_len, &this->rsa);
if (len > 0)
{
success = wc_RsaPSS_CheckPadding_ex(dgst.ptr, dgst.len, p, len,
hash, params->salt_len, mp_count_bits(&this->rsa.n)) == 0;
}
} }
len = wc_RsaEncryptSize(&this->rsa);
if (signature.len > len)
{
signature = chunk_skip(signature, signature.len - len);
}
padded = chunk_copy_pad(chunk_alloca(len), signature, 0x00);
len = wc_RsaPSS_VerifyInline_ex(padded.ptr, len, &p, hash, mgf,
params->salt_len, &this->rsa);
if (len > 0)
{
success = wc_RsaPSS_CheckPadding_ex(dgst.ptr, dgst.len, p, len, hash,
params->salt_len, mp_count_bits(&this->rsa.n)) == 0;
}
chunk_free(&dgst); chunk_free(&dgst);
if (buf != NULL)
{
free(buf);
}
return success; return success;
} }
#endif #endif
@@ -213,7 +198,7 @@ METHOD(public_key_t, verify, bool,
return verify_emsa_pss_signature(this, params, data, signature); return verify_emsa_pss_signature(this, params, data, signature);
#endif #endif
default: default:
DBG1(DBG_LIB, "signature scheme %N not supported in RSA", DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
signature_scheme_names, scheme); signature_scheme_names, scheme);
return FALSE; return FALSE;
} }
@@ -225,7 +210,6 @@ METHOD(public_key_t, encrypt, bool,
{ {
int padding, mgf, len; int padding, mgf, len;
enum wc_HashType hash; enum wc_HashType hash;
char *encrypted;
switch (scheme) switch (scheme)
{ {
@@ -277,17 +261,17 @@ METHOD(public_key_t, encrypt, bool,
return FALSE; return FALSE;
} }
len = wc_RsaEncryptSize(&this->rsa); len = wc_RsaEncryptSize(&this->rsa);
encrypted = malloc(len); *crypto = chunk_alloc(len);
len = wc_RsaPublicEncrypt_ex(plain.ptr, plain.len, encrypted, len, len = wc_RsaPublicEncrypt_ex(plain.ptr, plain.len, crypto->ptr, len,
&this->rsa, &this->rng, padding, hash, mgf, &this->rsa, &this->rng, padding, hash, mgf,
NULL, 0); NULL, 0);
if (len < 0) if (len < 0)
{ {
DBG1(DBG_LIB, "RSA encryption failed"); DBG1(DBG_LIB, "RSA encryption failed");
free(encrypted); chunk_free(crypto);
return FALSE; return FALSE;
} }
*crypto = chunk_create(encrypted, len); crypto->len = len;
return TRUE; return TRUE;
} }
@@ -297,6 +281,25 @@ METHOD(public_key_t, get_keysize, int,
return wc_RsaEncryptSize(&this->rsa) * 8; return wc_RsaEncryptSize(&this->rsa) * 8;
} }
/**
* Encode the given public key as ASN.1 DER with algorithm identifier
*/
bool wolfssl_rsa_encode_public(RsaKey *rsa, chunk_t *encoding)
{
int len;
len = wc_RsaEncryptSize(rsa) * 2 + 4 * MAX_SEQ_SZ + MAX_ALGO_SZ;
*encoding = chunk_alloc(len);
len = wc_RsaKeyToPublicDer(rsa, encoding->ptr, len);
if (len < 0)
{
chunk_free(encoding);
return FALSE;
}
encoding->len = len;
return TRUE;
}
/** /**
* Calculate fingerprint from a RSA key, also used in rsa private key. * Calculate fingerprint from a RSA key, also used in rsa private key.
*/ */
@@ -305,7 +308,7 @@ bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type,
{ {
hasher_t *hasher; hasher_t *hasher;
chunk_t key; chunk_t key;
int len; bool success = FALSE;
if (lib->encoding->get_cache(lib->encoding, type, rsa, fp)) if (lib->encoding->get_cache(lib->encoding, type, rsa, fp))
{ {
@@ -314,45 +317,47 @@ bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type,
switch (type) switch (type)
{ {
case KEYID_PUBKEY_SHA1: case KEYID_PUBKEY_SHA1:
len = wc_RsaEncryptSize(rsa) * 2 + 20;
key = chunk_alloc(len);
len = wc_RsaKeyToPublicDer(rsa, key.ptr, len);
break;
default:
{ {
chunk_t n = chunk_empty, e = chunk_empty; chunk_t n = chunk_empty, e = chunk_empty;
bool success = FALSE;
if (wolfssl_mp2chunk(&rsa->n, &n) && wolfssl_mp2chunk(&rsa->e, &e)) if (wolfssl_mp2chunk(&rsa->n, &n) &&
wolfssl_mp2chunk(&rsa->e, &e))
{ {
success = lib->encoding->encode(lib->encoding, type, rsa, fp, key = asn1_wrap(ASN1_SEQUENCE, "mm",
CRED_PART_RSA_MODULUS, n, asn1_integer("m", n),
CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); asn1_integer("m", e));
} }
chunk_free(&n); else
chunk_free(&e); {
return success; chunk_free(&n);
chunk_free(&e);
return FALSE;
}
break;
} }
case KEYID_PUBKEY_INFO_SHA1:
if (!wolfssl_rsa_encode_public(rsa, &key))
{
return FALSE;
}
break;
default:
return FALSE;
} }
if (len < 0)
{
chunk_free(&key);
return FALSE;
}
key.len = len;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher || !hasher->allocate_hash(hasher, key, fp)) if (!hasher || !hasher->allocate_hash(hasher, key, fp))
{ {
DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed"); DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
DESTROY_IF(hasher);
free(key.ptr);
return FALSE;
} }
free(key.ptr); else
hasher->destroy(hasher); {
lib->encoding->cache(lib->encoding, type, rsa, *fp); lib->encoding->cache(lib->encoding, type, rsa, *fp);
return TRUE; success = TRUE;
}
DESTROY_IF(hasher);
chunk_free(&key);
return success;
} }
METHOD(public_key_t, get_fingerprint, bool, METHOD(public_key_t, get_fingerprint, bool,
@@ -366,39 +371,24 @@ METHOD(public_key_t, get_encoding, bool,
private_wolfssl_rsa_public_key_t *this, cred_encoding_type_t type, private_wolfssl_rsa_public_key_t *this, cred_encoding_type_t type,
chunk_t *encoding) chunk_t *encoding)
{ {
chunk_t n = chunk_empty, e = chunk_empty;
bool success = FALSE; bool success = FALSE;
int len;
switch (type) if (type == PUBKEY_SPKI_ASN1_DER)
{ {
case PUBKEY_ASN1_DER: return wolfssl_rsa_encode_public(&this->rsa, encoding);
len = wc_RsaEncryptSize(&this->rsa) * 2 + 20;
*encoding = chunk_alloc(len);
len = wc_RsaKeyToPublicDer(&this->rsa, encoding->ptr, len);
if (len < 0)
{
DBG1(DBG_LIB, "Public Der failed, get encoding failed");
chunk_free(encoding);
return FALSE;
}
encoding->len = len;
return TRUE;
default:
{
chunk_t n = chunk_empty, e = chunk_empty;
if (wolfssl_mp2chunk(&this->rsa.n, &n) &&
wolfssl_mp2chunk(&this->rsa.e, &e))
{
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;
}
} }
if (wolfssl_mp2chunk(&this->rsa.n, &n) &&
wolfssl_mp2chunk(&this->rsa.e, &e))
{
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;
} }
METHOD(public_key_t, get_ref, public_key_t*, METHOD(public_key_t, get_ref, public_key_t*,
@@ -447,13 +437,13 @@ static private_wolfssl_rsa_public_key_t *create_empty()
if (wc_InitRng(&this->rng) != 0) if (wc_InitRng(&this->rng) != 0)
{ {
DBG1(DBG_LIB, "Init RNG, rsa public key load failed"); DBG1(DBG_LIB, "init RNG failed, rsa public key load failed");
free(this); free(this);
return NULL; return NULL;
} }
if (wc_InitRsaKey(&this->rsa, NULL) != 0) if (wc_InitRsaKey(&this->rsa, NULL) != 0)
{ {
DBG1(DBG_LIB, "Init RSA, rsa public key load failed"); DBG1(DBG_LIB, "init RSA failed, rsa public key load failed");
wc_FreeRng(&this->rng); wc_FreeRng(&this->rng);
free(this); free(this);
return NULL; return NULL;
@@ -461,8 +451,8 @@ static private_wolfssl_rsa_public_key_t *create_empty()
return this; return this;
} }
/** /*
* See header. * Described in header
*/ */
wolfssl_rsa_public_key_t *wolfssl_rsa_public_key_load(key_type_t type, wolfssl_rsa_public_key_t *wolfssl_rsa_public_key_load(key_type_t type,
va_list args) va_list args)
@@ -494,7 +484,7 @@ wolfssl_rsa_public_key_t *wolfssl_rsa_public_key_load(key_type_t type,
} }
this = create_empty(); this = create_empty();
if (this == NULL) if (!this)
{ {
return NULL; return NULL;
} }
@@ -509,7 +499,6 @@ wolfssl_rsa_public_key_t *wolfssl_rsa_public_key_load(key_type_t type,
if (wc_RsaPublicKeyDecode(blob.ptr, &idx, &this->rsa, if (wc_RsaPublicKeyDecode(blob.ptr, &idx, &this->rsa,
blob.len) != 0) blob.len) != 0)
{ {
DBG1(DBG_LIB, "Public , rsa public key load failed");
destroy(this); destroy(this);
return NULL; return NULL;
} }
@@ -37,7 +37,7 @@ typedef struct private_wolfssl_sha1_prf_t private_wolfssl_sha1_prf_t;
struct private_wolfssl_sha1_prf_t { struct private_wolfssl_sha1_prf_t {
/** /**
* Public wolfssl_sha1_prf_t interface. * Public wolfssl_sha1_prf_t interface
*/ */
wolfssl_sha1_prf_t public; wolfssl_sha1_prf_t public;
@@ -65,7 +65,6 @@ METHOD(prf_t, get_bytes, bool,
hash[3] = htonl(this->sha1.digest[3]); hash[3] = htonl(this->sha1.digest[3]);
hash[4] = htonl(this->sha1.digest[4]); hash[4] = htonl(this->sha1.digest[4]);
} }
return TRUE; return TRUE;
} }
@@ -134,18 +133,13 @@ METHOD(prf_t, destroy, void,
free(this); free(this);
} }
/** /*
* See header * Described in header
*/ */
wolfssl_sha1_prf_t *wolfssl_sha1_prf_create(pseudo_random_function_t algo) wolfssl_sha1_prf_t *wolfssl_sha1_prf_create(pseudo_random_function_t algo)
{ {
private_wolfssl_sha1_prf_t *this; private_wolfssl_sha1_prf_t *this;
if (algo != PRF_KEYED_SHA1)
{
return NULL;
}
INIT(this, INIT(this,
.public = { .public = {
.prf = { .prf = {
@@ -164,7 +158,6 @@ wolfssl_sha1_prf_t *wolfssl_sha1_prf_create(pseudo_random_function_t algo)
free(this); free(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
} }
@@ -48,7 +48,7 @@ struct wolfssl_sha1_prf_t {
* Creates a new wolfssl_sha1_prf_t. * Creates a new wolfssl_sha1_prf_t.
* *
* @param algo algorithm, must be PRF_KEYED_SHA1 * @param algo algorithm, must be PRF_KEYED_SHA1
* @return sha1_keyed_prf_tobject * @return wolfssl_sha1_prf_t object
*/ */
wolfssl_sha1_prf_t *wolfssl_sha1_prf_create(pseudo_random_function_t algo); wolfssl_sha1_prf_t *wolfssl_sha1_prf_create(pseudo_random_function_t algo);
@@ -28,8 +28,8 @@
#include <wolfssl/wolfcrypt/hash.h> #include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/rsa.h> #include <wolfssl/wolfcrypt/rsa.h>
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash) bool wolfssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash)
{ {
@@ -45,8 +45,8 @@ bool wolfssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash)
return TRUE; return TRUE;
} }
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_mp2chunk(mp_int *mp, chunk_t *chunk) bool wolfssl_mp2chunk(mp_int *mp, chunk_t *chunk)
{ {
@@ -63,8 +63,8 @@ bool wolfssl_mp2chunk(mp_int *mp, chunk_t *chunk)
return FALSE; return FALSE;
} }
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_mp_split(chunk_t chunk, mp_int *a, mp_int *b) bool wolfssl_mp_split(chunk_t chunk, mp_int *a, mp_int *b)
{ {
@@ -82,12 +82,11 @@ bool wolfssl_mp_split(chunk_t chunk, mp_int *a, mp_int *b)
{ {
ret = mp_read_unsigned_bin(b, chunk.ptr + len, len); ret = mp_read_unsigned_bin(b, chunk.ptr + len, len);
} }
return ret == 0; return ret == 0;
} }
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_mp_cat(int len, mp_int *a, mp_int *b, chunk_t *chunk) bool wolfssl_mp_cat(int len, mp_int *a, mp_int *b, chunk_t *chunk)
{ {
@@ -109,85 +108,84 @@ bool wolfssl_mp_cat(int len, mp_int *a, mp_int *b, chunk_t *chunk)
memset(chunk->ptr + len, 0, len - sz); memset(chunk->ptr + len, 0, len - sz);
ret = mp_to_unsigned_bin(b, chunk->ptr + 2 * len - sz); ret = mp_to_unsigned_bin(b, chunk->ptr + 2 * len - sz);
} }
return ret == 0; return ret == 0;
} }
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_hash2type(hash_algorithm_t hash, enum wc_HashType *type) bool wolfssl_hash2type(hash_algorithm_t hash, enum wc_HashType *type)
{ {
switch (hash) switch (hash)
{ {
#ifndef NO_MD5 #ifndef NO_MD5
case HASH_MD5: case HASH_MD5:
*type = WC_HASH_TYPE_MD5; *type = WC_HASH_TYPE_MD5;
break; break;
#endif #endif
#ifndef NO_SHA #ifndef NO_SHA
case HASH_SHA1: case HASH_SHA1:
*type = WC_HASH_TYPE_SHA; *type = WC_HASH_TYPE_SHA;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA224 #ifdef WOLFSSL_SHA224
case HASH_SHA224: case HASH_SHA224:
*type = WC_HASH_TYPE_SHA224; *type = WC_HASH_TYPE_SHA224;
break; break;
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case HASH_SHA256: case HASH_SHA256:
*type = WC_HASH_TYPE_SHA256; *type = WC_HASH_TYPE_SHA256;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case HASH_SHA384: case HASH_SHA384:
*type = WC_HASH_TYPE_SHA384; *type = WC_HASH_TYPE_SHA384;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case HASH_SHA512: case HASH_SHA512:
*type = WC_HASH_TYPE_SHA512; *type = WC_HASH_TYPE_SHA512;
break; break;
#endif #endif
default: default:
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
/** /*
* Described in header. * Described in header
*/ */
bool wolfssl_hash2mgf1(hash_algorithm_t hash, int *mgf1) bool wolfssl_hash2mgf1(hash_algorithm_t hash, int *mgf1)
{ {
switch (hash) switch (hash)
{ {
#ifndef NO_SHA #ifndef NO_SHA
case HASH_SHA1: case HASH_SHA1:
*mgf1 = WC_MGF1SHA1; *mgf1 = WC_MGF1SHA1;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA224 #ifdef WOLFSSL_SHA224
case HASH_SHA224: case HASH_SHA224:
*mgf1 = WC_MGF1SHA224; *mgf1 = WC_MGF1SHA224;
break; break;
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case HASH_SHA256: case HASH_SHA256:
*mgf1 = WC_MGF1SHA256; *mgf1 = WC_MGF1SHA256;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
case HASH_SHA384: case HASH_SHA384:
*mgf1 = WC_MGF1SHA384; *mgf1 = WC_MGF1SHA384;
break; break;
#endif #endif
#ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA512
case HASH_SHA512: case HASH_SHA512:
*mgf1 = WC_MGF1SHA512; *mgf1 = WC_MGF1SHA512;
break; break;
#endif #endif
default: default:
return FALSE; return FALSE;
} }
@@ -56,11 +56,6 @@ struct private_diffie_hellman_t {
* Shared secret * Shared secret
*/ */
chunk_t shared_secret; chunk_t shared_secret;
/**
* True if shared secret is computed
*/
bool computed;
}; };
/** /**
@@ -69,8 +64,8 @@ struct private_diffie_hellman_t {
static bool compute_shared_key(private_diffie_hellman_t *this, static bool compute_shared_key(private_diffie_hellman_t *this,
curve25519_key *pub, chunk_t *shared_secret) curve25519_key *pub, chunk_t *shared_secret)
{ {
int ret;
word32 len = CURVE25519_KEYSIZE; word32 len = CURVE25519_KEYSIZE;
int ret;
*shared_secret = chunk_alloc(len); *shared_secret = chunk_alloc(len);
ret = wc_curve25519_shared_secret_ex(&this->key, pub, shared_secret->ptr, ret = wc_curve25519_shared_secret_ex(&this->key, pub, shared_secret->ptr,
@@ -81,8 +76,8 @@ static bool compute_shared_key(private_diffie_hellman_t *this,
METHOD(diffie_hellman_t, set_other_public_value, bool, METHOD(diffie_hellman_t, set_other_public_value, bool,
private_diffie_hellman_t *this, chunk_t value) private_diffie_hellman_t *this, chunk_t value)
{ {
int ret;
curve25519_key pub; curve25519_key pub;
int ret;
if (!diffie_hellman_verify_value(this->group, value)) if (!diffie_hellman_verify_value(this->group, value))
{ {
@@ -90,7 +85,7 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
} }
ret = wc_curve25519_init(&pub); ret = wc_curve25519_init(&pub);
if (ret < 0) if (ret != 0)
{ {
DBG1(DBG_LIB, "%N public key initialization failed", DBG1(DBG_LIB, "%N public key initialization failed",
diffie_hellman_group_names, this->group); diffie_hellman_group_names, this->group);
@@ -112,10 +107,10 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
{ {
DBG1(DBG_LIB, "%N shared secret computation failed", DBG1(DBG_LIB, "%N shared secret computation failed",
diffie_hellman_group_names, this->group); diffie_hellman_group_names, this->group);
chunk_clear(&this->shared_secret);
wc_curve25519_free(&pub); wc_curve25519_free(&pub);
return FALSE; return FALSE;
} }
this->computed = TRUE;
wc_curve25519_free(&pub); wc_curve25519_free(&pub);
return TRUE; return TRUE;
} }
@@ -138,13 +133,13 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
METHOD(diffie_hellman_t, set_private_value, bool, METHOD(diffie_hellman_t, set_private_value, bool,
private_diffie_hellman_t *this, chunk_t value) private_diffie_hellman_t *this, chunk_t value)
{ {
int ret;
unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
curve25519_key pub; curve25519_key pub;
int len; u_char basepoint[CURVE25519_KEYSIZE] = {9};
word32 len = CURVE25519_KEYSIZE;
int ret;
ret = wc_curve25519_init(&pub); ret = wc_curve25519_init(&pub);
/* Create base point for calculating public key */ /* create base point for calculating public key */
if (ret == 0) if (ret == 0)
{ {
ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE, ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE,
@@ -157,22 +152,16 @@ METHOD(diffie_hellman_t, set_private_value, bool,
} }
if (ret == 0) if (ret == 0)
{ {
len = CURVE25519_KEYSIZE;
ret = wc_curve25519_shared_secret_ex(&this->key, &pub, ret = wc_curve25519_shared_secret_ex(&this->key, &pub,
this->key.p.point, &len, EC25519_LITTLE_ENDIAN); this->key.p.point, &len, EC25519_LITTLE_ENDIAN);
if (ret > 0)
{
ret = 0;
}
} }
return ret == 0; return ret == 0;
} }
METHOD(diffie_hellman_t, get_shared_secret, bool, METHOD(diffie_hellman_t, get_shared_secret, bool,
private_diffie_hellman_t *this, chunk_t *secret) private_diffie_hellman_t *this, chunk_t *secret)
{ {
if (!this->computed) if (!this->shared_secret.len)
{ {
return FALSE; return FALSE;
} }
@@ -203,14 +192,6 @@ diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
WC_RNG rng; WC_RNG rng;
int ret; int ret;
switch (group)
{
case CURVE_25519:
break;
default:
return NULL;
}
INIT(this, INIT(this,
.public = { .public = {
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
@@ -225,23 +206,23 @@ diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
if (wc_curve25519_init(&this->key) != 0) if (wc_curve25519_init(&this->key) != 0)
{ {
DBG1(DBG_LIB, "Initializing key failed"); DBG1(DBG_LIB, "initializing key failed");
free(this); free(this);
return NULL; return NULL;
} }
if (wc_InitRng(&rng) != 0) if (wc_InitRng(&rng) != 0)
{ {
DBG1(DBG_LIB, "Initializing a random number generator failed"); DBG1(DBG_LIB, "initializing a random number generator failed");
free(this); destroy(this);
return NULL; return NULL;
} }
ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &this->key); ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &this->key);
wc_FreeRng(&rng); wc_FreeRng(&rng);
if (ret != 0) if (ret != 0)
{ {
DBG1(DBG_LIB, "Making a key failed"); DBG1(DBG_LIB, "making a key failed");
free(this); destroy(this);
return NULL; return NULL;
} }
return &this->public; return &this->public;
@@ -41,4 +41,3 @@
diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group); diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group);
#endif /** WOLFSSL_X_DIFFIE_HELLMAN_H_ @}*/ #endif /** WOLFSSL_X_DIFFIE_HELLMAN_H_ @}*/