[1/1] cunit : add tests for crypto APIs

Message ID 1414680787-17459-1-git-send-email-alexandru.badicioiu@linaro.org
State New
Headers show

Commit Message

Alexandru Badicioiu Oct. 30, 2014, 2:53 p.m.
This patch adds a suite for async inplace mode of crypto APIs.
Correctness of crypto operations output is verified with known
test vectors  as well as various options and functionalities:
use session IV or operation IV for ciphering, use input packet
buffer or a separate buffer as the completion event, set and
retrieve the context associated with an operation.

Signed-off-by: Alexandru Badicioiu <alexandru.badicioiu@linaro.org>
---
 configure.ac                                  |    1 +
 test/cunit/Makefile.am                        |    2 +
 test/cunit/crypto/Makefile.am                 |    9 +
 test/cunit/crypto/odp_crypto_test.c           |   26 ++
 test/cunit/crypto/odp_crypto_test_async_inp.c |  463 +++++++++++++++++++++++++
 test/cunit/crypto/odp_crypto_test_async_inp.h |   13 +
 test/cunit/crypto/test_vectors.h              |   94 +++++
 7 files changed, 608 insertions(+), 0 deletions(-)
 create mode 100644 test/cunit/crypto/Makefile.am
 create mode 100644 test/cunit/crypto/odp_crypto_test.c
 create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.c
 create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.h
 create mode 100644 test/cunit/crypto/test_vectors.h

Comments

