From patchwork Thu Apr 6 11:39:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Uvarov X-Patchwork-Id: 96928 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp687943qgd; Thu, 6 Apr 2017 04:40:10 -0700 (PDT) X-Received: by 10.55.125.132 with SMTP id y126mr31611159qkc.314.1491478810326; Thu, 06 Apr 2017 04:40:10 -0700 (PDT) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id p206si1173278qke.7.2017.04.06.04.40.08; Thu, 06 Apr 2017 04:40:10 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id C599064354; Thu, 6 Apr 2017 11:40:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 111EC63631; Thu, 6 Apr 2017 11:39:55 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 0B47E642B4; Thu, 6 Apr 2017 11:39:52 +0000 (UTC) Received: from mail-lf0-f45.google.com (mail-lf0-f45.google.com [209.85.215.45]) by lists.linaro.org (Postfix) with ESMTPS id 69B0160D43 for ; Thu, 6 Apr 2017 11:39:49 +0000 (UTC) Received: by mail-lf0-f45.google.com with SMTP id j90so24421403lfk.2 for ; Thu, 06 Apr 2017 04:39:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=3/WU8SQaoK5XRDADGs2lZtn8vFVkGgmtEXsjOCAnR64=; b=NHs/hWIU7rar8WZgVgYkKi95QWLhyciKkVrtyxXUnlUdERqAtCWvu1rwNElyX2RNEl pBT2QuPsBybPW14zqfRWxPSQ36YCO0yYpnmhOWLYYN0IA33VbpfUf7NAJeWh5ss/gZcI ztSCiK+cQ8PChsfymIOlXe0NgARbGAU8xsnCFgOl6GEQaq+y+T/9N30EsQ80eGh81wWz 9jjiVMJ0VmyW78HqM5jYUQ/d7FJtH/9nhyuhI9Pu6jw+rEYWyght4qU5xxuMxhX0nu5n 0YuLxIDBAqe/MBBchN/REtj8DUpvxXS1JDg/Kp6j5qj0VZ/NnVJ9GpNegfQRU1LXr6hW 7Zxw== X-Gm-Message-State: AFeK/H1lh237XsvX5U1PxvpO7cGNOC2LKOVS+jA8w7HYy0G58VTiYsOvrChuL4Boo3hQr5020E8= X-Received: by 10.25.145.77 with SMTP id y13mr9661402lfj.49.1491478787875; Thu, 06 Apr 2017 04:39:47 -0700 (PDT) Received: from localhost.localdomain (ppp95-165-131-83.pppoe.spdop.ru. [95.165.131.83]) by smtp.gmail.com with ESMTPSA id w78sm288354lfi.23.2017.04.06.04.39.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 06 Apr 2017 04:39:47 -0700 (PDT) From: Maxim Uvarov To: lng-odp@lists.linaro.org Date: Thu, 6 Apr 2017 14:39:37 +0300 Message-Id: <20170406113937.31264-1-maxim.uvarov@linaro.org> X-Mailer: git-send-email 2.11.0.295.gd7dffce Subject: [lng-odp] [PATCH 1/4] validation: crypto: add tests for checking message digests X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov Currently ODP testsuite only verifies generation of digests. Let's also verify that checking the digest actually works. Test that check function will accept valid digest and that it will reject wrong digests. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 11 (lumag:crypto-update-main) ** https://github.com/Linaro/odp/pull/11 ** Patch: https://github.com/Linaro/odp/pull/11.patch ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea **/ test/common_plat/validation/api/crypto/crypto.h | 6 +- .../validation/api/crypto/odp_crypto_test_inp.c | 150 ++++++++++++++++++++- 2 files changed, 147 insertions(+), 9 deletions(-) diff --git a/test/common_plat/validation/api/crypto/crypto.h b/test/common_plat/validation/api/crypto/crypto.h index 9b909aa..661fe5d 100644 --- a/test/common_plat/validation/api/crypto/crypto.h +++ b/test/common_plat/validation/api/crypto/crypto.h @@ -22,8 +22,10 @@ void crypto_test_enc_alg_aes128_gcm(void); void crypto_test_enc_alg_aes128_gcm_ovr_iv(void); void crypto_test_dec_alg_aes128_gcm(void); void crypto_test_dec_alg_aes128_gcm_ovr_iv(void); -void crypto_test_alg_hmac_md5(void); -void crypto_test_alg_hmac_sha256(void); +void crypto_test_gen_alg_hmac_md5(void); +void crypto_test_check_alg_hmac_md5(void); +void crypto_test_gen_alg_hmac_sha256(void); +void crypto_test_check_alg_hmac_sha256(void); /* test arrays: */ extern odp_testinfo_t crypto_suite[]; diff --git a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c index 43ddb2f..0909741 100644 --- a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c +++ b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c @@ -65,6 +65,7 @@ static const char *cipher_alg_name(odp_cipher_alg_t cipher) * buffer can be used. * */ static void alg_test(odp_crypto_op_t op, + odp_bool_t should_fail, odp_cipher_alg_t cipher_alg, odp_crypto_iv_t ses_iv, uint8_t *op_iv_ptr, @@ -239,6 +240,10 @@ static void alg_test(odp_crypto_op_t op, op_params.override_iv_ptr = op_iv_ptr; op_params.hash_result_offset = plaintext_len; + if (0 != digest_len) { + memcpy(data_addr + op_params.hash_result_offset, + digest, digest_len); + } rc = odp_crypto_operation(&op_params, &posted, &result); if (rc < 0) { @@ -259,8 +264,15 @@ static void alg_test(odp_crypto_op_t op, odp_crypto_compl_free(compl_event); } - CU_ASSERT(result.ok); CU_ASSERT(result.pkt == pkt); + CU_ASSERT(result.ctx == (void *)0xdeadbeef); + + if (should_fail) { + CU_ASSERT(!result.ok); + goto cleanup; + } + + CU_ASSERT(result.ok); if (cipher_alg != ODP_CIPHER_ALG_NULL) CU_ASSERT(!memcmp(data_addr, ciphertext, ciphertext_len)); @@ -268,8 +280,6 @@ static void alg_test(odp_crypto_op_t op, if (op == ODP_CRYPTO_OP_ENCODE && auth_alg != ODP_AUTH_ALG_NULL) CU_ASSERT(!memcmp(data_addr + op_params.hash_result_offset, digest, digest_len)); - - CU_ASSERT(result.ctx == (void *)0xdeadbeef); cleanup: rc = odp_crypto_session_destroy(session); CU_ASSERT(!rc); @@ -445,6 +455,7 @@ void crypto_test_enc_alg_3des_cbc(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_3DES_CBC, iv, NULL, @@ -480,6 +491,7 @@ void crypto_test_enc_alg_3des_cbc_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_3DES_CBC, iv, tdes_cbc_reference_iv[i], @@ -519,6 +531,7 @@ void crypto_test_dec_alg_3des_cbc(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_3DES_CBC, iv, NULL, @@ -556,6 +569,7 @@ void crypto_test_dec_alg_3des_cbc_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_3DES_CBC, iv, tdes_cbc_reference_iv[i], @@ -602,6 +616,7 @@ void crypto_test_enc_alg_aes128_gcm(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_AES_GCM, iv, NULL, @@ -645,6 +660,7 @@ void crypto_test_enc_alg_aes128_gcm_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_AES_GCM, iv, aes128_gcm_reference_iv[i], @@ -691,6 +707,7 @@ void crypto_test_dec_alg_aes128_gcm(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_AES_GCM, iv, NULL, @@ -735,6 +752,7 @@ void crypto_test_dec_alg_aes128_gcm_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_AES_GCM, iv, aes128_gcm_reference_iv[i], @@ -782,6 +800,7 @@ void crypto_test_enc_alg_aes128_cbc(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_AES_CBC, iv, NULL, @@ -817,6 +836,7 @@ void crypto_test_enc_alg_aes128_cbc_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, ODP_CIPHER_ALG_AES_CBC, iv, aes128_cbc_reference_iv[i], @@ -856,6 +876,7 @@ void crypto_test_dec_alg_aes128_cbc(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_AES_CBC, iv, NULL, @@ -893,6 +914,7 @@ void crypto_test_dec_alg_aes128_cbc_ovr_iv(void) continue; alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_AES_CBC, iv, aes128_cbc_reference_iv[i], @@ -919,7 +941,7 @@ static int check_alg_hmac_md5(void) * In addition the test verifies if the implementation can use the * packet buffer as completion event buffer. * */ -void crypto_test_alg_hmac_md5(void) +void crypto_test_gen_alg_hmac_md5(void) { odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 }, auth_key = { .data = NULL, .length = 0 }; @@ -938,6 +960,45 @@ void crypto_test_alg_hmac_md5(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, + ODP_CIPHER_ALG_NULL, + iv, + iv.data, + cipher_key, + ODP_AUTH_ALG_MD5_HMAC, + auth_key, + NULL, NULL, + hmac_md5_reference_plaintext[i], + hmac_md5_reference_length[i], + NULL, 0, + hmac_md5_reference_digest[i], + HMAC_MD5_96_CHECK_LEN); + } +} + +void crypto_test_check_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 }; + uint8_t wrong_digest[HMAC_MD5_DIGEST_LEN]; + + unsigned int test_vec_num = (sizeof(hmac_md5_reference_length) / + sizeof(hmac_md5_reference_length[0])); + unsigned int i; + + memset(wrong_digest, 0xa5, sizeof(wrong_digest)); + + 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]); + + if (!check_auth_options(ODP_AUTH_ALG_MD5_HMAC, auth_key.length, + HMAC_MD5_96_CHECK_LEN)) + continue; + + alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_NULL, iv, iv.data, @@ -950,6 +1011,21 @@ void crypto_test_alg_hmac_md5(void) NULL, 0, hmac_md5_reference_digest[i], HMAC_MD5_96_CHECK_LEN); + + alg_test(ODP_CRYPTO_OP_DECODE, + 1, + ODP_CIPHER_ALG_NULL, + iv, + iv.data, + cipher_key, + ODP_AUTH_ALG_MD5_HMAC, + auth_key, + NULL, NULL, + hmac_md5_reference_plaintext[i], + hmac_md5_reference_length[i], + NULL, 0, + wrong_digest, + HMAC_MD5_96_CHECK_LEN); } } @@ -965,7 +1041,7 @@ static int check_alg_hmac_sha256(void) * In addition the test verifies if the implementation can use the * packet buffer as completion event buffer. * */ -void crypto_test_alg_hmac_sha256(void) +void crypto_test_gen_alg_hmac_sha256(void) { odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 }, auth_key = { .data = NULL, .length = 0 }; @@ -986,6 +1062,47 @@ void crypto_test_alg_hmac_sha256(void) continue; alg_test(ODP_CRYPTO_OP_ENCODE, + 0, + ODP_CIPHER_ALG_NULL, + iv, + iv.data, + cipher_key, + ODP_AUTH_ALG_SHA256_HMAC, + auth_key, + NULL, NULL, + hmac_sha256_reference_plaintext[i], + hmac_sha256_reference_length[i], + NULL, 0, + hmac_sha256_reference_digest[i], + HMAC_SHA256_128_CHECK_LEN); + } +} + +void crypto_test_check_alg_hmac_sha256(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 }; + uint8_t wrong_digest[HMAC_SHA256_DIGEST_LEN]; + + unsigned int test_vec_num = (sizeof(hmac_sha256_reference_length) / + sizeof(hmac_sha256_reference_length[0])); + + unsigned int i; + + memset(wrong_digest, 0xa5, sizeof(wrong_digest)); + + for (i = 0; i < test_vec_num; i++) { + auth_key.data = hmac_sha256_reference_key[i]; + auth_key.length = sizeof(hmac_sha256_reference_key[i]); + + if (!check_auth_options(ODP_AUTH_ALG_SHA256_HMAC, + auth_key.length, + HMAC_SHA256_128_CHECK_LEN)) + continue; + + alg_test(ODP_CRYPTO_OP_DECODE, + 0, ODP_CIPHER_ALG_NULL, iv, iv.data, @@ -998,6 +1115,21 @@ void crypto_test_alg_hmac_sha256(void) NULL, 0, hmac_sha256_reference_digest[i], HMAC_SHA256_128_CHECK_LEN); + + alg_test(ODP_CRYPTO_OP_DECODE, + 1, + ODP_CIPHER_ALG_NULL, + iv, + iv.data, + cipher_key, + ODP_AUTH_ALG_SHA256_HMAC, + auth_key, + NULL, NULL, + hmac_sha256_reference_plaintext[i], + hmac_sha256_reference_length[i], + NULL, 0, + wrong_digest, + HMAC_SHA256_128_CHECK_LEN); } } @@ -1050,9 +1182,13 @@ odp_testinfo_t crypto_suite[] = { check_alg_aes_gcm), ODP_TEST_INFO_CONDITIONAL(crypto_test_dec_alg_aes128_gcm_ovr_iv, check_alg_aes_gcm), - ODP_TEST_INFO_CONDITIONAL(crypto_test_alg_hmac_md5, + ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_md5, + check_alg_hmac_md5), + ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_md5, check_alg_hmac_md5), - ODP_TEST_INFO_CONDITIONAL(crypto_test_alg_hmac_sha256, + ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_sha256, + check_alg_hmac_sha256), + ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_sha256, check_alg_hmac_sha256), ODP_TEST_INFO_NULL, }; >From 778192fa715728f34c6736769c2fde91962a1ec1 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Wed, 8 Mar 2017 11:22:13 +0300 Subject: [PATCH 2/4] validation: crypto: correct comment for HMAC-SHA-256 tests Comment for HMAC-SHA-256 tests talks about HMAC-MD5 and respective lengths. Correct it to mention SHA-256 and proper digest lengths. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 11 (lumag:crypto-update-main) ** https://github.com/Linaro/odp/pull/11 ** Patch: https://github.com/Linaro/odp/pull/11.patch ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea **/ test/common_plat/validation/api/crypto/odp_crypto_test_inp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c index 0909741..a415f5c 100644 --- a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c +++ b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c @@ -1034,8 +1034,8 @@ static int check_alg_hmac_sha256(void) return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA256_HMAC); } -/* This test verifies the correctness of HMAC_MD5 digest operation. - * The output check length is truncated to 12 bytes (96 bits) as +/* This test verifies the correctness of HMAC_SHA256 digest operation. + * The output check length is truncated to 16 bytes (128 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 >From 7b5b9a1ffc53499c3cc344d62d41cc936542f73d Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Wed, 8 Mar 2017 05:08:00 +0300 Subject: [PATCH 3/4] linux-generic: crypto: unify auth code Authentication code contains similar functions. Instead of replicating them further (e.g. for SHA-1 or SHA-3) factor out common code blocks, moving all difference to session data. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 11 (lumag:crypto-update-main) ** https://github.com/Linaro/odp/pull/11 ** Patch: https://github.com/Linaro/odp/pull/11.patch ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea **/ .../linux-generic/include/odp_crypto_internal.h | 14 +-- platform/linux-generic/odp_crypto.c | 126 ++++----------------- 2 files changed, 28 insertions(+), 112 deletions(-) diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h index f85b76e..515cefa 100644 --- a/platform/linux-generic/include/odp_crypto_internal.h +++ b/platform/linux-generic/include/odp_crypto_internal.h @@ -60,16 +60,10 @@ struct odp_crypto_generic_session { } cipher; struct { - union { - struct { - uint8_t key[16]; - uint32_t bytes; - } md5; - struct { - uint8_t key[32]; - uint32_t bytes; - } sha256; - } data; + uint8_t key[EVP_MAX_KEY_LENGTH]; + uint32_t key_length; + uint32_t bytes; + const EVP_MD *evp_md; crypto_func_t func; } auth; }; diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c index 54b222f..d9b26c0 100644 --- a/platform/linux-generic/odp_crypto.c +++ b/platform/linux-generic/odp_crypto.c @@ -110,8 +110,8 @@ null_crypto_routine(odp_crypto_op_param_t *param ODP_UNUSED, } static -odp_crypto_alg_err_t md5_gen(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t auth_gen(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { uint8_t *data = odp_packet_data(param->out_pkt); uint8_t *icv = data; @@ -123,94 +123,28 @@ odp_crypto_alg_err_t md5_gen(odp_crypto_op_param_t *param, icv += param->hash_result_offset; /* Hash it */ - HMAC(EVP_md5(), - session->auth.data.md5.key, - 16, + HMAC(session->auth.evp_md, + session->auth.key, + session->auth.key_length, data, len, hash, NULL); /* Copy to the output location */ - memcpy(icv, hash, session->auth.data.md5.bytes); + memcpy(icv, hash, session->auth.bytes); return ODP_CRYPTO_ALG_ERR_NONE; } static -odp_crypto_alg_err_t md5_check(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; - uint32_t len = param->auth_range.length; - uint32_t bytes = session->auth.data.md5.bytes; - uint8_t hash_in[EVP_MAX_MD_SIZE]; - uint8_t hash_out[EVP_MAX_MD_SIZE]; - - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; - - /* Copy current value out and clear it before authentication */ - memset(hash_in, 0, sizeof(hash_in)); - memcpy(hash_in, icv, bytes); - memset(icv, 0, bytes); - memset(hash_out, 0, sizeof(hash_out)); - - /* Hash it */ - HMAC(EVP_md5(), - session->auth.data.md5.key, - 16, - data, - len, - hash_out, - NULL); - - /* Verify match */ - if (0 != memcmp(hash_in, hash_out, bytes)) - return ODP_CRYPTO_ALG_ERR_ICV_CHECK; - - /* Matched */ - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static -odp_crypto_alg_err_t sha256_gen(odp_crypto_op_param_t *param, +odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param, odp_crypto_generic_session_t *session) { uint8_t *data = odp_packet_data(param->out_pkt); uint8_t *icv = data; uint32_t len = param->auth_range.length; - uint8_t hash[EVP_MAX_MD_SIZE]; - - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; - - /* Hash it */ - HMAC(EVP_sha256(), - session->auth.data.sha256.key, - 32, - data, - len, - hash, - NULL); - - /* Copy to the output location */ - memcpy(icv, hash, session->auth.data.sha256.bytes); - - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static -odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; - uint32_t len = param->auth_range.length; - uint32_t bytes = session->auth.data.sha256.bytes; + uint32_t bytes = session->auth.bytes; uint8_t hash_in[EVP_MAX_MD_SIZE]; uint8_t hash_out[EVP_MAX_MD_SIZE]; @@ -225,9 +159,9 @@ odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param, memset(hash_out, 0, sizeof(hash_out)); /* Hash it */ - HMAC(EVP_sha256(), - session->auth.data.sha256.key, - 32, + HMAC(session->auth.evp_md, + session->auth.key, + session->auth.key_length, data, len, hash_out, @@ -587,38 +521,26 @@ static int process_des_param(odp_crypto_generic_session_t *session) return 0; } -static int process_md5_param(odp_crypto_generic_session_t *session, - uint32_t bits) +static int process_auth_param(odp_crypto_generic_session_t *session, + uint32_t bits, + uint32_t key_length, + const EVP_MD *evp_md) { /* Set function */ if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->auth.func = md5_gen; + session->auth.func = auth_gen; else - session->auth.func = md5_check; - - /* Number of valid bytes */ - session->auth.data.md5.bytes = bits / 8; - - /* Convert keys */ - memcpy(session->auth.data.md5.key, session->p.auth_key.data, 16); - - return 0; -} + session->auth.func = auth_check; -static int process_sha256_param(odp_crypto_generic_session_t *session, - uint32_t bits) -{ - /* Set function */ - if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->auth.func = sha256_gen; - else - session->auth.func = sha256_check; + session->auth.evp_md = evp_md; /* Number of valid bytes */ - session->auth.data.sha256.bytes = bits / 8; + session->auth.bytes = bits / 8; /* Convert keys */ - memcpy(session->auth.data.sha256.key, session->p.auth_key.data, 32); + session->auth.key_length = key_length; + memcpy(session->auth.key, session->p.auth_key.data, + session->auth.key_length); return 0; } @@ -814,12 +736,12 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, case ODP_AUTH_ALG_MD5_HMAC: /* deprecated */ case ODP_AUTH_ALG_MD5_96: - rc = process_md5_param(session, 96); + rc = process_auth_param(session, 96, 16, EVP_md5()); break; case ODP_AUTH_ALG_SHA256_HMAC: /* deprecated */ case ODP_AUTH_ALG_SHA256_128: - rc = process_sha256_param(session, 128); + rc = process_auth_param(session, 128, 32, EVP_sha256()); break; case ODP_AUTH_ALG_AES_GCM: /* deprecated */ >From 9b1d5f564e6eb0c19635240a0b5907975c3f0870 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Wed, 8 Mar 2017 10:38:09 +0300 Subject: [PATCH 4/4] linux-generic: crypto: switch to EVP interface for cipher algorithms Switch AES-CBC and 3DES-CBC to use generic (EVP) interface instad of low level interface (as recommended by OpenSSL documentation). This allows to use the same code path for all non-AEAD ciphers. The only AEAD cipher (AES-GCM) already uses EVP interface. Generalization of that code can happen if there will be more AEAD ciphers. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 11 (lumag:crypto-update-main) ** https://github.com/Linaro/odp/pull/11 ** Patch: https://github.com/Linaro/odp/pull/11.patch ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea **/ .../linux-generic/include/odp_crypto_internal.h | 16 +- platform/linux-generic/odp_crypto.c | 232 +++++---------------- 2 files changed, 52 insertions(+), 196 deletions(-) diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h index 515cefa..033fa6d 100644 --- a/platform/linux-generic/include/odp_crypto_internal.h +++ b/platform/linux-generic/include/odp_crypto_internal.h @@ -11,8 +11,6 @@ extern "C" { #endif -#include -#include #include #define MAX_IV_LEN 64 @@ -43,19 +41,7 @@ struct odp_crypto_generic_session { /* Copy of session IV data */ uint8_t iv_data[MAX_IV_LEN]; - union { - struct { - DES_key_schedule ks1; - DES_key_schedule ks2; - DES_key_schedule ks3; - } des; - struct { - AES_KEY key; - } aes; - struct { - EVP_CIPHER_CTX *ctx; - } aes_gcm; - } data; + EVP_CIPHER_CTX ctx; crypto_func_t func; } cipher; diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c index d9b26c0..c8aee1d 100644 --- a/platform/linux-generic/odp_crypto.c +++ b/platform/linux-generic/odp_crypto.c @@ -176,90 +176,6 @@ odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param, } static -odp_crypto_alg_err_t aes_encrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; - void *iv_ptr; - - if (param->override_iv_ptr) - iv_ptr = param->override_iv_ptr; - else if (session->p.iv.data) - iv_ptr = session->cipher.iv_data; - else - return ODP_CRYPTO_ALG_ERR_IV_INVALID; - - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; - /* Encrypt it */ - AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key, - iv_enc, AES_ENCRYPT); - - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static -odp_crypto_alg_err_t aes_decrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; - void *iv_ptr; - - if (param->override_iv_ptr) - iv_ptr = param->override_iv_ptr; - else if (session->p.iv.data) - iv_ptr = session->cipher.iv_data; - else - return ODP_CRYPTO_ALG_ERR_IV_INVALID; - - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; - /* Encrypt it */ - AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key, - iv_enc, AES_DECRYPT); - - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static int process_aes_param(odp_crypto_generic_session_t *session) -{ - /* Verify IV len is either 0 or 16 */ - if (!((0 == session->p.iv.length) || (16 == session->p.iv.length))) - return -1; - - /* Set function */ - if (ODP_CRYPTO_OP_ENCODE == session->p.op) { - session->cipher.func = aes_encrypt; - AES_set_encrypt_key(session->p.cipher_key.data, 128, - &session->cipher.data.aes.key); - } else { - session->cipher.func = aes_decrypt; - AES_set_decrypt_key(session->p.cipher_key.data, 128, - &session->cipher.data.aes.key); - } - - return 0; -} - -static odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, odp_crypto_generic_session_t *session) { @@ -269,7 +185,6 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, uint8_t *aad_tail = data + param->cipher_range.offset + param->cipher_range.length; uint32_t auth_len = param->auth_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; void *iv_ptr; uint8_t *tag = data + param->hash_result_offset; @@ -286,21 +201,14 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, param->cipher_range.offset + plain_len) return ODP_CRYPTO_ALG_ERR_DATA_SIZE; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - /* Adjust pointer for beginning of area to cipher/auth */ uint8_t *plaindata = data + param->cipher_range.offset; /* Encrypt it */ - EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx; + EVP_CIPHER_CTX *ctx = &session->cipher.ctx; int cipher_len = 0; - EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_enc); + EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); /* Authenticate header data (if any) without encrypting them */ if (aad_head < plaindata) { @@ -334,7 +242,6 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, uint8_t *aad_tail = data + param->cipher_range.offset + param->cipher_range.length; uint32_t auth_len = param->auth_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; void *iv_ptr; uint8_t *tag = data + param->hash_result_offset; @@ -351,20 +258,13 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, param->cipher_range.offset + cipher_len) return ODP_CRYPTO_ALG_ERR_DATA_SIZE; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - /* Adjust pointer for beginning of area to cipher/auth */ uint8_t *cipherdata = data + param->cipher_range.offset; /* Encrypt it */ - EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx; + EVP_CIPHER_CTX *ctx = &session->cipher.ctx; int plain_len = 0; - EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_enc); + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag); @@ -392,14 +292,15 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, static int process_aes_gcm_param(odp_crypto_generic_session_t *session) { + EVP_CIPHER_CTX *ctx = &session->cipher.ctx; + + EVP_CIPHER_CTX_init(ctx); + /* Verify Key len is 16 */ if (session->p.cipher_key.length != 16) return -1; /* Set function */ - EVP_CIPHER_CTX *ctx = - session->cipher.data.aes_gcm.ctx = EVP_CIPHER_CTX_new(); - if (ODP_CRYPTO_OP_ENCODE == session->p.op) { session->cipher.func = aes_gcm_encrypt; EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); @@ -422,13 +323,14 @@ static int process_aes_gcm_param(odp_crypto_generic_session_t *session) } static -odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t cipher_crypt(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { uint8_t *data = odp_packet_data(param->out_pkt); uint32_t len = param->cipher_range.length; - DES_cblock iv; void *iv_ptr; + int cipher_len = 0; + int rc; if (param->override_iv_ptr) iv_ptr = param->override_iv_ptr; @@ -437,86 +339,55 @@ odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param, else return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv, iv_ptr, sizeof(iv)); - - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; - /* Encrypt it */ - DES_ede3_cbc_encrypt(data, - data, - len, - &session->cipher.data.des.ks1, - &session->cipher.data.des.ks2, - &session->cipher.data.des.ks3, - &iv, - 1); - - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static -odp_crypto_alg_err_t des_decrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - DES_cblock iv; - void *iv_ptr; - - if (param->override_iv_ptr) - iv_ptr = param->override_iv_ptr; - else if (session->p.iv.data) - iv_ptr = session->cipher.iv_data; - else + rc = EVP_CipherInit_ex(&session->cipher.ctx, + NULL, NULL, NULL, iv_ptr, -1); + if (odp_unlikely(1 != rc)) return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv, iv_ptr, sizeof(iv)); - /* Adjust pointer for beginning of area to cipher */ data += param->cipher_range.offset; - /* Decrypt it */ - DES_ede3_cbc_encrypt(data, - data, - len, - &session->cipher.data.des.ks1, - &session->cipher.data.des.ks2, - &session->cipher.data.des.ks3, - &iv, - 0); + /* En/Decrypt it */ + EVP_CipherUpdate(&session->cipher.ctx, + data, + &cipher_len, + data, + len); + + EVP_CipherFinal_ex(&session->cipher.ctx, + data + cipher_len, + &cipher_len); return ODP_CRYPTO_ALG_ERR_NONE; } -static int process_des_param(odp_crypto_generic_session_t *session) +static int process_cipher_param(odp_crypto_generic_session_t *session, + const EVP_CIPHER *cipher) { + int rc; + + /* Verify Key len is 16 */ + if ((uint32_t)EVP_CIPHER_key_length(cipher) != + session->p.cipher_key.length) + return -1; + /* Verify IV len is either 0 or 8 */ - if (!((0 == session->p.iv.length) || (8 == session->p.iv.length))) + if (!((0 == session->p.iv.length) || + ((uint32_t)EVP_CIPHER_iv_length(cipher) == session->p.iv.length))) return -1; /* Set function */ - if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->cipher.func = des_encrypt; - else - session->cipher.func = des_decrypt; - - /* Convert keys */ - DES_set_key((DES_cblock *)&session->p.cipher_key.data[0], - &session->cipher.data.des.ks1); - DES_set_key((DES_cblock *)&session->p.cipher_key.data[8], - &session->cipher.data.des.ks2); - DES_set_key((DES_cblock *)&session->p.cipher_key.data[16], - &session->cipher.data.des.ks3); + session->cipher.func = cipher_crypt; + + EVP_CIPHER_CTX_init(&session->cipher.ctx); + rc = EVP_CipherInit_ex(&session->cipher.ctx, + cipher, + NULL, + session->p.cipher_key.data, + NULL, + (ODP_CRYPTO_OP_ENCODE == session->p.op) ? 1 : 0); + if (odp_unlikely(1 != rc)) + return -1; return 0; } @@ -699,12 +570,12 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, break; case ODP_CIPHER_ALG_DES: case ODP_CIPHER_ALG_3DES_CBC: - rc = process_des_param(session); + rc = process_cipher_param(session, EVP_des_ede3_cbc()); break; case ODP_CIPHER_ALG_AES_CBC: /* deprecated */ case ODP_CIPHER_ALG_AES128_CBC: - rc = process_aes_param(session); + rc = process_cipher_param(session, EVP_aes_128_cbc()); break; case ODP_CIPHER_ALG_AES_GCM: /* deprecated */ @@ -776,9 +647,8 @@ int odp_crypto_session_destroy(odp_crypto_session_t session) odp_crypto_generic_session_t *generic; generic = (odp_crypto_generic_session_t *)(intptr_t)session; - if (generic->p.cipher_alg == ODP_CIPHER_ALG_AES128_GCM || - generic->p.cipher_alg == ODP_CIPHER_ALG_AES_GCM) - EVP_CIPHER_CTX_free(generic->cipher.data.aes_gcm.ctx); + if (ODP_CIPHER_ALG_NULL != generic->p.cipher_alg) + EVP_CIPHER_CTX_cleanup(&generic->cipher.ctx); memset(generic, 0, sizeof(*generic)); free_session(generic); return 0;