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: 120*ade6f848SJerome Forissier case TEE_ALG_SM4_ECB_NOPAD: 121*ade6f848SJerome Forissier case TEE_ALG_SM4_CBC_NOPAD: 122*ade6f848SJerome Forissier case TEE_ALG_SM4_CTR: 123b0104773SPascal Brand if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) 124b0104773SPascal Brand block_size = TEE_AES_BLOCK_SIZE; 125*ade6f848SJerome Forissier else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4) 126*ade6f848SJerome Forissier block_size = TEE_SM4_BLOCK_SIZE; 127b0104773SPascal Brand else 128b0104773SPascal Brand block_size = TEE_DES_BLOCK_SIZE; 129afc0c182SBogdan Liulko /* FALLTHROUGH */ 13057aabac5SBogdan Liulko case TEE_ALG_AES_CTR: 131afc0c182SBogdan Liulko case TEE_ALG_AES_GCM: 132b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) 133b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 134b0104773SPascal Brand else if (mode == TEE_MODE_DECRYPT) 135b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 136b0104773SPascal Brand else 137b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 138b0104773SPascal Brand break; 139b0104773SPascal Brand 1406a2e0a9fSGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1) 1416a2e0a9fSGabor Szekely case TEE_ALG_RSASSA_PKCS1_V1_5: 1426a2e0a9fSGabor Szekely #endif 143b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 144b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 145b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 146b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 147b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 148b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 149b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 150b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 151b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 152b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 153b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 154b0104773SPascal Brand case TEE_ALG_DSA_SHA1: 155218d9055SCedric Chaumont case TEE_ALG_DSA_SHA224: 156218d9055SCedric Chaumont case TEE_ALG_DSA_SHA256: 1571220586eSCedric Chaumont case TEE_ALG_ECDSA_P192: 1581220586eSCedric Chaumont case TEE_ALG_ECDSA_P224: 1591220586eSCedric Chaumont case TEE_ALG_ECDSA_P256: 1601220586eSCedric Chaumont case TEE_ALG_ECDSA_P384: 1611220586eSCedric Chaumont case TEE_ALG_ECDSA_P521: 162b0104773SPascal Brand if (mode == TEE_MODE_SIGN) { 163b0104773SPascal Brand with_private_key = true; 164b0104773SPascal Brand req_key_usage = TEE_USAGE_SIGN; 165b0104773SPascal Brand } else if (mode == TEE_MODE_VERIFY) { 166b0104773SPascal Brand req_key_usage = TEE_USAGE_VERIFY; 167b0104773SPascal Brand } else { 168b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 169b0104773SPascal Brand } 170b0104773SPascal Brand break; 171b0104773SPascal Brand 172b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_V1_5: 173b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: 174b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: 175b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: 176b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: 177b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: 178b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 179b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 180b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 181b0104773SPascal Brand with_private_key = true; 182b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 183b0104773SPascal Brand } else { 184b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 185b0104773SPascal Brand } 186b0104773SPascal Brand break; 187b0104773SPascal Brand 188b0104773SPascal Brand case TEE_ALG_RSA_NOPAD: 189b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 190b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY; 191b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 192b0104773SPascal Brand with_private_key = true; 193b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN; 194b0104773SPascal Brand } else { 195b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 196b0104773SPascal Brand } 197b0104773SPascal Brand break; 198b0104773SPascal Brand 199b0104773SPascal Brand case TEE_ALG_DH_DERIVE_SHARED_SECRET: 2001220586eSCedric Chaumont case TEE_ALG_ECDH_P192: 2011220586eSCedric Chaumont case TEE_ALG_ECDH_P224: 2021220586eSCedric Chaumont case TEE_ALG_ECDH_P256: 2031220586eSCedric Chaumont case TEE_ALG_ECDH_P384: 2041220586eSCedric Chaumont case TEE_ALG_ECDH_P521: 205cdb198a7SJerome Forissier case TEE_ALG_HKDF_MD5_DERIVE_KEY: 206cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA1_DERIVE_KEY: 207cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA224_DERIVE_KEY: 208cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA256_DERIVE_KEY: 209cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA384_DERIVE_KEY: 210cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA512_DERIVE_KEY: 2118854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY: 2128854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY: 2138854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY: 2148854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY: 2158854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY: 2160f2293b7SJerome Forissier case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY: 217b0104773SPascal Brand if (mode != TEE_MODE_DERIVE) 218b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 219b0104773SPascal Brand with_private_key = true; 220b0104773SPascal Brand req_key_usage = TEE_USAGE_DERIVE; 221b0104773SPascal Brand break; 222b0104773SPascal Brand 223b0104773SPascal Brand case TEE_ALG_MD5: 224b0104773SPascal Brand case TEE_ALG_SHA1: 225b0104773SPascal Brand case TEE_ALG_SHA224: 226b0104773SPascal Brand case TEE_ALG_SHA256: 227b0104773SPascal Brand case TEE_ALG_SHA384: 228b0104773SPascal Brand case TEE_ALG_SHA512: 229b0104773SPascal Brand if (mode != TEE_MODE_DIGEST) 230b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 23105304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 232b0104773SPascal Brand handle_state |= TEE_HANDLE_FLAG_KEY_SET; 233b0104773SPascal Brand req_key_usage = 0; 234b0104773SPascal Brand break; 235b0104773SPascal Brand 236b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_NOPAD: 237b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_NOPAD: 238b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_PKCS5: 239b0104773SPascal Brand case TEE_ALG_AES_CMAC: 240b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_PKCS5: 241b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_NOPAD: 242b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_PKCS5: 243b0104773SPascal Brand case TEE_ALG_HMAC_MD5: 244b0104773SPascal Brand case TEE_ALG_HMAC_SHA1: 245b0104773SPascal Brand case TEE_ALG_HMAC_SHA224: 246b0104773SPascal Brand case TEE_ALG_HMAC_SHA256: 247b0104773SPascal Brand case TEE_ALG_HMAC_SHA384: 248b0104773SPascal Brand case TEE_ALG_HMAC_SHA512: 249b0104773SPascal Brand if (mode != TEE_MODE_MAC) 250b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 251b0104773SPascal Brand req_key_usage = TEE_USAGE_MAC; 252b0104773SPascal Brand break; 253b0104773SPascal Brand 254b0104773SPascal Brand default: 255b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 256b0104773SPascal Brand } 257b0104773SPascal Brand 258b66f219bSJens Wiklander op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO); 2599b52c538SCedric Chaumont if (!op) 260b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY; 261b0104773SPascal Brand 262b0104773SPascal Brand op->info.algorithm = algorithm; 263b0104773SPascal Brand op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); 2646a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1 2656a2e0a9fSGabor Szekely if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5) 2666a2e0a9fSGabor Szekely op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE; 2676a2e0a9fSGabor Szekely #endif 268b0104773SPascal Brand op->info.mode = mode; 269b0104773SPascal Brand op->info.maxKeySize = maxKeySize; 270b0104773SPascal Brand op->info.requiredKeyUsage = req_key_usage; 271b0104773SPascal Brand op->info.handleState = handle_state; 272b0104773SPascal Brand 273b0104773SPascal Brand if (block_size > 1) { 274b0104773SPascal Brand size_t buffer_size = block_size; 275b0104773SPascal Brand 276b0104773SPascal Brand if (buffer_two_blocks) 277b0104773SPascal Brand buffer_size *= 2; 278b0104773SPascal Brand 2799b52c538SCedric Chaumont op->buffer = TEE_Malloc(buffer_size, 2809b52c538SCedric Chaumont TEE_USER_MEM_HINT_NO_FILL_ZERO); 281b0104773SPascal Brand if (op->buffer == NULL) { 282b0104773SPascal Brand res = TEE_ERROR_OUT_OF_MEMORY; 283b66f219bSJens Wiklander goto out; 284b0104773SPascal Brand } 285b0104773SPascal Brand } 286b0104773SPascal Brand op->block_size = block_size; 287b0104773SPascal Brand op->buffer_two_blocks = buffer_two_blocks; 288b0104773SPascal Brand 289b0104773SPascal Brand if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { 290b0104773SPascal Brand uint32_t mks = maxKeySize; 291b0104773SPascal Brand TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, 292b0104773SPascal Brand with_private_key); 293b0104773SPascal Brand 294b0104773SPascal Brand /* 295b0104773SPascal Brand * If two keys are expected the max key size is the sum of 296b0104773SPascal Brand * the size of both keys. 297b0104773SPascal Brand */ 298b0104773SPascal Brand if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) 299b0104773SPascal Brand mks /= 2; 300b0104773SPascal Brand 301b0104773SPascal Brand res = TEE_AllocateTransientObject(key_type, mks, &op->key1); 302b0104773SPascal Brand if (res != TEE_SUCCESS) 303b66f219bSJens Wiklander goto out; 304b0104773SPascal Brand 30505304565SCedric Chaumont if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { 3069b52c538SCedric Chaumont res = TEE_AllocateTransientObject(key_type, mks, 307b0104773SPascal Brand &op->key2); 308b0104773SPascal Brand if (res != TEE_SUCCESS) 309b66f219bSJens Wiklander goto out; 310b0104773SPascal Brand } 311b0104773SPascal Brand } 312b0104773SPascal Brand 313e86f1266SJens Wiklander res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, 314e86f1266SJens Wiklander (unsigned long)op->key2, &op->state); 315b66f219bSJens Wiklander if (res != TEE_SUCCESS) 316b66f219bSJens Wiklander goto out; 317b0104773SPascal Brand 31805304565SCedric Chaumont /* 31905304565SCedric Chaumont * Initialize digest operations 32005304565SCedric Chaumont * Other multi-stage operations initialized w/ TEE_xxxInit functions 32105304565SCedric Chaumont * Non-applicable on asymmetric operations 32205304565SCedric Chaumont */ 32305304565SCedric Chaumont if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { 32405304565SCedric Chaumont res = utee_hash_init(op->state, NULL, 0); 32505304565SCedric Chaumont if (res != TEE_SUCCESS) 326b66f219bSJens Wiklander goto out; 32705304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 32805304565SCedric Chaumont op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 32905304565SCedric Chaumont } 33005304565SCedric Chaumont 331642a1607SCedric Chaumont op->operationState = TEE_OPERATION_STATE_INITIAL; 332642a1607SCedric Chaumont 333b0104773SPascal Brand *operation = op; 334b0104773SPascal Brand 335b66f219bSJens Wiklander out: 336b66f219bSJens Wiklander if (res != TEE_SUCCESS) { 337b66f219bSJens Wiklander if (res != TEE_ERROR_OUT_OF_MEMORY && 3389b52c538SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 339b36311adSJerome Forissier TEE_Panic(res); 340b66f219bSJens Wiklander if (op) { 341b66f219bSJens Wiklander if (op->state) { 342b66f219bSJens Wiklander TEE_FreeOperation(op); 343b66f219bSJens Wiklander } else { 344b66f219bSJens Wiklander TEE_Free(op->buffer); 345b66f219bSJens Wiklander TEE_FreeTransientObject(op->key1); 346b66f219bSJens Wiklander TEE_FreeTransientObject(op->key2); 347b66f219bSJens Wiklander TEE_Free(op); 348b66f219bSJens Wiklander } 349b66f219bSJens Wiklander } 350b66f219bSJens Wiklander } 351b66f219bSJens Wiklander 352b0104773SPascal Brand return res; 353b0104773SPascal Brand } 354b0104773SPascal Brand 355b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation) 356b0104773SPascal Brand { 357e889e80bSCedric Chaumont TEE_Result res; 358e889e80bSCedric Chaumont 359e889e80bSCedric Chaumont if (operation == TEE_HANDLE_NULL) 360e889e80bSCedric Chaumont TEE_Panic(0); 361e889e80bSCedric Chaumont 362b0104773SPascal Brand /* 363b0104773SPascal Brand * Note that keys should not be freed here, since they are 364b0104773SPascal Brand * claimed by the operation they will be freed by 365b0104773SPascal Brand * utee_cryp_state_free(). 366b0104773SPascal Brand */ 367e889e80bSCedric Chaumont res = utee_cryp_state_free(operation->state); 368e889e80bSCedric Chaumont if (res != TEE_SUCCESS) 369b36311adSJerome Forissier TEE_Panic(res); 370e889e80bSCedric Chaumont 371b0104773SPascal Brand TEE_Free(operation->buffer); 372b0104773SPascal Brand TEE_Free(operation); 373b0104773SPascal Brand } 374b0104773SPascal Brand 375b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation, 376b0104773SPascal Brand TEE_OperationInfo *operationInfo) 377b0104773SPascal Brand { 378b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 379b0104773SPascal Brand TEE_Panic(0); 380b0104773SPascal Brand 38105304565SCedric Chaumont if (!operationInfo) 382b0104773SPascal Brand TEE_Panic(0); 383b0104773SPascal Brand 384b0104773SPascal Brand *operationInfo = operation->info; 385b0104773SPascal Brand } 386b0104773SPascal Brand 38705304565SCedric Chaumont TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, 38805304565SCedric Chaumont TEE_OperationInfoMultiple *operationInfoMultiple, 38905304565SCedric Chaumont uint32_t *operationSize) 39005304565SCedric Chaumont { 39105304565SCedric Chaumont TEE_Result res = TEE_SUCCESS; 39205304565SCedric Chaumont TEE_ObjectInfo key_info1; 39305304565SCedric Chaumont TEE_ObjectInfo key_info2; 39405304565SCedric Chaumont uint32_t num_of_keys; 39505304565SCedric Chaumont size_t n; 39605304565SCedric Chaumont 39705304565SCedric Chaumont if (operation == TEE_HANDLE_NULL) { 39805304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 39905304565SCedric Chaumont goto out; 40005304565SCedric Chaumont } 40105304565SCedric Chaumont 40205304565SCedric Chaumont if (!operationInfoMultiple) { 40305304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40405304565SCedric Chaumont goto out; 40505304565SCedric Chaumont } 40605304565SCedric Chaumont 40705304565SCedric Chaumont if (!operationSize) { 40805304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40905304565SCedric Chaumont goto out; 41005304565SCedric Chaumont } 41105304565SCedric Chaumont 41205304565SCedric Chaumont num_of_keys = (*operationSize-sizeof(TEE_OperationInfoMultiple))/ 41305304565SCedric Chaumont sizeof(TEE_OperationInfoKey); 41405304565SCedric Chaumont 41505304565SCedric Chaumont if (num_of_keys > 2) { 41605304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 41705304565SCedric Chaumont goto out; 41805304565SCedric Chaumont } 41905304565SCedric Chaumont 42005304565SCedric Chaumont /* Two keys flag (TEE_ALG_AES_XTS only) */ 42105304565SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 42205304565SCedric Chaumont 0 && 42305304565SCedric Chaumont (num_of_keys != 2)) { 42405304565SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 42505304565SCedric Chaumont goto out; 42605304565SCedric Chaumont } 42705304565SCedric Chaumont 42805304565SCedric Chaumont /* Clear */ 42905304565SCedric Chaumont for (n = 0; n < num_of_keys; n++) { 43005304565SCedric Chaumont operationInfoMultiple->keyInformation[n].keySize = 0; 43105304565SCedric Chaumont operationInfoMultiple->keyInformation[n].requiredKeyUsage = 0; 43205304565SCedric Chaumont } 43305304565SCedric Chaumont 43405304565SCedric Chaumont if (num_of_keys == 2) { 43505304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key2, &key_info2); 43605304565SCedric Chaumont /* Key2 is not a valid handle */ 43705304565SCedric Chaumont if (res != TEE_SUCCESS) 43805304565SCedric Chaumont goto out; 43905304565SCedric Chaumont 44005304565SCedric Chaumont operationInfoMultiple->keyInformation[1].keySize = 44105304565SCedric Chaumont key_info2.keySize; 44205304565SCedric Chaumont operationInfoMultiple->keyInformation[1].requiredKeyUsage = 44305304565SCedric Chaumont operation->info.requiredKeyUsage; 44405304565SCedric Chaumont } 44505304565SCedric Chaumont 44605304565SCedric Chaumont if (num_of_keys >= 1) { 44705304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key1, &key_info1); 44805304565SCedric Chaumont /* Key1 is not a valid handle */ 44905304565SCedric Chaumont if (res != TEE_SUCCESS) { 45005304565SCedric Chaumont if (num_of_keys == 2) { 45105304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 45205304565SCedric Chaumont keySize = 0; 45305304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 45405304565SCedric Chaumont requiredKeyUsage = 0; 45505304565SCedric Chaumont } 45605304565SCedric Chaumont goto out; 45705304565SCedric Chaumont } 45805304565SCedric Chaumont 45905304565SCedric Chaumont operationInfoMultiple->keyInformation[0].keySize = 46005304565SCedric Chaumont key_info1.keySize; 46105304565SCedric Chaumont operationInfoMultiple->keyInformation[0].requiredKeyUsage = 46205304565SCedric Chaumont operation->info.requiredKeyUsage; 46305304565SCedric Chaumont } 46405304565SCedric Chaumont 46505304565SCedric Chaumont /* No key */ 46605304565SCedric Chaumont operationInfoMultiple->algorithm = operation->info.algorithm; 46705304565SCedric Chaumont operationInfoMultiple->operationClass = operation->info.operationClass; 46805304565SCedric Chaumont operationInfoMultiple->mode = operation->info.mode; 46905304565SCedric Chaumont operationInfoMultiple->digestLength = operation->info.digestLength; 47005304565SCedric Chaumont operationInfoMultiple->maxKeySize = operation->info.maxKeySize; 47105304565SCedric Chaumont operationInfoMultiple->handleState = operation->info.handleState; 47205304565SCedric Chaumont operationInfoMultiple->operationState = operation->operationState; 47305304565SCedric Chaumont operationInfoMultiple->numberOfKeys = num_of_keys; 47405304565SCedric Chaumont 47505304565SCedric Chaumont out: 47605304565SCedric Chaumont if (res != TEE_SUCCESS && 47705304565SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 478b36311adSJerome Forissier TEE_Panic(res); 47905304565SCedric Chaumont 48005304565SCedric Chaumont return res; 48105304565SCedric Chaumont } 48205304565SCedric Chaumont 483b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation) 484b0104773SPascal Brand { 485b0104773SPascal Brand TEE_Result res; 486b0104773SPascal Brand 487b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 488b0104773SPascal Brand TEE_Panic(0); 489bf80076aSCedric Chaumont 490642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) 491bf80076aSCedric Chaumont TEE_Panic(0); 492bf80076aSCedric Chaumont 493642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 494642a1607SCedric Chaumont 495b0104773SPascal Brand if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 496b0104773SPascal Brand res = utee_hash_init(operation->state, NULL, 0); 497b0104773SPascal Brand if (res != TEE_SUCCESS) 498b0104773SPascal Brand TEE_Panic(res); 49905304565SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 50005304565SCedric Chaumont } else { 501b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 502b0104773SPascal Brand } 50305304565SCedric Chaumont } 504b0104773SPascal Brand 505b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, 506b0104773SPascal Brand TEE_ObjectHandle key) 507b0104773SPascal Brand { 5087583c59eSCedric Chaumont TEE_Result res; 509b0104773SPascal Brand uint32_t key_size = 0; 510b0104773SPascal Brand TEE_ObjectInfo key_info; 511b0104773SPascal Brand 512a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 513a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 514a57c1e2eSCedric Chaumont goto out; 515a57c1e2eSCedric Chaumont } 516a57c1e2eSCedric Chaumont 517642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 518642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 519642a1607SCedric Chaumont goto out; 520642a1607SCedric Chaumont } 521642a1607SCedric Chaumont 522a57c1e2eSCedric Chaumont if (key == TEE_HANDLE_NULL) { 523a57c1e2eSCedric Chaumont /* Operation key cleared */ 524a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 525a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 526a57c1e2eSCedric Chaumont goto out; 527a57c1e2eSCedric Chaumont } 528a57c1e2eSCedric Chaumont 529a57c1e2eSCedric Chaumont /* No key for digest operation */ 530a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 531a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 532a57c1e2eSCedric Chaumont goto out; 533a57c1e2eSCedric Chaumont } 534a57c1e2eSCedric Chaumont 535a57c1e2eSCedric Chaumont /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ 536a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 537a57c1e2eSCedric Chaumont 0) { 538a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 539a57c1e2eSCedric Chaumont goto out; 540a57c1e2eSCedric Chaumont } 541a57c1e2eSCedric Chaumont 5427583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key, &key_info); 543a57c1e2eSCedric Chaumont /* Key is not a valid handle */ 5447583c59eSCedric Chaumont if (res != TEE_SUCCESS) 545a57c1e2eSCedric Chaumont goto out; 5467583c59eSCedric Chaumont 547b0104773SPascal Brand /* Supplied key has to meet required usage */ 548b0104773SPascal Brand if ((key_info.objectUsage & operation->info.requiredKeyUsage) != 549b0104773SPascal Brand operation->info.requiredKeyUsage) { 550a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 551a57c1e2eSCedric Chaumont goto out; 552b0104773SPascal Brand } 553b0104773SPascal Brand 554a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info.keySize) { 555a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 556a57c1e2eSCedric Chaumont goto out; 557a57c1e2eSCedric Chaumont } 558b0104773SPascal Brand 5597583c59eSCedric Chaumont key_size = key_info.keySize; 560b0104773SPascal Brand 561b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 562b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 563b0104773SPascal Brand 5647583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key); 5657583c59eSCedric Chaumont if (res != TEE_SUCCESS) 566a57c1e2eSCedric Chaumont goto out; 5677583c59eSCedric Chaumont 568b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 569b0104773SPascal Brand 570b0104773SPascal Brand operation->info.keySize = key_size; 571b0104773SPascal Brand 5727583c59eSCedric Chaumont out: 573a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 574a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 575a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 576b36311adSJerome Forissier TEE_Panic(res); 577a57c1e2eSCedric Chaumont 578a57c1e2eSCedric Chaumont return res; 579b0104773SPascal Brand } 580b0104773SPascal Brand 581b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, 582b0104773SPascal Brand TEE_ObjectHandle key1, TEE_ObjectHandle key2) 583b0104773SPascal Brand { 5847583c59eSCedric Chaumont TEE_Result res; 585b0104773SPascal Brand uint32_t key_size = 0; 586b0104773SPascal Brand TEE_ObjectInfo key_info1; 587b0104773SPascal Brand TEE_ObjectInfo key_info2; 588b0104773SPascal Brand 589a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 590a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 591a57c1e2eSCedric Chaumont goto out; 592a57c1e2eSCedric Chaumont } 593a57c1e2eSCedric Chaumont 594642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 595642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 596642a1607SCedric Chaumont goto out; 597642a1607SCedric Chaumont } 598642a1607SCedric Chaumont 599a57c1e2eSCedric Chaumont /* 600a57c1e2eSCedric Chaumont * Key1/Key2 and/or are not initialized and 601a57c1e2eSCedric Chaumont * Either both keys are NULL or both are not NULL 602a57c1e2eSCedric Chaumont */ 603a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL || key2 == TEE_HANDLE_NULL) { 604a57c1e2eSCedric Chaumont /* Clear operation key1 (if needed) */ 605a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL) 606a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 607a57c1e2eSCedric Chaumont /* Clear operation key2 (if needed) */ 608a57c1e2eSCedric Chaumont if (key2 == TEE_HANDLE_NULL) 609a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key2); 610a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 611a57c1e2eSCedric Chaumont goto out; 612a57c1e2eSCedric Chaumont } 613a57c1e2eSCedric Chaumont 614a57c1e2eSCedric Chaumont /* No key for digest operation */ 615a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 616a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 617a57c1e2eSCedric Chaumont goto out; 618a57c1e2eSCedric Chaumont } 619a57c1e2eSCedric Chaumont 620a57c1e2eSCedric Chaumont /* Two keys flag expected (TEE_ALG_AES_XTS only) */ 621a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 622a57c1e2eSCedric Chaumont 0) { 623a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 624a57c1e2eSCedric Chaumont goto out; 625a57c1e2eSCedric Chaumont } 626a57c1e2eSCedric Chaumont 6277583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key1, &key_info1); 628a57c1e2eSCedric Chaumont /* Key1 is not a valid handle */ 6297583c59eSCedric Chaumont if (res != TEE_SUCCESS) 630a57c1e2eSCedric Chaumont goto out; 6317583c59eSCedric Chaumont 632b0104773SPascal Brand /* Supplied key has to meet required usage */ 633b0104773SPascal Brand if ((key_info1.objectUsage & operation->info. 634b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 635a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 636a57c1e2eSCedric Chaumont goto out; 637b0104773SPascal Brand } 638b0104773SPascal Brand 6397583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key2, &key_info2); 640a57c1e2eSCedric Chaumont /* Key2 is not a valid handle */ 6417583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6427583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6437583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 644a57c1e2eSCedric Chaumont goto out; 6457583c59eSCedric Chaumont } 6467583c59eSCedric Chaumont 647b0104773SPascal Brand /* Supplied key has to meet required usage */ 648b0104773SPascal Brand if ((key_info2.objectUsage & operation->info. 649b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 650a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 651a57c1e2eSCedric Chaumont goto out; 652b0104773SPascal Brand } 653b0104773SPascal Brand 654b0104773SPascal Brand /* 655b0104773SPascal Brand * AES-XTS (the only multi key algorithm supported, requires the 656b0104773SPascal Brand * keys to be of equal size. 657b0104773SPascal Brand */ 658b0104773SPascal Brand if (operation->info.algorithm == TEE_ALG_AES_XTS && 659a57c1e2eSCedric Chaumont key_info1.keySize != key_info2.keySize) { 660a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 661a57c1e2eSCedric Chaumont goto out; 662b0104773SPascal Brand 663a57c1e2eSCedric Chaumont } 664a57c1e2eSCedric Chaumont 665a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info1.keySize) { 666a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 667a57c1e2eSCedric Chaumont goto out; 668a57c1e2eSCedric Chaumont } 669b0104773SPascal Brand 670b0104773SPascal Brand /* 671b0104773SPascal Brand * Odd that only the size of one key should be reported while 672b0104773SPascal Brand * size of two key are used when allocating the operation. 673b0104773SPascal Brand */ 6747583c59eSCedric Chaumont key_size = key_info1.keySize; 675b0104773SPascal Brand 676b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 677b0104773SPascal Brand TEE_ResetTransientObject(operation->key2); 678b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 679b0104773SPascal Brand 6807583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key1); 6817583c59eSCedric Chaumont if (res != TEE_SUCCESS) 682a57c1e2eSCedric Chaumont goto out; 6837583c59eSCedric Chaumont 6847583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key2, key2); 6857583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6867583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6877583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 688a57c1e2eSCedric Chaumont goto out; 6897583c59eSCedric Chaumont } 6907583c59eSCedric Chaumont 691b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 692b0104773SPascal Brand 693b0104773SPascal Brand operation->info.keySize = key_size; 694b0104773SPascal Brand 6957583c59eSCedric Chaumont out: 696a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 697a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 698a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT_2 && 699a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE && 700a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) 701b36311adSJerome Forissier TEE_Panic(res); 702a57c1e2eSCedric Chaumont 703a57c1e2eSCedric Chaumont return res; 704b0104773SPascal Brand } 705b0104773SPascal Brand 706b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) 707b0104773SPascal Brand { 708b0104773SPascal Brand TEE_Result res; 709b0104773SPascal Brand 710b0104773SPascal Brand if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) 711b0104773SPascal Brand TEE_Panic(0); 712b0104773SPascal Brand if (dst_op->info.algorithm != src_op->info.algorithm) 713b0104773SPascal Brand TEE_Panic(0); 714b0104773SPascal Brand if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { 715b0104773SPascal Brand TEE_ObjectHandle key1 = TEE_HANDLE_NULL; 716b0104773SPascal Brand TEE_ObjectHandle key2 = TEE_HANDLE_NULL; 717b0104773SPascal Brand 718b0104773SPascal Brand if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { 719b0104773SPascal Brand key1 = src_op->key1; 720b0104773SPascal Brand key2 = src_op->key2; 721b0104773SPascal Brand } 722b0104773SPascal Brand 723b0104773SPascal Brand if ((src_op->info.handleState & 724b0104773SPascal Brand TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { 725b0104773SPascal Brand TEE_SetOperationKey(dst_op, key1); 726b0104773SPascal Brand } else { 727b0104773SPascal Brand TEE_SetOperationKey2(dst_op, key1, key2); 728b0104773SPascal Brand } 729b0104773SPascal Brand } 730b0104773SPascal Brand dst_op->info.handleState = src_op->info.handleState; 731b0104773SPascal Brand dst_op->info.keySize = src_op->info.keySize; 732642a1607SCedric Chaumont dst_op->operationState = src_op->operationState; 733b0104773SPascal Brand 734b0104773SPascal Brand if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || 735b0104773SPascal Brand dst_op->block_size != src_op->block_size) 736b0104773SPascal Brand TEE_Panic(0); 737b0104773SPascal Brand 738b0104773SPascal Brand if (dst_op->buffer != NULL) { 739b0104773SPascal Brand if (src_op->buffer == NULL) 740b0104773SPascal Brand TEE_Panic(0); 741b0104773SPascal Brand 742b0104773SPascal Brand memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs); 743b0104773SPascal Brand dst_op->buffer_offs = src_op->buffer_offs; 744b0104773SPascal Brand } else if (src_op->buffer != NULL) { 745b0104773SPascal Brand TEE_Panic(0); 746b0104773SPascal Brand } 747b0104773SPascal Brand 748b0104773SPascal Brand res = utee_cryp_state_copy(dst_op->state, src_op->state); 749b0104773SPascal Brand if (res != TEE_SUCCESS) 750b0104773SPascal Brand TEE_Panic(res); 751b0104773SPascal Brand } 752b0104773SPascal Brand 753b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */ 754b0104773SPascal Brand 7558f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV, 7566d15db08SJerome Forissier uint32_t IVLen) 7576d15db08SJerome Forissier { 7586d15db08SJerome Forissier TEE_Result res; 7596d15db08SJerome Forissier 7606d15db08SJerome Forissier /* 7616d15db08SJerome Forissier * Note : IV and IVLen are never used in current implementation 7626d15db08SJerome Forissier * This is why coherent values of IV and IVLen are not checked 7636d15db08SJerome Forissier */ 7646d15db08SJerome Forissier res = utee_hash_init(operation->state, IV, IVLen); 7656d15db08SJerome Forissier if (res != TEE_SUCCESS) 7666d15db08SJerome Forissier TEE_Panic(res); 7676d15db08SJerome Forissier operation->buffer_offs = 0; 7686d15db08SJerome Forissier operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 7696d15db08SJerome Forissier } 7706d15db08SJerome Forissier 771b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation, 7728f07fe6fSJerome Forissier const void *chunk, uint32_t chunkSize) 773b0104773SPascal Brand { 77473d6c3baSJoakim Bech TEE_Result res = TEE_ERROR_GENERIC; 775b0104773SPascal Brand 77673d6c3baSJoakim Bech if (operation == TEE_HANDLE_NULL || 77773d6c3baSJoakim Bech operation->info.operationClass != TEE_OPERATION_DIGEST) 778b0104773SPascal Brand TEE_Panic(0); 77973d6c3baSJoakim Bech 780642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 781642a1607SCedric Chaumont 782b0104773SPascal Brand res = utee_hash_update(operation->state, chunk, chunkSize); 783b0104773SPascal Brand if (res != TEE_SUCCESS) 784b0104773SPascal Brand TEE_Panic(res); 785b0104773SPascal Brand } 786b0104773SPascal Brand 7878f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, 78879a3c601SCedric Chaumont uint32_t chunkLen, void *hash, uint32_t *hashLen) 789b0104773SPascal Brand { 79087c2f6b6SCedric Chaumont TEE_Result res; 791e86f1266SJens Wiklander uint64_t hl; 79287c2f6b6SCedric Chaumont 79387c2f6b6SCedric Chaumont if ((operation == TEE_HANDLE_NULL) || 79487c2f6b6SCedric Chaumont (!chunk && chunkLen) || 79587c2f6b6SCedric Chaumont !hash || 79687c2f6b6SCedric Chaumont !hashLen || 79787c2f6b6SCedric Chaumont (operation->info.operationClass != TEE_OPERATION_DIGEST)) { 79887c2f6b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 79987c2f6b6SCedric Chaumont goto out; 80087c2f6b6SCedric Chaumont } 80187c2f6b6SCedric Chaumont 802e86f1266SJens Wiklander hl = *hashLen; 803e86f1266SJens Wiklander res = utee_hash_final(operation->state, chunk, chunkLen, hash, &hl); 804e86f1266SJens Wiklander *hashLen = hl; 8056d15db08SJerome Forissier if (res != TEE_SUCCESS) 8066d15db08SJerome Forissier goto out; 8076d15db08SJerome Forissier 8086d15db08SJerome Forissier /* Reset operation state */ 8096d15db08SJerome Forissier init_hash_operation(operation, NULL, 0); 81087c2f6b6SCedric Chaumont 811642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 812642a1607SCedric Chaumont 81387c2f6b6SCedric Chaumont out: 81487c2f6b6SCedric Chaumont if (res != TEE_SUCCESS && 81587c2f6b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 816b36311adSJerome Forissier TEE_Panic(res); 81773d6c3baSJoakim Bech 81887c2f6b6SCedric Chaumont return res; 819b0104773SPascal Brand } 820b0104773SPascal Brand 821b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */ 822b0104773SPascal Brand 8238f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, 8248f07fe6fSJerome Forissier uint32_t IVLen) 825b0104773SPascal Brand { 826b0104773SPascal Brand TEE_Result res; 827b0104773SPascal Brand 828b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 829b0104773SPascal Brand TEE_Panic(0); 830642a1607SCedric Chaumont 831b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_CIPHER) 832b0104773SPascal Brand TEE_Panic(0); 833642a1607SCedric Chaumont 834642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 835642a1607SCedric Chaumont !(operation->key1)) 836642a1607SCedric Chaumont TEE_Panic(0); 837642a1607SCedric Chaumont 838642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 839642a1607SCedric Chaumont TEE_ResetOperation(operation); 840642a1607SCedric Chaumont 841642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 842642a1607SCedric Chaumont 843b0104773SPascal Brand res = utee_cipher_init(operation->state, IV, IVLen); 844b0104773SPascal Brand if (res != TEE_SUCCESS) 845b0104773SPascal Brand TEE_Panic(res); 846642a1607SCedric Chaumont 847b0104773SPascal Brand operation->buffer_offs = 0; 848b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 849b0104773SPascal Brand } 850b0104773SPascal Brand 851b0104773SPascal Brand static TEE_Result tee_buffer_update( 852b0104773SPascal Brand TEE_OperationHandle op, 853e86f1266SJens Wiklander TEE_Result(*update_func)(unsigned long state, const void *src, 854e86f1266SJens Wiklander size_t slen, void *dst, uint64_t *dlen), 855b0104773SPascal Brand const void *src_data, size_t src_len, 856e86f1266SJens Wiklander void *dest_data, uint64_t *dest_len) 857b0104773SPascal Brand { 858b0104773SPascal Brand TEE_Result res; 859b0104773SPascal Brand const uint8_t *src = src_data; 860b0104773SPascal Brand size_t slen = src_len; 861b0104773SPascal Brand uint8_t *dst = dest_data; 862b0104773SPascal Brand size_t dlen = *dest_len; 863b0104773SPascal Brand size_t acc_dlen = 0; 864e86f1266SJens Wiklander uint64_t tmp_dlen; 865b0104773SPascal Brand size_t l; 866b0104773SPascal Brand size_t buffer_size; 867d3588802SPascal Brand size_t buffer_left; 868b0104773SPascal Brand 869090268f5SJens Wiklander if (!src) { 870090268f5SJens Wiklander if (slen) 871090268f5SJens Wiklander TEE_Panic(0); 872090268f5SJens Wiklander goto out; 873090268f5SJens Wiklander } 874090268f5SJens Wiklander 875d3588802SPascal Brand if (op->buffer_two_blocks) { 876b0104773SPascal Brand buffer_size = op->block_size * 2; 877d3588802SPascal Brand buffer_left = 1; 878d3588802SPascal Brand } else { 879b0104773SPascal Brand buffer_size = op->block_size; 880d3588802SPascal Brand buffer_left = 0; 881d3588802SPascal Brand } 882b0104773SPascal Brand 883b0104773SPascal Brand if (op->buffer_offs > 0) { 884b0104773SPascal Brand /* Fill up complete block */ 885b0104773SPascal Brand if (op->buffer_offs < op->block_size) 886b0104773SPascal Brand l = MIN(slen, op->block_size - op->buffer_offs); 887b0104773SPascal Brand else 888b0104773SPascal Brand l = MIN(slen, buffer_size - op->buffer_offs); 889b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, l); 890b0104773SPascal Brand op->buffer_offs += l; 891b0104773SPascal Brand src += l; 892b0104773SPascal Brand slen -= l; 893b0104773SPascal Brand if ((op->buffer_offs % op->block_size) != 0) 894b0104773SPascal Brand goto out; /* Nothing left to do */ 895b0104773SPascal Brand } 896b0104773SPascal Brand 897b0104773SPascal Brand /* If we can feed from buffer */ 898d3588802SPascal Brand if ((op->buffer_offs > 0) && 899d3588802SPascal Brand ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) { 9002ff3fdbbSPascal Brand l = ROUNDUP(op->buffer_offs + slen - buffer_size, 901b0104773SPascal Brand op->block_size); 902b0104773SPascal Brand l = MIN(op->buffer_offs, l); 903b0104773SPascal Brand tmp_dlen = dlen; 904b0104773SPascal Brand res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); 905b0104773SPascal Brand if (res != TEE_SUCCESS) 906b0104773SPascal Brand TEE_Panic(res); 907b0104773SPascal Brand dst += tmp_dlen; 908b0104773SPascal Brand dlen -= tmp_dlen; 909b0104773SPascal Brand acc_dlen += tmp_dlen; 910b0104773SPascal Brand op->buffer_offs -= l; 911b0104773SPascal Brand if (op->buffer_offs > 0) { 912b0104773SPascal Brand /* 913b0104773SPascal Brand * Slen is small enough to be contained in rest buffer. 914b0104773SPascal Brand */ 915b0104773SPascal Brand memcpy(op->buffer, op->buffer + l, buffer_size - l); 916b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 917b0104773SPascal Brand op->buffer_offs += slen; 918b0104773SPascal Brand goto out; /* Nothing left to do */ 919b0104773SPascal Brand } 920b0104773SPascal Brand } 921b0104773SPascal Brand 922d3588802SPascal Brand if (slen >= (buffer_size + buffer_left)) { 923b0104773SPascal Brand /* Buffer is empty, feed as much as possible from src */ 924bf7a587fSJerome Forissier if (op->info.algorithm == TEE_ALG_AES_CTS) 925b1ecda78SJerome Forissier l = ROUNDUP(slen - buffer_size, op->block_size); 926bf7a587fSJerome Forissier else 927bf7a587fSJerome Forissier l = ROUNDUP(slen - buffer_size + 1, op->block_size); 928b0104773SPascal Brand 929b0104773SPascal Brand tmp_dlen = dlen; 930b0104773SPascal Brand res = update_func(op->state, src, l, dst, &tmp_dlen); 931b0104773SPascal Brand if (res != TEE_SUCCESS) 932b0104773SPascal Brand TEE_Panic(res); 933b0104773SPascal Brand src += l; 934b0104773SPascal Brand slen -= l; 935b0104773SPascal Brand dst += tmp_dlen; 936b0104773SPascal Brand dlen -= tmp_dlen; 937b0104773SPascal Brand acc_dlen += tmp_dlen; 938b0104773SPascal Brand } 939b0104773SPascal Brand 940b0104773SPascal Brand /* Slen is small enough to be contained in buffer. */ 941b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 942b0104773SPascal Brand op->buffer_offs += slen; 943b0104773SPascal Brand 944b0104773SPascal Brand out: 945b0104773SPascal Brand *dest_len = acc_dlen; 946b0104773SPascal Brand return TEE_SUCCESS; 947b0104773SPascal Brand } 948b0104773SPascal Brand 9498f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, 95079a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 951b0104773SPascal Brand { 952dea1f2b6SCedric Chaumont TEE_Result res; 953b0104773SPascal Brand size_t req_dlen; 954e86f1266SJens Wiklander uint64_t dl; 955b0104773SPascal Brand 956642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 957dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 958dea1f2b6SCedric Chaumont destLen == NULL || 959dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 960dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 961dea1f2b6SCedric Chaumont goto out; 962dea1f2b6SCedric Chaumont } 963dea1f2b6SCedric Chaumont 964642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 965dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 966dea1f2b6SCedric Chaumont goto out; 967dea1f2b6SCedric Chaumont } 968dea1f2b6SCedric Chaumont 969642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 970642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 971642a1607SCedric Chaumont goto out; 972642a1607SCedric Chaumont } 973642a1607SCedric Chaumont 974642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 975dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 976dea1f2b6SCedric Chaumont goto out; 977dea1f2b6SCedric Chaumont } 978b0104773SPascal Brand 979e32c5ddfSJerome Forissier if (!srcData && !srcLen) { 980090268f5SJens Wiklander *destLen = 0; 981e32c5ddfSJerome Forissier res = TEE_SUCCESS; 982e32c5ddfSJerome Forissier goto out; 983e32c5ddfSJerome Forissier } 984e32c5ddfSJerome Forissier 985b0104773SPascal Brand /* Calculate required dlen */ 98657aabac5SBogdan Liulko if (operation->block_size > 1) { 98757aabac5SBogdan Liulko req_dlen = ((operation->buffer_offs + srcLen) / 98857aabac5SBogdan Liulko operation->block_size) * operation->block_size; 98957aabac5SBogdan Liulko } else { 99057aabac5SBogdan Liulko req_dlen = srcLen; 99157aabac5SBogdan Liulko } 992642a1607SCedric Chaumont if (operation->buffer_two_blocks) { 993642a1607SCedric Chaumont if (req_dlen > operation->block_size * 2) 994642a1607SCedric Chaumont req_dlen -= operation->block_size * 2; 995b0104773SPascal Brand else 996b0104773SPascal Brand req_dlen = 0; 997b0104773SPascal Brand } 998b0104773SPascal Brand /* 999b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1000b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1001b0104773SPascal Brand * can't restore sync with this API. 1002b0104773SPascal Brand */ 1003b0104773SPascal Brand if (*destLen < req_dlen) { 1004b0104773SPascal Brand *destLen = req_dlen; 1005dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1006dea1f2b6SCedric Chaumont goto out; 1007b0104773SPascal Brand } 1008b0104773SPascal Brand 1009e86f1266SJens Wiklander dl = *destLen; 101057aabac5SBogdan Liulko if (operation->block_size > 1) { 101157aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, srcData, 101257aabac5SBogdan Liulko srcLen, destData, &dl); 101357aabac5SBogdan Liulko } else { 101457aabac5SBogdan Liulko if (srcLen > 0) { 101557aabac5SBogdan Liulko res = utee_cipher_update(operation->state, srcData, 101657aabac5SBogdan Liulko srcLen, destData, &dl); 101757aabac5SBogdan Liulko } else { 101857aabac5SBogdan Liulko res = TEE_SUCCESS; 101957aabac5SBogdan Liulko dl = 0; 102057aabac5SBogdan Liulko } 102157aabac5SBogdan Liulko } 1022e86f1266SJens Wiklander *destLen = dl; 1023b0104773SPascal Brand 1024dea1f2b6SCedric Chaumont out: 1025dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1026dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1027b36311adSJerome Forissier TEE_Panic(res); 1028dea1f2b6SCedric Chaumont 1029dea1f2b6SCedric Chaumont return res; 1030b0104773SPascal Brand } 1031b0104773SPascal Brand 1032642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, 10338f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 10348f07fe6fSJerome Forissier void *destData, uint32_t *destLen) 1035b0104773SPascal Brand { 1036b0104773SPascal Brand TEE_Result res; 1037b0104773SPascal Brand uint8_t *dst = destData; 1038b0104773SPascal Brand size_t acc_dlen = 0; 1039e86f1266SJens Wiklander uint64_t tmp_dlen; 1040b0104773SPascal Brand size_t req_dlen; 1041b0104773SPascal Brand 1042642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1043dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 1044dea1f2b6SCedric Chaumont destLen == NULL || 1045dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 1046dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1047dea1f2b6SCedric Chaumont goto out; 1048dea1f2b6SCedric Chaumont } 1049dea1f2b6SCedric Chaumont 1050642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 1051dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1052dea1f2b6SCedric Chaumont goto out; 1053dea1f2b6SCedric Chaumont } 1054dea1f2b6SCedric Chaumont 1055642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1056642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1057642a1607SCedric Chaumont goto out; 1058642a1607SCedric Chaumont } 1059642a1607SCedric Chaumont 1060642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1061dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1062dea1f2b6SCedric Chaumont goto out; 1063dea1f2b6SCedric Chaumont } 1064b0104773SPascal Brand 1065b0104773SPascal Brand /* 1066b0104773SPascal Brand * Check that the final block doesn't require padding for those 1067b0104773SPascal Brand * algorithms that requires client to supply padding. 1068b0104773SPascal Brand */ 1069642a1607SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || 1070642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || 1071642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || 1072642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || 1073642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || 1074*ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD || 1075*ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD || 1076*ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) { 1077642a1607SCedric Chaumont if (((operation->buffer_offs + srcLen) % operation->block_size) 1078642a1607SCedric Chaumont != 0) { 1079dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1080dea1f2b6SCedric Chaumont goto out; 1081dea1f2b6SCedric Chaumont } 1082b0104773SPascal Brand } 1083b0104773SPascal Brand 1084b0104773SPascal Brand /* 1085b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1086b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1087b0104773SPascal Brand * can't restore sync with this API. 1088b0104773SPascal Brand */ 108957aabac5SBogdan Liulko if (operation->block_size > 1) { 1090642a1607SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 109157aabac5SBogdan Liulko } else { 109257aabac5SBogdan Liulko req_dlen = srcLen; 109357aabac5SBogdan Liulko } 1094b0104773SPascal Brand if (*destLen < req_dlen) { 1095b0104773SPascal Brand *destLen = req_dlen; 1096dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1097dea1f2b6SCedric Chaumont goto out; 1098b0104773SPascal Brand } 1099b0104773SPascal Brand 1100b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 110157aabac5SBogdan Liulko if (operation->block_size > 1) { 110257aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, 110357aabac5SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1104dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS) 1105dea1f2b6SCedric Chaumont goto out; 1106dea1f2b6SCedric Chaumont 1107b0104773SPascal Brand dst += tmp_dlen; 1108b0104773SPascal Brand acc_dlen += tmp_dlen; 1109b0104773SPascal Brand 1110b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1111642a1607SCedric Chaumont res = utee_cipher_final(operation->state, operation->buffer, 1112642a1607SCedric Chaumont operation->buffer_offs, dst, &tmp_dlen); 111357aabac5SBogdan Liulko } else { 111457aabac5SBogdan Liulko res = utee_cipher_final(operation->state, srcData, 111557aabac5SBogdan Liulko srcLen, dst, &tmp_dlen); 111657aabac5SBogdan Liulko } 1117b0104773SPascal Brand if (res != TEE_SUCCESS) 1118dea1f2b6SCedric Chaumont goto out; 1119dea1f2b6SCedric Chaumont 1120b0104773SPascal Brand acc_dlen += tmp_dlen; 1121b0104773SPascal Brand *destLen = acc_dlen; 1122dea1f2b6SCedric Chaumont 1123642a1607SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1124642a1607SCedric Chaumont 1125642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1126642a1607SCedric Chaumont 1127dea1f2b6SCedric Chaumont out: 1128dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1129dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1130b36311adSJerome Forissier TEE_Panic(res); 1131dea1f2b6SCedric Chaumont 1132dea1f2b6SCedric Chaumont return res; 1133b0104773SPascal Brand } 1134b0104773SPascal Brand 1135b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */ 1136b0104773SPascal Brand 11378f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) 1138b0104773SPascal Brand { 1139b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 1140b0104773SPascal Brand TEE_Panic(0); 1141642a1607SCedric Chaumont 1142b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_MAC) 1143b0104773SPascal Brand TEE_Panic(0); 1144642a1607SCedric Chaumont 1145642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 1146642a1607SCedric Chaumont !(operation->key1)) 1147642a1607SCedric Chaumont TEE_Panic(0); 1148642a1607SCedric Chaumont 1149642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 1150642a1607SCedric Chaumont TEE_ResetOperation(operation); 1151642a1607SCedric Chaumont 1152642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1153642a1607SCedric Chaumont 11546d15db08SJerome Forissier init_hash_operation(operation, IV, IVLen); 1155b0104773SPascal Brand } 1156b0104773SPascal Brand 11578f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, 115828e0efc6SCedric Chaumont uint32_t chunkSize) 1159b0104773SPascal Brand { 1160b0104773SPascal Brand TEE_Result res; 1161b0104773SPascal Brand 116228e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) 1163b0104773SPascal Brand TEE_Panic(0); 1164642a1607SCedric Chaumont 116528e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) 1166b0104773SPascal Brand TEE_Panic(0); 1167642a1607SCedric Chaumont 116828e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1169b0104773SPascal Brand TEE_Panic(0); 1170b0104773SPascal Brand 1171642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) 1172642a1607SCedric Chaumont TEE_Panic(0); 1173642a1607SCedric Chaumont 117428e0efc6SCedric Chaumont res = utee_hash_update(operation->state, chunk, chunkSize); 1175b0104773SPascal Brand if (res != TEE_SUCCESS) 1176b0104773SPascal Brand TEE_Panic(res); 1177b0104773SPascal Brand } 1178b0104773SPascal Brand 117928e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, 11808f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 118179a3c601SCedric Chaumont void *mac, uint32_t *macLen) 1182b0104773SPascal Brand { 1183b0104773SPascal Brand TEE_Result res; 1184e86f1266SJens Wiklander uint64_t ml; 1185b0104773SPascal Brand 118628e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || 118728e0efc6SCedric Chaumont (message == NULL && messageLen != 0) || 118828e0efc6SCedric Chaumont mac == NULL || 118928e0efc6SCedric Chaumont macLen == NULL) { 119028e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 119128e0efc6SCedric Chaumont goto out; 119228e0efc6SCedric Chaumont } 1193b0104773SPascal Brand 119428e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 119528e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 119628e0efc6SCedric Chaumont goto out; 119728e0efc6SCedric Chaumont } 119828e0efc6SCedric Chaumont 119928e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 120028e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 120128e0efc6SCedric Chaumont goto out; 120228e0efc6SCedric Chaumont } 120328e0efc6SCedric Chaumont 1204642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1205642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1206642a1607SCedric Chaumont goto out; 1207642a1607SCedric Chaumont } 1208642a1607SCedric Chaumont 1209e86f1266SJens Wiklander ml = *macLen; 1210e86f1266SJens Wiklander res = utee_hash_final(operation->state, message, messageLen, mac, &ml); 1211e86f1266SJens Wiklander *macLen = ml; 121228e0efc6SCedric Chaumont if (res != TEE_SUCCESS) 121328e0efc6SCedric Chaumont goto out; 121428e0efc6SCedric Chaumont 121528e0efc6SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 121628e0efc6SCedric Chaumont 1217642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1218642a1607SCedric Chaumont 121928e0efc6SCedric Chaumont out: 122028e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 122128e0efc6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 122228e0efc6SCedric Chaumont TEE_Panic(res); 122328e0efc6SCedric Chaumont 1224b0104773SPascal Brand return res; 1225b0104773SPascal Brand } 1226b0104773SPascal Brand 1227b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, 12288f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 12298f07fe6fSJerome Forissier const void *mac, uint32_t macLen) 1230b0104773SPascal Brand { 1231b0104773SPascal Brand TEE_Result res; 1232b0104773SPascal Brand uint8_t computed_mac[TEE_MAX_HASH_SIZE]; 12337f74c64aSPascal Brand uint32_t computed_mac_size = TEE_MAX_HASH_SIZE; 1234b0104773SPascal Brand 123528e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 123628e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 123728e0efc6SCedric Chaumont goto out; 123828e0efc6SCedric Chaumont } 123928e0efc6SCedric Chaumont 124028e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 124128e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 124228e0efc6SCedric Chaumont goto out; 124328e0efc6SCedric Chaumont } 124428e0efc6SCedric Chaumont 1245642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1246642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1247642a1607SCedric Chaumont goto out; 1248642a1607SCedric Chaumont } 1249642a1607SCedric Chaumont 1250b0104773SPascal Brand res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, 1251b0104773SPascal Brand &computed_mac_size); 1252b0104773SPascal Brand if (res != TEE_SUCCESS) 125328e0efc6SCedric Chaumont goto out; 125428e0efc6SCedric Chaumont 125528e0efc6SCedric Chaumont if (computed_mac_size != macLen) { 125628e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 125728e0efc6SCedric Chaumont goto out; 125828e0efc6SCedric Chaumont } 125928e0efc6SCedric Chaumont 126048e10604SJerome Forissier if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) { 126128e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 126228e0efc6SCedric Chaumont goto out; 126328e0efc6SCedric Chaumont } 126428e0efc6SCedric Chaumont 1265642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1266642a1607SCedric Chaumont 126728e0efc6SCedric Chaumont out: 126828e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 126928e0efc6SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 127028e0efc6SCedric Chaumont TEE_Panic(res); 127128e0efc6SCedric Chaumont 1272b0104773SPascal Brand return res; 1273b0104773SPascal Brand } 1274b0104773SPascal Brand 1275b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */ 1276b0104773SPascal Brand 12778f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, 127879a3c601SCedric Chaumont uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, 1279b0104773SPascal Brand uint32_t payloadLen) 1280b0104773SPascal Brand { 1281b0104773SPascal Brand TEE_Result res; 1282b0104773SPascal Brand 1283b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || nonce == NULL) { 1284b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1285b5816c88SCedric Chaumont goto out; 1286b5816c88SCedric Chaumont } 1287b5816c88SCedric Chaumont 1288b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1289b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1290b5816c88SCedric Chaumont goto out; 1291b5816c88SCedric Chaumont } 1292b0104773SPascal Brand 1293642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 1294642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1295642a1607SCedric Chaumont goto out; 1296642a1607SCedric Chaumont } 1297642a1607SCedric Chaumont 1298b0104773SPascal Brand /* 1299b0104773SPascal Brand * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core 1300b0104773SPascal Brand * in the implementation. But AES-GCM spec doesn't specify the tag len 1301b0104773SPascal Brand * according to the same principle so we have to check here instead to 1302b0104773SPascal Brand * be GP compliant. 1303b0104773SPascal Brand */ 1304b5816c88SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_GCM) { 1305b0104773SPascal Brand /* 1306b0104773SPascal Brand * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 1307b0104773SPascal Brand */ 1308b5816c88SCedric Chaumont if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) { 1309b5816c88SCedric Chaumont res = TEE_ERROR_NOT_SUPPORTED; 1310b5816c88SCedric Chaumont goto out; 1311b5816c88SCedric Chaumont } 1312b0104773SPascal Brand } 1313b0104773SPascal Brand 1314b5816c88SCedric Chaumont res = utee_authenc_init(operation->state, nonce, nonceLen, 1315b5816c88SCedric Chaumont tagLen / 8, AADLen, payloadLen); 1316b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1317b5816c88SCedric Chaumont goto out; 1318b5816c88SCedric Chaumont 1319b5816c88SCedric Chaumont operation->ae_tag_len = tagLen / 8; 1320b5816c88SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 1321b5816c88SCedric Chaumont 1322b5816c88SCedric Chaumont out: 1323b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1324b5816c88SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 1325b0104773SPascal Brand TEE_Panic(res); 1326b5816c88SCedric Chaumont 1327b0104773SPascal Brand return res; 1328b0104773SPascal Brand } 1329b0104773SPascal Brand 13308f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, 133179a3c601SCedric Chaumont uint32_t AADdataLen) 1332b0104773SPascal Brand { 1333b0104773SPascal Brand TEE_Result res; 1334b0104773SPascal Brand 1335b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1336b5816c88SCedric Chaumont (AADdata == NULL && AADdataLen != 0)) 1337b0104773SPascal Brand TEE_Panic(0); 1338642a1607SCedric Chaumont 1339b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) 1340b0104773SPascal Brand TEE_Panic(0); 1341642a1607SCedric Chaumont 1342b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1343b0104773SPascal Brand TEE_Panic(0); 1344b0104773SPascal Brand 1345b5816c88SCedric Chaumont res = utee_authenc_update_aad(operation->state, AADdata, AADdataLen); 1346642a1607SCedric Chaumont 1347642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1348642a1607SCedric Chaumont 1349b0104773SPascal Brand if (res != TEE_SUCCESS) 1350b0104773SPascal Brand TEE_Panic(res); 1351b0104773SPascal Brand } 1352b0104773SPascal Brand 13538f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, 135479a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 1355b0104773SPascal Brand { 1356b5816c88SCedric Chaumont TEE_Result res; 1357b0104773SPascal Brand size_t req_dlen; 1358e86f1266SJens Wiklander uint64_t dl; 1359b0104773SPascal Brand 1360b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1361b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1362b5816c88SCedric Chaumont destLen == NULL || 1363b5816c88SCedric Chaumont (destData == NULL && *destLen != 0)) { 1364b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1365b5816c88SCedric Chaumont goto out; 1366b5816c88SCedric Chaumont } 1367b5816c88SCedric Chaumont 1368b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1369b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1370b5816c88SCedric Chaumont goto out; 1371b5816c88SCedric Chaumont } 1372b5816c88SCedric Chaumont 1373b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1374b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1375b5816c88SCedric Chaumont goto out; 1376b5816c88SCedric Chaumont } 1377b0104773SPascal Brand 1378827308b8SJerome Forissier if (!srcData && !srcLen) { 1379090268f5SJens Wiklander *destLen = 0; 1380827308b8SJerome Forissier res = TEE_SUCCESS; 1381827308b8SJerome Forissier goto out; 1382827308b8SJerome Forissier } 1383827308b8SJerome Forissier 1384b0104773SPascal Brand /* 1385b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1386b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1387b0104773SPascal Brand * can't restore sync with this API. 1388b0104773SPascal Brand */ 1389afc0c182SBogdan Liulko if (operation->block_size > 1) { 1390b5816c88SCedric Chaumont req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen, 1391b5816c88SCedric Chaumont operation->block_size); 1392afc0c182SBogdan Liulko } else { 1393afc0c182SBogdan Liulko req_dlen = srcLen; 1394afc0c182SBogdan Liulko } 1395afc0c182SBogdan Liulko 1396b0104773SPascal Brand if (*destLen < req_dlen) { 1397b0104773SPascal Brand *destLen = req_dlen; 1398b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1399b5816c88SCedric Chaumont goto out; 1400b0104773SPascal Brand } 1401b0104773SPascal Brand 1402e86f1266SJens Wiklander dl = *destLen; 1403afc0c182SBogdan Liulko if (operation->block_size > 1) { 1404afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1405afc0c182SBogdan Liulko srcData, srcLen, destData, &dl); 1406afc0c182SBogdan Liulko } else { 1407afc0c182SBogdan Liulko if (srcLen > 0) { 1408afc0c182SBogdan Liulko res = utee_authenc_update_payload(operation->state, 1409afc0c182SBogdan Liulko srcData, srcLen, 1410afc0c182SBogdan Liulko destData, &dl); 1411afc0c182SBogdan Liulko } else { 1412afc0c182SBogdan Liulko dl = 0; 1413afc0c182SBogdan Liulko res = TEE_SUCCESS; 1414afc0c182SBogdan Liulko } 1415afc0c182SBogdan Liulko } 1416afc0c182SBogdan Liulko if (res != TEE_SUCCESS) 1417afc0c182SBogdan Liulko goto out; 1418afc0c182SBogdan Liulko 1419e86f1266SJens Wiklander *destLen = dl; 1420b0104773SPascal Brand 1421642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1422642a1607SCedric Chaumont 1423b5816c88SCedric Chaumont out: 1424b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1425b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1426b5816c88SCedric Chaumont TEE_Panic(res); 1427b5816c88SCedric Chaumont 1428b5816c88SCedric Chaumont return res; 1429b0104773SPascal Brand } 1430b0104773SPascal Brand 1431b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, 14328f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 143379a3c601SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 143479a3c601SCedric Chaumont uint32_t *tagLen) 1435b0104773SPascal Brand { 1436b0104773SPascal Brand TEE_Result res; 1437b0104773SPascal Brand uint8_t *dst = destData; 1438b0104773SPascal Brand size_t acc_dlen = 0; 1439e86f1266SJens Wiklander uint64_t tmp_dlen; 1440b0104773SPascal Brand size_t req_dlen; 1441e86f1266SJens Wiklander uint64_t tl; 1442b0104773SPascal Brand 1443b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1444b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1445b5816c88SCedric Chaumont destLen == NULL || 1446b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1447b5816c88SCedric Chaumont tag == NULL || tagLen == NULL) { 1448b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1449b5816c88SCedric Chaumont goto out; 1450b5816c88SCedric Chaumont } 1451b5816c88SCedric Chaumont 1452b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1453b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1454b5816c88SCedric Chaumont goto out; 1455b5816c88SCedric Chaumont } 1456b5816c88SCedric Chaumont 1457b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1458b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1459b5816c88SCedric Chaumont goto out; 1460b5816c88SCedric Chaumont } 1461b0104773SPascal Brand 1462b0104773SPascal Brand /* 1463b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1464b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1465b0104773SPascal Brand * can't restore sync with this API. 14662733280aSEtienne Carriere * 14672733280aSEtienne Carriere * Need to check this before update_payload since sync would be lost if 14682733280aSEtienne Carriere * we return short buffer after that. 1469b0104773SPascal Brand */ 14702733280aSEtienne Carriere res = TEE_ERROR_GENERIC; 14712733280aSEtienne Carriere 1472b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1473b0104773SPascal Brand if (*destLen < req_dlen) { 1474b0104773SPascal Brand *destLen = req_dlen; 1475b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1476b0104773SPascal Brand } 1477b0104773SPascal Brand 1478b5816c88SCedric Chaumont if (*tagLen < operation->ae_tag_len) { 1479b5816c88SCedric Chaumont *tagLen = operation->ae_tag_len; 1480b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1481b0104773SPascal Brand } 1482b0104773SPascal Brand 14832733280aSEtienne Carriere if (res == TEE_ERROR_SHORT_BUFFER) 14842733280aSEtienne Carriere goto out; 14852733280aSEtienne Carriere 1486afc0c182SBogdan Liulko tl = *tagLen; 1487b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1488afc0c182SBogdan Liulko if (operation->block_size > 1) { 1489afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1490afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1491b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1492b5816c88SCedric Chaumont goto out; 1493b5816c88SCedric Chaumont 1494b0104773SPascal Brand dst += tmp_dlen; 1495b0104773SPascal Brand acc_dlen += tmp_dlen; 1496b0104773SPascal Brand 1497b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1498afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, 1499afc0c182SBogdan Liulko operation->buffer, 1500afc0c182SBogdan Liulko operation->buffer_offs, dst, 1501afc0c182SBogdan Liulko &tmp_dlen, tag, &tl); 1502afc0c182SBogdan Liulko } else { 1503afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, srcData, 1504afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1505e86f1266SJens Wiklander tag, &tl); 1506afc0c182SBogdan Liulko } 1507e86f1266SJens Wiklander *tagLen = tl; 1508b0104773SPascal Brand if (res != TEE_SUCCESS) 1509b5816c88SCedric Chaumont goto out; 1510b0104773SPascal Brand 1511b5816c88SCedric Chaumont acc_dlen += tmp_dlen; 1512b0104773SPascal Brand *destLen = acc_dlen; 1513642a1607SCedric Chaumont 1514b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1515b5816c88SCedric Chaumont 1516642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1517642a1607SCedric Chaumont 1518b5816c88SCedric Chaumont out: 1519b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1520b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1521b5816c88SCedric Chaumont TEE_Panic(res); 1522b0104773SPascal Brand 1523b0104773SPascal Brand return res; 1524b0104773SPascal Brand } 1525b0104773SPascal Brand 1526b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, 15278f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 1528b5816c88SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 152979a3c601SCedric Chaumont uint32_t tagLen) 1530b0104773SPascal Brand { 1531b0104773SPascal Brand TEE_Result res; 1532b0104773SPascal Brand uint8_t *dst = destData; 1533b0104773SPascal Brand size_t acc_dlen = 0; 1534e86f1266SJens Wiklander uint64_t tmp_dlen; 1535b0104773SPascal Brand size_t req_dlen; 1536b0104773SPascal Brand 1537b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1538b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1539b5816c88SCedric Chaumont destLen == NULL || 1540b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1541b5816c88SCedric Chaumont (tag == NULL && tagLen != 0)) { 1542b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1543b5816c88SCedric Chaumont goto out; 1544b5816c88SCedric Chaumont } 1545b5816c88SCedric Chaumont 1546b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1547b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1548b5816c88SCedric Chaumont goto out; 1549b5816c88SCedric Chaumont } 1550b5816c88SCedric Chaumont 1551b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1552b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1553b5816c88SCedric Chaumont goto out; 1554b5816c88SCedric Chaumont } 1555b0104773SPascal Brand 1556b0104773SPascal Brand /* 1557b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1558b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1559b0104773SPascal Brand * can't restore sync with this API. 1560b0104773SPascal Brand */ 1561b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1562b0104773SPascal Brand if (*destLen < req_dlen) { 1563b0104773SPascal Brand *destLen = req_dlen; 1564b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1565b5816c88SCedric Chaumont goto out; 1566b0104773SPascal Brand } 1567b0104773SPascal Brand 1568b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1569afc0c182SBogdan Liulko if (operation->block_size > 1) { 1570afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1571afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1572b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1573b5816c88SCedric Chaumont goto out; 1574b5816c88SCedric Chaumont 1575b0104773SPascal Brand dst += tmp_dlen; 1576b0104773SPascal Brand acc_dlen += tmp_dlen; 1577b0104773SPascal Brand 1578b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1579afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, 1580afc0c182SBogdan Liulko operation->buffer, 1581afc0c182SBogdan Liulko operation->buffer_offs, dst, 1582afc0c182SBogdan Liulko &tmp_dlen, tag, tagLen); 1583afc0c182SBogdan Liulko } else { 1584afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, srcData, 1585afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1586b5816c88SCedric Chaumont tag, tagLen); 1587afc0c182SBogdan Liulko } 1588b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1589b5816c88SCedric Chaumont goto out; 1590b5816c88SCedric Chaumont 1591b0104773SPascal Brand /* Supplied tagLen should match what we initiated with */ 1592b5816c88SCedric Chaumont if (tagLen != operation->ae_tag_len) 1593b0104773SPascal Brand res = TEE_ERROR_MAC_INVALID; 1594b0104773SPascal Brand 1595b0104773SPascal Brand acc_dlen += tmp_dlen; 1596b0104773SPascal Brand *destLen = acc_dlen; 1597642a1607SCedric Chaumont 1598b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1599b5816c88SCedric Chaumont 1600642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1601642a1607SCedric Chaumont 1602b5816c88SCedric Chaumont out: 1603b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1604b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER && 1605b5816c88SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 1606b5816c88SCedric Chaumont TEE_Panic(res); 1607b0104773SPascal Brand 1608b0104773SPascal Brand return res; 1609b0104773SPascal Brand } 1610b0104773SPascal Brand 1611b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */ 1612b0104773SPascal Brand 161312e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, 16148f07fe6fSJerome Forissier const TEE_Attribute *params, 16158f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 161679a3c601SCedric Chaumont uint32_t srcLen, void *destData, 161779a3c601SCedric Chaumont uint32_t *destLen) 1618b0104773SPascal Brand { 1619b0104773SPascal Brand TEE_Result res; 1620e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1621e86f1266SJens Wiklander uint64_t dl; 1622b0104773SPascal Brand 162312e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1624b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1625b0104773SPascal Brand TEE_Panic(0); 162612e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1627b0104773SPascal Brand TEE_Panic(0); 162812e66b6fSCedric Chaumont if (!operation->key1) 1629b0104773SPascal Brand TEE_Panic(0); 163012e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 163112e66b6fSCedric Chaumont TEE_Panic(0); 163212e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_ENCRYPT) 1633b0104773SPascal Brand TEE_Panic(0); 1634b0104773SPascal Brand 1635e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1636e86f1266SJens Wiklander dl = *destLen; 1637e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1638e86f1266SJens Wiklander srcLen, destData, &dl); 1639e86f1266SJens Wiklander *destLen = dl; 164012e66b6fSCedric Chaumont 16418844ebfcSPascal Brand if (res != TEE_SUCCESS && 16428844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16438844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1644b0104773SPascal Brand TEE_Panic(res); 164512e66b6fSCedric Chaumont 1646b0104773SPascal Brand return res; 1647b0104773SPascal Brand } 1648b0104773SPascal Brand 164912e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, 16508f07fe6fSJerome Forissier const TEE_Attribute *params, 16518f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 165279a3c601SCedric Chaumont uint32_t srcLen, void *destData, 165379a3c601SCedric Chaumont uint32_t *destLen) 1654b0104773SPascal Brand { 1655b0104773SPascal Brand TEE_Result res; 1656e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1657e86f1266SJens Wiklander uint64_t dl; 1658b0104773SPascal Brand 165912e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1660b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1661b0104773SPascal Brand TEE_Panic(0); 166212e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1663b0104773SPascal Brand TEE_Panic(0); 166412e66b6fSCedric Chaumont if (!operation->key1) 1665b0104773SPascal Brand TEE_Panic(0); 166612e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 166712e66b6fSCedric Chaumont TEE_Panic(0); 166812e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_DECRYPT) 1669b0104773SPascal Brand TEE_Panic(0); 1670b0104773SPascal Brand 1671e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1672e86f1266SJens Wiklander dl = *destLen; 1673e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1674e86f1266SJens Wiklander srcLen, destData, &dl); 1675e86f1266SJens Wiklander *destLen = dl; 167612e66b6fSCedric Chaumont 16778844ebfcSPascal Brand if (res != TEE_SUCCESS && 16788844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16798844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1680b0104773SPascal Brand TEE_Panic(res); 168112e66b6fSCedric Chaumont 1682b0104773SPascal Brand return res; 1683b0104773SPascal Brand } 1684b0104773SPascal Brand 168512e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, 16868f07fe6fSJerome Forissier const TEE_Attribute *params, 16878f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 168879a3c601SCedric Chaumont uint32_t digestLen, void *signature, 168979a3c601SCedric Chaumont uint32_t *signatureLen) 1690b0104773SPascal Brand { 1691b0104773SPascal Brand TEE_Result res; 1692e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1693e86f1266SJens Wiklander uint64_t sl; 1694b0104773SPascal Brand 169512e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 169612e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1697b0104773SPascal Brand signature == NULL || signatureLen == NULL) 1698b0104773SPascal Brand TEE_Panic(0); 169912e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1700b0104773SPascal Brand TEE_Panic(0); 170112e66b6fSCedric Chaumont if (!operation->key1) 1702b0104773SPascal Brand TEE_Panic(0); 170312e66b6fSCedric Chaumont if (operation->info.operationClass != 170412e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 170512e66b6fSCedric Chaumont TEE_Panic(0); 170612e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_SIGN) 1707b0104773SPascal Brand TEE_Panic(0); 1708b0104773SPascal Brand 1709e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1710e86f1266SJens Wiklander sl = *signatureLen; 1711e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, digest, 1712e86f1266SJens Wiklander digestLen, signature, &sl); 1713e86f1266SJens Wiklander *signatureLen = sl; 171412e66b6fSCedric Chaumont 1715b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) 1716b0104773SPascal Brand TEE_Panic(res); 171712e66b6fSCedric Chaumont 1718b0104773SPascal Brand return res; 1719b0104773SPascal Brand } 1720b0104773SPascal Brand 172112e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, 17228f07fe6fSJerome Forissier const TEE_Attribute *params, 17238f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 17248f07fe6fSJerome Forissier uint32_t digestLen, 17258f07fe6fSJerome Forissier const void *signature, 172679a3c601SCedric Chaumont uint32_t signatureLen) 1727b0104773SPascal Brand { 1728b0104773SPascal Brand TEE_Result res; 1729e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1730b0104773SPascal Brand 173112e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 173212e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1733b0104773SPascal Brand (signature == NULL && signatureLen != 0)) 1734b0104773SPascal Brand TEE_Panic(0); 173512e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1736b0104773SPascal Brand TEE_Panic(0); 173712e66b6fSCedric Chaumont if (!operation->key1) 1738b0104773SPascal Brand TEE_Panic(0); 173912e66b6fSCedric Chaumont if (operation->info.operationClass != 174012e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 174112e66b6fSCedric Chaumont TEE_Panic(0); 174212e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_VERIFY) 1743b0104773SPascal Brand TEE_Panic(0); 1744b0104773SPascal Brand 1745e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1746e86f1266SJens Wiklander res = utee_asymm_verify(operation->state, ua, paramCount, digest, 174712e66b6fSCedric Chaumont digestLen, signature, signatureLen); 174812e66b6fSCedric Chaumont 1749b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) 1750b0104773SPascal Brand TEE_Panic(res); 175112e66b6fSCedric Chaumont 1752b0104773SPascal Brand return res; 1753b0104773SPascal Brand } 1754b0104773SPascal Brand 1755b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */ 1756b0104773SPascal Brand 1757b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation, 1758b0104773SPascal Brand const TEE_Attribute *params, uint32_t paramCount, 1759b0104773SPascal Brand TEE_ObjectHandle derivedKey) 1760b0104773SPascal Brand { 1761b0104773SPascal Brand TEE_Result res; 1762b0104773SPascal Brand TEE_ObjectInfo key_info; 1763e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1764b0104773SPascal Brand 1765b0104773SPascal Brand if (operation == TEE_HANDLE_NULL || derivedKey == 0) 1766b0104773SPascal Brand TEE_Panic(0); 176784fa9467SCedric Chaumont if (params == NULL && paramCount != 0) 1768b0104773SPascal Brand TEE_Panic(0); 17698854d3c6SJerome Forissier if (TEE_ALG_GET_CLASS(operation->info.algorithm) != 17708854d3c6SJerome Forissier TEE_OPERATION_KEY_DERIVATION) 1771b0104773SPascal Brand TEE_Panic(0); 1772b0104773SPascal Brand 1773b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) 1774b0104773SPascal Brand TEE_Panic(0); 177584fa9467SCedric Chaumont if (!operation->key1) 177684fa9467SCedric Chaumont TEE_Panic(0); 1777b0104773SPascal Brand if (operation->info.mode != TEE_MODE_DERIVE) 1778b0104773SPascal Brand TEE_Panic(0); 1779b0104773SPascal Brand if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) 1780b0104773SPascal Brand TEE_Panic(0); 1781b0104773SPascal Brand 1782e86f1266SJens Wiklander res = utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); 1783b0104773SPascal Brand if (res != TEE_SUCCESS) 1784b36311adSJerome Forissier TEE_Panic(res); 1785b0104773SPascal Brand 1786b0104773SPascal Brand if (key_info.objectType != TEE_TYPE_GENERIC_SECRET) 1787b0104773SPascal Brand TEE_Panic(0); 1788b0104773SPascal Brand if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) 1789b0104773SPascal Brand TEE_Panic(0); 1790b0104773SPascal Brand 1791e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1792e86f1266SJens Wiklander res = utee_cryp_derive_key(operation->state, ua, paramCount, 1793e86f1266SJens Wiklander (unsigned long)derivedKey); 1794b0104773SPascal Brand if (res != TEE_SUCCESS) 1795b0104773SPascal Brand TEE_Panic(res); 1796b0104773SPascal Brand } 1797b0104773SPascal Brand 1798b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */ 1799b0104773SPascal Brand 180079a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) 1801b0104773SPascal Brand { 1802b0104773SPascal Brand TEE_Result res; 1803b0104773SPascal Brand 1804b0104773SPascal Brand res = utee_cryp_random_number_generate(randomBuffer, randomBufferLen); 1805b0104773SPascal Brand if (res != TEE_SUCCESS) 1806b0104773SPascal Brand TEE_Panic(res); 1807b0104773SPascal Brand } 1808433c4257SJens Wiklander 1809433c4257SJens Wiklander int rand(void) 1810433c4257SJens Wiklander { 1811433c4257SJens Wiklander int rc; 1812433c4257SJens Wiklander 1813433c4257SJens Wiklander TEE_GenerateRandom(&rc, sizeof(rc)); 1814433c4257SJens Wiklander 1815433c4257SJens Wiklander /* 1816433c4257SJens Wiklander * RAND_MAX is the larges int, INT_MAX which is all bits but the 1817433c4257SJens Wiklander * highest bit set. 1818433c4257SJens Wiklander */ 1819433c4257SJens Wiklander return rc & RAND_MAX; 1820433c4257SJens Wiklander } 1821