Merge branch 'ikev2-kdf-modularization'

This modularizes the IKEv2 key derivation, which makes certification (e.g.
FIPS) easier because it allows the two steps (PRF/prf+) to be implemented
by already certified third-party libraries.

For the existing third-party libraries, the two KDFs are implemented via
the respective library's HKDF implementation.  A generic implementation,
based on existing PRFs, is provided by the new kdf plugin.
This commit is contained in:
Tobias Brunner
2022-04-14 19:03:03 +02:00
1005 changed files with 3885 additions and 1638 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ include $(CLEAR_VARS)
# this is the list of plugins that are built into libstrongswan and charon
# also these plugins are loaded by default (if not changed in strongswan.conf)
strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \
pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android-dns \
pkcs1 pkcs8 pem xcbc hmac kdf kernel-netlink socket-default android-dns \
stroke eap-identity eap-mschapv2 eap-md5 eap-gtc
ifneq ($(strongswan_BUILD_SCEPCLIENT),)
+4
View File
@@ -148,6 +148,7 @@ ARG_ENABL_SET([gcrypt], [enables the libgcrypt plugin.])
ARG_DISBL_SET([gmp], [disable GNU MP (libgmp) based crypto implementation plugin.])
ARG_DISBL_SET([curve25519], [disable Curve25519 Diffie-Hellman plugin.])
ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.])
ARG_DISBL_SET([kdf], [disable KDF (prf+) implementation plugin.])
ARG_ENABL_SET([md4], [enable MD4 software implementation plugin.])
ARG_DISBL_SET([md5], [disable MD5 software implementation plugin.])
ARG_ENABL_SET([mgf1], [enable the MGF1 software implementation plugin.])
@@ -1502,6 +1503,7 @@ ADD_PLUGIN([chapoly], [s charon scripts nm cmd])
ADD_PLUGIN([xcbc], [s charon nm cmd])
ADD_PLUGIN([cmac], [s charon nm cmd])
ADD_PLUGIN([hmac], [s charon pki scripts nm cmd])
ADD_PLUGIN([kdf], [s charon pki scripts nm cmd])
ADD_PLUGIN([ctr], [s charon scripts nm cmd])
ADD_PLUGIN([ccm], [s charon scripts nm cmd])
ADD_PLUGIN([gcm], [s charon scripts nm cmd])
@@ -1656,6 +1658,7 @@ AM_CONDITIONAL(USE_DNSKEY, test x$dnskey = xtrue)
AM_CONDITIONAL(USE_SSHKEY, test x$sshkey = xtrue)
AM_CONDITIONAL(USE_PEM, test x$pem = xtrue)
AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue)
AM_CONDITIONAL(USE_KDF, test x$kdf = xtrue)
AM_CONDITIONAL(USE_CMAC, test x$cmac = xtrue)
AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue)
AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue)
@@ -1921,6 +1924,7 @@ AC_CONFIG_FILES([
src/libstrongswan/plugins/random/Makefile
src/libstrongswan/plugins/nonce/Makefile
src/libstrongswan/plugins/hmac/Makefile
src/libstrongswan/plugins/kdf/Makefile
src/libstrongswan/plugins/xcbc/Makefile
src/libstrongswan/plugins/x509/Makefile
src/libstrongswan/plugins/revocation/Makefile
+7
View File
@@ -200,10 +200,17 @@ win*)
if test "$APPVEYOR" != "True"; then
TARGET=
else
case "$IMG" in
2015|2017)
# old OpenSSL versions don't provide HKDF
CONFIG="$CONFIG --enable-kdf"
;;
esac
CONFIG="$CONFIG --enable-openssl"
CFLAGS="$CFLAGS -I$OPENSSL_DIR/include"
LDFLAGS="-L$OPENSSL_DIR"
export LDFLAGS
fi
CFLAGS="$CFLAGS -mno-ms-bitfields"
DEPS="gcc-mingw-w64-base"
@@ -6,7 +6,7 @@ include $(CLEAR_VARS)
strongswan_USE_BYOD := true
strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \
chapoly curve25519 pkcs1 pkcs8 pem xcbc hmac socket-default revocation \
chapoly curve25519 pkcs1 pkcs8 pem xcbc hmac kdf socket-default revocation \
eap-identity eap-mschapv2 eap-md5 eap-gtc eap-tls x509
ifneq ($(strongswan_USE_BYOD),)
-1
View File
@@ -50,7 +50,6 @@ typedef struct kernel_interface_t kernel_interface_t;
typedef enum kernel_feature_t kernel_feature_t;
#include <networking/host.h>
#include <crypto/prf_plus.h>
#include <kernel/kernel_listener.h>
#include <kernel/kernel_ipsec.h>
@@ -849,6 +849,7 @@ static void list_algs(FILE *out)
hash_algorithm_t hash;
pseudo_random_function_t prf;
ext_out_function_t xof;
key_derivation_function_t kdf;
drbg_type_t drbg;
diffie_hellman_group_t group;
rng_quality_t quality;
@@ -905,6 +906,14 @@ static void list_algs(FILE *out)
print_alg(out, &len, ext_out_function_names, xof, plugin_name);
}
enumerator->destroy(enumerator);
fprintf(out, "\n kdf: ");
len = 13;
enumerator = lib->crypto->create_kdf_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &kdf, &plugin_name))
{
print_alg(out, &len, key_derivation_function_names, kdf, plugin_name);
}
enumerator->destroy(enumerator);
fprintf(out, "\n drbg: ");
len = 13;
enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
+10
View File
@@ -1303,6 +1303,7 @@ CALLBACK(get_algorithms, vici_message_t*,
hash_algorithm_t hash;
pseudo_random_function_t prf;
ext_out_function_t xof;
key_derivation_function_t kdf;
drbg_type_t drbg;
diffie_hellman_group_t group;
rng_quality_t quality;
@@ -1364,6 +1365,15 @@ CALLBACK(get_algorithms, vici_message_t*,
enumerator->destroy(enumerator);
b->end_section(b);
b->begin_section(b, "kdf");
enumerator = lib->crypto->create_kdf_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &kdf, &plugin_name))
{
add_algorithm(b, key_derivation_function_names, kdf, plugin_name);
}
enumerator->destroy(enumerator);
b->end_section(b);
b->begin_section(b, "drbg");
enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &drbg, &plugin_name))
-1
View File
@@ -29,7 +29,6 @@ typedef struct child_sa_t child_sa_t;
typedef struct child_sa_create_t child_sa_create_t;
#include <library.h>
#include <crypto/prf_plus.h>
#include <encoding/payloads/proposal_substructure.h>
#include <crypto/proposal/proposal.h>
#include <config/child_cfg.h>
+34 -13
View File
@@ -507,6 +507,36 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
this->aead->get_block_size(this->aead));
}
/**
* Derive key material for CHILD_SAs according to section 5.5. in RFC 2409.
*/
static bool derive_child_keymat(private_keymat_v1_t *this, chunk_t seed,
uint16_t enc_size, chunk_t *encr,
uint16_t int_size, chunk_t *integ)
{
size_t block_size, i;
chunk_t keymat, prev = chunk_empty;
block_size = this->prf->get_block_size(this->prf);
keymat = chunk_alloc(round_up(enc_size + int_size, block_size));
keymat.len = enc_size + int_size;
for (i = 0; i < keymat.len; i += block_size)
{
if (!this->prf->get_bytes(this->prf, prev, NULL) ||
!this->prf->get_bytes(this->prf, seed, keymat.ptr + i))
{
chunk_clear(&keymat);
return FALSE;
}
prev = chunk_create(keymat.ptr + i, block_size);
}
chunk_split(keymat, "aa", enc_size, encr, int_size, integ);
chunk_clear(&keymat);
return TRUE;
}
METHOD(keymat_v1_t, derive_child_keys, bool,
private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
uint32_t spi_i, uint32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
@@ -514,8 +544,7 @@ METHOD(keymat_v1_t, derive_child_keys, bool,
{
uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
uint8_t protocol;
prf_plus_t *prf_plus;
chunk_t seed, secret = chunk_empty;
chunk_t seed = chunk_empty, secret = chunk_empty;
bool success = FALSE;
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
@@ -599,11 +628,7 @@ METHOD(keymat_v1_t, derive_child_keys, bool,
seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
chunk_from_thing(spi_r), nonce_i, nonce_r);
DBG4(DBG_CHD, "initiator SA seed %B", &seed);
prf_plus = prf_plus_create(this->prf, FALSE, seed);
if (!prf_plus ||
!prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
!prf_plus->allocate_bytes(prf_plus, int_size, integ_i))
if (!derive_child_keymat(this, seed, enc_size, encr_i, int_size, integ_i))
{
goto failure;
}
@@ -611,11 +636,7 @@ METHOD(keymat_v1_t, derive_child_keys, bool,
seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
chunk_from_thing(spi_i), nonce_i, nonce_r);
DBG4(DBG_CHD, "responder SA seed %B", &seed);
prf_plus->destroy(prf_plus);
prf_plus = prf_plus_create(this->prf, FALSE, seed);
if (!prf_plus ||
!prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
!prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
if (!derive_child_keymat(this, seed, enc_size, encr_r, int_size, integ_r))
{
goto failure;
}
@@ -640,7 +661,7 @@ failure:
chunk_clear(encr_r);
chunk_clear(integ_r);
}
DESTROY_IF(prf_plus);
memwipe(seed.ptr, seed.len);
chunk_clear(&secret);
return success;
+217 -278
View File
@@ -17,7 +17,6 @@
#include "keymat_v2.h"
#include <daemon.h>
#include <crypto/prf_plus.h>
#include <crypto/hashers/hash_algorithm_set.h>
typedef struct private_keymat_v2_t private_keymat_v2_t;
@@ -97,13 +96,12 @@ METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
}
/**
* Derive IKE keys for a combined AEAD algorithm
* Create aead_t objects for a combined-mode AEAD algorithm, sets the length of
* sk_ei and sk_er
*/
static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
uint16_t key_size, prf_plus_t *prf_plus,
chunk_t *sk_ei, chunk_t *sk_er)
static bool create_ike_aead(private_keymat_v2_t *this, uint16_t alg,
uint16_t key_size, chunk_t *sk_ei, chunk_t *sk_er)
{
aead_t *aead_i, *aead_r;
u_int salt_size;
switch (alg)
@@ -131,201 +129,177 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
return FALSE;
}
/* SK_ei/SK_er used for encryption */
aead_i = lib->crypto->create_aead(lib->crypto, alg, key_size / 8, salt_size);
aead_r = lib->crypto->create_aead(lib->crypto, alg, key_size / 8, salt_size);
if (aead_i == NULL || aead_r == NULL)
this->aead_in = lib->crypto->create_aead(lib->crypto, alg, key_size / 8,
salt_size);
this->aead_out = lib->crypto->create_aead(lib->crypto, alg, key_size / 8,
salt_size);
if (!this->aead_in || !this->aead_out)
{
DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
transform_type_names, ENCRYPTION_ALGORITHM,
encryption_algorithm_names, alg, key_size);
goto failure;
return FALSE;
}
key_size = aead_i->get_key_size(aead_i);
if (key_size != aead_r->get_key_size(aead_r))
sk_ei->len = this->aead_in->get_key_size(this->aead_in);
sk_er->len = this->aead_out->get_key_size(this->aead_out);
if (sk_ei->len != sk_er->len)
{
goto failure;
return FALSE;
}
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_ei))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_ei secret %B", sk_ei);
if (!aead_i->set_key(aead_i, *sk_ei))
{
goto failure;
}
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_er))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_er secret %B", sk_er);
if (!aead_r->set_key(aead_r, *sk_er))
{
goto failure;
}
if (this->initiator)
{
this->aead_in = aead_r;
this->aead_out = aead_i;
}
else
{
this->aead_in = aead_i;
this->aead_out = aead_r;
}
aead_i = aead_r = NULL;
failure:
DESTROY_IF(aead_i);
DESTROY_IF(aead_r);
return this->aead_in && this->aead_out;
return TRUE;
}
/**
* Derive IKE keys for traditional encryption and MAC algorithms
* Create aead_t objects for traditional encryption and MAC algorithms, sets the
* length of key chunks
*/
static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
uint16_t enc_size, uint16_t int_alg, prf_plus_t *prf_plus,
chunk_t *sk_ai, chunk_t *sk_ar, chunk_t *sk_ei,
chunk_t *sk_er)
static bool create_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
uint16_t enc_size, uint16_t int_alg, chunk_t *sk_ai,
chunk_t *sk_ar, chunk_t *sk_ei, chunk_t *sk_er)
{
crypter_t *crypter_i = NULL, *crypter_r = NULL;
signer_t *signer_i, *signer_r;
iv_gen_t *ivg_i, *ivg_r;
size_t key_size;
crypter_t *crypter_i = NULL, *crypter_o = NULL;
signer_t *signer_i, *signer_o;
iv_gen_t *ivg_i, *ivg_o;
signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
if (signer_i == NULL || signer_r == NULL)
signer_o = lib->crypto->create_signer(lib->crypto, int_alg);
if (!signer_i || !signer_o)
{
DBG1(DBG_IKE, "%N %N not supported!",
transform_type_names, INTEGRITY_ALGORITHM,
integrity_algorithm_names, int_alg);
goto failure;
}
if (crypter_i == NULL || crypter_r == NULL)
crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
crypter_o = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
if (!crypter_i || !crypter_o)
{
DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
transform_type_names, ENCRYPTION_ALGORITHM,
encryption_algorithm_names, enc_alg, enc_size);
goto failure;
}
/* SK_ai/SK_ar used for integrity protection */
key_size = signer_i->get_key_size(signer_i);
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_ai))
sk_ai->len = signer_i->get_key_size(signer_i);
sk_ar->len = signer_o->get_key_size(signer_o);
if (sk_ai->len != sk_ar->len)
{
goto failure;
}
DBG4(DBG_IKE, "Sk_ai secret %B", sk_ai);
if (!signer_i->set_key(signer_i, *sk_ai))
sk_ei->len = crypter_i->get_key_size(crypter_i);
sk_er->len = crypter_o->get_key_size(crypter_o);
if (sk_ei->len != sk_er->len)
{
goto failure;
}
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_ar))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_ar secret %B", sk_ar);
if (!signer_r->set_key(signer_r, *sk_ar))
{
goto failure;
}
/* SK_ei/SK_er used for encryption */
key_size = crypter_i->get_key_size(crypter_i);
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_ei))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_ei secret %B", sk_ei);
if (!crypter_i->set_key(crypter_i, *sk_ei))
{
goto failure;
}
if (!prf_plus->allocate_bytes(prf_plus, key_size, sk_er))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_er secret %B", sk_er);
if (!crypter_r->set_key(crypter_r, *sk_er))
{
goto failure;
}
ivg_i = iv_gen_create_for_alg(enc_alg);
ivg_r = iv_gen_create_for_alg(enc_alg);
if (!ivg_i || !ivg_r)
ivg_o = iv_gen_create_for_alg(enc_alg);
if (!ivg_i || !ivg_o)
{
goto failure;
}
if (this->initiator)
{
this->aead_in = aead_create(crypter_r, signer_r, ivg_r);
this->aead_out = aead_create(crypter_i, signer_i, ivg_i);
}
else
{
this->aead_in = aead_create(crypter_i, signer_i, ivg_i);
this->aead_out = aead_create(crypter_r, signer_r, ivg_r);
}
signer_i = signer_r = NULL;
crypter_i = crypter_r = NULL;
this->aead_in = aead_create(crypter_i, signer_i, ivg_i);
this->aead_out = aead_create(crypter_o, signer_o, ivg_o);
signer_i = signer_o = NULL;
crypter_i = crypter_o = NULL;
failure:
DESTROY_IF(signer_i);
DESTROY_IF(signer_r);
DESTROY_IF(signer_o);
DESTROY_IF(crypter_i);
DESTROY_IF(crypter_r);
DESTROY_IF(crypter_o);
return this->aead_in && this->aead_out;
}
/**
* Set keys on AEAD objects
*/
static bool set_aead_keys(private_keymat_v2_t *this, uint16_t enc_alg,
chunk_t sk_ai, chunk_t sk_ar,
chunk_t sk_ei, chunk_t sk_er)
{
aead_t *aead_i, *aead_r;
chunk_t sk_i, sk_r;
bool success;
aead_i = this->initiator ? this->aead_out : this->aead_in;
aead_r = this->initiator ? this->aead_in : this->aead_out;
sk_i = chunk_cat("cc", sk_ai, sk_ei);
sk_r = chunk_cat("cc", sk_ar, sk_er);
success = aead_i->set_key(aead_i, sk_i) &&
aead_r->set_key(aead_r, sk_r);
chunk_clear(&sk_i);
chunk_clear(&sk_r);
return success;
}
METHOD(keymat_v2_t, derive_ike_keys, bool,
private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
pseudo_random_function_t rekey_function, chunk_t rekey_skd)
{
chunk_t skeyseed = chunk_empty, secret, full_nonce, fixed_nonce;
chunk_t prf_plus_seed, spi_i, spi_r;
chunk_t prf_plus_seed, spi_i, spi_r, keymat = chunk_empty;
chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
chunk_t sk_ai = chunk_empty, sk_ar = chunk_empty, sk_pi, sk_pr;
prf_plus_t *prf_plus = NULL;
uint16_t alg, key_size, int_alg;
prf_t *rekey_prf = NULL;
kdf_t *prf = NULL, *prf_plus = NULL;
uint16_t prf_alg, key_size, enc_alg, enc_size, int_alg;
bool success = FALSE;
spi_i = chunk_alloca(sizeof(uint64_t));
spi_r = chunk_alloca(sizeof(uint64_t));
if (!dh->get_shared_secret(dh, &secret))
/* create SA's general purpose PRF first, we may use it here */
if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &prf_alg,
NULL))
{
DBG1(DBG_IKE, "no %N selected",
transform_type_names, PSEUDO_RANDOM_FUNCTION);
return FALSE;
}
this->prf_alg = prf_alg;
this->prf = lib->crypto->create_prf(lib->crypto, this->prf_alg);
if (!this->prf)
{
DBG1(DBG_IKE, "%N %N not supported!", transform_type_names,
PSEUDO_RANDOM_FUNCTION, pseudo_random_function_names,
this->prf_alg);
return FALSE;
}
key_size = this->prf->get_key_size(this->prf);
/* create SA's AEAD instances to determine key sizes */
if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg,
&enc_size))
{
DBG1(DBG_IKE, "no %N selected", transform_type_names,
ENCRYPTION_ALGORITHM);
return FALSE;
}
if (!encryption_algorithm_is_aead(enc_alg))
{
if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg,
NULL))
{
DBG1(DBG_IKE, "no %N selected", transform_type_names,
INTEGRITY_ALGORITHM);
return FALSE;
}
if (!create_ike_traditional(this, enc_alg, enc_size, int_alg,
&sk_ai, &sk_ar, &sk_ei, &sk_er))
{
return FALSE;
}
}
else if (!create_ike_aead(this, enc_alg, enc_size, &sk_ei, &sk_er))
{
return FALSE;
}
/* Create SAs general purpose PRF first, we may use it here */
if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
if (!dh->get_shared_secret(dh, &secret))
{
DBG1(DBG_IKE, "no %N selected",
transform_type_names, PSEUDO_RANDOM_FUNCTION);
chunk_clear(&secret);
return FALSE;
}
this->prf_alg = alg;
this->prf = lib->crypto->create_prf(lib->crypto, alg);
if (this->prf == NULL)
{
DBG1(DBG_IKE, "%N %N not supported!",
transform_type_names, PSEUDO_RANDOM_FUNCTION,
pseudo_random_function_names, alg);
chunk_clear(&secret);
return FALSE;
}
DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
@@ -333,7 +307,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
full_nonce = chunk_cat("cc", nonce_i, nonce_r);
/* but the PRF may need a fixed key which only uses the first bytes of
* the nonces. */
switch (alg)
switch (prf_alg)
{
case PRF_AES128_CMAC:
/* while variable keys may be used according to RFC 4615, RFC 7296
@@ -345,161 +319,150 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
case PRF_CAMELLIA128_XCBC:
/* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
* assume fixed key length. */
key_size = this->prf->get_key_size(this->prf)/2;
nonce_i.len = min(nonce_i.len, key_size);
nonce_r.len = min(nonce_r.len, key_size);
nonce_i.len = min(nonce_i.len, key_size / 2);
nonce_r.len = min(nonce_r.len, key_size / 2);
break;
default:
/* all other algorithms use variable key length, full nonce */
break;
}
fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
*((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
*((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
/* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
*
* if we are rekeying, SKEYSEED is built on another way
*/
if (rekey_function == PRF_UNDEFINED) /* not rekeying */
if (rekey_function == PRF_UNDEFINED)
{
/* SKEYSEED = prf(Ni | Nr, g^ir) */
if (this->prf->set_key(this->prf, fixed_nonce) &&
this->prf->allocate_bytes(this->prf, secret, &skeyseed) &&
this->prf->set_key(this->prf, skeyseed))
prf = lib->crypto->create_kdf(lib->crypto, KDF_PRF, this->prf_alg);
if (!prf)
{
prf_plus = prf_plus_create(this->prf, TRUE, prf_plus_seed);
DBG1(DBG_IKE, "%N with %N not supported",
key_derivation_function_names, KDF_PRF,
pseudo_random_function_names, rekey_function);
chunk_clear(&secret);
chunk_free(&full_nonce);
chunk_free(&fixed_nonce);
return FALSE;
}
if (prf->set_param(prf, KDF_PARAM_KEY, secret) &&
prf->set_param(prf, KDF_PARAM_SALT, fixed_nonce) &&
prf->allocate_bytes(prf, 0, &skeyseed))
{
prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS,
this->prf_alg);
}
}
else
{
/* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
* use OLD SAs PRF functions for both prf_plus and prf */
rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
if (!rekey_prf)
prf = lib->crypto->create_kdf(lib->crypto, KDF_PRF, rekey_function);
if (!prf)
{
DBG1(DBG_IKE, "PRF of old SA %N not supported!",
DBG1(DBG_IKE, "%N with PRF of old SA %N not supported",
key_derivation_function_names, KDF_PRF,
pseudo_random_function_names, rekey_function);
chunk_clear(&secret);
chunk_free(&full_nonce);
chunk_free(&fixed_nonce);
chunk_clear(&prf_plus_seed);
return FALSE;
}
secret = chunk_cat("sc", secret, full_nonce);
if (rekey_prf->set_key(rekey_prf, rekey_skd) &&
rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed) &&
rekey_prf->set_key(rekey_prf, skeyseed))
if (prf->set_param(prf, KDF_PARAM_KEY, secret) &&
prf->set_param(prf, KDF_PARAM_SALT, rekey_skd) &&
prf->allocate_bytes(prf, 0, &skeyseed))
{
prf_plus = prf_plus_create(rekey_prf, TRUE, prf_plus_seed);
prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS,
rekey_function);
}
}
DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
chunk_clear(&skeyseed);
chunk_clear(&secret);
chunk_free(&full_nonce);
chunk_free(&fixed_nonce);
chunk_clear(&prf_plus_seed);
DESTROY_IF(prf);
/* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
*/
*((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
*((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
if (prf_plus &&
(!prf_plus->set_param(prf_plus, KDF_PARAM_KEY, skeyseed) ||
!prf_plus->set_param(prf_plus, KDF_PARAM_SALT, prf_plus_seed)))
{
prf_plus->destroy(prf_plus);
prf_plus = NULL;
}
chunk_clear(&skeyseed);
chunk_free(&full_nonce);
chunk_free(&prf_plus_seed);
if (!prf_plus)
{
goto failure;
}
/* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
/* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr
*
* SK_d, SK_pi and SK_pr have the size of the PRF key
*/
keymat.len = 3 * key_size + sk_ai.len + sk_ar.len + sk_ei.len + sk_er.len;
if (!prf_plus->allocate_bytes(prf_plus, keymat.len, &keymat))
{
goto failure;
}
chunk_split(keymat, "ammmmaa", key_size, &this->skd, sk_ai.len, &sk_ai,
sk_ar.len, &sk_ar, sk_ei.len, &sk_ei, sk_er.len, &sk_er,
key_size, &sk_pi, key_size, &sk_pr);
/* SK_d is used for generating CHILD_SA key mat => store for later use */
key_size = this->prf->get_key_size(this->prf);
if (!prf_plus->allocate_bytes(prf_plus, key_size, &this->skd))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
if (!encryption_algorithm_is_aead(enc_alg))
{ /* SK_ai/SK_ar used for integrity protection */
DBG4(DBG_IKE, "Sk_ai secret %B", &sk_ai);
DBG4(DBG_IKE, "Sk_ar secret %B", &sk_ar);
}
/* SK_ei/SK_er used for encryption */
DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
if (!set_aead_keys(this, enc_alg, sk_ai, sk_ar, sk_ei, sk_er))
{
DBG1(DBG_IKE, "no %N selected",
transform_type_names, ENCRYPTION_ALGORITHM);
goto failure;
}
if (encryption_algorithm_is_aead(alg))
{
if (!derive_ike_aead(this, alg, key_size, prf_plus, &sk_ei, &sk_er))
{
goto failure;
}
}
else
{
if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
&int_alg, NULL))
{
DBG1(DBG_IKE, "no %N selected",
transform_type_names, INTEGRITY_ALGORITHM);
goto failure;
}
if (!derive_ike_traditional(this, alg, key_size, int_alg, prf_plus,
&sk_ai, &sk_ar, &sk_ei, &sk_er))
{
goto failure;
}
}
/* SK_pi/SK_pr used for authentication => stored for later */
key_size = this->prf->get_key_size(this->prf);
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_pi))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_pi secret %B", &sk_pi);
if (this->initiator)
{
this->skp_build = sk_pi;
}
else
{
this->skp_verify = sk_pi;
}
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_pr))
{
goto failure;
}
DBG4(DBG_IKE, "Sk_pr secret %B", &sk_pr);
if (this->initiator)
{
this->skp_build = sk_pi;
this->skp_verify = sk_pr;
}
else
{
this->skp_build = sk_pr;
this->skp_verify = sk_pi;
}
charon->bus->ike_derived_keys(charon->bus,this->skd, sk_ai, sk_ar, sk_ei,
sk_er, sk_pi, sk_pr);
charon->bus->ike_derived_keys(charon->bus, this->skd, sk_ai, sk_ar,
sk_ei, sk_er, sk_pi, sk_pr);
success = TRUE;
failure:
chunk_clear(&sk_ai);
chunk_clear(&sk_ar);
chunk_clear(&sk_ei);
chunk_clear(&sk_er);
chunk_clear(&keymat);
DESTROY_IF(prf_plus);
DESTROY_IF(rekey_prf);
return this->skp_build.len && this->skp_verify.len;
return success;
}
/**
* Derives a key from the given key and a PRF that was initialized with a PPK
* Derives a new key from the given PPK and old key
*/
static bool derive_ppk_key(prf_t *prf, char *name, chunk_t key,
chunk_t *new_key)
static bool derive_ppk_key(private_keymat_v2_t *this, char *name, chunk_t ppk,
chunk_t key, chunk_t *new_key)
{
prf_plus_t *prf_plus;
kdf_t *prf_plus;
prf_plus = prf_plus_create(prf, TRUE, key);
prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS, this->prf_alg);
if (!prf_plus ||
!prf_plus->set_param(prf_plus, KDF_PARAM_KEY, ppk) ||
!prf_plus->set_param(prf_plus, KDF_PARAM_SALT, key) ||
!prf_plus->allocate_bytes(prf_plus, key.len, new_key))
{
DBG1(DBG_IKE, "unable to derive %s with PPK", name);
@@ -510,20 +473,6 @@ static bool derive_ppk_key(prf_t *prf, char *name, chunk_t key,
return TRUE;
}
/**
* Use the given PPK to derive a new SK_pi/r
*/
static bool derive_skp_ppk(private_keymat_v2_t *this, chunk_t ppk, chunk_t skp,
chunk_t *new_skp)
{
if (!this->prf->set_key(this->prf, ppk))
{
DBG1(DBG_IKE, "unable to set PPK in PRF");
return FALSE;
}
return derive_ppk_key(this->prf, "SK_p", skp, new_skp);
}
METHOD(keymat_v2_t, derive_ike_keys_ppk, bool,
private_keymat_v2_t *this, chunk_t ppk)
{
@@ -548,14 +497,9 @@ METHOD(keymat_v2_t, derive_ike_keys_ppk, bool,
DBG4(DBG_IKE, "derive keys using PPK %B", &ppk);
if (!this->prf->set_key(this->prf, ppk))
{
DBG1(DBG_IKE, "unable to set PPK in PRF");
return FALSE;
}
if (!derive_ppk_key(this->prf, "Sk_d", this->skd, &skd) ||
!derive_ppk_key(this->prf, "Sk_pi", *skpi, &new_skpi) ||
!derive_ppk_key(this->prf, "Sk_pr", *skpr, &new_skpr))
if (!derive_ppk_key(this, "Sk_d", ppk, this->skd, &skd) ||
!derive_ppk_key(this, "Sk_pi", ppk, *skpi, &new_skpi) ||
!derive_ppk_key(this, "Sk_pr", ppk, *skpr, &new_skpr))
{
chunk_clear(&skd);
chunk_clear(&new_skpi);
@@ -583,8 +527,8 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
chunk_t *encr_r, chunk_t *integ_r)
{
uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
chunk_t seed, secret = chunk_empty;
prf_plus_t *prf_plus;
chunk_t seed, secret = chunk_empty, keymat = chunk_empty;
kdf_t *prf_plus;
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
&enc_alg, &enc_size))
@@ -650,11 +594,6 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
int_size /= 8;
}
if (!this->prf->set_key(this->prf, this->skd))
{
return FALSE;
}
if (dh)
{
if (!dh->get_shared_secret(dh, &secret))
@@ -666,30 +605,30 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
seed = chunk_cata("scc", secret, nonce_i, nonce_r);
DBG4(DBG_CHD, "seed %B", &seed);
prf_plus = prf_plus_create(this->prf, TRUE, seed);
memwipe(seed.ptr, seed.len);
if (!prf_plus)
prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS, this->prf_alg);
if (!prf_plus ||
!prf_plus->set_param(prf_plus, KDF_PARAM_KEY, this->skd) ||
!prf_plus->set_param(prf_plus, KDF_PARAM_SALT, seed))
{
DESTROY_IF(prf_plus);
memwipe(seed.ptr, seed.len);
return FALSE;
}
memwipe(seed.ptr, seed.len);
*encr_i = *integ_i = *encr_r = *integ_r = chunk_empty;
if (!prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
!prf_plus->allocate_bytes(prf_plus, int_size, integ_i) ||
!prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
!prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
keymat.len = 2 * enc_size + 2 * int_size;
if (!prf_plus->allocate_bytes(prf_plus, keymat.len, &keymat))
{
chunk_free(encr_i);
chunk_free(integ_i);
chunk_free(encr_r);
chunk_free(integ_r);
prf_plus->destroy(prf_plus);
return FALSE;
}
prf_plus->destroy(prf_plus);
chunk_split(keymat, "aaaa", enc_size, encr_i, int_size, integ_i,
enc_size, encr_r, int_size, integ_r);
chunk_clear(&keymat);
if (enc_size)
{
DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
@@ -729,7 +668,7 @@ METHOD(keymat_v2_t, get_auth_octets, bool,
if (ppk.ptr)
{
DBG4(DBG_IKE, "PPK %B", &ppk);
if (!derive_skp_ppk(this, ppk, skp, &skp_ppk))
if (!derive_ppk_key(this, "SK_p", ppk, skp, &skp_ppk))
{
return FALSE;
}
@@ -775,7 +714,7 @@ METHOD(keymat_v2_t, get_psk_sig, bool,
secret = verify ? this->skp_verify : this->skp_build;
if (ppk.ptr)
{
if (!derive_skp_ppk(this, ppk, secret, &skp_ppk))
if (!derive_ppk_key(this, "SK_p", ppk, secret, &skp_ppk))
{
return FALSE;
}
+9 -2
View File
@@ -18,6 +18,13 @@
typedef struct private_diffie_hellman_t private_diffie_hellman_t;
/** Mock DH public and shared key */
static chunk_t mock_key = chunk_from_chars(
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08);
/**
* Private data
*/
@@ -37,7 +44,7 @@ struct private_diffie_hellman_t {
METHOD(diffie_hellman_t, get_my_public_value, bool,
private_diffie_hellman_t *this, chunk_t *value)
{
*value = chunk_empty;
*value = chunk_clone(mock_key);
return TRUE;
}
@@ -50,7 +57,7 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
METHOD(diffie_hellman_t, get_shared_secret, bool,
private_diffie_hellman_t *this, chunk_t *secret)
{
*secret = chunk_empty;
*secret = chunk_clone(mock_key);
return TRUE;
}
+4 -2
View File
@@ -13,11 +13,11 @@ crypto/hashers/hash_algorithm_set.c crypto/proposal/proposal.c \
crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
crypto/rngs/rng.c crypto/rngs/rng_tester.c \
crypto/prf_plus.c crypto/signers/signer.c \
crypto/signers/signer.c \
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
crypto/iv/iv_gen_null.c \
crypto/iv/iv_gen_null.c crypto/kdfs/kdf.c \
crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
credentials/credential_factory.c credentials/builder.c \
credentials/cred_encoding.c credentials/keys/private_key.c \
@@ -92,6 +92,8 @@ endif
LOCAL_SRC_FILES += $(call add_plugin, hmac)
LOCAL_SRC_FILES += $(call add_plugin, kdf)
LOCAL_SRC_FILES += $(call add_plugin, md4)
LOCAL_SRC_FILES += $(call add_plugin, md5)
+11 -3
View File
@@ -11,11 +11,11 @@ crypto/hashers/hash_algorithm_set.c crypto/proposal/proposal.c \
crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
crypto/rngs/rng.c crypto/rngs/rng_tester.c \
crypto/prf_plus.c crypto/signers/signer.c \
crypto/signers/signer.c \
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
crypto/iv/iv_gen_null.c \
crypto/iv/iv_gen_null.c crypto/kdfs/kdf.c \
crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
credentials/credential_factory.c credentials/builder.c \
credentials/cred_encoding.c credentials/keys/private_key.c \
@@ -78,11 +78,12 @@ crypto/hashers/hash_algorithm_set.h crypto/mac.h crypto/proposal/proposal.h \
crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
crypto/rngs/rng.h crypto/rngs/rng_tester.h \
crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/nonce_gen.h \
crypto/prf_plus.h crypto/signers/signer.h crypto/signers/mac_signer.h \
crypto/signers/signer.h crypto/signers/mac_signer.h \
crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
crypto/aead.h crypto/transform.h crypto/pkcs5.h crypto/iv/iv_gen.h \
crypto/iv/iv_gen_rand.h crypto/iv/iv_gen_seq.h crypto/iv/iv_gen_null.h \
crypto/xofs/xof.h crypto/xofs/xof_bitspender.h crypto/xofs/mgf1.h \
crypto/kdfs/kdf.h \
credentials/credential_factory.h credentials/builder.h \
credentials/cred_encoding.h credentials/keys/private_key.h \
credentials/keys/public_key.h credentials/keys/shared_key.h \
@@ -394,6 +395,13 @@ if MONOLITHIC
endif
endif
if USE_KDF
SUBDIRS += plugins/kdf
if MONOLITHIC
libstrongswan_la_LIBADD += plugins/kdf/libstrongswan-kdf.la
endif
endif
if USE_CMAC
SUBDIRS += plugins/cmac
if MONOLITHIC
+133 -11
View File
@@ -23,8 +23,6 @@
#include <crypto/crypto_tester.h>
#include <utils/test.h>
const char *default_plugin_name = "default";
typedef struct entry_t entry_t;
struct entry_t {
@@ -53,6 +51,7 @@ struct entry_t {
hasher_constructor_t create_hasher;
prf_constructor_t create_prf;
xof_constructor_t create_xof;
kdf_constructor_t create_kdf;
drbg_constructor_t create_drbg;
rng_constructor_t create_rng;
nonce_gen_constructor_t create_nonce_gen;
@@ -103,6 +102,11 @@ struct private_crypto_factory_t {
*/
linked_list_t *xofs;
/**
* registered kdfs, as entry_t
*/
linked_list_t *kdfs;
/**
* registered drbgs, as entry_t
*/
@@ -171,7 +175,7 @@ METHOD(crypto_factory_t, create_crypter, crypter_t*,
if (this->test_on_create &&
!this->tester->test_crypter(this->tester, algo, key_size,
entry->create_crypter, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -204,7 +208,7 @@ METHOD(crypto_factory_t, create_aead, aead_t*,
if (this->test_on_create &&
!this->tester->test_aead(this->tester, algo, key_size,
salt_size, entry->create_aead, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -236,7 +240,7 @@ METHOD(crypto_factory_t, create_signer, signer_t*,
if (this->test_on_create &&
!this->tester->test_signer(this->tester, algo,
entry->create_signer, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -268,7 +272,7 @@ METHOD(crypto_factory_t, create_hasher, hasher_t*,
if (this->test_on_create &&
!this->tester->test_hasher(this->tester, algo,
entry->create_hasher, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -300,7 +304,7 @@ METHOD(crypto_factory_t, create_prf, prf_t*,
if (this->test_on_create &&
!this->tester->test_prf(this->tester, algo,
entry->create_prf, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -332,7 +336,7 @@ METHOD(crypto_factory_t, create_xof, xof_t*,
if (this->test_on_create &&
!this->tester->test_xof(this->tester, algo,
entry->create_xof, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -348,6 +352,48 @@ METHOD(crypto_factory_t, create_xof, xof_t*,
return xof;
}
METHOD(crypto_factory_t, create_kdf, kdf_t*,
private_crypto_factory_t *this, key_derivation_function_t algo, ...)
{
enumerator_t *enumerator;
entry_t *entry;
va_list args;
kdf_t *kdf = NULL;
this->lock->read_lock(this->lock);
enumerator = this->kdfs->create_enumerator(this->kdfs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == algo)
{
if (this->test_on_create)
{
kdf_test_args_t test_args = {};
va_start(test_args.args, algo);
if (!this->tester->test_kdf(this->tester, algo,
entry->create_kdf, &test_args, NULL,
entry->plugin_name))
{
va_end(test_args.args);
continue;
}
va_end(test_args.args);
}
va_start(args, algo);
kdf = entry->create_kdf(algo, args);
va_end(args);
if (kdf)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return kdf;
}
METHOD(crypto_factory_t, create_drbg, drbg_t*,
private_crypto_factory_t *this, drbg_type_t type, uint32_t strength,
rng_t *entropy, chunk_t personalization_str)
@@ -365,7 +411,7 @@ METHOD(crypto_factory_t, create_drbg, drbg_t*,
if (this->test_on_create &&
!this->tester->test_drbg(this->tester, type,
entry->create_drbg, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -398,7 +444,7 @@ METHOD(crypto_factory_t, create_rng, rng_t*,
if (this->test_on_create &&
!this->tester->test_rng(this->tester, quality,
entry->create_rng, NULL,
default_plugin_name))
entry->plugin_name))
{
continue;
}
@@ -462,7 +508,7 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
{
if (this->test_on_create && group != MODP_CUSTOM &&
!this->tester->test_dh(this->tester, group,
entry->create_dh, NULL, default_plugin_name))
entry->create_dh, NULL, entry->plugin_name))
{
continue;
}
@@ -749,6 +795,43 @@ METHOD(crypto_factory_t, remove_xof, void,
this->lock->unlock(this->lock);
}
METHOD(crypto_factory_t, add_kdf, bool,
private_crypto_factory_t *this, key_derivation_function_t algo,
const char *plugin_name, kdf_constructor_t create)
{
u_int speed = 0;
if (!this->test_on_add ||
this->tester->test_kdf(this->tester, algo, create, NULL,
this->bench ? &speed : NULL, plugin_name))
{
add_entry(this, this->kdfs, algo, plugin_name, 0, create);
return TRUE;
}
this->test_failures++;
return FALSE;
}
METHOD(crypto_factory_t, remove_kdf, void,
private_crypto_factory_t *this, kdf_constructor_t create)
{
entry_t *entry;
enumerator_t *enumerator;
this->lock->write_lock(this->lock);
enumerator = this->kdfs->create_enumerator(this->kdfs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create_kdf == create)
{
this->kdfs->remove_at(this->kdfs, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
METHOD(crypto_factory_t, add_drbg, bool,
private_crypto_factory_t *this, drbg_type_t type,
const char *plugin_name, drbg_constructor_t create)
@@ -1058,6 +1141,30 @@ METHOD(crypto_factory_t, create_xof_enumerator, enumerator_t*,
return create_enumerator(this, this->xofs, xof_filter);
}
CALLBACK(kdf_filter, bool,
void *n, enumerator_t *orig, va_list args)
{
entry_t *entry;
key_derivation_function_t *algo;
const char **plugin_name;
VA_ARGS_VGET(args, algo, plugin_name);
if (orig->enumerate(orig, &entry))
{
*algo = entry->algo;
*plugin_name = entry->plugin_name;
return TRUE;
}
return FALSE;
}
METHOD(crypto_factory_t, create_kdf_enumerator, enumerator_t*,
private_crypto_factory_t *this)
{
return create_enumerator(this, this->kdfs, kdf_filter);
}
CALLBACK(drbg_filter, bool,
void *n, enumerator_t *orig, va_list args)
{
@@ -1169,6 +1276,8 @@ METHOD(crypto_factory_t, add_test_vector, void,
return this->tester->add_prf_vector(this->tester, vector);
case EXTENDED_OUTPUT_FUNCTION:
return this->tester->add_xof_vector(this->tester, vector);
case KEY_DERIVATION_FUNCTION:
return this->tester->add_kdf_vector(this->tester, vector);
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
return this->tester->add_drbg_vector(this->tester, vector);
case RANDOM_NUMBER_GENERATOR:
@@ -1232,6 +1341,10 @@ METHOD(enumerator_t, verify_enumerate, bool,
*valid = this->tester->test_xof(this->tester, entry->algo,
entry->create_xof, NULL, entry->plugin_name);
break;
case KEY_DERIVATION_FUNCTION:
*valid = this->tester->test_kdf(this->tester, entry->algo,
entry->create_kdf, NULL, NULL, entry->plugin_name);
break;
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
*valid = this->tester->test_drbg(this->tester, entry->algo,
entry->create_drbg, NULL, entry->plugin_name);
@@ -1287,6 +1400,9 @@ METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
case EXTENDED_OUTPUT_FUNCTION:
inner = this->xofs->create_enumerator(this->xofs);
break;
case KEY_DERIVATION_FUNCTION:
inner = this->kdfs->create_enumerator(this->kdfs);
break;
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
inner = this->drbgs->create_enumerator(this->drbgs);
break;
@@ -1323,6 +1439,7 @@ METHOD(crypto_factory_t, destroy, void,
this->hashers->destroy(this->hashers);
this->prfs->destroy(this->prfs);
this->xofs->destroy(this->xofs);
this->kdfs->destroy(this->kdfs);
this->drbgs->destroy(this->drbgs);
this->rngs->destroy(this->rngs);
this->nonce_gens->destroy(this->nonce_gens);
@@ -1347,6 +1464,7 @@ crypto_factory_t *crypto_factory_create()
.create_hasher = _create_hasher,
.create_prf = _create_prf,
.create_xof = _create_xof,
.create_kdf = _create_kdf,
.create_drbg = _create_drbg,
.create_rng = _create_rng,
.create_nonce_gen = _create_nonce_gen,
@@ -1363,6 +1481,8 @@ crypto_factory_t *crypto_factory_create()
.remove_prf = _remove_prf,
.add_xof = _add_xof,
.remove_xof = _remove_xof,
.add_kdf = _add_kdf,
.remove_kdf = _remove_kdf,
.add_drbg = _add_drbg,
.remove_drbg = _remove_drbg,
.add_rng = _add_rng,
@@ -1377,6 +1497,7 @@ crypto_factory_t *crypto_factory_create()
.create_hasher_enumerator = _create_hasher_enumerator,
.create_prf_enumerator = _create_prf_enumerator,
.create_xof_enumerator = _create_xof_enumerator,
.create_kdf_enumerator = _create_kdf_enumerator,
.create_drbg_enumerator = _create_drbg_enumerator,
.create_dh_enumerator = _create_dh_enumerator,
.create_rng_enumerator = _create_rng_enumerator,
@@ -1391,6 +1512,7 @@ crypto_factory_t *crypto_factory_create()
.hashers = linked_list_create(),
.prfs = linked_list_create(),
.xofs = linked_list_create(),
.kdfs = linked_list_create(),
.drbgs = linked_list_create(),
.rngs = linked_list_create(),
.nonce_gens = linked_list_create(),
+48
View File
@@ -33,6 +33,7 @@ typedef struct crypto_factory_t crypto_factory_t;
#include <crypto/prfs/prf.h>
#include <crypto/rngs/rng.h>
#include <crypto/xofs/xof.h>
#include <crypto/kdfs/kdf.h>
#include <crypto/drbgs/drbg.h>
#include <crypto/nonce_gen.h>
#include <crypto/diffie_hellman.h>
@@ -70,6 +71,14 @@ typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo);
*/
typedef xof_t* (*xof_constructor_t)(ext_out_function_t algo);
/**
* Constructor function for key derivation functions
*
* The additional arguments depend on the algorithm, see comments
* for key_derivation_function_t.
*/
typedef kdf_t* (*kdf_constructor_t)(key_derivation_function_t algo, va_list args);
/**
* Constructor function for deterministic random bit generators
*/
@@ -154,6 +163,20 @@ struct crypto_factory_t {
*/
xof_t* (*create_xof)(crypto_factory_t *this, ext_out_function_t algo);
/**
* Create a key derivation function instance.
*
* Additional arguments depend on the KDF, please refer to the comments in
* key_derivation_function_t.
*
* @param algo KDF to create
* @param ... arguments depending on algo
* @return kdf_t instance, NULL if not supported
*/
kdf_t* (*create_kdf)(crypto_factory_t *this,
key_derivation_function_t algo, ...);
/**
* Create a deterministic random bit generator instance.
*
@@ -305,6 +328,24 @@ struct crypto_factory_t {
*/
void (*remove_xof)(crypto_factory_t *this, xof_constructor_t create);
/**
* Register a kdf constructor.
*
* @param algo algorithm to constructor
* @param plugin_name plugin that registered this algorithm
* @param create constructor function for that algorithm
* @return TRUE if registered, FALSE if test vector failed
*/
bool (*add_kdf)(crypto_factory_t *this, key_derivation_function_t algo,
const char *plugin_name, kdf_constructor_t create);
/**
* Unregister a kdf constructor.
*
* @param create constructor function to unregister
*/
void (*remove_kdf)(crypto_factory_t *this, kdf_constructor_t create);
/**
* Register a drbg constructor.
*
@@ -419,6 +460,13 @@ struct crypto_factory_t {
*/
enumerator_t* (*create_xof_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered KDFs.
*
* @return enumerator over key_derivation_function_t, plugin
*/
enumerator_t* (*create_kdf_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered DRBGs.
*
+220
View File
@@ -69,6 +69,11 @@ struct private_crypto_tester_t {
*/
linked_list_t *xof;
/**
* List of KDF test vectors
*/
linked_list_t *kdf;
/**
* List of DRBG test vectors
*/
@@ -1186,6 +1191,211 @@ failure:
return !failed;
}
/**
* Create a KDF using the given arguments
*/
static kdf_t *create_kdf_args(kdf_constructor_t create,
key_derivation_function_t alg, ...)
{
va_list args;
kdf_t *kdf;
va_start(args, alg);
kdf = create(alg, args);
va_end(args);
return kdf;
}
/**
* Create a KDF using arguments from the given test vector
*/
static kdf_t *create_kdf_vector(kdf_constructor_t create,
key_derivation_function_t alg,
kdf_test_vector_t *vector)
{
switch (alg)
{
case KDF_PRF:
case KDF_PRF_PLUS:
return create_kdf_args(create, alg, vector->arg.prf);
case KDF_UNDEFINED:
break;
}
return NULL;
}
/**
* Check if the given test vector applies to the passed arguments
*/
static bool kdf_vector_applies(key_derivation_function_t alg,
kdf_test_args_t *args, kdf_test_vector_t *vector)
{
bool applies = FALSE;
switch (alg)
{
case KDF_PRF:
case KDF_PRF_PLUS:
{
pseudo_random_function_t prf;
VA_ARGS_VGET(args->args, prf);
applies = (prf == vector->arg.prf);
break;
}
case KDF_UNDEFINED:
break;
}
return applies;
}
METHOD(crypto_tester_t, test_kdf, bool,
private_crypto_tester_t *this, key_derivation_function_t alg,
kdf_constructor_t create, kdf_test_args_t *args, u_int *speed,
const char *plugin_name)
{
enumerator_t *enumerator;
kdf_test_vector_t *vector;
va_list copy;
bool failed = FALSE;
u_int tested = 0, construction_failed = 0;
enumerator = this->kdf->create_enumerator(this->kdf);
while (enumerator->enumerate(enumerator, &vector))
{
kdf_t *kdf;
chunk_t out = chunk_empty;
if (vector->alg != alg ||
(args && !kdf_vector_applies(alg, args, vector)))
{
continue;
}
tested++;
failed = TRUE;
if (args)
{
va_copy(copy, args->args);
kdf = create(alg, copy);
va_end(copy);
}
else
{
kdf = create_kdf_vector(create, alg, vector);
}
if (!kdf)
{
if (args)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
key_derivation_function_names, alg, plugin_name);
break;
}
/* while there could be a problem, the constructor might just not
* be able to create an instance for this test vector, we check
* for that at the end */
construction_failed++;
failed = FALSE;
continue;
}
if (vector->key.len &&
!kdf->set_param(kdf, KDF_PARAM_KEY, vector->key))
{
goto failure;
}
if (vector->salt.len &&
!kdf->set_param(kdf, KDF_PARAM_SALT, vector->salt))
{
goto failure;
}
if (kdf_has_fixed_output_length(alg))
{
if (kdf->get_length(kdf) != vector->out.len)
{
goto failure;
}
}
else if (kdf->get_length(kdf) != SIZE_MAX)
{
goto failure;
}
/* allocated bytes */
if (!kdf->allocate_bytes(kdf, vector->out.len, &out))
{
goto failure;
}
if (!chunk_equals(out, vector->out))
{
goto failure;
}
/* allocate without knowing the length */
if (kdf_has_fixed_output_length(alg))
{
chunk_free(&out);
if (!kdf->allocate_bytes(kdf, 0, &out))
{
goto failure;
}
if (!chunk_equals(out, vector->out))
{
goto failure;
}
}
/* bytes to existing buffer */
memset(out.ptr, 0, out.len);
if (!kdf->get_bytes(kdf, out.len, out.ptr))
{
goto failure;
}
if (!chunk_equals(out, vector->out))
{
goto failure;
}
failed = FALSE;
failure:
kdf->destroy(kdf);
chunk_free(&out);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
key_derivation_function_names, alg, plugin_name,
get_name(vector));
break;
}
}
enumerator->destroy(enumerator);
if (!tested)
{
DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
this->required ? "disabled" : "enabled ",
key_derivation_function_names, alg, plugin_name);
return !this->required;
}
tested -= construction_failed;
if (!tested)
{
DBG1(DBG_LIB, "%s %N[%s]: unable to apply any available test vectors",
this->required ? "disabled" : "enabled ",
key_derivation_function_names, alg, plugin_name);
return !this->required;
}
if (!failed)
{
if (speed)
{
DBG2(DBG_LIB, "benchmarking for %N is currently not supported",
key_derivation_function_names, alg);
}
DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
key_derivation_function_names, alg, plugin_name, tested);
}
return !failed;
}
/**
* Benchmark a DRBG
*/
@@ -1622,6 +1832,12 @@ METHOD(crypto_tester_t, add_xof_vector, void,
this->xof->insert_last(this->xof, vector);
}
METHOD(crypto_tester_t, add_kdf_vector, void,
private_crypto_tester_t *this, kdf_test_vector_t *vector)
{
this->kdf->insert_last(this->kdf, vector);
}
METHOD(crypto_tester_t, add_drbg_vector, void,
private_crypto_tester_t *this, drbg_test_vector_t *vector)
{
@@ -1649,6 +1865,7 @@ METHOD(crypto_tester_t, destroy, void,
this->hasher->destroy(this->hasher);
this->prf->destroy(this->prf);
this->xof->destroy(this->xof);
this->kdf->destroy(this->kdf);
this->drbg->destroy(this->drbg);
this->rng->destroy(this->rng);
this->dh->destroy(this->dh);
@@ -1670,6 +1887,7 @@ crypto_tester_t *crypto_tester_create()
.test_hasher = _test_hasher,
.test_prf = _test_prf,
.test_xof = _test_xof,
.test_kdf = _test_kdf,
.test_drbg = _test_drbg,
.test_rng = _test_rng,
.test_dh = _test_dh,
@@ -1679,6 +1897,7 @@ crypto_tester_t *crypto_tester_create()
.add_hasher_vector = _add_hasher_vector,
.add_prf_vector = _add_prf_vector,
.add_xof_vector = _add_xof_vector,
.add_kdf_vector = _add_kdf_vector,
.add_drbg_vector = _add_drbg_vector,
.add_rng_vector = _add_rng_vector,
.add_dh_vector = _add_dh_vector,
@@ -1690,6 +1909,7 @@ crypto_tester_t *crypto_tester_create()
.hasher = linked_list_create(),
.prf = linked_list_create(),
.xof = linked_list_create(),
.kdf = linked_list_create(),
.drbg = linked_list_create(),
.rng = linked_list_create(),
.dh = linked_list_create(),
+45
View File
@@ -32,6 +32,8 @@ typedef struct signer_test_vector_t signer_test_vector_t;
typedef struct hasher_test_vector_t hasher_test_vector_t;
typedef struct prf_test_vector_t prf_test_vector_t;
typedef struct xof_test_vector_t xof_test_vector_t;
typedef struct kdf_test_vector_t kdf_test_vector_t;
typedef struct kdf_test_args_t kdf_test_args_t;
typedef struct drbg_test_vector_t drbg_test_vector_t;
typedef struct rng_test_vector_t rng_test_vector_t;
typedef struct dh_test_vector_t dh_test_vector_t;
@@ -130,6 +132,26 @@ struct xof_test_vector_t {
u_char *out;
};
struct kdf_test_vector_t {
/** kdf algorithm this test vector tests */
key_derivation_function_t alg;
/** argument passed to constructor, type depends on alg */
union {
pseudo_random_function_t prf;
} arg;
/** optional key */
chunk_t key;
/** optional salt */
chunk_t salt;
/** expected output */
chunk_t out;
};
struct kdf_test_args_t {
/** the arguments used to construct the KDF */
va_list args;
};
struct drbg_test_vector_t {
/** drbg type this test vector tests */
drbg_type_t type;
@@ -256,6 +278,22 @@ struct crypto_tester_t {
bool (*test_xof)(crypto_tester_t *this, ext_out_function_t alg,
xof_constructor_t create,
u_int *speed, const char *plugin_name);
/**
* Test a KDF algorithm.
*
* If constructor arguments are passed, only matching test vectors are
* tried. Otherwise, all are tried and implementations are allowed to fail
* construction with unsupported arguments.
*
* @param alg algorithm to test
* @param create constructor function for the XOF
* @param args optional arguments to pass to constructor
* @param speed speed test result, NULL to omit
* @return TRUE if test passed
*/
bool (*test_kdf)(crypto_tester_t *this, key_derivation_function_t alg,
kdf_constructor_t create, kdf_test_args_t *args,
u_int *speed, const char *plugin_name);
/**
* Test a DRBG type.
*
@@ -332,6 +370,13 @@ struct crypto_tester_t {
*/
void (*add_xof_vector)(crypto_tester_t *this, xof_test_vector_t *vector);
/**
* Add a test vector to test a KDF.
*
* @param vector pointer to test vector
*/
void (*add_kdf_vector)(crypto_tester_t *this, kdf_test_vector_t *vector);
/**
* Add a test vector to test a DRBG.
*
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "kdf.h"
ENUM(key_derivation_function_names, KDF_UNDEFINED, KDF_PRF_PLUS,
"KDF_UNDEFINED",
"KDF_PRF",
"KDF_PRF_PLUS",
);
/*
* Described in header
*/
bool kdf_has_fixed_output_length(key_derivation_function_t type)
{
switch (type)
{
case KDF_PRF:
return TRUE;
case KDF_PRF_PLUS:
case KDF_UNDEFINED:
break;
}
return FALSE;
}
+153
View File
@@ -0,0 +1,153 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @defgroup kdf kdf
* @{ @ingroup crypto
*/
#ifndef KDF_H_
#define KDF_H_
typedef enum key_derivation_function_t key_derivation_function_t;
typedef enum kdf_param_t kdf_param_t;
typedef struct kdf_t kdf_t;
#include <library.h>
/**
* Key Derivation Functions (KDF).
*/
enum key_derivation_function_t {
KDF_UNDEFINED,
/**
* RFC 7296 prf, expects a pseudo_random_function_t in the constructor,
* parameters are KEY (DH secret) and SALT (nonces).
* Has a fixed output length.
*/
KDF_PRF,
/**
* RFC 7296 prf+, expects a pseudo_random_function_t in the constructor,
* parameters are KEY (SKEYSEED/SK_d) and SALT (nonces etc.).
*/
KDF_PRF_PLUS,
};
/**
* enum name for key_derivation_function_t.
*/
extern enum_name_t *key_derivation_function_names;
/**
* Parameters for KDFs.
*/
enum kdf_param_t {
/**
* Key used for the key derivation (chunk_t).
*/
KDF_PARAM_KEY,
/**
* Salt used for the key derivation (chunk_t).
*/
KDF_PARAM_SALT,
};
/**
* Generic interface for Key Derivation Functions (KDF).
*
* Note that in comparison to xof_t, this interface does not support streaming.
* That is, calling get_bytes() or allocate_bytes() multiple times without
* changing the input parameters will result in the same output.
*/
struct kdf_t {
/**
* Return the type of KDF.
*
* @return KDF type
*/
key_derivation_function_t (*get_type)(kdf_t *this);
/**
* Output length for KDFs that produce a fixed amount of output.
*
* @return fixed output length, SIZE_MAX for variable length
*/
size_t (*get_length)(kdf_t *this);
/**
* Derives a key of the given length and writes it to the buffer.
*
* @note Fails if out_len doesn't match for KDFs with fixed output length.
*
* @param out_len number of key bytes requested
* @param buffer pointer where the derived key will be written
* @return TRUE if key derived successfully
*/
bool (*get_bytes)(kdf_t *this, size_t out_len,
uint8_t *buffer) __attribute__((warn_unused_result));
/**
* Derives a key of the given length and allocates space for it.
*
* @note Fails if out_len doesn't match for KDFs with fixed output length.
* However, for simplified usage, 0 can be passed for out_len to
* automatically allocate a chunk of the correct size.
*
* @param out_len number of key bytes requested, or 0 for KDFs with fixed
* output length
* @param chunk chunk which will hold the derived key
* @return TRUE if key derived successfully
*/
bool (*allocate_bytes)(kdf_t *this, size_t out_len,
chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Set a parameter for this KDF.
*
* @param param parameter to set
* @param ... parameter values
* @return TRUE if parameter set successfully
*/
bool (*set_param)(kdf_t *this, kdf_param_t param,
...) __attribute__((warn_unused_result));
/**
* Destroys this KDF object.
*/
void (*destroy)(kdf_t *this);
};
/**
* Check if the given KDF type has a fixed output length.
*
* @param type KDF type
* @return TRUE if the KDF type has a fixed output length
*/
bool kdf_has_fixed_output_length(key_derivation_function_t type);
#endif /** KDF_H_ @}*/
+3 -3
View File
@@ -131,7 +131,7 @@ static bool verify_padding(crypter_t *crypter, chunk_t *blob)
/**
* Prototype for key derivation functions.
*/
typedef bool (*kdf_t)(private_pkcs5_t *this, chunk_t password, chunk_t key);
typedef bool (*derive_t)(private_pkcs5_t *this, chunk_t password, chunk_t key);
/**
* Try to decrypt the given data with the given password using the given
@@ -139,7 +139,7 @@ typedef bool (*kdf_t)(private_pkcs5_t *this, chunk_t password, chunk_t key);
* to, key and iv point to the actual keys and initialization vectors resp.
*/
static bool decrypt_generic(private_pkcs5_t *this, chunk_t password,
chunk_t data, chunk_t *decrypted, kdf_t kdf,
chunk_t data, chunk_t *decrypted, derive_t kdf,
chunk_t keymat, chunk_t key, chunk_t iv)
{
if (!kdf(this, password, keymat))
@@ -341,7 +341,7 @@ METHOD(pkcs5_t, decrypt, bool,
private_pkcs5_t *this, chunk_t password, chunk_t data, chunk_t *decrypted)
{
chunk_t keymat, key, iv;
kdf_t kdf;
derive_t kdf;
if (!ensure_crypto_primitives(this, data) || !decrypted)
{
-170
View File
@@ -1,170 +0,0 @@
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include "prf_plus.h"
typedef struct private_prf_plus_t private_prf_plus_t;
typedef bool (*apply_prf_t)(private_prf_plus_t *this);
/**
* Private data of an prf_plus_t object.
*
*/
struct private_prf_plus_t {
/**
* Public interface of prf_plus_t.
*/
prf_plus_t public;
/**
* PRF to use.
*/
prf_t *prf;
/**
* Initial seed.
*/
chunk_t seed;
/**
* Octet which will be appended to the seed if a counter is used.
*/
uint8_t counter;
/**
* Already given out bytes in current buffer.
*/
size_t used;
/**
* Buffer to store current PRF result.
*/
chunk_t buffer;
/**
* The prf application method depending on whether a counter is used.
*/
apply_prf_t apply_prf;
};
/**
* Apply the PRF using the running counter
*/
static bool apply_prf_counter(private_prf_plus_t *this)
{
if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
!this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
this->buffer.ptr))
{
return FALSE;
}
this->counter++;
if (!this->counter)
{ /* according to RFC 7296, section 2.13, prf+ is undefined once the
* counter wrapped, so let's fail for future calls */
this->apply_prf = (void*)return_false;
}
return TRUE;
}
/**
* Apply the PRF using the running counter
*/
static bool apply_prf(private_prf_plus_t *this)
{
return this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
}
METHOD(prf_plus_t, get_bytes, bool,
private_prf_plus_t *this, size_t length, uint8_t *buffer)
{
size_t round, written = 0;
while (length > 0)
{
if (this->buffer.len == this->used)
{ /* buffer used, get next round */
if (!this->prf->get_bytes(this->prf, this->buffer, NULL))
{
return FALSE;
}
if (!this->apply_prf(this))
{
return FALSE;
}
this->used = 0;
}
round = min(length, this->buffer.len - this->used);
memcpy(buffer + written, this->buffer.ptr + this->used, round);
length -= round;
this->used += round;
written += round;
}
return TRUE;
}
METHOD(prf_plus_t, allocate_bytes, bool,
private_prf_plus_t *this, size_t length, chunk_t *chunk)
{
*chunk = chunk_alloc(length);
if (!get_bytes(this, length, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(prf_plus_t, destroy, void,
private_prf_plus_t *this)
{
chunk_clear(&this->buffer);
chunk_clear(&this->seed);
free(this);
}
/*
* Description in header.
*/
prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed)
{
private_prf_plus_t *this;
INIT(this,
.public = {
.get_bytes = _get_bytes,
.allocate_bytes = _allocate_bytes,
.destroy = _destroy,
},
.prf = prf,
.seed = chunk_clone(seed),
.buffer = chunk_alloc(prf->get_block_size(prf)),
.apply_prf = counter ? apply_prf_counter : apply_prf,
.counter = 0x01,
);
if (!this->apply_prf(this))
{
destroy(this);
return NULL;
}
return &this->public;
}
-70
View File
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup prf_plus prf_plus
* @{ @ingroup crypto
*/
#ifndef PRF_PLUS_H_
#define PRF_PLUS_H_
typedef struct prf_plus_t prf_plus_t;
#include <crypto/prfs/prf.h>
/**
* Implementation of the prf+ function used in IKEv1/IKEv2 keymat extension.
*/
struct prf_plus_t {
/**
* Get pseudo random bytes.
*
* @param length number of bytes to get
* @param buffer pointer where the generated bytes will be written
* @return TRUE if bytes generated successfully
*/
bool (*get_bytes)(prf_plus_t *this, size_t length,
uint8_t *buffer) __attribute__((warn_unused_result));
/**
* Allocate pseudo random bytes.
*
* @param length number of bytes to get
* @param chunk chunk which will hold generated bytes
* @return TRUE if bytes allocated successfully
*/
bool (*allocate_bytes)(prf_plus_t *this, size_t length,
chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys a prf_plus_t object.
*/
void (*destroy)(prf_plus_t *this);
};
/**
* Creates a new prf_plus_t object.
*
* @param prf prf object to use, must be destroyed after prf+.
* @param counter use an appending counter byte (for IKEv2 variant)
* @param seed input seed for prf
* @return prf_plus_t object, NULL on failure
*/
prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed);
#endif /** PRF_PLUS_H_ @}*/
+7 -4
View File
@@ -16,6 +16,7 @@
#include <crypto/transform.h>
#include <crypto/hashers/hasher.h>
#include <crypto/rngs/rng.h>
#include <crypto/kdfs/kdf.h>
ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS,
"ENCRYPTION_ALGORITHM",
@@ -23,16 +24,16 @@ ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS
"INTEGRITY_ALGORITHM",
"DIFFIE_HELLMAN_GROUP",
"EXTENDED_SEQUENCE_NUMBERS");
ENUM_NEXT(transform_type_names, HASH_ALGORITHM, DETERMINISTIC_RANDOM_BIT_GENERATOR,
ENUM_NEXT(transform_type_names, HASH_ALGORITHM, KEY_DERIVATION_FUNCTION,
EXTENDED_SEQUENCE_NUMBERS,
"HASH_ALGORITHM",
"RANDOM_NUMBER_GENERATOR",
"AEAD_ALGORITHM",
"COMPRESSION_ALGORITHM",
"EXTENDED OUTPUT FUNCTION",
"DETERMINISTIC RANDOM BIT GENERATOR");
ENUM_END(transform_type_names, DETERMINISTIC_RANDOM_BIT_GENERATOR);
"DETERMINISTIC RANDOM BIT GENERATOR",
"KEY_DERIVATION_FUNCTION");
ENUM_END(transform_type_names, KEY_DERIVATION_FUNCTION);
ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
"NO_EXT_SEQ",
@@ -65,6 +66,8 @@ enum_name_t* transform_get_enum_names(transform_type_t type)
return ext_out_function_names;
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
return drbg_type_names;
case KEY_DERIVATION_FUNCTION:
return key_derivation_function_names;
case COMPRESSION_ALGORITHM:
break;
}
+1
View File
@@ -40,6 +40,7 @@ enum transform_type_t {
COMPRESSION_ALGORITHM = 259,
EXTENDED_OUTPUT_FUNCTION = 260,
DETERMINISTIC_RANDOM_BIT_GENERATOR = 261,
KEY_DERIVATION_FUNCTION = 262,
};
/**
@@ -16,6 +16,7 @@ libstrongswan_botan_la_SOURCES = \
botan_rng.h botan_rng.c \
botan_hasher.h botan_hasher.c \
botan_hmac.h botan_hmac.c \
botan_kdf.h botan_kdf.c \
botan_crypter.h botan_crypter.c \
botan_rsa_public_key.h botan_rsa_public_key.c \
botan_rsa_private_key.h botan_rsa_private_key.c \
+221
View File
@@ -0,0 +1,221 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define _GNU_SOURCE
#include "botan_kdf.h"
#include "botan_util.h"
#include <botan/build.h>
#ifdef BOTAN_HAS_HKDF
#include <botan/ffi.h>
typedef struct private_kdf_t private_kdf_t;
/**
* Private data.
*/
struct private_kdf_t {
/**
* Public interface.
*/
kdf_t public;
/**
* KDF type.
*/
key_derivation_function_t type;
/**
* Name of the KDF algorithm in Botan.
*/
char *name;
/**
* Key for KDF.
*/
chunk_t key;
/**
* Salt for KDF.
*/
chunk_t salt;
/**
* Length of the hash output.
*/
size_t hash_size;
};
METHOD(kdf_t, get_type, key_derivation_function_t,
private_kdf_t *this)
{
return this->type;
}
METHOD(kdf_t, get_length, size_t,
private_kdf_t *this)
{
if (this->type == KDF_PRF_PLUS)
{
return SIZE_MAX;
}
return this->hash_size;
}
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
if (this->type == KDF_PRF)
{
if (out_len != get_length(this) ||
botan_kdf(this->name, buffer, out_len, this->key.ptr, this->key.len,
this->salt.ptr, this->salt.len, NULL, 0))
{
return FALSE;
}
return TRUE;
}
#if BOTAN_VERSION_MAJOR == 2
/* Botan 2 doesn't check the length, just silently prevents wrapping the
* counter and returns truncated output, so do this manually */
if (out_len > this->hash_size * 255)
{
return FALSE;
}
#endif
if (botan_kdf(this->name, buffer, out_len, this->key.ptr, this->key.len,
NULL, 0, this->salt.ptr, this->salt.len))
{
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, allocate_bytes, bool,
private_kdf_t *this, size_t out_len, chunk_t *chunk)
{
if (this->type == KDF_PRF)
{
out_len = out_len ?: get_length(this);
}
*chunk = chunk_alloc(out_len);
if (!get_bytes(this, out_len, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, set_param, bool,
private_kdf_t *this, kdf_param_t param, ...)
{
chunk_t chunk;
switch (param)
{
case KDF_PARAM_KEY:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->key);
this->key = chunk_clone(chunk);
break;
case KDF_PARAM_SALT:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->salt);
this->salt = chunk_clone(chunk);
break;
}
return TRUE;
}
METHOD(kdf_t, destroy, void,
private_kdf_t *this)
{
chunk_clear(&this->salt);
chunk_clear(&this->key);
free(this->name);
free(this);
}
/*
* Described in header
*/
kdf_t *botan_kdf_create(key_derivation_function_t algo, va_list args)
{
private_kdf_t *this;
pseudo_random_function_t prf_alg;
const char *hash_name;
char *name, buf[HASH_SIZE_SHA512];
if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
{
return NULL;
}
VA_ARGS_VGET(args, prf_alg);
hash_name = botan_get_hash(hasher_algorithm_from_prf(prf_alg));
if (!hash_name)
{
return NULL;
}
if (algo == KDF_PRF)
{
if (asprintf(&name, "HKDF-Extract(%s)", hash_name) <= 0)
{
return NULL;
}
}
else if (asprintf(&name, "HKDF-Expand(%s)", hash_name) <= 0)
{
return NULL;
}
INIT(this,
.public = {
.get_type = _get_type,
.get_length = _get_length,
.get_bytes = _get_bytes,
.allocate_bytes = _allocate_bytes,
.set_param = _set_param,
.destroy = _destroy,
},
.type = algo,
.name = name,
.hash_size = hasher_hash_size(hasher_algorithm_from_prf(prf_alg)),
);
/* test if we can actually use the algorithm */
if (!get_bytes(this, algo == KDF_PRF ? get_length(this) : sizeof(buf), buf))
{
destroy(this);
return NULL;
}
return &this->public;
}
#endif
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Implements key derivation functions (KDF) using Botan, in particular prf+,
* which is implemented via Botan's HKDF implementation.
*
* @defgroup botan_kdf botan_kdf
* @{ @ingroup botan_p
*/
#ifndef BOTAN_KDF_H_
#define BOTAN_KDF_H_
#include <crypto/kdfs/kdf.h>
/**
* Creates a new kdf_t object.
*
* @param algo algorithm to instantiate
* @param args algorithm-specific arguments
* @return kdf_t object, NULL if not supported
*/
kdf_t *botan_kdf_create(key_derivation_function_t algo, va_list args);
#endif /** BOTAN_KDF_H_ @}*/
@@ -32,6 +32,7 @@
#include "botan_crypter.h"
#include "botan_diffie_hellman.h"
#include "botan_hmac.h"
#include "botan_kdf.h"
#include "botan_rsa_public_key.h"
#include "botan_rsa_private_key.h"
#include "botan_ec_diffie_hellman.h"
@@ -209,6 +210,13 @@ METHOD(plugin_t, get_features, int,
#endif
#endif /* BOTAN_HAS_HMAC */
/* kdfs */
#ifdef BOTAN_HAS_HKDF
PLUGIN_REGISTER(SIGNER, botan_kdf_create),
PLUGIN_PROVIDE(KDF, KDF_PRF),
PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
#endif /* BOTAN_HAS_HKDF */
/* generic key loaders */
#if defined (BOTAN_HAS_RSA) || defined(BOTAN_HAS_ECDSA) || \
defined(BOTAN_HAS_ED25519)
+17
View File
@@ -0,0 +1,17 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = \
$(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-kdf.la
else
plugin_LTLIBRARIES = libstrongswan-kdf.la
endif
libstrongswan_kdf_la_SOURCES = \
kdf_plugin.h kdf_plugin.c \
kdf_kdf.h kdf_kdf.c
libstrongswan_kdf_la_LDFLAGS = -module -avoid-version
+221
View File
@@ -0,0 +1,221 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "kdf_kdf.h"
typedef struct private_kdf_t private_kdf_t;
/**
* Private data.
*/
struct private_kdf_t {
/**
* Public interface.
*/
kdf_t public;
/**
* KDF type.
*/
key_derivation_function_t type;
/**
* Underlying PRF.
*/
prf_t *prf;
/**
* Salt value.
*/
chunk_t salt;
};
METHOD(kdf_t, get_type, key_derivation_function_t,
private_kdf_t *this)
{
return this->type;
}
METHOD(kdf_t, get_length, size_t,
private_kdf_t *this)
{
if (this->type == KDF_PRF_PLUS)
{
return SIZE_MAX;
}
return this->prf->get_block_size(this->prf);
}
METHOD(kdf_t, get_bytes_prf_plus, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
chunk_t block, previous = chunk_empty;
uint8_t counter = 1, *out = buffer;
size_t len;
bool success = TRUE;
block = chunk_alloca(this->prf->get_block_size(this->prf));
if (out_len > block.len * 255)
{
return FALSE;
}
while (out_len)
{
if (!this->prf->get_bytes(this->prf, previous, NULL) ||
!this->prf->get_bytes(this->prf, this->salt, NULL) ||
!this->prf->get_bytes(this->prf, chunk_from_thing(counter),
block.ptr))
{
success = FALSE;
break;
}
len = min(out_len, block.len);
memcpy(out, block.ptr, len);
previous = chunk_create(out, block.len);
out_len -= len;
out += len;
counter++;
}
memwipe(block.ptr, block.len);
return success;
}
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
if (out_len != get_length(this))
{
return FALSE;
}
return this->prf->get_bytes(this->prf, this->salt, buffer);
}
METHOD(kdf_t, allocate_bytes, bool,
private_kdf_t *this, size_t out_len, chunk_t *chunk)
{
if (this->type == KDF_PRF)
{
out_len = out_len ?: get_length(this);
}
*chunk = chunk_alloc(out_len);
if (!this->public.get_bytes(&this->public, out_len, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, set_param, bool,
private_kdf_t *this, kdf_param_t param, ...)
{
chunk_t chunk;
bool success = FALSE;
if (this->type == KDF_PRF)
{ /* IKEv2 uses the nonces etc., which we receive as SALT, as PRF key and
* the DH secret as salt */
switch (param)
{
case KDF_PARAM_KEY:
param = KDF_PARAM_SALT;
break;
case KDF_PARAM_SALT:
param = KDF_PARAM_KEY;
break;
default:
break;
}
}
switch (param)
{
case KDF_PARAM_KEY:
VA_ARGS_GET(param, chunk);
success = this->prf->set_key(this->prf, chunk);
break;
case KDF_PARAM_SALT:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->salt);
this->salt = chunk_clone(chunk);
success = TRUE;
break;
}
return success;
}
METHOD(kdf_t, destroy, void,
private_kdf_t *this)
{
this->prf->destroy(this->prf);
chunk_clear(&this->salt);
free(this);
}
/*
* Described in header
*/
kdf_t *kdf_kdf_create(key_derivation_function_t algo, va_list args)
{
private_kdf_t *this;
pseudo_random_function_t prf_alg;
prf_t *prf;
if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
{
return NULL;
}
VA_ARGS_VGET(args, prf_alg);
prf = lib->crypto->create_prf(lib->crypto, prf_alg);
if (!prf)
{
DBG1(DBG_LIB, "failed to create %N for %N",
pseudo_random_function_names, prf_alg,
key_derivation_function_names, algo);
return NULL;
}
INIT(this,
.public = {
.get_type = _get_type,
.get_length = _get_length,
.get_bytes = _get_bytes,
.allocate_bytes = _allocate_bytes,
.set_param = _set_param,
.destroy = _destroy,
},
.type = algo,
.prf = prf,
);
if (algo == KDF_PRF_PLUS)
{
this->public.get_bytes = _get_bytes_prf_plus;
}
return &this->public;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Implements a KDF wrapper around PRFs, and prf+ as defined in RFC 7296,
* section 2.13:
*
* @verbatim
prf+ (K,S) = T1 | T2 | T3 | T4 | ...
where:
T1 = prf (K, S | 0x01)
T2 = prf (K, T1 | S | 0x02)
T3 = prf (K, T2 | S | 0x03)
T4 = prf (K, T3 | S | 0x04)
...
* @endverbatim
*
* @defgroup kdf_kdf kdf_kdf
* @{ @ingroup kdf_p
*/
#ifndef KDF_KDF_H_
#define KDF_KDF_H_
#include <crypto/kdfs/kdf.h>
/**
* Create a kdf_t object
*
* @param algo KDF_PRF_PLUS
* @param args pseudo_random_function_t of the underlying PRF
* @return kdf_t object, NULL if not supported
*/
kdf_t *kdf_kdf_create(key_derivation_function_t algo, va_list args);
#endif /** KDF_KDF_H_ @}*/
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "kdf_plugin.h"
#include "kdf_kdf.h"
#include <library.h>
typedef struct private_kdf_plugin_t private_kdf_plugin_t;
/**
* Private data
*/
struct private_kdf_plugin_t {
/**
* Public interface
*/
kdf_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
private_kdf_plugin_t *this)
{
return "kdf";
}
METHOD(plugin_t, get_features, int,
private_kdf_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_REGISTER(KDF, kdf_kdf_create),
PLUGIN_PROVIDE(KDF, KDF_PRF),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA1),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_256),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_384),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_512),
PLUGIN_SDEPEND(PRF, PRF_AES128_XCBC),
PLUGIN_SDEPEND(PRF, PRF_AES128_CMAC),
PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA1),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_256),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_384),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_512),
PLUGIN_SDEPEND(PRF, PRF_AES128_XCBC),
PLUGIN_SDEPEND(PRF, PRF_AES128_CMAC),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
private_kdf_plugin_t *this)
{
free(this);
}
/*
* Described in header
*/
plugin_t *kdf_plugin_create()
{
private_kdf_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
);
return &this->public.plugin;
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @defgroup kdf_p kdf
* @ingroup plugins
*
* @defgroup kdf_plugin kdf_plugin
* @{ @ingroup kdf_p
*/
#ifndef KDF_PLUGIN_H_
#define KDF_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct kdf_plugin_t kdf_plugin_t;
/**
* Plugin implementing the key derivation functions (KDF) in software.
*/
struct kdf_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** KDF_PLUGIN_H_ @}*/
@@ -33,6 +33,7 @@ libstrongswan_openssl_la_SOURCES = \
openssl_pkcs12.c openssl_pkcs12.h \
openssl_rng.c openssl_rng.h \
openssl_hmac.c openssl_hmac.h \
openssl_kdf.c openssl_kdf.h \
openssl_aead.c openssl_aead.h \
openssl_x_diffie_hellman.c openssl_x_diffie_hellman.h \
openssl_ed_private_key.c openssl_ed_private_key.h \
@@ -0,0 +1,219 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <openssl/opensslv.h>
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_NO_HMAC) && OPENSSL_VERSION_NUMBER >= 0x10101000L
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "openssl_kdf.h"
typedef struct private_kdf_t private_kdf_t;
/**
* Private data.
*/
struct private_kdf_t {
/**
* Public interface.
*/
kdf_t public;
/**
* KDF type.
*/
key_derivation_function_t type;
/**
* Hasher to use for underlying PRF.
*/
const EVP_MD *hasher;
/**
* Key for KDF. Stored here because OpenSSL's HKDF API does not provide a
* way to clear the "info" field in the context, new data is always
* appended (up to 1024 bytes).
*/
chunk_t key;
/**
* Salt for prf+ (see above).
*/
chunk_t salt;
};
METHOD(kdf_t, get_type, key_derivation_function_t,
private_kdf_t *this)
{
return this->type;
}
METHOD(kdf_t, get_length, size_t,
private_kdf_t *this)
{
if (this->type == KDF_PRF_PLUS)
{
return SIZE_MAX;
}
return EVP_MD_size(this->hasher);
}
/**
* Set the parameters as a appropriate for the given KDF type.
*/
static bool set_params(private_kdf_t *this, EVP_PKEY_CTX *ctx)
{
if (this->type == KDF_PRF)
{
return EVP_PKEY_CTX_hkdf_mode(ctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) > 0 &&
EVP_PKEY_CTX_set1_hkdf_key(ctx, this->key.ptr, this->key.len) > 0 &&
EVP_PKEY_CTX_set1_hkdf_salt(ctx, this->salt.ptr, this->salt.len) > 0;
}
/* for HKDF-Expand() we map the salt to the "info" field */
return EVP_PKEY_CTX_hkdf_mode(ctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) > 0 &&
EVP_PKEY_CTX_set1_hkdf_key(ctx, this->key.ptr, this->key.len) > 0 &&
EVP_PKEY_CTX_add1_hkdf_info(ctx, this->salt.ptr, this->salt.len) > 0;
}
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
EVP_PKEY_CTX *ctx;
if (this->type == KDF_PRF && out_len != get_length(this))
{
return FALSE;
}
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
if (!ctx ||
EVP_PKEY_derive_init(ctx) <= 0 ||
EVP_PKEY_CTX_set_hkdf_md(ctx, this->hasher) <= 0 ||
!set_params(this, ctx) ||
EVP_PKEY_derive(ctx, buffer, &out_len) <= 0)
{
EVP_PKEY_CTX_free(ctx);
return FALSE;
}
EVP_PKEY_CTX_free(ctx);
return TRUE;
}
METHOD(kdf_t, allocate_bytes, bool,
private_kdf_t *this, size_t out_len, chunk_t *chunk)
{
if (this->type == KDF_PRF)
{
out_len = out_len ?: get_length(this);
}
*chunk = chunk_alloc(out_len);
if (!get_bytes(this, out_len, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, set_param, bool,
private_kdf_t *this, kdf_param_t param, ...)
{
chunk_t chunk;
switch (param)
{
case KDF_PARAM_KEY:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->key);
this->key = chunk_clone(chunk);
break;
case KDF_PARAM_SALT:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->salt);
this->salt = chunk_clone(chunk);
break;
}
return TRUE;
}
METHOD(kdf_t, destroy, void,
private_kdf_t *this)
{
chunk_clear(&this->salt);
chunk_clear(&this->key);
free(this);
}
/*
* Described in header
*/
kdf_t *openssl_kdf_create(key_derivation_function_t algo, va_list args)
{
private_kdf_t *this;
pseudo_random_function_t prf_alg;
char *name, buf[EVP_MAX_MD_SIZE];
if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
{
return NULL;
}
VA_ARGS_VGET(args, prf_alg);
name = enum_to_name(hash_algorithm_short_names,
hasher_algorithm_from_prf(prf_alg));
if (!name)
{
return NULL;
}
INIT(this,
.public = {
.get_type = _get_type,
.get_length = _get_length,
.get_bytes = _get_bytes,
.allocate_bytes = _allocate_bytes,
.set_param = _set_param,
.destroy = _destroy,
},
.type = algo,
.hasher = EVP_get_digestbyname(name),
/* use a lengthy key to test the implementation below to make sure the
* algorithms are usable, see openssl_hmac.c for details */
.key = chunk_clone(chunk_from_str("00000000000000000000000000000000")),
);
if (!this->hasher ||
!get_bytes(this, algo == KDF_PRF ? get_length(this) : sizeof(buf), buf))
{
destroy(this);
return NULL;
}
return &this->public;
}
#endif /* OPENSSL_NO_HMAC && OPENSSL_VERSION_NUMBER */
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Implements key derivation functions (KDF) via OpenSSL, in particular prf+,
* which is implemented via OpenSSL's HKDF implementation.
*
* @defgroup openssl_kdf openssl_kdf
* @{ @ingroup openssl_p
*/
#ifndef OPENSSL_KDF_H_
#define OPENSSL_KDF_H_
#include <crypto/kdfs/kdf.h>
/**
* Creates a new kdf_t object.
*
* @param algo algorithm to instantiate
* @param args algorithm-specific arguments
* @return kdf_t object, NULL if not supported
*/
kdf_t *openssl_kdf_create(key_derivation_function_t algo, va_list args);
#endif /** OPENSSL_KDF_H_ @}*/
@@ -52,6 +52,7 @@
#include "openssl_pkcs12.h"
#include "openssl_rng.h"
#include "openssl_hmac.h"
#include "openssl_kdf.h"
#include "openssl_aead.h"
#include "openssl_x_diffie_hellman.h"
#include "openssl_ed_public_key.h"
@@ -654,6 +655,12 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
/* HKDF is available since 1.1.0, expand-only mode only since 1.1.1 */
PLUGIN_REGISTER(KDF, openssl_kdf_create),
PLUGIN_PROVIDE(KDF, KDF_PRF),
PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
#endif
#endif /* OPENSSL_NO_HMAC */
#if (OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_AES)) || \
(OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_CHACHA))
+43 -4
View File
@@ -32,6 +32,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
"HASHER",
"PRF",
"XOF",
"KDF",
"DRBG",
"DH",
"RNG",
@@ -93,6 +94,9 @@ uint32_t plugin_feature_hash(plugin_feature_t *feature)
case FEATURE_XOF:
data = chunk_from_thing(feature->arg.xof);
break;
case FEATURE_KDF:
data = chunk_from_thing(feature->arg.kdf);
break;
case FEATURE_DRBG:
data = chunk_from_thing(feature->arg.drbg);
break;
@@ -171,6 +175,8 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
return a->arg.prf == b->arg.prf;
case FEATURE_XOF:
return a->arg.xof == b->arg.xof;
case FEATURE_KDF:
return a->arg.kdf == b->arg.kdf;
case FEATURE_DRBG:
return a->arg.drbg == b->arg.drbg;
case FEATURE_DH:
@@ -232,6 +238,7 @@ bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
case FEATURE_HASHER:
case FEATURE_PRF:
case FEATURE_XOF:
case FEATURE_KDF:
case FEATURE_DRBG:
case FEATURE_DH:
case FEATURE_NONCE_GEN:
@@ -327,6 +334,13 @@ char* plugin_feature_get_string(plugin_feature_t *feature)
return str;
}
break;
case FEATURE_KDF:
if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
key_derivation_function_names, feature->arg.kdf) > 0)
{
return str;
}
break;
case FEATURE_DRBG:
if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
drbg_type_names, feature->arg.drbg) > 0)
@@ -472,6 +486,17 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
name = plugin->get_name(plugin);
switch (feature->type)
{
case FEATURE_NONE:
case FEATURE_PRIVKEY_SIGN:
case FEATURE_PRIVKEY_DECRYPT:
case FEATURE_PUBKEY_VERIFY:
case FEATURE_PUBKEY_ENCRYPT:
case FEATURE_EAP_SERVER:
case FEATURE_EAP_PEER:
case FEATURE_XAUTH_SERVER:
case FEATURE_XAUTH_PEER:
case FEATURE_CUSTOM:
break;
case FEATURE_CRYPTER:
lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg,
feature->arg.crypter.key_size,
@@ -498,6 +523,10 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
lib->crypto->add_xof(lib->crypto, feature->arg.xof,
name, reg->arg.reg.f);
break;
case FEATURE_KDF:
lib->crypto->add_kdf(lib->crypto, feature->arg.kdf,
name, reg->arg.reg.f);
break;
case FEATURE_DRBG:
lib->crypto->add_drbg(lib->crypto, feature->arg.drbg,
name, reg->arg.reg.f);
@@ -547,8 +576,6 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
case FEATURE_RESOLVER:
lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f);
break;
default:
break;
}
return TRUE;
}
@@ -574,6 +601,17 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
}
switch (feature->type)
{
case FEATURE_NONE:
case FEATURE_PRIVKEY_SIGN:
case FEATURE_PRIVKEY_DECRYPT:
case FEATURE_PUBKEY_VERIFY:
case FEATURE_PUBKEY_ENCRYPT:
case FEATURE_EAP_SERVER:
case FEATURE_EAP_PEER:
case FEATURE_XAUTH_SERVER:
case FEATURE_XAUTH_PEER:
case FEATURE_CUSTOM:
break;
case FEATURE_CRYPTER:
lib->crypto->remove_crypter(lib->crypto, reg->arg.reg.f);
break;
@@ -592,6 +630,9 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
case FEATURE_XOF:
lib->crypto->remove_xof(lib->crypto, reg->arg.reg.f);
break;
case FEATURE_KDF:
lib->crypto->remove_kdf(lib->crypto, reg->arg.reg.f);
break;
case FEATURE_DRBG:
lib->crypto->remove_drbg(lib->crypto, reg->arg.reg.f);
break;
@@ -628,8 +669,6 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
case FEATURE_RESOLVER:
lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f);
break;
default:
break;
}
return TRUE;
}
+7 -1
View File
@@ -113,6 +113,8 @@ struct plugin_feature_t {
FEATURE_PRF,
/** xof_t */
FEATURE_XOF,
/** kdf_t */
FEATURE_KDF,
/** drbg_t */
FEATURE_DRBG,
/** diffie_hellman_t */
@@ -176,8 +178,10 @@ struct plugin_feature_t {
integrity_algorithm_t signer;
/** FEATURE_PRF */
pseudo_random_function_t prf;
/** FEATURE_XOFF */
/** FEATURE_XOF */
ext_out_function_t xof;
/** FEATURE_KDF */
key_derivation_function_t kdf;
/** FEATURE_DRBG */
drbg_type_t drbg;
/** FEATURE_HASHER */
@@ -288,6 +292,7 @@ struct plugin_feature_t {
#define _PLUGIN_FEATURE_HASHER(kind, alg) __PLUGIN_FEATURE(kind, HASHER, .hasher = alg)
#define _PLUGIN_FEATURE_PRF(kind, alg) __PLUGIN_FEATURE(kind, PRF, .prf = alg)
#define _PLUGIN_FEATURE_XOF(kind, alg) __PLUGIN_FEATURE(kind, XOF, .xof = alg)
#define _PLUGIN_FEATURE_KDF(kind, alg) __PLUGIN_FEATURE(kind, KDF, .kdf = alg)
#define _PLUGIN_FEATURE_DRBG(kind, type) __PLUGIN_FEATURE(kind, DRBG, .drbg = type)
#define _PLUGIN_FEATURE_DH(kind, group) __PLUGIN_FEATURE(kind, DH, .dh_group = group)
#define _PLUGIN_FEATURE_RNG(kind, quality) __PLUGIN_FEATURE(kind, RNG, .rng_quality = quality)
@@ -322,6 +327,7 @@ struct plugin_feature_t {
#define _PLUGIN_FEATURE_REGISTER_HASHER(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_PRF(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_XOF(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_KDF(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_DRBG(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_DH(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_RNG(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
@@ -30,6 +30,8 @@ libstrongswan_test_vectors_la_SOURCES = \
test_vectors/cast.c \
test_vectors/des.c \
test_vectors/idea.c \
test_vectors/kdf_prf.c \
test_vectors/kdf_prf_plus.c \
test_vectors/null.c \
test_vectors/rc2.c \
test_vectors/rc5.c \
@@ -220,6 +220,20 @@ TEST_VECTOR_HASHER(sha3_256_255)
TEST_VECTOR_HASHER(sha3_384_255)
TEST_VECTOR_HASHER(sha3_512_255)
TEST_VECTOR_KDF(prf_sha256_1)
TEST_VECTOR_KDF(prf_sha256_2)
TEST_VECTOR_KDF(prf_sha384_1)
TEST_VECTOR_KDF(prf_sha384_2)
TEST_VECTOR_KDF(prf_sha512_1)
TEST_VECTOR_KDF(prf_sha512_2)
TEST_VECTOR_KDF(prf_plus_sha256_old)
TEST_VECTOR_KDF(prf_plus_sha256_1)
TEST_VECTOR_KDF(prf_plus_sha256_2)
TEST_VECTOR_KDF(prf_plus_sha384_1)
TEST_VECTOR_KDF(prf_plus_sha384_2)
TEST_VECTOR_KDF(prf_plus_sha512_1)
TEST_VECTOR_KDF(prf_plus_sha512_2)
TEST_VECTOR_PRF(aes_xcbc_p1)
TEST_VECTOR_PRF(aes_xcbc_p2)
TEST_VECTOR_PRF(aes_xcbc_p3)
@@ -0,0 +1,236 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <crypto/crypto_tester.h>
/**
* The following test vectors are from CAVP/SP 800-135 for IKEv2.
*
* key = g^ir, salt = Ni | Nr (one vector with min. and one with max. size for
* nonces)
*/
kdf_test_vector_t prf_sha256_1 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_256,
.key = chunk_from_chars(
0x42,0x96,0x8e,0x5d,0x0c,0xcc,0x3c,0xfc,0x5a,0x3e,0x4b,0xc1,0xbb,0xa3,0x70,0xce,
0xa1,0xfa,0xe0,0xd5,0x4c,0x49,0xcc,0xba,0x34,0xb2,0xbe,0xe8,0x04,0xbe,0xeb,0x2e,
0x9e,0x8c,0x57,0xa4,0xe0,0x1b,0xd4,0x51,0x02,0xcf,0x24,0x33,0xaa,0xcc,0x6c,0xfe,
0xc0,0x67,0x92,0xf3,0x63,0xe5,0x17,0x0e,0x6a,0xa6,0x65,0x02,0x74,0xe9,0x06,0x64,
0x8e,0x44,0x9d,0x27,0xa8,0xf0,0x0b,0x5b,0x44,0x26,0x19,0x82,0xc9,0x83,0x5c,0x74,
0x8a,0x75,0x1e,0xc5,0x13,0x8e,0xaa,0xcc,0x5e,0x02,0x56,0x61,0x33,0x95,0x38,0xa6,
0x1b,0xf4,0x18,0xe4,0x54,0x69,0x9e,0x19,0xc3,0x2d,0xb8,0xd9,0xce,0x5d,0xd8,0x6b,
0x22,0x0f,0x1e,0x89,0xaf,0xc5,0x87,0x2e,0x68,0xbe,0x36,0xcb,0x1a,0x0c,0x88,0x66),
.salt = chunk_from_chars(
0xed,0x80,0xdc,0x79,0x91,0x2c,0x32,0xa9,0x35,0xfb,0x6d,0x1a,0x3f,0xea,0xc0,0x78),
.out = chunk_from_chars(
0x37,0xfd,0xe9,0x0b,0x81,0xd6,0x36,0x92,0x62,0x0f,0x67,0x36,0x7b,0x62,0x09,0x2e,
0x3e,0xfd,0xc6,0xa0,0x35,0x09,0x13,0x7d,0x73,0x10,0x04,0x76,0x7f,0xf3,0x50,0x10),
};
kdf_test_vector_t prf_sha256_2 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_256,
.key = chunk_from_chars(
0xb0,0x70,0x20,0x8f,0x89,0x47,0xdf,0x4f,0x7d,0x12,0x76,0x16,0x1f,0x40,0x7f,0x7b,
0x7f,0x5c,0x4a,0x49,0xac,0x79,0xf0,0xcc,0x0c,0x7d,0x4e,0x28,0x48,0x4c,0x6f,0x85,
0x84,0xf0,0x00,0x7b,0x9b,0xf0,0xe0,0x5f,0xdb,0x59,0x61,0xa1,0x7d,0x3a,0xa8,0x5c,
0x6e,0x3f,0x55,0x71,0x29,0x6a,0x43,0xba,0x89,0x6c,0xdc,0x88,0xc1,0xa4,0x45,0x7f,
0xb1,0x2c,0xbe,0x56,0xca,0x4a,0x20,0xc9,0xa7,0xe1,0x9a,0xdc,0x67,0x45,0x3c,0x4a,
0xde,0x53,0x9e,0x25,0x9f,0x82,0x5f,0xf9,0x4c,0x9a,0x83,0xf8,0x39,0x60,0x2f,0x86,
0x51,0xc9,0x27,0x6d,0x8e,0x44,0x4e,0xcb,0x95,0xa0,0x54,0x0e,0xe7,0xea,0x32,0x20,
0xa9,0x22,0x34,0x5e,0xd9,0x9e,0xf7,0xe7,0xad,0x32,0xb1,0x9d,0x46,0x10,0xe9,0xef),
.salt = chunk_from_chars(
0xef,0xa7,0x29,0x13,0x18,0x22,0x78,0xff,0xbd,0x14,0xe7,0x89,0x20,0xc0,0x62,0x51,
0x9a,0xba,0xb8,0xc1,0x6e,0x5e,0xd7,0x0c,0x08,0x41,0xa4,0x8c,0xdb,0x98,0x23,0x7e,
0xe9,0x3f,0x73,0x5f,0xb2,0xdf,0x18,0x43,0x58,0xaa,0xdc,0x13,0xd8,0x3f,0x43,0xfe,
0x8d,0x87,0x05,0x17,0x6c,0x8c,0xa3,0x13,0x82,0x5a,0x1b,0xcd,0xf7,0x79,0x11,0xc5,
0x98,0x00,0x16,0x71,0xff,0xbf,0x01,0x4e,0x37,0xa8,0xc0,0x4d,0x49,0xa7,0x83,0x9d,
0xfe,0xa6,0xcd,0xc5,0x87,0x68,0x8d,0x45,0x88,0xfe,0x43,0x23,0x5b,0x71,0x69,0x3f,
0xfd,0x07,0x29,0x33,0x86,0xb6,0xbf,0x4c,0x19,0x9e,0x33,0x61,0x65,0xb2,0x60,0x78,
0x77,0x36,0xf5,0x4b,0xe9,0x5d,0xb6,0x91,0x16,0x38,0x8b,0xc2,0xec,0xa2,0xb3,0xb2,
0x94,0x84,0x71,0x74,0x17,0xbb,0x3c,0x71,0x81,0x4c,0xe1,0x3b,0x84,0x44,0x6d,0xc3,
0x96,0x4c,0x30,0x29,0x84,0xf9,0x77,0x81,0xf6,0x31,0x66,0x24,0x08,0x90,0x10,0x7c,
0x2e,0x75,0x1a,0x00,0x43,0x6f,0x7c,0x3c,0x9f,0xf1,0x27,0x60,0xe4,0x9d,0x91,0x56,
0x3b,0xe6,0x03,0xfd,0x96,0x41,0xa0,0xa6,0x49,0x18,0xa9,0x32,0x91,0xed,0x11,0x3d,
0xb1,0x2f,0x97,0x07,0x60,0x9d,0x17,0x20,0x96,0xeb,0x58,0xf9,0x15,0x44,0x74,0xda,
0x40,0xc1,0xf5,0xc0,0x90,0x3e,0x9c,0xa2,0xf9,0x1b,0xa6,0x60,0x07,0x75,0xdf,0x71,
0x66,0xca,0xf8,0xe3,0x27,0x85,0x9e,0x67,0x62,0x32,0xd3,0x40,0x46,0x04,0x4c,0xee,
0x43,0xf9,0x01,0x9f,0x04,0x68,0x56,0x12,0x63,0x5b,0x99,0xcb,0xeb,0xcb,0x36,0x3d,
0x56,0x5e,0xaf,0x0e,0x54,0x7e,0xec,0xb9,0x41,0xc9,0x94,0xdf,0xd4,0x71,0xed,0x56,
0x43,0xc0,0x87,0x74,0x4f,0x77,0x09,0xcc,0x3e,0x25,0x10,0xf2,0x74,0x26,0xc6,0x2c,
0x0f,0xf3,0xac,0xb3,0xc2,0x76,0x61,0xd2,0x6a,0x6d,0x83,0xc2,0xa2,0x5e,0x13,0xa6,
0xd4,0x65,0xbd,0x04,0x7f,0x90,0x55,0x00,0xe5,0xeb,0xbe,0x42,0x66,0x43,0x0d,0x56,
0x67,0x14,0x0f,0x77,0xe7,0x97,0x71,0x2a,0x8c,0x8f,0x63,0xc5,0x83,0xf4,0xb4,0x64,
0x9b,0x72,0x89,0x9e,0xa3,0x4a,0xbf,0xdb,0x17,0x61,0x7c,0x46,0x0c,0x35,0xf2,0x50,
0x64,0x94,0x49,0x4f,0x22,0x3e,0x25,0x1a,0xc7,0x1a,0x5b,0x9b,0x7e,0xea,0x87,0xf4,
0xf5,0xe3,0x33,0xa3,0xc1,0xbb,0xb4,0xbb,0x09,0x25,0x8b,0x6a,0x4b,0x5f,0x8c,0x9f,
0xb8,0x2b,0xf4,0x2d,0xa9,0xd4,0xa4,0x65,0x43,0xc6,0xa9,0xeb,0x9a,0xa3,0x0e,0xa9,
0xda,0x80,0x19,0x15,0xab,0xcc,0x17,0x12,0xd0,0x82,0xf2,0x92,0xa6,0x3f,0xd9,0xaf,
0x71,0x54,0xa9,0x7c,0xc7,0x38,0x59,0xa4,0xbe,0x3c,0xba,0x35,0x9d,0x32,0x18,0x00,
0x4e,0x14,0xdf,0x02,0xd0,0x9e,0xdf,0x0a,0xd5,0x79,0x6b,0xb0,0x10,0x99,0x52,0x93,
0xab,0x5d,0x04,0x2c,0x31,0x05,0x53,0x80,0xcc,0x9c,0xb2,0xe3,0x61,0x79,0x82,0xc4,
0x5f,0x6b,0xce,0x1f,0xb8,0xa4,0x0e,0xf9,0xea,0xc4,0x8a,0xe1,0x77,0x20,0xdf,0xec,
0xc7,0x1e,0xc8,0x57,0xea,0x33,0xf3,0x2e,0xb3,0x46,0xba,0x60,0x36,0xe8,0xf9,0xcc,
0xd7,0xbc,0xad,0xc6,0xc1,0xab,0x92,0xa8,0x0c,0x57,0xe7,0x89,0x59,0xd8,0xb8,0x28),
.out = chunk_from_chars(
0x29,0xbd,0x11,0x55,0x68,0xae,0x09,0x88,0x27,0x0f,0xc3,0x86,0xd3,0x95,0xfe,0x37,
0x07,0xa4,0xd0,0x62,0x89,0xf3,0x52,0xbb,0xa4,0xc0,0x0a,0x9a,0xd8,0x55,0xa0,0x8d),
};
kdf_test_vector_t prf_sha384_1 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_384,
.key = chunk_from_chars(
0x4d,0xf0,0x40,0xb7,0x09,0x78,0x62,0x9c,0x49,0x43,0x7c,0xff,0x41,0xa0,0xd4,0x6c,
0xbe,0xa6,0x8c,0x8d,0x75,0xb3,0x70,0xff,0xc1,0x1d,0x7b,0x38,0x71,0x44,0xea,0x83,
0xbb,0x59,0x03,0xfb,0xb9,0x2e,0x47,0x3d,0xf5,0x0a,0x9b,0x19,0xea,0x43,0xe9,0xc2,
0xf3,0xda,0x9a,0x84,0x9c,0x03,0x86,0x42,0x76,0xc6,0xf2,0x64,0xec,0xf0,0x2a,0x60,
0xd4,0x0b,0xa6,0x5c,0x06,0x65,0x6b,0x63,0x3f,0x02,0xa8,0x74,0x27,0xe9,0x28,0xeb,
0x66,0xa2,0xda,0xbd,0x9d,0xc0,0x57,0x44,0x71,0x7b,0xca,0xf7,0xae,0x78,0xc2,0x96,
0x87,0x2f,0x5c,0x48,0xd1,0xa8,0x12,0x0c,0x21,0x55,0xb7,0x0c,0x56,0x5c,0xe2,0x71,
0x99,0x8e,0x3e,0x44,0xaf,0x26,0x3d,0x48,0x7e,0xa3,0xba,0x7f,0x56,0x13,0x2d,0x7d),
.salt = chunk_from_chars(
0xd6,0x72,0xb0,0xbc,0x85,0x28,0x29,0xb9,0x35,0x09,0xf3,0xb7,0x24,0x70,0x63,0x64),
.out = chunk_from_chars(
0x54,0x43,0x6a,0x9e,0xa9,0x5d,0x6f,0xf7,0x9b,0x96,0x7f,0x4b,0x07,0xf6,0xde,0x97,
0x6a,0x37,0x6e,0x8e,0xa2,0x6a,0xa9,0x57,0x47,0x09,0xaf,0xc6,0x02,0x43,0xc9,0xc1,
0x41,0xda,0x4c,0xa0,0xe1,0x58,0xe6,0x27,0xa7,0x5e,0xa8,0x7f,0x6f,0xeb,0x07,0xef),
};
kdf_test_vector_t prf_sha384_2 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_384,
.key = chunk_from_chars(
0xae,0x50,0x50,0x82,0xac,0x47,0xff,0x9a,0xa3,0x54,0xb7,0xaf,0x2b,0x07,0x2c,0xb4,
0x9c,0xec,0x83,0x8d,0x00,0xee,0x36,0x13,0x88,0x1a,0x99,0x77,0xb2,0x15,0x95,0x99,
0xa0,0x24,0x95,0xf0,0xe5,0x2d,0x96,0x1a,0x51,0x6c,0x6b,0xb6,0x1e,0xd0,0x3a,0x86,
0x37,0xbb,0x50,0x7c,0x5c,0x27,0xba,0xb5,0x8d,0xf1,0x54,0xe8,0xe5,0x01,0x48,0x21,
0x84,0x0c,0xfc,0x50,0xb3,0xa4,0x78,0xb4,0x5d,0xd1,0x68,0xeb,0x18,0x0d,0x69,0xcb,
0xa6,0x1a,0x1b,0x42,0x59,0x19,0x3a,0x51,0xa7,0xa4,0x95,0xc9,0x58,0x05,0x38,0x2e,
0x3a,0xbf,0x55,0x87,0x68,0x8f,0x34,0xb6,0x3f,0x71,0x16,0x39,0x82,0xde,0x3d,0xdf,
0x7f,0x26,0x3b,0xb6,0x9f,0x65,0xc3,0xec,0xae,0x61,0x65,0xbf,0x7f,0xdd,0x53,0x17),
.salt = chunk_from_chars(
0x9e,0x2a,0x62,0xf9,0x36,0x28,0x93,0xdd,0xf8,0x47,0x16,0xfe,0xc2,0xf2,0x3f,0x9d,
0xcb,0xd9,0x01,0x0d,0xf6,0xfe,0x9e,0x0e,0xb4,0x6d,0x03,0xd9,0x14,0xf3,0x04,0xd8,
0xfe,0x4d,0x3e,0xe2,0xd6,0xa0,0x3b,0x40,0xe5,0x6a,0x32,0x5e,0x82,0x2a,0x17,0x36,
0x19,0x29,0x18,0x4a,0xde,0x09,0xea,0xa4,0x45,0x27,0x8d,0x38,0x70,0x41,0x7a,0x7c,
0xf5,0x65,0x58,0x4f,0x57,0x2a,0xd3,0x4f,0xf7,0x2b,0xc7,0x78,0x1a,0x39,0xa4,0x8b,
0x54,0xb5,0x5d,0x6e,0xb0,0xed,0x68,0x55,0x1b,0x22,0x2c,0x7a,0xfa,0xda,0x0b,0xc8,
0x22,0x36,0xec,0x31,0xce,0x6c,0x04,0x6b,0x3b,0x2e,0xdb,0x2d,0xef,0x61,0xf4,0xd2,
0xd8,0x57,0xb2,0xd1,0xcb,0x36,0x96,0xc0,0x23,0xe0,0x8c,0x08,0xd6,0xab,0xd0,0x4d,
0x4f,0x69,0x09,0x2b,0x14,0x58,0x37,0x35,0xb9,0xe9,0x18,0xae,0xe5,0xa3,0x99,0x9d,
0xcb,0xf5,0x8f,0xda,0xd6,0xfc,0xd4,0x7c,0x95,0x92,0x98,0x77,0x03,0x0e,0x54,0xb7,
0x08,0x23,0x5f,0x2a,0x2e,0x11,0xe7,0xc5,0x85,0x84,0x61,0x9a,0xa2,0xfa,0x69,0x31,
0x53,0x44,0xd3,0x65,0x7b,0x55,0x72,0x0a,0x25,0xeb,0xe8,0x8e,0xa0,0x77,0x69,0x72,
0xc9,0xe2,0x24,0x69,0xb7,0xed,0x5d,0xa9,0x6b,0x3c,0x76,0x85,0xf7,0xb0,0x56,0x99,
0x60,0xbd,0x64,0x4f,0x13,0x0b,0x44,0xa0,0xd5,0x51,0xbb,0x0e,0x90,0x2e,0xd6,0x8a,
0xb3,0x84,0xfd,0xc2,0xfa,0xca,0xf7,0x9b,0xbf,0x8d,0x6d,0x37,0x36,0xdf,0xa9,0x52,
0xcd,0x70,0xf4,0x74,0x6f,0x1a,0x4a,0xea,0xc2,0xbd,0xbe,0xca,0x97,0xb7,0x8f,0xc1,
0x77,0x78,0x78,0xc1,0x28,0x59,0x43,0x35,0x52,0xa7,0x7d,0x7f,0x94,0x2e,0x5b,0x60,
0x47,0x69,0x91,0xa1,0xe3,0xd0,0x42,0x7c,0xd6,0x77,0x34,0x5a,0x1c,0xe2,0x06,0x3a,
0x2e,0x0e,0xc5,0x47,0xa9,0xd8,0x21,0xda,0x75,0x9f,0x1a,0x91,0xb5,0x88,0x17,0xbd,
0x0d,0xc4,0xef,0xfc,0x12,0x6f,0x6f,0x4e,0xb0,0xb9,0x11,0xe9,0x04,0xed,0x21,0xdc,
0x43,0x9d,0x65,0x8a,0x77,0x3f,0x97,0xe1,0x79,0xad,0x20,0xbc,0x3c,0x63,0x60,0x9f,
0x28,0x74,0x06,0x2e,0x83,0x5f,0x6a,0xe0,0x8d,0x59,0x65,0x4f,0x9c,0x88,0x61,0xe5,
0x27,0x03,0x9e,0xea,0xc3,0x2b,0x9e,0xed,0x29,0x3b,0xd8,0xb1,0xe0,0xe7,0xc6,0x7b,
0xf1,0xd7,0x55,0x24,0x6a,0x1b,0x06,0x3f,0xf0,0x06,0x32,0xa4,0x6d,0xd5,0xcf,0x69,
0x48,0xf0,0xee,0xd9,0xb6,0x5c,0x59,0x39,0xdf,0xd2,0x14,0x80,0xa6,0x3d,0xf0,0xca,
0xb0,0xa7,0x50,0x9c,0x42,0x45,0xa1,0xbe,0x75,0x47,0xcc,0xc6,0xf7,0x3c,0x72,0x4b,
0x48,0xb7,0x86,0x70,0x12,0xe0,0xca,0x3e,0x47,0x2e,0x0d,0x55,0x06,0x49,0xa7,0x34,
0x44,0x0f,0xef,0xfc,0x8e,0x73,0x68,0x2c,0xb6,0x04,0x53,0xe7,0xa4,0x7e,0x72,0xfe,
0x08,0x74,0xeb,0x40,0xac,0xd0,0xd4,0x8e,0x4e,0x57,0x19,0x74,0x16,0x11,0x2b,0xcd,
0xc8,0xbb,0x7a,0x58,0xbe,0xa7,0x45,0xfd,0xd6,0x4c,0x16,0xf6,0x66,0xc8,0x8d,0x9e,
0x3b,0xd2,0x35,0xb1,0x37,0x20,0x6f,0x6c,0xdb,0xa1,0x90,0xbe,0x65,0xec,0x03,0x3c,
0x19,0x1f,0x67,0x6b,0x42,0x8e,0xc1,0x20,0x5d,0xc5,0xe9,0x45,0x82,0x85,0x08,0xd8),
.out = chunk_from_chars(
0xff,0x66,0xe9,0xd0,0x92,0xdc,0x01,0xe0,0xb8,0x1f,0x93,0x9f,0x52,0xf5,0xc0,0x7d,
0x38,0xd8,0x05,0xb9,0x86,0x28,0xce,0x1a,0xc5,0xfe,0x94,0xc0,0x98,0x57,0x76,0x47,
0x33,0x9f,0xad,0x68,0x94,0x1f,0xfe,0x21,0xe0,0x1e,0xfb,0x4e,0x70,0x50,0x21,0x3b),
};
kdf_test_vector_t prf_sha512_1 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_512,
.key = chunk_from_chars(
0x1e,0x3b,0x00,0x7d,0x2d,0xa9,0x13,0xca,0x60,0xec,0xc9,0x8c,0x25,0xa2,0x2d,0xb0,
0x80,0x73,0xd5,0xc3,0x5c,0x11,0xb2,0x52,0x4b,0x29,0x8a,0x92,0x2b,0x6a,0xbf,0xe6,
0xac,0xf7,0x35,0x9d,0xb6,0x6a,0xe5,0xf8,0x5d,0x67,0xaa,0xcf,0xf6,0x86,0x41,0x9c,
0xd8,0x66,0x6d,0x05,0xae,0x79,0x77,0xce,0xfa,0xd7,0xf5,0x4d,0xd8,0xe3,0x12,0xa8,
0xe8,0xe5,0xe0,0x37,0x0f,0x88,0x14,0x2f,0xbd,0xd6,0x59,0xdd,0x6f,0xde,0x22,0xbd,
0xd5,0x31,0xf5,0x40,0x28,0x81,0xa8,0xde,0x85,0xc1,0x02,0x4e,0x59,0x5e,0xc9,0x3c,
0x57,0x56,0x18,0xaf,0x7f,0xd3,0xdb,0xac,0x79,0x82,0x91,0x90,0x78,0xd7,0x1c,0xc1,
0x3e,0xff,0x19,0x10,0xa0,0x32,0x75,0x0e,0x1f,0xf4,0x28,0x67,0x5d,0xe1,0x89,0xee),
.salt = chunk_from_chars(
0xdf,0x79,0x31,0xdb,0x9b,0x42,0x9e,0x10,0xb8,0xaa,0x8e,0x4d,0x46,0x04,0x23,0x93),
.out = chunk_from_chars(
0xda,0xf9,0xbd,0x6f,0x2f,0x91,0x2d,0xa5,0x53,0x86,0x79,0x66,0xaf,0x38,0x6e,0x67,
0x90,0x9a,0x8d,0xf0,0xca,0x7e,0x84,0xb8,0x3b,0x35,0x5c,0xb7,0xd7,0xf1,0x02,0x6f,
0x17,0xd8,0xea,0x34,0xb5,0xd5,0x7f,0xd0,0xd1,0xba,0x38,0x95,0x28,0xfc,0xa1,0xe8,
0x1d,0x1c,0x8c,0xe5,0x11,0xb2,0x8a,0x24,0x58,0x24,0x11,0x43,0xfe,0xe3,0x0c,0xcc),
};
kdf_test_vector_t prf_sha512_2 = {
.alg = KDF_PRF, .arg.prf = PRF_HMAC_SHA2_512,
.key = chunk_from_chars(
0x9c,0xb4,0xbf,0x24,0x46,0x17,0x0a,0xc3,0x81,0x02,0x52,0x66,0xa1,0xa4,0xb8,0x65,
0x13,0xdf,0x60,0xea,0x7d,0x07,0xb1,0xb2,0x13,0x9d,0x78,0xf3,0x31,0xef,0x7e,0xb7,
0xbe,0x8b,0x15,0xd8,0x6c,0xd8,0x5e,0x2a,0x6a,0x34,0xa5,0x58,0x69,0xf8,0xdc,0xc9,
0x75,0x4f,0x49,0x69,0x73,0x31,0xb9,0xb6,0x50,0xce,0x25,0x6e,0xdb,0x33,0x71,0xa9,
0x4b,0x7c,0x2a,0x13,0x2f,0x2f,0xc9,0x9d,0x22,0x30,0x37,0x17,0xc3,0x67,0x39,0xd1,
0x7c,0x0e,0x97,0x18,0xd7,0xc0,0x52,0xe7,0xab,0x4d,0x48,0x58,0xad,0xeb,0x9b,0x8b,
0x4d,0x33,0x03,0xa9,0xe1,0xb6,0xbe,0xf2,0x9f,0x03,0x03,0x5b,0xee,0xd0,0x71,0xd3,
0xbb,0x81,0x0d,0x85,0x39,0x71,0xa7,0x48,0xc5,0x6c,0x59,0xe0,0xba,0xfb,0x9b,0x5a),
.salt = chunk_from_chars(
0xd8,0x96,0x84,0xe3,0xcb,0x17,0xf3,0xaa,0xbd,0x85,0x3a,0x78,0xdb,0x3e,0xcd,0x5a,
0xac,0xc1,0xed,0x71,0xc7,0x0b,0x88,0xa2,0x97,0x56,0xf4,0x6f,0xc7,0x19,0x7c,0x80,
0x4e,0xc0,0x01,0x54,0x40,0x02,0xa8,0xae,0xa3,0x60,0x68,0x4b,0x18,0x00,0x6d,0xef,
0x0d,0xbd,0x86,0x33,0xb1,0x01,0x9f,0xbc,0xfa,0x85,0xb9,0x4c,0xac,0x2b,0xb8,0x21,
0x25,0x84,0xbe,0x62,0xad,0xab,0x0e,0xe4,0xbb,0x8a,0x36,0xae,0xe2,0x52,0x75,0xef,
0x07,0x13,0x90,0x48,0x0e,0xef,0xa2,0x09,0x2e,0xb3,0x08,0xaa,0x73,0x37,0xc5,0xce,
0xb6,0x06,0x9a,0xb6,0x90,0xe8,0x96,0x2f,0xbf,0xe0,0x98,0x6e,0x4f,0x5c,0x18,0xf4,
0x86,0x86,0x1e,0xd3,0xf1,0xdc,0xbe,0xe4,0xc9,0xe4,0xa7,0x66,0x9d,0x74,0x0c,0xa2,
0xb0,0xe8,0xed,0x40,0x31,0xb0,0xa4,0x99,0xdc,0x31,0x5c,0xed,0xe7,0xef,0x03,0x39,
0x9c,0xbc,0x33,0xdc,0xd6,0x29,0x70,0x34,0x9f,0x12,0x20,0x88,0x1b,0x55,0x45,0x2e,
0x0c,0x6c,0x9b,0x52,0xa8,0x8b,0x67,0xf5,0x97,0x58,0x67,0x95,0xb2,0x25,0x70,0x73,
0x3f,0xd4,0xff,0x2c,0xc2,0xad,0x93,0x1d,0x83,0x30,0x16,0x5a,0x9e,0x45,0x0e,0x38,
0x88,0x59,0xce,0x62,0x4f,0x01,0xdb,0x17,0xc2,0x50,0x2b,0x4e,0x66,0xad,0xf9,0x65,
0x27,0x36,0x3d,0x6f,0x90,0x6b,0x20,0x23,0xe8,0xed,0x74,0xd5,0xaf,0x0a,0xa6,0x02,
0x46,0xb0,0xb9,0x2f,0x49,0xc4,0x93,0x3e,0xf3,0x12,0xf8,0xa2,0x54,0x34,0xee,0x96,
0x98,0xd6,0xd9,0x20,0x43,0x45,0xbd,0x10,0xbb,0x11,0xaa,0x39,0x86,0x56,0x16,0xd5,
0xad,0x1b,0x57,0x44,0x70,0x6c,0xfd,0x4e,0xa1,0x40,0x8e,0x20,0xc8,0xfd,0xcf,0x85,
0x51,0xee,0xe8,0x81,0x4b,0x7b,0x37,0x33,0x0b,0x05,0x26,0xf0,0xbc,0x5e,0xe1,0x5d,
0x4e,0xcd,0xa7,0xa1,0xbd,0x25,0xaa,0x97,0xf2,0x45,0x84,0xd8,0x5d,0x3f,0x52,0x49,
0x69,0x4b,0x9f,0x43,0x53,0x9e,0x69,0xea,0x35,0xbf,0xe7,0xfd,0x44,0x07,0xbc,0x8e,
0x9d,0xca,0x8a,0x9f,0xae,0x4b,0xdc,0x6b,0x7b,0xb3,0x8c,0x6d,0x68,0xf8,0x99,0xe1,
0xd3,0x2c,0x85,0xbc,0xd6,0x17,0xa5,0x67,0x67,0x8c,0xf8,0x5d,0x22,0x17,0xa4,0xe8,
0x6a,0x75,0x56,0x24,0xb6,0x40,0x02,0x35,0x4c,0x02,0x68,0x42,0xbc,0x95,0x42,0x49,
0x1a,0xf1,0xc3,0xd6,0x29,0x09,0x70,0x55,0x9a,0xf1,0x1b,0xdc,0x2c,0x83,0xb5,0x4c,
0x74,0x14,0x49,0x05,0xc0,0xa3,0x58,0xf3,0x15,0x3d,0xb7,0x67,0xa5,0xda,0x2a,0x86,
0x27,0xf6,0x96,0x27,0xe1,0xd4,0x1e,0xde,0x9c,0x90,0x7c,0x79,0xb5,0x1f,0xf8,0x15,
0xe4,0x64,0x5c,0x33,0x75,0xe0,0xf6,0x3f,0x84,0xfc,0xf5,0xd7,0xc3,0x40,0x7a,0x1d,
0xd6,0x83,0x9e,0x19,0x06,0xa1,0xe3,0x80,0x2c,0xcf,0x5e,0x82,0x30,0xd9,0x5c,0xf4,
0xb8,0x27,0xb4,0x1c,0x48,0x34,0x25,0xa8,0xa6,0x0b,0xfa,0x51,0x89,0xda,0xc4,0x38,
0x06,0x0f,0x2f,0x5c,0xd5,0x26,0x66,0x2f,0x29,0x06,0xc1,0xdd,0x64,0xf4,0x84,0x4e,
0x94,0x2c,0xa8,0x4d,0xae,0xce,0x6d,0xd7,0xbb,0xf7,0x19,0x4d,0x8c,0xe5,0x6b,0xc2,
0x83,0x10,0x85,0xa7,0xd3,0x10,0xe4,0x94,0x4c,0xfa,0xe7,0x62,0x60,0xaa,0xbf,0x6b),
.out = chunk_from_chars(
0xe5,0x70,0xe7,0x48,0x46,0x34,0x30,0x0d,0x7a,0xdd,0xf5,0xa8,0x52,0x7c,0x13,0x8b,
0x76,0x96,0xdb,0xc3,0xd8,0xbe,0x09,0x69,0xb7,0x52,0x15,0x31,0x8a,0x11,0xad,0xa2,
0x13,0x53,0x8f,0x62,0x93,0xb0,0xee,0xe5,0xb3,0x09,0xad,0x8f,0x5d,0x8d,0x94,0xdb,
0xe5,0x73,0x61,0x27,0xe0,0xd2,0x56,0x0f,0x28,0x1c,0x9c,0x58,0x6b,0xf7,0xc8,0x6f),
};
@@ -0,0 +1,290 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <crypto/crypto_tester.h>
/**
* This is an old test vector derived from one in RFC 4868.
*/
kdf_test_vector_t prf_plus_sha256_old = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_256,
.key = chunk_from_chars(
0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
0x0b,0x0b,0x0b,0x0b),
.salt = chunk_from_chars(
0x48,0x69,0x20,0x54,0x68,0x65,0x72,0x65),
.out = chunk_from_chars(
0xb9,0xbd,0xc0,0x89,0x88,0xb4,0xc2,0xb7,0x5a,0xa9,0x3e,0x59,0x6a,0xc8,0x42,0x05,
0xfa,0x2d,0xdd,0xe1,0xbf,0x7a,0x25,0x72,0x06,0x7b,0x00,0xe1,0x4b,0x23,0x77,0x32,
0x83,0x05,0x09,0x98,0x1a,0xd2,0xf9,0x4a,0x8c,0x32,0xa4,0x7d,0xaa,0x22,0x55,0xb6,
0x60,0xc4,0x36,0x34,0x7a,0xe7,0x56,0xa6,0xed,0xc0,0x23,0x47,0x7d,0x80,0x95,0x90,
0xe6,0x82,0xf6,0x1d,0x9c,0x04,0xb0,0x6b,0x4a,0xd9,0x71,0xa3,0x4c,0x81,0x47,0xfa,
0x66,0x79,0x2f,0xf1,0x43,0x4b,0x93,0xc7,0x22,0xb3,0x2e,0x12,0xf4,0x88,0x32,0xeb,
0xc1,0x5c,0xe2,0x36,0x9c,0xe7,0x1f,0xe9,0xb7,0xb8,0x1e,0x57,0x04,0xc1,0x4d,0x0f,
0x52,0x80,0xa6,0xec,0x62,0x6e,0x99,0x2d,0x7a,0x9f),
};
/**
* The following test vectors are from CAVP/SP 800-135 for IKEv2.
*
* key = SKEYSEED, salt = Ni | Nr | SPIi | SPIr (one vector with min. and one
* with max. size for nonces)
*/
kdf_test_vector_t prf_plus_sha256_1 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_256,
.key = chunk_from_chars(
0x37,0xfd,0xe9,0x0b,0x81,0xd6,0x36,0x92,0x62,0x0f,0x67,0x36,0x7b,0x62,0x09,0x2e,
0x3e,0xfd,0xc6,0xa0,0x35,0x09,0x13,0x7d,0x73,0x10,0x04,0x76,0x7f,0xf3,0x50,0x10),
.salt = chunk_from_chars(
0xed,0x80,0xdc,0x79,0x91,0x2c,0x32,0xa9,0x35,0xfb,0x6d,0x1a,0x3f,0xea,0xc0,0x78,
0x47,0xc1,0x85,0x8e,0xfc,0x93,0x2e,0xa4,0x60,0x6f,0xd0,0x56,0x09,0x62,0x40,0x02),
.out = chunk_from_chars(
0x63,0xd0,0x18,0xa0,0x8f,0x7a,0x29,0xda,0xa7,0xd1,0xf9,0x2c,0xb6,0x3f,0x45,0xfa,
0x39,0xbb,0xaf,0x5e,0x5f,0x1a,0x78,0x13,0x96,0x13,0xbb,0x89,0x1e,0x3e,0x6b,0xf9,
0xd0,0x44,0x8f,0x7c,0x74,0xe0,0x5b,0x4c,0x1a,0x25,0xc0,0xb6,0x1e,0x62,0xc8,0x75,
0xe8,0x52,0xf2,0x87,0xe1,0x92,0xd4,0xae,0x53,0x61,0x12,0xdb,0x51,0x97,0x21,0x64,
0x00,0xbd,0x5e,0x12,0x34,0x70,0xef,0xc1,0x5f,0x53,0x16,0x18,0x65,0xfe,0x8b,0x19,
0xa1,0x41,0x65,0x18,0xa1,0x57,0xd6,0x51,0xec,0xd2,0xca,0xdd,0xab,0x6a,0x9e,0xae,
0x6a,0x27,0xa5,0x5a,0xf0,0x88,0x21,0x8d,0x51,0x56,0xed,0xaa,0x97,0x89,0xf9,0x34,
0xd9,0x83,0x6e,0xd4,0x3e,0xdf,0xfd,0xa5,0x53,0x82,0x22,0x02,0xff,0x9f,0x7d,0x48,
0x60,0xca,0x72,0xe0),
};
kdf_test_vector_t prf_plus_sha256_2 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_256,
.key = chunk_from_chars(
0x29,0xbd,0x11,0x55,0x68,0xae,0x09,0x88,0x27,0x0f,0xc3,0x86,0xd3,0x95,0xfe,0x37,
0x07,0xa4,0xd0,0x62,0x89,0xf3,0x52,0xbb,0xa4,0xc0,0x0a,0x9a,0xd8,0x55,0xa0,0x8d),
.salt = chunk_from_chars(
0xef,0xa7,0x29,0x13,0x18,0x22,0x78,0xff,0xbd,0x14,0xe7,0x89,0x20,0xc0,0x62,0x51,
0x9a,0xba,0xb8,0xc1,0x6e,0x5e,0xd7,0x0c,0x08,0x41,0xa4,0x8c,0xdb,0x98,0x23,0x7e,
0xe9,0x3f,0x73,0x5f,0xb2,0xdf,0x18,0x43,0x58,0xaa,0xdc,0x13,0xd8,0x3f,0x43,0xfe,
0x8d,0x87,0x05,0x17,0x6c,0x8c,0xa3,0x13,0x82,0x5a,0x1b,0xcd,0xf7,0x79,0x11,0xc5,
0x98,0x00,0x16,0x71,0xff,0xbf,0x01,0x4e,0x37,0xa8,0xc0,0x4d,0x49,0xa7,0x83,0x9d,
0xfe,0xa6,0xcd,0xc5,0x87,0x68,0x8d,0x45,0x88,0xfe,0x43,0x23,0x5b,0x71,0x69,0x3f,
0xfd,0x07,0x29,0x33,0x86,0xb6,0xbf,0x4c,0x19,0x9e,0x33,0x61,0x65,0xb2,0x60,0x78,
0x77,0x36,0xf5,0x4b,0xe9,0x5d,0xb6,0x91,0x16,0x38,0x8b,0xc2,0xec,0xa2,0xb3,0xb2,
0x94,0x84,0x71,0x74,0x17,0xbb,0x3c,0x71,0x81,0x4c,0xe1,0x3b,0x84,0x44,0x6d,0xc3,
0x96,0x4c,0x30,0x29,0x84,0xf9,0x77,0x81,0xf6,0x31,0x66,0x24,0x08,0x90,0x10,0x7c,
0x2e,0x75,0x1a,0x00,0x43,0x6f,0x7c,0x3c,0x9f,0xf1,0x27,0x60,0xe4,0x9d,0x91,0x56,
0x3b,0xe6,0x03,0xfd,0x96,0x41,0xa0,0xa6,0x49,0x18,0xa9,0x32,0x91,0xed,0x11,0x3d,
0xb1,0x2f,0x97,0x07,0x60,0x9d,0x17,0x20,0x96,0xeb,0x58,0xf9,0x15,0x44,0x74,0xda,
0x40,0xc1,0xf5,0xc0,0x90,0x3e,0x9c,0xa2,0xf9,0x1b,0xa6,0x60,0x07,0x75,0xdf,0x71,
0x66,0xca,0xf8,0xe3,0x27,0x85,0x9e,0x67,0x62,0x32,0xd3,0x40,0x46,0x04,0x4c,0xee,
0x43,0xf9,0x01,0x9f,0x04,0x68,0x56,0x12,0x63,0x5b,0x99,0xcb,0xeb,0xcb,0x36,0x3d,
0x56,0x5e,0xaf,0x0e,0x54,0x7e,0xec,0xb9,0x41,0xc9,0x94,0xdf,0xd4,0x71,0xed,0x56,
0x43,0xc0,0x87,0x74,0x4f,0x77,0x09,0xcc,0x3e,0x25,0x10,0xf2,0x74,0x26,0xc6,0x2c,
0x0f,0xf3,0xac,0xb3,0xc2,0x76,0x61,0xd2,0x6a,0x6d,0x83,0xc2,0xa2,0x5e,0x13,0xa6,
0xd4,0x65,0xbd,0x04,0x7f,0x90,0x55,0x00,0xe5,0xeb,0xbe,0x42,0x66,0x43,0x0d,0x56,
0x67,0x14,0x0f,0x77,0xe7,0x97,0x71,0x2a,0x8c,0x8f,0x63,0xc5,0x83,0xf4,0xb4,0x64,
0x9b,0x72,0x89,0x9e,0xa3,0x4a,0xbf,0xdb,0x17,0x61,0x7c,0x46,0x0c,0x35,0xf2,0x50,
0x64,0x94,0x49,0x4f,0x22,0x3e,0x25,0x1a,0xc7,0x1a,0x5b,0x9b,0x7e,0xea,0x87,0xf4,
0xf5,0xe3,0x33,0xa3,0xc1,0xbb,0xb4,0xbb,0x09,0x25,0x8b,0x6a,0x4b,0x5f,0x8c,0x9f,
0xb8,0x2b,0xf4,0x2d,0xa9,0xd4,0xa4,0x65,0x43,0xc6,0xa9,0xeb,0x9a,0xa3,0x0e,0xa9,
0xda,0x80,0x19,0x15,0xab,0xcc,0x17,0x12,0xd0,0x82,0xf2,0x92,0xa6,0x3f,0xd9,0xaf,
0x71,0x54,0xa9,0x7c,0xc7,0x38,0x59,0xa4,0xbe,0x3c,0xba,0x35,0x9d,0x32,0x18,0x00,
0x4e,0x14,0xdf,0x02,0xd0,0x9e,0xdf,0x0a,0xd5,0x79,0x6b,0xb0,0x10,0x99,0x52,0x93,
0xab,0x5d,0x04,0x2c,0x31,0x05,0x53,0x80,0xcc,0x9c,0xb2,0xe3,0x61,0x79,0x82,0xc4,
0x5f,0x6b,0xce,0x1f,0xb8,0xa4,0x0e,0xf9,0xea,0xc4,0x8a,0xe1,0x77,0x20,0xdf,0xec,
0xc7,0x1e,0xc8,0x57,0xea,0x33,0xf3,0x2e,0xb3,0x46,0xba,0x60,0x36,0xe8,0xf9,0xcc,
0xd7,0xbc,0xad,0xc6,0xc1,0xab,0x92,0xa8,0x0c,0x57,0xe7,0x89,0x59,0xd8,0xb8,0x28,
0x57,0xe9,0x1d,0xf9,0xc5,0xff,0xb8,0x42,0x4d,0x5e,0xad,0xac,0x0e,0x57,0x0f,0x7c),
.out = chunk_from_chars(
0xd5,0x03,0x3d,0x08,0x79,0x34,0xc6,0x15,0x38,0xb2,0x3d,0xff,0x87,0x5b,0x3b,0xa9,
0x20,0xe0,0x5c,0x1b,0x42,0xac,0x7f,0x97,0x93,0x99,0x5e,0x76,0xba,0x3e,0x46,0x1d,
0x6e,0x83,0xb2,0xfb,0xe0,0xfa,0x68,0x1b,0xa2,0x85,0x69,0x6d,0x53,0xb1,0x75,0xe0,
0x70,0xc4,0xc1,0xcb,0xc7,0x40,0x43,0xf7,0xca,0xc5,0x58,0xc4,0x94,0xac,0xd2,0x3a,
0xab,0xfc,0x7a,0x68,0x5b,0x62,0x74,0x13,0x44,0x08,0xca,0xfc,0x16,0x92,0x85,0x2a,
0xca,0x66,0x3c,0xef,0xd7,0xdd,0x0c,0x8a,0x87,0x2a,0x36,0xa1,0x41,0x4d,0xb4,0xb7,
0xf3,0x14,0xad,0x0e,0x49,0xf2,0xc1,0x87,0x16,0x2e,0x28,0x76,0xc6,0x05,0x3d,0xbe,
0xf5,0xa2,0xea,0x8c,0x33,0xdc,0xd3,0xdd,0x91,0x68,0x76,0x44,0x37,0x7c,0x45,0xf4,
0xb5,0xc4,0x18,0xe1,0xe1,0x0b,0xec,0x22,0xba,0xac,0x31,0x3b,0x90,0x2b,0xdf,0xfc,
0xfb,0x69,0xc6,0x8e,0xf4,0xe7,0x1c,0x5a,0xcc,0x39,0xa9,0xf0,0x7a,0xcb,0x1f,0xc3,
0xba,0x8e,0x92,0xc6,0xdc,0xa8,0x61,0xa6,0x41,0x63,0xb0,0x68,0x9d,0xa4,0xa9,0x7f,
0x12,0x40,0x26,0x36,0x09,0x90,0xc9,0xf1,0xae,0x4e,0x8d,0x02,0x98,0xf0,0x77,0xfc,
0xbb,0x0c,0x20,0x3f,0xd2,0xca,0x82,0x1d,0xea,0xb0,0x59,0x1a,0x22,0x1d,0x9d,0x0a,
0x79,0x8d,0x02,0xf0,0x78,0xd8,0xfb,0x6e,0x93,0x1c,0xa4,0x46,0xa1,0x3f,0x11,0x63,
0x8c,0x6b,0x6a,0xfb,0x82,0x25,0xa0,0x08,0xf9,0x38,0xa6,0x87,0x8c,0x5b,0x57,0x7e,
0x03,0xae,0xcf,0xa7,0x31,0x41,0x01,0xed,0xd0,0xfd,0xa3,0xbd,0xbe,0xa4,0x98,0x5c),
};
kdf_test_vector_t prf_plus_sha384_1 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_384,
.key = chunk_from_chars(
0x54,0x43,0x6a,0x9e,0xa9,0x5d,0x6f,0xf7,0x9b,0x96,0x7f,0x4b,0x07,0xf6,0xde,0x97,
0x6a,0x37,0x6e,0x8e,0xa2,0x6a,0xa9,0x57,0x47,0x09,0xaf,0xc6,0x02,0x43,0xc9,0xc1,
0x41,0xda,0x4c,0xa0,0xe1,0x58,0xe6,0x27,0xa7,0x5e,0xa8,0x7f,0x6f,0xeb,0x07,0xef),
.salt = chunk_from_chars(
0xd6,0x72,0xb0,0xbc,0x85,0x28,0x29,0xb9,0x35,0x09,0xf3,0xb7,0x24,0x70,0x63,0x64,
0x0f,0x9a,0x01,0x6d,0x7b,0x22,0x22,0x3c,0x85,0xf7,0x10,0xda,0xf8,0xb9,0x82,0xd8),
.out = chunk_from_chars(
0x10,0xb0,0x0a,0x65,0x46,0x43,0xb3,0xb9,0x85,0x76,0x4f,0x86,0xe2,0x3e,0xf6,0x24,
0x31,0x12,0x2f,0xcc,0x96,0xde,0x16,0xe3,0x38,0xa3,0x72,0xbe,0xe4,0x93,0x91,0xdb,
0x1f,0x83,0xa7,0x35,0x8c,0x08,0x03,0x80,0xab,0xbf,0x4a,0xf4,0x7c,0xdb,0x83,0xb9,
0x53,0x03,0x43,0x16,0x8f,0x7d,0xbc,0x92,0x21,0x26,0x0e,0x15,0x46,0xc6,0xb3,0x83,
0xe2,0x23,0x5d,0x27,0x05,0xa7,0x27,0xf0,0xb4,0x1a,0xeb,0xf6,0xa1,0xb4,0xc6,0x1c,
0xb4,0x60,0x66,0x01,0x52,0xa1,0x7b,0xa7,0x4c,0x20,0xd5,0x19,0x1b,0xa6,0x84,0x17,
0x94,0x94,0x52,0x70,0xd8,0x29,0x58,0x7b,0x7f,0x32,0x94,0x63,0x9e,0xa7,0xb7,0x71,
0x49,0xe1,0xd0,0x72,0x30,0xac,0x16,0xe0,0xcd,0x5a,0xb2,0x36,0xfa,0x32,0x12,0xbd,
0x56,0x9e,0xe7,0x0f),
};
kdf_test_vector_t prf_plus_sha384_2 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_384,
.key = chunk_from_chars(
0xff,0x66,0xe9,0xd0,0x92,0xdc,0x01,0xe0,0xb8,0x1f,0x93,0x9f,0x52,0xf5,0xc0,0x7d,
0x38,0xd8,0x05,0xb9,0x86,0x28,0xce,0x1a,0xc5,0xfe,0x94,0xc0,0x98,0x57,0x76,0x47,
0x33,0x9f,0xad,0x68,0x94,0x1f,0xfe,0x21,0xe0,0x1e,0xfb,0x4e,0x70,0x50,0x21,0x3b),
.salt = chunk_from_chars(
0x9e,0x2a,0x62,0xf9,0x36,0x28,0x93,0xdd,0xf8,0x47,0x16,0xfe,0xc2,0xf2,0x3f,0x9d,
0xcb,0xd9,0x01,0x0d,0xf6,0xfe,0x9e,0x0e,0xb4,0x6d,0x03,0xd9,0x14,0xf3,0x04,0xd8,
0xfe,0x4d,0x3e,0xe2,0xd6,0xa0,0x3b,0x40,0xe5,0x6a,0x32,0x5e,0x82,0x2a,0x17,0x36,
0x19,0x29,0x18,0x4a,0xde,0x09,0xea,0xa4,0x45,0x27,0x8d,0x38,0x70,0x41,0x7a,0x7c,
0xf5,0x65,0x58,0x4f,0x57,0x2a,0xd3,0x4f,0xf7,0x2b,0xc7,0x78,0x1a,0x39,0xa4,0x8b,
0x54,0xb5,0x5d,0x6e,0xb0,0xed,0x68,0x55,0x1b,0x22,0x2c,0x7a,0xfa,0xda,0x0b,0xc8,
0x22,0x36,0xec,0x31,0xce,0x6c,0x04,0x6b,0x3b,0x2e,0xdb,0x2d,0xef,0x61,0xf4,0xd2,
0xd8,0x57,0xb2,0xd1,0xcb,0x36,0x96,0xc0,0x23,0xe0,0x8c,0x08,0xd6,0xab,0xd0,0x4d,
0x4f,0x69,0x09,0x2b,0x14,0x58,0x37,0x35,0xb9,0xe9,0x18,0xae,0xe5,0xa3,0x99,0x9d,
0xcb,0xf5,0x8f,0xda,0xd6,0xfc,0xd4,0x7c,0x95,0x92,0x98,0x77,0x03,0x0e,0x54,0xb7,
0x08,0x23,0x5f,0x2a,0x2e,0x11,0xe7,0xc5,0x85,0x84,0x61,0x9a,0xa2,0xfa,0x69,0x31,
0x53,0x44,0xd3,0x65,0x7b,0x55,0x72,0x0a,0x25,0xeb,0xe8,0x8e,0xa0,0x77,0x69,0x72,
0xc9,0xe2,0x24,0x69,0xb7,0xed,0x5d,0xa9,0x6b,0x3c,0x76,0x85,0xf7,0xb0,0x56,0x99,
0x60,0xbd,0x64,0x4f,0x13,0x0b,0x44,0xa0,0xd5,0x51,0xbb,0x0e,0x90,0x2e,0xd6,0x8a,
0xb3,0x84,0xfd,0xc2,0xfa,0xca,0xf7,0x9b,0xbf,0x8d,0x6d,0x37,0x36,0xdf,0xa9,0x52,
0xcd,0x70,0xf4,0x74,0x6f,0x1a,0x4a,0xea,0xc2,0xbd,0xbe,0xca,0x97,0xb7,0x8f,0xc1,
0x77,0x78,0x78,0xc1,0x28,0x59,0x43,0x35,0x52,0xa7,0x7d,0x7f,0x94,0x2e,0x5b,0x60,
0x47,0x69,0x91,0xa1,0xe3,0xd0,0x42,0x7c,0xd6,0x77,0x34,0x5a,0x1c,0xe2,0x06,0x3a,
0x2e,0x0e,0xc5,0x47,0xa9,0xd8,0x21,0xda,0x75,0x9f,0x1a,0x91,0xb5,0x88,0x17,0xbd,
0x0d,0xc4,0xef,0xfc,0x12,0x6f,0x6f,0x4e,0xb0,0xb9,0x11,0xe9,0x04,0xed,0x21,0xdc,
0x43,0x9d,0x65,0x8a,0x77,0x3f,0x97,0xe1,0x79,0xad,0x20,0xbc,0x3c,0x63,0x60,0x9f,
0x28,0x74,0x06,0x2e,0x83,0x5f,0x6a,0xe0,0x8d,0x59,0x65,0x4f,0x9c,0x88,0x61,0xe5,
0x27,0x03,0x9e,0xea,0xc3,0x2b,0x9e,0xed,0x29,0x3b,0xd8,0xb1,0xe0,0xe7,0xc6,0x7b,
0xf1,0xd7,0x55,0x24,0x6a,0x1b,0x06,0x3f,0xf0,0x06,0x32,0xa4,0x6d,0xd5,0xcf,0x69,
0x48,0xf0,0xee,0xd9,0xb6,0x5c,0x59,0x39,0xdf,0xd2,0x14,0x80,0xa6,0x3d,0xf0,0xca,
0xb0,0xa7,0x50,0x9c,0x42,0x45,0xa1,0xbe,0x75,0x47,0xcc,0xc6,0xf7,0x3c,0x72,0x4b,
0x48,0xb7,0x86,0x70,0x12,0xe0,0xca,0x3e,0x47,0x2e,0x0d,0x55,0x06,0x49,0xa7,0x34,
0x44,0x0f,0xef,0xfc,0x8e,0x73,0x68,0x2c,0xb6,0x04,0x53,0xe7,0xa4,0x7e,0x72,0xfe,
0x08,0x74,0xeb,0x40,0xac,0xd0,0xd4,0x8e,0x4e,0x57,0x19,0x74,0x16,0x11,0x2b,0xcd,
0xc8,0xbb,0x7a,0x58,0xbe,0xa7,0x45,0xfd,0xd6,0x4c,0x16,0xf6,0x66,0xc8,0x8d,0x9e,
0x3b,0xd2,0x35,0xb1,0x37,0x20,0x6f,0x6c,0xdb,0xa1,0x90,0xbe,0x65,0xec,0x03,0x3c,
0x19,0x1f,0x67,0x6b,0x42,0x8e,0xc1,0x20,0x5d,0xc5,0xe9,0x45,0x82,0x85,0x08,0xd8,
0x6f,0xd4,0xbc,0x62,0x54,0x02,0xaa,0x68,0x5f,0x60,0x72,0x5e,0xfd,0xb4,0x25,0x96),
.out = chunk_from_chars(
0x28,0x10,0x28,0x8a,0x45,0xa5,0x02,0x21,0x1f,0xea,0xde,0x99,0x43,0xb4,0x22,0x4a,
0x3f,0x54,0xcf,0x97,0xf1,0x91,0xb6,0x21,0xd8,0x0a,0x19,0xf3,0xf1,0xb0,0x36,0x6d,
0x5e,0xd7,0x3d,0x19,0x5b,0x73,0x2a,0x15,0xb5,0x99,0x05,0x1a,0x13,0xb7,0xc5,0x84,
0x17,0x55,0x21,0xe3,0xa9,0x7c,0xdb,0x22,0x0c,0x89,0x24,0xb0,0xec,0x23,0x4a,0x94,
0x2e,0x05,0x79,0x67,0x5f,0x19,0x39,0x26,0xab,0x33,0x29,0x70,0x58,0x55,0x53,0xe2,
0x30,0xe3,0x42,0x9c,0x6e,0x8b,0xa7,0x1b,0x93,0x74,0xbd,0x4a,0x8d,0xf9,0x69,0x45,
0x68,0x40,0x52,0x7f,0x2c,0xf6,0x35,0x39,0x2b,0xe9,0xc1,0x7c,0xa8,0x47,0x4c,0xf0,
0x1b,0x33,0x2b,0x81,0x08,0xb5,0x4c,0x48,0xaa,0xfc,0x86,0xac,0x4c,0xfc,0xe7,0x05,
0x8e,0xe1,0x14,0x54,0x0e,0x5a,0x1b,0x95,0x22,0x01,0xee,0x3d,0x0a,0xc9,0xd3,0xe3,
0x3f,0x01,0x80,0x75,0x84,0x33,0x9a,0xc3,0xf4,0x3c,0xcd,0xd3,0x95,0xc5,0x8b,0xb3,
0xf4,0xa4,0xcc,0x5c,0x57,0x87,0x1e,0xa1,0xd3,0xea,0xa8,0xd0,0x30,0x2b,0xb3,0x08,
0xd1,0xd2,0x03,0xaf,0x13,0x14,0x7e,0x87,0xab,0x2b,0x91,0x59,0xae,0x36,0x1e,0xc0,
0x11,0xd6,0x73,0xfe,0x3f,0x16,0x2b,0x39,0x89,0xda,0x34,0x88,0xd8,0xff,0xea,0x2b,
0x51,0xe7,0x46,0x5f,0xad,0xdc,0xa6,0x7d,0x1d,0x54,0xc8,0x94,0x0a,0x8a,0xb6,0x2e,
0x8a,0xbe,0x41,0x45,0xcb,0x25,0x15,0x91,0x25,0x95,0x01,0x19,0xe3,0xc0,0x1a,0x81,
0x35,0x75,0xf0,0xa9,0x59,0xb1,0x43,0xbc,0x31,0xf6,0x2b,0x47,0x34,0xaa,0x45,0xe2),
};
kdf_test_vector_t prf_plus_sha512_1 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_512,
.key = chunk_from_chars(
0xda,0xf9,0xbd,0x6f,0x2f,0x91,0x2d,0xa5,0x53,0x86,0x79,0x66,0xaf,0x38,0x6e,0x67,
0x90,0x9a,0x8d,0xf0,0xca,0x7e,0x84,0xb8,0x3b,0x35,0x5c,0xb7,0xd7,0xf1,0x02,0x6f,
0x17,0xd8,0xea,0x34,0xb5,0xd5,0x7f,0xd0,0xd1,0xba,0x38,0x95,0x28,0xfc,0xa1,0xe8,
0x1d,0x1c,0x8c,0xe5,0x11,0xb2,0x8a,0x24,0x58,0x24,0x11,0x43,0xfe,0xe3,0x0c,0xcc),
.salt = chunk_from_chars(
0xdf,0x79,0x31,0xdb,0x9b,0x42,0x9e,0x10,0xb8,0xaa,0x8e,0x4d,0x46,0x04,0x23,0x93,
0x9b,0xa4,0x0a,0xf9,0x15,0x7f,0x47,0x92,0x53,0x83,0xc7,0xcd,0x3d,0x10,0x46,0xe6),
.out = chunk_from_chars(
0x91,0x9a,0x75,0xde,0xae,0xcc,0xbd,0x39,0x3b,0xeb,0xc8,0x96,0x15,0xf8,0xa2,0x15,
0xed,0xb7,0x07,0x3b,0x23,0x19,0xd8,0x67,0x40,0x22,0x1e,0xee,0x7a,0x2d,0xeb,0x92,
0x50,0x90,0x44,0xd7,0xe6,0x1f,0xcb,0x1b,0xf9,0x67,0x6b,0x38,0x81,0xc7,0xce,0xd4,
0x9e,0x6b,0xba,0x15,0x49,0xda,0x31,0x13,0x60,0x16,0x77,0xa2,0x44,0x5d,0x91,0xac,
0x13,0xa5,0x97,0x33,0x57,0x82,0xdd,0x3a,0x9c,0xf4,0x96,0xd9,0xe1,0x9b,0x93,0x2f,
0x27,0xdd,0x35,0xe3,0x6f,0x80,0x70,0xd2,0x32,0xd0,0xa3,0xb3,0xf4,0xc4,0xa0,0xb4,
0xba,0x44,0x70,0x77,0x8d,0xc0,0x90,0xf3,0x1f,0x52,0xab,0x1b,0x6d,0x81,0xe4,0xc7,
0xdf,0xb3,0x50,0x63,0xad,0x96,0xc3,0x27,0xad,0xcd,0xbd,0xe7,0x14,0xcc,0x9a,0x6b,
0x5e,0xf0,0x49,0xb8),
};
kdf_test_vector_t prf_plus_sha512_2 = {
.alg = KDF_PRF_PLUS, .arg.prf = PRF_HMAC_SHA2_512,
.key = chunk_from_chars(
0xe5,0x70,0xe7,0x48,0x46,0x34,0x30,0x0d,0x7a,0xdd,0xf5,0xa8,0x52,0x7c,0x13,0x8b,
0x76,0x96,0xdb,0xc3,0xd8,0xbe,0x09,0x69,0xb7,0x52,0x15,0x31,0x8a,0x11,0xad,0xa2,
0x13,0x53,0x8f,0x62,0x93,0xb0,0xee,0xe5,0xb3,0x09,0xad,0x8f,0x5d,0x8d,0x94,0xdb,
0xe5,0x73,0x61,0x27,0xe0,0xd2,0x56,0x0f,0x28,0x1c,0x9c,0x58,0x6b,0xf7,0xc8,0x6f),
.salt = chunk_from_chars(
0xd8,0x96,0x84,0xe3,0xcb,0x17,0xf3,0xaa,0xbd,0x85,0x3a,0x78,0xdb,0x3e,0xcd,0x5a,
0xac,0xc1,0xed,0x71,0xc7,0x0b,0x88,0xa2,0x97,0x56,0xf4,0x6f,0xc7,0x19,0x7c,0x80,
0x4e,0xc0,0x01,0x54,0x40,0x02,0xa8,0xae,0xa3,0x60,0x68,0x4b,0x18,0x00,0x6d,0xef,
0x0d,0xbd,0x86,0x33,0xb1,0x01,0x9f,0xbc,0xfa,0x85,0xb9,0x4c,0xac,0x2b,0xb8,0x21,
0x25,0x84,0xbe,0x62,0xad,0xab,0x0e,0xe4,0xbb,0x8a,0x36,0xae,0xe2,0x52,0x75,0xef,
0x07,0x13,0x90,0x48,0x0e,0xef,0xa2,0x09,0x2e,0xb3,0x08,0xaa,0x73,0x37,0xc5,0xce,
0xb6,0x06,0x9a,0xb6,0x90,0xe8,0x96,0x2f,0xbf,0xe0,0x98,0x6e,0x4f,0x5c,0x18,0xf4,
0x86,0x86,0x1e,0xd3,0xf1,0xdc,0xbe,0xe4,0xc9,0xe4,0xa7,0x66,0x9d,0x74,0x0c,0xa2,
0xb0,0xe8,0xed,0x40,0x31,0xb0,0xa4,0x99,0xdc,0x31,0x5c,0xed,0xe7,0xef,0x03,0x39,
0x9c,0xbc,0x33,0xdc,0xd6,0x29,0x70,0x34,0x9f,0x12,0x20,0x88,0x1b,0x55,0x45,0x2e,
0x0c,0x6c,0x9b,0x52,0xa8,0x8b,0x67,0xf5,0x97,0x58,0x67,0x95,0xb2,0x25,0x70,0x73,
0x3f,0xd4,0xff,0x2c,0xc2,0xad,0x93,0x1d,0x83,0x30,0x16,0x5a,0x9e,0x45,0x0e,0x38,
0x88,0x59,0xce,0x62,0x4f,0x01,0xdb,0x17,0xc2,0x50,0x2b,0x4e,0x66,0xad,0xf9,0x65,
0x27,0x36,0x3d,0x6f,0x90,0x6b,0x20,0x23,0xe8,0xed,0x74,0xd5,0xaf,0x0a,0xa6,0x02,
0x46,0xb0,0xb9,0x2f,0x49,0xc4,0x93,0x3e,0xf3,0x12,0xf8,0xa2,0x54,0x34,0xee,0x96,
0x98,0xd6,0xd9,0x20,0x43,0x45,0xbd,0x10,0xbb,0x11,0xaa,0x39,0x86,0x56,0x16,0xd5,
0xad,0x1b,0x57,0x44,0x70,0x6c,0xfd,0x4e,0xa1,0x40,0x8e,0x20,0xc8,0xfd,0xcf,0x85,
0x51,0xee,0xe8,0x81,0x4b,0x7b,0x37,0x33,0x0b,0x05,0x26,0xf0,0xbc,0x5e,0xe1,0x5d,
0x4e,0xcd,0xa7,0xa1,0xbd,0x25,0xaa,0x97,0xf2,0x45,0x84,0xd8,0x5d,0x3f,0x52,0x49,
0x69,0x4b,0x9f,0x43,0x53,0x9e,0x69,0xea,0x35,0xbf,0xe7,0xfd,0x44,0x07,0xbc,0x8e,
0x9d,0xca,0x8a,0x9f,0xae,0x4b,0xdc,0x6b,0x7b,0xb3,0x8c,0x6d,0x68,0xf8,0x99,0xe1,
0xd3,0x2c,0x85,0xbc,0xd6,0x17,0xa5,0x67,0x67,0x8c,0xf8,0x5d,0x22,0x17,0xa4,0xe8,
0x6a,0x75,0x56,0x24,0xb6,0x40,0x02,0x35,0x4c,0x02,0x68,0x42,0xbc,0x95,0x42,0x49,
0x1a,0xf1,0xc3,0xd6,0x29,0x09,0x70,0x55,0x9a,0xf1,0x1b,0xdc,0x2c,0x83,0xb5,0x4c,
0x74,0x14,0x49,0x05,0xc0,0xa3,0x58,0xf3,0x15,0x3d,0xb7,0x67,0xa5,0xda,0x2a,0x86,
0x27,0xf6,0x96,0x27,0xe1,0xd4,0x1e,0xde,0x9c,0x90,0x7c,0x79,0xb5,0x1f,0xf8,0x15,
0xe4,0x64,0x5c,0x33,0x75,0xe0,0xf6,0x3f,0x84,0xfc,0xf5,0xd7,0xc3,0x40,0x7a,0x1d,
0xd6,0x83,0x9e,0x19,0x06,0xa1,0xe3,0x80,0x2c,0xcf,0x5e,0x82,0x30,0xd9,0x5c,0xf4,
0xb8,0x27,0xb4,0x1c,0x48,0x34,0x25,0xa8,0xa6,0x0b,0xfa,0x51,0x89,0xda,0xc4,0x38,
0x06,0x0f,0x2f,0x5c,0xd5,0x26,0x66,0x2f,0x29,0x06,0xc1,0xdd,0x64,0xf4,0x84,0x4e,
0x94,0x2c,0xa8,0x4d,0xae,0xce,0x6d,0xd7,0xbb,0xf7,0x19,0x4d,0x8c,0xe5,0x6b,0xc2,
0x83,0x10,0x85,0xa7,0xd3,0x10,0xe4,0x94,0x4c,0xfa,0xe7,0x62,0x60,0xaa,0xbf,0x6b,
0x60,0x9d,0x88,0x78,0x9b,0x8a,0x1a,0xbf,0x50,0x01,0x86,0xc3,0xd9,0x7e,0xd2,0xab),
.out = chunk_from_chars(
0x98,0x7f,0xad,0xd8,0x04,0x99,0x45,0x67,0xd5,0x7f,0x98,0x9b,0x6c,0xda,0x66,0xef,
0xbf,0xfc,0xab,0x28,0xac,0x3e,0x3b,0xc6,0x10,0x78,0x05,0x95,0x4e,0xb1,0xea,0xd0,
0xce,0xa6,0xfb,0x49,0xaa,0x96,0x1c,0xbe,0x98,0xfd,0xad,0x57,0xdd,0x9c,0x45,0x56,
0x7c,0xe4,0x96,0x74,0x78,0x62,0xf8,0x8b,0xcd,0x9f,0xc5,0x75,0x59,0xa0,0x7e,0xa9,
0x27,0xa4,0x20,0x82,0xba,0x87,0xe0,0xf5,0x1b,0x3d,0x5b,0x8c,0xbd,0xea,0xdd,0xed,
0xa3,0xae,0x4c,0x73,0xb1,0xa5,0x1d,0xd0,0xdc,0xe3,0xcc,0x8e,0xb3,0xb1,0x41,0x9b,
0x93,0xf2,0x9d,0xc6,0x52,0x2b,0x2f,0x5e,0x93,0x75,0x23,0x82,0x03,0xec,0xa9,0x8e,
0xd8,0x6b,0xf1,0xe6,0x86,0x8a,0xb4,0x28,0xd8,0x63,0xa5,0xf3,0xb9,0x87,0xd6,0xc0,
0xf9,0x57,0xaf,0x08,0xa1,0x63,0x1f,0x7c,0xdc,0x00,0x8c,0xbb,0xff,0xc2,0x4b,0x02,
0x93,0x1a,0x02,0x01,0x94,0xe3,0x68,0xd6,0xb5,0x70,0x2e,0x7f,0x8b,0x96,0x0d,0xbc,
0x93,0xca,0x56,0xed,0x5a,0x68,0xda,0xe0,0x20,0x69,0x94,0xed,0xf1,0x47,0x6f,0x5f,
0xa3,0x4e,0xfb,0xda,0xa9,0x73,0xd2,0x7b,0xa3,0x68,0xce,0xdc,0xc6,0x66,0xd7,0x63,
0xbd,0x6a,0xd5,0x60,0x57,0x38,0x51,0xbf,0xfb,0x70,0x99,0xaf,0x58,0x8f,0x34,0xff,
0x2e,0x59,0x9b,0x0e,0x87,0xf7,0x0a,0x7f,0x4a,0xa4,0x8e,0x95,0x1d,0x0c,0x5c,0x30,
0xdd,0xfc,0x1f,0x98,0xc1,0x28,0x63,0x15,0x90,0xcd,0xe0,0x0a,0x7c,0x93,0x15,0x8d,
0xbf,0x4c,0xaa,0x53,0x7b,0x31,0x59,0x31,0xb7,0x14,0xd7,0x2f,0x4d,0x2a,0x01,0xc9),
};
@@ -25,6 +25,7 @@
#define TEST_VECTOR_HASHER(x) extern hasher_test_vector_t x;
#define TEST_VECTOR_PRF(x) extern prf_test_vector_t x;
#define TEST_VECTOR_XOF(x) extern xof_test_vector_t x;
#define TEST_VECTOR_KDF(x) extern kdf_test_vector_t x;
#define TEST_VECTOR_DRBG(x) extern drbg_test_vector_t x;
#define TEST_VECTOR_RNG(x) extern rng_test_vector_t x;
#define TEST_VECTOR_DH(x) extern dh_test_vector_t x;
@@ -37,6 +38,7 @@
#undef TEST_VECTOR_HASHER
#undef TEST_VECTOR_PRF
#undef TEST_VECTOR_XOF
#undef TEST_VECTOR_KDF
#undef TEST_VECTOR_DRBG
#undef TEST_VECTOR_RNG
#undef TEST_VECTOR_DH
@@ -47,6 +49,7 @@
#define TEST_VECTOR_HASHER(x)
#define TEST_VECTOR_PRF(x)
#define TEST_VECTOR_XOF(x)
#define TEST_VECTOR_KDF(x)
#define TEST_VECTOR_DRBG(x)
#define TEST_VECTOR_RNG(x)
#define TEST_VECTOR_DH(x)
@@ -100,6 +103,14 @@ static xof_test_vector_t *xof[] = {
#undef TEST_VECTOR_XOF
#define TEST_VECTOR_XOF(x)
#undef TEST_VECTOR_KDF
#define TEST_VECTOR_KDF(x) &x,
static kdf_test_vector_t *kdf[] = {
#include "test_vectors.h"
};
#undef TEST_VECTOR_KDF
#define TEST_VECTOR_KDF(x)
#undef TEST_VECTOR_DRBG
#define TEST_VECTOR_DRBG(x) &x,
static drbg_test_vector_t *drbg[] = {
@@ -208,6 +219,11 @@ plugin_t *test_vectors_plugin_create()
lib->crypto->add_test_vector(lib->crypto,
EXTENDED_OUTPUT_FUNCTION, xof[i]);
}
for (i = 0; i < countof(kdf); i++)
{
lib->crypto->add_test_vector(lib->crypto,
KEY_DERIVATION_FUNCTION, kdf[i]);
}
for (i = 0; i < countof(drbg); i++)
{
lib->crypto->add_test_vector(lib->crypto,
@@ -24,6 +24,7 @@ libstrongswan_wolfssl_la_SOURCES = \
wolfssl_ed_public_key.h wolfssl_ed_public_key.c \
wolfssl_hasher.h wolfssl_hasher.c \
wolfssl_hmac.h wolfssl_hmac.c \
wolfssl_kdf.h wolfssl_kdf.c \
wolfssl_rsa_public_key.h wolfssl_rsa_public_key.c \
wolfssl_rsa_private_key.h wolfssl_rsa_private_key.c \
wolfssl_rng.h wolfssl_rng.c \
@@ -0,0 +1,193 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "wolfssl_common.h"
#if !defined(NO_HMAC) && defined(HAVE_HKDF)
#include <wolfssl/wolfcrypt/hmac.h>
#define _GNU_SOURCE
#include "wolfssl_kdf.h"
#include "wolfssl_util.h"
typedef struct private_kdf_t private_kdf_t;
/**
* Private data.
*/
struct private_kdf_t {
/**
* Public interface.
*/
kdf_t public;
/**
* KDF type.
*/
key_derivation_function_t type;
/**
* Hash algorithm type.
*/
enum wc_HashType hash;
/**
* Key for KDF.
*/
chunk_t key;
/**
* Salt for KDF.
*/
chunk_t salt;
};
METHOD(kdf_t, get_type, key_derivation_function_t,
private_kdf_t *this)
{
return this->type;
}
METHOD(kdf_t, get_length, size_t,
private_kdf_t *this)
{
if (this->type == KDF_PRF_PLUS)
{
return SIZE_MAX;
}
return wc_HashGetDigestSize(this->hash);
}
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
if (this->type == KDF_PRF)
{
if (out_len != get_length(this) ||
wc_HKDF_Extract(this->hash, this->salt.ptr, this->salt.len,
this->key.ptr, this->key.len, buffer))
{
return FALSE;
}
return TRUE;
}
if (wc_HKDF_Expand(this->hash, this->key.ptr, this->key.len,
this->salt.ptr, this->salt.len, buffer, out_len))
{
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, allocate_bytes, bool,
private_kdf_t *this, size_t out_len, chunk_t *chunk)
{
if (this->type == KDF_PRF)
{
out_len = out_len ?: get_length(this);
}
*chunk = chunk_alloc(out_len);
if (!get_bytes(this, out_len, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(kdf_t, set_param, bool,
private_kdf_t *this, kdf_param_t param, ...)
{
chunk_t chunk;
switch (param)
{
case KDF_PARAM_KEY:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->key);
this->key = chunk_clone(chunk);
break;
case KDF_PARAM_SALT:
VA_ARGS_GET(param, chunk);
chunk_clear(&this->salt);
this->salt = chunk_clone(chunk);
break;
}
return TRUE;
}
METHOD(kdf_t, destroy, void,
private_kdf_t *this)
{
chunk_clear(&this->salt);
chunk_clear(&this->key);
free(this);
}
/*
* Described in header
*/
kdf_t *wolfssl_kdf_create(key_derivation_function_t algo, va_list args)
{
private_kdf_t *this;
pseudo_random_function_t prf_alg;
enum wc_HashType hash;
char buf[HASH_SIZE_SHA512];
if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
{
return NULL;
}
VA_ARGS_VGET(args, prf_alg);
if (!wolfssl_hash2type(hasher_algorithm_from_prf(prf_alg), &hash))
{
return NULL;
}
INIT(this,
.public = {
.get_type = _get_type,
.get_length = _get_length,
.get_bytes = _get_bytes,
.allocate_bytes = _allocate_bytes,
.set_param = _set_param,
.destroy = _destroy,
},
.type = algo,
.hash = hash,
);
/* test if we can actually use the algorithm */
if (!get_bytes(this, algo == KDF_PRF ? get_length(this) : sizeof(buf), buf))
{
destroy(this);
return NULL;
}
return &this->public;
}
#endif /* !NO_HMAC && HAVE_HKDF */
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Tobias Brunner, codelabs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Implements key derivation functions (KDF) using wolfSSL, in particular prf+,
* which is implemented via wolfSSL's HKDF implementation.
*
* @defgroup wolfssl_kdf wolfssl_kdf
* @{ @ingroup wolfssl_p
*/
#ifndef WOLFSSL_KDF_H_
#define WOLFSSL_KDF_H_
#include <crypto/kdfs/kdf.h>
/**
* Creates a new kdf_t object.
*
* @param algo algorithm to instantiate
* @param args algorithm-specific arguments
* @return kdf_t object, NULL if not supported
*/
kdf_t *wolfssl_kdf_create(key_derivation_function_t algo, va_list args);
#endif /** WOLFSSL_KDF_H_ @}*/
@@ -36,6 +36,7 @@
#include "wolfssl_ed_public_key.h"
#include "wolfssl_hasher.h"
#include "wolfssl_hmac.h"
#include "wolfssl_kdf.h"
#include "wolfssl_rsa_private_key.h"
#include "wolfssl_rsa_public_key.h"
#include "wolfssl_rng.h"
@@ -185,6 +186,11 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
#endif
#ifdef HAVE_HKDF
PLUGIN_REGISTER(KDF, wolfssl_kdf_create),
PLUGIN_PROVIDE(KDF, KDF_PRF),
PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
#endif
#endif /* NO_HMAC */
#if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AESCCM))) || \
(defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+111 -103
View File
@@ -15,129 +15,138 @@
#include "test_suite.h"
#include <crypto/prf_plus.h>
#include <library.h>
static struct {
chunk_t key;
chunk_t seed;
chunk_t iterations[10];
} counter_data[] = {
chunk_t expected;
} test_data[] = {
{ .key = chunk_from_chars(0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
0x0b,0x0b,0x0b,0x0b),
.seed = chunk_from_chars(0x48,0x69,0x20,0x54,0x68,0x65,0x72,0x65),
.iterations = {
chunk_from_chars(0xb9,0xbd,0xc0),
chunk_from_chars(0x89,0x88,0xb4,0xc2,0xb7,0x5a),
chunk_from_chars(0xa9,0x3e,0x59,0x6a,0xc8,0x42,0x05),
chunk_from_chars(0xfa,0x2d,0xdd,0xe1,0xbf,0x7a,0x25,0x72,
0x06,0x7b,0x00,0xe1,0x4b,0x23,0x77,0x32),
chunk_from_chars(0x83,0x05,0x09,0x98,0x1a,0xd2,0xf9,0x4a),
chunk_from_chars(0x8c,0x32,0xa4,0x7d,0xaa,0x22,0x55,0xb6),
chunk_from_chars(0x60,0xc4,0x36,0x34,0x7a,0xe7,0x56,0xa6,
0xed,0xc0,0x23,0x47,0x7d,0x80),
chunk_from_chars(0x95,0x90,0xe6,0x82,0xf6,0x1d,0x9c,0x04,
0xb0,0x6b,0x4a,0xd9,0x71,0xa3,0x4c,0x81,
0x47,0xfa,0x66,0x79),
chunk_from_chars(0x2f,0xf1,0x43,0x4b,0x93,0xc7,0x22,0xb3,
0x2e,0x12,0xf4,0x88,0x32,0xeb,0xc1,0x5c,
0xe2,0x36,0x9c,0xe7,0x1f,0xe9,0xb7,0xb8,
0x1e,0x57,0x04,0xc1,0x4d,0x0f,0x52,0x80,
0xa6,0xec,0x62,0x6e,0x99,0x2d,0x7a,0x9f),
},
.expected = chunk_from_chars(0xb9,0xbd,0xc0,0x89,0x88,0xb4,0xc2,0xb7,
0x5a,0xa9,0x3e,0x59,0x6a,0xc8,0x42,0x05,
0xfa,0x2d,0xdd,0xe1,0xbf,0x7a,0x25,0x72,
0x06,0x7b,0x00,0xe1,0x4b,0x23,0x77,0x32,
0x83,0x05,0x09,0x98,0x1a,0xd2,0xf9,0x4a,
0x8c,0x32,0xa4,0x7d,0xaa,0x22,0x55,0xb6,
0x60,0xc4,0x36,0x34,0x7a,0xe7,0x56,0xa6,
0xed,0xc0,0x23,0x47,0x7d,0x80,0x95,0x90,
0xe6,0x82,0xf6,0x1d,0x9c,0x04,0xb0,0x6b,
0x4a,0xd9,0x71,0xa3,0x4c,0x81,0x47,0xfa,
0x66,0x79,0x2f,0xf1,0x43,0x4b,0x93,0xc7,
0x22,0xb3,0x2e,0x12,0xf4,0x88,0x32,0xeb,
0xc1,0x5c,0xe2,0x36,0x9c,0xe7,0x1f,0xe9,
0xb7,0xb8,0x1e,0x57,0x04,0xc1,0x4d,0x0f,
0x52,0x80,0xa6,0xec,0x62,0x6e,0x99,0x2d,
0x7a,0x9f),
},
/* change the key, keep the seed */
{ .key = chunk_from_chars(0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,
0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,
0x0a,0x0a,0x0a,0x0a),
.expected = chunk_from_chars(0x1a,0x2f,0xc7,0x4a,0x06,0x8c,0xae,0x76,
0xfa,0xb3,0xd6,0x34,0xae,0xe9,0x81,0x55,
0x11,0x6a,0x4b,0x21,0xe1,0x0d,0x1b,0x16,
0x45,0x7a,0x06,0xd9,0x42,0x27,0x93,0x98,
0xf7,0x4d,0xf1,0x59,0xc1,0x25,0x21,0xae,
0xe6,0xf4,0x80,0x01,0xe5,0x86,0x8e,0xa7,
0x4b,0x1e,0x13,0xd1,0xcf,0xdc,0xb7,0x7b,
0xf8,0xcf,0x75,0x2c,0x67,0x13,0x18,0x7a,
0x38,0x55,0xba,0x4b,0xf2,0x57,0x55,0xcd,
0x96,0x20,0xcb,0xe3,0xc4,0x8a,0x7f,0xa3,
0x86,0xa5,0xc6,0x26,0x8e,0x57,0xd8,0xe0,
0xb6,0xf9,0x8a,0x41,0x16,0x82,0x64,0x8a),
},
/* change the seed, keep the key */
{ .seed = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10),
.expected = chunk_from_chars(0x8b,0x90,0x9c,0xbc,0xbb,0xf1,0x72,0x63,
0x6b,0x4e,0x63,0xcd,0x7e,0xc5,0xe3,0x45,
0x57,0x3e,0xbf,0x72,0x8f,0x62,0xa4,0x9b,
0x83,0x7b,0xd9,0x53,0xc0,0x0c,0xad,0x3d,
0x19,0x16,0x28,0x81,0x85,0xf9,0x27,0xb6,
0xc4,0x0c,0x48,0x31,0x45,0x12,0x3b,0x5a,
0xb8,0x47,0xd0,0x19,0x6e,0x6b,0x1c,0x5a,
0x2a,0xc1,0xe5,0x1e,0xc5,0x43,0xcc,0xd4,
0x28,0xba,0x30,0x4b,0x5e,0xad,0x97,0xa7,
0xc0,0x9d,0x13,0xdd,0xfb,0x4a,0x42,0x43,
0x87,0xd6,0x22,0xf6,0x03,0x19,0x21,0x31,
0x6a,0xa6,0x38,0x44,0xa5,0x61,0xf6,0x23,
0x0c,0x50,0x14,0xcc,0xce,0x09,0x5f,0xb3,
0xcc,0xe4,0xcb,0x8f,0x43,0xdc,0x2b,0x65,
0xfd,0x42,0xcc,0xeb,0x49,0x0e,0xcb,0xeb,
0x47,0x30,0xb5,0x18,0x6d,0x34,0x7a,0xea,
0xad,0xfd,0x66,0xa7,0x7e,0xd3,0x3f,0x42,
0xdf,0x75,0x54,0xef,0x5f,0x4f,0x7e,0x26,
0xf9,0x38,0x73,0x26,0x92,0x7a,0xc7,0x80),
},
};
START_TEST(test_vectors_counter)
START_TEST(test_params)
{
prf_plus_t *prf_plus;
prf_t *prf;
chunk_t *iter = counter_data[_i].iterations, out;
kdf_t *kdf;
chunk_t out;
int i;
prf = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA2_256);
ck_assert(prf->set_key(prf, counter_data[_i].key));
prf_plus = prf_plus_create(prf, TRUE, counter_data[_i].seed);
while (iter->ptr)
kdf = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS, PRF_HMAC_SHA2_256);
if (!kdf)
{
ck_assert(prf_plus->allocate_bytes(prf_plus, iter->len, &out));
ck_assert_chunk_eq(*iter, out);
chunk_free(&out);
iter++;
warn("%N (%N) not supported", key_derivation_function_names,
KDF_PRF_PLUS, pseudo_random_function_names, PRF_HMAC_SHA2_256);
return;
}
prf_plus->destroy(prf_plus);
prf->destroy(prf);
for (i = 0; i < countof(test_data); i++)
{
if (test_data[i].key.len)
{
ck_assert(kdf->set_param(kdf, KDF_PARAM_KEY, test_data[i].key));
}
if (test_data[i].seed.len)
{
ck_assert(kdf->set_param(kdf, KDF_PARAM_SALT, test_data[i].seed));
}
ck_assert(kdf->allocate_bytes(kdf, test_data[i].expected.len, &out));
ck_assert_chunk_eq(test_data[i].expected, out);
chunk_free(&out);
/* same output the second time */
ck_assert(kdf->allocate_bytes(kdf, test_data[i].expected.len, &out));
ck_assert_chunk_eq(test_data[i].expected, out);
chunk_free(&out);
}
kdf->destroy(kdf);
}
END_TEST
START_TEST(test_wrap)
{
prf_plus_t *prf_plus;
prf_t *prf;
u_char buf[32];
int i;
kdf_t *kdf;
chunk_t out;
prf = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA2_256);
ck_assert(prf->set_key(prf, counter_data[0].key));
prf_plus = prf_plus_create(prf, TRUE, counter_data[0].seed);
for (i = 1; i < 256; i++)
kdf = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS, PRF_HMAC_SHA2_256);
if (!kdf)
{
ck_assert(prf_plus->get_bytes(prf_plus, sizeof(buf), buf));
warn("%N (%N) not supported", key_derivation_function_names,
KDF_PRF_PLUS, pseudo_random_function_names, PRF_HMAC_SHA2_256);
return;
}
ck_assert(!prf_plus->get_bytes(prf_plus, sizeof(buf), buf));
prf_plus->destroy(prf_plus);
prf->destroy(prf);
}
END_TEST
ck_assert(kdf->set_param(kdf, KDF_PARAM_KEY, test_data[0].key));
ck_assert(kdf->set_param(kdf, KDF_PARAM_SALT, test_data[0].seed));
static struct {
chunk_t key;
chunk_t seed;
chunk_t iterations[10];
} classic_data[] = {
{ .key = chunk_from_chars(0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
0x0b,0x0b,0x0b,0x0b),
.seed = chunk_from_chars(0x48,0x69,0x20,0x54,0x68,0x65,0x72,0x65),
.iterations = {
chunk_from_chars(0xb0,0x34,0x4c),
chunk_from_chars(0x61,0xd8,0xdb,0x38,0x53,0x5c),
chunk_from_chars(0xa8,0xaf,0xce,0xaf,0x0b,0xf1,0x2b),
chunk_from_chars(0x88,0x1d,0xc2,0x00,0xc9,0x83,0x3d,0xa7,
0x26,0xe9,0x37,0x6c,0x2e,0x32,0xcf,0xf7),
chunk_from_chars(0xd0,0x9a,0xe2,0x4b,0x3a,0x83,0xff,0xd4),
chunk_from_chars(0xb1,0xef,0xa5,0x94,0x5c,0xc5,0xed,0x85),
chunk_from_chars(0xb0,0xb2,0xcc,0x56,0xfc,0xf7,0x5d,0x23,
0xa0,0xa3,0x4c,0xa4,0xdb,0xff,),
chunk_from_chars(0xea,0xfd,0xaa,0x6a,0x3b,0xf4,0x11,0x34,
0x24,0xe4,0x50,0x2d,0xf9,0x7a,0x76,0x93,
0x24,0xf6,0x11,0x24),
chunk_from_chars(0x24,0x3b,0x99,0x6e,0x7d,0x0f,0x35,0x99,
0x88,0x79,0x73,0x6b,0xdb,0x70,0x65,0x9a,
0x6e,0xfa,0xd2,0x39,0x94,0x10,0xe6,0xce,
0x80,0x45,0x6e,0xb6,0x07,0x07,0x8f,0xe1,
0xc4,0x7c,0x6b,0x5e,0x81,0x65,0x47,0x8a),
},
},
};
START_TEST(test_vectors_classic)
{
prf_plus_t *prf_plus;
prf_t *prf;
chunk_t *iter = classic_data[_i].iterations, out;
prf = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA2_256);
ck_assert(prf->set_key(prf, classic_data[_i].key));
prf_plus = prf_plus_create(prf, FALSE, classic_data[_i].seed);
while (iter->ptr)
{
ck_assert(prf_plus->allocate_bytes(prf_plus, iter->len, &out));
ck_assert_chunk_eq(*iter, out);
chunk_free(&out);
iter++;
/* the 1-byte counter overflows after 255 blocks of the underlying PRF */
out = chunk_alloc(32 * 255 + 1);
ck_assert(kdf->get_bytes(kdf, out.len - 2, out.ptr));
if (!kdf->get_bytes(kdf, out.len - 1, out.ptr))
{ /* Botan 3.x has a check for (len/bs) >= 255 blocks, so we allow this */
warn("unable to generate maximum-sized key for %N (%N) but maximum-1 "
"is fine", key_derivation_function_names, KDF_PRF_PLUS,
pseudo_random_function_names, PRF_HMAC_SHA2_256);
}
prf_plus->destroy(prf_plus);
prf->destroy(prf);
ck_assert(!kdf->get_bytes(kdf, out.len, out.ptr));
chunk_free(&out);
kdf->destroy(kdf);
}
END_TEST
@@ -148,13 +157,12 @@ Suite *prf_plus_suite_create()
s = suite_create("prf_plus");
tc = tcase_create("counter");
tcase_add_loop_test(tc, test_vectors_counter, 0, countof(counter_data));
tcase_add_test(tc, test_wrap);
tc = tcase_create("params");
tcase_add_test(tc, test_params);
suite_add_tcase(s, tc);
tc = tcase_create("no counter");
tcase_add_loop_test(tc, test_vectors_classic, 0, countof(classic_data));
tc = tcase_create("wrap");
tcase_add_test(tc, test_wrap);
suite_add_tcase(s, tc);
return s;
@@ -29,6 +29,7 @@ static transform_type_t tfs[] = {
HASH_ALGORITHM,
PSEUDO_RANDOM_FUNCTION,
EXTENDED_OUTPUT_FUNCTION,
KEY_DERIVATION_FUNCTION,
DETERMINISTIC_RANDOM_BIT_GENERATOR,
RANDOM_NUMBER_GENERATOR,
DIFFIE_HELLMAN_GROUP,
+1 -1
View File
@@ -55,7 +55,7 @@ TEST_SUITE(asn1_parser_suite_create)
TEST_SUITE(rng_tester_suite_create)
TEST_SUITE_DEPEND(mgf1_sha1_suite_create, XOF, XOF_MGF1_SHA1)
TEST_SUITE_DEPEND(mgf1_sha256_suite_create, XOF, XOF_MGF1_SHA256)
TEST_SUITE_DEPEND(prf_plus_suite_create, PRF, PRF_HMAC_SHA2_256)
TEST_SUITE_DEPEND(prf_plus_suite_create, KDF, KDF_PRF_PLUS)
TEST_SUITE_DEPEND(ntru_suite_create, DH, NTRU_112_BIT)
TEST_SUITE_DEPEND(fetch_http_suite_create, FETCHER, "http://")
TEST_SUITE_DEPEND(ed25519_suite_create, PRIVKEY_GEN, KEY_ED25519)
+1
View File
@@ -637,6 +637,7 @@ static char *whitelist[] = {
"botan_privkey_create",
"botan_privkey_load_ecdh",
"botan_privkey_load",
"botan_kdf",
};
/**
+17 -15
View File
@@ -18,7 +18,6 @@
#include "tls_hkdf.h"
#include <bio/bio_writer.h>
#include <crypto/prf_plus.h>
typedef struct private_tls_hkdf_t private_tls_hkdf_t;
@@ -51,6 +50,11 @@ struct private_tls_hkdf_t {
*/
prf_t *prf;
/**
* prf+ implementation.
*/
kdf_t *prf_plus;
/**
* Hasher used.
*/
@@ -115,7 +119,6 @@ static bool extract(private_tls_hkdf_t *this, chunk_t salt, chunk_t ikm,
}
DBG4(DBG_TLS, "PRK: %B", prk);
return TRUE;
}
@@ -126,24 +129,15 @@ static bool extract(private_tls_hkdf_t *this, chunk_t salt, chunk_t ikm,
static bool expand(private_tls_hkdf_t *this, chunk_t prk, chunk_t info,
size_t length, chunk_t *okm)
{
prf_plus_t *prf_plus;
if (!this->prf->set_key(this->prf, prk))
{
DBG1(DBG_TLS, "unable to set PRF secret to PRK");
return FALSE;
}
prf_plus = prf_plus_create(this->prf, TRUE, info);
if (!prf_plus || !prf_plus->allocate_bytes(prf_plus, length, okm))
if (!this->prf_plus->set_param(this->prf_plus, KDF_PARAM_KEY, prk) ||
!this->prf_plus->set_param(this->prf_plus, KDF_PARAM_SALT, info) ||
!this->prf_plus->allocate_bytes(this->prf_plus, length, okm))
{
DBG1(DBG_TLS, "unable to allocate PRF+ result");
DESTROY_IF(prf_plus);
return FALSE;
}
prf_plus->destroy(prf_plus);
DBG4(DBG_TLS, "OKM: %B", okm);
return TRUE;
}
@@ -681,6 +675,7 @@ METHOD(tls_hkdf_t, destroy, void,
destroy_secrets(&this->handshake_traffic_secrets);
destroy_secrets(&this->traffic_secrets);
DESTROY_IF(this->prf);
DESTROY_IF(this->prf_plus);
DESTROY_IF(this->hasher);
free(this);
}
@@ -720,16 +715,23 @@ tls_hkdf_t *tls_hkdf_create(hash_algorithm_t hash_algorithm, chunk_t psk)
.phase = HKDF_PHASE_0,
.psk = psk.ptr ? chunk_clone(psk) : chunk_empty,
.prf = lib->crypto->create_prf(lib->crypto, prf_algorithm),
.prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS,
prf_algorithm),
.hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm),
);
if (!this->prf || !this->hasher)
if (!this->prf || !this->prf_plus || !this->hasher)
{
if (!this->prf)
{
DBG1(DBG_TLS, "%N not supported", pseudo_random_function_names,
prf_algorithm);
}
if (!this->prf_plus)
{
DBG1(DBG_TLS, "%N (%N) not supported", key_derivation_function_names,
KDF_PRF_PLUS, pseudo_random_function_names, prf_algorithm);
}
if (!this->hasher)
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names,
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
+1 -1
View File
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
load = sha1 sha2 md5 aes des hmac kdf pem pkcs1 x509 revocation constraints curve25519 pubkey gmp random nonce curl kernel-netlink socket-default updown stroke vici
}
@@ -5,5 +5,5 @@ swanctl {
}
charon-systemd {
load = random nonce pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
load = random nonce kdf pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
}
@@ -5,5 +5,5 @@ swanctl {
}
charon-systemd {
load = random nonce pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
load = random nonce kdf pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
}
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = random nonce test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
load = random nonce kdf test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
integrity_test = yes
crypto_test {
on_add = yes
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = random nonce test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp x509 revocation curl hmac xcbc ctr ccm gcm kernel-netlink socket-default updown vici
load = random nonce kdf test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp x509 revocation curl hmac kdf xcbc ctr ccm gcm kernel-netlink socket-default updown vici
integrity_test = yes
crypto_test {
on_add = yes
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = random nonce test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
load = random nonce kdf test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
integrity_test = yes
crypto_test {
on_add = yes
@@ -5,5 +5,5 @@ swanctl {
}
charon-systemd {
load = random nonce aes sha1 sha2 hmac pem pkcs1 pkcs8 x509 revocation constraints curve25519 curl kernel-netlink socket-default updown vici
load = random nonce aes sha1 sha2 hmac kdf pem pkcs1 pkcs8 x509 revocation constraints curve25519 curl kernel-netlink socket-default updown vici
}
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = random nonce sha1 sha2 aes curve25519 hmac mgf1 pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default updown vici
load = random nonce sha1 sha2 aes curve25519 hmac kdf mgf1 pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default updown vici
rsa_pss = yes
}
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = random nonce sha1 sha2 aes hmac mgf1 pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default updown vici
load = random nonce sha1 sha2 aes hmac kdf mgf1 pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default updown vici
rsa_pss = yes
}
@@ -5,6 +5,6 @@ swanctl {
}
charon-systemd {
load = nonce pem pkcs1 gcrypt hmac x509 revocation curl vici kernel-netlink socket-default
load = nonce pem pkcs1 gcrypt hmac kdf x509 revocation curl vici kernel-netlink socket-default
send_vendor_id = yes
}
@@ -5,6 +5,6 @@ swanctl {
}
charon-systemd {
load = nonce pem pkcs1 gcrypt hmac x509 revocation vici kernel-netlink socket-default
load = nonce pem pkcs1 gcrypt hmac kdf x509 revocation vici kernel-netlink socket-default
send_vendor_id = yes
}
@@ -5,6 +5,6 @@ swanctl {
}
charon-systemd {
load = nonce pem pkcs1 gcrypt hmac x509 revocation curl vici kernel-netlink socket-default
load = nonce pem pkcs1 gcrypt hmac kdf x509 revocation curl vici kernel-netlink socket-default
send_vendor_id = yes
}
@@ -5,6 +5,6 @@ swanctl {
}
charon-systemd {
load = nonce pem pkcs1 gcrypt hmac x509 revocation vici kernel-netlink socket-default
load = nonce pem pkcs1 gcrypt hmac kdf x509 revocation vici kernel-netlink socket-default
send_vendor_id = yes
}
@@ -5,5 +5,5 @@ swanctl {
}
charon-systemd {
load = random nonce pem pkcs1 gcrypt hmac x509 revocation kernel-netlink curl socket-default updown vici
load = random nonce pem pkcs1 gcrypt hmac kdf x509 revocation kernel-netlink curl socket-default updown vici
}
@@ -5,5 +5,5 @@ swanctl {
}
charon-systemd {
load = random nonce pem pkcs1 gcrypt hmac x509 revocation kernel-netlink curl socket-default updown vici
load = random nonce pem pkcs1 gcrypt hmac kdf x509 revocation kernel-netlink curl socket-default updown vici
}
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = curl test-vectors pem pkcs1 gcrypt nonce x509 revocation hmac xcbc ctr ccm gcm vici kernel-netlink socket-default updown
load = curl test-vectors pem pkcs1 gcrypt nonce x509 revocation hmac kdf xcbc ctr ccm gcm vici kernel-netlink socket-default updown
integrity_test = yes
crypto_test {
on_add = yes
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm vici stroke kernel-netlink socket-default updown
load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac kdf xcbc ctr ccm vici stroke kernel-netlink socket-default updown
integrity_test = yes
crypto_test {
required = yes
@@ -5,7 +5,7 @@ swanctl {
}
charon-systemd {
load = curl test-vectors pem pkcs1 gcrypt nonce x509 revocation hmac xcbc ctr ccm gcm vici kernel-netlink socket-default updown
load = curl test-vectors pem pkcs1 gcrypt nonce x509 revocation hmac kdf xcbc ctr ccm gcm vici kernel-netlink socket-default updown
integrity_test = yes
crypto_test {
on_add = yes
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default ha
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default ha
plugins {
ha {
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown
}
@@ -1,6 +1,6 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown
}
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default ha
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default ha
plugins {
ha {
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default ha
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default ha
plugins {
ha {
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown
}
@@ -1,6 +1,6 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown
}
@@ -1,7 +1,7 @@
# /etc/strongswan.conf - strongSwan configuration file
charon-systemd {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default ha
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default ha
plugins {
ha {
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp hmac x509 curl revocation stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 md5 pem pkcs1 curve25519 gmp hmac kdf x509 curl revocation stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp hmac x509 curl revocation stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp hmac kdf x509 curl revocation stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp hmac x509 curl revocation stroke kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp hmac kdf x509 curl revocation stroke kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce des md5 sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce des md5 sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce des md5 sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce des md5 sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce blowfish sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}
@@ -1,5 +1,5 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac vici kernel-netlink socket-default
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default
}

Some files were not shown because too many files have changed in this diff Show More