[4/4] linux-generic: crypto: switch to EVP interface for cipher algorithms

Message ID 20170425014152.3112-5-dmitry.ereminsolenikov@linaro.org
State New
Headers show
Series
  • crypto: rework implementation of encryption and auth code
Related show

Commit Message

Dmitry Eremin-Solenikov April 25, 2017, 1:41 a.m.
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 <dmitry.ereminsolenikov@linaro.org>

---
 .../linux-generic/include/odp_crypto_internal.h    |  16 +-
 platform/linux-generic/odp_crypto.c                | 232 +++++----------------
 2 files changed, 52 insertions(+), 196 deletions(-)

-- 
2.11.0

Comments

Dmitry Eremin-Solenikov April 26, 2017, 11:57 p.m. | #1
On 25.04.2017 04:41, Dmitry Eremin-Solenikov wrote:
> 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 <dmitry.ereminsolenikov@linaro.org>


Please ignore this particular patch for now. Neither original AES-GCM
implementation, nor this implementation is not thread safe: they use CTX
from the session during crypto_operation. I will rethink and update this
patch.

Other 3 patches are still valid.

-- 
With best wishes
Dmitry

Patch hide | download patch | download mbox

diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
index 515cefaa..033fa6d9 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 <openssl/des.h>
-#include <openssl/aes.h>
 #include <openssl/evp.h>
 
 #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 d9b26c01..c8aee1dc 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;