11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2b0104773SPascal Brand /* 3b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V. 4b0104773SPascal Brand */ 5b0104773SPascal Brand #include <stdlib.h> 6b0104773SPascal Brand #include <string.h> 7b796ebf3SJerome Forissier #include <string_ext.h> 8b0104773SPascal Brand 9b0104773SPascal Brand #include <tee_api.h> 108854d3c6SJerome Forissier #include <tee_api_defines_extensions.h> 11b0104773SPascal Brand #include <tee_internal_api_extensions.h> 12b0104773SPascal Brand #include <utee_syscalls.h> 13b0104773SPascal Brand #include <utee_defines.h> 14fc26c92aSJens Wiklander #include <util.h> 15e86f1266SJens Wiklander #include "tee_api_private.h" 16b0104773SPascal Brand 17b0104773SPascal Brand struct __TEE_OperationHandle { 18b0104773SPascal Brand TEE_OperationInfo info; 19b0104773SPascal Brand TEE_ObjectHandle key1; 20b0104773SPascal Brand TEE_ObjectHandle key2; 21642a1607SCedric Chaumont uint32_t operationState;/* Operation state : INITIAL or ACTIVE */ 22b0104773SPascal Brand uint8_t *buffer; /* buffer to collect complete blocks */ 23b0104773SPascal Brand bool buffer_two_blocks; /* True if two blocks need to be buffered */ 24b0104773SPascal Brand size_t block_size; /* Block size of cipher */ 25b0104773SPascal Brand size_t buffer_offs; /* Offset in buffer */ 26b0104773SPascal Brand uint32_t state; /* Handle to state in TEE Core */ 27b0104773SPascal Brand uint32_t ae_tag_len; /* 28b0104773SPascal Brand * tag_len in bytes for AE operation else unused 29b0104773SPascal Brand */ 30b0104773SPascal Brand }; 31b0104773SPascal Brand 32b0104773SPascal Brand /* Cryptographic Operations API - Generic Operation Functions */ 33b0104773SPascal Brand 34b0104773SPascal Brand TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, 35b0104773SPascal Brand uint32_t algorithm, uint32_t mode, 36b0104773SPascal Brand uint32_t maxKeySize) 37b0104773SPascal Brand { 38b0104773SPascal Brand TEE_Result res; 39b0104773SPascal Brand TEE_OperationHandle op = TEE_HANDLE_NULL; 40b0104773SPascal Brand uint32_t handle_state = 0; 41b0104773SPascal Brand size_t block_size = 1; 42b0104773SPascal Brand uint32_t req_key_usage; 43b0104773SPascal Brand bool with_private_key = false; 44b0104773SPascal Brand bool buffer_two_blocks = false; 45b0104773SPascal Brand 469b52c538SCedric Chaumont if (!operation) 47b0104773SPascal Brand TEE_Panic(0); 48b0104773SPascal Brand 49b0104773SPascal Brand if (algorithm == TEE_ALG_AES_XTS) 50b0104773SPascal Brand handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; 51b0104773SPascal Brand 52218d9055SCedric Chaumont /* Check algorithm max key size */ 53218d9055SCedric Chaumont switch (algorithm) { 54218d9055SCedric Chaumont case TEE_ALG_DSA_SHA1: 55218d9055SCedric Chaumont if (maxKeySize < 512) 56218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 57218d9055SCedric Chaumont if (maxKeySize > 1024) 58218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 59218d9055SCedric Chaumont if (maxKeySize % 64 != 0) 60218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 61218d9055SCedric Chaumont break; 62218d9055SCedric Chaumont 63218d9055SCedric Chaumont case TEE_ALG_DSA_SHA224: 64218d9055SCedric Chaumont if (maxKeySize != 2048) 65218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 66218d9055SCedric Chaumont break; 67218d9055SCedric Chaumont 68218d9055SCedric Chaumont case TEE_ALG_DSA_SHA256: 69218d9055SCedric Chaumont if (maxKeySize != 2048 && maxKeySize != 3072) 70218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 71218d9055SCedric Chaumont break; 72218d9055SCedric Chaumont 731220586eSCedric Chaumont case TEE_ALG_ECDSA_P192: 741220586eSCedric Chaumont case TEE_ALG_ECDH_P192: 751220586eSCedric Chaumont if (maxKeySize != 192) 761220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 771220586eSCedric Chaumont break; 781220586eSCedric Chaumont 791220586eSCedric Chaumont case TEE_ALG_ECDSA_P224: 801220586eSCedric Chaumont case TEE_ALG_ECDH_P224: 811220586eSCedric Chaumont if (maxKeySize != 224) 821220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 831220586eSCedric Chaumont break; 841220586eSCedric Chaumont 851220586eSCedric Chaumont case TEE_ALG_ECDSA_P256: 861220586eSCedric Chaumont case TEE_ALG_ECDH_P256: 871220586eSCedric Chaumont if (maxKeySize != 256) 881220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 891220586eSCedric Chaumont break; 901220586eSCedric Chaumont 911220586eSCedric Chaumont case TEE_ALG_ECDSA_P384: 921220586eSCedric Chaumont case TEE_ALG_ECDH_P384: 931220586eSCedric Chaumont if (maxKeySize != 384) 941220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 951220586eSCedric Chaumont break; 961220586eSCedric Chaumont 971220586eSCedric Chaumont case TEE_ALG_ECDSA_P521: 981220586eSCedric Chaumont case TEE_ALG_ECDH_P521: 991220586eSCedric Chaumont if (maxKeySize != 521) 1001220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 1011220586eSCedric Chaumont break; 1021220586eSCedric Chaumont 103218d9055SCedric Chaumont default: 104218d9055SCedric Chaumont break; 105218d9055SCedric Chaumont } 106218d9055SCedric Chaumont 107218d9055SCedric Chaumont /* Check algorithm mode */ 108b0104773SPascal Brand switch (algorithm) { 109b0104773SPascal Brand case TEE_ALG_AES_CTS: 110b0104773SPascal Brand case TEE_ALG_AES_XTS: 111b0104773SPascal Brand buffer_two_blocks = true; 1124bd53c54SJerome Forissier /* FALLTHROUGH */ 1134bd53c54SJerome Forissier case TEE_ALG_AES_ECB_NOPAD: 114b0104773SPascal Brand case TEE_ALG_AES_CBC_NOPAD: 115b0104773SPascal Brand case TEE_ALG_AES_CCM: 116b0104773SPascal Brand case TEE_ALG_DES_ECB_NOPAD: 117b0104773SPascal Brand case TEE_ALG_DES_CBC_NOPAD: 118b0104773SPascal Brand case TEE_ALG_DES3_ECB_NOPAD: 119b0104773SPascal Brand case TEE_ALG_DES3_CBC_NOPAD: 120b0104773SPascal Brand if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) 121b0104773SPascal Brand block_size = TEE_AES_BLOCK_SIZE; 122b0104773SPascal Brand else 123b0104773SPascal Brand block_size = TEE_DES_BLOCK_SIZE; 124afc0c182SBogdan Liulko /* FALLTHROUGH */ 12557aabac5SBogdan Liulko case TEE_ALG_AES_CTR: 126afc0c182SBogdan Liulko case TEE_ALG_AES_GCM: 127b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) 128b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 129b0104773SPascal Brand else if (mode == TEE_MODE_DECRYPT) 130b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 131b0104773SPascal Brand else 132b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 133b0104773SPascal Brand break; 134b0104773SPascal Brand 1356a2e0a9fSGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1) 1366a2e0a9fSGabor Szekely case TEE_ALG_RSASSA_PKCS1_V1_5: 1376a2e0a9fSGabor Szekely #endif 138b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 139b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 140b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 141b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 142b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 143b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 144b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 145b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 146b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 147b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 148b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 149b0104773SPascal Brand case TEE_ALG_DSA_SHA1: 150218d9055SCedric Chaumont case TEE_ALG_DSA_SHA224: 151218d9055SCedric Chaumont case TEE_ALG_DSA_SHA256: 1521220586eSCedric Chaumont case TEE_ALG_ECDSA_P192: 1531220586eSCedric Chaumont case TEE_ALG_ECDSA_P224: 1541220586eSCedric Chaumont case TEE_ALG_ECDSA_P256: 1551220586eSCedric Chaumont case TEE_ALG_ECDSA_P384: 1561220586eSCedric Chaumont case TEE_ALG_ECDSA_P521: 157b0104773SPascal Brand if (mode == TEE_MODE_SIGN) { 158b0104773SPascal Brand with_private_key = true; 159b0104773SPascal Brand req_key_usage = TEE_USAGE_SIGN; 160b0104773SPascal Brand } else if (mode == TEE_MODE_VERIFY) { 161b0104773SPascal Brand req_key_usage = TEE_USAGE_VERIFY; 162b0104773SPascal Brand } else { 163b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 164b0104773SPascal Brand } 165b0104773SPascal Brand break; 166b0104773SPascal Brand 167b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_V1_5: 168b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: 169b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: 170b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: 171b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: 172b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: 173b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 174b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 175b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 176b0104773SPascal Brand with_private_key = true; 177b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 178b0104773SPascal Brand } else { 179b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 180b0104773SPascal Brand } 181b0104773SPascal Brand break; 182b0104773SPascal Brand 183b0104773SPascal Brand case TEE_ALG_RSA_NOPAD: 184b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 185b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY; 186b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 187b0104773SPascal Brand with_private_key = true; 188b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN; 189b0104773SPascal Brand } else { 190b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 191b0104773SPascal Brand } 192b0104773SPascal Brand break; 193b0104773SPascal Brand 194b0104773SPascal Brand case TEE_ALG_DH_DERIVE_SHARED_SECRET: 1951220586eSCedric Chaumont case TEE_ALG_ECDH_P192: 1961220586eSCedric Chaumont case TEE_ALG_ECDH_P224: 1971220586eSCedric Chaumont case TEE_ALG_ECDH_P256: 1981220586eSCedric Chaumont case TEE_ALG_ECDH_P384: 1991220586eSCedric Chaumont case TEE_ALG_ECDH_P521: 200cdb198a7SJerome Forissier case TEE_ALG_HKDF_MD5_DERIVE_KEY: 201cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA1_DERIVE_KEY: 202cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA224_DERIVE_KEY: 203cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA256_DERIVE_KEY: 204cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA384_DERIVE_KEY: 205cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA512_DERIVE_KEY: 2068854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY: 2078854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY: 2088854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY: 2098854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY: 2108854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY: 2110f2293b7SJerome Forissier case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY: 212b0104773SPascal Brand if (mode != TEE_MODE_DERIVE) 213b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 214b0104773SPascal Brand with_private_key = true; 215b0104773SPascal Brand req_key_usage = TEE_USAGE_DERIVE; 216b0104773SPascal Brand break; 217b0104773SPascal Brand 218b0104773SPascal Brand case TEE_ALG_MD5: 219b0104773SPascal Brand case TEE_ALG_SHA1: 220b0104773SPascal Brand case TEE_ALG_SHA224: 221b0104773SPascal Brand case TEE_ALG_SHA256: 222b0104773SPascal Brand case TEE_ALG_SHA384: 223b0104773SPascal Brand case TEE_ALG_SHA512: 224b0104773SPascal Brand if (mode != TEE_MODE_DIGEST) 225b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 22605304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 227b0104773SPascal Brand handle_state |= TEE_HANDLE_FLAG_KEY_SET; 228b0104773SPascal Brand req_key_usage = 0; 229b0104773SPascal Brand break; 230b0104773SPascal Brand 231b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_NOPAD: 232b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_NOPAD: 233b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_PKCS5: 234b0104773SPascal Brand case TEE_ALG_AES_CMAC: 235b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_PKCS5: 236b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_NOPAD: 237b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_PKCS5: 238b0104773SPascal Brand case TEE_ALG_HMAC_MD5: 239b0104773SPascal Brand case TEE_ALG_HMAC_SHA1: 240b0104773SPascal Brand case TEE_ALG_HMAC_SHA224: 241b0104773SPascal Brand case TEE_ALG_HMAC_SHA256: 242b0104773SPascal Brand case TEE_ALG_HMAC_SHA384: 243b0104773SPascal Brand case TEE_ALG_HMAC_SHA512: 244b0104773SPascal Brand if (mode != TEE_MODE_MAC) 245b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 246b0104773SPascal Brand req_key_usage = TEE_USAGE_MAC; 247b0104773SPascal Brand break; 248b0104773SPascal Brand 249b0104773SPascal Brand default: 250b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 251b0104773SPascal Brand } 252b0104773SPascal Brand 253b66f219bSJens Wiklander op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO); 2549b52c538SCedric Chaumont if (!op) 255b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY; 256b0104773SPascal Brand 257b0104773SPascal Brand op->info.algorithm = algorithm; 258b0104773SPascal Brand op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); 2596a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1 2606a2e0a9fSGabor Szekely if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5) 2616a2e0a9fSGabor Szekely op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE; 2626a2e0a9fSGabor Szekely #endif 263b0104773SPascal Brand op->info.mode = mode; 264b0104773SPascal Brand op->info.maxKeySize = maxKeySize; 265b0104773SPascal Brand op->info.requiredKeyUsage = req_key_usage; 266b0104773SPascal Brand op->info.handleState = handle_state; 267b0104773SPascal Brand 268b0104773SPascal Brand if (block_size > 1) { 269b0104773SPascal Brand size_t buffer_size = block_size; 270b0104773SPascal Brand 271b0104773SPascal Brand if (buffer_two_blocks) 272b0104773SPascal Brand buffer_size *= 2; 273b0104773SPascal Brand 2749b52c538SCedric Chaumont op->buffer = TEE_Malloc(buffer_size, 2759b52c538SCedric Chaumont TEE_USER_MEM_HINT_NO_FILL_ZERO); 276b0104773SPascal Brand if (op->buffer == NULL) { 277b0104773SPascal Brand res = TEE_ERROR_OUT_OF_MEMORY; 278b66f219bSJens Wiklander goto out; 279b0104773SPascal Brand } 280b0104773SPascal Brand } 281b0104773SPascal Brand op->block_size = block_size; 282b0104773SPascal Brand op->buffer_two_blocks = buffer_two_blocks; 283b0104773SPascal Brand 284b0104773SPascal Brand if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { 285b0104773SPascal Brand uint32_t mks = maxKeySize; 286b0104773SPascal Brand TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, 287b0104773SPascal Brand with_private_key); 288b0104773SPascal Brand 289b0104773SPascal Brand /* 290b0104773SPascal Brand * If two keys are expected the max key size is the sum of 291b0104773SPascal Brand * the size of both keys. 292b0104773SPascal Brand */ 293b0104773SPascal Brand if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) 294b0104773SPascal Brand mks /= 2; 295b0104773SPascal Brand 296b0104773SPascal Brand res = TEE_AllocateTransientObject(key_type, mks, &op->key1); 297b0104773SPascal Brand if (res != TEE_SUCCESS) 298b66f219bSJens Wiklander goto out; 299b0104773SPascal Brand 30005304565SCedric Chaumont if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { 3019b52c538SCedric Chaumont res = TEE_AllocateTransientObject(key_type, mks, 302b0104773SPascal Brand &op->key2); 303b0104773SPascal Brand if (res != TEE_SUCCESS) 304b66f219bSJens Wiklander goto out; 305b0104773SPascal Brand } 306b0104773SPascal Brand } 307b0104773SPascal Brand 308e86f1266SJens Wiklander res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, 309e86f1266SJens Wiklander (unsigned long)op->key2, &op->state); 310b66f219bSJens Wiklander if (res != TEE_SUCCESS) 311b66f219bSJens Wiklander goto out; 312b0104773SPascal Brand 31305304565SCedric Chaumont /* 31405304565SCedric Chaumont * Initialize digest operations 31505304565SCedric Chaumont * Other multi-stage operations initialized w/ TEE_xxxInit functions 31605304565SCedric Chaumont * Non-applicable on asymmetric operations 31705304565SCedric Chaumont */ 31805304565SCedric Chaumont if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { 31905304565SCedric Chaumont res = utee_hash_init(op->state, NULL, 0); 32005304565SCedric Chaumont if (res != TEE_SUCCESS) 321b66f219bSJens Wiklander goto out; 32205304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 32305304565SCedric Chaumont op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 32405304565SCedric Chaumont } 32505304565SCedric Chaumont 326642a1607SCedric Chaumont op->operationState = TEE_OPERATION_STATE_INITIAL; 327642a1607SCedric Chaumont 328b0104773SPascal Brand *operation = op; 329b0104773SPascal Brand 330b66f219bSJens Wiklander out: 331b66f219bSJens Wiklander if (res != TEE_SUCCESS) { 332b66f219bSJens Wiklander if (res != TEE_ERROR_OUT_OF_MEMORY && 3339b52c538SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 334b36311adSJerome Forissier TEE_Panic(res); 335b66f219bSJens Wiklander if (op) { 336b66f219bSJens Wiklander if (op->state) { 337b66f219bSJens Wiklander TEE_FreeOperation(op); 338b66f219bSJens Wiklander } else { 339b66f219bSJens Wiklander TEE_Free(op->buffer); 340b66f219bSJens Wiklander TEE_FreeTransientObject(op->key1); 341b66f219bSJens Wiklander TEE_FreeTransientObject(op->key2); 342b66f219bSJens Wiklander TEE_Free(op); 343b66f219bSJens Wiklander } 344b66f219bSJens Wiklander } 345b66f219bSJens Wiklander } 346b66f219bSJens Wiklander 347b0104773SPascal Brand return res; 348b0104773SPascal Brand } 349b0104773SPascal Brand 350b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation) 351b0104773SPascal Brand { 352e889e80bSCedric Chaumont TEE_Result res; 353e889e80bSCedric Chaumont 354e889e80bSCedric Chaumont if (operation == TEE_HANDLE_NULL) 355e889e80bSCedric Chaumont TEE_Panic(0); 356e889e80bSCedric Chaumont 357b0104773SPascal Brand /* 358b0104773SPascal Brand * Note that keys should not be freed here, since they are 359b0104773SPascal Brand * claimed by the operation they will be freed by 360b0104773SPascal Brand * utee_cryp_state_free(). 361b0104773SPascal Brand */ 362e889e80bSCedric Chaumont res = utee_cryp_state_free(operation->state); 363e889e80bSCedric Chaumont if (res != TEE_SUCCESS) 364b36311adSJerome Forissier TEE_Panic(res); 365e889e80bSCedric Chaumont 366b0104773SPascal Brand TEE_Free(operation->buffer); 367b0104773SPascal Brand TEE_Free(operation); 368b0104773SPascal Brand } 369b0104773SPascal Brand 370b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation, 371b0104773SPascal Brand TEE_OperationInfo *operationInfo) 372b0104773SPascal Brand { 373b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 374b0104773SPascal Brand TEE_Panic(0); 375b0104773SPascal Brand 37605304565SCedric Chaumont if (!operationInfo) 377b0104773SPascal Brand TEE_Panic(0); 378b0104773SPascal Brand 379b0104773SPascal Brand *operationInfo = operation->info; 380b0104773SPascal Brand } 381b0104773SPascal Brand 38205304565SCedric Chaumont TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, 38305304565SCedric Chaumont TEE_OperationInfoMultiple *operationInfoMultiple, 38405304565SCedric Chaumont uint32_t *operationSize) 38505304565SCedric Chaumont { 38605304565SCedric Chaumont TEE_Result res = TEE_SUCCESS; 38705304565SCedric Chaumont TEE_ObjectInfo key_info1; 38805304565SCedric Chaumont TEE_ObjectInfo key_info2; 38905304565SCedric Chaumont uint32_t num_of_keys; 39005304565SCedric Chaumont size_t n; 39105304565SCedric Chaumont 39205304565SCedric Chaumont if (operation == TEE_HANDLE_NULL) { 39305304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 39405304565SCedric Chaumont goto out; 39505304565SCedric Chaumont } 39605304565SCedric Chaumont 39705304565SCedric Chaumont if (!operationInfoMultiple) { 39805304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 39905304565SCedric Chaumont goto out; 40005304565SCedric Chaumont } 40105304565SCedric Chaumont 40205304565SCedric Chaumont if (!operationSize) { 40305304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40405304565SCedric Chaumont goto out; 40505304565SCedric Chaumont } 40605304565SCedric Chaumont 40705304565SCedric Chaumont num_of_keys = (*operationSize-sizeof(TEE_OperationInfoMultiple))/ 40805304565SCedric Chaumont sizeof(TEE_OperationInfoKey); 40905304565SCedric Chaumont 41005304565SCedric Chaumont if (num_of_keys > 2) { 41105304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 41205304565SCedric Chaumont goto out; 41305304565SCedric Chaumont } 41405304565SCedric Chaumont 41505304565SCedric Chaumont /* Two keys flag (TEE_ALG_AES_XTS only) */ 41605304565SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 41705304565SCedric Chaumont 0 && 41805304565SCedric Chaumont (num_of_keys != 2)) { 41905304565SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 42005304565SCedric Chaumont goto out; 42105304565SCedric Chaumont } 42205304565SCedric Chaumont 42305304565SCedric Chaumont /* Clear */ 42405304565SCedric Chaumont for (n = 0; n < num_of_keys; n++) { 42505304565SCedric Chaumont operationInfoMultiple->keyInformation[n].keySize = 0; 42605304565SCedric Chaumont operationInfoMultiple->keyInformation[n].requiredKeyUsage = 0; 42705304565SCedric Chaumont } 42805304565SCedric Chaumont 42905304565SCedric Chaumont if (num_of_keys == 2) { 43005304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key2, &key_info2); 43105304565SCedric Chaumont /* Key2 is not a valid handle */ 43205304565SCedric Chaumont if (res != TEE_SUCCESS) 43305304565SCedric Chaumont goto out; 43405304565SCedric Chaumont 43505304565SCedric Chaumont operationInfoMultiple->keyInformation[1].keySize = 43605304565SCedric Chaumont key_info2.keySize; 43705304565SCedric Chaumont operationInfoMultiple->keyInformation[1].requiredKeyUsage = 43805304565SCedric Chaumont operation->info.requiredKeyUsage; 43905304565SCedric Chaumont } 44005304565SCedric Chaumont 44105304565SCedric Chaumont if (num_of_keys >= 1) { 44205304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key1, &key_info1); 44305304565SCedric Chaumont /* Key1 is not a valid handle */ 44405304565SCedric Chaumont if (res != TEE_SUCCESS) { 44505304565SCedric Chaumont if (num_of_keys == 2) { 44605304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 44705304565SCedric Chaumont keySize = 0; 44805304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 44905304565SCedric Chaumont requiredKeyUsage = 0; 45005304565SCedric Chaumont } 45105304565SCedric Chaumont goto out; 45205304565SCedric Chaumont } 45305304565SCedric Chaumont 45405304565SCedric Chaumont operationInfoMultiple->keyInformation[0].keySize = 45505304565SCedric Chaumont key_info1.keySize; 45605304565SCedric Chaumont operationInfoMultiple->keyInformation[0].requiredKeyUsage = 45705304565SCedric Chaumont operation->info.requiredKeyUsage; 45805304565SCedric Chaumont } 45905304565SCedric Chaumont 46005304565SCedric Chaumont /* No key */ 46105304565SCedric Chaumont operationInfoMultiple->algorithm = operation->info.algorithm; 46205304565SCedric Chaumont operationInfoMultiple->operationClass = operation->info.operationClass; 46305304565SCedric Chaumont operationInfoMultiple->mode = operation->info.mode; 46405304565SCedric Chaumont operationInfoMultiple->digestLength = operation->info.digestLength; 46505304565SCedric Chaumont operationInfoMultiple->maxKeySize = operation->info.maxKeySize; 46605304565SCedric Chaumont operationInfoMultiple->handleState = operation->info.handleState; 46705304565SCedric Chaumont operationInfoMultiple->operationState = operation->operationState; 46805304565SCedric Chaumont operationInfoMultiple->numberOfKeys = num_of_keys; 46905304565SCedric Chaumont 47005304565SCedric Chaumont out: 47105304565SCedric Chaumont if (res != TEE_SUCCESS && 47205304565SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 473b36311adSJerome Forissier TEE_Panic(res); 47405304565SCedric Chaumont 47505304565SCedric Chaumont return res; 47605304565SCedric Chaumont } 47705304565SCedric Chaumont 478b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation) 479b0104773SPascal Brand { 480b0104773SPascal Brand TEE_Result res; 481b0104773SPascal Brand 482b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 483b0104773SPascal Brand TEE_Panic(0); 484bf80076aSCedric Chaumont 485642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) 486bf80076aSCedric Chaumont TEE_Panic(0); 487bf80076aSCedric Chaumont 488642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 489642a1607SCedric Chaumont 490b0104773SPascal Brand if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 491b0104773SPascal Brand res = utee_hash_init(operation->state, NULL, 0); 492b0104773SPascal Brand if (res != TEE_SUCCESS) 493b0104773SPascal Brand TEE_Panic(res); 49405304565SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 49505304565SCedric Chaumont } else { 496b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 497b0104773SPascal Brand } 49805304565SCedric Chaumont } 499b0104773SPascal Brand 500b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, 501b0104773SPascal Brand TEE_ObjectHandle key) 502b0104773SPascal Brand { 5037583c59eSCedric Chaumont TEE_Result res; 504b0104773SPascal Brand uint32_t key_size = 0; 505b0104773SPascal Brand TEE_ObjectInfo key_info; 506b0104773SPascal Brand 507a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 508a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 509a57c1e2eSCedric Chaumont goto out; 510a57c1e2eSCedric Chaumont } 511a57c1e2eSCedric Chaumont 512642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 513642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 514642a1607SCedric Chaumont goto out; 515642a1607SCedric Chaumont } 516642a1607SCedric Chaumont 517a57c1e2eSCedric Chaumont if (key == TEE_HANDLE_NULL) { 518a57c1e2eSCedric Chaumont /* Operation key cleared */ 519a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 520a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 521a57c1e2eSCedric Chaumont goto out; 522a57c1e2eSCedric Chaumont } 523a57c1e2eSCedric Chaumont 524a57c1e2eSCedric Chaumont /* No key for digest operation */ 525a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 526a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 527a57c1e2eSCedric Chaumont goto out; 528a57c1e2eSCedric Chaumont } 529a57c1e2eSCedric Chaumont 530a57c1e2eSCedric Chaumont /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ 531a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 532a57c1e2eSCedric Chaumont 0) { 533a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 534a57c1e2eSCedric Chaumont goto out; 535a57c1e2eSCedric Chaumont } 536a57c1e2eSCedric Chaumont 5377583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key, &key_info); 538a57c1e2eSCedric Chaumont /* Key is not a valid handle */ 5397583c59eSCedric Chaumont if (res != TEE_SUCCESS) 540a57c1e2eSCedric Chaumont goto out; 5417583c59eSCedric Chaumont 542b0104773SPascal Brand /* Supplied key has to meet required usage */ 543b0104773SPascal Brand if ((key_info.objectUsage & operation->info.requiredKeyUsage) != 544b0104773SPascal Brand operation->info.requiredKeyUsage) { 545a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 546a57c1e2eSCedric Chaumont goto out; 547b0104773SPascal Brand } 548b0104773SPascal Brand 549a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info.keySize) { 550a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 551a57c1e2eSCedric Chaumont goto out; 552a57c1e2eSCedric Chaumont } 553b0104773SPascal Brand 5547583c59eSCedric Chaumont key_size = key_info.keySize; 555b0104773SPascal Brand 556b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 557b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 558b0104773SPascal Brand 5597583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key); 5607583c59eSCedric Chaumont if (res != TEE_SUCCESS) 561a57c1e2eSCedric Chaumont goto out; 5627583c59eSCedric Chaumont 563b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 564b0104773SPascal Brand 565b0104773SPascal Brand operation->info.keySize = key_size; 566b0104773SPascal Brand 5677583c59eSCedric Chaumont out: 568a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 569a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 570a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 571b36311adSJerome Forissier TEE_Panic(res); 572a57c1e2eSCedric Chaumont 573a57c1e2eSCedric Chaumont return res; 574b0104773SPascal Brand } 575b0104773SPascal Brand 576b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, 577b0104773SPascal Brand TEE_ObjectHandle key1, TEE_ObjectHandle key2) 578b0104773SPascal Brand { 5797583c59eSCedric Chaumont TEE_Result res; 580b0104773SPascal Brand uint32_t key_size = 0; 581b0104773SPascal Brand TEE_ObjectInfo key_info1; 582b0104773SPascal Brand TEE_ObjectInfo key_info2; 583b0104773SPascal Brand 584a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 585a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 586a57c1e2eSCedric Chaumont goto out; 587a57c1e2eSCedric Chaumont } 588a57c1e2eSCedric Chaumont 589642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 590642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 591642a1607SCedric Chaumont goto out; 592642a1607SCedric Chaumont } 593642a1607SCedric Chaumont 594a57c1e2eSCedric Chaumont /* 595a57c1e2eSCedric Chaumont * Key1/Key2 and/or are not initialized and 596a57c1e2eSCedric Chaumont * Either both keys are NULL or both are not NULL 597a57c1e2eSCedric Chaumont */ 598a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL || key2 == TEE_HANDLE_NULL) { 599a57c1e2eSCedric Chaumont /* Clear operation key1 (if needed) */ 600a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL) 601a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 602a57c1e2eSCedric Chaumont /* Clear operation key2 (if needed) */ 603a57c1e2eSCedric Chaumont if (key2 == TEE_HANDLE_NULL) 604a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key2); 605a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 606a57c1e2eSCedric Chaumont goto out; 607a57c1e2eSCedric Chaumont } 608a57c1e2eSCedric Chaumont 609a57c1e2eSCedric Chaumont /* No key for digest operation */ 610a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 611a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 612a57c1e2eSCedric Chaumont goto out; 613a57c1e2eSCedric Chaumont } 614a57c1e2eSCedric Chaumont 615a57c1e2eSCedric Chaumont /* Two keys flag expected (TEE_ALG_AES_XTS only) */ 616a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 617a57c1e2eSCedric Chaumont 0) { 618a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 619a57c1e2eSCedric Chaumont goto out; 620a57c1e2eSCedric Chaumont } 621a57c1e2eSCedric Chaumont 6227583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key1, &key_info1); 623a57c1e2eSCedric Chaumont /* Key1 is not a valid handle */ 6247583c59eSCedric Chaumont if (res != TEE_SUCCESS) 625a57c1e2eSCedric Chaumont goto out; 6267583c59eSCedric Chaumont 627b0104773SPascal Brand /* Supplied key has to meet required usage */ 628b0104773SPascal Brand if ((key_info1.objectUsage & operation->info. 629b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 630a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 631a57c1e2eSCedric Chaumont goto out; 632b0104773SPascal Brand } 633b0104773SPascal Brand 6347583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key2, &key_info2); 635a57c1e2eSCedric Chaumont /* Key2 is not a valid handle */ 6367583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6377583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6387583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 639a57c1e2eSCedric Chaumont goto out; 6407583c59eSCedric Chaumont } 6417583c59eSCedric Chaumont 642b0104773SPascal Brand /* Supplied key has to meet required usage */ 643b0104773SPascal Brand if ((key_info2.objectUsage & operation->info. 644b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 645a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 646a57c1e2eSCedric Chaumont goto out; 647b0104773SPascal Brand } 648b0104773SPascal Brand 649b0104773SPascal Brand /* 650b0104773SPascal Brand * AES-XTS (the only multi key algorithm supported, requires the 651b0104773SPascal Brand * keys to be of equal size. 652b0104773SPascal Brand */ 653b0104773SPascal Brand if (operation->info.algorithm == TEE_ALG_AES_XTS && 654a57c1e2eSCedric Chaumont key_info1.keySize != key_info2.keySize) { 655a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 656a57c1e2eSCedric Chaumont goto out; 657b0104773SPascal Brand 658a57c1e2eSCedric Chaumont } 659a57c1e2eSCedric Chaumont 660a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info1.keySize) { 661a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 662a57c1e2eSCedric Chaumont goto out; 663a57c1e2eSCedric Chaumont } 664b0104773SPascal Brand 665b0104773SPascal Brand /* 666b0104773SPascal Brand * Odd that only the size of one key should be reported while 667b0104773SPascal Brand * size of two key are used when allocating the operation. 668b0104773SPascal Brand */ 6697583c59eSCedric Chaumont key_size = key_info1.keySize; 670b0104773SPascal Brand 671b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 672b0104773SPascal Brand TEE_ResetTransientObject(operation->key2); 673b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 674b0104773SPascal Brand 6757583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key1); 6767583c59eSCedric Chaumont if (res != TEE_SUCCESS) 677a57c1e2eSCedric Chaumont goto out; 6787583c59eSCedric Chaumont 6797583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key2, key2); 6807583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6817583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6827583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 683a57c1e2eSCedric Chaumont goto out; 6847583c59eSCedric Chaumont } 6857583c59eSCedric Chaumont 686b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 687b0104773SPascal Brand 688b0104773SPascal Brand operation->info.keySize = key_size; 689b0104773SPascal Brand 6907583c59eSCedric Chaumont out: 691a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 692a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 693a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT_2 && 694a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE && 695a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) 696b36311adSJerome Forissier TEE_Panic(res); 697a57c1e2eSCedric Chaumont 698a57c1e2eSCedric Chaumont return res; 699b0104773SPascal Brand } 700b0104773SPascal Brand 701b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) 702b0104773SPascal Brand { 703b0104773SPascal Brand TEE_Result res; 704b0104773SPascal Brand 705b0104773SPascal Brand if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) 706b0104773SPascal Brand TEE_Panic(0); 707b0104773SPascal Brand if (dst_op->info.algorithm != src_op->info.algorithm) 708b0104773SPascal Brand TEE_Panic(0); 709b0104773SPascal Brand if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { 710b0104773SPascal Brand TEE_ObjectHandle key1 = TEE_HANDLE_NULL; 711b0104773SPascal Brand TEE_ObjectHandle key2 = TEE_HANDLE_NULL; 712b0104773SPascal Brand 713b0104773SPascal Brand if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { 714b0104773SPascal Brand key1 = src_op->key1; 715b0104773SPascal Brand key2 = src_op->key2; 716b0104773SPascal Brand } 717b0104773SPascal Brand 718b0104773SPascal Brand if ((src_op->info.handleState & 719b0104773SPascal Brand TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { 720b0104773SPascal Brand TEE_SetOperationKey(dst_op, key1); 721b0104773SPascal Brand } else { 722b0104773SPascal Brand TEE_SetOperationKey2(dst_op, key1, key2); 723b0104773SPascal Brand } 724b0104773SPascal Brand } 725b0104773SPascal Brand dst_op->info.handleState = src_op->info.handleState; 726b0104773SPascal Brand dst_op->info.keySize = src_op->info.keySize; 727642a1607SCedric Chaumont dst_op->operationState = src_op->operationState; 728b0104773SPascal Brand 729b0104773SPascal Brand if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || 730b0104773SPascal Brand dst_op->block_size != src_op->block_size) 731b0104773SPascal Brand TEE_Panic(0); 732b0104773SPascal Brand 733b0104773SPascal Brand if (dst_op->buffer != NULL) { 734b0104773SPascal Brand if (src_op->buffer == NULL) 735b0104773SPascal Brand TEE_Panic(0); 736b0104773SPascal Brand 737b0104773SPascal Brand memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs); 738b0104773SPascal Brand dst_op->buffer_offs = src_op->buffer_offs; 739b0104773SPascal Brand } else if (src_op->buffer != NULL) { 740b0104773SPascal Brand TEE_Panic(0); 741b0104773SPascal Brand } 742b0104773SPascal Brand 743b0104773SPascal Brand res = utee_cryp_state_copy(dst_op->state, src_op->state); 744b0104773SPascal Brand if (res != TEE_SUCCESS) 745b0104773SPascal Brand TEE_Panic(res); 746b0104773SPascal Brand } 747b0104773SPascal Brand 748b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */ 749b0104773SPascal Brand 7508f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV, 7516d15db08SJerome Forissier uint32_t IVLen) 7526d15db08SJerome Forissier { 7536d15db08SJerome Forissier TEE_Result res; 7546d15db08SJerome Forissier 7556d15db08SJerome Forissier /* 7566d15db08SJerome Forissier * Note : IV and IVLen are never used in current implementation 7576d15db08SJerome Forissier * This is why coherent values of IV and IVLen are not checked 7586d15db08SJerome Forissier */ 7596d15db08SJerome Forissier res = utee_hash_init(operation->state, IV, IVLen); 7606d15db08SJerome Forissier if (res != TEE_SUCCESS) 7616d15db08SJerome Forissier TEE_Panic(res); 7626d15db08SJerome Forissier operation->buffer_offs = 0; 7636d15db08SJerome Forissier operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 7646d15db08SJerome Forissier } 7656d15db08SJerome Forissier 766b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation, 7678f07fe6fSJerome Forissier const void *chunk, uint32_t chunkSize) 768b0104773SPascal Brand { 76973d6c3baSJoakim Bech TEE_Result res = TEE_ERROR_GENERIC; 770b0104773SPascal Brand 77173d6c3baSJoakim Bech if (operation == TEE_HANDLE_NULL || 77273d6c3baSJoakim Bech operation->info.operationClass != TEE_OPERATION_DIGEST) 773b0104773SPascal Brand TEE_Panic(0); 77473d6c3baSJoakim Bech 775642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 776642a1607SCedric Chaumont 777b0104773SPascal Brand res = utee_hash_update(operation->state, chunk, chunkSize); 778b0104773SPascal Brand if (res != TEE_SUCCESS) 779b0104773SPascal Brand TEE_Panic(res); 780b0104773SPascal Brand } 781b0104773SPascal Brand 7828f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, 78379a3c601SCedric Chaumont uint32_t chunkLen, void *hash, uint32_t *hashLen) 784b0104773SPascal Brand { 78587c2f6b6SCedric Chaumont TEE_Result res; 786e86f1266SJens Wiklander uint64_t hl; 78787c2f6b6SCedric Chaumont 78887c2f6b6SCedric Chaumont if ((operation == TEE_HANDLE_NULL) || 78987c2f6b6SCedric Chaumont (!chunk && chunkLen) || 79087c2f6b6SCedric Chaumont !hash || 79187c2f6b6SCedric Chaumont !hashLen || 79287c2f6b6SCedric Chaumont (operation->info.operationClass != TEE_OPERATION_DIGEST)) { 79387c2f6b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 79487c2f6b6SCedric Chaumont goto out; 79587c2f6b6SCedric Chaumont } 79687c2f6b6SCedric Chaumont 797e86f1266SJens Wiklander hl = *hashLen; 798e86f1266SJens Wiklander res = utee_hash_final(operation->state, chunk, chunkLen, hash, &hl); 799e86f1266SJens Wiklander *hashLen = hl; 8006d15db08SJerome Forissier if (res != TEE_SUCCESS) 8016d15db08SJerome Forissier goto out; 8026d15db08SJerome Forissier 8036d15db08SJerome Forissier /* Reset operation state */ 8046d15db08SJerome Forissier init_hash_operation(operation, NULL, 0); 80587c2f6b6SCedric Chaumont 806642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 807642a1607SCedric Chaumont 80887c2f6b6SCedric Chaumont out: 80987c2f6b6SCedric Chaumont if (res != TEE_SUCCESS && 81087c2f6b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 811b36311adSJerome Forissier TEE_Panic(res); 81273d6c3baSJoakim Bech 81387c2f6b6SCedric Chaumont return res; 814b0104773SPascal Brand } 815b0104773SPascal Brand 816b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */ 817b0104773SPascal Brand 8188f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, 8198f07fe6fSJerome Forissier uint32_t IVLen) 820b0104773SPascal Brand { 821b0104773SPascal Brand TEE_Result res; 822b0104773SPascal Brand 823b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 824b0104773SPascal Brand TEE_Panic(0); 825642a1607SCedric Chaumont 826b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_CIPHER) 827b0104773SPascal Brand TEE_Panic(0); 828642a1607SCedric Chaumont 829642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 830642a1607SCedric Chaumont !(operation->key1)) 831642a1607SCedric Chaumont TEE_Panic(0); 832642a1607SCedric Chaumont 833642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 834642a1607SCedric Chaumont TEE_ResetOperation(operation); 835642a1607SCedric Chaumont 836642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 837642a1607SCedric Chaumont 838b0104773SPascal Brand res = utee_cipher_init(operation->state, IV, IVLen); 839b0104773SPascal Brand if (res != TEE_SUCCESS) 840b0104773SPascal Brand TEE_Panic(res); 841642a1607SCedric Chaumont 842b0104773SPascal Brand operation->buffer_offs = 0; 843b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 844b0104773SPascal Brand } 845b0104773SPascal Brand 846b0104773SPascal Brand static TEE_Result tee_buffer_update( 847b0104773SPascal Brand TEE_OperationHandle op, 848e86f1266SJens Wiklander TEE_Result(*update_func)(unsigned long state, const void *src, 849e86f1266SJens Wiklander size_t slen, void *dst, uint64_t *dlen), 850b0104773SPascal Brand const void *src_data, size_t src_len, 851e86f1266SJens Wiklander void *dest_data, uint64_t *dest_len) 852b0104773SPascal Brand { 853b0104773SPascal Brand TEE_Result res; 854b0104773SPascal Brand const uint8_t *src = src_data; 855b0104773SPascal Brand size_t slen = src_len; 856b0104773SPascal Brand uint8_t *dst = dest_data; 857b0104773SPascal Brand size_t dlen = *dest_len; 858b0104773SPascal Brand size_t acc_dlen = 0; 859e86f1266SJens Wiklander uint64_t tmp_dlen; 860b0104773SPascal Brand size_t l; 861b0104773SPascal Brand size_t buffer_size; 862d3588802SPascal Brand size_t buffer_left; 863b0104773SPascal Brand 864090268f5SJens Wiklander if (!src) { 865090268f5SJens Wiklander if (slen) 866090268f5SJens Wiklander TEE_Panic(0); 867090268f5SJens Wiklander goto out; 868090268f5SJens Wiklander } 869090268f5SJens Wiklander 870d3588802SPascal Brand if (op->buffer_two_blocks) { 871b0104773SPascal Brand buffer_size = op->block_size * 2; 872d3588802SPascal Brand buffer_left = 1; 873d3588802SPascal Brand } else { 874b0104773SPascal Brand buffer_size = op->block_size; 875d3588802SPascal Brand buffer_left = 0; 876d3588802SPascal Brand } 877b0104773SPascal Brand 878b0104773SPascal Brand if (op->buffer_offs > 0) { 879b0104773SPascal Brand /* Fill up complete block */ 880b0104773SPascal Brand if (op->buffer_offs < op->block_size) 881b0104773SPascal Brand l = MIN(slen, op->block_size - op->buffer_offs); 882b0104773SPascal Brand else 883b0104773SPascal Brand l = MIN(slen, buffer_size - op->buffer_offs); 884b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, l); 885b0104773SPascal Brand op->buffer_offs += l; 886b0104773SPascal Brand src += l; 887b0104773SPascal Brand slen -= l; 888b0104773SPascal Brand if ((op->buffer_offs % op->block_size) != 0) 889b0104773SPascal Brand goto out; /* Nothing left to do */ 890b0104773SPascal Brand } 891b0104773SPascal Brand 892b0104773SPascal Brand /* If we can feed from buffer */ 893d3588802SPascal Brand if ((op->buffer_offs > 0) && 894d3588802SPascal Brand ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) { 8952ff3fdbbSPascal Brand l = ROUNDUP(op->buffer_offs + slen - buffer_size, 896b0104773SPascal Brand op->block_size); 897b0104773SPascal Brand l = MIN(op->buffer_offs, l); 898b0104773SPascal Brand tmp_dlen = dlen; 899b0104773SPascal Brand res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); 900b0104773SPascal Brand if (res != TEE_SUCCESS) 901b0104773SPascal Brand TEE_Panic(res); 902b0104773SPascal Brand dst += tmp_dlen; 903b0104773SPascal Brand dlen -= tmp_dlen; 904b0104773SPascal Brand acc_dlen += tmp_dlen; 905b0104773SPascal Brand op->buffer_offs -= l; 906b0104773SPascal Brand if (op->buffer_offs > 0) { 907b0104773SPascal Brand /* 908b0104773SPascal Brand * Slen is small enough to be contained in rest buffer. 909b0104773SPascal Brand */ 910b0104773SPascal Brand memcpy(op->buffer, op->buffer + l, buffer_size - l); 911b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 912b0104773SPascal Brand op->buffer_offs += slen; 913b0104773SPascal Brand goto out; /* Nothing left to do */ 914b0104773SPascal Brand } 915b0104773SPascal Brand } 916b0104773SPascal Brand 917d3588802SPascal Brand if (slen >= (buffer_size + buffer_left)) { 918b0104773SPascal Brand /* Buffer is empty, feed as much as possible from src */ 919bf7a587fSJerome Forissier if (op->info.algorithm == TEE_ALG_AES_CTS) 920b1ecda78SJerome Forissier l = ROUNDUP(slen - buffer_size, op->block_size); 921bf7a587fSJerome Forissier else 922bf7a587fSJerome Forissier l = ROUNDUP(slen - buffer_size + 1, op->block_size); 923b0104773SPascal Brand 924b0104773SPascal Brand tmp_dlen = dlen; 925b0104773SPascal Brand res = update_func(op->state, src, l, dst, &tmp_dlen); 926b0104773SPascal Brand if (res != TEE_SUCCESS) 927b0104773SPascal Brand TEE_Panic(res); 928b0104773SPascal Brand src += l; 929b0104773SPascal Brand slen -= l; 930b0104773SPascal Brand dst += tmp_dlen; 931b0104773SPascal Brand dlen -= tmp_dlen; 932b0104773SPascal Brand acc_dlen += tmp_dlen; 933b0104773SPascal Brand } 934b0104773SPascal Brand 935b0104773SPascal Brand /* Slen is small enough to be contained in buffer. */ 936b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 937b0104773SPascal Brand op->buffer_offs += slen; 938b0104773SPascal Brand 939b0104773SPascal Brand out: 940b0104773SPascal Brand *dest_len = acc_dlen; 941b0104773SPascal Brand return TEE_SUCCESS; 942b0104773SPascal Brand } 943b0104773SPascal Brand 9448f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, 94579a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 946b0104773SPascal Brand { 947dea1f2b6SCedric Chaumont TEE_Result res; 948b0104773SPascal Brand size_t req_dlen; 949e86f1266SJens Wiklander uint64_t dl; 950b0104773SPascal Brand 951642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 952dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 953dea1f2b6SCedric Chaumont destLen == NULL || 954dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 955dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 956dea1f2b6SCedric Chaumont goto out; 957dea1f2b6SCedric Chaumont } 958dea1f2b6SCedric Chaumont 959642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 960dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 961dea1f2b6SCedric Chaumont goto out; 962dea1f2b6SCedric Chaumont } 963dea1f2b6SCedric Chaumont 964642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 965642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 966642a1607SCedric Chaumont goto out; 967642a1607SCedric Chaumont } 968642a1607SCedric Chaumont 969642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 970dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 971dea1f2b6SCedric Chaumont goto out; 972dea1f2b6SCedric Chaumont } 973b0104773SPascal Brand 974e32c5ddfSJerome Forissier if (!srcData && !srcLen) { 975090268f5SJens Wiklander *destLen = 0; 976e32c5ddfSJerome Forissier res = TEE_SUCCESS; 977e32c5ddfSJerome Forissier goto out; 978e32c5ddfSJerome Forissier } 979e32c5ddfSJerome Forissier 980b0104773SPascal Brand /* Calculate required dlen */ 98157aabac5SBogdan Liulko if (operation->block_size > 1) { 98257aabac5SBogdan Liulko req_dlen = ((operation->buffer_offs + srcLen) / 98357aabac5SBogdan Liulko operation->block_size) * operation->block_size; 98457aabac5SBogdan Liulko } else { 98557aabac5SBogdan Liulko req_dlen = srcLen; 98657aabac5SBogdan Liulko } 987642a1607SCedric Chaumont if (operation->buffer_two_blocks) { 988642a1607SCedric Chaumont if (req_dlen > operation->block_size * 2) 989642a1607SCedric Chaumont req_dlen -= operation->block_size * 2; 990b0104773SPascal Brand else 991b0104773SPascal Brand req_dlen = 0; 992b0104773SPascal Brand } 993b0104773SPascal Brand /* 994b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 995b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 996b0104773SPascal Brand * can't restore sync with this API. 997b0104773SPascal Brand */ 998b0104773SPascal Brand if (*destLen < req_dlen) { 999b0104773SPascal Brand *destLen = req_dlen; 1000dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1001dea1f2b6SCedric Chaumont goto out; 1002b0104773SPascal Brand } 1003b0104773SPascal Brand 1004e86f1266SJens Wiklander dl = *destLen; 100557aabac5SBogdan Liulko if (operation->block_size > 1) { 100657aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, srcData, 100757aabac5SBogdan Liulko srcLen, destData, &dl); 100857aabac5SBogdan Liulko } else { 100957aabac5SBogdan Liulko if (srcLen > 0) { 101057aabac5SBogdan Liulko res = utee_cipher_update(operation->state, srcData, 101157aabac5SBogdan Liulko srcLen, destData, &dl); 101257aabac5SBogdan Liulko } else { 101357aabac5SBogdan Liulko res = TEE_SUCCESS; 101457aabac5SBogdan Liulko dl = 0; 101557aabac5SBogdan Liulko } 101657aabac5SBogdan Liulko } 1017e86f1266SJens Wiklander *destLen = dl; 1018b0104773SPascal Brand 1019dea1f2b6SCedric Chaumont out: 1020dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1021dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1022b36311adSJerome Forissier TEE_Panic(res); 1023dea1f2b6SCedric Chaumont 1024dea1f2b6SCedric Chaumont return res; 1025b0104773SPascal Brand } 1026b0104773SPascal Brand 1027642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, 10288f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 10298f07fe6fSJerome Forissier void *destData, uint32_t *destLen) 1030b0104773SPascal Brand { 1031b0104773SPascal Brand TEE_Result res; 1032b0104773SPascal Brand uint8_t *dst = destData; 1033b0104773SPascal Brand size_t acc_dlen = 0; 1034e86f1266SJens Wiklander uint64_t tmp_dlen; 1035b0104773SPascal Brand size_t req_dlen; 1036b0104773SPascal Brand 1037642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1038dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 1039dea1f2b6SCedric Chaumont destLen == NULL || 1040dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 1041dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1042dea1f2b6SCedric Chaumont goto out; 1043dea1f2b6SCedric Chaumont } 1044dea1f2b6SCedric Chaumont 1045642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 1046dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1047dea1f2b6SCedric Chaumont goto out; 1048dea1f2b6SCedric Chaumont } 1049dea1f2b6SCedric Chaumont 1050642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1051642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1052642a1607SCedric Chaumont goto out; 1053642a1607SCedric Chaumont } 1054642a1607SCedric Chaumont 1055642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1056dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1057dea1f2b6SCedric Chaumont goto out; 1058dea1f2b6SCedric Chaumont } 1059b0104773SPascal Brand 1060b0104773SPascal Brand /* 1061b0104773SPascal Brand * Check that the final block doesn't require padding for those 1062b0104773SPascal Brand * algorithms that requires client to supply padding. 1063b0104773SPascal Brand */ 1064642a1607SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || 1065642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || 1066642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || 1067642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || 1068642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || 1069642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD) { 1070642a1607SCedric Chaumont if (((operation->buffer_offs + srcLen) % operation->block_size) 1071642a1607SCedric Chaumont != 0) { 1072dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1073dea1f2b6SCedric Chaumont goto out; 1074dea1f2b6SCedric Chaumont } 1075b0104773SPascal Brand } 1076b0104773SPascal Brand 1077b0104773SPascal Brand /* 1078b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1079b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1080b0104773SPascal Brand * can't restore sync with this API. 1081b0104773SPascal Brand */ 108257aabac5SBogdan Liulko if (operation->block_size > 1) { 1083642a1607SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 108457aabac5SBogdan Liulko } else { 108557aabac5SBogdan Liulko req_dlen = srcLen; 108657aabac5SBogdan Liulko } 1087b0104773SPascal Brand if (*destLen < req_dlen) { 1088b0104773SPascal Brand *destLen = req_dlen; 1089dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1090dea1f2b6SCedric Chaumont goto out; 1091b0104773SPascal Brand } 1092b0104773SPascal Brand 1093b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 109457aabac5SBogdan Liulko if (operation->block_size > 1) { 109557aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, 109657aabac5SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1097dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS) 1098dea1f2b6SCedric Chaumont goto out; 1099dea1f2b6SCedric Chaumont 1100b0104773SPascal Brand dst += tmp_dlen; 1101b0104773SPascal Brand acc_dlen += tmp_dlen; 1102b0104773SPascal Brand 1103b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1104642a1607SCedric Chaumont res = utee_cipher_final(operation->state, operation->buffer, 1105642a1607SCedric Chaumont operation->buffer_offs, dst, &tmp_dlen); 110657aabac5SBogdan Liulko } else { 110757aabac5SBogdan Liulko res = utee_cipher_final(operation->state, srcData, 110857aabac5SBogdan Liulko srcLen, dst, &tmp_dlen); 110957aabac5SBogdan Liulko } 1110b0104773SPascal Brand if (res != TEE_SUCCESS) 1111dea1f2b6SCedric Chaumont goto out; 1112dea1f2b6SCedric Chaumont 1113b0104773SPascal Brand acc_dlen += tmp_dlen; 1114b0104773SPascal Brand *destLen = acc_dlen; 1115dea1f2b6SCedric Chaumont 1116642a1607SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1117642a1607SCedric Chaumont 1118642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1119642a1607SCedric Chaumont 1120dea1f2b6SCedric Chaumont out: 1121dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1122dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1123b36311adSJerome Forissier TEE_Panic(res); 1124dea1f2b6SCedric Chaumont 1125dea1f2b6SCedric Chaumont return res; 1126b0104773SPascal Brand } 1127b0104773SPascal Brand 1128b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */ 1129b0104773SPascal Brand 11308f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) 1131b0104773SPascal Brand { 1132b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 1133b0104773SPascal Brand TEE_Panic(0); 1134642a1607SCedric Chaumont 1135b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_MAC) 1136b0104773SPascal Brand TEE_Panic(0); 1137642a1607SCedric Chaumont 1138642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 1139642a1607SCedric Chaumont !(operation->key1)) 1140642a1607SCedric Chaumont TEE_Panic(0); 1141642a1607SCedric Chaumont 1142642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 1143642a1607SCedric Chaumont TEE_ResetOperation(operation); 1144642a1607SCedric Chaumont 1145642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1146642a1607SCedric Chaumont 11476d15db08SJerome Forissier init_hash_operation(operation, IV, IVLen); 1148b0104773SPascal Brand } 1149b0104773SPascal Brand 11508f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, 115128e0efc6SCedric Chaumont uint32_t chunkSize) 1152b0104773SPascal Brand { 1153b0104773SPascal Brand TEE_Result res; 1154b0104773SPascal Brand 115528e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) 1156b0104773SPascal Brand TEE_Panic(0); 1157642a1607SCedric Chaumont 115828e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) 1159b0104773SPascal Brand TEE_Panic(0); 1160642a1607SCedric Chaumont 116128e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1162b0104773SPascal Brand TEE_Panic(0); 1163b0104773SPascal Brand 1164642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) 1165642a1607SCedric Chaumont TEE_Panic(0); 1166642a1607SCedric Chaumont 116728e0efc6SCedric Chaumont res = utee_hash_update(operation->state, chunk, chunkSize); 1168b0104773SPascal Brand if (res != TEE_SUCCESS) 1169b0104773SPascal Brand TEE_Panic(res); 1170b0104773SPascal Brand } 1171b0104773SPascal Brand 117228e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, 11738f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 117479a3c601SCedric Chaumont void *mac, uint32_t *macLen) 1175b0104773SPascal Brand { 1176b0104773SPascal Brand TEE_Result res; 1177e86f1266SJens Wiklander uint64_t ml; 1178b0104773SPascal Brand 117928e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || 118028e0efc6SCedric Chaumont (message == NULL && messageLen != 0) || 118128e0efc6SCedric Chaumont mac == NULL || 118228e0efc6SCedric Chaumont macLen == NULL) { 118328e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 118428e0efc6SCedric Chaumont goto out; 118528e0efc6SCedric Chaumont } 1186b0104773SPascal Brand 118728e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 118828e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 118928e0efc6SCedric Chaumont goto out; 119028e0efc6SCedric Chaumont } 119128e0efc6SCedric Chaumont 119228e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 119328e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 119428e0efc6SCedric Chaumont goto out; 119528e0efc6SCedric Chaumont } 119628e0efc6SCedric Chaumont 1197642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1198642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1199642a1607SCedric Chaumont goto out; 1200642a1607SCedric Chaumont } 1201642a1607SCedric Chaumont 1202e86f1266SJens Wiklander ml = *macLen; 1203e86f1266SJens Wiklander res = utee_hash_final(operation->state, message, messageLen, mac, &ml); 1204e86f1266SJens Wiklander *macLen = ml; 120528e0efc6SCedric Chaumont if (res != TEE_SUCCESS) 120628e0efc6SCedric Chaumont goto out; 120728e0efc6SCedric Chaumont 120828e0efc6SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 120928e0efc6SCedric Chaumont 1210642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1211642a1607SCedric Chaumont 121228e0efc6SCedric Chaumont out: 121328e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 121428e0efc6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 121528e0efc6SCedric Chaumont TEE_Panic(res); 121628e0efc6SCedric Chaumont 1217b0104773SPascal Brand return res; 1218b0104773SPascal Brand } 1219b0104773SPascal Brand 1220b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, 12218f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 12228f07fe6fSJerome Forissier const void *mac, uint32_t macLen) 1223b0104773SPascal Brand { 1224b0104773SPascal Brand TEE_Result res; 1225b0104773SPascal Brand uint8_t computed_mac[TEE_MAX_HASH_SIZE]; 12267f74c64aSPascal Brand uint32_t computed_mac_size = TEE_MAX_HASH_SIZE; 1227b0104773SPascal Brand 122828e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 122928e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 123028e0efc6SCedric Chaumont goto out; 123128e0efc6SCedric Chaumont } 123228e0efc6SCedric Chaumont 123328e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 123428e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 123528e0efc6SCedric Chaumont goto out; 123628e0efc6SCedric Chaumont } 123728e0efc6SCedric Chaumont 1238642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1239642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1240642a1607SCedric Chaumont goto out; 1241642a1607SCedric Chaumont } 1242642a1607SCedric Chaumont 1243b0104773SPascal Brand res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, 1244b0104773SPascal Brand &computed_mac_size); 1245b0104773SPascal Brand if (res != TEE_SUCCESS) 124628e0efc6SCedric Chaumont goto out; 124728e0efc6SCedric Chaumont 124828e0efc6SCedric Chaumont if (computed_mac_size != macLen) { 124928e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 125028e0efc6SCedric Chaumont goto out; 125128e0efc6SCedric Chaumont } 125228e0efc6SCedric Chaumont 1253*48e10604SJerome Forissier if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) { 125428e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 125528e0efc6SCedric Chaumont goto out; 125628e0efc6SCedric Chaumont } 125728e0efc6SCedric Chaumont 1258642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1259642a1607SCedric Chaumont 126028e0efc6SCedric Chaumont out: 126128e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 126228e0efc6SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 126328e0efc6SCedric Chaumont TEE_Panic(res); 126428e0efc6SCedric Chaumont 1265b0104773SPascal Brand return res; 1266b0104773SPascal Brand } 1267b0104773SPascal Brand 1268b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */ 1269b0104773SPascal Brand 12708f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, 127179a3c601SCedric Chaumont uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, 1272b0104773SPascal Brand uint32_t payloadLen) 1273b0104773SPascal Brand { 1274b0104773SPascal Brand TEE_Result res; 1275b0104773SPascal Brand 1276b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || nonce == NULL) { 1277b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1278b5816c88SCedric Chaumont goto out; 1279b5816c88SCedric Chaumont } 1280b5816c88SCedric Chaumont 1281b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1282b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1283b5816c88SCedric Chaumont goto out; 1284b5816c88SCedric Chaumont } 1285b0104773SPascal Brand 1286642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 1287642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1288642a1607SCedric Chaumont goto out; 1289642a1607SCedric Chaumont } 1290642a1607SCedric Chaumont 1291b0104773SPascal Brand /* 1292b0104773SPascal Brand * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core 1293b0104773SPascal Brand * in the implementation. But AES-GCM spec doesn't specify the tag len 1294b0104773SPascal Brand * according to the same principle so we have to check here instead to 1295b0104773SPascal Brand * be GP compliant. 1296b0104773SPascal Brand */ 1297b5816c88SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_GCM) { 1298b0104773SPascal Brand /* 1299b0104773SPascal Brand * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 1300b0104773SPascal Brand */ 1301b5816c88SCedric Chaumont if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) { 1302b5816c88SCedric Chaumont res = TEE_ERROR_NOT_SUPPORTED; 1303b5816c88SCedric Chaumont goto out; 1304b5816c88SCedric Chaumont } 1305b0104773SPascal Brand } 1306b0104773SPascal Brand 1307b5816c88SCedric Chaumont res = utee_authenc_init(operation->state, nonce, nonceLen, 1308b5816c88SCedric Chaumont tagLen / 8, AADLen, payloadLen); 1309b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1310b5816c88SCedric Chaumont goto out; 1311b5816c88SCedric Chaumont 1312b5816c88SCedric Chaumont operation->ae_tag_len = tagLen / 8; 1313b5816c88SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 1314b5816c88SCedric Chaumont 1315b5816c88SCedric Chaumont out: 1316b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1317b5816c88SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 1318b0104773SPascal Brand TEE_Panic(res); 1319b5816c88SCedric Chaumont 1320b0104773SPascal Brand return res; 1321b0104773SPascal Brand } 1322b0104773SPascal Brand 13238f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, 132479a3c601SCedric Chaumont uint32_t AADdataLen) 1325b0104773SPascal Brand { 1326b0104773SPascal Brand TEE_Result res; 1327b0104773SPascal Brand 1328b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1329b5816c88SCedric Chaumont (AADdata == NULL && AADdataLen != 0)) 1330b0104773SPascal Brand TEE_Panic(0); 1331642a1607SCedric Chaumont 1332b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) 1333b0104773SPascal Brand TEE_Panic(0); 1334642a1607SCedric Chaumont 1335b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1336b0104773SPascal Brand TEE_Panic(0); 1337b0104773SPascal Brand 1338b5816c88SCedric Chaumont res = utee_authenc_update_aad(operation->state, AADdata, AADdataLen); 1339642a1607SCedric Chaumont 1340642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1341642a1607SCedric Chaumont 1342b0104773SPascal Brand if (res != TEE_SUCCESS) 1343b0104773SPascal Brand TEE_Panic(res); 1344b0104773SPascal Brand } 1345b0104773SPascal Brand 13468f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, 134779a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 1348b0104773SPascal Brand { 1349b5816c88SCedric Chaumont TEE_Result res; 1350b0104773SPascal Brand size_t req_dlen; 1351e86f1266SJens Wiklander uint64_t dl; 1352b0104773SPascal Brand 1353b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1354b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1355b5816c88SCedric Chaumont destLen == NULL || 1356b5816c88SCedric Chaumont (destData == NULL && *destLen != 0)) { 1357b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1358b5816c88SCedric Chaumont goto out; 1359b5816c88SCedric Chaumont } 1360b5816c88SCedric Chaumont 1361b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1362b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1363b5816c88SCedric Chaumont goto out; 1364b5816c88SCedric Chaumont } 1365b5816c88SCedric Chaumont 1366b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1367b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1368b5816c88SCedric Chaumont goto out; 1369b5816c88SCedric Chaumont } 1370b0104773SPascal Brand 1371827308b8SJerome Forissier if (!srcData && !srcLen) { 1372090268f5SJens Wiklander *destLen = 0; 1373827308b8SJerome Forissier res = TEE_SUCCESS; 1374827308b8SJerome Forissier goto out; 1375827308b8SJerome Forissier } 1376827308b8SJerome Forissier 1377b0104773SPascal Brand /* 1378b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1379b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1380b0104773SPascal Brand * can't restore sync with this API. 1381b0104773SPascal Brand */ 1382afc0c182SBogdan Liulko if (operation->block_size > 1) { 1383b5816c88SCedric Chaumont req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen, 1384b5816c88SCedric Chaumont operation->block_size); 1385afc0c182SBogdan Liulko } else { 1386afc0c182SBogdan Liulko req_dlen = srcLen; 1387afc0c182SBogdan Liulko } 1388afc0c182SBogdan Liulko 1389b0104773SPascal Brand if (*destLen < req_dlen) { 1390b0104773SPascal Brand *destLen = req_dlen; 1391b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1392b5816c88SCedric Chaumont goto out; 1393b0104773SPascal Brand } 1394b0104773SPascal Brand 1395e86f1266SJens Wiklander dl = *destLen; 1396afc0c182SBogdan Liulko if (operation->block_size > 1) { 1397afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1398afc0c182SBogdan Liulko srcData, srcLen, destData, &dl); 1399afc0c182SBogdan Liulko } else { 1400afc0c182SBogdan Liulko if (srcLen > 0) { 1401afc0c182SBogdan Liulko res = utee_authenc_update_payload(operation->state, 1402afc0c182SBogdan Liulko srcData, srcLen, 1403afc0c182SBogdan Liulko destData, &dl); 1404afc0c182SBogdan Liulko } else { 1405afc0c182SBogdan Liulko dl = 0; 1406afc0c182SBogdan Liulko res = TEE_SUCCESS; 1407afc0c182SBogdan Liulko } 1408afc0c182SBogdan Liulko } 1409afc0c182SBogdan Liulko if (res != TEE_SUCCESS) 1410afc0c182SBogdan Liulko goto out; 1411afc0c182SBogdan Liulko 1412e86f1266SJens Wiklander *destLen = dl; 1413b0104773SPascal Brand 1414642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1415642a1607SCedric Chaumont 1416b5816c88SCedric Chaumont out: 1417b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1418b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1419b5816c88SCedric Chaumont TEE_Panic(res); 1420b5816c88SCedric Chaumont 1421b5816c88SCedric Chaumont return res; 1422b0104773SPascal Brand } 1423b0104773SPascal Brand 1424b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, 14258f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 142679a3c601SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 142779a3c601SCedric Chaumont uint32_t *tagLen) 1428b0104773SPascal Brand { 1429b0104773SPascal Brand TEE_Result res; 1430b0104773SPascal Brand uint8_t *dst = destData; 1431b0104773SPascal Brand size_t acc_dlen = 0; 1432e86f1266SJens Wiklander uint64_t tmp_dlen; 1433b0104773SPascal Brand size_t req_dlen; 1434e86f1266SJens Wiklander uint64_t tl; 1435b0104773SPascal Brand 1436b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1437b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1438b5816c88SCedric Chaumont destLen == NULL || 1439b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1440b5816c88SCedric Chaumont tag == NULL || tagLen == NULL) { 1441b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1442b5816c88SCedric Chaumont goto out; 1443b5816c88SCedric Chaumont } 1444b5816c88SCedric Chaumont 1445b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1446b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1447b5816c88SCedric Chaumont goto out; 1448b5816c88SCedric Chaumont } 1449b5816c88SCedric Chaumont 1450b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1451b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1452b5816c88SCedric Chaumont goto out; 1453b5816c88SCedric Chaumont } 1454b0104773SPascal Brand 1455b0104773SPascal Brand /* 1456b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1457b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1458b0104773SPascal Brand * can't restore sync with this API. 14592733280aSEtienne Carriere * 14602733280aSEtienne Carriere * Need to check this before update_payload since sync would be lost if 14612733280aSEtienne Carriere * we return short buffer after that. 1462b0104773SPascal Brand */ 14632733280aSEtienne Carriere res = TEE_ERROR_GENERIC; 14642733280aSEtienne Carriere 1465b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1466b0104773SPascal Brand if (*destLen < req_dlen) { 1467b0104773SPascal Brand *destLen = req_dlen; 1468b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1469b0104773SPascal Brand } 1470b0104773SPascal Brand 1471b5816c88SCedric Chaumont if (*tagLen < operation->ae_tag_len) { 1472b5816c88SCedric Chaumont *tagLen = operation->ae_tag_len; 1473b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1474b0104773SPascal Brand } 1475b0104773SPascal Brand 14762733280aSEtienne Carriere if (res == TEE_ERROR_SHORT_BUFFER) 14772733280aSEtienne Carriere goto out; 14782733280aSEtienne Carriere 1479afc0c182SBogdan Liulko tl = *tagLen; 1480b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1481afc0c182SBogdan Liulko if (operation->block_size > 1) { 1482afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1483afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1484b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1485b5816c88SCedric Chaumont goto out; 1486b5816c88SCedric Chaumont 1487b0104773SPascal Brand dst += tmp_dlen; 1488b0104773SPascal Brand acc_dlen += tmp_dlen; 1489b0104773SPascal Brand 1490b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1491afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, 1492afc0c182SBogdan Liulko operation->buffer, 1493afc0c182SBogdan Liulko operation->buffer_offs, dst, 1494afc0c182SBogdan Liulko &tmp_dlen, tag, &tl); 1495afc0c182SBogdan Liulko } else { 1496afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, srcData, 1497afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1498e86f1266SJens Wiklander tag, &tl); 1499afc0c182SBogdan Liulko } 1500e86f1266SJens Wiklander *tagLen = tl; 1501b0104773SPascal Brand if (res != TEE_SUCCESS) 1502b5816c88SCedric Chaumont goto out; 1503b0104773SPascal Brand 1504b5816c88SCedric Chaumont acc_dlen += tmp_dlen; 1505b0104773SPascal Brand *destLen = acc_dlen; 1506642a1607SCedric Chaumont 1507b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1508b5816c88SCedric Chaumont 1509642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1510642a1607SCedric Chaumont 1511b5816c88SCedric Chaumont out: 1512b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1513b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1514b5816c88SCedric Chaumont TEE_Panic(res); 1515b0104773SPascal Brand 1516b0104773SPascal Brand return res; 1517b0104773SPascal Brand } 1518b0104773SPascal Brand 1519b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, 15208f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 1521b5816c88SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 152279a3c601SCedric Chaumont uint32_t tagLen) 1523b0104773SPascal Brand { 1524b0104773SPascal Brand TEE_Result res; 1525b0104773SPascal Brand uint8_t *dst = destData; 1526b0104773SPascal Brand size_t acc_dlen = 0; 1527e86f1266SJens Wiklander uint64_t tmp_dlen; 1528b0104773SPascal Brand size_t req_dlen; 1529b0104773SPascal Brand 1530b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1531b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1532b5816c88SCedric Chaumont destLen == NULL || 1533b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1534b5816c88SCedric Chaumont (tag == NULL && tagLen != 0)) { 1535b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1536b5816c88SCedric Chaumont goto out; 1537b5816c88SCedric Chaumont } 1538b5816c88SCedric Chaumont 1539b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1540b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1541b5816c88SCedric Chaumont goto out; 1542b5816c88SCedric Chaumont } 1543b5816c88SCedric Chaumont 1544b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1545b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1546b5816c88SCedric Chaumont goto out; 1547b5816c88SCedric Chaumont } 1548b0104773SPascal Brand 1549b0104773SPascal Brand /* 1550b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1551b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1552b0104773SPascal Brand * can't restore sync with this API. 1553b0104773SPascal Brand */ 1554b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1555b0104773SPascal Brand if (*destLen < req_dlen) { 1556b0104773SPascal Brand *destLen = req_dlen; 1557b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1558b5816c88SCedric Chaumont goto out; 1559b0104773SPascal Brand } 1560b0104773SPascal Brand 1561b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1562afc0c182SBogdan Liulko if (operation->block_size > 1) { 1563afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1564afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1565b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1566b5816c88SCedric Chaumont goto out; 1567b5816c88SCedric Chaumont 1568b0104773SPascal Brand dst += tmp_dlen; 1569b0104773SPascal Brand acc_dlen += tmp_dlen; 1570b0104773SPascal Brand 1571b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1572afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, 1573afc0c182SBogdan Liulko operation->buffer, 1574afc0c182SBogdan Liulko operation->buffer_offs, dst, 1575afc0c182SBogdan Liulko &tmp_dlen, tag, tagLen); 1576afc0c182SBogdan Liulko } else { 1577afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, srcData, 1578afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1579b5816c88SCedric Chaumont tag, tagLen); 1580afc0c182SBogdan Liulko } 1581b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1582b5816c88SCedric Chaumont goto out; 1583b5816c88SCedric Chaumont 1584b0104773SPascal Brand /* Supplied tagLen should match what we initiated with */ 1585b5816c88SCedric Chaumont if (tagLen != operation->ae_tag_len) 1586b0104773SPascal Brand res = TEE_ERROR_MAC_INVALID; 1587b0104773SPascal Brand 1588b0104773SPascal Brand acc_dlen += tmp_dlen; 1589b0104773SPascal Brand *destLen = acc_dlen; 1590642a1607SCedric Chaumont 1591b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1592b5816c88SCedric Chaumont 1593642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1594642a1607SCedric Chaumont 1595b5816c88SCedric Chaumont out: 1596b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1597b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER && 1598b5816c88SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 1599b5816c88SCedric Chaumont TEE_Panic(res); 1600b0104773SPascal Brand 1601b0104773SPascal Brand return res; 1602b0104773SPascal Brand } 1603b0104773SPascal Brand 1604b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */ 1605b0104773SPascal Brand 160612e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, 16078f07fe6fSJerome Forissier const TEE_Attribute *params, 16088f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 160979a3c601SCedric Chaumont uint32_t srcLen, void *destData, 161079a3c601SCedric Chaumont uint32_t *destLen) 1611b0104773SPascal Brand { 1612b0104773SPascal Brand TEE_Result res; 1613e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1614e86f1266SJens Wiklander uint64_t dl; 1615b0104773SPascal Brand 161612e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1617b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1618b0104773SPascal Brand TEE_Panic(0); 161912e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1620b0104773SPascal Brand TEE_Panic(0); 162112e66b6fSCedric Chaumont if (!operation->key1) 1622b0104773SPascal Brand TEE_Panic(0); 162312e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 162412e66b6fSCedric Chaumont TEE_Panic(0); 162512e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_ENCRYPT) 1626b0104773SPascal Brand TEE_Panic(0); 1627b0104773SPascal Brand 1628e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1629e86f1266SJens Wiklander dl = *destLen; 1630e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1631e86f1266SJens Wiklander srcLen, destData, &dl); 1632e86f1266SJens Wiklander *destLen = dl; 163312e66b6fSCedric Chaumont 16348844ebfcSPascal Brand if (res != TEE_SUCCESS && 16358844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16368844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1637b0104773SPascal Brand TEE_Panic(res); 163812e66b6fSCedric Chaumont 1639b0104773SPascal Brand return res; 1640b0104773SPascal Brand } 1641b0104773SPascal Brand 164212e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, 16438f07fe6fSJerome Forissier const TEE_Attribute *params, 16448f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 164579a3c601SCedric Chaumont uint32_t srcLen, void *destData, 164679a3c601SCedric Chaumont uint32_t *destLen) 1647b0104773SPascal Brand { 1648b0104773SPascal Brand TEE_Result res; 1649e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1650e86f1266SJens Wiklander uint64_t dl; 1651b0104773SPascal Brand 165212e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1653b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1654b0104773SPascal Brand TEE_Panic(0); 165512e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1656b0104773SPascal Brand TEE_Panic(0); 165712e66b6fSCedric Chaumont if (!operation->key1) 1658b0104773SPascal Brand TEE_Panic(0); 165912e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 166012e66b6fSCedric Chaumont TEE_Panic(0); 166112e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_DECRYPT) 1662b0104773SPascal Brand TEE_Panic(0); 1663b0104773SPascal Brand 1664e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1665e86f1266SJens Wiklander dl = *destLen; 1666e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1667e86f1266SJens Wiklander srcLen, destData, &dl); 1668e86f1266SJens Wiklander *destLen = dl; 166912e66b6fSCedric Chaumont 16708844ebfcSPascal Brand if (res != TEE_SUCCESS && 16718844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16728844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1673b0104773SPascal Brand TEE_Panic(res); 167412e66b6fSCedric Chaumont 1675b0104773SPascal Brand return res; 1676b0104773SPascal Brand } 1677b0104773SPascal Brand 167812e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, 16798f07fe6fSJerome Forissier const TEE_Attribute *params, 16808f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 168179a3c601SCedric Chaumont uint32_t digestLen, void *signature, 168279a3c601SCedric Chaumont uint32_t *signatureLen) 1683b0104773SPascal Brand { 1684b0104773SPascal Brand TEE_Result res; 1685e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1686e86f1266SJens Wiklander uint64_t sl; 1687b0104773SPascal Brand 168812e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 168912e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1690b0104773SPascal Brand signature == NULL || signatureLen == NULL) 1691b0104773SPascal Brand TEE_Panic(0); 169212e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1693b0104773SPascal Brand TEE_Panic(0); 169412e66b6fSCedric Chaumont if (!operation->key1) 1695b0104773SPascal Brand TEE_Panic(0); 169612e66b6fSCedric Chaumont if (operation->info.operationClass != 169712e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 169812e66b6fSCedric Chaumont TEE_Panic(0); 169912e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_SIGN) 1700b0104773SPascal Brand TEE_Panic(0); 1701b0104773SPascal Brand 1702e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1703e86f1266SJens Wiklander sl = *signatureLen; 1704e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, digest, 1705e86f1266SJens Wiklander digestLen, signature, &sl); 1706e86f1266SJens Wiklander *signatureLen = sl; 170712e66b6fSCedric Chaumont 1708b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) 1709b0104773SPascal Brand TEE_Panic(res); 171012e66b6fSCedric Chaumont 1711b0104773SPascal Brand return res; 1712b0104773SPascal Brand } 1713b0104773SPascal Brand 171412e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, 17158f07fe6fSJerome Forissier const TEE_Attribute *params, 17168f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 17178f07fe6fSJerome Forissier uint32_t digestLen, 17188f07fe6fSJerome Forissier const void *signature, 171979a3c601SCedric Chaumont uint32_t signatureLen) 1720b0104773SPascal Brand { 1721b0104773SPascal Brand TEE_Result res; 1722e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1723b0104773SPascal Brand 172412e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 172512e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1726b0104773SPascal Brand (signature == NULL && signatureLen != 0)) 1727b0104773SPascal Brand TEE_Panic(0); 172812e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1729b0104773SPascal Brand TEE_Panic(0); 173012e66b6fSCedric Chaumont if (!operation->key1) 1731b0104773SPascal Brand TEE_Panic(0); 173212e66b6fSCedric Chaumont if (operation->info.operationClass != 173312e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 173412e66b6fSCedric Chaumont TEE_Panic(0); 173512e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_VERIFY) 1736b0104773SPascal Brand TEE_Panic(0); 1737b0104773SPascal Brand 1738e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1739e86f1266SJens Wiklander res = utee_asymm_verify(operation->state, ua, paramCount, digest, 174012e66b6fSCedric Chaumont digestLen, signature, signatureLen); 174112e66b6fSCedric Chaumont 1742b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) 1743b0104773SPascal Brand TEE_Panic(res); 174412e66b6fSCedric Chaumont 1745b0104773SPascal Brand return res; 1746b0104773SPascal Brand } 1747b0104773SPascal Brand 1748b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */ 1749b0104773SPascal Brand 1750b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation, 1751b0104773SPascal Brand const TEE_Attribute *params, uint32_t paramCount, 1752b0104773SPascal Brand TEE_ObjectHandle derivedKey) 1753b0104773SPascal Brand { 1754b0104773SPascal Brand TEE_Result res; 1755b0104773SPascal Brand TEE_ObjectInfo key_info; 1756e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1757b0104773SPascal Brand 1758b0104773SPascal Brand if (operation == TEE_HANDLE_NULL || derivedKey == 0) 1759b0104773SPascal Brand TEE_Panic(0); 176084fa9467SCedric Chaumont if (params == NULL && paramCount != 0) 1761b0104773SPascal Brand TEE_Panic(0); 17628854d3c6SJerome Forissier if (TEE_ALG_GET_CLASS(operation->info.algorithm) != 17638854d3c6SJerome Forissier TEE_OPERATION_KEY_DERIVATION) 1764b0104773SPascal Brand TEE_Panic(0); 1765b0104773SPascal Brand 1766b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) 1767b0104773SPascal Brand TEE_Panic(0); 176884fa9467SCedric Chaumont if (!operation->key1) 176984fa9467SCedric Chaumont TEE_Panic(0); 1770b0104773SPascal Brand if (operation->info.mode != TEE_MODE_DERIVE) 1771b0104773SPascal Brand TEE_Panic(0); 1772b0104773SPascal Brand if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) 1773b0104773SPascal Brand TEE_Panic(0); 1774b0104773SPascal Brand 1775e86f1266SJens Wiklander res = utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); 1776b0104773SPascal Brand if (res != TEE_SUCCESS) 1777b36311adSJerome Forissier TEE_Panic(res); 1778b0104773SPascal Brand 1779b0104773SPascal Brand if (key_info.objectType != TEE_TYPE_GENERIC_SECRET) 1780b0104773SPascal Brand TEE_Panic(0); 1781b0104773SPascal Brand if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) 1782b0104773SPascal Brand TEE_Panic(0); 1783b0104773SPascal Brand 1784e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1785e86f1266SJens Wiklander res = utee_cryp_derive_key(operation->state, ua, paramCount, 1786e86f1266SJens Wiklander (unsigned long)derivedKey); 1787b0104773SPascal Brand if (res != TEE_SUCCESS) 1788b0104773SPascal Brand TEE_Panic(res); 1789b0104773SPascal Brand } 1790b0104773SPascal Brand 1791b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */ 1792b0104773SPascal Brand 179379a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) 1794b0104773SPascal Brand { 1795b0104773SPascal Brand TEE_Result res; 1796b0104773SPascal Brand 1797b0104773SPascal Brand res = utee_cryp_random_number_generate(randomBuffer, randomBufferLen); 1798b0104773SPascal Brand if (res != TEE_SUCCESS) 1799b0104773SPascal Brand TEE_Panic(res); 1800b0104773SPascal Brand } 1801433c4257SJens Wiklander 1802433c4257SJens Wiklander int rand(void) 1803433c4257SJens Wiklander { 1804433c4257SJens Wiklander int rc; 1805433c4257SJens Wiklander 1806433c4257SJens Wiklander TEE_GenerateRandom(&rc, sizeof(rc)); 1807433c4257SJens Wiklander 1808433c4257SJens Wiklander /* 1809433c4257SJens Wiklander * RAND_MAX is the larges int, INT_MAX which is all bits but the 1810433c4257SJens Wiklander * highest bit set. 1811433c4257SJens Wiklander */ 1812433c4257SJens Wiklander return rc & RAND_MAX; 1813433c4257SJens Wiklander } 1814