diff options
Diffstat (limited to 'src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c')
-rw-r--r-- | src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c b/src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c new file mode 100644 index 000000000..eddef42e3 --- /dev/null +++ b/src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c @@ -0,0 +1,511 @@ +/***************************************************************************** + Copyright (c) 2019, Intel Corporation + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <intel-ipsec-mb.h> + +#include "gcm_ctr_vectors_test.h" +#include "utils.h" + +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 + +int chained_test(const enum arch_type arch, struct MB_MGR *mb_mgr); + +struct chained_vector { + const uint8_t *cipher_key; /* cipher key */ + uint32_t cipher_key_len; /* cipher key length */ + const uint8_t *IV; /* initialization vector */ + const uint8_t *PT; /* plaintext */ + uint64_t PTlen; /* plaintext length */ + const uint8_t *CT; /* ciphertext - same length as PT */ + const uint8_t *hash_key; /* hash key */ + uint32_t hash_key_len; /* hash key length */ + const uint8_t *Digest_PT; /* digest for plaintext */ + const uint8_t *Digest_CT; /* digest for ciphertext */ + uint32_t Digest_len; /* digest length */ +}; + +const struct test_set { + JOB_CIPHER_DIRECTION dir; + JOB_CHAIN_ORDER order; + const char *set_name; +} test_sets[] = { + { + .dir = ENCRYPT, + .order = CIPHER_HASH, + .set_name = "encrypt-hash" + }, + { + .dir = DECRYPT, + .order = CIPHER_HASH, + .set_name = "decrypt-hash" + }, + { + .dir = ENCRYPT, + .order = HASH_CIPHER, + .set_name = "hash-encrypt" + }, + { + .dir = DECRYPT, + .order = HASH_CIPHER, + .set_name = "hash-decrypt" + }, + +}; + +const char *place_str[] = {"out-of-place", "in-place"}; + +/* AES-CBC + SHA1-HMAC test vectors */ + +/* 128-bit */ +static const uint8_t K1[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const uint8_t IV1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; +static const uint8_t P1[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +static const uint8_t C1[] = { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, + 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, + 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 +}; +static const uint8_t DP1[] = { + 0x6F, 0xA4, 0x7D, 0x1B, 0x8E, 0xAB, 0x1D, 0xB9, + 0x8B, 0x62, 0xC9, 0xF2, 0xDF, 0xA2, 0xCC, 0x46, + 0x37, 0xB8, 0xD7, 0xB1 +}; +static const uint8_t DC1[] = { + 0xDF, 0x1E, 0x5A, 0xDB, 0xE7, 0x5A, 0xAB, 0xAE, + 0x0B, 0x98, 0x34, 0x30, 0xE8, 0x40, 0x8B, 0xB4, + 0xDB, 0x22, 0x3A, 0x89 +}; + +/* Same key for cipher and hash */ +static const struct chained_vector chained_vectors[] = { + {K1, sizeof(K1), IV1, P1, sizeof(P1), C1, + K1, sizeof(K1), DP1, DC1, sizeof(DP1)}, +}; + +static int +chained_job_ok(const JOB_AES_HMAC *job, + const unsigned num_vec, + const uint8_t *expected_text, + const unsigned text_len, + const uint8_t *received_text, + const uint8_t *expected_digest, + const unsigned digest_len, + const uint8_t *received_digest, + const uint8_t *padding, + const size_t sizeof_padding) +{ + if (job->status != STS_COMPLETED) { + printf("%d error status:%d, job %d", + __LINE__, job->status, num_vec); + return 0; + } + + /* cipher checks */ + if (memcmp(expected_text, received_text + sizeof_padding, + text_len)) { + printf("cipher %d mismatched\n", num_vec); + hexdump(stderr, "Received", received_text + sizeof_padding, + text_len); + hexdump(stderr, "Expected", expected_text, + text_len); + return 0; + } + + if (memcmp(padding, received_text, sizeof_padding)) { + printf("cipher %d overwrite head\n", num_vec); + hexdump(stderr, "Target", received_text, sizeof_padding); + return 0; + } + + if (memcmp(padding, + received_text + sizeof_padding + text_len, + sizeof_padding)) { + printf("cipher %d overwrite tail\n", num_vec); + hexdump(stderr, "Target", + received_text + sizeof_padding + text_len, + sizeof_padding); + return 0; + } + + /* hash checks */ + if (memcmp(expected_digest, received_digest + sizeof_padding, + digest_len)) { + printf("hash %d mismatched\n", num_vec); + hexdump(stderr, "Received", received_digest + sizeof_padding, + digest_len); + hexdump(stderr, "Expected", expected_digest, + digest_len); + return 0; + } + + if (memcmp(padding, received_digest, sizeof_padding)) { + printf("hash %d overwrite head\n", num_vec); + hexdump(stderr, "Target", received_digest, sizeof_padding); + return 0; + } + + if (memcmp(padding, received_digest + sizeof_padding + digest_len, + sizeof_padding)) { + printf("hash %d overwrite tail\n", num_vec); + hexdump(stderr, "Target", + received_digest + sizeof_padding + digest_len, + sizeof_padding); + return 0; + } + + + return 1; +} + +static int +test_chained_many(struct MB_MGR *mb_mgr, + const void *enc_keys, + const void *dec_keys, + const struct chained_vector *vec, + JOB_CIPHER_DIRECTION dir, + JOB_CHAIN_ORDER order, + JOB_CIPHER_MODE cipher, + JOB_HASH_ALG hash, + const void *ipad_hash, + const void *opad_hash, + const unsigned in_place, + const unsigned num_jobs) +{ + struct JOB_AES_HMAC *job; + uint8_t padding[16]; + uint8_t **targets = NULL; + uint8_t **auths = NULL; + unsigned i, jobs_rx = 0; + int ret = -1; + const unsigned cipher_key_size = vec->cipher_key_len; + const void *iv = vec->IV; + const unsigned text_len = (unsigned) vec->PTlen; + const unsigned digest_size = vec->Digest_len; + const uint8_t *in_text = (dir == ENCRYPT) ? vec->PT : vec->CT; + const uint8_t *out_text = (dir == ENCRYPT) ? vec->CT : vec->PT; + const uint8_t *digest; + + if (num_jobs == 0) + return 0; + + if ((dir == ENCRYPT && order == CIPHER_HASH) || + (dir == DECRYPT && order == HASH_CIPHER)) + digest = vec->Digest_CT; + else + digest = vec->Digest_PT; + + targets = malloc(num_jobs * sizeof(void *)); + if (targets == NULL) { + fprintf(stderr, "Can't allocate memory for targets array\n"); + goto end; + } + memset(targets, 0, num_jobs * sizeof(void *)); + auths = malloc(num_jobs * sizeof(void *)); + if (auths == NULL) { + fprintf(stderr, "Can't allocate memory for auths array\n"); + goto end; + } + memset(auths, 0, num_jobs * sizeof(void *)); + + memset(padding, -1, sizeof(padding)); + + for (i = 0; i < num_jobs; i++) { + targets[i] = malloc(text_len + (sizeof(padding) * 2)); + if (targets[i] == NULL) { + fprintf(stderr, "Can't allocate buffer memory\n"); + goto end; + } + memset(targets[i], -1, text_len + (sizeof(padding) * 2)); + if (in_place) { + /* copy input text to the allocated buffer */ + memcpy(targets[i] + sizeof(padding), in_text, text_len); + } + + auths[i] = malloc(digest_size + (sizeof(padding) * 2)); + if (auths[i] == NULL) { + fprintf(stderr, "Can't allocate buffer memory\n"); + goto end; + } + memset(auths[i], -1, digest_size + (sizeof(padding) * 2)); + } + + /* flush the scheduler */ + while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) + ; + + for (i = 0; i < num_jobs; i++) { + job = IMB_GET_NEXT_JOB(mb_mgr); + job->cipher_direction = dir; + job->chain_order = order; + if (in_place) { + job->dst = targets[i] + sizeof(padding); + job->src = targets[i] + sizeof(padding); + } else { + job->dst = targets[i] + sizeof(padding); + job->src = in_text; + } + job->cipher_mode = cipher; + job->aes_enc_key_expanded = enc_keys; + job->aes_dec_key_expanded = dec_keys; + job->aes_key_len_in_bytes = cipher_key_size; + + job->iv = iv; + job->iv_len_in_bytes = 16; + job->cipher_start_src_offset_in_bytes = 0; + job->msg_len_to_cipher_in_bytes = text_len; + job->user_data = (void *)((uint64_t)i); + + job->hash_alg = hash; + job->auth_tag_output = auths[i] + sizeof(padding); + job->auth_tag_output_len_in_bytes = digest_size; + /* + * If operation is out of place and hash operation is done + * after encryption/decryption, hash operation needs to be + * done in the destination buffer. + * Since hash_start_src_offset_in_bytes refers to the offset + * in the source buffer, this offset is set to point at + * the destination buffer. + */ + if (!in_place && (job->chain_order == CIPHER_HASH)) { + const uintptr_t u_src = (const uintptr_t) job->src; + const uintptr_t u_dst = (const uintptr_t) job->dst; + const uintptr_t offset = (u_dst > u_src) ? + (u_dst - u_src) : + (UINTPTR_MAX - u_src + u_dst + 1); + + job->hash_start_src_offset_in_bytes = (uint64_t)offset; + } else { + job->hash_start_src_offset_in_bytes = 0; + } + job->msg_len_to_hash_in_bytes = text_len; + job->u.HMAC._hashed_auth_key_xor_ipad = ipad_hash; + job->u.HMAC._hashed_auth_key_xor_opad = opad_hash; + + job = IMB_SUBMIT_JOB(mb_mgr); + if (job != NULL) { + jobs_rx++; + const unsigned num = + (const unsigned)((uint64_t)job->user_data); + + if (!chained_job_ok(job, num, out_text, text_len, + targets[num], + digest, digest_size, auths[num], + padding, sizeof(padding))) + goto end; + } + } + + while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) { + jobs_rx++; + const int num = (const unsigned)((uint64_t)job->user_data); + + if (!chained_job_ok(job, num, out_text, text_len, targets[num], + digest, digest_size, auths[num], + padding, sizeof(padding))) + goto end; + } + + if (jobs_rx != num_jobs) { + printf("Expected %d jobs, received %d\n", num_jobs, jobs_rx); + goto end; + } + ret = 0; + + end: + while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) + ; + + for (i = 0; i < num_jobs; i++) { + if (targets != NULL) + free(targets[i]); + if (auths != NULL) + free(auths[i]); + } + free(targets); + free(auths); + return ret; +} + +static int +test_chained_vectors(struct MB_MGR *mb_mgr, const int vec_cnt, + const struct chained_vector *vec_tab, const char *banner, + const JOB_CIPHER_MODE cipher, + const JOB_HASH_ALG hash, + unsigned hash_block_size, int num_jobs) +{ + int vect, errors = 0; + DECLARE_ALIGNED(uint32_t enc_keys[15*4], 16); + DECLARE_ALIGNED(uint32_t dec_keys[15*4], 16); + uint8_t *buf = NULL; + uint8_t *hash_key = NULL; + DECLARE_ALIGNED(uint8_t ipad_hash[128], 16); + DECLARE_ALIGNED(uint8_t opad_hash[128], 16); + unsigned hash_key_len, i; + + buf = malloc(hash_block_size); + if (buf == NULL) { + fprintf(stderr, "Can't allocate buffer memory\n"); + goto exit; + } + + hash_key = malloc(hash_block_size); + if (hash_key == NULL) { + fprintf(stderr, "Can't allocate key memory\n"); + goto exit; + } + + printf("%s (N jobs = %d):\n", banner, num_jobs); + for (vect = 0; vect < vec_cnt; vect++) { +#ifdef DEBUG + printf("[%d/%d] Standard vector key_len:%d\n", + vect + 1, vec_cnt, + (int) vec_tab[vect].cipher_key_len); +#else + printf("."); +#endif + /* prepare the cipher key */ + switch (vec_tab[vect].cipher_key_len) { + case 16: + IMB_AES_KEYEXP_128(mb_mgr, vec_tab[vect].cipher_key, + enc_keys, dec_keys); + break; + case 24: + IMB_AES_KEYEXP_192(mb_mgr, vec_tab[vect].cipher_key, + enc_keys, dec_keys); + break; + case 32: + default: + IMB_AES_KEYEXP_256(mb_mgr, vec_tab[vect].cipher_key, + enc_keys, dec_keys); + break; + } + + /* prepare the hash key */ + memset(hash_key, 0, hash_block_size); + if (vec_tab[vect].hash_key_len <= hash_block_size) { + memcpy(hash_key, vec_tab[vect].hash_key, + vec_tab[vect].hash_key_len); + hash_key_len = (int) vec_tab[vect].hash_key_len; + } else { + IMB_SHA1(mb_mgr, vec_tab[vect].hash_key, + vec_tab[vect].hash_key_len, hash_key); + hash_key_len = hash_block_size; + } + + /* compute ipad hash */ + memset(buf, 0x36, hash_block_size); + for (i = 0; i < hash_key_len; i++) + buf[i] ^= hash_key[i]; + IMB_SHA1_ONE_BLOCK(mb_mgr, buf, ipad_hash); + + /* compute opad hash */ + memset(buf, 0x5c, hash_block_size); + for (i = 0; i < hash_key_len; i++) + buf[i] ^= hash_key[i]; + IMB_SHA1_ONE_BLOCK(mb_mgr, buf, opad_hash); + + for (i = 0; i < DIM(test_sets); i++) { + unsigned in_place; + + for (in_place = 0; in_place < DIM(place_str); + in_place++) { + if (test_chained_many(mb_mgr, + enc_keys, dec_keys, + &vec_tab[vect], + test_sets[i].dir, + test_sets[i].order, + cipher, hash, + ipad_hash, opad_hash, + in_place, num_jobs)) { + printf("error #%d %s %s\n", vect + 1, + test_sets[i].set_name, + place_str[in_place]); + errors++; + } + } + } + } + printf("\n"); + +exit: + free(buf); + free(hash_key); + return errors; +} + +int +chained_test(const enum arch_type arch, + struct MB_MGR *mb_mgr) +{ + const int num_jobs_tab[] = { + 1, 3, 4, 5, 7, 8, 9, 15, 16, 17 + }; + unsigned i; + int errors = 0; + + (void) arch; /* unused */ + + for (i = 0; i < DIM(num_jobs_tab); i++) + errors += test_chained_vectors(mb_mgr, DIM(chained_vectors), + chained_vectors, + "AES-CBC + SHA1-HMAC standard test vectors", + CBC, SHA1, SHA1_BLOCK_SIZE, + num_jobs_tab[i]); + if (0 == errors) + printf("...Pass\n"); + else + printf("...Fail\n"); + + return errors; +} |