On 11/16/2015 16:09, Nicolas Morey-Chaisemartin wrote:
Signed-off-by: Nicolas Morey-Chaisemartin <[email protected]>
---
include/odp/api/crypto.h | 4 +
.../linux-generic/include/odp_crypto_internal.h | 3 +
platform/linux-generic/odp_crypto.c | 183 +++++++++++++++++++++
3 files changed, 190 insertions(+)
diff --git a/include/odp/api/crypto.h b/include/odp/api/crypto.h
index c62021e..41beedb 100644
--- a/include/odp/api/crypto.h
+++ b/include/odp/api/crypto.h
@@ -70,6 +70,8 @@ typedef enum {
ODP_CIPHER_ALG_3DES_CBC,
/** AES128 with cipher block chaining */
ODP_CIPHER_ALG_AES128_CBC,
+ /** AES128 in Galois/Counter Mode */
+ ODP_CIPHER_ALG_AES128_GCM,
} odp_cipher_alg_t;
/**
@@ -82,6 +84,8 @@ typedef enum {
ODP_AUTH_ALG_MD5_96,
/** SHA256 with 128 bit key */
ODP_AUTH_ALG_SHA256_128,
+ /** AES128 in Galois/Counter Mode */
+ ODP_AUTH_ALG_AES128_GCM,
} odp_auth_alg_t;
/**
diff --git a/platform/linux-generic/include/odp_crypto_internal.h
b/platform/linux-generic/include/odp_crypto_internal.h
index b9128a4..7b104af 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -50,6 +50,9 @@ struct odp_crypto_generic_session {
struct {
AES_KEY key;
} aes;
+ struct {
+ EVP_CIPHER_CTX *ctx;
+ } aes_gcm;
} data;
crypto_func_t func;
} cipher;
diff --git a/platform/linux-generic/odp_crypto.c
b/platform/linux-generic/odp_crypto.c
index 17fced9..65e8503 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -292,6 +292,170 @@ int process_aes_params(odp_crypto_generic_session_t
*session,
}
static
+odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_params_t *params,
+ odp_crypto_generic_session_t *session)
+{
+ uint8_t *data = odp_packet_data(params->out_pkt);
+ uint32_t plain_len = params->cipher_range.length;
+ uint8_t *aad_head = data + params->auth_range.offset;
+ uint8_t *aad_tail = data + params->cipher_range.offset +
+ params->cipher_range.length;
+ uint32_t auth_len = params->auth_range.length;
+ unsigned char iv_enc[AES_BLOCK_SIZE];
+ void *iv_ptr;
+ uint8_t *tag = data + params->hash_result_offset;
+
+ if (params->override_iv_ptr)
+ iv_ptr = params->override_iv_ptr;
+ else if (session->cipher.iv.data)
+ iv_ptr = session->cipher.iv.data;
+ else
+ return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+
+ /* All cipher data must be part of the authentication */
+ if (params->auth_range.offset > params->cipher_range.offset ||
+ params->auth_range.offset + auth_len <
+ params->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 + params->cipher_range.offset;
+
+ /* Encrypt it */
+ EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
+ int cipher_len = 0;
+
+ EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+
+ /* Authenticate header data (if any) without encrypting them */
+ if (aad_head < plaindata) {
+ EVP_EncryptUpdate(ctx, NULL, &cipher_len,
+ aad_head, plaindata - aad_head);
+ }
+
+ EVP_EncryptUpdate(ctx, plaindata, &cipher_len,
+ plaindata, plain_len);
+ cipher_len = plain_len;
+
+ /* Authenticate footer data (if any) without encrypting them */
+ if (aad_head + auth_len > plaindata + plain_len) {
+ EVP_EncryptUpdate(ctx, NULL, NULL, aad_tail,
+ auth_len - (aad_tail - aad_head));
+ }
+
+ EVP_EncryptFinal_ex(ctx, plaindata + cipher_len, &cipher_len);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);
+
+ return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_params_t *params,
+ odp_crypto_generic_session_t *session)
+{
+ uint8_t *data = odp_packet_data(params->out_pkt);
+ uint32_t cipher_len = params->cipher_range.length;
+ uint8_t *aad_head = data + params->auth_range.offset;
+ uint8_t *aad_tail = data + params->cipher_range.offset +
+ params->cipher_range.length;
+ uint32_t auth_len = params->auth_range.length;
+ unsigned char iv_enc[AES_BLOCK_SIZE];
+ void *iv_ptr;
+ uint8_t *tag = data + params->hash_result_offset;
+
+ if (params->override_iv_ptr)
+ iv_ptr = params->override_iv_ptr;
+ else if (session->cipher.iv.data)
+ iv_ptr = session->cipher.iv.data;
+ else
+ return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+
+ /* All cipher data must be part of the authentication */
+ if (params->auth_range.offset > params->cipher_range.offset ||
+ params->auth_range.offset + auth_len <
+ params->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 + params->cipher_range.offset;
+ /* Encrypt it */
+ EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
does checkpatch warns that definition of variables should be at the
start of block?
+ int plain_len = 0;
+
+ EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+
+ /* Authenticate header data (if any) without encrypting them */
+ if (aad_head < cipherdata) {
+ EVP_DecryptUpdate(ctx, NULL, &plain_len,
+ aad_head, cipherdata - aad_head);
+ }
+
+ EVP_DecryptUpdate(ctx, cipherdata, &plain_len,
+ cipherdata, cipher_len);
+ plain_len = cipher_len;
+
+ /* Authenticate footer data (if any) without encrypting them */
+ if (aad_head + auth_len > cipherdata + cipher_len) {
+ EVP_DecryptUpdate(ctx, NULL, NULL, aad_tail,
+ auth_len - (aad_tail - aad_head));
+ }
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);
+
+ if (EVP_DecryptFinal_ex(ctx, cipherdata + cipher_len, &plain_len) < 0)
+ return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
+
+ return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+int process_aes_gcm_params(odp_crypto_generic_session_t *session,
+ odp_crypto_session_params_t *params)
+{
+ /* Verify Key len is 16 */
+ if (params->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 == params->op) {
+ session->cipher.func = aes_gcm_encrypt;
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+ } else {
+ session->cipher.func = aes_gcm_decrypt;
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+ }
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+ params->iv.length, NULL);
+ if (ODP_CRYPTO_OP_ENCODE == params->op) {
+ EVP_EncryptInit_ex(ctx, NULL, NULL,
+ params->cipher_key.data, NULL);
+ } else {
+ EVP_DecryptInit_ex(ctx, NULL, NULL,
+ params->cipher_key.data, NULL);
+ }
+
+ return 0;
+}
+
+static
odp_crypto_alg_err_t des_encrypt(odp_crypto_op_params_t *params,
odp_crypto_generic_session_t *session)
{
@@ -479,6 +643,15 @@ odp_crypto_session_create(odp_crypto_session_params_t
*params,
case ODP_CIPHER_ALG_AES128_CBC:
rc = process_aes_params(session, params);
break;
+ case ODP_CIPHER_ALG_AES128_GCM:
+ /* AES-GCM requires to do both auth and
+ * cipher at the same time */
+ if (params->auth_alg != ODP_AUTH_ALG_AES128_GCM) {
+ rc = -1;
+ break;
+ }
+ rc = process_aes_gcm_params(session, params);
+ break;
default:
rc = -1;
}
@@ -501,6 +674,16 @@ odp_crypto_session_create(odp_crypto_session_params_t
*params,
case ODP_AUTH_ALG_SHA256_128:
rc = process_sha256_params(session, params, 128);
break;
+ case ODP_AUTH_ALG_AES128_GCM:
+ /* AES-GCM requires to do both auth and
+ * cipher at the same time */
+ if (params->cipher_alg != ODP_CIPHER_ALG_AES128_GCM) {
+ rc = -1;
+ break;
+ }
+ session->auth.func = null_crypto_routine;
+ rc = 0;
+ break;
default:
rc = -1;
}
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp