implemented a crypto_tester class to test crypto algorithms
libstrongswan.crypto.test.required to require at least one test vector to use an algorithm libstrongswan.crypto.test.rng_true to run RNG tests on RNG_TRUE quality
This commit is contained in:
@@ -28,6 +28,7 @@ crypto/rngs/rng.c crypto/rngs/rng.h \
|
|||||||
crypto/prf_plus.h crypto/prf_plus.c \
|
crypto/prf_plus.h crypto/prf_plus.c \
|
||||||
crypto/signers/signer.c crypto/signers/signer.h \
|
crypto/signers/signer.c crypto/signers/signer.h \
|
||||||
crypto/crypto_factory.c crypto/crypto_factory.h \
|
crypto/crypto_factory.c crypto/crypto_factory.h \
|
||||||
|
crypto/crypto_tester.c crypto/crypto_tester.h \
|
||||||
crypto/diffie_hellman.c crypto/diffie_hellman.h \
|
crypto/diffie_hellman.c crypto/diffie_hellman.h \
|
||||||
crypto/transform.c crypto/transform.h \
|
crypto/transform.c crypto/transform.h \
|
||||||
credentials/credential_factory.c credentials/credential_factory.h \
|
credentials/credential_factory.c credentials/credential_factory.h \
|
||||||
|
|||||||
@@ -0,0 +1,628 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Martin Willi
|
||||||
|
* 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 "crypto_tester.h"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
|
typedef struct private_crypto_tester_t private_crypto_tester_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an crypto_tester_t object.
|
||||||
|
*/
|
||||||
|
struct private_crypto_tester_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public crypto_tester_t interface.
|
||||||
|
*/
|
||||||
|
crypto_tester_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of crypter test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *crypter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of signer test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *signer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of hasher test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *hasher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of PRF test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *prf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of RNG test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *rng;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a test vector required to pass a test?
|
||||||
|
*/
|
||||||
|
bool required;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* should we run RNG_TRUE tests? Enough entropy?
|
||||||
|
*/
|
||||||
|
bool rng_true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypto_tester_t.test_crypter
|
||||||
|
*/
|
||||||
|
static bool test_crypter(private_crypto_tester_t *this,
|
||||||
|
encryption_algorithm_t alg, size_t key_size, crypter_constructor_t create)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
crypter_test_vector_t *vector;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0;
|
||||||
|
|
||||||
|
enumerator = this->crypter->create_enumerator(this->crypter);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
crypter_t *crypter;
|
||||||
|
chunk_t key, plain, cipher, iv;
|
||||||
|
|
||||||
|
if (vector->alg != alg)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key_size && key_size != vector->key_size)
|
||||||
|
{ /* test only vectors with a specific key size, if key size given */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
crypter = create(alg, vector->key_size);
|
||||||
|
if (!crypter)
|
||||||
|
{ /* key size not supported... */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
tested++;
|
||||||
|
|
||||||
|
key = chunk_create(vector->key, crypter->get_key_size(crypter));
|
||||||
|
crypter->set_key(crypter, key);
|
||||||
|
iv = chunk_create(vector->iv, crypter->get_block_size(crypter));
|
||||||
|
|
||||||
|
/* allocated encryption */
|
||||||
|
plain = chunk_create(vector->plain, vector->len);
|
||||||
|
crypter->encrypt(crypter, plain, iv, &cipher);
|
||||||
|
if (!memeq(vector->cipher, cipher.ptr, cipher.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* inline decryption */
|
||||||
|
crypter->decrypt(crypter, cipher, iv, NULL);
|
||||||
|
if (!memeq(vector->plain, cipher.ptr, cipher.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
free(cipher.ptr);
|
||||||
|
/* allocated decryption */
|
||||||
|
cipher = chunk_create(vector->cipher, vector->len);
|
||||||
|
crypter->decrypt(crypter, cipher, iv, &plain);
|
||||||
|
if (!memeq(vector->plain, plain.ptr, plain.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* inline encryption */
|
||||||
|
crypter->encrypt(crypter, plain, iv, NULL);
|
||||||
|
if (!memeq(vector->cipher, plain.ptr, plain.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
free(plain.ptr);
|
||||||
|
|
||||||
|
crypter->destroy(crypter);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1("test vector %d failed, %N disabled",
|
||||||
|
tested, encryption_algorithm_names, alg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DBG2("%N test vector %d successful",
|
||||||
|
encryption_algorithm_names, alg, tested);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1("no test vectors found for %N%s",
|
||||||
|
encryption_algorithm_names, alg,
|
||||||
|
this->required ? ", disabled" : "");
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
DBG2("successfully tested %d test vectors for %N",
|
||||||
|
tested, encryption_algorithm_names, alg);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypto_tester_t.test_signer
|
||||||
|
*/
|
||||||
|
static bool test_signer(private_crypto_tester_t *this,
|
||||||
|
integrity_algorithm_t alg, signer_constructor_t create)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
signer_test_vector_t *vector;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0;
|
||||||
|
|
||||||
|
enumerator = this->signer->create_enumerator(this->signer);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
signer_t *signer;
|
||||||
|
chunk_t key, data, mac;
|
||||||
|
|
||||||
|
if (vector->alg != alg)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
signer = create(alg);
|
||||||
|
if (!signer)
|
||||||
|
{
|
||||||
|
DBG1("creating instance failed, %N disabled",
|
||||||
|
integrity_algorithm_names, alg);
|
||||||
|
failed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
|
||||||
|
key = chunk_create(vector->key, signer->get_key_size(signer));
|
||||||
|
signer->set_key(signer, key);
|
||||||
|
|
||||||
|
/* allocated signature */
|
||||||
|
data = chunk_create(vector->data, vector->len);
|
||||||
|
signer->allocate_signature(signer, data, &mac);
|
||||||
|
if (mac.len != signer->get_block_size(signer))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
if (!memeq(vector->mac, mac.ptr, mac.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* signature to existing buffer */
|
||||||
|
memset(mac.ptr, 0, mac.len);
|
||||||
|
signer->get_signature(signer, data, mac.ptr);
|
||||||
|
if (!memeq(vector->mac, mac.ptr, mac.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* signature verification, good case */
|
||||||
|
if (!signer->verify_signature(signer, data, mac))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* signature verification, bad case */
|
||||||
|
*(mac.ptr + mac.len - 1) += 1;
|
||||||
|
if (signer->verify_signature(signer, data, mac))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* signature to existing buffer, using append mode */
|
||||||
|
if (data.len > 2)
|
||||||
|
{
|
||||||
|
memset(mac.ptr, 0, mac.len);
|
||||||
|
signer->allocate_signature(signer, chunk_create(data.ptr, 1), NULL);
|
||||||
|
signer->get_signature(signer, chunk_create(data.ptr + 1, 1), NULL);
|
||||||
|
signer->get_signature(signer, chunk_skip(data, 2), mac.ptr);
|
||||||
|
if (!memeq(vector->mac, mac.ptr, mac.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(mac.ptr);
|
||||||
|
|
||||||
|
signer->destroy(signer);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1("test vector %d failed, %N disabled",
|
||||||
|
tested, integrity_algorithm_names, alg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DBG2(" %N test vector %d successful",
|
||||||
|
integrity_algorithm_names, alg, tested);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1("no test vectors found for %N%s",
|
||||||
|
integrity_algorithm_names, alg,
|
||||||
|
this->required ? ", disabled" : "");
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
DBG2("successfully tested %d test vectors for %N",
|
||||||
|
tested, integrity_algorithm_names, alg);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of hasher_t.test_hasher
|
||||||
|
*/
|
||||||
|
static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
|
||||||
|
hasher_constructor_t create)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
hasher_test_vector_t *vector;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0;
|
||||||
|
|
||||||
|
enumerator = this->hasher->create_enumerator(this->hasher);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
hasher_t *hasher;
|
||||||
|
chunk_t data, hash;
|
||||||
|
|
||||||
|
if (vector->alg != alg)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
hasher = create(alg);
|
||||||
|
if (!hasher)
|
||||||
|
{
|
||||||
|
DBG1("creating instance failed, %N disabled",
|
||||||
|
hash_algorithm_names, alg);
|
||||||
|
failed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
|
||||||
|
/* allocated hash */
|
||||||
|
data = chunk_create(vector->data, vector->len);
|
||||||
|
hasher->allocate_hash(hasher, data, &hash);
|
||||||
|
if (hash.len != hasher->get_hash_size(hasher))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
if (!memeq(vector->hash, hash.ptr, hash.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* hash to existing buffer */
|
||||||
|
memset(hash.ptr, 0, hash.len);
|
||||||
|
hasher->get_hash(hasher, data, hash.ptr);
|
||||||
|
if (!memeq(vector->hash, hash.ptr, hash.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* hasher to existing buffer, using append mode */
|
||||||
|
if (data.len > 2)
|
||||||
|
{
|
||||||
|
memset(hash.ptr, 0, hash.len);
|
||||||
|
hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL);
|
||||||
|
hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL);
|
||||||
|
hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr);
|
||||||
|
if (!memeq(vector->hash, hash.ptr, hash.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(hash.ptr);
|
||||||
|
|
||||||
|
hasher->destroy(hasher);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1("test vector %d failed, %N disabled",
|
||||||
|
tested, hash_algorithm_names, alg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DBG2("%N test vector %d successful",
|
||||||
|
hash_algorithm_names, alg, tested);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1("no test vectors found for %N%s",
|
||||||
|
hash_algorithm_names, alg,
|
||||||
|
this->required ? ", disabled" : "");
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
DBG2("successfully tested %d test vectors for %N",
|
||||||
|
tested, hash_algorithm_names, alg);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypto_tester_t.test_prf
|
||||||
|
*/
|
||||||
|
static bool test_prf(private_crypto_tester_t *this,
|
||||||
|
pseudo_random_function_t alg, prf_constructor_t create)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
prf_test_vector_t *vector;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0;
|
||||||
|
|
||||||
|
enumerator = this->prf->create_enumerator(this->prf);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
prf_t *prf;
|
||||||
|
chunk_t key, seed, out;
|
||||||
|
|
||||||
|
if (vector->alg != alg)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
prf = create(alg);
|
||||||
|
if (!prf)
|
||||||
|
{
|
||||||
|
DBG1("creating instance failed, %N disabled",
|
||||||
|
pseudo_random_function_names, alg);
|
||||||
|
failed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
|
||||||
|
key = chunk_create(vector->key, vector->key_size);
|
||||||
|
prf->set_key(prf, key);
|
||||||
|
|
||||||
|
/* allocated bytes */
|
||||||
|
seed = chunk_create(vector->seed, vector->len);
|
||||||
|
prf->allocate_bytes(prf, seed, &out);
|
||||||
|
if (out.len != prf->get_block_size(prf))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
if (!memeq(vector->out, out.ptr, out.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* bytes to existing buffer */
|
||||||
|
memset(out.ptr, 0, out.len);
|
||||||
|
prf->get_bytes(prf, seed, out.ptr);
|
||||||
|
if (!memeq(vector->out, out.ptr, out.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* bytes to existing buffer, using append mode */
|
||||||
|
if (seed.len > 2)
|
||||||
|
{
|
||||||
|
memset(out.ptr, 0, out.len);
|
||||||
|
prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL);
|
||||||
|
prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL);
|
||||||
|
prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr);
|
||||||
|
if (!memeq(vector->out, out.ptr, out.len))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(out.ptr);
|
||||||
|
|
||||||
|
prf->destroy(prf);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1("test vector %d failed, %N disabled",
|
||||||
|
tested, pseudo_random_function_names, alg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DBG2("%N test vector %d successful",
|
||||||
|
pseudo_random_function_names, alg, tested);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1("no test vectors found for %N%s",
|
||||||
|
pseudo_random_function_names, alg,
|
||||||
|
this->required ? ", disabled" : "");
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
DBG2("successfully tested %d testvectors for %N",
|
||||||
|
tested, pseudo_random_function_names, alg);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypto_tester_t.test_rng
|
||||||
|
*/
|
||||||
|
static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
|
||||||
|
rng_constructor_t create)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
rng_test_vector_t *vector;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0;
|
||||||
|
|
||||||
|
if (!this->rng_true && quality == RNG_TRUE)
|
||||||
|
{
|
||||||
|
DBG1("skipping %N test, disabled by config", rng_quality_names, quality);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
enumerator = this->rng->create_enumerator(this->rng);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
rng_t *rng;
|
||||||
|
chunk_t data;
|
||||||
|
|
||||||
|
if (vector->quality != quality)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
rng = create(quality);
|
||||||
|
if (!rng)
|
||||||
|
{
|
||||||
|
DBG1("creating instance failed, %N disabled",
|
||||||
|
rng_quality_names, quality);
|
||||||
|
failed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
|
||||||
|
/* allocated bytes */
|
||||||
|
rng->allocate_bytes(rng, vector->len, &data);
|
||||||
|
if (data.len != vector->len)
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
if (!vector->test(vector->user, data))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
/* bytes to existing buffer */
|
||||||
|
memset(data.ptr, 0, data.len);
|
||||||
|
rng->get_bytes(rng, vector->len, data.ptr);
|
||||||
|
if (!vector->test(vector->user, data))
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
free(data.ptr);
|
||||||
|
|
||||||
|
rng->destroy(rng);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1("test vector %d failed, %N disabled",
|
||||||
|
tested, rng_quality_names, quality);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DBG2("%N test vector %d successful", rng_quality_names, quality, tested);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1("no test vectors found for %N%s",
|
||||||
|
rng_quality_names, quality, this->required ? ", disabled" : "");
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
DBG2("successfully tested %d testvectors for %N",
|
||||||
|
tested, rng_quality_names, quality);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypter_tester_t.add_crypter_vector
|
||||||
|
*/
|
||||||
|
static void add_crypter_vector(private_crypto_tester_t *this,
|
||||||
|
crypter_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->crypter->insert_last(this->crypter, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypter_tester_t.add_signer_vector
|
||||||
|
*/
|
||||||
|
static void add_signer_vector(private_crypto_tester_t *this,
|
||||||
|
signer_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->signer->insert_last(this->signer, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypter_tester_t.add_hasher_vector
|
||||||
|
*/
|
||||||
|
static void add_hasher_vector(private_crypto_tester_t *this,
|
||||||
|
hasher_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->hasher->insert_last(this->hasher, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypter_tester_t.add_prf_vector
|
||||||
|
*/
|
||||||
|
static void add_prf_vector(private_crypto_tester_t *this,
|
||||||
|
prf_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->prf->insert_last(this->prf, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypter_tester_t.add_rng_vector
|
||||||
|
*/
|
||||||
|
static void add_rng_vector(private_crypto_tester_t *this,
|
||||||
|
rng_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->rng->insert_last(this->rng, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of crypto_tester_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_crypto_tester_t *this)
|
||||||
|
{
|
||||||
|
this->crypter->destroy(this->crypter);
|
||||||
|
this->signer->destroy(this->signer);
|
||||||
|
this->hasher->destroy(this->hasher);
|
||||||
|
this->prf->destroy(this->prf);
|
||||||
|
this->rng->destroy(this->rng);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
crypto_tester_t *crypto_tester_create()
|
||||||
|
{
|
||||||
|
private_crypto_tester_t *this = malloc_thing(private_crypto_tester_t);
|
||||||
|
|
||||||
|
this->public.test_crypter = (bool(*)(crypto_tester_t*, encryption_algorithm_t alg,size_t key_size, crypter_constructor_t create))test_crypter;
|
||||||
|
this->public.test_signer = (bool(*)(crypto_tester_t*, integrity_algorithm_t alg, signer_constructor_t create))test_signer;
|
||||||
|
this->public.test_hasher = (bool(*)(crypto_tester_t*, hash_algorithm_t alg, hasher_constructor_t create))test_hasher;
|
||||||
|
this->public.test_prf = (bool(*)(crypto_tester_t*, pseudo_random_function_t alg, prf_constructor_t create))test_prf;
|
||||||
|
this->public.test_rng = (bool(*)(crypto_tester_t*, rng_quality_t quality, rng_constructor_t create))test_rng;
|
||||||
|
this->public.add_crypter_vector = (void(*)(crypto_tester_t*, crypter_test_vector_t *vector))add_crypter_vector;
|
||||||
|
this->public.add_signer_vector = (void(*)(crypto_tester_t*, signer_test_vector_t *vector))add_signer_vector;
|
||||||
|
this->public.add_hasher_vector = (void(*)(crypto_tester_t*, hasher_test_vector_t *vector))add_hasher_vector;
|
||||||
|
this->public.add_prf_vector = (void(*)(crypto_tester_t*, prf_test_vector_t *vector))add_prf_vector;
|
||||||
|
this->public.add_rng_vector = (void(*)(crypto_tester_t*, rng_test_vector_t *vector))add_rng_vector;
|
||||||
|
this->public.destroy = (void(*)(crypto_tester_t*))destroy;
|
||||||
|
|
||||||
|
this->crypter = linked_list_create();
|
||||||
|
this->signer = linked_list_create();
|
||||||
|
this->hasher = linked_list_create();
|
||||||
|
this->prf = linked_list_create();
|
||||||
|
this->rng = linked_list_create();
|
||||||
|
|
||||||
|
this->required = lib->settings->get_bool(lib->settings,
|
||||||
|
"libstrongswan.crypto.test.required", FALSE);
|
||||||
|
this->rng_true = lib->settings->get_bool(lib->settings,
|
||||||
|
"libstrongswan.crypto.test.rng_true", FALSE);
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Martin Willi
|
||||||
|
* 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 crypto_tester crypto_tester
|
||||||
|
* @{ @ingroup crypto
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRYPTO_TESTER_H_
|
||||||
|
#define CRYPTO_TESTER_H_
|
||||||
|
|
||||||
|
typedef struct crypto_tester_t crypto_tester_t;
|
||||||
|
|
||||||
|
#include <crypto/crypto_factory.h>
|
||||||
|
|
||||||
|
typedef struct crypter_test_vector_t crypter_test_vector_t;
|
||||||
|
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 rng_test_vector_t rng_test_vector_t;
|
||||||
|
|
||||||
|
struct crypter_test_vector_t {
|
||||||
|
/** encryption algorithm this vector tests */
|
||||||
|
encryption_algorithm_t alg;
|
||||||
|
/** key length to use, in bytes */
|
||||||
|
size_t key_size;
|
||||||
|
/** encryption key of test vector */
|
||||||
|
u_char *key;
|
||||||
|
/** initialization vector, using crypters blocksize bytes */
|
||||||
|
u_char *iv;
|
||||||
|
/** length of plain and cipher text */
|
||||||
|
size_t len;
|
||||||
|
/** plain text */
|
||||||
|
u_char *plain;
|
||||||
|
/** cipher text */
|
||||||
|
u_char *cipher;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct signer_test_vector_t {
|
||||||
|
/** signer algorithm this test vector tests */
|
||||||
|
pseudo_random_function_t alg;
|
||||||
|
/** key to use, with a length the algorithm expects */
|
||||||
|
u_char *key;
|
||||||
|
/** size of the input data */
|
||||||
|
size_t len;
|
||||||
|
/** input data */
|
||||||
|
u_char *data;
|
||||||
|
/** expected output, with ouput size of the tested algorithm */
|
||||||
|
u_char *mac;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hasher_test_vector_t {
|
||||||
|
/** hash algorithm this test vector tests */
|
||||||
|
hash_algorithm_t alg;
|
||||||
|
/** length of the input data */
|
||||||
|
size_t len;
|
||||||
|
/** input data */
|
||||||
|
u_char *data;
|
||||||
|
/** expected hash, with hash size of the tested algorithm */
|
||||||
|
u_char *hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct prf_test_vector_t {
|
||||||
|
/** prf algorithm this test vector tests */
|
||||||
|
pseudo_random_function_t alg;
|
||||||
|
/** key length to use, in bytes */
|
||||||
|
size_t key_size;
|
||||||
|
/** key to use */
|
||||||
|
u_char *key;
|
||||||
|
/** size of the seed data */
|
||||||
|
size_t len;
|
||||||
|
/** seed data */
|
||||||
|
u_char *seed;
|
||||||
|
/** expected output, with block size of the tested algorithm */
|
||||||
|
u_char *out;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test vector for a RNG.
|
||||||
|
*
|
||||||
|
* Contains a callback function to analyze the output of a RNG,
|
||||||
|
*/
|
||||||
|
struct rng_test_vector_t {
|
||||||
|
/** quality of random data this test vector tests */
|
||||||
|
rng_quality_t quality;
|
||||||
|
/** callback function to test RNG output, returns TRUE if data ok */
|
||||||
|
bool (*test)(void *user, chunk_t data);
|
||||||
|
/** number of bytes the function requests */
|
||||||
|
size_t len;
|
||||||
|
/** user data passed back to the test() function on invocation */
|
||||||
|
void *user;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cryptographic primitive testing framework.
|
||||||
|
*/
|
||||||
|
struct crypto_tester_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a crypter algorithm, optionally using a specified key size.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param key_size key size to test, 0 for all
|
||||||
|
* @param create constructor function for the crypter
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_crypter)(crypto_tester_t *this, encryption_algorithm_t alg,
|
||||||
|
size_t key_size, crypter_constructor_t create);
|
||||||
|
/**
|
||||||
|
* Test a signer algorithm.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param create constructor function for the signer
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_signer)(crypto_tester_t *this, integrity_algorithm_t alg,
|
||||||
|
signer_constructor_t create);
|
||||||
|
/**
|
||||||
|
* Test a hasher algorithm.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param create constructor function for the hasher
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_hasher)(crypto_tester_t *this, hash_algorithm_t alg,
|
||||||
|
hasher_constructor_t create);
|
||||||
|
/**
|
||||||
|
* Test a PRF algorithm.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param create constructor function for the PRF
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_prf)(crypto_tester_t *this, pseudo_random_function_t alg,
|
||||||
|
prf_constructor_t create);
|
||||||
|
/**
|
||||||
|
* Test a RNG implementation.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param create constructor function for the RNG
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_rng)(crypto_tester_t *this, rng_quality_t quality,
|
||||||
|
rng_constructor_t create);
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a crypter.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_crypter_vector)(crypto_tester_t *this,
|
||||||
|
crypter_test_vector_t *vector);
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a signer.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_signer_vector)(crypto_tester_t *this,
|
||||||
|
signer_test_vector_t *vector);
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a hasher.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_hasher_vector)(crypto_tester_t *this,
|
||||||
|
hasher_test_vector_t *vector);
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a PRF.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_prf_vector)(crypto_tester_t *this, prf_test_vector_t *vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a RNG.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_rng_vector)(crypto_tester_t *this, rng_test_vector_t *vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a crypto_tester_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(crypto_tester_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a crypto_tester instance.
|
||||||
|
*/
|
||||||
|
crypto_tester_t *crypto_tester_create();
|
||||||
|
|
||||||
|
#endif /* CRYPTO_TESTER_ @}*/
|
||||||
Reference in New Issue
Block a user