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: 120ade6f848SJerome Forissier case TEE_ALG_SM4_ECB_NOPAD: 121ade6f848SJerome Forissier case TEE_ALG_SM4_CBC_NOPAD: 122ade6f848SJerome 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; 125ade6f848SJerome Forissier else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4) 126ade6f848SJerome 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: 229*47645577SJerome Forissier case TEE_ALG_SM3: 230b0104773SPascal Brand if (mode != TEE_MODE_DIGEST) 231b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 23205304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 233b0104773SPascal Brand handle_state |= TEE_HANDLE_FLAG_KEY_SET; 234b0104773SPascal Brand req_key_usage = 0; 235b0104773SPascal Brand break; 236b0104773SPascal Brand 237b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_NOPAD: 238b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_NOPAD: 239b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_PKCS5: 240b0104773SPascal Brand case TEE_ALG_AES_CMAC: 241b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_PKCS5: 242b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_NOPAD: 243b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_PKCS5: 244b0104773SPascal Brand case TEE_ALG_HMAC_MD5: 245b0104773SPascal Brand case TEE_ALG_HMAC_SHA1: 246b0104773SPascal Brand case TEE_ALG_HMAC_SHA224: 247b0104773SPascal Brand case TEE_ALG_HMAC_SHA256: 248b0104773SPascal Brand case TEE_ALG_HMAC_SHA384: 249b0104773SPascal Brand case TEE_ALG_HMAC_SHA512: 250*47645577SJerome Forissier case TEE_ALG_HMAC_SM3: 251b0104773SPascal Brand if (mode != TEE_MODE_MAC) 252b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 253b0104773SPascal Brand req_key_usage = TEE_USAGE_MAC; 254b0104773SPascal Brand break; 255b0104773SPascal Brand 256b0104773SPascal Brand default: 257b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 258b0104773SPascal Brand } 259b0104773SPascal Brand 260b66f219bSJens Wiklander op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO); 2619b52c538SCedric Chaumont if (!op) 262b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY; 263b0104773SPascal Brand 264b0104773SPascal Brand op->info.algorithm = algorithm; 265b0104773SPascal Brand op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); 2666a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1 2676a2e0a9fSGabor Szekely if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5) 2686a2e0a9fSGabor Szekely op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE; 2696a2e0a9fSGabor Szekely #endif 270b0104773SPascal Brand op->info.mode = mode; 271b0104773SPascal Brand op->info.maxKeySize = maxKeySize; 272b0104773SPascal Brand op->info.requiredKeyUsage = req_key_usage; 273b0104773SPascal Brand op->info.handleState = handle_state; 274b0104773SPascal Brand 275b0104773SPascal Brand if (block_size > 1) { 276b0104773SPascal Brand size_t buffer_size = block_size; 277b0104773SPascal Brand 278b0104773SPascal Brand if (buffer_two_blocks) 279b0104773SPascal Brand buffer_size *= 2; 280b0104773SPascal Brand 2819b52c538SCedric Chaumont op->buffer = TEE_Malloc(buffer_size, 2829b52c538SCedric Chaumont TEE_USER_MEM_HINT_NO_FILL_ZERO); 283b0104773SPascal Brand if (op->buffer == NULL) { 284b0104773SPascal Brand res = TEE_ERROR_OUT_OF_MEMORY; 285b66f219bSJens Wiklander goto out; 286b0104773SPascal Brand } 287b0104773SPascal Brand } 288b0104773SPascal Brand op->block_size = block_size; 289b0104773SPascal Brand op->buffer_two_blocks = buffer_two_blocks; 290b0104773SPascal Brand 291b0104773SPascal Brand if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { 292b0104773SPascal Brand uint32_t mks = maxKeySize; 293b0104773SPascal Brand TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, 294b0104773SPascal Brand with_private_key); 295b0104773SPascal Brand 296b0104773SPascal Brand /* 297b0104773SPascal Brand * If two keys are expected the max key size is the sum of 298b0104773SPascal Brand * the size of both keys. 299b0104773SPascal Brand */ 300b0104773SPascal Brand if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) 301b0104773SPascal Brand mks /= 2; 302b0104773SPascal Brand 303b0104773SPascal Brand res = TEE_AllocateTransientObject(key_type, mks, &op->key1); 304b0104773SPascal Brand if (res != TEE_SUCCESS) 305b66f219bSJens Wiklander goto out; 306b0104773SPascal Brand 30705304565SCedric Chaumont if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { 3089b52c538SCedric Chaumont res = TEE_AllocateTransientObject(key_type, mks, 309b0104773SPascal Brand &op->key2); 310b0104773SPascal Brand if (res != TEE_SUCCESS) 311b66f219bSJens Wiklander goto out; 312b0104773SPascal Brand } 313b0104773SPascal Brand } 314b0104773SPascal Brand 315e86f1266SJens Wiklander res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, 316e86f1266SJens Wiklander (unsigned long)op->key2, &op->state); 317b66f219bSJens Wiklander if (res != TEE_SUCCESS) 318b66f219bSJens Wiklander goto out; 319b0104773SPascal Brand 32005304565SCedric Chaumont /* 32105304565SCedric Chaumont * Initialize digest operations 32205304565SCedric Chaumont * Other multi-stage operations initialized w/ TEE_xxxInit functions 32305304565SCedric Chaumont * Non-applicable on asymmetric operations 32405304565SCedric Chaumont */ 32505304565SCedric Chaumont if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { 32605304565SCedric Chaumont res = utee_hash_init(op->state, NULL, 0); 32705304565SCedric Chaumont if (res != TEE_SUCCESS) 328b66f219bSJens Wiklander goto out; 32905304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 33005304565SCedric Chaumont op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 33105304565SCedric Chaumont } 33205304565SCedric Chaumont 333642a1607SCedric Chaumont op->operationState = TEE_OPERATION_STATE_INITIAL; 334642a1607SCedric Chaumont 335b0104773SPascal Brand *operation = op; 336b0104773SPascal Brand 337b66f219bSJens Wiklander out: 338b66f219bSJens Wiklander if (res != TEE_SUCCESS) { 339b66f219bSJens Wiklander if (res != TEE_ERROR_OUT_OF_MEMORY && 3409b52c538SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 341b36311adSJerome Forissier TEE_Panic(res); 342b66f219bSJens Wiklander if (op) { 343b66f219bSJens Wiklander if (op->state) { 344b66f219bSJens Wiklander TEE_FreeOperation(op); 345b66f219bSJens Wiklander } else { 346b66f219bSJens Wiklander TEE_Free(op->buffer); 347b66f219bSJens Wiklander TEE_FreeTransientObject(op->key1); 348b66f219bSJens Wiklander TEE_FreeTransientObject(op->key2); 349b66f219bSJens Wiklander TEE_Free(op); 350b66f219bSJens Wiklander } 351b66f219bSJens Wiklander } 352b66f219bSJens Wiklander } 353b66f219bSJens Wiklander 354b0104773SPascal Brand return res; 355b0104773SPascal Brand } 356b0104773SPascal Brand 357b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation) 358b0104773SPascal Brand { 359e889e80bSCedric Chaumont TEE_Result res; 360e889e80bSCedric Chaumont 361e889e80bSCedric Chaumont if (operation == TEE_HANDLE_NULL) 362e889e80bSCedric Chaumont TEE_Panic(0); 363e889e80bSCedric Chaumont 364b0104773SPascal Brand /* 365b0104773SPascal Brand * Note that keys should not be freed here, since they are 366b0104773SPascal Brand * claimed by the operation they will be freed by 367b0104773SPascal Brand * utee_cryp_state_free(). 368b0104773SPascal Brand */ 369e889e80bSCedric Chaumont res = utee_cryp_state_free(operation->state); 370e889e80bSCedric Chaumont if (res != TEE_SUCCESS) 371b36311adSJerome Forissier TEE_Panic(res); 372e889e80bSCedric Chaumont 373b0104773SPascal Brand TEE_Free(operation->buffer); 374b0104773SPascal Brand TEE_Free(operation); 375b0104773SPascal Brand } 376b0104773SPascal Brand 377b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation, 378b0104773SPascal Brand TEE_OperationInfo *operationInfo) 379b0104773SPascal Brand { 380b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 381b0104773SPascal Brand TEE_Panic(0); 382b0104773SPascal Brand 38305304565SCedric Chaumont if (!operationInfo) 384b0104773SPascal Brand TEE_Panic(0); 385b0104773SPascal Brand 386b0104773SPascal Brand *operationInfo = operation->info; 387b0104773SPascal Brand } 388b0104773SPascal Brand 38905304565SCedric Chaumont TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, 39005304565SCedric Chaumont TEE_OperationInfoMultiple *operationInfoMultiple, 39105304565SCedric Chaumont uint32_t *operationSize) 39205304565SCedric Chaumont { 39305304565SCedric Chaumont TEE_Result res = TEE_SUCCESS; 39405304565SCedric Chaumont TEE_ObjectInfo key_info1; 39505304565SCedric Chaumont TEE_ObjectInfo key_info2; 39605304565SCedric Chaumont uint32_t num_of_keys; 39705304565SCedric Chaumont size_t n; 39805304565SCedric Chaumont 39905304565SCedric Chaumont if (operation == TEE_HANDLE_NULL) { 40005304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40105304565SCedric Chaumont goto out; 40205304565SCedric Chaumont } 40305304565SCedric Chaumont 40405304565SCedric Chaumont if (!operationInfoMultiple) { 40505304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40605304565SCedric Chaumont goto out; 40705304565SCedric Chaumont } 40805304565SCedric Chaumont 40905304565SCedric Chaumont if (!operationSize) { 41005304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 41105304565SCedric Chaumont goto out; 41205304565SCedric Chaumont } 41305304565SCedric Chaumont 41405304565SCedric Chaumont num_of_keys = (*operationSize-sizeof(TEE_OperationInfoMultiple))/ 41505304565SCedric Chaumont sizeof(TEE_OperationInfoKey); 41605304565SCedric Chaumont 41705304565SCedric Chaumont if (num_of_keys > 2) { 41805304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 41905304565SCedric Chaumont goto out; 42005304565SCedric Chaumont } 42105304565SCedric Chaumont 42205304565SCedric Chaumont /* Two keys flag (TEE_ALG_AES_XTS only) */ 42305304565SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 42405304565SCedric Chaumont 0 && 42505304565SCedric Chaumont (num_of_keys != 2)) { 42605304565SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 42705304565SCedric Chaumont goto out; 42805304565SCedric Chaumont } 42905304565SCedric Chaumont 43005304565SCedric Chaumont /* Clear */ 43105304565SCedric Chaumont for (n = 0; n < num_of_keys; n++) { 43205304565SCedric Chaumont operationInfoMultiple->keyInformation[n].keySize = 0; 43305304565SCedric Chaumont operationInfoMultiple->keyInformation[n].requiredKeyUsage = 0; 43405304565SCedric Chaumont } 43505304565SCedric Chaumont 43605304565SCedric Chaumont if (num_of_keys == 2) { 43705304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key2, &key_info2); 43805304565SCedric Chaumont /* Key2 is not a valid handle */ 43905304565SCedric Chaumont if (res != TEE_SUCCESS) 44005304565SCedric Chaumont goto out; 44105304565SCedric Chaumont 44205304565SCedric Chaumont operationInfoMultiple->keyInformation[1].keySize = 44305304565SCedric Chaumont key_info2.keySize; 44405304565SCedric Chaumont operationInfoMultiple->keyInformation[1].requiredKeyUsage = 44505304565SCedric Chaumont operation->info.requiredKeyUsage; 44605304565SCedric Chaumont } 44705304565SCedric Chaumont 44805304565SCedric Chaumont if (num_of_keys >= 1) { 44905304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key1, &key_info1); 45005304565SCedric Chaumont /* Key1 is not a valid handle */ 45105304565SCedric Chaumont if (res != TEE_SUCCESS) { 45205304565SCedric Chaumont if (num_of_keys == 2) { 45305304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 45405304565SCedric Chaumont keySize = 0; 45505304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 45605304565SCedric Chaumont requiredKeyUsage = 0; 45705304565SCedric Chaumont } 45805304565SCedric Chaumont goto out; 45905304565SCedric Chaumont } 46005304565SCedric Chaumont 46105304565SCedric Chaumont operationInfoMultiple->keyInformation[0].keySize = 46205304565SCedric Chaumont key_info1.keySize; 46305304565SCedric Chaumont operationInfoMultiple->keyInformation[0].requiredKeyUsage = 46405304565SCedric Chaumont operation->info.requiredKeyUsage; 46505304565SCedric Chaumont } 46605304565SCedric Chaumont 46705304565SCedric Chaumont /* No key */ 46805304565SCedric Chaumont operationInfoMultiple->algorithm = operation->info.algorithm; 46905304565SCedric Chaumont operationInfoMultiple->operationClass = operation->info.operationClass; 47005304565SCedric Chaumont operationInfoMultiple->mode = operation->info.mode; 47105304565SCedric Chaumont operationInfoMultiple->digestLength = operation->info.digestLength; 47205304565SCedric Chaumont operationInfoMultiple->maxKeySize = operation->info.maxKeySize; 47305304565SCedric Chaumont operationInfoMultiple->handleState = operation->info.handleState; 47405304565SCedric Chaumont operationInfoMultiple->operationState = operation->operationState; 47505304565SCedric Chaumont operationInfoMultiple->numberOfKeys = num_of_keys; 47605304565SCedric Chaumont 47705304565SCedric Chaumont out: 47805304565SCedric Chaumont if (res != TEE_SUCCESS && 47905304565SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 480b36311adSJerome Forissier TEE_Panic(res); 48105304565SCedric Chaumont 48205304565SCedric Chaumont return res; 48305304565SCedric Chaumont } 48405304565SCedric Chaumont 485b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation) 486b0104773SPascal Brand { 487b0104773SPascal Brand TEE_Result res; 488b0104773SPascal Brand 489b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 490b0104773SPascal Brand TEE_Panic(0); 491bf80076aSCedric Chaumont 492642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) 493bf80076aSCedric Chaumont TEE_Panic(0); 494bf80076aSCedric Chaumont 495642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 496642a1607SCedric Chaumont 497b0104773SPascal Brand if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 498b0104773SPascal Brand res = utee_hash_init(operation->state, NULL, 0); 499b0104773SPascal Brand if (res != TEE_SUCCESS) 500b0104773SPascal Brand TEE_Panic(res); 50105304565SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 50205304565SCedric Chaumont } else { 503b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 504b0104773SPascal Brand } 50505304565SCedric Chaumont } 506b0104773SPascal Brand 507b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, 508b0104773SPascal Brand TEE_ObjectHandle key) 509b0104773SPascal Brand { 5107583c59eSCedric Chaumont TEE_Result res; 511b0104773SPascal Brand uint32_t key_size = 0; 512b0104773SPascal Brand TEE_ObjectInfo key_info; 513b0104773SPascal Brand 514a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 515a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 516a57c1e2eSCedric Chaumont goto out; 517a57c1e2eSCedric Chaumont } 518a57c1e2eSCedric Chaumont 519642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 520642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 521642a1607SCedric Chaumont goto out; 522642a1607SCedric Chaumont } 523642a1607SCedric Chaumont 524a57c1e2eSCedric Chaumont if (key == TEE_HANDLE_NULL) { 525a57c1e2eSCedric Chaumont /* Operation key cleared */ 526a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 527a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 528a57c1e2eSCedric Chaumont goto out; 529a57c1e2eSCedric Chaumont } 530a57c1e2eSCedric Chaumont 531a57c1e2eSCedric Chaumont /* No key for digest operation */ 532a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 533a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 534a57c1e2eSCedric Chaumont goto out; 535a57c1e2eSCedric Chaumont } 536a57c1e2eSCedric Chaumont 537a57c1e2eSCedric Chaumont /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ 538a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 539a57c1e2eSCedric Chaumont 0) { 540a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 541a57c1e2eSCedric Chaumont goto out; 542a57c1e2eSCedric Chaumont } 543a57c1e2eSCedric Chaumont 5447583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key, &key_info); 545a57c1e2eSCedric Chaumont /* Key is not a valid handle */ 5467583c59eSCedric Chaumont if (res != TEE_SUCCESS) 547a57c1e2eSCedric Chaumont goto out; 5487583c59eSCedric Chaumont 549b0104773SPascal Brand /* Supplied key has to meet required usage */ 550b0104773SPascal Brand if ((key_info.objectUsage & operation->info.requiredKeyUsage) != 551b0104773SPascal Brand operation->info.requiredKeyUsage) { 552a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 553a57c1e2eSCedric Chaumont goto out; 554b0104773SPascal Brand } 555b0104773SPascal Brand 556a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info.keySize) { 557a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 558a57c1e2eSCedric Chaumont goto out; 559a57c1e2eSCedric Chaumont } 560b0104773SPascal Brand 5617583c59eSCedric Chaumont key_size = key_info.keySize; 562b0104773SPascal Brand 563b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 564b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 565b0104773SPascal Brand 5667583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key); 5677583c59eSCedric Chaumont if (res != TEE_SUCCESS) 568a57c1e2eSCedric Chaumont goto out; 5697583c59eSCedric Chaumont 570b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 571b0104773SPascal Brand 572b0104773SPascal Brand operation->info.keySize = key_size; 573b0104773SPascal Brand 5747583c59eSCedric Chaumont out: 575a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 576a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 577a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 578b36311adSJerome Forissier TEE_Panic(res); 579a57c1e2eSCedric Chaumont 580a57c1e2eSCedric Chaumont return res; 581b0104773SPascal Brand } 582b0104773SPascal Brand 583b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, 584b0104773SPascal Brand TEE_ObjectHandle key1, TEE_ObjectHandle key2) 585b0104773SPascal Brand { 5867583c59eSCedric Chaumont TEE_Result res; 587b0104773SPascal Brand uint32_t key_size = 0; 588b0104773SPascal Brand TEE_ObjectInfo key_info1; 589b0104773SPascal Brand TEE_ObjectInfo key_info2; 590b0104773SPascal Brand 591a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 592a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 593a57c1e2eSCedric Chaumont goto out; 594a57c1e2eSCedric Chaumont } 595a57c1e2eSCedric Chaumont 596642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 597642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 598642a1607SCedric Chaumont goto out; 599642a1607SCedric Chaumont } 600642a1607SCedric Chaumont 601a57c1e2eSCedric Chaumont /* 602a57c1e2eSCedric Chaumont * Key1/Key2 and/or are not initialized and 603a57c1e2eSCedric Chaumont * Either both keys are NULL or both are not NULL 604a57c1e2eSCedric Chaumont */ 605a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL || key2 == TEE_HANDLE_NULL) { 606a57c1e2eSCedric Chaumont /* Clear operation key1 (if needed) */ 607a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL) 608a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 609a57c1e2eSCedric Chaumont /* Clear operation key2 (if needed) */ 610a57c1e2eSCedric Chaumont if (key2 == TEE_HANDLE_NULL) 611a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key2); 612a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 613a57c1e2eSCedric Chaumont goto out; 614a57c1e2eSCedric Chaumont } 615a57c1e2eSCedric Chaumont 616a57c1e2eSCedric Chaumont /* No key for digest operation */ 617a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 618a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 619a57c1e2eSCedric Chaumont goto out; 620a57c1e2eSCedric Chaumont } 621a57c1e2eSCedric Chaumont 622a57c1e2eSCedric Chaumont /* Two keys flag expected (TEE_ALG_AES_XTS only) */ 623a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 624a57c1e2eSCedric Chaumont 0) { 625a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 626a57c1e2eSCedric Chaumont goto out; 627a57c1e2eSCedric Chaumont } 628a57c1e2eSCedric Chaumont 6297583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key1, &key_info1); 630a57c1e2eSCedric Chaumont /* Key1 is not a valid handle */ 6317583c59eSCedric Chaumont if (res != TEE_SUCCESS) 632a57c1e2eSCedric Chaumont goto out; 6337583c59eSCedric Chaumont 634b0104773SPascal Brand /* Supplied key has to meet required usage */ 635b0104773SPascal Brand if ((key_info1.objectUsage & operation->info. 636b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 637a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 638a57c1e2eSCedric Chaumont goto out; 639b0104773SPascal Brand } 640b0104773SPascal Brand 6417583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key2, &key_info2); 642a57c1e2eSCedric Chaumont /* Key2 is not a valid handle */ 6437583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6447583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6457583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 646a57c1e2eSCedric Chaumont goto out; 6477583c59eSCedric Chaumont } 6487583c59eSCedric Chaumont 649b0104773SPascal Brand /* Supplied key has to meet required usage */ 650b0104773SPascal Brand if ((key_info2.objectUsage & operation->info. 651b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 652a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 653a57c1e2eSCedric Chaumont goto out; 654b0104773SPascal Brand } 655b0104773SPascal Brand 656b0104773SPascal Brand /* 657b0104773SPascal Brand * AES-XTS (the only multi key algorithm supported, requires the 658b0104773SPascal Brand * keys to be of equal size. 659b0104773SPascal Brand */ 660b0104773SPascal Brand if (operation->info.algorithm == TEE_ALG_AES_XTS && 661a57c1e2eSCedric Chaumont key_info1.keySize != key_info2.keySize) { 662a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 663a57c1e2eSCedric Chaumont goto out; 664b0104773SPascal Brand 665a57c1e2eSCedric Chaumont } 666a57c1e2eSCedric Chaumont 667a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info1.keySize) { 668a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 669a57c1e2eSCedric Chaumont goto out; 670a57c1e2eSCedric Chaumont } 671b0104773SPascal Brand 672b0104773SPascal Brand /* 673b0104773SPascal Brand * Odd that only the size of one key should be reported while 674b0104773SPascal Brand * size of two key are used when allocating the operation. 675b0104773SPascal Brand */ 6767583c59eSCedric Chaumont key_size = key_info1.keySize; 677b0104773SPascal Brand 678b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 679b0104773SPascal Brand TEE_ResetTransientObject(operation->key2); 680b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 681b0104773SPascal Brand 6827583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key1); 6837583c59eSCedric Chaumont if (res != TEE_SUCCESS) 684a57c1e2eSCedric Chaumont goto out; 6857583c59eSCedric Chaumont 6867583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key2, key2); 6877583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6887583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6897583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 690a57c1e2eSCedric Chaumont goto out; 6917583c59eSCedric Chaumont } 6927583c59eSCedric Chaumont 693b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 694b0104773SPascal Brand 695b0104773SPascal Brand operation->info.keySize = key_size; 696b0104773SPascal Brand 6977583c59eSCedric Chaumont out: 698a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 699a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 700a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT_2 && 701a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE && 702a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) 703b36311adSJerome Forissier TEE_Panic(res); 704a57c1e2eSCedric Chaumont 705a57c1e2eSCedric Chaumont return res; 706b0104773SPascal Brand } 707b0104773SPascal Brand 708b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) 709b0104773SPascal Brand { 710b0104773SPascal Brand TEE_Result res; 711b0104773SPascal Brand 712b0104773SPascal Brand if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) 713b0104773SPascal Brand TEE_Panic(0); 714b0104773SPascal Brand if (dst_op->info.algorithm != src_op->info.algorithm) 715b0104773SPascal Brand TEE_Panic(0); 716b0104773SPascal Brand if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { 717b0104773SPascal Brand TEE_ObjectHandle key1 = TEE_HANDLE_NULL; 718b0104773SPascal Brand TEE_ObjectHandle key2 = TEE_HANDLE_NULL; 719b0104773SPascal Brand 720b0104773SPascal Brand if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { 721b0104773SPascal Brand key1 = src_op->key1; 722b0104773SPascal Brand key2 = src_op->key2; 723b0104773SPascal Brand } 724b0104773SPascal Brand 725b0104773SPascal Brand if ((src_op->info.handleState & 726b0104773SPascal Brand TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { 727b0104773SPascal Brand TEE_SetOperationKey(dst_op, key1); 728b0104773SPascal Brand } else { 729b0104773SPascal Brand TEE_SetOperationKey2(dst_op, key1, key2); 730b0104773SPascal Brand } 731b0104773SPascal Brand } 732b0104773SPascal Brand dst_op->info.handleState = src_op->info.handleState; 733b0104773SPascal Brand dst_op->info.keySize = src_op->info.keySize; 734642a1607SCedric Chaumont dst_op->operationState = src_op->operationState; 735b0104773SPascal Brand 736b0104773SPascal Brand if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || 737b0104773SPascal Brand dst_op->block_size != src_op->block_size) 738b0104773SPascal Brand TEE_Panic(0); 739b0104773SPascal Brand 740b0104773SPascal Brand if (dst_op->buffer != NULL) { 741b0104773SPascal Brand if (src_op->buffer == NULL) 742b0104773SPascal Brand TEE_Panic(0); 743b0104773SPascal Brand 744b0104773SPascal Brand memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs); 745b0104773SPascal Brand dst_op->buffer_offs = src_op->buffer_offs; 746b0104773SPascal Brand } else if (src_op->buffer != NULL) { 747b0104773SPascal Brand TEE_Panic(0); 748b0104773SPascal Brand } 749b0104773SPascal Brand 750b0104773SPascal Brand res = utee_cryp_state_copy(dst_op->state, src_op->state); 751b0104773SPascal Brand if (res != TEE_SUCCESS) 752b0104773SPascal Brand TEE_Panic(res); 753b0104773SPascal Brand } 754b0104773SPascal Brand 755b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */ 756b0104773SPascal Brand 7578f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV, 7586d15db08SJerome Forissier uint32_t IVLen) 7596d15db08SJerome Forissier { 7606d15db08SJerome Forissier TEE_Result res; 7616d15db08SJerome Forissier 7626d15db08SJerome Forissier /* 7636d15db08SJerome Forissier * Note : IV and IVLen are never used in current implementation 7646d15db08SJerome Forissier * This is why coherent values of IV and IVLen are not checked 7656d15db08SJerome Forissier */ 7666d15db08SJerome Forissier res = utee_hash_init(operation->state, IV, IVLen); 7676d15db08SJerome Forissier if (res != TEE_SUCCESS) 7686d15db08SJerome Forissier TEE_Panic(res); 7696d15db08SJerome Forissier operation->buffer_offs = 0; 7706d15db08SJerome Forissier operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 7716d15db08SJerome Forissier } 7726d15db08SJerome Forissier 773b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation, 7748f07fe6fSJerome Forissier const void *chunk, uint32_t chunkSize) 775b0104773SPascal Brand { 77673d6c3baSJoakim Bech TEE_Result res = TEE_ERROR_GENERIC; 777b0104773SPascal Brand 77873d6c3baSJoakim Bech if (operation == TEE_HANDLE_NULL || 77973d6c3baSJoakim Bech operation->info.operationClass != TEE_OPERATION_DIGEST) 780b0104773SPascal Brand TEE_Panic(0); 78173d6c3baSJoakim Bech 782642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 783642a1607SCedric Chaumont 784b0104773SPascal Brand res = utee_hash_update(operation->state, chunk, chunkSize); 785b0104773SPascal Brand if (res != TEE_SUCCESS) 786b0104773SPascal Brand TEE_Panic(res); 787b0104773SPascal Brand } 788b0104773SPascal Brand 7898f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, 79079a3c601SCedric Chaumont uint32_t chunkLen, void *hash, uint32_t *hashLen) 791b0104773SPascal Brand { 79287c2f6b6SCedric Chaumont TEE_Result res; 793e86f1266SJens Wiklander uint64_t hl; 79487c2f6b6SCedric Chaumont 79587c2f6b6SCedric Chaumont if ((operation == TEE_HANDLE_NULL) || 79687c2f6b6SCedric Chaumont (!chunk && chunkLen) || 79787c2f6b6SCedric Chaumont !hash || 79887c2f6b6SCedric Chaumont !hashLen || 79987c2f6b6SCedric Chaumont (operation->info.operationClass != TEE_OPERATION_DIGEST)) { 80087c2f6b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 80187c2f6b6SCedric Chaumont goto out; 80287c2f6b6SCedric Chaumont } 80387c2f6b6SCedric Chaumont 804e86f1266SJens Wiklander hl = *hashLen; 805e86f1266SJens Wiklander res = utee_hash_final(operation->state, chunk, chunkLen, hash, &hl); 806e86f1266SJens Wiklander *hashLen = hl; 8076d15db08SJerome Forissier if (res != TEE_SUCCESS) 8086d15db08SJerome Forissier goto out; 8096d15db08SJerome Forissier 8106d15db08SJerome Forissier /* Reset operation state */ 8116d15db08SJerome Forissier init_hash_operation(operation, NULL, 0); 81287c2f6b6SCedric Chaumont 813642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 814642a1607SCedric Chaumont 81587c2f6b6SCedric Chaumont out: 81687c2f6b6SCedric Chaumont if (res != TEE_SUCCESS && 81787c2f6b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 818b36311adSJerome Forissier TEE_Panic(res); 81973d6c3baSJoakim Bech 82087c2f6b6SCedric Chaumont return res; 821b0104773SPascal Brand } 822b0104773SPascal Brand 823b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */ 824b0104773SPascal Brand 8258f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, 8268f07fe6fSJerome Forissier uint32_t IVLen) 827b0104773SPascal Brand { 828b0104773SPascal Brand TEE_Result res; 829b0104773SPascal Brand 830b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 831b0104773SPascal Brand TEE_Panic(0); 832642a1607SCedric Chaumont 833b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_CIPHER) 834b0104773SPascal Brand TEE_Panic(0); 835642a1607SCedric Chaumont 836642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 837642a1607SCedric Chaumont !(operation->key1)) 838642a1607SCedric Chaumont TEE_Panic(0); 839642a1607SCedric Chaumont 840642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 841642a1607SCedric Chaumont TEE_ResetOperation(operation); 842642a1607SCedric Chaumont 843642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 844642a1607SCedric Chaumont 845b0104773SPascal Brand res = utee_cipher_init(operation->state, IV, IVLen); 846b0104773SPascal Brand if (res != TEE_SUCCESS) 847b0104773SPascal Brand TEE_Panic(res); 848642a1607SCedric Chaumont 849b0104773SPascal Brand operation->buffer_offs = 0; 850b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 851b0104773SPascal Brand } 852b0104773SPascal Brand 853b0104773SPascal Brand static TEE_Result tee_buffer_update( 854b0104773SPascal Brand TEE_OperationHandle op, 855e86f1266SJens Wiklander TEE_Result(*update_func)(unsigned long state, const void *src, 856e86f1266SJens Wiklander size_t slen, void *dst, uint64_t *dlen), 857b0104773SPascal Brand const void *src_data, size_t src_len, 858e86f1266SJens Wiklander void *dest_data, uint64_t *dest_len) 859b0104773SPascal Brand { 860b0104773SPascal Brand TEE_Result res; 861b0104773SPascal Brand const uint8_t *src = src_data; 862b0104773SPascal Brand size_t slen = src_len; 863b0104773SPascal Brand uint8_t *dst = dest_data; 864b0104773SPascal Brand size_t dlen = *dest_len; 865b0104773SPascal Brand size_t acc_dlen = 0; 866e86f1266SJens Wiklander uint64_t tmp_dlen; 867b0104773SPascal Brand size_t l; 868b0104773SPascal Brand size_t buffer_size; 869d3588802SPascal Brand size_t buffer_left; 870b0104773SPascal Brand 871090268f5SJens Wiklander if (!src) { 872090268f5SJens Wiklander if (slen) 873090268f5SJens Wiklander TEE_Panic(0); 874090268f5SJens Wiklander goto out; 875090268f5SJens Wiklander } 876090268f5SJens Wiklander 877d3588802SPascal Brand if (op->buffer_two_blocks) { 878b0104773SPascal Brand buffer_size = op->block_size * 2; 879d3588802SPascal Brand buffer_left = 1; 880d3588802SPascal Brand } else { 881b0104773SPascal Brand buffer_size = op->block_size; 882d3588802SPascal Brand buffer_left = 0; 883d3588802SPascal Brand } 884b0104773SPascal Brand 885b0104773SPascal Brand if (op->buffer_offs > 0) { 886b0104773SPascal Brand /* Fill up complete block */ 887b0104773SPascal Brand if (op->buffer_offs < op->block_size) 888b0104773SPascal Brand l = MIN(slen, op->block_size - op->buffer_offs); 889b0104773SPascal Brand else 890b0104773SPascal Brand l = MIN(slen, buffer_size - op->buffer_offs); 891b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, l); 892b0104773SPascal Brand op->buffer_offs += l; 893b0104773SPascal Brand src += l; 894b0104773SPascal Brand slen -= l; 895b0104773SPascal Brand if ((op->buffer_offs % op->block_size) != 0) 896b0104773SPascal Brand goto out; /* Nothing left to do */ 897b0104773SPascal Brand } 898b0104773SPascal Brand 899b0104773SPascal Brand /* If we can feed from buffer */ 900d3588802SPascal Brand if ((op->buffer_offs > 0) && 901d3588802SPascal Brand ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) { 9022ff3fdbbSPascal Brand l = ROUNDUP(op->buffer_offs + slen - buffer_size, 903b0104773SPascal Brand op->block_size); 904b0104773SPascal Brand l = MIN(op->buffer_offs, l); 905b0104773SPascal Brand tmp_dlen = dlen; 906b0104773SPascal Brand res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); 907b0104773SPascal Brand if (res != TEE_SUCCESS) 908b0104773SPascal Brand TEE_Panic(res); 909b0104773SPascal Brand dst += tmp_dlen; 910b0104773SPascal Brand dlen -= tmp_dlen; 911b0104773SPascal Brand acc_dlen += tmp_dlen; 912b0104773SPascal Brand op->buffer_offs -= l; 913b0104773SPascal Brand if (op->buffer_offs > 0) { 914b0104773SPascal Brand /* 915b0104773SPascal Brand * Slen is small enough to be contained in rest buffer. 916b0104773SPascal Brand */ 917b0104773SPascal Brand memcpy(op->buffer, op->buffer + l, buffer_size - l); 918b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 919b0104773SPascal Brand op->buffer_offs += slen; 920b0104773SPascal Brand goto out; /* Nothing left to do */ 921b0104773SPascal Brand } 922b0104773SPascal Brand } 923b0104773SPascal Brand 924d3588802SPascal Brand if (slen >= (buffer_size + buffer_left)) { 925b0104773SPascal Brand /* Buffer is empty, feed as much as possible from src */ 926bf7a587fSJerome Forissier if (op->info.algorithm == TEE_ALG_AES_CTS) 927b1ecda78SJerome Forissier l = ROUNDUP(slen - buffer_size, op->block_size); 928bf7a587fSJerome Forissier else 929bf7a587fSJerome Forissier l = ROUNDUP(slen - buffer_size + 1, op->block_size); 930b0104773SPascal Brand 931b0104773SPascal Brand tmp_dlen = dlen; 932b0104773SPascal Brand res = update_func(op->state, src, l, dst, &tmp_dlen); 933b0104773SPascal Brand if (res != TEE_SUCCESS) 934b0104773SPascal Brand TEE_Panic(res); 935b0104773SPascal Brand src += l; 936b0104773SPascal Brand slen -= l; 937b0104773SPascal Brand dst += tmp_dlen; 938b0104773SPascal Brand dlen -= tmp_dlen; 939b0104773SPascal Brand acc_dlen += tmp_dlen; 940b0104773SPascal Brand } 941b0104773SPascal Brand 942b0104773SPascal Brand /* Slen is small enough to be contained in buffer. */ 943b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 944b0104773SPascal Brand op->buffer_offs += slen; 945b0104773SPascal Brand 946b0104773SPascal Brand out: 947b0104773SPascal Brand *dest_len = acc_dlen; 948b0104773SPascal Brand return TEE_SUCCESS; 949b0104773SPascal Brand } 950b0104773SPascal Brand 9518f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, 95279a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 953b0104773SPascal Brand { 954dea1f2b6SCedric Chaumont TEE_Result res; 955b0104773SPascal Brand size_t req_dlen; 956e86f1266SJens Wiklander uint64_t dl; 957b0104773SPascal Brand 958642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 959dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 960dea1f2b6SCedric Chaumont destLen == NULL || 961dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 962dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 963dea1f2b6SCedric Chaumont goto out; 964dea1f2b6SCedric Chaumont } 965dea1f2b6SCedric Chaumont 966642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 967dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 968dea1f2b6SCedric Chaumont goto out; 969dea1f2b6SCedric Chaumont } 970dea1f2b6SCedric Chaumont 971642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 972642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 973642a1607SCedric Chaumont goto out; 974642a1607SCedric Chaumont } 975642a1607SCedric Chaumont 976642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 977dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 978dea1f2b6SCedric Chaumont goto out; 979dea1f2b6SCedric Chaumont } 980b0104773SPascal Brand 981e32c5ddfSJerome Forissier if (!srcData && !srcLen) { 982090268f5SJens Wiklander *destLen = 0; 983e32c5ddfSJerome Forissier res = TEE_SUCCESS; 984e32c5ddfSJerome Forissier goto out; 985e32c5ddfSJerome Forissier } 986e32c5ddfSJerome Forissier 987b0104773SPascal Brand /* Calculate required dlen */ 98857aabac5SBogdan Liulko if (operation->block_size > 1) { 98957aabac5SBogdan Liulko req_dlen = ((operation->buffer_offs + srcLen) / 99057aabac5SBogdan Liulko operation->block_size) * operation->block_size; 99157aabac5SBogdan Liulko } else { 99257aabac5SBogdan Liulko req_dlen = srcLen; 99357aabac5SBogdan Liulko } 994642a1607SCedric Chaumont if (operation->buffer_two_blocks) { 995642a1607SCedric Chaumont if (req_dlen > operation->block_size * 2) 996642a1607SCedric Chaumont req_dlen -= operation->block_size * 2; 997b0104773SPascal Brand else 998b0104773SPascal Brand req_dlen = 0; 999b0104773SPascal Brand } 1000b0104773SPascal Brand /* 1001b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1002b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1003b0104773SPascal Brand * can't restore sync with this API. 1004b0104773SPascal Brand */ 1005b0104773SPascal Brand if (*destLen < req_dlen) { 1006b0104773SPascal Brand *destLen = req_dlen; 1007dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1008dea1f2b6SCedric Chaumont goto out; 1009b0104773SPascal Brand } 1010b0104773SPascal Brand 1011e86f1266SJens Wiklander dl = *destLen; 101257aabac5SBogdan Liulko if (operation->block_size > 1) { 101357aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, srcData, 101457aabac5SBogdan Liulko srcLen, destData, &dl); 101557aabac5SBogdan Liulko } else { 101657aabac5SBogdan Liulko if (srcLen > 0) { 101757aabac5SBogdan Liulko res = utee_cipher_update(operation->state, srcData, 101857aabac5SBogdan Liulko srcLen, destData, &dl); 101957aabac5SBogdan Liulko } else { 102057aabac5SBogdan Liulko res = TEE_SUCCESS; 102157aabac5SBogdan Liulko dl = 0; 102257aabac5SBogdan Liulko } 102357aabac5SBogdan Liulko } 1024e86f1266SJens Wiklander *destLen = dl; 1025b0104773SPascal Brand 1026dea1f2b6SCedric Chaumont out: 1027dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1028dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1029b36311adSJerome Forissier TEE_Panic(res); 1030dea1f2b6SCedric Chaumont 1031dea1f2b6SCedric Chaumont return res; 1032b0104773SPascal Brand } 1033b0104773SPascal Brand 1034642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, 10358f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 10368f07fe6fSJerome Forissier void *destData, uint32_t *destLen) 1037b0104773SPascal Brand { 1038b0104773SPascal Brand TEE_Result res; 1039b0104773SPascal Brand uint8_t *dst = destData; 1040b0104773SPascal Brand size_t acc_dlen = 0; 1041e86f1266SJens Wiklander uint64_t tmp_dlen; 1042b0104773SPascal Brand size_t req_dlen; 1043b0104773SPascal Brand 1044642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1045dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 1046dea1f2b6SCedric Chaumont destLen == NULL || 1047dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 1048dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1049dea1f2b6SCedric Chaumont goto out; 1050dea1f2b6SCedric Chaumont } 1051dea1f2b6SCedric Chaumont 1052642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 1053dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1054dea1f2b6SCedric Chaumont goto out; 1055dea1f2b6SCedric Chaumont } 1056dea1f2b6SCedric Chaumont 1057642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1058642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1059642a1607SCedric Chaumont goto out; 1060642a1607SCedric Chaumont } 1061642a1607SCedric Chaumont 1062642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1063dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1064dea1f2b6SCedric Chaumont goto out; 1065dea1f2b6SCedric Chaumont } 1066b0104773SPascal Brand 1067b0104773SPascal Brand /* 1068b0104773SPascal Brand * Check that the final block doesn't require padding for those 1069b0104773SPascal Brand * algorithms that requires client to supply padding. 1070b0104773SPascal Brand */ 1071642a1607SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || 1072642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || 1073642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || 1074642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || 1075642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || 1076ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD || 1077ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD || 1078ade6f848SJerome Forissier operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) { 1079642a1607SCedric Chaumont if (((operation->buffer_offs + srcLen) % operation->block_size) 1080642a1607SCedric Chaumont != 0) { 1081dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1082dea1f2b6SCedric Chaumont goto out; 1083dea1f2b6SCedric Chaumont } 1084b0104773SPascal Brand } 1085b0104773SPascal Brand 1086b0104773SPascal Brand /* 1087b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1088b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1089b0104773SPascal Brand * can't restore sync with this API. 1090b0104773SPascal Brand */ 109157aabac5SBogdan Liulko if (operation->block_size > 1) { 1092642a1607SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 109357aabac5SBogdan Liulko } else { 109457aabac5SBogdan Liulko req_dlen = srcLen; 109557aabac5SBogdan Liulko } 1096b0104773SPascal Brand if (*destLen < req_dlen) { 1097b0104773SPascal Brand *destLen = req_dlen; 1098dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1099dea1f2b6SCedric Chaumont goto out; 1100b0104773SPascal Brand } 1101b0104773SPascal Brand 1102b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 110357aabac5SBogdan Liulko if (operation->block_size > 1) { 110457aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, 110557aabac5SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1106dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS) 1107dea1f2b6SCedric Chaumont goto out; 1108dea1f2b6SCedric Chaumont 1109b0104773SPascal Brand dst += tmp_dlen; 1110b0104773SPascal Brand acc_dlen += tmp_dlen; 1111b0104773SPascal Brand 1112b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1113642a1607SCedric Chaumont res = utee_cipher_final(operation->state, operation->buffer, 1114642a1607SCedric Chaumont operation->buffer_offs, dst, &tmp_dlen); 111557aabac5SBogdan Liulko } else { 111657aabac5SBogdan Liulko res = utee_cipher_final(operation->state, srcData, 111757aabac5SBogdan Liulko srcLen, dst, &tmp_dlen); 111857aabac5SBogdan Liulko } 1119b0104773SPascal Brand if (res != TEE_SUCCESS) 1120dea1f2b6SCedric Chaumont goto out; 1121dea1f2b6SCedric Chaumont 1122b0104773SPascal Brand acc_dlen += tmp_dlen; 1123b0104773SPascal Brand *destLen = acc_dlen; 1124dea1f2b6SCedric Chaumont 1125642a1607SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1126642a1607SCedric Chaumont 1127642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1128642a1607SCedric Chaumont 1129dea1f2b6SCedric Chaumont out: 1130dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1131dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1132b36311adSJerome Forissier TEE_Panic(res); 1133dea1f2b6SCedric Chaumont 1134dea1f2b6SCedric Chaumont return res; 1135b0104773SPascal Brand } 1136b0104773SPascal Brand 1137b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */ 1138b0104773SPascal Brand 11398f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) 1140b0104773SPascal Brand { 1141b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 1142b0104773SPascal Brand TEE_Panic(0); 1143642a1607SCedric Chaumont 1144b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_MAC) 1145b0104773SPascal Brand TEE_Panic(0); 1146642a1607SCedric Chaumont 1147642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 1148642a1607SCedric Chaumont !(operation->key1)) 1149642a1607SCedric Chaumont TEE_Panic(0); 1150642a1607SCedric Chaumont 1151642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 1152642a1607SCedric Chaumont TEE_ResetOperation(operation); 1153642a1607SCedric Chaumont 1154642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1155642a1607SCedric Chaumont 11566d15db08SJerome Forissier init_hash_operation(operation, IV, IVLen); 1157b0104773SPascal Brand } 1158b0104773SPascal Brand 11598f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, 116028e0efc6SCedric Chaumont uint32_t chunkSize) 1161b0104773SPascal Brand { 1162b0104773SPascal Brand TEE_Result res; 1163b0104773SPascal Brand 116428e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) 1165b0104773SPascal Brand TEE_Panic(0); 1166642a1607SCedric Chaumont 116728e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) 1168b0104773SPascal Brand TEE_Panic(0); 1169642a1607SCedric Chaumont 117028e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1171b0104773SPascal Brand TEE_Panic(0); 1172b0104773SPascal Brand 1173642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) 1174642a1607SCedric Chaumont TEE_Panic(0); 1175642a1607SCedric Chaumont 117628e0efc6SCedric Chaumont res = utee_hash_update(operation->state, chunk, chunkSize); 1177b0104773SPascal Brand if (res != TEE_SUCCESS) 1178b0104773SPascal Brand TEE_Panic(res); 1179b0104773SPascal Brand } 1180b0104773SPascal Brand 118128e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, 11828f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 118379a3c601SCedric Chaumont void *mac, uint32_t *macLen) 1184b0104773SPascal Brand { 1185b0104773SPascal Brand TEE_Result res; 1186e86f1266SJens Wiklander uint64_t ml; 1187b0104773SPascal Brand 118828e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || 118928e0efc6SCedric Chaumont (message == NULL && messageLen != 0) || 119028e0efc6SCedric Chaumont mac == NULL || 119128e0efc6SCedric Chaumont macLen == NULL) { 119228e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 119328e0efc6SCedric Chaumont goto out; 119428e0efc6SCedric Chaumont } 1195b0104773SPascal Brand 119628e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 119728e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 119828e0efc6SCedric Chaumont goto out; 119928e0efc6SCedric Chaumont } 120028e0efc6SCedric Chaumont 120128e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 120228e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 120328e0efc6SCedric Chaumont goto out; 120428e0efc6SCedric Chaumont } 120528e0efc6SCedric Chaumont 1206642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1207642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1208642a1607SCedric Chaumont goto out; 1209642a1607SCedric Chaumont } 1210642a1607SCedric Chaumont 1211e86f1266SJens Wiklander ml = *macLen; 1212e86f1266SJens Wiklander res = utee_hash_final(operation->state, message, messageLen, mac, &ml); 1213e86f1266SJens Wiklander *macLen = ml; 121428e0efc6SCedric Chaumont if (res != TEE_SUCCESS) 121528e0efc6SCedric Chaumont goto out; 121628e0efc6SCedric Chaumont 121728e0efc6SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 121828e0efc6SCedric Chaumont 1219642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1220642a1607SCedric Chaumont 122128e0efc6SCedric Chaumont out: 122228e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 122328e0efc6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 122428e0efc6SCedric Chaumont TEE_Panic(res); 122528e0efc6SCedric Chaumont 1226b0104773SPascal Brand return res; 1227b0104773SPascal Brand } 1228b0104773SPascal Brand 1229b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, 12308f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 12318f07fe6fSJerome Forissier const void *mac, uint32_t macLen) 1232b0104773SPascal Brand { 1233b0104773SPascal Brand TEE_Result res; 1234b0104773SPascal Brand uint8_t computed_mac[TEE_MAX_HASH_SIZE]; 12357f74c64aSPascal Brand uint32_t computed_mac_size = TEE_MAX_HASH_SIZE; 1236b0104773SPascal Brand 123728e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 123828e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 123928e0efc6SCedric Chaumont goto out; 124028e0efc6SCedric Chaumont } 124128e0efc6SCedric Chaumont 124228e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 124328e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 124428e0efc6SCedric Chaumont goto out; 124528e0efc6SCedric Chaumont } 124628e0efc6SCedric Chaumont 1247642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1248642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1249642a1607SCedric Chaumont goto out; 1250642a1607SCedric Chaumont } 1251642a1607SCedric Chaumont 1252b0104773SPascal Brand res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, 1253b0104773SPascal Brand &computed_mac_size); 1254b0104773SPascal Brand if (res != TEE_SUCCESS) 125528e0efc6SCedric Chaumont goto out; 125628e0efc6SCedric Chaumont 125728e0efc6SCedric Chaumont if (computed_mac_size != macLen) { 125828e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 125928e0efc6SCedric Chaumont goto out; 126028e0efc6SCedric Chaumont } 126128e0efc6SCedric Chaumont 126248e10604SJerome Forissier if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) { 126328e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 126428e0efc6SCedric Chaumont goto out; 126528e0efc6SCedric Chaumont } 126628e0efc6SCedric Chaumont 1267642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1268642a1607SCedric Chaumont 126928e0efc6SCedric Chaumont out: 127028e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 127128e0efc6SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 127228e0efc6SCedric Chaumont TEE_Panic(res); 127328e0efc6SCedric Chaumont 1274b0104773SPascal Brand return res; 1275b0104773SPascal Brand } 1276b0104773SPascal Brand 1277b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */ 1278b0104773SPascal Brand 12798f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, 128079a3c601SCedric Chaumont uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, 1281b0104773SPascal Brand uint32_t payloadLen) 1282b0104773SPascal Brand { 1283b0104773SPascal Brand TEE_Result res; 1284b0104773SPascal Brand 1285b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || nonce == NULL) { 1286b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1287b5816c88SCedric Chaumont goto out; 1288b5816c88SCedric Chaumont } 1289b5816c88SCedric Chaumont 1290b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1291b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1292b5816c88SCedric Chaumont goto out; 1293b5816c88SCedric Chaumont } 1294b0104773SPascal Brand 1295642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 1296642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1297642a1607SCedric Chaumont goto out; 1298642a1607SCedric Chaumont } 1299642a1607SCedric Chaumont 1300b0104773SPascal Brand /* 1301b0104773SPascal Brand * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core 1302b0104773SPascal Brand * in the implementation. But AES-GCM spec doesn't specify the tag len 1303b0104773SPascal Brand * according to the same principle so we have to check here instead to 1304b0104773SPascal Brand * be GP compliant. 1305b0104773SPascal Brand */ 1306b5816c88SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_GCM) { 1307b0104773SPascal Brand /* 1308b0104773SPascal Brand * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 1309b0104773SPascal Brand */ 1310b5816c88SCedric Chaumont if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) { 1311b5816c88SCedric Chaumont res = TEE_ERROR_NOT_SUPPORTED; 1312b5816c88SCedric Chaumont goto out; 1313b5816c88SCedric Chaumont } 1314b0104773SPascal Brand } 1315b0104773SPascal Brand 1316b5816c88SCedric Chaumont res = utee_authenc_init(operation->state, nonce, nonceLen, 1317b5816c88SCedric Chaumont tagLen / 8, AADLen, payloadLen); 1318b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1319b5816c88SCedric Chaumont goto out; 1320b5816c88SCedric Chaumont 1321b5816c88SCedric Chaumont operation->ae_tag_len = tagLen / 8; 1322b5816c88SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 1323b5816c88SCedric Chaumont 1324b5816c88SCedric Chaumont out: 1325b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1326b5816c88SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 1327b0104773SPascal Brand TEE_Panic(res); 1328b5816c88SCedric Chaumont 1329b0104773SPascal Brand return res; 1330b0104773SPascal Brand } 1331b0104773SPascal Brand 13328f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, 133379a3c601SCedric Chaumont uint32_t AADdataLen) 1334b0104773SPascal Brand { 1335b0104773SPascal Brand TEE_Result res; 1336b0104773SPascal Brand 1337b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1338b5816c88SCedric Chaumont (AADdata == NULL && AADdataLen != 0)) 1339b0104773SPascal Brand TEE_Panic(0); 1340642a1607SCedric Chaumont 1341b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) 1342b0104773SPascal Brand TEE_Panic(0); 1343642a1607SCedric Chaumont 1344b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1345b0104773SPascal Brand TEE_Panic(0); 1346b0104773SPascal Brand 1347b5816c88SCedric Chaumont res = utee_authenc_update_aad(operation->state, AADdata, AADdataLen); 1348642a1607SCedric Chaumont 1349642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1350642a1607SCedric Chaumont 1351b0104773SPascal Brand if (res != TEE_SUCCESS) 1352b0104773SPascal Brand TEE_Panic(res); 1353b0104773SPascal Brand } 1354b0104773SPascal Brand 13558f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, 135679a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 1357b0104773SPascal Brand { 1358b5816c88SCedric Chaumont TEE_Result res; 1359b0104773SPascal Brand size_t req_dlen; 1360e86f1266SJens Wiklander uint64_t dl; 1361b0104773SPascal Brand 1362b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1363b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1364b5816c88SCedric Chaumont destLen == NULL || 1365b5816c88SCedric Chaumont (destData == NULL && *destLen != 0)) { 1366b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1367b5816c88SCedric Chaumont goto out; 1368b5816c88SCedric Chaumont } 1369b5816c88SCedric Chaumont 1370b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1371b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1372b5816c88SCedric Chaumont goto out; 1373b5816c88SCedric Chaumont } 1374b5816c88SCedric Chaumont 1375b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1376b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1377b5816c88SCedric Chaumont goto out; 1378b5816c88SCedric Chaumont } 1379b0104773SPascal Brand 1380827308b8SJerome Forissier if (!srcData && !srcLen) { 1381090268f5SJens Wiklander *destLen = 0; 1382827308b8SJerome Forissier res = TEE_SUCCESS; 1383827308b8SJerome Forissier goto out; 1384827308b8SJerome Forissier } 1385827308b8SJerome Forissier 1386b0104773SPascal Brand /* 1387b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1388b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1389b0104773SPascal Brand * can't restore sync with this API. 1390b0104773SPascal Brand */ 1391afc0c182SBogdan Liulko if (operation->block_size > 1) { 1392b5816c88SCedric Chaumont req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen, 1393b5816c88SCedric Chaumont operation->block_size); 1394afc0c182SBogdan Liulko } else { 1395afc0c182SBogdan Liulko req_dlen = srcLen; 1396afc0c182SBogdan Liulko } 1397afc0c182SBogdan Liulko 1398b0104773SPascal Brand if (*destLen < req_dlen) { 1399b0104773SPascal Brand *destLen = req_dlen; 1400b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1401b5816c88SCedric Chaumont goto out; 1402b0104773SPascal Brand } 1403b0104773SPascal Brand 1404e86f1266SJens Wiklander dl = *destLen; 1405afc0c182SBogdan Liulko if (operation->block_size > 1) { 1406afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1407afc0c182SBogdan Liulko srcData, srcLen, destData, &dl); 1408afc0c182SBogdan Liulko } else { 1409afc0c182SBogdan Liulko if (srcLen > 0) { 1410afc0c182SBogdan Liulko res = utee_authenc_update_payload(operation->state, 1411afc0c182SBogdan Liulko srcData, srcLen, 1412afc0c182SBogdan Liulko destData, &dl); 1413afc0c182SBogdan Liulko } else { 1414afc0c182SBogdan Liulko dl = 0; 1415afc0c182SBogdan Liulko res = TEE_SUCCESS; 1416afc0c182SBogdan Liulko } 1417afc0c182SBogdan Liulko } 1418afc0c182SBogdan Liulko if (res != TEE_SUCCESS) 1419afc0c182SBogdan Liulko goto out; 1420afc0c182SBogdan Liulko 1421e86f1266SJens Wiklander *destLen = dl; 1422b0104773SPascal Brand 1423642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1424642a1607SCedric Chaumont 1425b5816c88SCedric Chaumont out: 1426b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1427b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1428b5816c88SCedric Chaumont TEE_Panic(res); 1429b5816c88SCedric Chaumont 1430b5816c88SCedric Chaumont return res; 1431b0104773SPascal Brand } 1432b0104773SPascal Brand 1433b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, 14348f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 143579a3c601SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 143679a3c601SCedric Chaumont uint32_t *tagLen) 1437b0104773SPascal Brand { 1438b0104773SPascal Brand TEE_Result res; 1439b0104773SPascal Brand uint8_t *dst = destData; 1440b0104773SPascal Brand size_t acc_dlen = 0; 1441e86f1266SJens Wiklander uint64_t tmp_dlen; 1442b0104773SPascal Brand size_t req_dlen; 1443e86f1266SJens Wiklander uint64_t tl; 1444b0104773SPascal Brand 1445b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1446b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1447b5816c88SCedric Chaumont destLen == NULL || 1448b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1449b5816c88SCedric Chaumont tag == NULL || tagLen == NULL) { 1450b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1451b5816c88SCedric Chaumont goto out; 1452b5816c88SCedric Chaumont } 1453b5816c88SCedric Chaumont 1454b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1455b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1456b5816c88SCedric Chaumont goto out; 1457b5816c88SCedric Chaumont } 1458b5816c88SCedric Chaumont 1459b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1460b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1461b5816c88SCedric Chaumont goto out; 1462b5816c88SCedric Chaumont } 1463b0104773SPascal Brand 1464b0104773SPascal Brand /* 1465b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1466b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1467b0104773SPascal Brand * can't restore sync with this API. 14682733280aSEtienne Carriere * 14692733280aSEtienne Carriere * Need to check this before update_payload since sync would be lost if 14702733280aSEtienne Carriere * we return short buffer after that. 1471b0104773SPascal Brand */ 14722733280aSEtienne Carriere res = TEE_ERROR_GENERIC; 14732733280aSEtienne Carriere 1474b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1475b0104773SPascal Brand if (*destLen < req_dlen) { 1476b0104773SPascal Brand *destLen = req_dlen; 1477b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1478b0104773SPascal Brand } 1479b0104773SPascal Brand 1480b5816c88SCedric Chaumont if (*tagLen < operation->ae_tag_len) { 1481b5816c88SCedric Chaumont *tagLen = operation->ae_tag_len; 1482b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1483b0104773SPascal Brand } 1484b0104773SPascal Brand 14852733280aSEtienne Carriere if (res == TEE_ERROR_SHORT_BUFFER) 14862733280aSEtienne Carriere goto out; 14872733280aSEtienne Carriere 1488afc0c182SBogdan Liulko tl = *tagLen; 1489b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1490afc0c182SBogdan Liulko if (operation->block_size > 1) { 1491afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1492afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1493b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1494b5816c88SCedric Chaumont goto out; 1495b5816c88SCedric Chaumont 1496b0104773SPascal Brand dst += tmp_dlen; 1497b0104773SPascal Brand acc_dlen += tmp_dlen; 1498b0104773SPascal Brand 1499b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1500afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, 1501afc0c182SBogdan Liulko operation->buffer, 1502afc0c182SBogdan Liulko operation->buffer_offs, dst, 1503afc0c182SBogdan Liulko &tmp_dlen, tag, &tl); 1504afc0c182SBogdan Liulko } else { 1505afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, srcData, 1506afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1507e86f1266SJens Wiklander tag, &tl); 1508afc0c182SBogdan Liulko } 1509e86f1266SJens Wiklander *tagLen = tl; 1510b0104773SPascal Brand if (res != TEE_SUCCESS) 1511b5816c88SCedric Chaumont goto out; 1512b0104773SPascal Brand 1513b5816c88SCedric Chaumont acc_dlen += tmp_dlen; 1514b0104773SPascal Brand *destLen = acc_dlen; 1515642a1607SCedric Chaumont 1516b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1517b5816c88SCedric Chaumont 1518642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1519642a1607SCedric Chaumont 1520b5816c88SCedric Chaumont out: 1521b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1522b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1523b5816c88SCedric Chaumont TEE_Panic(res); 1524b0104773SPascal Brand 1525b0104773SPascal Brand return res; 1526b0104773SPascal Brand } 1527b0104773SPascal Brand 1528b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, 15298f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 1530b5816c88SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 153179a3c601SCedric Chaumont uint32_t tagLen) 1532b0104773SPascal Brand { 1533b0104773SPascal Brand TEE_Result res; 1534b0104773SPascal Brand uint8_t *dst = destData; 1535b0104773SPascal Brand size_t acc_dlen = 0; 1536e86f1266SJens Wiklander uint64_t tmp_dlen; 1537b0104773SPascal Brand size_t req_dlen; 1538b0104773SPascal Brand 1539b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1540b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1541b5816c88SCedric Chaumont destLen == NULL || 1542b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1543b5816c88SCedric Chaumont (tag == NULL && tagLen != 0)) { 1544b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1545b5816c88SCedric Chaumont goto out; 1546b5816c88SCedric Chaumont } 1547b5816c88SCedric Chaumont 1548b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1549b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1550b5816c88SCedric Chaumont goto out; 1551b5816c88SCedric Chaumont } 1552b5816c88SCedric Chaumont 1553b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1554b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1555b5816c88SCedric Chaumont goto out; 1556b5816c88SCedric Chaumont } 1557b0104773SPascal Brand 1558b0104773SPascal Brand /* 1559b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1560b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1561b0104773SPascal Brand * can't restore sync with this API. 1562b0104773SPascal Brand */ 1563b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1564b0104773SPascal Brand if (*destLen < req_dlen) { 1565b0104773SPascal Brand *destLen = req_dlen; 1566b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1567b5816c88SCedric Chaumont goto out; 1568b0104773SPascal Brand } 1569b0104773SPascal Brand 1570b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1571afc0c182SBogdan Liulko if (operation->block_size > 1) { 1572afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1573afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1574b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1575b5816c88SCedric Chaumont goto out; 1576b5816c88SCedric Chaumont 1577b0104773SPascal Brand dst += tmp_dlen; 1578b0104773SPascal Brand acc_dlen += tmp_dlen; 1579b0104773SPascal Brand 1580b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1581afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, 1582afc0c182SBogdan Liulko operation->buffer, 1583afc0c182SBogdan Liulko operation->buffer_offs, dst, 1584afc0c182SBogdan Liulko &tmp_dlen, tag, tagLen); 1585afc0c182SBogdan Liulko } else { 1586afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, srcData, 1587afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1588b5816c88SCedric Chaumont tag, tagLen); 1589afc0c182SBogdan Liulko } 1590b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1591b5816c88SCedric Chaumont goto out; 1592b5816c88SCedric Chaumont 1593b0104773SPascal Brand /* Supplied tagLen should match what we initiated with */ 1594b5816c88SCedric Chaumont if (tagLen != operation->ae_tag_len) 1595b0104773SPascal Brand res = TEE_ERROR_MAC_INVALID; 1596b0104773SPascal Brand 1597b0104773SPascal Brand acc_dlen += tmp_dlen; 1598b0104773SPascal Brand *destLen = acc_dlen; 1599642a1607SCedric Chaumont 1600b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1601b5816c88SCedric Chaumont 1602642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1603642a1607SCedric Chaumont 1604b5816c88SCedric Chaumont out: 1605b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1606b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER && 1607b5816c88SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 1608b5816c88SCedric Chaumont TEE_Panic(res); 1609b0104773SPascal Brand 1610b0104773SPascal Brand return res; 1611b0104773SPascal Brand } 1612b0104773SPascal Brand 1613b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */ 1614b0104773SPascal Brand 161512e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, 16168f07fe6fSJerome Forissier const TEE_Attribute *params, 16178f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 161879a3c601SCedric Chaumont uint32_t srcLen, void *destData, 161979a3c601SCedric Chaumont uint32_t *destLen) 1620b0104773SPascal Brand { 1621b0104773SPascal Brand TEE_Result res; 1622e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1623e86f1266SJens Wiklander uint64_t dl; 1624b0104773SPascal Brand 162512e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1626b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1627b0104773SPascal Brand TEE_Panic(0); 162812e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1629b0104773SPascal Brand TEE_Panic(0); 163012e66b6fSCedric Chaumont if (!operation->key1) 1631b0104773SPascal Brand TEE_Panic(0); 163212e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 163312e66b6fSCedric Chaumont TEE_Panic(0); 163412e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_ENCRYPT) 1635b0104773SPascal Brand TEE_Panic(0); 1636b0104773SPascal Brand 1637e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1638e86f1266SJens Wiklander dl = *destLen; 1639e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1640e86f1266SJens Wiklander srcLen, destData, &dl); 1641e86f1266SJens Wiklander *destLen = dl; 164212e66b6fSCedric Chaumont 16438844ebfcSPascal Brand if (res != TEE_SUCCESS && 16448844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16458844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1646b0104773SPascal Brand TEE_Panic(res); 164712e66b6fSCedric Chaumont 1648b0104773SPascal Brand return res; 1649b0104773SPascal Brand } 1650b0104773SPascal Brand 165112e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, 16528f07fe6fSJerome Forissier const TEE_Attribute *params, 16538f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 165479a3c601SCedric Chaumont uint32_t srcLen, void *destData, 165579a3c601SCedric Chaumont uint32_t *destLen) 1656b0104773SPascal Brand { 1657b0104773SPascal Brand TEE_Result res; 1658e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1659e86f1266SJens Wiklander uint64_t dl; 1660b0104773SPascal Brand 166112e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1662b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1663b0104773SPascal Brand TEE_Panic(0); 166412e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1665b0104773SPascal Brand TEE_Panic(0); 166612e66b6fSCedric Chaumont if (!operation->key1) 1667b0104773SPascal Brand TEE_Panic(0); 166812e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 166912e66b6fSCedric Chaumont TEE_Panic(0); 167012e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_DECRYPT) 1671b0104773SPascal Brand TEE_Panic(0); 1672b0104773SPascal Brand 1673e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1674e86f1266SJens Wiklander dl = *destLen; 1675e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1676e86f1266SJens Wiklander srcLen, destData, &dl); 1677e86f1266SJens Wiklander *destLen = dl; 167812e66b6fSCedric Chaumont 16798844ebfcSPascal Brand if (res != TEE_SUCCESS && 16808844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16818844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1682b0104773SPascal Brand TEE_Panic(res); 168312e66b6fSCedric Chaumont 1684b0104773SPascal Brand return res; 1685b0104773SPascal Brand } 1686b0104773SPascal Brand 168712e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, 16888f07fe6fSJerome Forissier const TEE_Attribute *params, 16898f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 169079a3c601SCedric Chaumont uint32_t digestLen, void *signature, 169179a3c601SCedric Chaumont uint32_t *signatureLen) 1692b0104773SPascal Brand { 1693b0104773SPascal Brand TEE_Result res; 1694e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1695e86f1266SJens Wiklander uint64_t sl; 1696b0104773SPascal Brand 169712e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 169812e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1699b0104773SPascal Brand signature == NULL || signatureLen == NULL) 1700b0104773SPascal Brand TEE_Panic(0); 170112e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1702b0104773SPascal Brand TEE_Panic(0); 170312e66b6fSCedric Chaumont if (!operation->key1) 1704b0104773SPascal Brand TEE_Panic(0); 170512e66b6fSCedric Chaumont if (operation->info.operationClass != 170612e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 170712e66b6fSCedric Chaumont TEE_Panic(0); 170812e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_SIGN) 1709b0104773SPascal Brand TEE_Panic(0); 1710b0104773SPascal Brand 1711e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1712e86f1266SJens Wiklander sl = *signatureLen; 1713e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, digest, 1714e86f1266SJens Wiklander digestLen, signature, &sl); 1715e86f1266SJens Wiklander *signatureLen = sl; 171612e66b6fSCedric Chaumont 1717b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) 1718b0104773SPascal Brand TEE_Panic(res); 171912e66b6fSCedric Chaumont 1720b0104773SPascal Brand return res; 1721b0104773SPascal Brand } 1722b0104773SPascal Brand 172312e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, 17248f07fe6fSJerome Forissier const TEE_Attribute *params, 17258f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 17268f07fe6fSJerome Forissier uint32_t digestLen, 17278f07fe6fSJerome Forissier const void *signature, 172879a3c601SCedric Chaumont uint32_t signatureLen) 1729b0104773SPascal Brand { 1730b0104773SPascal Brand TEE_Result res; 1731e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1732b0104773SPascal Brand 173312e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 173412e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1735b0104773SPascal Brand (signature == NULL && signatureLen != 0)) 1736b0104773SPascal Brand TEE_Panic(0); 173712e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1738b0104773SPascal Brand TEE_Panic(0); 173912e66b6fSCedric Chaumont if (!operation->key1) 1740b0104773SPascal Brand TEE_Panic(0); 174112e66b6fSCedric Chaumont if (operation->info.operationClass != 174212e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 174312e66b6fSCedric Chaumont TEE_Panic(0); 174412e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_VERIFY) 1745b0104773SPascal Brand TEE_Panic(0); 1746b0104773SPascal Brand 1747e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1748e86f1266SJens Wiklander res = utee_asymm_verify(operation->state, ua, paramCount, digest, 174912e66b6fSCedric Chaumont digestLen, signature, signatureLen); 175012e66b6fSCedric Chaumont 1751b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) 1752b0104773SPascal Brand TEE_Panic(res); 175312e66b6fSCedric Chaumont 1754b0104773SPascal Brand return res; 1755b0104773SPascal Brand } 1756b0104773SPascal Brand 1757b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */ 1758b0104773SPascal Brand 1759b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation, 1760b0104773SPascal Brand const TEE_Attribute *params, uint32_t paramCount, 1761b0104773SPascal Brand TEE_ObjectHandle derivedKey) 1762b0104773SPascal Brand { 1763b0104773SPascal Brand TEE_Result res; 1764b0104773SPascal Brand TEE_ObjectInfo key_info; 1765e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1766b0104773SPascal Brand 1767b0104773SPascal Brand if (operation == TEE_HANDLE_NULL || derivedKey == 0) 1768b0104773SPascal Brand TEE_Panic(0); 176984fa9467SCedric Chaumont if (params == NULL && paramCount != 0) 1770b0104773SPascal Brand TEE_Panic(0); 17718854d3c6SJerome Forissier if (TEE_ALG_GET_CLASS(operation->info.algorithm) != 17728854d3c6SJerome Forissier TEE_OPERATION_KEY_DERIVATION) 1773b0104773SPascal Brand TEE_Panic(0); 1774b0104773SPascal Brand 1775b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) 1776b0104773SPascal Brand TEE_Panic(0); 177784fa9467SCedric Chaumont if (!operation->key1) 177884fa9467SCedric Chaumont TEE_Panic(0); 1779b0104773SPascal Brand if (operation->info.mode != TEE_MODE_DERIVE) 1780b0104773SPascal Brand TEE_Panic(0); 1781b0104773SPascal Brand if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) 1782b0104773SPascal Brand TEE_Panic(0); 1783b0104773SPascal Brand 1784e86f1266SJens Wiklander res = utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); 1785b0104773SPascal Brand if (res != TEE_SUCCESS) 1786b36311adSJerome Forissier TEE_Panic(res); 1787b0104773SPascal Brand 1788b0104773SPascal Brand if (key_info.objectType != TEE_TYPE_GENERIC_SECRET) 1789b0104773SPascal Brand TEE_Panic(0); 1790b0104773SPascal Brand if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) 1791b0104773SPascal Brand TEE_Panic(0); 1792b0104773SPascal Brand 1793e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1794e86f1266SJens Wiklander res = utee_cryp_derive_key(operation->state, ua, paramCount, 1795e86f1266SJens Wiklander (unsigned long)derivedKey); 1796b0104773SPascal Brand if (res != TEE_SUCCESS) 1797b0104773SPascal Brand TEE_Panic(res); 1798b0104773SPascal Brand } 1799b0104773SPascal Brand 1800b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */ 1801b0104773SPascal Brand 180279a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) 1803b0104773SPascal Brand { 1804b0104773SPascal Brand TEE_Result res; 1805b0104773SPascal Brand 1806b0104773SPascal Brand res = utee_cryp_random_number_generate(randomBuffer, randomBufferLen); 1807b0104773SPascal Brand if (res != TEE_SUCCESS) 1808b0104773SPascal Brand TEE_Panic(res); 1809b0104773SPascal Brand } 1810433c4257SJens Wiklander 1811433c4257SJens Wiklander int rand(void) 1812433c4257SJens Wiklander { 1813433c4257SJens Wiklander int rc; 1814433c4257SJens Wiklander 1815433c4257SJens Wiklander TEE_GenerateRandom(&rc, sizeof(rc)); 1816433c4257SJens Wiklander 1817433c4257SJens Wiklander /* 1818433c4257SJens Wiklander * RAND_MAX is the larges int, INT_MAX which is all bits but the 1819433c4257SJens Wiklander * highest bit set. 1820433c4257SJens Wiklander */ 1821433c4257SJens Wiklander return rc & RAND_MAX; 1822433c4257SJens Wiklander } 1823