From: yhe <y...@sonicwall.com> --- /** Email created from pull request 470 (SonicwallYhe:api-next-seperate) ** https://github.com/Linaro/odp/pull/470 ** Patch: https://github.com/Linaro/odp/pull/470.patch ** Base sha: af7be638ef9ac98bdb1f2e4917f152889eb1850f ** Merge commit sha: f30e7ae4157bae994d5734b8917d2dd31dbf201e **/ platform/linux-generic/odp_crypto.c | 164 ++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+)
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c index 5579ade5b..16ec25d67 100644 --- a/platform/linux-generic/odp_crypto.c +++ b/platform/linux-generic/odp_crypto.c @@ -36,6 +36,9 @@ #define MAX_SESSIONS 32 +#define AES_BLOCK_SIZE 16 +typedef uint32_t aes_block[4]; + /* * Cipher algorithm capabilities * @@ -95,10 +98,18 @@ static const odp_crypto_auth_capability_t auth_capa_sha256_hmac[] = { {.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} }, {.digest_len = 32, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; +static const odp_crypto_auth_capability_t auth_capa_sha384_hmac[] = { +{.digest_len = 24, .key_len = 48, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 48, .key_len = 48, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; + static const odp_crypto_auth_capability_t auth_capa_sha512_hmac[] = { {.digest_len = 32, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} }, {.digest_len = 64, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; +static const odp_crypto_auth_capability_t auth_capa_aes_xcbc[] = { +{.digest_len = 12, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 16, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; + static const odp_crypto_auth_capability_t auth_capa_aes_gcm[] = { {.digest_len = 16, .key_len = 0, .aad_len = {.min = 8, .max = 12, .inc = 4} } }; @@ -308,6 +319,142 @@ void packet_hmac(odp_packet_t pkt, HMAC_Final(ctx, hash, NULL); } +static void do_pad_xor(uint8_t *out, const uint8_t *in, int len) { + int pos=0; + for (pos=1; pos <= 16; pos++, in++, out++) { + if (pos <= len) + *out ^= *in; + if (pos > len) { + *out ^= 0x80; + break; + } + } +} +static void xor_block(aes_block res, const aes_block op) { + res[0] ^= op[0]; + res[1] ^= op[1]; + res[2] ^= op[2]; + res[3] ^= op[3]; +} + +static +odp_crypto_alg_err_t aesxcbc_gen(odp_packet_t pkt, + const odp_crypto_packet_op_param_t *param, + odp_crypto_generic_session_t *session) +{ + aes_block e = {0, 0, 0, 0}; + uint8_t *data = odp_packet_data(pkt); + uint8_t *icv = data; + uint32_t len = param->auth_range.length; + uint8_t hash_out[16]; + EVP_CIPHER_CTX *ctx; + int dummy_len = 0; + /* Adjust pointer for beginning of area to auth */ + data += param->auth_range.offset; + icv += param->hash_result_offset; + + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, session->auth.key, NULL); + for (; len > AES_BLOCK_SIZE ; len -= AES_BLOCK_SIZE) { + xor_block(e, (const uint32_t*) data); + EVP_EncryptUpdate(ctx, (uint8_t *)e, &dummy_len, (uint8_t *)e, sizeof(e)); + data += AES_BLOCK_SIZE; + } + do_pad_xor((uint8_t *)e, data, len); + if (len == AES_BLOCK_SIZE) { + xor_block(e, (const uint32_t*) (session->auth.key + 16)); + } + else + { + xor_block(e, (const uint32_t*) (session->auth.key + 16*2)); + } + EVP_EncryptUpdate(ctx, hash_out, &dummy_len, (uint8_t *)e, sizeof(e)); + EVP_CIPHER_CTX_free(ctx); + memcpy (icv, hash_out, 12); + + return ODP_CRYPTO_ALG_ERR_NONE; +} + +static +odp_crypto_alg_err_t aesxcbc_check(odp_packet_t pkt, + const odp_crypto_packet_op_param_t *param, + odp_crypto_generic_session_t *session) +{ + aes_block e = {0, 0, 0, 0}; + uint8_t *data = odp_packet_data(pkt); + uint8_t *icv = data; + uint32_t len = param->auth_range.length; + uint8_t hash_in[12]; + uint8_t hash_out[12]; + EVP_CIPHER_CTX *ctx; + int dummy_len = 0; + + /* 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, 12); + memset(hash_out, 0, sizeof(hash_out)); + + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, session->auth.key, NULL); + + for (; len > AES_BLOCK_SIZE ; len -= AES_BLOCK_SIZE) { + xor_block(e, (const uint32_t*) data); + EVP_EncryptUpdate(ctx, (uint8_t *)e, &dummy_len, (uint8_t *)e, sizeof(e)); + data += AES_BLOCK_SIZE; + } + do_pad_xor((uint8_t *)e, data, len); + if (len == AES_BLOCK_SIZE) { + xor_block(e, (const uint32_t*) (session->auth.key + 16)); + } + else + { + xor_block(e, (const uint32_t*) (session->auth.key + 16*2)); + } + EVP_EncryptUpdate(ctx, hash_out, &dummy_len, (uint8_t *)e, sizeof(e)); + EVP_CIPHER_CTX_free(ctx); + /* Verify match */ + if (0 != memcmp(hash_in, hash_out, 12)) + return ODP_CRYPTO_ALG_ERR_ICV_CHECK; + + /* Matched */ + return ODP_CRYPTO_ALG_ERR_NONE; +} + +static int process_aesxcbc_param(odp_crypto_generic_session_t *session) +{ + aes_block kn[3] = { + { 0x01010101, 0x01010101, 0x01010101, 0x01010101 }, + { 0x02020202, 0x02020202, 0x02020202, 0x02020202 }, + { 0x03030303, 0x03030303, 0x03030303, 0x03030303 }, + }; + EVP_CIPHER_CTX *ctx; + int dummy_len = 0; + + /* Set function */ + if (ODP_CRYPTO_OP_ENCODE == session->p.op) + session->auth.func = aesxcbc_gen; + else + session->auth.func = aesxcbc_check; + + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, session->p.auth_key.data, NULL); + /* K1 = 0x01010101010101010101010101010101 encrypted with Key K */ + EVP_EncryptUpdate(ctx, session->auth.key, &dummy_len, (uint8_t *)kn[0], 16); + + /* K2 = 0x02020202020202020202020202020202 encrypted with Key K */ + EVP_EncryptUpdate(ctx, session->auth.key+16, &dummy_len, (uint8_t *)kn[1], 16); + + /* K3 = 0x03030303030303030303030303030303 encrypted with Key K */ + EVP_EncryptUpdate(ctx, session->auth.key+16*2, &dummy_len, (uint8_t *)kn[2], 16); + + EVP_CIPHER_CTX_free(ctx); + return 0; +} + static odp_crypto_alg_err_t auth_hmac_gen(odp_packet_t pkt, const odp_crypto_packet_op_param_t *param, @@ -1152,7 +1299,9 @@ int odp_crypto_capability(odp_crypto_capability_t *capa) capa->auths.bit.md5_hmac = 1; capa->auths.bit.sha1_hmac = 1; capa->auths.bit.sha256_hmac = 1; + capa->auths.bit.sha384_hmac = 1; capa->auths.bit.sha512_hmac = 1; + capa->auths.bit.aes_xcbc_mac = 1; capa->auths.bit.aes_gcm = 1; capa->auths.bit.aes_ccm = 1; capa->auths.bit.aes_gmac = 1; @@ -1249,10 +1398,18 @@ int odp_crypto_auth_capability(odp_auth_alg_t auth, src = auth_capa_sha256_hmac; num = sizeof(auth_capa_sha256_hmac) / size; break; + case ODP_AUTH_ALG_SHA384_HMAC: + src = auth_capa_sha384_hmac; + num = sizeof(auth_capa_sha384_hmac) / size; + break; case ODP_AUTH_ALG_SHA512_HMAC: src = auth_capa_sha512_hmac; num = sizeof(auth_capa_sha512_hmac) / size; break; + case ODP_AUTH_ALG_AES_XCBC_MAC: + src = auth_capa_aes_xcbc; + num = sizeof(auth_capa_aes_xcbc) / size; + break; case ODP_AUTH_ALG_AES_GCM: src = auth_capa_aes_gcm; num = sizeof(auth_capa_aes_gcm) / size; @@ -1462,9 +1619,16 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, case ODP_AUTH_ALG_SHA256_HMAC: rc = process_auth_hmac_param(session, EVP_sha256()); break; + case ODP_AUTH_ALG_SHA384_HMAC: + rc = process_auth_hmac_param(session, EVP_sha384()); + break; case ODP_AUTH_ALG_SHA512_HMAC: rc = process_auth_hmac_param(session, EVP_sha512()); break; + + case ODP_AUTH_ALG_AES_XCBC_MAC: + rc = process_aesxcbc_param(session); + break; #if ODP_DEPRECATED_API case ODP_AUTH_ALG_AES128_GCM: if (param->cipher_alg == ODP_CIPHER_ALG_AES128_GCM)