[API-NEXT,v1,1/5] linux-gen: crypto: implement AES-XCBC-MAC and SHA384-HMAC

Message ID 1518537618-25725-2-git-send-email-odpbot@yandex.ru
State New
Headers show
Series
  • linux-gen: crypto: implement AES-XCBC-MAC and SHA384-HMAC
Related show

Commit Message

Github ODP bot Feb. 13, 2018, 4 p.m.
From: yhe <yhe@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(+)

Patch

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)