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 #########################################
# @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
${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
${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})
-/*
- * 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"
#define TEE_ALG_GENERATE_DSA_KEY 0x90000002
#define TEE_ALG_GENERATE_DH_KEY 0x90000003
-typedef enum
+typedef enum
{
CRYPTO_HW_ENGINE,
CRYPTO_SW_ENGINE,
CRYPTO_USE_SW_ENGINE
}crypto_internal_engine_type;
-typedef struct
+typedef struct
{
TEE_OperationInfo info;
TEE_ObjectHandle key1;
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 */
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_
--- /dev/null
+/**
+ * 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
#include <permission.h>
#include "CC_API.h"
+#include "ssf_crypto_openssl.h"
#define TAG "TEE:Crypto"
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)
}
/* get handle */
- if(crypto_internal_open(op)!=0) {
+ if (crypto_internal_open(op)!=0) {
rc = TEE_ERROR_NOT_SUPPORTED;
goto error;
}
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);
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;
}
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;
}
{
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)
--- /dev/null
+/**
+ * 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;
+}