ssflib: Use OpenSSL for missing AES GCM mode 27/144727/5
authorLukasz Kostyra <l.kostyra@samsung.com>
Thu, 17 Aug 2017 12:34:45 +0000 (14:34 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Mon, 11 Sep 2017 14:51:01 +0000 (16:51 +0200)
CryptoCore library used in Simulator does not support auth cipher
modes like AES GCM. The support was added through OpenSSL library.

Change-Id: I97cb17a954e904dc0a6e7aba1d74c7b8077438d5

CMakeLists.txt
ssflib/CMakeLists.txt
ssflib/inc/crypto_internal.h
ssflib/inc/ssf_crypto_openssl.h [new file with mode: 0644]
ssflib/src/ssf_crypto.cpp
ssflib/src/ssf_crypto_openssl.cpp [new file with mode: 0644]

index 53d03f6cff11c05b79fa368c55bb9b4812ae2ad2..da7492c14fbc2ce663b8894dcbf9b9314d158c3b 100644 (file)
@@ -54,6 +54,7 @@ IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
     ADD_DEFINITIONS("-ggdb -O0")
     # undefine _FORTIFY_SOURCE to supress warnings
     ADD_COMPILE_OPTIONS("-U_FORTIFY_SOURCE")
+    ADD_DEFINITIONS("-D_LOGGING")
 ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
 
 ############################# targets #########################################
index e806c2ba00fa3b8daabeab035fd176fb97ca89ac..1ef7fb57390a33b97d9d9f799af127803e2c2b7f 100644 (file)
 # @brief   CMakeLists for tef-simulator ssflib unit
 #
 
+PKG_CHECK_MODULES(SSFLIB_DEPS REQUIRED
+                  openssl
+                  )
+
 SET(SSFLIB_CRYPTOCORE_SOURCES
     ${SSFLIB_DEP_CRYPTOCORE_PATH}/source/CC_API.c
     ${SSFLIB_DEP_CRYPTOCORE_PATH}/source/base/cc_ANSI_x931.c
@@ -70,6 +74,7 @@ SET(SSFLIB_SOURCES
     ${SSFLIB_PATH}/src/ssf_arithmetic.cpp
     ${SSFLIB_PATH}/src/ssf_client.cpp
     ${SSFLIB_PATH}/src/ssf_crypto.cpp
+    ${SSFLIB_PATH}/src/ssf_crypto_openssl.cpp
     ${SSFLIB_PATH}/src/ssf_lib.cpp
     ${SSFLIB_PATH}/src/ssf_malloc.cpp
     ${SSFLIB_PATH}/src/ssf_panic.cpp
@@ -97,11 +102,13 @@ INCLUDE_DIRECTORIES(
     ${LOG_PATH}
     ${OSAL_PATH}
     ${TEF_SIMULATOR_INCLUDE_PATH}/include
+    ${SSFLIB_DEPS_INCLUDE_DIRS}
     )
 
 TARGET_LINK_LIBRARIES(${TARGET_TEF_SIMULATOR_SSFLIB}
     ${TARGET_TEF_SIMULATOR_OSAL}
     ${TARGET_TEF_SIMULATOR_LOG}
+    ${SSFLIB_DEPS_LIBRARIES}
     )
 
 INSTALL(TARGETS ${TARGET_TEF_SIMULATOR_SSFLIB} LIBRARY DESTINATION ${LIB_DIR})
index 4df29f9dd3008a27b0f0c89f34d09022df44832d..83e0ef0305dfb8302e5d17ffc91b28b6093e9377 100644 (file)
@@ -1,13 +1,26 @@
-/*
- * ace.c
+/**
+ * Copyright (c) 2011-2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
- * This source file is proprietary property of Samsung Electronics Co., Ltd.
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
  *
- * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *        http://www.apache.org/licenses/LICENSE-2.0
  *
- * Contact: Jaemin Ryu <jm77.ryu@samsung.com>
- *
- */ 
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file
+ * @author  Jaemin Ryu (jm77.ryu@samsung.com)
+ */
+
+#ifndef _CRYPTO_INTERNAL_H_
+#define _CRYPTO_INTERNAL_H_
 
 #include "tee_internal_api.h"
 
@@ -20,7 +33,7 @@
 #define TEE_ALG_GENERATE_DSA_KEY                       0x90000002
 #define TEE_ALG_GENERATE_DH_KEY                        0x90000003
 
-typedef enum 
+typedef enum
 {
        CRYPTO_HW_ENGINE,
        CRYPTO_SW_ENGINE,
@@ -33,7 +46,7 @@ typedef enum
        CRYPTO_USE_SW_ENGINE
 }crypto_internal_engine_type;
 
-typedef struct 
+typedef struct
 {
        TEE_OperationInfo info;
        TEE_ObjectHandle key1;
@@ -44,13 +57,13 @@ typedef struct
        unsigned int block_len; // cipher block data length
 } crypto_internal_operation;
 
-typedef struct 
+typedef struct
 {
        unsigned char *buffer;
-       unsigned int size;      
+       unsigned int size;
 } crypto_internal_keydata;
 
-typedef struct 
+typedef struct
 {
        crypto_internal_keydata secret;                         /* TEE_ATTR_SECRET_VALUE */
        crypto_internal_keydata rsa_modulus;            /* TEE_ATTR_RSA_MODULUS */
@@ -70,3 +83,4 @@ int crypto_internal_init(crypto_internal_operation *operation, crypto_internal_k
 int crypto_internal_update(crypto_internal_operation *operation, unsigned char *src_data, size_t src_len, unsigned char *dst_data, size_t *dst_len);
 int crypto_internal_final(crypto_internal_operation *operation, unsigned char *src_data, size_t src_len, unsigned char *dst_data, size_t *dst_len);
 
+#endif // _CRYPTO_INTERNAL_H_
diff --git a/ssflib/inc/ssf_crypto_openssl.h b/ssflib/inc/ssf_crypto_openssl.h
new file mode 100644 (file)
index 0000000..e01d66e
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file
+ * @author  Lukasz Kostyra (l.kostyra@samsung.com)
+ * @brief   OpenSSL backend for TEF Simulator Crypto Auth operations
+ */
+
+#ifndef _SSF_CRYPTO_OPENSSL_H_
+#define _SSF_CRYPTO_OPENSSL_H_
+
+#include <crypto_internal.h>
+
+int ossl_crypto_open(crypto_internal_operation *op);
+void ossl_crypto_close(crypto_internal_operation *op);
+
+int ossl_crypto_ae_init(crypto_internal_operation *op, crypto_internal_keystruct *key,
+                                               void *iv, size_t iv_len, unsigned int tag_len);
+
+int ossl_crypto_ae_update_aad(crypto_internal_operation *op, void *aad, size_t aad_len);
+int ossl_crypto_ae_update(crypto_internal_operation *op, void *src, size_t src_len,
+                                                       void *dst, size_t *dst_len);
+
+int ossl_crypto_ae_enc_final(crypto_internal_operation *op, void *src, size_t src_len,
+                                                       void *dst, size_t *dst_len, void *tag, size_t *tag_len);
+int ossl_crypto_ae_dec_final(crypto_internal_operation *op, void *src, size_t src_len,
+                                                       void *dst, size_t *dst_len, void *tag, size_t tag_len);
+
+#endif // _SSF_CRYPTO_OPENSSL_H_
\ No newline at end of file
index c8563189c7b2b57451066a2ca092515371355933..d7053a1aabf7ef12e1c227f8fa4a18f24e01899d 100644 (file)
@@ -28,6 +28,7 @@
 #include <permission.h>
 
 #include "CC_API.h"
+#include "ssf_crypto_openssl.h"
 
 #define TAG "TEE:Crypto"
 
@@ -903,12 +904,21 @@ static int sw_crypto_close(crypto_internal_operation *operation)
 
 int crypto_internal_open(crypto_internal_operation *operation)
 {
-       return sw_crypto_open(operation);
+       if (operation->info.algorithm == TEE_ALG_AES_GCM) {
+               return ossl_crypto_open(operation);
+       } else {
+               return sw_crypto_open(operation);
+       }
 }
 
 int crypto_internal_close(crypto_internal_operation *operation)
 {
-       return sw_crypto_close(operation);
+       if (operation->info.algorithm == TEE_ALG_AES_GCM) {
+               ossl_crypto_close(operation);
+               return 0;
+       } else {
+               return sw_crypto_close(operation);
+       }
 }
 
 int crypto_internal_init(crypto_internal_operation *operation, crypto_internal_keystruct *key, unsigned char *ivec, size_t ivec_len)
@@ -1812,7 +1822,7 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, uint32_t algori
        }
 
        /* get handle */
-       if(crypto_internal_open(op)!=0) {
+       if (crypto_internal_open(op)!=0) {
                rc = TEE_ERROR_NOT_SUPPORTED;
                goto error;
        }
@@ -1838,7 +1848,7 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, uint32_t algori
        op->key2 = key2;
        op->block_len = block_len;
 
-       *operation = (TEE_OperationHandle) &op->info;
+       *operation = (TEE_OperationHandle)op;
 
        if (alg_class == TEE_OPERATION_DIGEST) {
                TEE_DigestInit(*operation);
@@ -2242,32 +2252,145 @@ TEE_Result TEE_MACCompareFinal( TEE_OperationHandle operation, void* message, si
 TEE_Result TEE_AEInit(TEE_OperationHandle operation, void* nonce, size_t nonceLen, uint32_t tagLen, uint32_t AADLen, uint32_t payloadLen)
 {
        PERMISSION_CHECK(PERM_CRYPTO);
-       (void)operation;
-       (void)nonce;
-       (void)nonceLen;
-       (void)tagLen;
-       (void)AADLen;
-       (void)payloadLen;
+
+       crypto_internal_operation *op = (crypto_internal_operation*)operation;
+       crypto_internal_keystruct key;
+       unsigned char key_buf[32] = {0x0, };
+
+       memset(&key, 0x00, sizeof(crypto_internal_keystruct));
+       key.secret.size = sizeof(key_buf);
+       key.secret.buffer = key_buf;
+
+       // operation check
+       if (op->info.operationClass != TEE_OPERATION_AE) {
+               LOGE(SSF_LIB, "Incorrect operation class %x", op->info.operationClass);
+               CRYPTO_PANIC;
+       }
+       if (op->info.mode != TEE_MODE_ENCRYPT && op->info.mode != TEE_MODE_DECRYPT) {
+               LOGE(SSF_LIB, "Incorrect operation mode %x", op->info.mode);
+               CRYPTO_PANIC;
+       }
+       if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) {
+               LOGE(SSF_LIB, "Key not set in operation");
+               CRYPTO_PANIC;
+       }
+       // nonce check (must be equal to AES block size)
+       if (nonce == NULL || nonceLen != 16) {
+               LOGE(SSF_LIB, "Incorrect nonce provided");
+               CRYPTO_PANIC;
+       }
+       // tagLen check
+       switch (op->info.algorithm) {
+               case TEE_ALG_AES_GCM: {
+                       switch (tagLen) {
+                               case 128:
+                               case 120:
+                               case 112:
+                               case 104:
+                               case 96:
+                                       break;
+                               default:
+                                       LOGE(SSF_LIB, "Incorrect tag length %u", tagLen);
+                                       return TEE_ERROR_NOT_SUPPORTED;
+                       };
+                       break;
+               }
+               case TEE_ALG_AES_CCM: {
+                       switch (tagLen) {
+                               case 128:
+                               case 112:
+                               case 96:
+                               case 64:
+                               case 48:
+                               case 32:
+                                       break;
+                               default:
+                                       LOGE(SSF_LIB, "Incorrect tag length %u", tagLen);
+                                       return TEE_ERROR_NOT_SUPPORTED;
+                       };
+                       break;
+               }
+               default: {
+                       LOGE(SSF_LIB, "Incorrect algorithm %x", op->info.algorithm);
+                       CRYPTO_PANIC;
+               }
+       };
+       // CCM exclusive checks
+       if (op->info.algorithm == TEE_ALG_AES_CCM) {
+               // TODO support CCM and check AAD/payload here
+               LOGE(SSF_LIB, "CCM mode not supported");
+               return TEE_ERROR_NOT_SUPPORTED;
+       }
+       // key check
+       if (TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_SECRET_VALUE,
+               (void*)key.secret.buffer, (size_t*)&key.secret.size) != TEE_SUCCESS) {
+               LOGE(SSF_LIB, "Cannot acquire key from operation");
+               CRYPTO_PANIC;
+       }
+       if (!key.secret.buffer) {
+               LOGE(SSF_LIB, "Uninitialized operation key");
+               CRYPTO_PANIC;
+       }
+
+       if (ossl_crypto_ae_init(op, &key,
+                                                       (unsigned char*)nonce, nonceLen, tagLen)) {
+               LOGE(SSF_LIB, "Failed to initialize AE algorithm");
+               CRYPTO_PANIC;
+       }
+
        return TEE_SUCCESS;
 }
 
 void TEE_AEUpdateAAD(TEE_OperationHandle operation, void* AADdata, size_t AADdataLen)
 {
        PERMISSION_CHECK_RETURN_VOID(PERM_CRYPTO);
-       (void)operation;
-       (void)AADdata;
-       (void)AADdataLen;
+       crypto_internal_operation *op = (crypto_internal_operation*)operation;
+
+       // operation check
+       if (op->info.operationClass != TEE_OPERATION_AE) {
+               LOGE(SSF_LIB, "Incorrect operation class %x", op->info.operationClass);
+               CRYPTO_PANIC;
+       }
+       if (op->info.mode != TEE_MODE_ENCRYPT && op->info.mode != TEE_MODE_DECRYPT) {
+               LOGE(SSF_LIB, "Incorrect operation mode %x", op->info.mode);
+               CRYPTO_PANIC;
+       }
+       if (op->crypto == 0) {
+               LOGE(SSF_LIB, "Uninitialized operation handle provided");
+               CRYPTO_PANIC;
+       }
+
+       if (ossl_crypto_ae_update_aad(op, AADdata, AADdataLen)) {
+               LOGE(SSF_LIB, "Failed to update AAD data");
+               CRYPTO_PANIC;
+       }
+
        return;
 }
 
 TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, void* srcData, size_t srcLen, void* destData, size_t *destLen)
 {
        PERMISSION_CHECK(PERM_CRYPTO);
-       (void)operation;
-       (void)srcData;
-       (void)srcLen;
-       (void)destData;
-       (void)destLen;
+       crypto_internal_operation *op = (crypto_internal_operation*)operation;
+
+       if (op->info.operationClass != TEE_OPERATION_AE) {
+               LOGE(SSF_LIB, "Incorrect operation class %x", op->info.operationClass);
+               CRYPTO_PANIC;
+       }
+       if (op->info.mode != TEE_MODE_ENCRYPT && op->info.mode != TEE_MODE_DECRYPT) {
+               LOGE(SSF_LIB, "Incorrect operation mode %x", op->info.mode);
+               CRYPTO_PANIC;
+       }
+       if (op->crypto == 0) {
+               LOGE(SSF_LIB, "Uninitialized operation handle provided");
+               CRYPTO_PANIC;
+       }
+
+       if (ossl_crypto_ae_update(op, srcData, srcLen, destData, destLen)) {
+               LOGE(SSF_LIB, "Failed to update cipher data");
+               CRYPTO_PANIC;
+       }
+
        return TEE_SUCCESS;
 }
 
@@ -2277,17 +2400,23 @@ TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, void* srcData, size
        crypto_internal_operation * op = (crypto_internal_operation*) operation;
 
        if (op->info.operationClass != TEE_OPERATION_AE) {
+               LOGE(SSF_LIB, "Incorrect operation class %x", op->info.operationClass);
                CRYPTO_PANIC;
        }
        if (op->info.mode != TEE_MODE_ENCRYPT) {
+               LOGE(SSF_LIB, "Incorrect operation mode %x", op->info.mode);
+               CRYPTO_PANIC;
+       }
+       if (op->crypto == 0) {
+               LOGE(SSF_LIB, "Uninitialized operation handle provided");
                CRYPTO_PANIC;
        }
-       (void)srcData;
-       (void)srcLen;
-       (void)destData;
-       (void)destLen;
-       (void)tag;
-       (void)tagLen;
+
+       if (ossl_crypto_ae_enc_final(op, srcData, srcLen, destData, destLen, tag, tagLen)) {
+               LOGE(SSF_LIB, "Failed to finalize AE encryption");
+               CRYPTO_PANIC;
+       }
+
        return TEE_SUCCESS;
 }
 
@@ -2295,20 +2424,28 @@ TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, void* srcData, size
 {
        PERMISSION_CHECK(PERM_CRYPTO);
        crypto_internal_operation * op = (crypto_internal_operation*) operation;
+       TEE_Result ret = TEE_SUCCESS;
 
        if (op->info.operationClass != TEE_OPERATION_AE) {
+               LOGE(SSF_LIB, "Incorrect operation class %x", op->info.operationClass);
                CRYPTO_PANIC;
        }
        if (op->info.mode != TEE_MODE_DECRYPT) {
+               LOGE(SSF_LIB, "Incorrect operation mode %x", op->info.mode);
                CRYPTO_PANIC;
        }
-       (void)srcData;
-       (void)srcLen;
-       (void)destData;
-       (void)destLen;
-       (void)tag;
-       (void)tagLen;
-       return TEE_SUCCESS;
+       if (op->crypto == 0) {
+               LOGE(SSF_LIB, "Uninitialized operation handle provided");
+               CRYPTO_PANIC;
+       }
+
+       ret = ossl_crypto_ae_dec_final(op, srcData, srcLen, destData, destLen, tag, tagLen);
+       if (ret != TEE_SUCCESS && ret != TEE_ERROR_MAC_INVALID) {
+               LOGE(SSF_LIB, "Failed to finalize AE decryption");
+               CRYPTO_PANIC;
+       }
+
+       return ret;
 }
 
 TEE_Result TEE_AsymmetricEncrypt( TEE_OperationHandle operation,const TEE_Attribute* params, uint32_t paramCount, const void* srcData, size_t srcLen, void* destData, size_t *destLen)
diff --git a/ssflib/src/ssf_crypto_openssl.cpp b/ssflib/src/ssf_crypto_openssl.cpp
new file mode 100644 (file)
index 0000000..e60e684
--- /dev/null
@@ -0,0 +1,253 @@
+/**
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file
+ * @author  Lukasz Kostyra (l.kostyra@samsung.com)
+ * @brief   OpenSSL backend for TEF Simulator Crypto Auth operations
+ */
+
+#include "ssf_crypto_openssl.h"
+#include <tee_internal_api.h>
+#include <openssl/evp.h>
+#include <log.h>
+
+// DO NOT MODIFY BELOW VALUES
+#define EVP_SUCCESS 1
+#define EVP_FAILED 0
+
+// Below implementation tries to match CryptoCore's behavior:
+//  * "open" creates a context, "close" destroys it
+//  * "init" initializes opened context with parameters, key and iv
+//  * "update" and "final" progress crypto operations
+
+int ossl_crypto_open(crypto_internal_operation *op)
+{
+       EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "OSSL Crypto CTX failed to open");
+               return -1;
+       }
+
+       op->crypto = (int)ctx;
+       return 0;
+}
+
+void ossl_crypto_close(crypto_internal_operation *op)
+{
+       if (op->crypto == 0) {
+               return;
+       }
+
+       EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)op->crypto;
+       EVP_CIPHER_CTX_free(ctx);
+       op->crypto = 0;
+}
+
+int ossl_crypto_ae_init(crypto_internal_operation *op, crypto_internal_keystruct *key,
+                                               void *iv, size_t iv_len, unsigned int tag_len)
+{
+       const EVP_CIPHER *(*EVP_alg)();
+       EVP_CIPHER_CTX *ctx;
+       int ret = -1;
+
+       LOGI(SSF_LIB, "AE Init");
+
+       ctx = (EVP_CIPHER_CTX *)op->crypto;
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "Invalid OSSL Crypto CTX provided");
+               return -1;
+       }
+
+       if (op->info.mode != TEE_MODE_ENCRYPT && op->info.mode != TEE_MODE_DECRYPT) {
+               LOGE(SSF_LIB, "Invalid operation mode");
+               return -1;
+       }
+
+       if (key == NULL || key->secret.buffer == NULL || key->secret.size == 0) {
+               LOGE(SSF_LIB, "Invalid key provided");
+               return -1;
+       }
+
+       if ((key->secret.size * 8) != op->info.keySize) {
+               LOGE(SSF_LIB, "Provided key with incorrect length: %d", key->secret.size * 8);
+               return -1;
+       }
+
+       // right now use AES GCM only (could be further extended to CCM)
+       switch (op->info.algorithm)
+       {
+               case TEE_ALG_AES_GCM: {
+                       switch (op->info.keySize) {
+                               case 128: EVP_alg = EVP_aes_128_gcm; break;
+                               case 192: EVP_alg = EVP_aes_192_gcm; break;
+                               case 256: EVP_alg = EVP_aes_256_gcm; break;
+                               default: {
+                                       LOGE(SSF_LIB, "Unsupported key size %d", op->info.keySize);
+                                       return -1;
+                               }
+                       }
+                       break;
+               }
+
+               default: {
+                       LOGE(SSF_LIB, "Unsupported AE crypto algorithm %x", op->info.algorithm);
+                       return -1;
+               }
+       }
+
+       ret = EVP_CipherInit(ctx, EVP_alg(), key->secret.buffer, (unsigned char*)iv,
+                                               (op->info.mode == TEE_MODE_ENCRYPT) ? 1 : 0);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to initialize cipher");
+               return ret;
+       }
+
+       ret = EVP_CIPHER_CTX_set_padding(ctx, 0);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to disable padding in OpenSSL");
+               return ret;
+       }
+
+       return 0;
+}
+
+int ossl_crypto_ae_update_aad(crypto_internal_operation *op, void *aad, size_t aad_len)
+{
+       EVP_CIPHER_CTX *ctx;
+       int dstLen = 0;
+       int ret = 0;
+
+       LOGI(SSF_LIB, "AE Update AAD");
+
+       ctx = (EVP_CIPHER_CTX *)op->crypto;
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "Invalid OSSL Crypto CTX provided");
+               return -1;
+       }
+
+       ret = EVP_CipherUpdate(ctx, NULL, &dstLen, (unsigned char*)aad, aad_len);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "AAD Update failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+int ossl_crypto_ae_update(crypto_internal_operation *op, void *src, size_t src_len,
+                                               void *dst, size_t *dst_len)
+{
+       EVP_CIPHER_CTX *ctx;
+       int ret = 0;
+
+       LOGI(SSF_LIB, "AE Update");
+
+       ctx = (EVP_CIPHER_CTX *)op->crypto;
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "Invalid OSSL Crypto CTX provided");
+               return -1;
+       }
+
+       ret = EVP_CipherUpdate(ctx, (unsigned char*)dst, (int*)dst_len, (unsigned char*)src, src_len);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Cipher Update failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+int ossl_crypto_ae_enc_final(crypto_internal_operation *op, void *src, size_t src_len,
+                                                       void *dst, size_t *dst_len, void *tag, size_t *tag_len)
+{
+       EVP_CIPHER_CTX *ctx;
+       int ret = -1;
+       int written = (int)*dst_len;
+
+       ctx = (EVP_CIPHER_CTX *)op->crypto;
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "Invalid OSSL Crypto CTX provided");
+               return -1;
+       }
+
+       // deliver final portion of data
+       ret = EVP_CipherUpdate(ctx, (unsigned char*)dst, &written, (unsigned char*)src, src_len);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to perform final crypto operation");
+               return ret;
+       }
+
+       *dst_len = written;
+
+       // finalize operation
+       ret = EVP_CipherFinal(ctx, (unsigned char*)dst, &written);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to finalize crypto operation");
+               return ret;
+       }
+
+       *dst_len += written;
+
+       // get tag
+       ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, *tag_len, tag);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to acquire operation tag");
+               return ret;
+       }
+
+       return 0;
+}
+
+int ossl_crypto_ae_dec_final(crypto_internal_operation *op, void *src, size_t src_len,
+                                                       void *dst, size_t *dst_len, void *tag, size_t tag_len)
+{
+       EVP_CIPHER_CTX *ctx;
+       int ret = -1;
+       int written = (int)*dst_len;
+
+       ctx = (EVP_CIPHER_CTX *)op->crypto;
+       if (ctx == NULL) {
+               LOGE(SSF_LIB, "Invalid OSSL Crypto CTX provided");
+               return -1;
+       }
+
+       // deliver final portion of data
+       ret = EVP_CipherUpdate(ctx, (unsigned char*)dst, &written, (unsigned char*)src, src_len);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to perform final crypto operation");
+               return ret;
+       }
+
+       *dst_len = written;
+
+       // set tag
+       ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to set operation tag");
+               return ret;
+       }
+
+       // finalize operation
+       ret = EVP_CipherFinal(ctx, (unsigned char*)dst, &written);
+       if (ret != EVP_SUCCESS) {
+               LOGE(SSF_LIB, "Failed to finalize crypto operation (auth error)");
+               return TEE_ERROR_MAC_INVALID;
+       }
+
+       *dst_len += written;
+       return 0;
+}