API change is OK. There's a typo in patch name: "AES1268-GCM support" should be "AES128-GCM support"
-Petri > -----Original Message----- > From: lng-odp [mailto:[email protected]] On Behalf Of > EXT Nicolas Morey-Chaisemartin > Sent: Thursday, November 12, 2015 11:25 AM > To: [email protected] > Subject: [lng-odp] [API-NEXT PATCH 3/4] api: crypto: Add AES1268-GCM > support > > 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; > + 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; > } > -- > 2.6.2.406.gaaaec35 > > > _______________________________________________ > lng-odp mailing list > [email protected] > https://lists.linaro.org/mailman/listinfo/lng-odp _______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