Maxim Uvarov Oct. 30, 2014, 9:51 p.m. | #1
On 10/30/2014 05:53 PM, alexandru.badicioiu@linaro.org wrote:
> This patch adds a suite for async inplace mode of crypto APIs.
> Correctness of crypto operations output is verified with known
> test vectors  as well as various options and functionalities:
> use session IV or operation IV for ciphering, use input packet
> buffer or a separate buffer as the completion event, set and
> retrieve the context associated with an operation.
>
> Signed-off-by: Alexandru Badicioiu <alexandru.badicioiu@linaro.org>
> ---
>   configure.ac                                  |    1 +
>   test/cunit/Makefile.am                        |    2 +
>   test/cunit/crypto/Makefile.am                 |    9 +
>   test/cunit/crypto/odp_crypto_test.c           |   26 ++
>   test/cunit/crypto/odp_crypto_test_async_inp.c |  463 +++++++++++++++++++++++++
>   test/cunit/crypto/odp_crypto_test_async_inp.h |   13 +
>   test/cunit/crypto/test_vectors.h              |   94 +++++
>   7 files changed, 608 insertions(+), 0 deletions(-)
>   create mode 100644 test/cunit/crypto/Makefile.am
>   create mode 100644 test/cunit/crypto/odp_crypto_test.c
>   create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.c
>   create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.h
>   create mode 100644 test/cunit/crypto/test_vectors.h
>
> diff --git a/configure.ac b/configure.ac
> index fd69e85..b1785e9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -166,6 +166,7 @@ AC_CONFIG_FILES([Makefile
>   		 test/Makefile
>   		 test/api_test/Makefile
>                    test/cunit/Makefile
> +		 test/cunit/crypto/Makefile
>   		 pkgconfig/libodp.pc])
>   
>   AC_SEARCH_LIBS([timer_create],[rt posix4])
> diff --git a/test/cunit/Makefile.am b/test/cunit/Makefile.am
> index 927a5a5..7611145 100644
> --- a/test/cunit/Makefile.am
> +++ b/test/cunit/Makefile.am
> @@ -3,6 +3,8 @@ include $(top_srcdir)/test/Makefile.inc
>   AM_CFLAGS += -I$(CUNIT_PATH)/include
>   AM_LDFLAGS += -L$(CUNIT_PATH)/lib
>   
> +SUBDIRS = crypto
> +
>   if ODP_CUNIT_ENABLED
>   TESTS = ${bin_PROGRAMS}
>   check_PROGRAMS = ${bin_PROGRAMS}
> diff --git a/test/cunit/crypto/Makefile.am b/test/cunit/crypto/Makefile.am
> new file mode 100644
> index 0000000..b984eaa
> --- /dev/null
> +++ b/test/cunit/crypto/Makefile.am
> @@ -0,0 +1,9 @@
> +include $(top_srcdir)/test/Makefile.inc
> +
> +if ODP_CUNIT_ENABLED
> +bin_PROGRAMS = odp_crypto
> +odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static -lcunit
> +endif
> +
> +dist_odp_crypto_SOURCES = odp_crypto_test_async_inp.c \
> +			  odp_crypto_test.c
> diff --git a/test/cunit/crypto/odp_crypto_test.c b/test/cunit/crypto/odp_crypto_test.c
> new file mode 100644
> index 0000000..b5d0dea
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test.c
> @@ -0,0 +1,26 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include "CUnit/Headers/Basic.h"
> +#include "CUnit/Headers/TestDB.h"
> +#include "odp_crypto_test_async_inp.h"
> +
> +int main(void)
> +{
> +	/* initialize the CUnit test registry */
> +	if (CUE_SUCCESS != CU_initialize_registry())
> +		return CU_get_error();
> +
> +	/* register suites */
> +	CU_register_suites(suites);
> +	/* Run all tests using the CUnit Basic interface */
> +	CU_basic_set_mode(CU_BRM_VERBOSE);
> +	CU_basic_run_tests();
> +	CU_cleanup_registry();
> +
> +	return CU_get_error();
> +}
> diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.c b/test/cunit/crypto/odp_crypto_test_async_inp.c
> new file mode 100644
> index 0000000..53b7c6d
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test_async_inp.c
> @@ -0,0 +1,463 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:	BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include <odp_crypto.h>
> +#include "CUnit/Headers/Basic.h"
> +#include "CUnit/Headers/TestDB.h"
> +#include "test_vectors.h"
> +
> +#define pr_error(fmt, ...) \
> +	fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
> +		__LINE__, __func__, ##__VA_ARGS__)
> +
> +/* Suite name */
> +#define ODP_CRYPTO_ASYNC_INP	"odp_crypto_async_inp"
> +
> +/* Suite init/finalize funcs */
> +/* ODP global/local initialization
> + * Packet pool creation
> + * Crypto output queue creation */
> +
> +#define SHM_PKT_POOL_SIZE      (512*2048*2)
> +#define SHM_PKT_POOL_BUF_SIZE  (1024 * 32)
> +
> +#define SHM_COMPL_POOL_SIZE	(128*1024)
> +#define SHM_COMPL_POOL_BUF_SIZE 128
> +
> +static int init(void)
> +{
> +	odp_shm_t shm;
> +	void *pool_base = NULL;

Set up to NULL is not needed.

> +	odp_buffer_pool_t pool;
> +	odp_queue_t out_queue;
> +
> +	if (odp_init_global(NULL, NULL)) {
> +		pr_error("ODP global init failed.\n");
> +		return -1;
> +	}
> +	odp_init_local();
> +
> +	shm = odp_shm_reserve("shm_packet_pool",
> +			      SHM_PKT_POOL_SIZE,
> +			      ODP_CACHE_LINE_SIZE, 0);
> +
> +	pool_base = odp_shm_addr(shm);
> +	if (!pool_base) {
> +		pr_error("Packet pool allocation failed.\n");
> +		return -1;
> +	}
> +
> +	pool = odp_buffer_pool_create("packet_pool", pool_base,
> +				      SHM_PKT_POOL_SIZE,
> +				      SHM_PKT_POOL_BUF_SIZE,
> +				      ODP_CACHE_LINE_SIZE,
> +				      ODP_BUFFER_TYPE_PACKET);
> +	if (pool == ODP_BUFFER_POOL_INVALID) {
> +		pr_error("Packet pool creation failed.\n");
> +		/* TODO - cleanup */

doxygen understands @todo, not sure if it understands simple TODO, 
please check*/

> +		return -1;
> +	}
> +	out_queue = odp_queue_create("crypto-out",
> +				     ODP_QUEUE_TYPE_POLL, NULL);
> +	if (out_queue == ODP_QUEUE_INVALID) {
> +		pr_error("Crypto outq creation failed.\n");
> +		/* TODO - cleanup */
> +		return -1;
> +	}
> +	shm = odp_shm_reserve("shm_compl_pool",
> +			     SHM_COMPL_POOL_SIZE,
> +			     ODP_CACHE_LINE_SIZE,
> +			     ODP_SHM_SW_ONLY);
> +	pool_base = odp_shm_addr(shm);
> +	if (!pool_base) {
> +		pr_error("Completion pool allocation failed.\n");
is pr_error cunit function? Just under  why not ODP_ERROR().

> +		return -1;
> +	}
> +	pool = odp_buffer_pool_create("compl_pool", pool_base,
> +				      SHM_COMPL_POOL_SIZE,
> +				      SHM_COMPL_POOL_BUF_SIZE,
> +				      ODP_CACHE_LINE_SIZE,
> +				      ODP_BUFFER_TYPE_RAW);
> +	if (pool == ODP_BUFFER_POOL_INVALID) {
> +		pr_error("Completion pool creation failed.\n");
> +		return -1;
> +	}
> +
> +	printf("\tODP version: %s\n", odp_version_api_str());
> +	return 0;
> +}
> +
> +/* ODP cleanup */
> +static int finalise(void)
> +{
> +	return 0;
> +}
> +
> +
> +/* Basic algorithm run function.
> + * Creates a session from input parameters and runs one operation
> + * on input_vec. Checks the output of the crypto operation against
> + * output_vec. Operation completion event is dequeued polling the
> + * session output queue. Completion context pointer is retrieved
> + * and checked against the one set before the operation.
> + * */
> +static void alg_test(enum odp_crypto_op op,
> +		     enum odp_cipher_alg cipher_alg,
> +		     odp_crypto_iv_t ses_iv,
> +		     uint8_t *op_iv_ptr,
> +		     odp_crypto_key_t cipher_key,
> +		     enum odp_auth_alg auth_alg,
> +		     odp_crypto_key_t auth_key,
> +		     odp_buffer_t compl_new,
> +		     uint8_t *input_vec,
> +		     unsigned int input_vec_len,
> +		     uint8_t *output_vec,
> +		     unsigned int output_vec_len)
> +{
> +	odp_crypto_session_t session;
> +	int rc;
> +	enum odp_crypto_ses_create_err status;
> +	bool posted;
> +	odp_buffer_t compl_event;
> +
> +	odp_queue_t compl_queue = odp_queue_lookup("crypto-out");
> +	CU_ASSERT(compl_queue != ODP_QUEUE_INVALID);
> +	odp_buffer_pool_t pool = odp_buffer_pool_lookup("packet_pool");
> +	CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
> +
> +	/* Create a crypto session */
> +	odp_crypto_session_params_t ses_params;
> +	memset(&ses_params, 0, sizeof(ses_params));
> +	ses_params.op = op;
> +	ses_params.auth_cipher_text = false;
> +	ses_params.pref_mode = ODP_CRYPTO_ASYNC;
> +	ses_params.cipher_alg = cipher_alg;
> +	ses_params.auth_alg = auth_alg;
> +	ses_params.compl_queue = compl_queue;
> +	ses_params.output_pool = pool;
> +	ses_params.cipher_key = cipher_key;
> +	ses_params.iv = ses_iv;
> +	ses_params.auth_key = auth_key;
> +
> +	/* TEST : odp_crypto_session_create */
> +	rc = odp_crypto_session_create(&ses_params, &session, &status);
> +	CU_ASSERT(!rc);
> +	CU_ASSERT(status == ODP_CRYPTO_SES_CREATE_ERR_NONE);
> +
> +	/* Prepare input data */
> +	odp_buffer_t buf = odp_buffer_alloc(pool);
> +	CU_ASSERT(buf != ODP_BUFFER_INVALID);
> +	odp_packet_t pkt = odp_packet_from_buffer(buf);
> +	CU_ASSERT(pkt != ODP_PACKET_INVALID);
> +	uint8_t *data_addr = odp_packet_data(pkt);
> +	memcpy(data_addr, input_vec, input_vec_len);
> +	/* offsets are relative to buffer address (not packet data)
> +	until https://bugs.linaro.org/show_bug.cgi?id=387 is fixed */
> +	int data_off = data_addr - (uint8_t *)odp_buffer_addr(buf);
> +
> +	/* Prepare input/output params */
> +	odp_crypto_op_params_t op_params;
> +	memset(&op_params, 0, sizeof(op_params));
> +	op_params.session = session;
> +	op_params.pkt = pkt;
> +	op_params.out_pkt = pkt;
> +	if (cipher_alg != ODP_CIPHER_ALG_NULL &&
> +	    auth_alg == ODP_AUTH_ALG_NULL) {
> +		op_params.cipher_range.offset = data_off;
> +		op_params.cipher_range.length = input_vec_len;
> +		if (op_iv_ptr)
> +			op_params.override_iv_ptr = op_iv_ptr;
> +	} else if (cipher_alg == ODP_CIPHER_ALG_NULL &&
> +		 auth_alg != ODP_AUTH_ALG_NULL) {
> +		op_params.auth_range.offset = data_off;
> +		op_params.auth_range.length = input_vec_len;
> +		op_params.hash_result_offset = data_off;
> +	} else {
> +		CU_FAIL("%s : not implemented for combined alg mode\n");
> +	}
> +
> +	/* TEST : odp_crypto_set_operation_compl_ctx */
> +	/* TEST : odp_crypto_operation */
> +	if (compl_new == ODP_BUFFER_INVALID) {
> +		odp_crypto_set_operation_compl_ctx(buf, (void *)0xdeadbeef);
> +		rc = odp_crypto_operation(&op_params, &posted, buf);
> +	} else {
> +		odp_crypto_set_operation_compl_ctx(compl_new,
> +						   (void *)0xdeadbeef);
> +		rc = odp_crypto_operation(&op_params, &posted, compl_new);
> +	}
> +	CU_ASSERT(posted);
> +
> +	/* Poll completion queue for results */
> +	do {
> +		compl_event = odp_queue_deq(compl_queue);
> +	} while (compl_event == ODP_BUFFER_INVALID);
> +
> +	if (compl_new == ODP_BUFFER_INVALID) {
> +		CU_ASSERT(compl_event == buf);
> +	} else {
> +		CU_ASSERT(compl_event == compl_new);
> +	}
> +
> +	/* TEST : odp_crypto_get_operation_compl_status */
> +	struct odp_crypto_compl_status auth_status, cipher_status;
> +	odp_crypto_get_operation_compl_status(compl_event,
> +					      &auth_status, &cipher_status);
> +	CU_ASSERT(auth_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
> +	CU_ASSERT(auth_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
> +	CU_ASSERT(cipher_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
> +	CU_ASSERT(cipher_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
> +
> +	/* TEST : odp_crypto_get_operation_compl_packet */
> +	odp_packet_t out_pkt;
> +	out_pkt = odp_crypto_get_operation_compl_packet(compl_event);
> +	CU_ASSERT(out_pkt == pkt);
> +
> +	/* TEST : operation output was correct */
> +	CU_ASSERT(!memcmp(data_addr, output_vec, output_vec_len));
> +
> +	/* TEST : we got back the context pointer */
> +	void *ctx = odp_crypto_get_operation_compl_ctx(compl_event);
> +	CU_ASSERT(ctx == (void *)0xdeadbeef);
> +
> +	odp_buffer_free(buf);
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session IV.
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.*/
> +#define ASYNC_INP_ENC_ALG_3DES_CBC	"ENC_ALG_3DES_CBC"
> +static void test_enc_alg_3des_cbc(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv;
> +	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +				     sizeof(tdes_cbc_reference_length[0]));
> +
> +	unsigned int i;
> +	for (i = 0; i < test_vec_num; i++) {
> +		cipher_key.data = tdes_cbc_reference_key[i];
> +		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +		iv.data = tdes_cbc_reference_iv[i];
> +		iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_ENCODE,
> +			 ODP_CIPHER_ALG_3DES_CBC,
> +			 iv,
> +			 NULL,
> +			 cipher_key,
> +			 ODP_AUTH_ALG_NULL,
> +			 auth_key,
> +			 ODP_BUFFER_INVALID,
> +			 tdes_cbc_reference_plaintext[i],
> +			 tdes_cbc_reference_length[i],
> +			 tdes_cbc_reference_ciphertext[i],
> +			 tdes_cbc_reference_length[i]);
> +	}
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the operation IV.
> + * */
> +#define ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV	"ENC_ALG_3DES_CBC_OVR_IV"
> +static void test_enc_alg_3des_cbc_ovr_iv(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
> +	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +				     sizeof(tdes_cbc_reference_length[0]));
> +
> +	unsigned int i;
> +	for (i = 0; i < test_vec_num; i++) {
> +		cipher_key.data = tdes_cbc_reference_key[i];
> +		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_ENCODE,
> +			 ODP_CIPHER_ALG_3DES_CBC,
> +			 iv,
> +			 tdes_cbc_reference_iv[i],
> +			 cipher_key,
> +			 ODP_AUTH_ALG_NULL,
> +			 auth_key,
> +			 ODP_BUFFER_INVALID,
> +			 tdes_cbc_reference_plaintext[i],
> +			 tdes_cbc_reference_length[i],
> +			 tdes_cbc_reference_ciphertext[i],
> +			 tdes_cbc_reference_length[i]);
> +	}
> +}
> +
> +
> +/* This test verifies the correctness of decode (ciphertext -> plaintext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session IV
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_DEC_ALG_3DES_CBC	 "DEC_ALG_3DES_CBC"
> +static void test_dec_alg_3des_cbc(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
> +	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +				     sizeof(tdes_cbc_reference_length[0]));
> +
> +	unsigned int i;
> +	for (i = 0; i < test_vec_num; i++) {
> +		cipher_key.data = tdes_cbc_reference_key[i];
> +		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +		iv.data = tdes_cbc_reference_iv[i];
> +		iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_DECODE,
> +			 ODP_CIPHER_ALG_3DES_CBC,
> +			 iv,
> +			 NULL,
> +			 cipher_key,
> +			 ODP_AUTH_ALG_NULL,
> +			 auth_key,
> +			 ODP_BUFFER_INVALID,
> +			 tdes_cbc_reference_ciphertext[i],
> +			 tdes_cbc_reference_length[i],
> +			 tdes_cbc_reference_plaintext[i],
> +			 tdes_cbc_reference_length[i]);
> +	}
> +}
> +
> +/* This test verifies the correctness of decode (ciphertext -> plaintext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session IV
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV	 "DEC_ALG_3DES_CBC_OVR_IV"
> +static void test_dec_alg_3des_cbc_ovr_iv(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
> +	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +				     sizeof(tdes_cbc_reference_length[0]));
> +
> +	unsigned int i;
> +	for (i = 0; i < test_vec_num; i++) {
> +		cipher_key.data = tdes_cbc_reference_key[i];
> +		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_DECODE,
> +			 ODP_CIPHER_ALG_3DES_CBC,
> +			 iv,
> +			 tdes_cbc_reference_iv[i],
> +			 cipher_key,
> +			 ODP_AUTH_ALG_NULL,
> +			 auth_key,
> +			 ODP_BUFFER_INVALID,
> +			 tdes_cbc_reference_ciphertext[i],
> +			 tdes_cbc_reference_length[i],
> +			 tdes_cbc_reference_plaintext[i],
> +			 tdes_cbc_reference_length[i]);
> +	}
> +}
> +
> +
> +/* This test verifies the correctness of HMAC_MD5 digest operation.
> + * The output check length is truncated to 12 bytes (96 bits) as
> + * returned by the crypto operation API call.
> + * Note that hash digest is a one-way operation.
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_ALG_HMAC_MD5	      "ALG_HMAC_MD5"
> +static void test_alg_hmac_md5(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
> +
> +	unsigned int test_vec_num = (sizeof(hmac_md5_reference_length)/
> +				     sizeof(hmac_md5_reference_length[0]));
> +
> +	unsigned int i;
> +	for (i = 0; i < test_vec_num; i++) {
> +		auth_key.data = hmac_md5_reference_key[i];
> +		auth_key.length = sizeof(hmac_md5_reference_key[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_ENCODE,
> +			 ODP_CIPHER_ALG_NULL,
> +			 iv,
> +			 iv.data,
> +			 cipher_key,
> +			 ODP_AUTH_ALG_MD5_96,
> +			 auth_key,
> +			 ODP_BUFFER_INVALID,
> +			 hmac_md5_reference_plaintext[i],
> +			 hmac_md5_reference_length[i],
> +			 hmac_md5_reference_digest[i],
> +			 HMAC_MD5_96_CHECK_LEN);
> +	}
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session IV.
> + * Uses a separate buffer for completion event
> + * */
> +#define ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW	   "ENC_ALG_3DES_CBC_COMPL_NEW"
> +static void test_enc_alg_3des_cbc_compl_new(void)
> +{
> +	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +			 auth_key   = { .data = NULL, .length = 0 };
> +	odp_crypto_iv_t iv;
> +	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +				     sizeof(tdes_cbc_reference_length[0]));
> +
> +	odp_buffer_pool_t pool = odp_buffer_pool_lookup("compl_pool");
> +	CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
> +
> +	unsigned int i;
> +	odp_buffer_t compl_new;
> +	for (i = 0; i < test_vec_num; i++) {
> +		compl_new = odp_buffer_alloc(pool);
> +		CU_ASSERT(compl_new != ODP_BUFFER_INVALID);
> +
> +		cipher_key.data = tdes_cbc_reference_key[i];
> +		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +		iv.data = tdes_cbc_reference_iv[i];
> +		iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +		alg_test(ODP_CRYPTO_OP_ENCODE,
> +			 ODP_CIPHER_ALG_3DES_CBC,
> +			 iv,
> +			 NULL,
> +			 cipher_key,
> +			 ODP_AUTH_ALG_NULL,
> +			 auth_key,
> +			 compl_new,
> +			 tdes_cbc_reference_plaintext[i],
> +			 tdes_cbc_reference_length[i],
> +			 tdes_cbc_reference_ciphertext[i],
> +			 tdes_cbc_reference_length[i]);
> +		odp_buffer_free(compl_new);
> +	}
> +}
> +
> +static CU_TestInfo test_array[] = {
> +	{ASYNC_INP_ENC_ALG_3DES_CBC, test_enc_alg_3des_cbc },
> +	{ASYNC_INP_DEC_ALG_3DES_CBC, test_dec_alg_3des_cbc },
> +	{ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV, test_enc_alg_3des_cbc_ovr_iv },
> +	{ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV, test_dec_alg_3des_cbc_ovr_iv },
> +	{ASYNC_INP_ALG_HMAC_MD5, test_alg_hmac_md5 },
> +	{ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW, test_enc_alg_3des_cbc_compl_new },
> +	CU_TEST_INFO_NULL,
> +};
> +
> +CU_SuiteInfo suites[] = {
> +	{ ODP_CRYPTO_ASYNC_INP , init, finalise, NULL, NULL, test_array },
> +	CU_SUITE_INFO_NULL,
> +};
> +
> diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.h b/test/cunit/crypto/odp_crypto_test_async_inp.h
> new file mode 100644
> index 0000000..818f7e7
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test_async_inp.h
> @@ -0,0 +1,13 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +#ifndef ODP_CRYPTO_TEST_ASYNC_INP_
> +#define ODP_CRYPTO_TEST_ASYNC_INP_
> +
> +#include "CUnit/Headers/TestDB.h"
> +
> +CU_SuiteInfo suites[1];
> +
> +#endif
> diff --git a/test/cunit/crypto/test_vectors.h b/test/cunit/crypto/test_vectors.h
> new file mode 100644
> index 0000000..c151952
> --- /dev/null
> +++ b/test/cunit/crypto/test_vectors.h
> @@ -0,0 +1,94 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:	BSD-3-Clause
> + */
> +
> +
> +/* TDES-CBC reference vectors, according to
> + * "http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf"
> + */
> +
> +#define TDES_CBC_KEY_LEN	24	/* key length(in bytes) for tdes-cbc */
> +#define TDES_CBC_IV_LEN		8	/* IV length(in bytes) for tdes-cbc */
> +#define TDES_CBC_MAX_DATA_LEN	16	/* max. plain text length(in bytes) */
> +
> +static uint8_t tdes_cbc_reference_key[][TDES_CBC_KEY_LEN] = {
> +	{0x62, 0x7f, 0x46, 0x0e, 0x08, 0x10, 0x4a, 0x10, 0x43, 0xcd, 0x26, 0x5d,
> +	 0x58, 0x40, 0xea, 0xf1, 0x31, 0x3e, 0xdf, 0x97, 0xdf, 0x2a, 0x8a, 0x8c,
> +	 },
> +
> +	{0x37, 0xae, 0x5e, 0xbf, 0x46, 0xdf, 0xf2, 0xdc, 0x07, 0x54, 0xb9, 0x4f,
> +	 0x31, 0xcb, 0xb3, 0x85, 0x5e, 0x7f, 0xd3, 0x6d, 0xc8, 0x70, 0xbf, 0xae}
> +};
> +
> +static uint8_t tdes_cbc_reference_iv[][TDES_CBC_IV_LEN] = {
> +	{0x8e, 0x29, 0xf7, 0x5e, 0xa7, 0x7e, 0x54, 0x75},
> +
> +	{0x3d, 0x1d, 0xe3, 0xcc, 0x13, 0x2e, 0x3b, 0x65}
> +};
> +
> +/** length in bytes */
> +static uint32_t tdes_cbc_reference_length[] = { 8, 16 };
> +
> +static uint8_t tdes_cbc_reference_plaintext[][TDES_CBC_MAX_DATA_LEN] = {
> +	{0x32, 0x6a, 0x49, 0x4c, 0xd3, 0x3f, 0xe7, 0x56},
> +
> +	{0x84, 0x40, 0x1f, 0x78, 0xfe, 0x6c, 0x10, 0x87, 0x6d, 0x8e, 0xa2, 0x30,
> +	 0x94, 0xea, 0x53, 0x09}
> +};
> +
> +static uint8_t tdes_cbc_reference_ciphertext[][TDES_CBC_MAX_DATA_LEN] = {
> +	{0xb2, 0x2b, 0x8d, 0x66, 0xde, 0x97, 0x06, 0x92},
> +
> +	{0x7b, 0x1f, 0x7c, 0x7e, 0x3b, 0x1c, 0x94, 0x8e, 0xbd, 0x04, 0xa7, 0x5f,
> +	 0xfb, 0xa7, 0xd2, 0xf5}
> +};
> +
> +
> +/* HMAC-MD5 test vectors  - RFC2104 */
> +#define HMAC_MD5_KEY_LEN	16
> +#define HMAC_MD5_MAX_DATA_LEN	128
> +#define HMAC_MD5_DIGEST_LEN	16
> +#define HMAC_MD5_96_CHECK_LEN	12
> +
> +static uint8_t hmac_md5_reference_key[][HMAC_MD5_KEY_LEN] = {
> +	{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
> +	  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b } ,
> +
> +	/* "Jefe" */
> +	{ 0x4a, 0x65, 0x66, 0x65 },
> +
> +	{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
> +	  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }
> +};
> +
> +static uint32_t hmac_md5_reference_length[] = { 8, 28, 50 };
> +
> +static uint8_t hmac_md5_reference_plaintext[][HMAC_MD5_MAX_DATA_LEN] = {
> +	/* "Hi There" */
> +	{ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
> +
> +	/* what do ya want for nothing?*/
> +	{ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
> +	  0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
> +	  0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
> +	  0x69, 0x6e, 0x67, 0x3f },
> +
> +	{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }
> +};
> +
> +static uint8_t hmac_md5_reference_digest[][HMAC_MD5_DIGEST_LEN] = {
> +	{ 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
> +	  0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
> +
> +	{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
> +	  0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
> +
> +	{ 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
> +	  0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }
> +};
Mike Holmes Oct. 31, 2014, 2:29 a.m. | #2
On 30 October 2014 10:53, <alexandru.badicioiu@linaro.org> wrote:

> This patch adds a suite for async inplace mode of crypto APIs.
> Correctness of crypto operations output is verified with known
> test vectors  as well as various options and functionalities:
> use session IV or operation IV for ciphering, use input packet
> buffer or a separate buffer as the completion event, set and
> retrieve the context associated with an operation.
>
> Signed-off-by: Alexandru Badicioiu <alexandru.badicioiu@linaro.org>
> ---
>  configure.ac                                  |    1 +
>  test/cunit/Makefile.am                        |    2 +
>  test/cunit/crypto/Makefile.am                 |    9 +
>  test/cunit/crypto/odp_crypto_test.c           |   26 ++
>  test/cunit/crypto/odp_crypto_test_async_inp.c |  463
> +++++++++++++++++++++++++
>  test/cunit/crypto/odp_crypto_test_async_inp.h |   13 +
>  test/cunit/crypto/test_vectors.h              |   94 +++++
>  7 files changed, 608 insertions(+), 0 deletions(-)
>  create mode 100644 test/cunit/crypto/Makefile.am
>  create mode 100644 test/cunit/crypto/odp_crypto_test.c
>  create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.c
>  create mode 100644 test/cunit/crypto/odp_crypto_test_async_inp.h
>  create mode 100644 test/cunit/crypto/test_vectors.h
>
> diff --git a/configure.ac b/configure.ac
> index fd69e85..b1785e9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -166,6 +166,7 @@ AC_CONFIG_FILES([Makefile
>                  test/Makefile
>                  test/api_test/Makefile
>                   test/cunit/Makefile
> +                test/cunit/crypto/Makefile
>                  pkgconfig/libodp.pc])
>
>  AC_SEARCH_LIBS([timer_create],[rt posix4])
> diff --git a/test/cunit/Makefile.am b/test/cunit/Makefile.am
> index 927a5a5..7611145 100644
> --- a/test/cunit/Makefile.am
> +++ b/test/cunit/Makefile.am
> @@ -3,6 +3,8 @@ include $(top_srcdir)/test/Makefile.inc
>  AM_CFLAGS += -I$(CUNIT_PATH)/include
>  AM_LDFLAGS += -L$(CUNIT_PATH)/lib
>
> +SUBDIRS = crypto
> +
>  if ODP_CUNIT_ENABLED
>  TESTS = ${bin_PROGRAMS}
>  check_PROGRAMS = ${bin_PROGRAMS}
> diff --git a/test/cunit/crypto/Makefile.am b/test/cunit/crypto/Makefile.am
> new file mode 100644
> index 0000000..b984eaa
> --- /dev/null
> +++ b/test/cunit/crypto/Makefile.am
> @@ -0,0 +1,9 @@
> +include $(top_srcdir)/test/Makefile.inc
> +
> +if ODP_CUNIT_ENABLED
> +bin_PROGRAMS = odp_crypto
> +odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static -lcunit
> +endif
> +
> +dist_odp_crypto_SOURCES = odp_crypto_test_async_inp.c \
> +                         odp_crypto_test.c
> diff --git a/test/cunit/crypto/odp_crypto_test.c
> b/test/cunit/crypto/odp_crypto_test.c
> new file mode 100644
> index 0000000..b5d0dea
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test.c
> @@ -0,0 +1,26 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include "CUnit/Headers/Basic.h"
> +#include "CUnit/Headers/TestDB.h"
> +#include "odp_crypto_test_async_inp.h"

+
> +int main(void)
> +{
> +       /* initialize the CUnit test registry */
> +       if (CUE_SUCCESS != CU_initialize_registry())
> +               return CU_get_error();
> +
> +       /* register suites */
> +       CU_register_suites(suites);
> +       /* Run all tests using the CUnit Basic interface */
> +       CU_basic_set_mode(CU_BRM_VERBOSE);
> +       CU_basic_run_tests();
> +       CU_cleanup_registry();
> +
> +       return CU_get_error();
> +}
> diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.c
> b/test/cunit/crypto/odp_crypto_test_async_inp.c
> new file mode 100644
> index 0000000..53b7c6d
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test_async_inp.c
> @@ -0,0 +1,463 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:    BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include <odp_crypto.h>
> +#include "CUnit/Headers/Basic.h"
> +#include "CUnit/Headers/TestDB.h"
> +#include "test_vectors.h"
> +
> +#define pr_error(fmt, ...) \
> +       fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
> +               __LINE__, __func__, ##__VA_ARGS__)
> +
> +/* Suite name */
> +#define ODP_CRYPTO_ASYNC_INP   "odp_crypto_async_inp"
> +
> +/* Suite init/finalize funcs */
> +/* ODP global/local initialization
> + * Packet pool creation
> + * Crypto output queue creation */
> +
> +#define SHM_PKT_POOL_SIZE      (512*2048*2)
> +#define SHM_PKT_POOL_BUF_SIZE  (1024 * 32)
> +
> +#define SHM_COMPL_POOL_SIZE    (128*1024)
> +#define SHM_COMPL_POOL_BUF_SIZE 128
> +
> +static int init(void)
> +{
> +       odp_shm_t shm;
> +       void *pool_base = NULL;
> +       odp_buffer_pool_t pool;
> +       odp_queue_t out_queue;
> +
> +       if (odp_init_global(NULL, NULL)) {
> +               pr_error("ODP global init failed.\n");
> +               return -1;
>

CU_ASSERT rather than pr_error ?

odp_term_global ?

+       }
> +       odp_init_local();
>

odp_term_local ?

+
> +       shm = odp_shm_reserve("shm_packet_pool",
> +                             SHM_PKT_POOL_SIZE,
> +                             ODP_CACHE_LINE_SIZE, 0);
> +
> +       pool_base = odp_shm_addr(shm);
> +       if (!pool_base) {
> +               pr_error("Packet pool allocation failed.\n");
> +               return -1;
> +       }
> +
> +       pool = odp_buffer_pool_create("packet_pool", pool_base,
> +                                     SHM_PKT_POOL_SIZE,
> +                                     SHM_PKT_POOL_BUF_SIZE,
> +                                     ODP_CACHE_LINE_SIZE,
> +                                     ODP_BUFFER_TYPE_PACKET);
> +       if (pool == ODP_BUFFER_POOL_INVALID) {
> +               pr_error("Packet pool creation failed.\n");
> +               /* TODO - cleanup */
> +               return -1;
> +       }
> +       out_queue = odp_queue_create("crypto-out",
> +                                    ODP_QUEUE_TYPE_POLL, NULL);
> +       if (out_queue == ODP_QUEUE_INVALID) {
> +               pr_error("Crypto outq creation failed.\n");
> +               /* TODO - cleanup */
> +               return -1;
> +       }
> +       shm = odp_shm_reserve("shm_compl_pool",
> +                            SHM_COMPL_POOL_SIZE,
> +                            ODP_CACHE_LINE_SIZE,
> +                            ODP_SHM_SW_ONLY);
> +       pool_base = odp_shm_addr(shm);
> +       if (!pool_base) {
> +               pr_error("Completion pool allocation failed.\n");
> +               return -1;
> +       }
> +       pool = odp_buffer_pool_create("compl_pool", pool_base,
> +                                     SHM_COMPL_POOL_SIZE,
> +                                     SHM_COMPL_POOL_BUF_SIZE,
> +                                     ODP_CACHE_LINE_SIZE,
> +                                     ODP_BUFFER_TYPE_RAW);
> +       if (pool == ODP_BUFFER_POOL_INVALID) {
> +               pr_error("Completion pool creation failed.\n");
> +               return -1;
> +       }
> +
> +       printf("\tODP version: %s\n", odp_version_api_str());
> +       return 0;
> +}
> +
> +/* ODP cleanup */
> +static int finalise(void)
>

finalize spelling ?


> +{
> +       return 0;
> +}
> +
> +
> +/* Basic algorithm run function.
> + * Creates a session from input parameters and runs one operation
> + * on input_vec. Checks the output of the crypto operation against
> + * output_vec. Operation completion event is dequeued polling the
> + * session output queue. Completion context pointer is retrieved
> + * and checked against the one set before the operation.
> + * */
> +static void alg_test(enum odp_crypto_op op,
> +                    enum odp_cipher_alg cipher_alg,
> +                    odp_crypto_iv_t ses_iv,
> +                    uint8_t *op_iv_ptr,
> +                    odp_crypto_key_t cipher_key,
> +                    enum odp_auth_alg auth_alg,
> +                    odp_crypto_key_t auth_key,
> +                    odp_buffer_t compl_new,
> +                    uint8_t *input_vec,
> +                    unsigned int input_vec_len,
> +                    uint8_t *output_vec,
> +                    unsigned int output_vec_len)
> +{
> +       odp_crypto_session_t session;
> +       int rc;
> +       enum odp_crypto_ses_create_err status;
> +       bool posted;
> +       odp_buffer_t compl_event;
> +
> +       odp_queue_t compl_queue = odp_queue_lookup("crypto-out");
> +       CU_ASSERT(compl_queue != ODP_QUEUE_INVALID);
> +       odp_buffer_pool_t pool = odp_buffer_pool_lookup("packet_pool");
> +       CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
> +
> +       /* Create a crypto session */
> +       odp_crypto_session_params_t ses_params;
> +       memset(&ses_params, 0, sizeof(ses_params));
> +       ses_params.op = op;
> +       ses_params.auth_cipher_text = false;
> +       ses_params.pref_mode = ODP_CRYPTO_ASYNC;
> +       ses_params.cipher_alg = cipher_alg;
> +       ses_params.auth_alg = auth_alg;
> +       ses_params.compl_queue = compl_queue;
> +       ses_params.output_pool = pool;
> +       ses_params.cipher_key = cipher_key;
> +       ses_params.iv = ses_iv;
> +       ses_params.auth_key = auth_key;
> +
> +       /* TEST : odp_crypto_session_create */
> +       rc = odp_crypto_session_create(&ses_params, &session, &status);
> +       CU_ASSERT(!rc);
> +       CU_ASSERT(status == ODP_CRYPTO_SES_CREATE_ERR_NONE);
> +
> +       /* Prepare input data */
> +       odp_buffer_t buf = odp_buffer_alloc(pool);
> +       CU_ASSERT(buf != ODP_BUFFER_INVALID);
> +       odp_packet_t pkt = odp_packet_from_buffer(buf);
> +       CU_ASSERT(pkt != ODP_PACKET_INVALID);
> +       uint8_t *data_addr = odp_packet_data(pkt);
> +       memcpy(data_addr, input_vec, input_vec_len);
> +       /* offsets are relative to buffer address (not packet data)
> +       until https://bugs.linaro.org/show_bug.cgi?id=387 is fixed */
>

If we use /** @todo .... */ this bug fix will also appear in the doc if
doxygen is allowed to run on all the code.


> +       int data_off = data_addr - (uint8_t *)odp_buffer_addr(buf);
> +
> +       /* Prepare input/output params */
> +       odp_crypto_op_params_t op_params;
> +       memset(&op_params, 0, sizeof(op_params));
> +       op_params.session = session;
> +       op_params.pkt = pkt;
> +       op_params.out_pkt = pkt;
> +       if (cipher_alg != ODP_CIPHER_ALG_NULL &&
> +           auth_alg == ODP_AUTH_ALG_NULL) {
> +               op_params.cipher_range.offset = data_off;
> +               op_params.cipher_range.length = input_vec_len;
> +               if (op_iv_ptr)
> +                       op_params.override_iv_ptr = op_iv_ptr;
> +       } else if (cipher_alg == ODP_CIPHER_ALG_NULL &&
> +                auth_alg != ODP_AUTH_ALG_NULL) {
> +               op_params.auth_range.offset = data_off;
> +               op_params.auth_range.length = input_vec_len;
> +               op_params.hash_result_offset = data_off;
> +       } else {
> +               CU_FAIL("%s : not implemented for combined alg mode\n");
> +       }
> +
> +       /* TEST : odp_crypto_set_operation_compl_ctx */
> +       /* TEST : odp_crypto_operation */
> +       if (compl_new == ODP_BUFFER_INVALID) {
> +               odp_crypto_set_operation_compl_ctx(buf, (void
> *)0xdeadbeef);
> +               rc = odp_crypto_operation(&op_params, &posted, buf);
> +       } else {
> +               odp_crypto_set_operation_compl_ctx(compl_new,
> +                                                  (void *)0xdeadbeef);
> +               rc = odp_crypto_operation(&op_params, &posted, compl_new);
> +       }
> +       CU_ASSERT(posted);
> +
> +       /* Poll completion queue for results */
> +       do {
> +               compl_event = odp_queue_deq(compl_queue);
> +       } while (compl_event == ODP_BUFFER_INVALID);
> +
> +       if (compl_new == ODP_BUFFER_INVALID) {
> +               CU_ASSERT(compl_event == buf);
> +       } else {
> +               CU_ASSERT(compl_event == compl_new);
> +       }
> +
> +       /* TEST : odp_crypto_get_operation_compl_status */
> +       struct odp_crypto_compl_status auth_status, cipher_status;
> +       odp_crypto_get_operation_compl_status(compl_event,
> +                                             &auth_status,
> &cipher_status);
> +       CU_ASSERT(auth_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
> +       CU_ASSERT(auth_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
> +       CU_ASSERT(cipher_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
> +       CU_ASSERT(cipher_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
> +
> +       /* TEST : odp_crypto_get_operation_compl_packet */
> +       odp_packet_t out_pkt;
> +       out_pkt = odp_crypto_get_operation_compl_packet(compl_event);
> +       CU_ASSERT(out_pkt == pkt);
> +
> +       /* TEST : operation output was correct */
> +       CU_ASSERT(!memcmp(data_addr, output_vec, output_vec_len));
> +
> +       /* TEST : we got back the context pointer */
> +       void *ctx = odp_crypto_get_operation_compl_ctx(compl_event);
> +       CU_ASSERT(ctx == (void *)0xdeadbeef);
> +
> +       odp_buffer_free(buf);
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session
> IV.
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.*/
> +#define ASYNC_INP_ENC_ALG_3DES_CBC     "ENC_ALG_3DES_CBC"
> +static void test_enc_alg_3des_cbc(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv;
> +       unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +                                    sizeof(tdes_cbc_reference_length[0]));
> +
> +       unsigned int i;
> +       for (i = 0; i < test_vec_num; i++) {
> +               cipher_key.data = tdes_cbc_reference_key[i];
> +               cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +               iv.data = tdes_cbc_reference_iv[i];
> +               iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_ENCODE,
> +                        ODP_CIPHER_ALG_3DES_CBC,
> +                        iv,
> +                        NULL,
> +                        cipher_key,
> +                        ODP_AUTH_ALG_NULL,
> +                        auth_key,
> +                        ODP_BUFFER_INVALID,
> +                        tdes_cbc_reference_plaintext[i],
> +                        tdes_cbc_reference_length[i],
> +                        tdes_cbc_reference_ciphertext[i],
> +                        tdes_cbc_reference_length[i]);
> +       }
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the
> operation IV.
> + * */
> +#define ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV      "ENC_ALG_3DES_CBC_OVR_IV"
> +static void test_enc_alg_3des_cbc_ovr_iv(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
> +       unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +                                    sizeof(tdes_cbc_reference_length[0]));
> +
> +       unsigned int i;
> +       for (i = 0; i < test_vec_num; i++) {
> +               cipher_key.data = tdes_cbc_reference_key[i];
> +               cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_ENCODE,
> +                        ODP_CIPHER_ALG_3DES_CBC,
> +                        iv,
> +                        tdes_cbc_reference_iv[i],
> +                        cipher_key,
> +                        ODP_AUTH_ALG_NULL,
> +                        auth_key,
> +                        ODP_BUFFER_INVALID,
> +                        tdes_cbc_reference_plaintext[i],
> +                        tdes_cbc_reference_length[i],
> +                        tdes_cbc_reference_ciphertext[i],
> +                        tdes_cbc_reference_length[i]);
> +       }
> +}
> +
> +
> +/* This test verifies the correctness of decode (ciphertext -> plaintext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session
> IV
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_DEC_ALG_3DES_CBC      "DEC_ALG_3DES_CBC"
> +static void test_dec_alg_3des_cbc(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
> +       unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +                                    sizeof(tdes_cbc_reference_length[0]));
> +
> +       unsigned int i;
> +       for (i = 0; i < test_vec_num; i++) {
> +               cipher_key.data = tdes_cbc_reference_key[i];
> +               cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +               iv.data = tdes_cbc_reference_iv[i];
> +               iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_DECODE,
> +                        ODP_CIPHER_ALG_3DES_CBC,
> +                        iv,
> +                        NULL,
> +                        cipher_key,
> +                        ODP_AUTH_ALG_NULL,
> +                        auth_key,
> +                        ODP_BUFFER_INVALID,
> +                        tdes_cbc_reference_ciphertext[i],
> +                        tdes_cbc_reference_length[i],
> +                        tdes_cbc_reference_plaintext[i],
> +                        tdes_cbc_reference_length[i]);
> +       }
> +}
> +
> +/* This test verifies the correctness of decode (ciphertext -> plaintext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session
> IV
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV       "DEC_ALG_3DES_CBC_OVR_IV"
> +static void test_dec_alg_3des_cbc_ovr_iv(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
> +       unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +                                    sizeof(tdes_cbc_reference_length[0]));
> +
> +       unsigned int i;
> +       for (i = 0; i < test_vec_num; i++) {
> +               cipher_key.data = tdes_cbc_reference_key[i];
> +               cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_DECODE,
> +                        ODP_CIPHER_ALG_3DES_CBC,
> +                        iv,
> +                        tdes_cbc_reference_iv[i],
> +                        cipher_key,
> +                        ODP_AUTH_ALG_NULL,
> +                        auth_key,
> +                        ODP_BUFFER_INVALID,
> +                        tdes_cbc_reference_ciphertext[i],
> +                        tdes_cbc_reference_length[i],
> +                        tdes_cbc_reference_plaintext[i],
> +                        tdes_cbc_reference_length[i]);
> +       }
> +}
> +
> +
> +/* This test verifies the correctness of HMAC_MD5 digest operation.
> + * The output check length is truncated to 12 bytes (96 bits) as
> + * returned by the crypto operation API call.
> + * Note that hash digest is a one-way operation.
> + * In addition the test verifies if the implementation can use the
> + * packet buffer as completion event buffer.
> + * */
> +#define ASYNC_INP_ALG_HMAC_MD5       "ALG_HMAC_MD5"
> +static void test_alg_hmac_md5(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
> +
> +       unsigned int test_vec_num = (sizeof(hmac_md5_reference_length)/
> +                                    sizeof(hmac_md5_reference_length[0]));
> +
> +       unsigned int i;
> +       for (i = 0; i < test_vec_num; i++) {
> +               auth_key.data = hmac_md5_reference_key[i];
> +               auth_key.length = sizeof(hmac_md5_reference_key[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_ENCODE,
> +                        ODP_CIPHER_ALG_NULL,
> +                        iv,
> +                        iv.data,
> +                        cipher_key,
> +                        ODP_AUTH_ALG_MD5_96,
> +                        auth_key,
> +                        ODP_BUFFER_INVALID,
> +                        hmac_md5_reference_plaintext[i],
> +                        hmac_md5_reference_length[i],
> +                        hmac_md5_reference_digest[i],
> +                        HMAC_MD5_96_CHECK_LEN);
> +       }
> +}
> +
> +/* This test verifies the correctness of encode (plaintext -> ciphertext)
> + * operation for 3DES_CBC algorithm. IV for the operation is the session
> IV.
> + * Uses a separate buffer for completion event
> + * */
> +#define ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW
> "ENC_ALG_3DES_CBC_COMPL_NEW"
> +static void test_enc_alg_3des_cbc_compl_new(void)
> +{
> +       odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
> +                        auth_key   = { .data = NULL, .length = 0 };
> +       odp_crypto_iv_t iv;
> +       unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
> +                                    sizeof(tdes_cbc_reference_length[0]));
> +
> +       odp_buffer_pool_t pool = odp_buffer_pool_lookup("compl_pool");
> +       CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
> +
> +       unsigned int i;
> +       odp_buffer_t compl_new;
> +       for (i = 0; i < test_vec_num; i++) {
> +               compl_new = odp_buffer_alloc(pool);
> +               CU_ASSERT(compl_new != ODP_BUFFER_INVALID);
> +
> +               cipher_key.data = tdes_cbc_reference_key[i];
> +               cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
> +               iv.data = tdes_cbc_reference_iv[i];
> +               iv.length = sizeof(tdes_cbc_reference_iv[i]);
> +
> +               alg_test(ODP_CRYPTO_OP_ENCODE,
> +                        ODP_CIPHER_ALG_3DES_CBC,
> +                        iv,
> +                        NULL,
> +                        cipher_key,
> +                        ODP_AUTH_ALG_NULL,
> +                        auth_key,
> +                        compl_new,
> +                        tdes_cbc_reference_plaintext[i],
> +                        tdes_cbc_reference_length[i],
> +                        tdes_cbc_reference_ciphertext[i],
> +                        tdes_cbc_reference_length[i]);
> +               odp_buffer_free(compl_new);

+       }
> +}
> +
> +static CU_TestInfo test_array[] = {
> +       {ASYNC_INP_ENC_ALG_3DES_CBC, test_enc_alg_3des_cbc },
> +       {ASYNC_INP_DEC_ALG_3DES_CBC, test_dec_alg_3des_cbc },
> +       {ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV, test_enc_alg_3des_cbc_ovr_iv },
> +       {ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV, test_dec_alg_3des_cbc_ovr_iv },
> +       {ASYNC_INP_ALG_HMAC_MD5, test_alg_hmac_md5 },
> +       {ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW,
> test_enc_alg_3des_cbc_compl_new },
> +       CU_TEST_INFO_NULL,
> +};
> +
> +CU_SuiteInfo suites[] = {
> +       { ODP_CRYPTO_ASYNC_INP , init, finalise, NULL, NULL, test_array },
> +       CU_SUITE_INFO_NULL,
> +};
> +
> diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.h
> b/test/cunit/crypto/odp_crypto_test_async_inp.h
> new file mode 100644
> index 0000000..818f7e7
> --- /dev/null
> +++ b/test/cunit/crypto/odp_crypto_test_async_inp.h
> @@ -0,0 +1,13 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +#ifndef ODP_CRYPTO_TEST_ASYNC_INP_
> +#define ODP_CRYPTO_TEST_ASYNC_INP_
> +
> +#include "CUnit/Headers/TestDB.h"
> +
> +CU_SuiteInfo suites[1];
> +
> +#endif
> diff --git a/test/cunit/crypto/test_vectors.h
> b/test/cunit/crypto/test_vectors.h
> new file mode 100644
> index 0000000..c151952
> --- /dev/null
> +++ b/test/cunit/crypto/test_vectors.h
> @@ -0,0 +1,94 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:    BSD-3-Clause
> + */
> +
> +
> +/* TDES-CBC reference vectors, according to
> + * "http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf"
> + */
> +
> +#define TDES_CBC_KEY_LEN       24      /* key length(in bytes) for
> tdes-cbc */
> +#define TDES_CBC_IV_LEN                8       /* IV length(in bytes) for
> tdes-cbc */
> +#define TDES_CBC_MAX_DATA_LEN  16      /* max. plain text length(in
> bytes) */
> +
> +static uint8_t tdes_cbc_reference_key[][TDES_CBC_KEY_LEN] = {
> +       {0x62, 0x7f, 0x46, 0x0e, 0x08, 0x10, 0x4a, 0x10, 0x43, 0xcd, 0x26,
> 0x5d,
> +        0x58, 0x40, 0xea, 0xf1, 0x31, 0x3e, 0xdf, 0x97, 0xdf, 0x2a, 0x8a,
> 0x8c,
> +        },
> +
> +       {0x37, 0xae, 0x5e, 0xbf, 0x46, 0xdf, 0xf2, 0xdc, 0x07, 0x54, 0xb9,
> 0x4f,
> +        0x31, 0xcb, 0xb3, 0x85, 0x5e, 0x7f, 0xd3, 0x6d, 0xc8, 0x70, 0xbf,
> 0xae}
> +};
> +
> +static uint8_t tdes_cbc_reference_iv[][TDES_CBC_IV_LEN] = {
> +       {0x8e, 0x29, 0xf7, 0x5e, 0xa7, 0x7e, 0x54, 0x75},
> +
> +       {0x3d, 0x1d, 0xe3, 0xcc, 0x13, 0x2e, 0x3b, 0x65}
> +};
> +
> +/** length in bytes */
> +static uint32_t tdes_cbc_reference_length[] = { 8, 16 };
> +
> +static uint8_t tdes_cbc_reference_plaintext[][TDES_CBC_MAX_DATA_LEN] = {
> +       {0x32, 0x6a, 0x49, 0x4c, 0xd3, 0x3f, 0xe7, 0x56},
> +
> +       {0x84, 0x40, 0x1f, 0x78, 0xfe, 0x6c, 0x10, 0x87, 0x6d, 0x8e, 0xa2,
> 0x30,
> +        0x94, 0xea, 0x53, 0x09}
> +};
> +
> +static uint8_t tdes_cbc_reference_ciphertext[][TDES_CBC_MAX_DATA_LEN] = {
> +       {0xb2, 0x2b, 0x8d, 0x66, 0xde, 0x97, 0x06, 0x92},
> +
> +       {0x7b, 0x1f, 0x7c, 0x7e, 0x3b, 0x1c, 0x94, 0x8e, 0xbd, 0x04, 0xa7,
> 0x5f,
> +        0xfb, 0xa7, 0xd2, 0xf5}
> +};
> +
> +
> +/* HMAC-MD5 test vectors  - RFC2104 */
> +#define HMAC_MD5_KEY_LEN       16
> +#define HMAC_MD5_MAX_DATA_LEN  128
> +#define HMAC_MD5_DIGEST_LEN    16
> +#define HMAC_MD5_96_CHECK_LEN  12
> +
> +static uint8_t hmac_md5_reference_key[][HMAC_MD5_KEY_LEN] = {
> +       { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
> +         0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b } ,
> +
> +       /* "Jefe" */
> +       { 0x4a, 0x65, 0x66, 0x65 },
> +
> +       { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
> +         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }
> +};
> +
> +static uint32_t hmac_md5_reference_length[] = { 8, 28, 50 };
> +
> +static uint8_t hmac_md5_reference_plaintext[][HMAC_MD5_MAX_DATA_LEN] = {
> +       /* "Hi There" */
> +       { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
> +
> +       /* what do ya want for nothing?*/
> +       { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
> +         0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
> +         0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
> +         0x69, 0x6e, 0x67, 0x3f },
> +
> +       { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +         0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +         0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +         0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
> +         0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }
> +};
> +
> +static uint8_t hmac_md5_reference_digest[][HMAC_MD5_DIGEST_LEN] = {
> +       { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
> +         0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
> +
> +       { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
> +         0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
> +
> +       { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
> +         0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }
> +};
> --
> 1.7.3.4
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>

Patch

diff --git a/configure.ac b/configure.ac
index fd69e85..b1785e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -166,6 +166,7 @@  AC_CONFIG_FILES([Makefile
 		 test/Makefile
 		 test/api_test/Makefile
                  test/cunit/Makefile
+		 test/cunit/crypto/Makefile
 		 pkgconfig/libodp.pc])
 
 AC_SEARCH_LIBS([timer_create],[rt posix4])
diff --git a/test/cunit/Makefile.am b/test/cunit/Makefile.am
index 927a5a5..7611145 100644
--- a/test/cunit/Makefile.am
+++ b/test/cunit/Makefile.am
@@ -3,6 +3,8 @@  include $(top_srcdir)/test/Makefile.inc
 AM_CFLAGS += -I$(CUNIT_PATH)/include
 AM_LDFLAGS += -L$(CUNIT_PATH)/lib
 
+SUBDIRS = crypto
+
 if ODP_CUNIT_ENABLED
 TESTS = ${bin_PROGRAMS}
 check_PROGRAMS = ${bin_PROGRAMS}
diff --git a/test/cunit/crypto/Makefile.am b/test/cunit/crypto/Makefile.am
new file mode 100644
index 0000000..b984eaa
--- /dev/null
+++ b/test/cunit/crypto/Makefile.am
@@ -0,0 +1,9 @@ 
+include $(top_srcdir)/test/Makefile.inc
+
+if ODP_CUNIT_ENABLED
+bin_PROGRAMS = odp_crypto
+odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static -lcunit
+endif
+
+dist_odp_crypto_SOURCES = odp_crypto_test_async_inp.c \
+			  odp_crypto_test.c
diff --git a/test/cunit/crypto/odp_crypto_test.c b/test/cunit/crypto/odp_crypto_test.c
new file mode 100644
index 0000000..b5d0dea
--- /dev/null
+++ b/test/cunit/crypto/odp_crypto_test.c
@@ -0,0 +1,26 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp.h>
+#include "CUnit/Headers/Basic.h"
+#include "CUnit/Headers/TestDB.h"
+#include "odp_crypto_test_async_inp.h"
+
+int main(void)
+{
+	/* initialize the CUnit test registry */
+	if (CUE_SUCCESS != CU_initialize_registry())
+		return CU_get_error();
+
+	/* register suites */
+	CU_register_suites(suites);
+	/* Run all tests using the CUnit Basic interface */
+	CU_basic_set_mode(CU_BRM_VERBOSE);
+	CU_basic_run_tests();
+	CU_cleanup_registry();
+
+	return CU_get_error();
+}
diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.c b/test/cunit/crypto/odp_crypto_test_async_inp.c
new file mode 100644
index 0000000..53b7c6d
--- /dev/null
+++ b/test/cunit/crypto/odp_crypto_test_async_inp.c
@@ -0,0 +1,463 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+#include <odp.h>
+#include <odp_crypto.h>
+#include "CUnit/Headers/Basic.h"
+#include "CUnit/Headers/TestDB.h"
+#include "test_vectors.h"
+
+#define pr_error(fmt, ...) \
+	fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
+		__LINE__, __func__, ##__VA_ARGS__)
+
+/* Suite name */
+#define ODP_CRYPTO_ASYNC_INP	"odp_crypto_async_inp"
+
+/* Suite init/finalize funcs */
+/* ODP global/local initialization
+ * Packet pool creation
+ * Crypto output queue creation */
+
+#define SHM_PKT_POOL_SIZE      (512*2048*2)
+#define SHM_PKT_POOL_BUF_SIZE  (1024 * 32)
+
+#define SHM_COMPL_POOL_SIZE	(128*1024)
+#define SHM_COMPL_POOL_BUF_SIZE 128
+
+static int init(void)
+{
+	odp_shm_t shm;
+	void *pool_base = NULL;
+	odp_buffer_pool_t pool;
+	odp_queue_t out_queue;
+
+	if (odp_init_global(NULL, NULL)) {
+		pr_error("ODP global init failed.\n");
+		return -1;
+	}
+	odp_init_local();
+
+	shm = odp_shm_reserve("shm_packet_pool",
+			      SHM_PKT_POOL_SIZE,
+			      ODP_CACHE_LINE_SIZE, 0);
+
+	pool_base = odp_shm_addr(shm);
+	if (!pool_base) {
+		pr_error("Packet pool allocation failed.\n");
+		return -1;
+	}
+
+	pool = odp_buffer_pool_create("packet_pool", pool_base,
+				      SHM_PKT_POOL_SIZE,
+				      SHM_PKT_POOL_BUF_SIZE,
+				      ODP_CACHE_LINE_SIZE,
+				      ODP_BUFFER_TYPE_PACKET);
+	if (pool == ODP_BUFFER_POOL_INVALID) {
+		pr_error("Packet pool creation failed.\n");
+		/* TODO - cleanup */
+		return -1;
+	}
+	out_queue = odp_queue_create("crypto-out",
+				     ODP_QUEUE_TYPE_POLL, NULL);
+	if (out_queue == ODP_QUEUE_INVALID) {
+		pr_error("Crypto outq creation failed.\n");
+		/* TODO - cleanup */
+		return -1;
+	}
+	shm = odp_shm_reserve("shm_compl_pool",
+			     SHM_COMPL_POOL_SIZE,
+			     ODP_CACHE_LINE_SIZE,
+			     ODP_SHM_SW_ONLY);
+	pool_base = odp_shm_addr(shm);
+	if (!pool_base) {
+		pr_error("Completion pool allocation failed.\n");
+		return -1;
+	}
+	pool = odp_buffer_pool_create("compl_pool", pool_base,
+				      SHM_COMPL_POOL_SIZE,
+				      SHM_COMPL_POOL_BUF_SIZE,
+				      ODP_CACHE_LINE_SIZE,
+				      ODP_BUFFER_TYPE_RAW);
+	if (pool == ODP_BUFFER_POOL_INVALID) {
+		pr_error("Completion pool creation failed.\n");
+		return -1;
+	}
+
+	printf("\tODP version: %s\n", odp_version_api_str());
+	return 0;
+}
+
+/* ODP cleanup */
+static int finalise(void)
+{
+	return 0;
+}
+
+
+/* Basic algorithm run function.
+ * Creates a session from input parameters and runs one operation
+ * on input_vec. Checks the output of the crypto operation against
+ * output_vec. Operation completion event is dequeued polling the
+ * session output queue. Completion context pointer is retrieved
+ * and checked against the one set before the operation.
+ * */
+static void alg_test(enum odp_crypto_op op,
+		     enum odp_cipher_alg cipher_alg,
+		     odp_crypto_iv_t ses_iv,
+		     uint8_t *op_iv_ptr,
+		     odp_crypto_key_t cipher_key,
+		     enum odp_auth_alg auth_alg,
+		     odp_crypto_key_t auth_key,
+		     odp_buffer_t compl_new,
+		     uint8_t *input_vec,
+		     unsigned int input_vec_len,
+		     uint8_t *output_vec,
+		     unsigned int output_vec_len)
+{
+	odp_crypto_session_t session;
+	int rc;
+	enum odp_crypto_ses_create_err status;
+	bool posted;
+	odp_buffer_t compl_event;
+
+	odp_queue_t compl_queue = odp_queue_lookup("crypto-out");
+	CU_ASSERT(compl_queue != ODP_QUEUE_INVALID);
+	odp_buffer_pool_t pool = odp_buffer_pool_lookup("packet_pool");
+	CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
+
+	/* Create a crypto session */
+	odp_crypto_session_params_t ses_params;
+	memset(&ses_params, 0, sizeof(ses_params));
+	ses_params.op = op;
+	ses_params.auth_cipher_text = false;
+	ses_params.pref_mode = ODP_CRYPTO_ASYNC;
+	ses_params.cipher_alg = cipher_alg;
+	ses_params.auth_alg = auth_alg;
+	ses_params.compl_queue = compl_queue;
+	ses_params.output_pool = pool;
+	ses_params.cipher_key = cipher_key;
+	ses_params.iv = ses_iv;
+	ses_params.auth_key = auth_key;
+
+	/* TEST : odp_crypto_session_create */
+	rc = odp_crypto_session_create(&ses_params, &session, &status);
+	CU_ASSERT(!rc);
+	CU_ASSERT(status == ODP_CRYPTO_SES_CREATE_ERR_NONE);
+
+	/* Prepare input data */
+	odp_buffer_t buf = odp_buffer_alloc(pool);
+	CU_ASSERT(buf != ODP_BUFFER_INVALID);
+	odp_packet_t pkt = odp_packet_from_buffer(buf);
+	CU_ASSERT(pkt != ODP_PACKET_INVALID);
+	uint8_t *data_addr = odp_packet_data(pkt);
+	memcpy(data_addr, input_vec, input_vec_len);
+	/* offsets are relative to buffer address (not packet data)
+	until https://bugs.linaro.org/show_bug.cgi?id=387 is fixed */
+	int data_off = data_addr - (uint8_t *)odp_buffer_addr(buf);
+
+	/* Prepare input/output params */
+	odp_crypto_op_params_t op_params;
+	memset(&op_params, 0, sizeof(op_params));
+	op_params.session = session;
+	op_params.pkt = pkt;
+	op_params.out_pkt = pkt;
+	if (cipher_alg != ODP_CIPHER_ALG_NULL &&
+	    auth_alg == ODP_AUTH_ALG_NULL) {
+		op_params.cipher_range.offset = data_off;
+		op_params.cipher_range.length = input_vec_len;
+		if (op_iv_ptr)
+			op_params.override_iv_ptr = op_iv_ptr;
+	} else if (cipher_alg == ODP_CIPHER_ALG_NULL &&
+		 auth_alg != ODP_AUTH_ALG_NULL) {
+		op_params.auth_range.offset = data_off;
+		op_params.auth_range.length = input_vec_len;
+		op_params.hash_result_offset = data_off;
+	} else {
+		CU_FAIL("%s : not implemented for combined alg mode\n");
+	}
+
+	/* TEST : odp_crypto_set_operation_compl_ctx */
+	/* TEST : odp_crypto_operation */
+	if (compl_new == ODP_BUFFER_INVALID) {
+		odp_crypto_set_operation_compl_ctx(buf, (void *)0xdeadbeef);
+		rc = odp_crypto_operation(&op_params, &posted, buf);
+	} else {
+		odp_crypto_set_operation_compl_ctx(compl_new,
+						   (void *)0xdeadbeef);
+		rc = odp_crypto_operation(&op_params, &posted, compl_new);
+	}
+	CU_ASSERT(posted);
+
+	/* Poll completion queue for results */
+	do {
+		compl_event = odp_queue_deq(compl_queue);
+	} while (compl_event == ODP_BUFFER_INVALID);
+
+	if (compl_new == ODP_BUFFER_INVALID) {
+		CU_ASSERT(compl_event == buf);
+	} else {
+		CU_ASSERT(compl_event == compl_new);
+	}
+
+	/* TEST : odp_crypto_get_operation_compl_status */
+	struct odp_crypto_compl_status auth_status, cipher_status;
+	odp_crypto_get_operation_compl_status(compl_event,
+					      &auth_status, &cipher_status);
+	CU_ASSERT(auth_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
+	CU_ASSERT(auth_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
+	CU_ASSERT(cipher_status.alg_err == ODP_CRYPTO_ALG_ERR_NONE);
+	CU_ASSERT(cipher_status.hw_err == ODP_CRYPTO_HW_ERR_NONE);
+
+	/* TEST : odp_crypto_get_operation_compl_packet */
+	odp_packet_t out_pkt;
+	out_pkt = odp_crypto_get_operation_compl_packet(compl_event);
+	CU_ASSERT(out_pkt == pkt);
+
+	/* TEST : operation output was correct */
+	CU_ASSERT(!memcmp(data_addr, output_vec, output_vec_len));
+
+	/* TEST : we got back the context pointer */
+	void *ctx = odp_crypto_get_operation_compl_ctx(compl_event);
+	CU_ASSERT(ctx == (void *)0xdeadbeef);
+
+	odp_buffer_free(buf);
+}
+
+/* This test verifies the correctness of encode (plaintext -> ciphertext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV.
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.*/
+#define ASYNC_INP_ENC_ALG_3DES_CBC	"ENC_ALG_3DES_CBC"
+static void test_enc_alg_3des_cbc(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv;
+	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
+				     sizeof(tdes_cbc_reference_length[0]));
+
+	unsigned int i;
+	for (i = 0; i < test_vec_num; i++) {
+		cipher_key.data = tdes_cbc_reference_key[i];
+		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
+		iv.data = tdes_cbc_reference_iv[i];
+		iv.length = sizeof(tdes_cbc_reference_iv[i]);
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 ODP_CIPHER_ALG_3DES_CBC,
+			 iv,
+			 NULL,
+			 cipher_key,
+			 ODP_AUTH_ALG_NULL,
+			 auth_key,
+			 ODP_BUFFER_INVALID,
+			 tdes_cbc_reference_plaintext[i],
+			 tdes_cbc_reference_length[i],
+			 tdes_cbc_reference_ciphertext[i],
+			 tdes_cbc_reference_length[i]);
+	}
+}
+
+/* This test verifies the correctness of encode (plaintext -> ciphertext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the operation IV.
+ * */
+#define ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV	"ENC_ALG_3DES_CBC_OVR_IV"
+static void test_enc_alg_3des_cbc_ovr_iv(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
+	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
+				     sizeof(tdes_cbc_reference_length[0]));
+
+	unsigned int i;
+	for (i = 0; i < test_vec_num; i++) {
+		cipher_key.data = tdes_cbc_reference_key[i];
+		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 ODP_CIPHER_ALG_3DES_CBC,
+			 iv,
+			 tdes_cbc_reference_iv[i],
+			 cipher_key,
+			 ODP_AUTH_ALG_NULL,
+			 auth_key,
+			 ODP_BUFFER_INVALID,
+			 tdes_cbc_reference_plaintext[i],
+			 tdes_cbc_reference_length[i],
+			 tdes_cbc_reference_ciphertext[i],
+			 tdes_cbc_reference_length[i]);
+	}
+}
+
+
+/* This test verifies the correctness of decode (ciphertext -> plaintext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.
+ * */
+#define ASYNC_INP_DEC_ALG_3DES_CBC	 "DEC_ALG_3DES_CBC"
+static void test_dec_alg_3des_cbc(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
+	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
+				     sizeof(tdes_cbc_reference_length[0]));
+
+	unsigned int i;
+	for (i = 0; i < test_vec_num; i++) {
+		cipher_key.data = tdes_cbc_reference_key[i];
+		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
+		iv.data = tdes_cbc_reference_iv[i];
+		iv.length = sizeof(tdes_cbc_reference_iv[i]);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 ODP_CIPHER_ALG_3DES_CBC,
+			 iv,
+			 NULL,
+			 cipher_key,
+			 ODP_AUTH_ALG_NULL,
+			 auth_key,
+			 ODP_BUFFER_INVALID,
+			 tdes_cbc_reference_ciphertext[i],
+			 tdes_cbc_reference_length[i],
+			 tdes_cbc_reference_plaintext[i],
+			 tdes_cbc_reference_length[i]);
+	}
+}
+
+/* This test verifies the correctness of decode (ciphertext -> plaintext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.
+ * */
+#define ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV	 "DEC_ALG_3DES_CBC_OVR_IV"
+static void test_dec_alg_3des_cbc_ovr_iv(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = TDES_CBC_IV_LEN };
+	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
+				     sizeof(tdes_cbc_reference_length[0]));
+
+	unsigned int i;
+	for (i = 0; i < test_vec_num; i++) {
+		cipher_key.data = tdes_cbc_reference_key[i];
+		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 ODP_CIPHER_ALG_3DES_CBC,
+			 iv,
+			 tdes_cbc_reference_iv[i],
+			 cipher_key,
+			 ODP_AUTH_ALG_NULL,
+			 auth_key,
+			 ODP_BUFFER_INVALID,
+			 tdes_cbc_reference_ciphertext[i],
+			 tdes_cbc_reference_length[i],
+			 tdes_cbc_reference_plaintext[i],
+			 tdes_cbc_reference_length[i]);
+	}
+}
+
+
+/* This test verifies the correctness of HMAC_MD5 digest operation.
+ * The output check length is truncated to 12 bytes (96 bits) as
+ * returned by the crypto operation API call.
+ * Note that hash digest is a one-way operation.
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.
+ * */
+#define ASYNC_INP_ALG_HMAC_MD5	      "ALG_HMAC_MD5"
+static void test_alg_hmac_md5(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
+
+	unsigned int test_vec_num = (sizeof(hmac_md5_reference_length)/
+				     sizeof(hmac_md5_reference_length[0]));
+
+	unsigned int i;
+	for (i = 0; i < test_vec_num; i++) {
+		auth_key.data = hmac_md5_reference_key[i];
+		auth_key.length = sizeof(hmac_md5_reference_key[i]);
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_MD5_96,
+			 auth_key,
+			 ODP_BUFFER_INVALID,
+			 hmac_md5_reference_plaintext[i],
+			 hmac_md5_reference_length[i],
+			 hmac_md5_reference_digest[i],
+			 HMAC_MD5_96_CHECK_LEN);
+	}
+}
+
+/* This test verifies the correctness of encode (plaintext -> ciphertext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV.
+ * Uses a separate buffer for completion event
+ * */
+#define ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW	   "ENC_ALG_3DES_CBC_COMPL_NEW"
+static void test_enc_alg_3des_cbc_compl_new(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv;
+	unsigned int test_vec_num = (sizeof(tdes_cbc_reference_length)/
+				     sizeof(tdes_cbc_reference_length[0]));
+
+	odp_buffer_pool_t pool = odp_buffer_pool_lookup("compl_pool");
+	CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID);
+
+	unsigned int i;
+	odp_buffer_t compl_new;
+	for (i = 0; i < test_vec_num; i++) {
+		compl_new = odp_buffer_alloc(pool);
+		CU_ASSERT(compl_new != ODP_BUFFER_INVALID);
+
+		cipher_key.data = tdes_cbc_reference_key[i];
+		cipher_key.length = sizeof(tdes_cbc_reference_key[i]);
+		iv.data = tdes_cbc_reference_iv[i];
+		iv.length = sizeof(tdes_cbc_reference_iv[i]);
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 ODP_CIPHER_ALG_3DES_CBC,
+			 iv,
+			 NULL,
+			 cipher_key,
+			 ODP_AUTH_ALG_NULL,
+			 auth_key,
+			 compl_new,
+			 tdes_cbc_reference_plaintext[i],
+			 tdes_cbc_reference_length[i],
+			 tdes_cbc_reference_ciphertext[i],
+			 tdes_cbc_reference_length[i]);
+		odp_buffer_free(compl_new);
+	}
+}
+
+static CU_TestInfo test_array[] = {
+	{ASYNC_INP_ENC_ALG_3DES_CBC, test_enc_alg_3des_cbc },
+	{ASYNC_INP_DEC_ALG_3DES_CBC, test_dec_alg_3des_cbc },
+	{ASYNC_INP_ENC_ALG_3DES_CBC_OVR_IV, test_enc_alg_3des_cbc_ovr_iv },
+	{ASYNC_INP_DEC_ALG_3DES_CBC_OVR_IV, test_dec_alg_3des_cbc_ovr_iv },
+	{ASYNC_INP_ALG_HMAC_MD5, test_alg_hmac_md5 },
+	{ASYNC_INP_ENC_ALG_3DES_CBC_COMPL_NEW, test_enc_alg_3des_cbc_compl_new },
+	CU_TEST_INFO_NULL,
+};
+
+CU_SuiteInfo suites[] = {
+	{ ODP_CRYPTO_ASYNC_INP , init, finalise, NULL, NULL, test_array },
+	CU_SUITE_INFO_NULL,
+};
+
diff --git a/test/cunit/crypto/odp_crypto_test_async_inp.h b/test/cunit/crypto/odp_crypto_test_async_inp.h
new file mode 100644
index 0000000..818f7e7
--- /dev/null
+++ b/test/cunit/crypto/odp_crypto_test_async_inp.h
@@ -0,0 +1,13 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+#ifndef ODP_CRYPTO_TEST_ASYNC_INP_
+#define ODP_CRYPTO_TEST_ASYNC_INP_
+
+#include "CUnit/Headers/TestDB.h"
+
+CU_SuiteInfo suites[1];
+
+#endif
diff --git a/test/cunit/crypto/test_vectors.h b/test/cunit/crypto/test_vectors.h
new file mode 100644
index 0000000..c151952
--- /dev/null
+++ b/test/cunit/crypto/test_vectors.h
@@ -0,0 +1,94 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+
+/* TDES-CBC reference vectors, according to
+ * "http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf"
+ */
+
+#define TDES_CBC_KEY_LEN	24	/* key length(in bytes) for tdes-cbc */
+#define TDES_CBC_IV_LEN		8	/* IV length(in bytes) for tdes-cbc */
+#define TDES_CBC_MAX_DATA_LEN	16	/* max. plain text length(in bytes) */
+
+static uint8_t tdes_cbc_reference_key[][TDES_CBC_KEY_LEN] = {
+	{0x62, 0x7f, 0x46, 0x0e, 0x08, 0x10, 0x4a, 0x10, 0x43, 0xcd, 0x26, 0x5d,
+	 0x58, 0x40, 0xea, 0xf1, 0x31, 0x3e, 0xdf, 0x97, 0xdf, 0x2a, 0x8a, 0x8c,
+	 },
+
+	{0x37, 0xae, 0x5e, 0xbf, 0x46, 0xdf, 0xf2, 0xdc, 0x07, 0x54, 0xb9, 0x4f,
+	 0x31, 0xcb, 0xb3, 0x85, 0x5e, 0x7f, 0xd3, 0x6d, 0xc8, 0x70, 0xbf, 0xae}
+};
+
+static uint8_t tdes_cbc_reference_iv[][TDES_CBC_IV_LEN] = {
+	{0x8e, 0x29, 0xf7, 0x5e, 0xa7, 0x7e, 0x54, 0x75},
+
+	{0x3d, 0x1d, 0xe3, 0xcc, 0x13, 0x2e, 0x3b, 0x65}
+};
+
+/** length in bytes */
+static uint32_t tdes_cbc_reference_length[] = { 8, 16 };
+
+static uint8_t tdes_cbc_reference_plaintext[][TDES_CBC_MAX_DATA_LEN] = {
+	{0x32, 0x6a, 0x49, 0x4c, 0xd3, 0x3f, 0xe7, 0x56},
+
+	{0x84, 0x40, 0x1f, 0x78, 0xfe, 0x6c, 0x10, 0x87, 0x6d, 0x8e, 0xa2, 0x30,
+	 0x94, 0xea, 0x53, 0x09}
+};
+
+static uint8_t tdes_cbc_reference_ciphertext[][TDES_CBC_MAX_DATA_LEN] = {
+	{0xb2, 0x2b, 0x8d, 0x66, 0xde, 0x97, 0x06, 0x92},
+
+	{0x7b, 0x1f, 0x7c, 0x7e, 0x3b, 0x1c, 0x94, 0x8e, 0xbd, 0x04, 0xa7, 0x5f,
+	 0xfb, 0xa7, 0xd2, 0xf5}
+};
+
+
+/* HMAC-MD5 test vectors  - RFC2104 */
+#define HMAC_MD5_KEY_LEN	16
+#define HMAC_MD5_MAX_DATA_LEN	128
+#define HMAC_MD5_DIGEST_LEN	16
+#define HMAC_MD5_96_CHECK_LEN	12
+
+static uint8_t hmac_md5_reference_key[][HMAC_MD5_KEY_LEN] = {
+	{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b } ,
+
+	/* "Jefe" */
+	{ 0x4a, 0x65, 0x66, 0x65 },
+
+	{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }
+};
+
+static uint32_t hmac_md5_reference_length[] = { 8, 28, 50 };
+
+static uint8_t hmac_md5_reference_plaintext[][HMAC_MD5_MAX_DATA_LEN] = {
+	/* "Hi There" */
+	{ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
+
+	/* what do ya want for nothing?*/
+	{ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+	  0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+	  0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+	  0x69, 0x6e, 0x67, 0x3f },
+
+	{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }
+};
+
+static uint8_t hmac_md5_reference_digest[][HMAC_MD5_DIGEST_LEN] = {
+	{ 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+	  0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
+
+	{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+	  0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
+
+	{ 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+	  0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }
+};