11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2b0104773SPascal Brand /* 3b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V. 4b0104773SPascal Brand */ 5b0104773SPascal Brand #include <stdlib.h> 6b0104773SPascal Brand #include <string.h> 7b796ebf3SJerome Forissier #include <string_ext.h> 8b0104773SPascal Brand 9b0104773SPascal Brand #include <tee_api.h> 108854d3c6SJerome Forissier #include <tee_api_defines_extensions.h> 11b0104773SPascal Brand #include <tee_internal_api_extensions.h> 12b0104773SPascal Brand #include <utee_syscalls.h> 13b0104773SPascal Brand #include <utee_defines.h> 14fc26c92aSJens Wiklander #include <util.h> 15e86f1266SJens Wiklander #include "tee_api_private.h" 16b0104773SPascal Brand 17b0104773SPascal Brand struct __TEE_OperationHandle { 18b0104773SPascal Brand TEE_OperationInfo info; 19b0104773SPascal Brand TEE_ObjectHandle key1; 20b0104773SPascal Brand TEE_ObjectHandle key2; 21642a1607SCedric Chaumont uint32_t operationState;/* Operation state : INITIAL or ACTIVE */ 22b0104773SPascal Brand uint8_t *buffer; /* buffer to collect complete blocks */ 23b0104773SPascal Brand bool buffer_two_blocks; /* True if two blocks need to be buffered */ 24b0104773SPascal Brand size_t block_size; /* Block size of cipher */ 25b0104773SPascal Brand size_t buffer_offs; /* Offset in buffer */ 26b0104773SPascal Brand uint32_t state; /* Handle to state in TEE Core */ 27b0104773SPascal Brand uint32_t ae_tag_len; /* 28b0104773SPascal Brand * tag_len in bytes for AE operation else unused 29b0104773SPascal Brand */ 30b0104773SPascal Brand }; 31b0104773SPascal Brand 32b0104773SPascal Brand /* Cryptographic Operations API - Generic Operation Functions */ 33b0104773SPascal Brand 34b0104773SPascal Brand TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, 35b0104773SPascal Brand uint32_t algorithm, uint32_t mode, 36b0104773SPascal Brand uint32_t maxKeySize) 37b0104773SPascal Brand { 38b0104773SPascal Brand TEE_Result res; 39b0104773SPascal Brand TEE_OperationHandle op = TEE_HANDLE_NULL; 40b0104773SPascal Brand uint32_t handle_state = 0; 41b0104773SPascal Brand size_t block_size = 1; 42b0104773SPascal Brand uint32_t req_key_usage; 43b0104773SPascal Brand bool with_private_key = false; 44b0104773SPascal Brand bool buffer_two_blocks = false; 45b0104773SPascal Brand 469b52c538SCedric Chaumont if (!operation) 47b0104773SPascal Brand TEE_Panic(0); 48b0104773SPascal Brand 49b0104773SPascal Brand if (algorithm == TEE_ALG_AES_XTS) 50b0104773SPascal Brand handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; 51b0104773SPascal Brand 52218d9055SCedric Chaumont /* Check algorithm max key size */ 53218d9055SCedric Chaumont switch (algorithm) { 54218d9055SCedric Chaumont case TEE_ALG_DSA_SHA1: 55218d9055SCedric Chaumont if (maxKeySize < 512) 56218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 57218d9055SCedric Chaumont if (maxKeySize > 1024) 58218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 59218d9055SCedric Chaumont if (maxKeySize % 64 != 0) 60218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 61218d9055SCedric Chaumont break; 62218d9055SCedric Chaumont 63218d9055SCedric Chaumont case TEE_ALG_DSA_SHA224: 64218d9055SCedric Chaumont if (maxKeySize != 2048) 65218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 66218d9055SCedric Chaumont break; 67218d9055SCedric Chaumont 68218d9055SCedric Chaumont case TEE_ALG_DSA_SHA256: 69218d9055SCedric Chaumont if (maxKeySize != 2048 && maxKeySize != 3072) 70218d9055SCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 71218d9055SCedric Chaumont break; 72218d9055SCedric Chaumont 731220586eSCedric Chaumont case TEE_ALG_ECDSA_P192: 741220586eSCedric Chaumont case TEE_ALG_ECDH_P192: 751220586eSCedric Chaumont if (maxKeySize != 192) 761220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 771220586eSCedric Chaumont break; 781220586eSCedric Chaumont 791220586eSCedric Chaumont case TEE_ALG_ECDSA_P224: 801220586eSCedric Chaumont case TEE_ALG_ECDH_P224: 811220586eSCedric Chaumont if (maxKeySize != 224) 821220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 831220586eSCedric Chaumont break; 841220586eSCedric Chaumont 851220586eSCedric Chaumont case TEE_ALG_ECDSA_P256: 861220586eSCedric Chaumont case TEE_ALG_ECDH_P256: 871220586eSCedric Chaumont if (maxKeySize != 256) 881220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 891220586eSCedric Chaumont break; 901220586eSCedric Chaumont 911220586eSCedric Chaumont case TEE_ALG_ECDSA_P384: 921220586eSCedric Chaumont case TEE_ALG_ECDH_P384: 931220586eSCedric Chaumont if (maxKeySize != 384) 941220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 951220586eSCedric Chaumont break; 961220586eSCedric Chaumont 971220586eSCedric Chaumont case TEE_ALG_ECDSA_P521: 981220586eSCedric Chaumont case TEE_ALG_ECDH_P521: 991220586eSCedric Chaumont if (maxKeySize != 521) 1001220586eSCedric Chaumont return TEE_ERROR_NOT_SUPPORTED; 1011220586eSCedric Chaumont break; 1021220586eSCedric Chaumont 103218d9055SCedric Chaumont default: 104218d9055SCedric Chaumont break; 105218d9055SCedric Chaumont } 106218d9055SCedric Chaumont 107218d9055SCedric Chaumont /* Check algorithm mode */ 108b0104773SPascal Brand switch (algorithm) { 109b0104773SPascal Brand case TEE_ALG_AES_CTS: 110b0104773SPascal Brand case TEE_ALG_AES_XTS: 111b0104773SPascal Brand buffer_two_blocks = true; 1124bd53c54SJerome Forissier /* FALLTHROUGH */ 1134bd53c54SJerome Forissier case TEE_ALG_AES_ECB_NOPAD: 114b0104773SPascal Brand case TEE_ALG_AES_CBC_NOPAD: 115b0104773SPascal Brand case TEE_ALG_AES_CCM: 116b0104773SPascal Brand case TEE_ALG_DES_ECB_NOPAD: 117b0104773SPascal Brand case TEE_ALG_DES_CBC_NOPAD: 118b0104773SPascal Brand case TEE_ALG_DES3_ECB_NOPAD: 119b0104773SPascal Brand case TEE_ALG_DES3_CBC_NOPAD: 120b0104773SPascal Brand if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) 121b0104773SPascal Brand block_size = TEE_AES_BLOCK_SIZE; 122b0104773SPascal Brand else 123b0104773SPascal Brand block_size = TEE_DES_BLOCK_SIZE; 124afc0c182SBogdan Liulko /* FALLTHROUGH */ 12557aabac5SBogdan Liulko case TEE_ALG_AES_CTR: 126afc0c182SBogdan Liulko case TEE_ALG_AES_GCM: 127b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) 128b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 129b0104773SPascal Brand else if (mode == TEE_MODE_DECRYPT) 130b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 131b0104773SPascal Brand else 132b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 133b0104773SPascal Brand break; 134b0104773SPascal Brand 135b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: 136b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: 137b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: 138b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: 139b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: 140b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: 141b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: 142b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: 143b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: 144b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: 145b0104773SPascal Brand case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: 146b0104773SPascal Brand case TEE_ALG_DSA_SHA1: 147218d9055SCedric Chaumont case TEE_ALG_DSA_SHA224: 148218d9055SCedric Chaumont case TEE_ALG_DSA_SHA256: 1491220586eSCedric Chaumont case TEE_ALG_ECDSA_P192: 1501220586eSCedric Chaumont case TEE_ALG_ECDSA_P224: 1511220586eSCedric Chaumont case TEE_ALG_ECDSA_P256: 1521220586eSCedric Chaumont case TEE_ALG_ECDSA_P384: 1531220586eSCedric Chaumont case TEE_ALG_ECDSA_P521: 154b0104773SPascal Brand if (mode == TEE_MODE_SIGN) { 155b0104773SPascal Brand with_private_key = true; 156b0104773SPascal Brand req_key_usage = TEE_USAGE_SIGN; 157b0104773SPascal Brand } else if (mode == TEE_MODE_VERIFY) { 158b0104773SPascal Brand req_key_usage = TEE_USAGE_VERIFY; 159b0104773SPascal Brand } else { 160b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 161b0104773SPascal Brand } 162b0104773SPascal Brand break; 163b0104773SPascal Brand 164b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_V1_5: 165b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: 166b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: 167b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: 168b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: 169b0104773SPascal Brand case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: 170b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 171b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT; 172b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 173b0104773SPascal Brand with_private_key = true; 174b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT; 175b0104773SPascal Brand } else { 176b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 177b0104773SPascal Brand } 178b0104773SPascal Brand break; 179b0104773SPascal Brand 180b0104773SPascal Brand case TEE_ALG_RSA_NOPAD: 181b0104773SPascal Brand if (mode == TEE_MODE_ENCRYPT) { 182b0104773SPascal Brand req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY; 183b0104773SPascal Brand } else if (mode == TEE_MODE_DECRYPT) { 184b0104773SPascal Brand with_private_key = true; 185b0104773SPascal Brand req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN; 186b0104773SPascal Brand } else { 187b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 188b0104773SPascal Brand } 189b0104773SPascal Brand break; 190b0104773SPascal Brand 191b0104773SPascal Brand case TEE_ALG_DH_DERIVE_SHARED_SECRET: 1921220586eSCedric Chaumont case TEE_ALG_ECDH_P192: 1931220586eSCedric Chaumont case TEE_ALG_ECDH_P224: 1941220586eSCedric Chaumont case TEE_ALG_ECDH_P256: 1951220586eSCedric Chaumont case TEE_ALG_ECDH_P384: 1961220586eSCedric Chaumont case TEE_ALG_ECDH_P521: 197cdb198a7SJerome Forissier case TEE_ALG_HKDF_MD5_DERIVE_KEY: 198cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA1_DERIVE_KEY: 199cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA224_DERIVE_KEY: 200cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA256_DERIVE_KEY: 201cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA384_DERIVE_KEY: 202cdb198a7SJerome Forissier case TEE_ALG_HKDF_SHA512_DERIVE_KEY: 2038854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY: 2048854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY: 2058854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY: 2068854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY: 2078854d3c6SJerome Forissier case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY: 2080f2293b7SJerome Forissier case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY: 209b0104773SPascal Brand if (mode != TEE_MODE_DERIVE) 210b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 211b0104773SPascal Brand with_private_key = true; 212b0104773SPascal Brand req_key_usage = TEE_USAGE_DERIVE; 213b0104773SPascal Brand break; 214b0104773SPascal Brand 215b0104773SPascal Brand case TEE_ALG_MD5: 216b0104773SPascal Brand case TEE_ALG_SHA1: 217b0104773SPascal Brand case TEE_ALG_SHA224: 218b0104773SPascal Brand case TEE_ALG_SHA256: 219b0104773SPascal Brand case TEE_ALG_SHA384: 220b0104773SPascal Brand case TEE_ALG_SHA512: 221b0104773SPascal Brand if (mode != TEE_MODE_DIGEST) 222b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 22305304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 224b0104773SPascal Brand handle_state |= TEE_HANDLE_FLAG_KEY_SET; 225b0104773SPascal Brand req_key_usage = 0; 226b0104773SPascal Brand break; 227b0104773SPascal Brand 228b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_NOPAD: 229b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_NOPAD: 230b0104773SPascal Brand case TEE_ALG_AES_CBC_MAC_PKCS5: 231b0104773SPascal Brand case TEE_ALG_AES_CMAC: 232b0104773SPascal Brand case TEE_ALG_DES_CBC_MAC_PKCS5: 233b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_NOPAD: 234b0104773SPascal Brand case TEE_ALG_DES3_CBC_MAC_PKCS5: 235b0104773SPascal Brand case TEE_ALG_HMAC_MD5: 236b0104773SPascal Brand case TEE_ALG_HMAC_SHA1: 237b0104773SPascal Brand case TEE_ALG_HMAC_SHA224: 238b0104773SPascal Brand case TEE_ALG_HMAC_SHA256: 239b0104773SPascal Brand case TEE_ALG_HMAC_SHA384: 240b0104773SPascal Brand case TEE_ALG_HMAC_SHA512: 241b0104773SPascal Brand if (mode != TEE_MODE_MAC) 242b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 243b0104773SPascal Brand req_key_usage = TEE_USAGE_MAC; 244b0104773SPascal Brand break; 245b0104773SPascal Brand 246b0104773SPascal Brand default: 247b0104773SPascal Brand return TEE_ERROR_NOT_SUPPORTED; 248b0104773SPascal Brand } 249b0104773SPascal Brand 250b66f219bSJens Wiklander op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO); 2519b52c538SCedric Chaumont if (!op) 252b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY; 253b0104773SPascal Brand 254b0104773SPascal Brand op->info.algorithm = algorithm; 255b0104773SPascal Brand op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); 256b0104773SPascal Brand op->info.mode = mode; 257b0104773SPascal Brand op->info.maxKeySize = maxKeySize; 258b0104773SPascal Brand op->info.requiredKeyUsage = req_key_usage; 259b0104773SPascal Brand op->info.handleState = handle_state; 260b0104773SPascal Brand 261b0104773SPascal Brand if (block_size > 1) { 262b0104773SPascal Brand size_t buffer_size = block_size; 263b0104773SPascal Brand 264b0104773SPascal Brand if (buffer_two_blocks) 265b0104773SPascal Brand buffer_size *= 2; 266b0104773SPascal Brand 2679b52c538SCedric Chaumont op->buffer = TEE_Malloc(buffer_size, 2689b52c538SCedric Chaumont TEE_USER_MEM_HINT_NO_FILL_ZERO); 269b0104773SPascal Brand if (op->buffer == NULL) { 270b0104773SPascal Brand res = TEE_ERROR_OUT_OF_MEMORY; 271b66f219bSJens Wiklander goto out; 272b0104773SPascal Brand } 273b0104773SPascal Brand } 274b0104773SPascal Brand op->block_size = block_size; 275b0104773SPascal Brand op->buffer_two_blocks = buffer_two_blocks; 276b0104773SPascal Brand 277b0104773SPascal Brand if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { 278b0104773SPascal Brand uint32_t mks = maxKeySize; 279b0104773SPascal Brand TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, 280b0104773SPascal Brand with_private_key); 281b0104773SPascal Brand 282b0104773SPascal Brand /* 283b0104773SPascal Brand * If two keys are expected the max key size is the sum of 284b0104773SPascal Brand * the size of both keys. 285b0104773SPascal Brand */ 286b0104773SPascal Brand if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) 287b0104773SPascal Brand mks /= 2; 288b0104773SPascal Brand 289b0104773SPascal Brand res = TEE_AllocateTransientObject(key_type, mks, &op->key1); 290b0104773SPascal Brand if (res != TEE_SUCCESS) 291b66f219bSJens Wiklander goto out; 292b0104773SPascal Brand 29305304565SCedric Chaumont if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { 2949b52c538SCedric Chaumont res = TEE_AllocateTransientObject(key_type, mks, 295b0104773SPascal Brand &op->key2); 296b0104773SPascal Brand if (res != TEE_SUCCESS) 297b66f219bSJens Wiklander goto out; 298b0104773SPascal Brand } 299b0104773SPascal Brand } 300b0104773SPascal Brand 301e86f1266SJens Wiklander res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, 302e86f1266SJens Wiklander (unsigned long)op->key2, &op->state); 303b66f219bSJens Wiklander if (res != TEE_SUCCESS) 304b66f219bSJens Wiklander goto out; 305b0104773SPascal Brand 30605304565SCedric Chaumont /* 30705304565SCedric Chaumont * Initialize digest operations 30805304565SCedric Chaumont * Other multi-stage operations initialized w/ TEE_xxxInit functions 30905304565SCedric Chaumont * Non-applicable on asymmetric operations 31005304565SCedric Chaumont */ 31105304565SCedric Chaumont if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { 31205304565SCedric Chaumont res = utee_hash_init(op->state, NULL, 0); 31305304565SCedric Chaumont if (res != TEE_SUCCESS) 314b66f219bSJens Wiklander goto out; 31505304565SCedric Chaumont /* v1.1: flags always set for digest operations */ 31605304565SCedric Chaumont op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 31705304565SCedric Chaumont } 31805304565SCedric Chaumont 319642a1607SCedric Chaumont op->operationState = TEE_OPERATION_STATE_INITIAL; 320642a1607SCedric Chaumont 321b0104773SPascal Brand *operation = op; 322b0104773SPascal Brand 323b66f219bSJens Wiklander out: 324b66f219bSJens Wiklander if (res != TEE_SUCCESS) { 325b66f219bSJens Wiklander if (res != TEE_ERROR_OUT_OF_MEMORY && 3269b52c538SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 327b36311adSJerome Forissier TEE_Panic(res); 328b66f219bSJens Wiklander if (op) { 329b66f219bSJens Wiklander if (op->state) { 330b66f219bSJens Wiklander TEE_FreeOperation(op); 331b66f219bSJens Wiklander } else { 332b66f219bSJens Wiklander TEE_Free(op->buffer); 333b66f219bSJens Wiklander TEE_FreeTransientObject(op->key1); 334b66f219bSJens Wiklander TEE_FreeTransientObject(op->key2); 335b66f219bSJens Wiklander TEE_Free(op); 336b66f219bSJens Wiklander } 337b66f219bSJens Wiklander } 338b66f219bSJens Wiklander } 339b66f219bSJens Wiklander 340b0104773SPascal Brand return res; 341b0104773SPascal Brand } 342b0104773SPascal Brand 343b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation) 344b0104773SPascal Brand { 345e889e80bSCedric Chaumont TEE_Result res; 346e889e80bSCedric Chaumont 347e889e80bSCedric Chaumont if (operation == TEE_HANDLE_NULL) 348e889e80bSCedric Chaumont TEE_Panic(0); 349e889e80bSCedric Chaumont 350b0104773SPascal Brand /* 351b0104773SPascal Brand * Note that keys should not be freed here, since they are 352b0104773SPascal Brand * claimed by the operation they will be freed by 353b0104773SPascal Brand * utee_cryp_state_free(). 354b0104773SPascal Brand */ 355e889e80bSCedric Chaumont res = utee_cryp_state_free(operation->state); 356e889e80bSCedric Chaumont if (res != TEE_SUCCESS) 357b36311adSJerome Forissier TEE_Panic(res); 358e889e80bSCedric Chaumont 359b0104773SPascal Brand TEE_Free(operation->buffer); 360b0104773SPascal Brand TEE_Free(operation); 361b0104773SPascal Brand } 362b0104773SPascal Brand 363b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation, 364b0104773SPascal Brand TEE_OperationInfo *operationInfo) 365b0104773SPascal Brand { 366b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 367b0104773SPascal Brand TEE_Panic(0); 368b0104773SPascal Brand 36905304565SCedric Chaumont if (!operationInfo) 370b0104773SPascal Brand TEE_Panic(0); 371b0104773SPascal Brand 372b0104773SPascal Brand *operationInfo = operation->info; 373b0104773SPascal Brand } 374b0104773SPascal Brand 37505304565SCedric Chaumont TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, 37605304565SCedric Chaumont TEE_OperationInfoMultiple *operationInfoMultiple, 37705304565SCedric Chaumont uint32_t *operationSize) 37805304565SCedric Chaumont { 37905304565SCedric Chaumont TEE_Result res = TEE_SUCCESS; 38005304565SCedric Chaumont TEE_ObjectInfo key_info1; 38105304565SCedric Chaumont TEE_ObjectInfo key_info2; 38205304565SCedric Chaumont uint32_t num_of_keys; 38305304565SCedric Chaumont size_t n; 38405304565SCedric Chaumont 38505304565SCedric Chaumont if (operation == TEE_HANDLE_NULL) { 38605304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 38705304565SCedric Chaumont goto out; 38805304565SCedric Chaumont } 38905304565SCedric Chaumont 39005304565SCedric Chaumont if (!operationInfoMultiple) { 39105304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 39205304565SCedric Chaumont goto out; 39305304565SCedric Chaumont } 39405304565SCedric Chaumont 39505304565SCedric Chaumont if (!operationSize) { 39605304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 39705304565SCedric Chaumont goto out; 39805304565SCedric Chaumont } 39905304565SCedric Chaumont 40005304565SCedric Chaumont num_of_keys = (*operationSize-sizeof(TEE_OperationInfoMultiple))/ 40105304565SCedric Chaumont sizeof(TEE_OperationInfoKey); 40205304565SCedric Chaumont 40305304565SCedric Chaumont if (num_of_keys > 2) { 40405304565SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 40505304565SCedric Chaumont goto out; 40605304565SCedric Chaumont } 40705304565SCedric Chaumont 40805304565SCedric Chaumont /* Two keys flag (TEE_ALG_AES_XTS only) */ 40905304565SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 41005304565SCedric Chaumont 0 && 41105304565SCedric Chaumont (num_of_keys != 2)) { 41205304565SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 41305304565SCedric Chaumont goto out; 41405304565SCedric Chaumont } 41505304565SCedric Chaumont 41605304565SCedric Chaumont /* Clear */ 41705304565SCedric Chaumont for (n = 0; n < num_of_keys; n++) { 41805304565SCedric Chaumont operationInfoMultiple->keyInformation[n].keySize = 0; 41905304565SCedric Chaumont operationInfoMultiple->keyInformation[n].requiredKeyUsage = 0; 42005304565SCedric Chaumont } 42105304565SCedric Chaumont 42205304565SCedric Chaumont if (num_of_keys == 2) { 42305304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key2, &key_info2); 42405304565SCedric Chaumont /* Key2 is not a valid handle */ 42505304565SCedric Chaumont if (res != TEE_SUCCESS) 42605304565SCedric Chaumont goto out; 42705304565SCedric Chaumont 42805304565SCedric Chaumont operationInfoMultiple->keyInformation[1].keySize = 42905304565SCedric Chaumont key_info2.keySize; 43005304565SCedric Chaumont operationInfoMultiple->keyInformation[1].requiredKeyUsage = 43105304565SCedric Chaumont operation->info.requiredKeyUsage; 43205304565SCedric Chaumont } 43305304565SCedric Chaumont 43405304565SCedric Chaumont if (num_of_keys >= 1) { 43505304565SCedric Chaumont res = TEE_GetObjectInfo1(operation->key1, &key_info1); 43605304565SCedric Chaumont /* Key1 is not a valid handle */ 43705304565SCedric Chaumont if (res != TEE_SUCCESS) { 43805304565SCedric Chaumont if (num_of_keys == 2) { 43905304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 44005304565SCedric Chaumont keySize = 0; 44105304565SCedric Chaumont operationInfoMultiple->keyInformation[1]. 44205304565SCedric Chaumont requiredKeyUsage = 0; 44305304565SCedric Chaumont } 44405304565SCedric Chaumont goto out; 44505304565SCedric Chaumont } 44605304565SCedric Chaumont 44705304565SCedric Chaumont operationInfoMultiple->keyInformation[0].keySize = 44805304565SCedric Chaumont key_info1.keySize; 44905304565SCedric Chaumont operationInfoMultiple->keyInformation[0].requiredKeyUsage = 45005304565SCedric Chaumont operation->info.requiredKeyUsage; 45105304565SCedric Chaumont } 45205304565SCedric Chaumont 45305304565SCedric Chaumont /* No key */ 45405304565SCedric Chaumont operationInfoMultiple->algorithm = operation->info.algorithm; 45505304565SCedric Chaumont operationInfoMultiple->operationClass = operation->info.operationClass; 45605304565SCedric Chaumont operationInfoMultiple->mode = operation->info.mode; 45705304565SCedric Chaumont operationInfoMultiple->digestLength = operation->info.digestLength; 45805304565SCedric Chaumont operationInfoMultiple->maxKeySize = operation->info.maxKeySize; 45905304565SCedric Chaumont operationInfoMultiple->handleState = operation->info.handleState; 46005304565SCedric Chaumont operationInfoMultiple->operationState = operation->operationState; 46105304565SCedric Chaumont operationInfoMultiple->numberOfKeys = num_of_keys; 46205304565SCedric Chaumont 46305304565SCedric Chaumont out: 46405304565SCedric Chaumont if (res != TEE_SUCCESS && 46505304565SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 466b36311adSJerome Forissier TEE_Panic(res); 46705304565SCedric Chaumont 46805304565SCedric Chaumont return res; 46905304565SCedric Chaumont } 47005304565SCedric Chaumont 471b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation) 472b0104773SPascal Brand { 473b0104773SPascal Brand TEE_Result res; 474b0104773SPascal Brand 475b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 476b0104773SPascal Brand TEE_Panic(0); 477bf80076aSCedric Chaumont 478642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) 479bf80076aSCedric Chaumont TEE_Panic(0); 480bf80076aSCedric Chaumont 481642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 482642a1607SCedric Chaumont 483b0104773SPascal Brand if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 484b0104773SPascal Brand res = utee_hash_init(operation->state, NULL, 0); 485b0104773SPascal Brand if (res != TEE_SUCCESS) 486b0104773SPascal Brand TEE_Panic(res); 48705304565SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 48805304565SCedric Chaumont } else { 489b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 490b0104773SPascal Brand } 49105304565SCedric Chaumont } 492b0104773SPascal Brand 493b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, 494b0104773SPascal Brand TEE_ObjectHandle key) 495b0104773SPascal Brand { 4967583c59eSCedric Chaumont TEE_Result res; 497b0104773SPascal Brand uint32_t key_size = 0; 498b0104773SPascal Brand TEE_ObjectInfo key_info; 499b0104773SPascal Brand 500a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 501a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 502a57c1e2eSCedric Chaumont goto out; 503a57c1e2eSCedric Chaumont } 504a57c1e2eSCedric Chaumont 505642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 506642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 507642a1607SCedric Chaumont goto out; 508642a1607SCedric Chaumont } 509642a1607SCedric Chaumont 510a57c1e2eSCedric Chaumont if (key == TEE_HANDLE_NULL) { 511a57c1e2eSCedric Chaumont /* Operation key cleared */ 512a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 513a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 514a57c1e2eSCedric Chaumont goto out; 515a57c1e2eSCedric Chaumont } 516a57c1e2eSCedric Chaumont 517a57c1e2eSCedric Chaumont /* No key for digest operation */ 518a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 519a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 520a57c1e2eSCedric Chaumont goto out; 521a57c1e2eSCedric Chaumont } 522a57c1e2eSCedric Chaumont 523a57c1e2eSCedric Chaumont /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ 524a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 525a57c1e2eSCedric Chaumont 0) { 526a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 527a57c1e2eSCedric Chaumont goto out; 528a57c1e2eSCedric Chaumont } 529a57c1e2eSCedric Chaumont 5307583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key, &key_info); 531a57c1e2eSCedric Chaumont /* Key is not a valid handle */ 5327583c59eSCedric Chaumont if (res != TEE_SUCCESS) 533a57c1e2eSCedric Chaumont goto out; 5347583c59eSCedric Chaumont 535b0104773SPascal Brand /* Supplied key has to meet required usage */ 536b0104773SPascal Brand if ((key_info.objectUsage & operation->info.requiredKeyUsage) != 537b0104773SPascal Brand operation->info.requiredKeyUsage) { 538a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 539a57c1e2eSCedric Chaumont goto out; 540b0104773SPascal Brand } 541b0104773SPascal Brand 542a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info.keySize) { 543a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 544a57c1e2eSCedric Chaumont goto out; 545a57c1e2eSCedric Chaumont } 546b0104773SPascal Brand 5477583c59eSCedric Chaumont key_size = key_info.keySize; 548b0104773SPascal Brand 549b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 550b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 551b0104773SPascal Brand 5527583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key); 5537583c59eSCedric Chaumont if (res != TEE_SUCCESS) 554a57c1e2eSCedric Chaumont goto out; 5557583c59eSCedric Chaumont 556b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 557b0104773SPascal Brand 558b0104773SPascal Brand operation->info.keySize = key_size; 559b0104773SPascal Brand 5607583c59eSCedric Chaumont out: 561a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 562a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 563a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 564b36311adSJerome Forissier TEE_Panic(res); 565a57c1e2eSCedric Chaumont 566a57c1e2eSCedric Chaumont return res; 567b0104773SPascal Brand } 568b0104773SPascal Brand 569b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, 570b0104773SPascal Brand TEE_ObjectHandle key1, TEE_ObjectHandle key2) 571b0104773SPascal Brand { 5727583c59eSCedric Chaumont TEE_Result res; 573b0104773SPascal Brand uint32_t key_size = 0; 574b0104773SPascal Brand TEE_ObjectInfo key_info1; 575b0104773SPascal Brand TEE_ObjectInfo key_info2; 576b0104773SPascal Brand 577a57c1e2eSCedric Chaumont if (operation == TEE_HANDLE_NULL) { 578a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 579a57c1e2eSCedric Chaumont goto out; 580a57c1e2eSCedric Chaumont } 581a57c1e2eSCedric Chaumont 582642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 583642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 584642a1607SCedric Chaumont goto out; 585642a1607SCedric Chaumont } 586642a1607SCedric Chaumont 587a57c1e2eSCedric Chaumont /* 588a57c1e2eSCedric Chaumont * Key1/Key2 and/or are not initialized and 589a57c1e2eSCedric Chaumont * Either both keys are NULL or both are not NULL 590a57c1e2eSCedric Chaumont */ 591a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL || key2 == TEE_HANDLE_NULL) { 592a57c1e2eSCedric Chaumont /* Clear operation key1 (if needed) */ 593a57c1e2eSCedric Chaumont if (key1 == TEE_HANDLE_NULL) 594a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key1); 595a57c1e2eSCedric Chaumont /* Clear operation key2 (if needed) */ 596a57c1e2eSCedric Chaumont if (key2 == TEE_HANDLE_NULL) 597a57c1e2eSCedric Chaumont TEE_ResetTransientObject(operation->key2); 598a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 599a57c1e2eSCedric Chaumont goto out; 600a57c1e2eSCedric Chaumont } 601a57c1e2eSCedric Chaumont 602a57c1e2eSCedric Chaumont /* No key for digest operation */ 603a57c1e2eSCedric Chaumont if (operation->info.operationClass == TEE_OPERATION_DIGEST) { 604a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 605a57c1e2eSCedric Chaumont goto out; 606a57c1e2eSCedric Chaumont } 607a57c1e2eSCedric Chaumont 608a57c1e2eSCedric Chaumont /* Two keys flag expected (TEE_ALG_AES_XTS only) */ 609a57c1e2eSCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 610a57c1e2eSCedric Chaumont 0) { 611a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 612a57c1e2eSCedric Chaumont goto out; 613a57c1e2eSCedric Chaumont } 614a57c1e2eSCedric Chaumont 6157583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key1, &key_info1); 616a57c1e2eSCedric Chaumont /* Key1 is not a valid handle */ 6177583c59eSCedric Chaumont if (res != TEE_SUCCESS) 618a57c1e2eSCedric Chaumont goto out; 6197583c59eSCedric Chaumont 620b0104773SPascal Brand /* Supplied key has to meet required usage */ 621b0104773SPascal Brand if ((key_info1.objectUsage & operation->info. 622b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 623a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 624a57c1e2eSCedric Chaumont goto out; 625b0104773SPascal Brand } 626b0104773SPascal Brand 6277583c59eSCedric Chaumont res = TEE_GetObjectInfo1(key2, &key_info2); 628a57c1e2eSCedric Chaumont /* Key2 is not a valid handle */ 6297583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6307583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6317583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 632a57c1e2eSCedric Chaumont goto out; 6337583c59eSCedric Chaumont } 6347583c59eSCedric Chaumont 635b0104773SPascal Brand /* Supplied key has to meet required usage */ 636b0104773SPascal Brand if ((key_info2.objectUsage & operation->info. 637b0104773SPascal Brand requiredKeyUsage) != operation->info.requiredKeyUsage) { 638a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 639a57c1e2eSCedric Chaumont goto out; 640b0104773SPascal Brand } 641b0104773SPascal Brand 642b0104773SPascal Brand /* 643b0104773SPascal Brand * AES-XTS (the only multi key algorithm supported, requires the 644b0104773SPascal Brand * keys to be of equal size. 645b0104773SPascal Brand */ 646b0104773SPascal Brand if (operation->info.algorithm == TEE_ALG_AES_XTS && 647a57c1e2eSCedric Chaumont key_info1.keySize != key_info2.keySize) { 648a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 649a57c1e2eSCedric Chaumont goto out; 650b0104773SPascal Brand 651a57c1e2eSCedric Chaumont } 652a57c1e2eSCedric Chaumont 653a57c1e2eSCedric Chaumont if (operation->info.maxKeySize < key_info1.keySize) { 654a57c1e2eSCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 655a57c1e2eSCedric Chaumont goto out; 656a57c1e2eSCedric Chaumont } 657b0104773SPascal Brand 658b0104773SPascal Brand /* 659b0104773SPascal Brand * Odd that only the size of one key should be reported while 660b0104773SPascal Brand * size of two key are used when allocating the operation. 661b0104773SPascal Brand */ 6627583c59eSCedric Chaumont key_size = key_info1.keySize; 663b0104773SPascal Brand 664b0104773SPascal Brand TEE_ResetTransientObject(operation->key1); 665b0104773SPascal Brand TEE_ResetTransientObject(operation->key2); 666b0104773SPascal Brand operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; 667b0104773SPascal Brand 6687583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key1, key1); 6697583c59eSCedric Chaumont if (res != TEE_SUCCESS) 670a57c1e2eSCedric Chaumont goto out; 6717583c59eSCedric Chaumont 6727583c59eSCedric Chaumont res = TEE_CopyObjectAttributes1(operation->key2, key2); 6737583c59eSCedric Chaumont if (res != TEE_SUCCESS) { 6747583c59eSCedric Chaumont if (res == TEE_ERROR_CORRUPT_OBJECT) 6757583c59eSCedric Chaumont res = TEE_ERROR_CORRUPT_OBJECT_2; 676a57c1e2eSCedric Chaumont goto out; 6777583c59eSCedric Chaumont } 6787583c59eSCedric Chaumont 679b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; 680b0104773SPascal Brand 681b0104773SPascal Brand operation->info.keySize = key_size; 682b0104773SPascal Brand 6837583c59eSCedric Chaumont out: 684a57c1e2eSCedric Chaumont if (res != TEE_SUCCESS && 685a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT && 686a57c1e2eSCedric Chaumont res != TEE_ERROR_CORRUPT_OBJECT_2 && 687a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE && 688a57c1e2eSCedric Chaumont res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) 689b36311adSJerome Forissier TEE_Panic(res); 690a57c1e2eSCedric Chaumont 691a57c1e2eSCedric Chaumont return res; 692b0104773SPascal Brand } 693b0104773SPascal Brand 694b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) 695b0104773SPascal Brand { 696b0104773SPascal Brand TEE_Result res; 697b0104773SPascal Brand 698b0104773SPascal Brand if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) 699b0104773SPascal Brand TEE_Panic(0); 700b0104773SPascal Brand if (dst_op->info.algorithm != src_op->info.algorithm) 701b0104773SPascal Brand TEE_Panic(0); 702b0104773SPascal Brand if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { 703b0104773SPascal Brand TEE_ObjectHandle key1 = TEE_HANDLE_NULL; 704b0104773SPascal Brand TEE_ObjectHandle key2 = TEE_HANDLE_NULL; 705b0104773SPascal Brand 706b0104773SPascal Brand if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { 707b0104773SPascal Brand key1 = src_op->key1; 708b0104773SPascal Brand key2 = src_op->key2; 709b0104773SPascal Brand } 710b0104773SPascal Brand 711b0104773SPascal Brand if ((src_op->info.handleState & 712b0104773SPascal Brand TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { 713b0104773SPascal Brand TEE_SetOperationKey(dst_op, key1); 714b0104773SPascal Brand } else { 715b0104773SPascal Brand TEE_SetOperationKey2(dst_op, key1, key2); 716b0104773SPascal Brand } 717b0104773SPascal Brand } 718b0104773SPascal Brand dst_op->info.handleState = src_op->info.handleState; 719b0104773SPascal Brand dst_op->info.keySize = src_op->info.keySize; 720642a1607SCedric Chaumont dst_op->operationState = src_op->operationState; 721b0104773SPascal Brand 722b0104773SPascal Brand if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || 723b0104773SPascal Brand dst_op->block_size != src_op->block_size) 724b0104773SPascal Brand TEE_Panic(0); 725b0104773SPascal Brand 726b0104773SPascal Brand if (dst_op->buffer != NULL) { 727b0104773SPascal Brand if (src_op->buffer == NULL) 728b0104773SPascal Brand TEE_Panic(0); 729b0104773SPascal Brand 730b0104773SPascal Brand memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs); 731b0104773SPascal Brand dst_op->buffer_offs = src_op->buffer_offs; 732b0104773SPascal Brand } else if (src_op->buffer != NULL) { 733b0104773SPascal Brand TEE_Panic(0); 734b0104773SPascal Brand } 735b0104773SPascal Brand 736b0104773SPascal Brand res = utee_cryp_state_copy(dst_op->state, src_op->state); 737b0104773SPascal Brand if (res != TEE_SUCCESS) 738b0104773SPascal Brand TEE_Panic(res); 739b0104773SPascal Brand } 740b0104773SPascal Brand 741b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */ 742b0104773SPascal Brand 7438f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV, 7446d15db08SJerome Forissier uint32_t IVLen) 7456d15db08SJerome Forissier { 7466d15db08SJerome Forissier TEE_Result res; 7476d15db08SJerome Forissier 7486d15db08SJerome Forissier /* 7496d15db08SJerome Forissier * Note : IV and IVLen are never used in current implementation 7506d15db08SJerome Forissier * This is why coherent values of IV and IVLen are not checked 7516d15db08SJerome Forissier */ 7526d15db08SJerome Forissier res = utee_hash_init(operation->state, IV, IVLen); 7536d15db08SJerome Forissier if (res != TEE_SUCCESS) 7546d15db08SJerome Forissier TEE_Panic(res); 7556d15db08SJerome Forissier operation->buffer_offs = 0; 7566d15db08SJerome Forissier operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 7576d15db08SJerome Forissier } 7586d15db08SJerome Forissier 759b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation, 7608f07fe6fSJerome Forissier const void *chunk, uint32_t chunkSize) 761b0104773SPascal Brand { 76273d6c3baSJoakim Bech TEE_Result res = TEE_ERROR_GENERIC; 763b0104773SPascal Brand 76473d6c3baSJoakim Bech if (operation == TEE_HANDLE_NULL || 76573d6c3baSJoakim Bech operation->info.operationClass != TEE_OPERATION_DIGEST) 766b0104773SPascal Brand TEE_Panic(0); 76773d6c3baSJoakim Bech 768642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 769642a1607SCedric Chaumont 770b0104773SPascal Brand res = utee_hash_update(operation->state, chunk, chunkSize); 771b0104773SPascal Brand if (res != TEE_SUCCESS) 772b0104773SPascal Brand TEE_Panic(res); 773b0104773SPascal Brand } 774b0104773SPascal Brand 7758f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, 77679a3c601SCedric Chaumont uint32_t chunkLen, void *hash, uint32_t *hashLen) 777b0104773SPascal Brand { 77887c2f6b6SCedric Chaumont TEE_Result res; 779e86f1266SJens Wiklander uint64_t hl; 78087c2f6b6SCedric Chaumont 78187c2f6b6SCedric Chaumont if ((operation == TEE_HANDLE_NULL) || 78287c2f6b6SCedric Chaumont (!chunk && chunkLen) || 78387c2f6b6SCedric Chaumont !hash || 78487c2f6b6SCedric Chaumont !hashLen || 78587c2f6b6SCedric Chaumont (operation->info.operationClass != TEE_OPERATION_DIGEST)) { 78687c2f6b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 78787c2f6b6SCedric Chaumont goto out; 78887c2f6b6SCedric Chaumont } 78987c2f6b6SCedric Chaumont 790e86f1266SJens Wiklander hl = *hashLen; 791e86f1266SJens Wiklander res = utee_hash_final(operation->state, chunk, chunkLen, hash, &hl); 792e86f1266SJens Wiklander *hashLen = hl; 7936d15db08SJerome Forissier if (res != TEE_SUCCESS) 7946d15db08SJerome Forissier goto out; 7956d15db08SJerome Forissier 7966d15db08SJerome Forissier /* Reset operation state */ 7976d15db08SJerome Forissier init_hash_operation(operation, NULL, 0); 79887c2f6b6SCedric Chaumont 799642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 800642a1607SCedric Chaumont 80187c2f6b6SCedric Chaumont out: 80287c2f6b6SCedric Chaumont if (res != TEE_SUCCESS && 80387c2f6b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 804b36311adSJerome Forissier TEE_Panic(res); 80573d6c3baSJoakim Bech 80687c2f6b6SCedric Chaumont return res; 807b0104773SPascal Brand } 808b0104773SPascal Brand 809b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */ 810b0104773SPascal Brand 8118f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, 8128f07fe6fSJerome Forissier uint32_t IVLen) 813b0104773SPascal Brand { 814b0104773SPascal Brand TEE_Result res; 815b0104773SPascal Brand 816b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 817b0104773SPascal Brand TEE_Panic(0); 818642a1607SCedric Chaumont 819b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_CIPHER) 820b0104773SPascal Brand TEE_Panic(0); 821642a1607SCedric Chaumont 822642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 823642a1607SCedric Chaumont !(operation->key1)) 824642a1607SCedric Chaumont TEE_Panic(0); 825642a1607SCedric Chaumont 826642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 827642a1607SCedric Chaumont TEE_ResetOperation(operation); 828642a1607SCedric Chaumont 829642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 830642a1607SCedric Chaumont 831b0104773SPascal Brand res = utee_cipher_init(operation->state, IV, IVLen); 832b0104773SPascal Brand if (res != TEE_SUCCESS) 833b0104773SPascal Brand TEE_Panic(res); 834642a1607SCedric Chaumont 835b0104773SPascal Brand operation->buffer_offs = 0; 836b0104773SPascal Brand operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 837b0104773SPascal Brand } 838b0104773SPascal Brand 839b0104773SPascal Brand static TEE_Result tee_buffer_update( 840b0104773SPascal Brand TEE_OperationHandle op, 841e86f1266SJens Wiklander TEE_Result(*update_func)(unsigned long state, const void *src, 842e86f1266SJens Wiklander size_t slen, void *dst, uint64_t *dlen), 843b0104773SPascal Brand const void *src_data, size_t src_len, 844e86f1266SJens Wiklander void *dest_data, uint64_t *dest_len) 845b0104773SPascal Brand { 846b0104773SPascal Brand TEE_Result res; 847b0104773SPascal Brand const uint8_t *src = src_data; 848b0104773SPascal Brand size_t slen = src_len; 849b0104773SPascal Brand uint8_t *dst = dest_data; 850b0104773SPascal Brand size_t dlen = *dest_len; 851b0104773SPascal Brand size_t acc_dlen = 0; 852e86f1266SJens Wiklander uint64_t tmp_dlen; 853b0104773SPascal Brand size_t l; 854b0104773SPascal Brand size_t buffer_size; 855d3588802SPascal Brand size_t buffer_left; 856b0104773SPascal Brand 857090268f5SJens Wiklander if (!src) { 858090268f5SJens Wiklander if (slen) 859090268f5SJens Wiklander TEE_Panic(0); 860090268f5SJens Wiklander goto out; 861090268f5SJens Wiklander } 862090268f5SJens Wiklander 863d3588802SPascal Brand if (op->buffer_two_blocks) { 864b0104773SPascal Brand buffer_size = op->block_size * 2; 865d3588802SPascal Brand buffer_left = 1; 866d3588802SPascal Brand } else { 867b0104773SPascal Brand buffer_size = op->block_size; 868d3588802SPascal Brand buffer_left = 0; 869d3588802SPascal Brand } 870b0104773SPascal Brand 871b0104773SPascal Brand if (op->buffer_offs > 0) { 872b0104773SPascal Brand /* Fill up complete block */ 873b0104773SPascal Brand if (op->buffer_offs < op->block_size) 874b0104773SPascal Brand l = MIN(slen, op->block_size - op->buffer_offs); 875b0104773SPascal Brand else 876b0104773SPascal Brand l = MIN(slen, buffer_size - op->buffer_offs); 877b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, l); 878b0104773SPascal Brand op->buffer_offs += l; 879b0104773SPascal Brand src += l; 880b0104773SPascal Brand slen -= l; 881b0104773SPascal Brand if ((op->buffer_offs % op->block_size) != 0) 882b0104773SPascal Brand goto out; /* Nothing left to do */ 883b0104773SPascal Brand } 884b0104773SPascal Brand 885b0104773SPascal Brand /* If we can feed from buffer */ 886d3588802SPascal Brand if ((op->buffer_offs > 0) && 887d3588802SPascal Brand ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) { 8882ff3fdbbSPascal Brand l = ROUNDUP(op->buffer_offs + slen - buffer_size, 889b0104773SPascal Brand op->block_size); 890b0104773SPascal Brand l = MIN(op->buffer_offs, l); 891b0104773SPascal Brand tmp_dlen = dlen; 892b0104773SPascal Brand res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); 893b0104773SPascal Brand if (res != TEE_SUCCESS) 894b0104773SPascal Brand TEE_Panic(res); 895b0104773SPascal Brand dst += tmp_dlen; 896b0104773SPascal Brand dlen -= tmp_dlen; 897b0104773SPascal Brand acc_dlen += tmp_dlen; 898b0104773SPascal Brand op->buffer_offs -= l; 899b0104773SPascal Brand if (op->buffer_offs > 0) { 900b0104773SPascal Brand /* 901b0104773SPascal Brand * Slen is small enough to be contained in rest buffer. 902b0104773SPascal Brand */ 903b0104773SPascal Brand memcpy(op->buffer, op->buffer + l, buffer_size - l); 904b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 905b0104773SPascal Brand op->buffer_offs += slen; 906b0104773SPascal Brand goto out; /* Nothing left to do */ 907b0104773SPascal Brand } 908b0104773SPascal Brand } 909b0104773SPascal Brand 910d3588802SPascal Brand if (slen >= (buffer_size + buffer_left)) { 911b0104773SPascal Brand /* Buffer is empty, feed as much as possible from src */ 912bf7a587fSJerome Forissier if (op->info.algorithm == TEE_ALG_AES_CTS) 913b1ecda78SJerome Forissier l = ROUNDUP(slen - buffer_size, op->block_size); 914bf7a587fSJerome Forissier else 915bf7a587fSJerome Forissier l = ROUNDUP(slen - buffer_size + 1, op->block_size); 916b0104773SPascal Brand 917b0104773SPascal Brand tmp_dlen = dlen; 918b0104773SPascal Brand res = update_func(op->state, src, l, dst, &tmp_dlen); 919b0104773SPascal Brand if (res != TEE_SUCCESS) 920b0104773SPascal Brand TEE_Panic(res); 921b0104773SPascal Brand src += l; 922b0104773SPascal Brand slen -= l; 923b0104773SPascal Brand dst += tmp_dlen; 924b0104773SPascal Brand dlen -= tmp_dlen; 925b0104773SPascal Brand acc_dlen += tmp_dlen; 926b0104773SPascal Brand } 927b0104773SPascal Brand 928b0104773SPascal Brand /* Slen is small enough to be contained in buffer. */ 929b0104773SPascal Brand memcpy(op->buffer + op->buffer_offs, src, slen); 930b0104773SPascal Brand op->buffer_offs += slen; 931b0104773SPascal Brand 932b0104773SPascal Brand out: 933b0104773SPascal Brand *dest_len = acc_dlen; 934b0104773SPascal Brand return TEE_SUCCESS; 935b0104773SPascal Brand } 936b0104773SPascal Brand 9378f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, 93879a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 939b0104773SPascal Brand { 940dea1f2b6SCedric Chaumont TEE_Result res; 941b0104773SPascal Brand size_t req_dlen; 942e86f1266SJens Wiklander uint64_t dl; 943b0104773SPascal Brand 944642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 945dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 946dea1f2b6SCedric Chaumont destLen == NULL || 947dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 948dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 949dea1f2b6SCedric Chaumont goto out; 950dea1f2b6SCedric Chaumont } 951dea1f2b6SCedric Chaumont 952642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 953dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 954dea1f2b6SCedric Chaumont goto out; 955dea1f2b6SCedric Chaumont } 956dea1f2b6SCedric Chaumont 957642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 958642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 959642a1607SCedric Chaumont goto out; 960642a1607SCedric Chaumont } 961642a1607SCedric Chaumont 962642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 963dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 964dea1f2b6SCedric Chaumont goto out; 965dea1f2b6SCedric Chaumont } 966b0104773SPascal Brand 967e32c5ddfSJerome Forissier if (!srcData && !srcLen) { 968090268f5SJens Wiklander *destLen = 0; 969e32c5ddfSJerome Forissier res = TEE_SUCCESS; 970e32c5ddfSJerome Forissier goto out; 971e32c5ddfSJerome Forissier } 972e32c5ddfSJerome Forissier 973b0104773SPascal Brand /* Calculate required dlen */ 97457aabac5SBogdan Liulko if (operation->block_size > 1) { 97557aabac5SBogdan Liulko req_dlen = ((operation->buffer_offs + srcLen) / 97657aabac5SBogdan Liulko operation->block_size) * operation->block_size; 97757aabac5SBogdan Liulko } else { 97857aabac5SBogdan Liulko req_dlen = srcLen; 97957aabac5SBogdan Liulko } 980642a1607SCedric Chaumont if (operation->buffer_two_blocks) { 981642a1607SCedric Chaumont if (req_dlen > operation->block_size * 2) 982642a1607SCedric Chaumont req_dlen -= operation->block_size * 2; 983b0104773SPascal Brand else 984b0104773SPascal Brand req_dlen = 0; 985b0104773SPascal Brand } 986b0104773SPascal Brand /* 987b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 988b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 989b0104773SPascal Brand * can't restore sync with this API. 990b0104773SPascal Brand */ 991b0104773SPascal Brand if (*destLen < req_dlen) { 992b0104773SPascal Brand *destLen = req_dlen; 993dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 994dea1f2b6SCedric Chaumont goto out; 995b0104773SPascal Brand } 996b0104773SPascal Brand 997e86f1266SJens Wiklander dl = *destLen; 99857aabac5SBogdan Liulko if (operation->block_size > 1) { 99957aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, srcData, 100057aabac5SBogdan Liulko srcLen, destData, &dl); 100157aabac5SBogdan Liulko } else { 100257aabac5SBogdan Liulko if (srcLen > 0) { 100357aabac5SBogdan Liulko res = utee_cipher_update(operation->state, srcData, 100457aabac5SBogdan Liulko srcLen, destData, &dl); 100557aabac5SBogdan Liulko } else { 100657aabac5SBogdan Liulko res = TEE_SUCCESS; 100757aabac5SBogdan Liulko dl = 0; 100857aabac5SBogdan Liulko } 100957aabac5SBogdan Liulko } 1010e86f1266SJens Wiklander *destLen = dl; 1011b0104773SPascal Brand 1012dea1f2b6SCedric Chaumont out: 1013dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1014dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1015b36311adSJerome Forissier TEE_Panic(res); 1016dea1f2b6SCedric Chaumont 1017dea1f2b6SCedric Chaumont return res; 1018b0104773SPascal Brand } 1019b0104773SPascal Brand 1020642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, 10218f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 10228f07fe6fSJerome Forissier void *destData, uint32_t *destLen) 1023b0104773SPascal Brand { 1024b0104773SPascal Brand TEE_Result res; 1025b0104773SPascal Brand uint8_t *dst = destData; 1026b0104773SPascal Brand size_t acc_dlen = 0; 1027e86f1266SJens Wiklander uint64_t tmp_dlen; 1028b0104773SPascal Brand size_t req_dlen; 1029b0104773SPascal Brand 1030642a1607SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1031dea1f2b6SCedric Chaumont (srcData == NULL && srcLen != 0) || 1032dea1f2b6SCedric Chaumont destLen == NULL || 1033dea1f2b6SCedric Chaumont (destData == NULL && *destLen != 0)) { 1034dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1035dea1f2b6SCedric Chaumont goto out; 1036dea1f2b6SCedric Chaumont } 1037dea1f2b6SCedric Chaumont 1038642a1607SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_CIPHER) { 1039dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1040dea1f2b6SCedric Chaumont goto out; 1041dea1f2b6SCedric Chaumont } 1042dea1f2b6SCedric Chaumont 1043642a1607SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1044642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1045642a1607SCedric Chaumont goto out; 1046642a1607SCedric Chaumont } 1047642a1607SCedric Chaumont 1048642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1049dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1050dea1f2b6SCedric Chaumont goto out; 1051dea1f2b6SCedric Chaumont } 1052b0104773SPascal Brand 1053b0104773SPascal Brand /* 1054b0104773SPascal Brand * Check that the final block doesn't require padding for those 1055b0104773SPascal Brand * algorithms that requires client to supply padding. 1056b0104773SPascal Brand */ 1057642a1607SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || 1058642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || 1059642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || 1060642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || 1061642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || 1062642a1607SCedric Chaumont operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD) { 1063642a1607SCedric Chaumont if (((operation->buffer_offs + srcLen) % operation->block_size) 1064642a1607SCedric Chaumont != 0) { 1065dea1f2b6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1066dea1f2b6SCedric Chaumont goto out; 1067dea1f2b6SCedric Chaumont } 1068b0104773SPascal Brand } 1069b0104773SPascal Brand 1070b0104773SPascal Brand /* 1071b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1072b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1073b0104773SPascal Brand * can't restore sync with this API. 1074b0104773SPascal Brand */ 107557aabac5SBogdan Liulko if (operation->block_size > 1) { 1076642a1607SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 107757aabac5SBogdan Liulko } else { 107857aabac5SBogdan Liulko req_dlen = srcLen; 107957aabac5SBogdan Liulko } 1080b0104773SPascal Brand if (*destLen < req_dlen) { 1081b0104773SPascal Brand *destLen = req_dlen; 1082dea1f2b6SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1083dea1f2b6SCedric Chaumont goto out; 1084b0104773SPascal Brand } 1085b0104773SPascal Brand 1086b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 108757aabac5SBogdan Liulko if (operation->block_size > 1) { 108857aabac5SBogdan Liulko res = tee_buffer_update(operation, utee_cipher_update, 108957aabac5SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1090dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS) 1091dea1f2b6SCedric Chaumont goto out; 1092dea1f2b6SCedric Chaumont 1093b0104773SPascal Brand dst += tmp_dlen; 1094b0104773SPascal Brand acc_dlen += tmp_dlen; 1095b0104773SPascal Brand 1096b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1097642a1607SCedric Chaumont res = utee_cipher_final(operation->state, operation->buffer, 1098642a1607SCedric Chaumont operation->buffer_offs, dst, &tmp_dlen); 109957aabac5SBogdan Liulko } else { 110057aabac5SBogdan Liulko res = utee_cipher_final(operation->state, srcData, 110157aabac5SBogdan Liulko srcLen, dst, &tmp_dlen); 110257aabac5SBogdan Liulko } 1103b0104773SPascal Brand if (res != TEE_SUCCESS) 1104dea1f2b6SCedric Chaumont goto out; 1105dea1f2b6SCedric Chaumont 1106b0104773SPascal Brand acc_dlen += tmp_dlen; 1107b0104773SPascal Brand *destLen = acc_dlen; 1108dea1f2b6SCedric Chaumont 1109642a1607SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1110642a1607SCedric Chaumont 1111642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1112642a1607SCedric Chaumont 1113dea1f2b6SCedric Chaumont out: 1114dea1f2b6SCedric Chaumont if (res != TEE_SUCCESS && 1115dea1f2b6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1116b36311adSJerome Forissier TEE_Panic(res); 1117dea1f2b6SCedric Chaumont 1118dea1f2b6SCedric Chaumont return res; 1119b0104773SPascal Brand } 1120b0104773SPascal Brand 1121b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */ 1122b0104773SPascal Brand 11238f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) 1124b0104773SPascal Brand { 1125b0104773SPascal Brand if (operation == TEE_HANDLE_NULL) 1126b0104773SPascal Brand TEE_Panic(0); 1127642a1607SCedric Chaumont 1128b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_MAC) 1129b0104773SPascal Brand TEE_Panic(0); 1130642a1607SCedric Chaumont 1131642a1607SCedric Chaumont if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || 1132642a1607SCedric Chaumont !(operation->key1)) 1133642a1607SCedric Chaumont TEE_Panic(0); 1134642a1607SCedric Chaumont 1135642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) 1136642a1607SCedric Chaumont TEE_ResetOperation(operation); 1137642a1607SCedric Chaumont 1138642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1139642a1607SCedric Chaumont 11406d15db08SJerome Forissier init_hash_operation(operation, IV, IVLen); 1141b0104773SPascal Brand } 1142b0104773SPascal Brand 11438f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, 114428e0efc6SCedric Chaumont uint32_t chunkSize) 1145b0104773SPascal Brand { 1146b0104773SPascal Brand TEE_Result res; 1147b0104773SPascal Brand 114828e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) 1149b0104773SPascal Brand TEE_Panic(0); 1150642a1607SCedric Chaumont 115128e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) 1152b0104773SPascal Brand TEE_Panic(0); 1153642a1607SCedric Chaumont 115428e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1155b0104773SPascal Brand TEE_Panic(0); 1156b0104773SPascal Brand 1157642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) 1158642a1607SCedric Chaumont TEE_Panic(0); 1159642a1607SCedric Chaumont 116028e0efc6SCedric Chaumont res = utee_hash_update(operation->state, chunk, chunkSize); 1161b0104773SPascal Brand if (res != TEE_SUCCESS) 1162b0104773SPascal Brand TEE_Panic(res); 1163b0104773SPascal Brand } 1164b0104773SPascal Brand 116528e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, 11668f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 116779a3c601SCedric Chaumont void *mac, uint32_t *macLen) 1168b0104773SPascal Brand { 1169b0104773SPascal Brand TEE_Result res; 1170e86f1266SJens Wiklander uint64_t ml; 1171b0104773SPascal Brand 117228e0efc6SCedric Chaumont if (operation == TEE_HANDLE_NULL || 117328e0efc6SCedric Chaumont (message == NULL && messageLen != 0) || 117428e0efc6SCedric Chaumont mac == NULL || 117528e0efc6SCedric Chaumont macLen == NULL) { 117628e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 117728e0efc6SCedric Chaumont goto out; 117828e0efc6SCedric Chaumont } 1179b0104773SPascal Brand 118028e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 118128e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 118228e0efc6SCedric Chaumont goto out; 118328e0efc6SCedric Chaumont } 118428e0efc6SCedric Chaumont 118528e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 118628e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 118728e0efc6SCedric Chaumont goto out; 118828e0efc6SCedric Chaumont } 118928e0efc6SCedric Chaumont 1190642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1191642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1192642a1607SCedric Chaumont goto out; 1193642a1607SCedric Chaumont } 1194642a1607SCedric Chaumont 1195e86f1266SJens Wiklander ml = *macLen; 1196e86f1266SJens Wiklander res = utee_hash_final(operation->state, message, messageLen, mac, &ml); 1197e86f1266SJens Wiklander *macLen = ml; 119828e0efc6SCedric Chaumont if (res != TEE_SUCCESS) 119928e0efc6SCedric Chaumont goto out; 120028e0efc6SCedric Chaumont 120128e0efc6SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 120228e0efc6SCedric Chaumont 1203642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1204642a1607SCedric Chaumont 120528e0efc6SCedric Chaumont out: 120628e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 120728e0efc6SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 120828e0efc6SCedric Chaumont TEE_Panic(res); 120928e0efc6SCedric Chaumont 1210b0104773SPascal Brand return res; 1211b0104773SPascal Brand } 1212b0104773SPascal Brand 1213b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, 12148f07fe6fSJerome Forissier const void *message, uint32_t messageLen, 12158f07fe6fSJerome Forissier const void *mac, uint32_t macLen) 1216b0104773SPascal Brand { 1217b0104773SPascal Brand TEE_Result res; 1218b0104773SPascal Brand uint8_t computed_mac[TEE_MAX_HASH_SIZE]; 12197f74c64aSPascal Brand uint32_t computed_mac_size = TEE_MAX_HASH_SIZE; 1220b0104773SPascal Brand 122128e0efc6SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_MAC) { 122228e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 122328e0efc6SCedric Chaumont goto out; 122428e0efc6SCedric Chaumont } 122528e0efc6SCedric Chaumont 122628e0efc6SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 122728e0efc6SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 122828e0efc6SCedric Chaumont goto out; 122928e0efc6SCedric Chaumont } 123028e0efc6SCedric Chaumont 1231642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { 1232642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1233642a1607SCedric Chaumont goto out; 1234642a1607SCedric Chaumont } 1235642a1607SCedric Chaumont 1236b0104773SPascal Brand res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, 1237b0104773SPascal Brand &computed_mac_size); 1238b0104773SPascal Brand if (res != TEE_SUCCESS) 123928e0efc6SCedric Chaumont goto out; 124028e0efc6SCedric Chaumont 124128e0efc6SCedric Chaumont if (computed_mac_size != macLen) { 124228e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 124328e0efc6SCedric Chaumont goto out; 124428e0efc6SCedric Chaumont } 124528e0efc6SCedric Chaumont 124628e0efc6SCedric Chaumont if (buf_compare_ct(mac, computed_mac, computed_mac_size) != 0) { 124728e0efc6SCedric Chaumont res = TEE_ERROR_MAC_INVALID; 124828e0efc6SCedric Chaumont goto out; 124928e0efc6SCedric Chaumont } 125028e0efc6SCedric Chaumont 1251642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1252642a1607SCedric Chaumont 125328e0efc6SCedric Chaumont out: 125428e0efc6SCedric Chaumont if (res != TEE_SUCCESS && 125528e0efc6SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 125628e0efc6SCedric Chaumont TEE_Panic(res); 125728e0efc6SCedric Chaumont 1258b0104773SPascal Brand return res; 1259b0104773SPascal Brand } 1260b0104773SPascal Brand 1261b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */ 1262b0104773SPascal Brand 12638f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, 126479a3c601SCedric Chaumont uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, 1265b0104773SPascal Brand uint32_t payloadLen) 1266b0104773SPascal Brand { 1267b0104773SPascal Brand TEE_Result res; 1268b0104773SPascal Brand 1269b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || nonce == NULL) { 1270b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1271b5816c88SCedric Chaumont goto out; 1272b5816c88SCedric Chaumont } 1273b5816c88SCedric Chaumont 1274b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1275b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1276b5816c88SCedric Chaumont goto out; 1277b5816c88SCedric Chaumont } 1278b0104773SPascal Brand 1279642a1607SCedric Chaumont if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { 1280642a1607SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1281642a1607SCedric Chaumont goto out; 1282642a1607SCedric Chaumont } 1283642a1607SCedric Chaumont 1284b0104773SPascal Brand /* 1285b0104773SPascal Brand * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core 1286b0104773SPascal Brand * in the implementation. But AES-GCM spec doesn't specify the tag len 1287b0104773SPascal Brand * according to the same principle so we have to check here instead to 1288b0104773SPascal Brand * be GP compliant. 1289b0104773SPascal Brand */ 1290b5816c88SCedric Chaumont if (operation->info.algorithm == TEE_ALG_AES_GCM) { 1291b0104773SPascal Brand /* 1292b0104773SPascal Brand * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 1293b0104773SPascal Brand */ 1294b5816c88SCedric Chaumont if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) { 1295b5816c88SCedric Chaumont res = TEE_ERROR_NOT_SUPPORTED; 1296b5816c88SCedric Chaumont goto out; 1297b5816c88SCedric Chaumont } 1298b0104773SPascal Brand } 1299b0104773SPascal Brand 1300b5816c88SCedric Chaumont res = utee_authenc_init(operation->state, nonce, nonceLen, 1301b5816c88SCedric Chaumont tagLen / 8, AADLen, payloadLen); 1302b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1303b5816c88SCedric Chaumont goto out; 1304b5816c88SCedric Chaumont 1305b5816c88SCedric Chaumont operation->ae_tag_len = tagLen / 8; 1306b5816c88SCedric Chaumont operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; 1307b5816c88SCedric Chaumont 1308b5816c88SCedric Chaumont out: 1309b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1310b5816c88SCedric Chaumont res != TEE_ERROR_NOT_SUPPORTED) 1311b0104773SPascal Brand TEE_Panic(res); 1312b5816c88SCedric Chaumont 1313b0104773SPascal Brand return res; 1314b0104773SPascal Brand } 1315b0104773SPascal Brand 13168f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, 131779a3c601SCedric Chaumont uint32_t AADdataLen) 1318b0104773SPascal Brand { 1319b0104773SPascal Brand TEE_Result res; 1320b0104773SPascal Brand 1321b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1322b5816c88SCedric Chaumont (AADdata == NULL && AADdataLen != 0)) 1323b0104773SPascal Brand TEE_Panic(0); 1324642a1607SCedric Chaumont 1325b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) 1326b0104773SPascal Brand TEE_Panic(0); 1327642a1607SCedric Chaumont 1328b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) 1329b0104773SPascal Brand TEE_Panic(0); 1330b0104773SPascal Brand 1331b5816c88SCedric Chaumont res = utee_authenc_update_aad(operation->state, AADdata, AADdataLen); 1332642a1607SCedric Chaumont 1333642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1334642a1607SCedric Chaumont 1335b0104773SPascal Brand if (res != TEE_SUCCESS) 1336b0104773SPascal Brand TEE_Panic(res); 1337b0104773SPascal Brand } 1338b0104773SPascal Brand 13398f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, 134079a3c601SCedric Chaumont uint32_t srcLen, void *destData, uint32_t *destLen) 1341b0104773SPascal Brand { 1342b5816c88SCedric Chaumont TEE_Result res; 1343b0104773SPascal Brand size_t req_dlen; 1344e86f1266SJens Wiklander uint64_t dl; 1345b0104773SPascal Brand 1346b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1347b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1348b5816c88SCedric Chaumont destLen == NULL || 1349b5816c88SCedric Chaumont (destData == NULL && *destLen != 0)) { 1350b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1351b5816c88SCedric Chaumont goto out; 1352b5816c88SCedric Chaumont } 1353b5816c88SCedric Chaumont 1354b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1355b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1356b5816c88SCedric Chaumont goto out; 1357b5816c88SCedric Chaumont } 1358b5816c88SCedric Chaumont 1359b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1360b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1361b5816c88SCedric Chaumont goto out; 1362b5816c88SCedric Chaumont } 1363b0104773SPascal Brand 1364827308b8SJerome Forissier if (!srcData && !srcLen) { 1365090268f5SJens Wiklander *destLen = 0; 1366827308b8SJerome Forissier res = TEE_SUCCESS; 1367827308b8SJerome Forissier goto out; 1368827308b8SJerome Forissier } 1369827308b8SJerome Forissier 1370b0104773SPascal Brand /* 1371b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1372b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1373b0104773SPascal Brand * can't restore sync with this API. 1374b0104773SPascal Brand */ 1375afc0c182SBogdan Liulko if (operation->block_size > 1) { 1376b5816c88SCedric Chaumont req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen, 1377b5816c88SCedric Chaumont operation->block_size); 1378afc0c182SBogdan Liulko } else { 1379afc0c182SBogdan Liulko req_dlen = srcLen; 1380afc0c182SBogdan Liulko } 1381afc0c182SBogdan Liulko 1382b0104773SPascal Brand if (*destLen < req_dlen) { 1383b0104773SPascal Brand *destLen = req_dlen; 1384b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1385b5816c88SCedric Chaumont goto out; 1386b0104773SPascal Brand } 1387b0104773SPascal Brand 1388e86f1266SJens Wiklander dl = *destLen; 1389afc0c182SBogdan Liulko if (operation->block_size > 1) { 1390afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1391afc0c182SBogdan Liulko srcData, srcLen, destData, &dl); 1392afc0c182SBogdan Liulko } else { 1393afc0c182SBogdan Liulko if (srcLen > 0) { 1394afc0c182SBogdan Liulko res = utee_authenc_update_payload(operation->state, 1395afc0c182SBogdan Liulko srcData, srcLen, 1396afc0c182SBogdan Liulko destData, &dl); 1397afc0c182SBogdan Liulko } else { 1398afc0c182SBogdan Liulko dl = 0; 1399afc0c182SBogdan Liulko res = TEE_SUCCESS; 1400afc0c182SBogdan Liulko } 1401afc0c182SBogdan Liulko } 1402afc0c182SBogdan Liulko if (res != TEE_SUCCESS) 1403afc0c182SBogdan Liulko goto out; 1404afc0c182SBogdan Liulko 1405e86f1266SJens Wiklander *destLen = dl; 1406b0104773SPascal Brand 1407642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_ACTIVE; 1408642a1607SCedric Chaumont 1409b5816c88SCedric Chaumont out: 1410b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1411b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1412b5816c88SCedric Chaumont TEE_Panic(res); 1413b5816c88SCedric Chaumont 1414b5816c88SCedric Chaumont return res; 1415b0104773SPascal Brand } 1416b0104773SPascal Brand 1417b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, 14188f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 141979a3c601SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 142079a3c601SCedric Chaumont uint32_t *tagLen) 1421b0104773SPascal Brand { 1422b0104773SPascal Brand TEE_Result res; 1423b0104773SPascal Brand uint8_t *dst = destData; 1424b0104773SPascal Brand size_t acc_dlen = 0; 1425e86f1266SJens Wiklander uint64_t tmp_dlen; 1426b0104773SPascal Brand size_t req_dlen; 1427e86f1266SJens Wiklander uint64_t tl; 1428b0104773SPascal Brand 1429b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1430b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1431b5816c88SCedric Chaumont destLen == NULL || 1432b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1433b5816c88SCedric Chaumont tag == NULL || tagLen == NULL) { 1434b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1435b5816c88SCedric Chaumont goto out; 1436b5816c88SCedric Chaumont } 1437b5816c88SCedric Chaumont 1438b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1439b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1440b5816c88SCedric Chaumont goto out; 1441b5816c88SCedric Chaumont } 1442b5816c88SCedric Chaumont 1443b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1444b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1445b5816c88SCedric Chaumont goto out; 1446b5816c88SCedric Chaumont } 1447b0104773SPascal Brand 1448b0104773SPascal Brand /* 1449b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1450b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1451b0104773SPascal Brand * can't restore sync with this API. 14522733280aSEtienne Carriere * 14532733280aSEtienne Carriere * Need to check this before update_payload since sync would be lost if 14542733280aSEtienne Carriere * we return short buffer after that. 1455b0104773SPascal Brand */ 14562733280aSEtienne Carriere res = TEE_ERROR_GENERIC; 14572733280aSEtienne Carriere 1458b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1459b0104773SPascal Brand if (*destLen < req_dlen) { 1460b0104773SPascal Brand *destLen = req_dlen; 1461b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1462b0104773SPascal Brand } 1463b0104773SPascal Brand 1464b5816c88SCedric Chaumont if (*tagLen < operation->ae_tag_len) { 1465b5816c88SCedric Chaumont *tagLen = operation->ae_tag_len; 1466b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1467b0104773SPascal Brand } 1468b0104773SPascal Brand 14692733280aSEtienne Carriere if (res == TEE_ERROR_SHORT_BUFFER) 14702733280aSEtienne Carriere goto out; 14712733280aSEtienne Carriere 1472afc0c182SBogdan Liulko tl = *tagLen; 1473b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1474afc0c182SBogdan Liulko if (operation->block_size > 1) { 1475afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1476afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1477b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1478b5816c88SCedric Chaumont goto out; 1479b5816c88SCedric Chaumont 1480b0104773SPascal Brand dst += tmp_dlen; 1481b0104773SPascal Brand acc_dlen += tmp_dlen; 1482b0104773SPascal Brand 1483b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1484afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, 1485afc0c182SBogdan Liulko operation->buffer, 1486afc0c182SBogdan Liulko operation->buffer_offs, dst, 1487afc0c182SBogdan Liulko &tmp_dlen, tag, &tl); 1488afc0c182SBogdan Liulko } else { 1489afc0c182SBogdan Liulko res = utee_authenc_enc_final(operation->state, srcData, 1490afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1491e86f1266SJens Wiklander tag, &tl); 1492afc0c182SBogdan Liulko } 1493e86f1266SJens Wiklander *tagLen = tl; 1494b0104773SPascal Brand if (res != TEE_SUCCESS) 1495b5816c88SCedric Chaumont goto out; 1496b0104773SPascal Brand 1497b5816c88SCedric Chaumont acc_dlen += tmp_dlen; 1498b0104773SPascal Brand *destLen = acc_dlen; 1499642a1607SCedric Chaumont 1500b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1501b5816c88SCedric Chaumont 1502642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1503642a1607SCedric Chaumont 1504b5816c88SCedric Chaumont out: 1505b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1506b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER) 1507b5816c88SCedric Chaumont TEE_Panic(res); 1508b0104773SPascal Brand 1509b0104773SPascal Brand return res; 1510b0104773SPascal Brand } 1511b0104773SPascal Brand 1512b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, 15138f07fe6fSJerome Forissier const void *srcData, uint32_t srcLen, 1514b5816c88SCedric Chaumont void *destData, uint32_t *destLen, void *tag, 151579a3c601SCedric Chaumont uint32_t tagLen) 1516b0104773SPascal Brand { 1517b0104773SPascal Brand TEE_Result res; 1518b0104773SPascal Brand uint8_t *dst = destData; 1519b0104773SPascal Brand size_t acc_dlen = 0; 1520e86f1266SJens Wiklander uint64_t tmp_dlen; 1521b0104773SPascal Brand size_t req_dlen; 1522b0104773SPascal Brand 1523b5816c88SCedric Chaumont if (operation == TEE_HANDLE_NULL || 1524b5816c88SCedric Chaumont (srcData == NULL && srcLen != 0) || 1525b5816c88SCedric Chaumont destLen == NULL || 1526b5816c88SCedric Chaumont (destData == NULL && *destLen != 0) || 1527b5816c88SCedric Chaumont (tag == NULL && tagLen != 0)) { 1528b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1529b5816c88SCedric Chaumont goto out; 1530b5816c88SCedric Chaumont } 1531b5816c88SCedric Chaumont 1532b5816c88SCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_AE) { 1533b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1534b5816c88SCedric Chaumont goto out; 1535b5816c88SCedric Chaumont } 1536b5816c88SCedric Chaumont 1537b5816c88SCedric Chaumont if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { 1538b5816c88SCedric Chaumont res = TEE_ERROR_BAD_PARAMETERS; 1539b5816c88SCedric Chaumont goto out; 1540b5816c88SCedric Chaumont } 1541b0104773SPascal Brand 1542b0104773SPascal Brand /* 1543b0104773SPascal Brand * Check that required destLen is big enough before starting to feed 1544b0104773SPascal Brand * data to the algorithm. Errors during feeding of data are fatal as we 1545b0104773SPascal Brand * can't restore sync with this API. 1546b0104773SPascal Brand */ 1547b5816c88SCedric Chaumont req_dlen = operation->buffer_offs + srcLen; 1548b0104773SPascal Brand if (*destLen < req_dlen) { 1549b0104773SPascal Brand *destLen = req_dlen; 1550b5816c88SCedric Chaumont res = TEE_ERROR_SHORT_BUFFER; 1551b5816c88SCedric Chaumont goto out; 1552b0104773SPascal Brand } 1553b0104773SPascal Brand 1554b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1555afc0c182SBogdan Liulko if (operation->block_size > 1) { 1556afc0c182SBogdan Liulko res = tee_buffer_update(operation, utee_authenc_update_payload, 1557afc0c182SBogdan Liulko srcData, srcLen, dst, &tmp_dlen); 1558b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1559b5816c88SCedric Chaumont goto out; 1560b5816c88SCedric Chaumont 1561b0104773SPascal Brand dst += tmp_dlen; 1562b0104773SPascal Brand acc_dlen += tmp_dlen; 1563b0104773SPascal Brand 1564b0104773SPascal Brand tmp_dlen = *destLen - acc_dlen; 1565afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, 1566afc0c182SBogdan Liulko operation->buffer, 1567afc0c182SBogdan Liulko operation->buffer_offs, dst, 1568afc0c182SBogdan Liulko &tmp_dlen, tag, tagLen); 1569afc0c182SBogdan Liulko } else { 1570afc0c182SBogdan Liulko res = utee_authenc_dec_final(operation->state, srcData, 1571afc0c182SBogdan Liulko srcLen, dst, &tmp_dlen, 1572b5816c88SCedric Chaumont tag, tagLen); 1573afc0c182SBogdan Liulko } 1574b5816c88SCedric Chaumont if (res != TEE_SUCCESS) 1575b5816c88SCedric Chaumont goto out; 1576b5816c88SCedric Chaumont 1577b0104773SPascal Brand /* Supplied tagLen should match what we initiated with */ 1578b5816c88SCedric Chaumont if (tagLen != operation->ae_tag_len) 1579b0104773SPascal Brand res = TEE_ERROR_MAC_INVALID; 1580b0104773SPascal Brand 1581b0104773SPascal Brand acc_dlen += tmp_dlen; 1582b0104773SPascal Brand *destLen = acc_dlen; 1583642a1607SCedric Chaumont 1584b5816c88SCedric Chaumont operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; 1585b5816c88SCedric Chaumont 1586642a1607SCedric Chaumont operation->operationState = TEE_OPERATION_STATE_INITIAL; 1587642a1607SCedric Chaumont 1588b5816c88SCedric Chaumont out: 1589b5816c88SCedric Chaumont if (res != TEE_SUCCESS && 1590b5816c88SCedric Chaumont res != TEE_ERROR_SHORT_BUFFER && 1591b5816c88SCedric Chaumont res != TEE_ERROR_MAC_INVALID) 1592b5816c88SCedric Chaumont TEE_Panic(res); 1593b0104773SPascal Brand 1594b0104773SPascal Brand return res; 1595b0104773SPascal Brand } 1596b0104773SPascal Brand 1597b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */ 1598b0104773SPascal Brand 159912e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, 16008f07fe6fSJerome Forissier const TEE_Attribute *params, 16018f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 160279a3c601SCedric Chaumont uint32_t srcLen, void *destData, 160379a3c601SCedric Chaumont uint32_t *destLen) 1604b0104773SPascal Brand { 1605b0104773SPascal Brand TEE_Result res; 1606e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1607e86f1266SJens Wiklander uint64_t dl; 1608b0104773SPascal Brand 160912e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1610b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1611b0104773SPascal Brand TEE_Panic(0); 161212e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1613b0104773SPascal Brand TEE_Panic(0); 161412e66b6fSCedric Chaumont if (!operation->key1) 1615b0104773SPascal Brand TEE_Panic(0); 161612e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 161712e66b6fSCedric Chaumont TEE_Panic(0); 161812e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_ENCRYPT) 1619b0104773SPascal Brand TEE_Panic(0); 1620b0104773SPascal Brand 1621e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1622e86f1266SJens Wiklander dl = *destLen; 1623e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1624e86f1266SJens Wiklander srcLen, destData, &dl); 1625e86f1266SJens Wiklander *destLen = dl; 162612e66b6fSCedric Chaumont 16278844ebfcSPascal Brand if (res != TEE_SUCCESS && 16288844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16298844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1630b0104773SPascal Brand TEE_Panic(res); 163112e66b6fSCedric Chaumont 1632b0104773SPascal Brand return res; 1633b0104773SPascal Brand } 1634b0104773SPascal Brand 163512e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, 16368f07fe6fSJerome Forissier const TEE_Attribute *params, 16378f07fe6fSJerome Forissier uint32_t paramCount, const void *srcData, 163879a3c601SCedric Chaumont uint32_t srcLen, void *destData, 163979a3c601SCedric Chaumont uint32_t *destLen) 1640b0104773SPascal Brand { 1641b0104773SPascal Brand TEE_Result res; 1642e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1643e86f1266SJens Wiklander uint64_t dl; 1644b0104773SPascal Brand 164512e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || 1646b0104773SPascal Brand destLen == NULL || (destData == NULL && *destLen != 0)) 1647b0104773SPascal Brand TEE_Panic(0); 164812e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1649b0104773SPascal Brand TEE_Panic(0); 165012e66b6fSCedric Chaumont if (!operation->key1) 1651b0104773SPascal Brand TEE_Panic(0); 165212e66b6fSCedric Chaumont if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) 165312e66b6fSCedric Chaumont TEE_Panic(0); 165412e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_DECRYPT) 1655b0104773SPascal Brand TEE_Panic(0); 1656b0104773SPascal Brand 1657e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1658e86f1266SJens Wiklander dl = *destLen; 1659e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, srcData, 1660e86f1266SJens Wiklander srcLen, destData, &dl); 1661e86f1266SJens Wiklander *destLen = dl; 166212e66b6fSCedric Chaumont 16638844ebfcSPascal Brand if (res != TEE_SUCCESS && 16648844ebfcSPascal Brand res != TEE_ERROR_SHORT_BUFFER && 16658844ebfcSPascal Brand res != TEE_ERROR_BAD_PARAMETERS) 1666b0104773SPascal Brand TEE_Panic(res); 166712e66b6fSCedric Chaumont 1668b0104773SPascal Brand return res; 1669b0104773SPascal Brand } 1670b0104773SPascal Brand 167112e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, 16728f07fe6fSJerome Forissier const TEE_Attribute *params, 16738f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 167479a3c601SCedric Chaumont uint32_t digestLen, void *signature, 167579a3c601SCedric Chaumont uint32_t *signatureLen) 1676b0104773SPascal Brand { 1677b0104773SPascal Brand TEE_Result res; 1678e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1679e86f1266SJens Wiklander uint64_t sl; 1680b0104773SPascal Brand 168112e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 168212e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1683b0104773SPascal Brand signature == NULL || signatureLen == NULL) 1684b0104773SPascal Brand TEE_Panic(0); 168512e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1686b0104773SPascal Brand TEE_Panic(0); 168712e66b6fSCedric Chaumont if (!operation->key1) 1688b0104773SPascal Brand TEE_Panic(0); 168912e66b6fSCedric Chaumont if (operation->info.operationClass != 169012e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 169112e66b6fSCedric Chaumont TEE_Panic(0); 169212e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_SIGN) 1693b0104773SPascal Brand TEE_Panic(0); 1694b0104773SPascal Brand 1695e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1696e86f1266SJens Wiklander sl = *signatureLen; 1697e86f1266SJens Wiklander res = utee_asymm_operate(operation->state, ua, paramCount, digest, 1698e86f1266SJens Wiklander digestLen, signature, &sl); 1699e86f1266SJens Wiklander *signatureLen = sl; 170012e66b6fSCedric Chaumont 1701b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) 1702b0104773SPascal Brand TEE_Panic(res); 170312e66b6fSCedric Chaumont 1704b0104773SPascal Brand return res; 1705b0104773SPascal Brand } 1706b0104773SPascal Brand 170712e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, 17088f07fe6fSJerome Forissier const TEE_Attribute *params, 17098f07fe6fSJerome Forissier uint32_t paramCount, const void *digest, 17108f07fe6fSJerome Forissier uint32_t digestLen, 17118f07fe6fSJerome Forissier const void *signature, 171279a3c601SCedric Chaumont uint32_t signatureLen) 1713b0104773SPascal Brand { 1714b0104773SPascal Brand TEE_Result res; 1715e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1716b0104773SPascal Brand 171712e66b6fSCedric Chaumont if (operation == TEE_HANDLE_NULL || 171812e66b6fSCedric Chaumont (digest == NULL && digestLen != 0) || 1719b0104773SPascal Brand (signature == NULL && signatureLen != 0)) 1720b0104773SPascal Brand TEE_Panic(0); 172112e66b6fSCedric Chaumont if (params == NULL && paramCount != 0) 1722b0104773SPascal Brand TEE_Panic(0); 172312e66b6fSCedric Chaumont if (!operation->key1) 1724b0104773SPascal Brand TEE_Panic(0); 172512e66b6fSCedric Chaumont if (operation->info.operationClass != 172612e66b6fSCedric Chaumont TEE_OPERATION_ASYMMETRIC_SIGNATURE) 172712e66b6fSCedric Chaumont TEE_Panic(0); 172812e66b6fSCedric Chaumont if (operation->info.mode != TEE_MODE_VERIFY) 1729b0104773SPascal Brand TEE_Panic(0); 1730b0104773SPascal Brand 1731e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1732e86f1266SJens Wiklander res = utee_asymm_verify(operation->state, ua, paramCount, digest, 173312e66b6fSCedric Chaumont digestLen, signature, signatureLen); 173412e66b6fSCedric Chaumont 1735b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) 1736b0104773SPascal Brand TEE_Panic(res); 173712e66b6fSCedric Chaumont 1738b0104773SPascal Brand return res; 1739b0104773SPascal Brand } 1740b0104773SPascal Brand 1741b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */ 1742b0104773SPascal Brand 1743b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation, 1744b0104773SPascal Brand const TEE_Attribute *params, uint32_t paramCount, 1745b0104773SPascal Brand TEE_ObjectHandle derivedKey) 1746b0104773SPascal Brand { 1747b0104773SPascal Brand TEE_Result res; 1748b0104773SPascal Brand TEE_ObjectInfo key_info; 1749e86f1266SJens Wiklander struct utee_attribute ua[paramCount]; 1750b0104773SPascal Brand 1751b0104773SPascal Brand if (operation == TEE_HANDLE_NULL || derivedKey == 0) 1752b0104773SPascal Brand TEE_Panic(0); 175384fa9467SCedric Chaumont if (params == NULL && paramCount != 0) 1754b0104773SPascal Brand TEE_Panic(0); 17558854d3c6SJerome Forissier if (TEE_ALG_GET_CLASS(operation->info.algorithm) != 17568854d3c6SJerome Forissier TEE_OPERATION_KEY_DERIVATION) 1757b0104773SPascal Brand TEE_Panic(0); 1758b0104773SPascal Brand 1759b0104773SPascal Brand if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) 1760b0104773SPascal Brand TEE_Panic(0); 176184fa9467SCedric Chaumont if (!operation->key1) 176284fa9467SCedric Chaumont TEE_Panic(0); 1763b0104773SPascal Brand if (operation->info.mode != TEE_MODE_DERIVE) 1764b0104773SPascal Brand TEE_Panic(0); 1765b0104773SPascal Brand if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) 1766b0104773SPascal Brand TEE_Panic(0); 1767b0104773SPascal Brand 1768e86f1266SJens Wiklander res = utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); 1769b0104773SPascal Brand if (res != TEE_SUCCESS) 1770b36311adSJerome Forissier TEE_Panic(res); 1771b0104773SPascal Brand 1772b0104773SPascal Brand if (key_info.objectType != TEE_TYPE_GENERIC_SECRET) 1773b0104773SPascal Brand TEE_Panic(0); 1774b0104773SPascal Brand if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) 1775b0104773SPascal Brand TEE_Panic(0); 1776b0104773SPascal Brand 1777e86f1266SJens Wiklander __utee_from_attr(ua, params, paramCount); 1778e86f1266SJens Wiklander res = utee_cryp_derive_key(operation->state, ua, paramCount, 1779e86f1266SJens Wiklander (unsigned long)derivedKey); 1780b0104773SPascal Brand if (res != TEE_SUCCESS) 1781b0104773SPascal Brand TEE_Panic(res); 1782b0104773SPascal Brand } 1783b0104773SPascal Brand 1784b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */ 1785b0104773SPascal Brand 178679a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) 1787b0104773SPascal Brand { 1788b0104773SPascal Brand TEE_Result res; 1789b0104773SPascal Brand 1790b0104773SPascal Brand res = utee_cryp_random_number_generate(randomBuffer, randomBufferLen); 1791b0104773SPascal Brand if (res != TEE_SUCCESS) 1792b0104773SPascal Brand TEE_Panic(res); 1793b0104773SPascal Brand } 1794*433c4257SJens Wiklander 1795*433c4257SJens Wiklander int rand(void) 1796*433c4257SJens Wiklander { 1797*433c4257SJens Wiklander int rc; 1798*433c4257SJens Wiklander 1799*433c4257SJens Wiklander TEE_GenerateRandom(&rc, sizeof(rc)); 1800*433c4257SJens Wiklander 1801*433c4257SJens Wiklander /* 1802*433c4257SJens Wiklander * RAND_MAX is the larges int, INT_MAX which is all bits but the 1803*433c4257SJens Wiklander * highest bit set. 1804*433c4257SJens Wiklander */ 1805*433c4257SJens Wiklander return rc & RAND_MAX; 1806*433c4257SJens Wiklander } 1807