Support concatenated wrapping 65/311165/1
authorDariusz Michaluk <d.michaluk@samsung.com>
Wed, 15 May 2024 11:52:57 +0000 (13:52 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 15 May 2024 17:14:48 +0000 (19:14 +0200)
Change-Id: Iefb0313784d0fbbb742b9eccf5491cc31838eb3d

ta/include/cmd_exec.h
ta/include/km_ta_defines.h
ta/src/cmd_exec.c
ta/src/km_ta.c

index 6767dc06294cf790a6edf43e6c9234513edc4635..68a12d5c0a037038c60ccc4f03b1f0b9cdaaa876 100644 (file)
@@ -72,4 +72,8 @@ TEE_Result KM_ExecCmdCipherCleanup(TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdGetMaxChunkSize(TEE_Param param[4]);
 
+TEE_Result KM_ExecCmdWrapConcatenatedData(TEE_Param param[4]);
+
+TEE_Result KM_ExecCmdUnwrapConcatenatedData(TEE_Param param[4]);
+
 #endif // __CMD_EXEC_H__
index ec0e74b325c4ff8510a3048f807ef779a392b098..5f2eb6ff2435b515339d609ec847ede4df1cdd0c 100644 (file)
@@ -64,6 +64,9 @@ typedef enum {
        CMD_CIPHER_FINALIZE,    ///< Finish the encryption/decryption
        CMD_CIPHER_CLEANUP,     ///< Release resources related to the context in the TA
        CMD_GET_MAX_CHUNK_SIZE, ///< Get maximum chunk size that can be passed to TA.
+       CMD_WRAP_CONCATENATED_DATA,   ///< Wraps concatenated key|data with wrapping key and export
+       CMD_UNWRAP_CONCATENATED_DATA, ///< Unwraps concatenated key|data with wrapping key,
+                                  ///< import key and export data
 } tz_command;
 
 /** \enum tz_algo_type
index 6b7c606df54b636d46ebf182f3c03924adb546da..5bbde3e287947dfa882d4eb9bf290323b1d70304 100644 (file)
@@ -3077,3 +3077,302 @@ TEE_Result KM_ExecCmdGetMaxChunkSize(TEE_Param param[4])
 
        return ret;
 }
+
+TEE_Result KM_ExecCmdWrapConcatenatedData(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_SUCCESS;
+       TEE_ObjectHandle wkey = TEE_HANDLE_NULL;
+       TEE_ObjectInfo wkey_info;
+
+       KM_BinaryData wkey_id = {0, NULL}; // wkey = wrapping key
+       KM_BinaryData ktw_id = {0, NULL}; // ktw = key to wrap
+       KM_BinaryData ktw_data = {0, NULL};
+       KM_BinaryData wrapped_key = {0, NULL};
+       KM_BinaryData user_data = {0, NULL};
+       KM_BinaryData concatenated = {0, NULL};
+       KM_PwdData wkey_pwd_data;
+       KM_PwdData ktw_pwd_data;
+       uint32_t with_wkey_pwd = 0;
+       uint32_t with_ktw_pwd = 0;
+       uint32_t algo = 0;
+       uint32_t tee_enc_mode = TEE_MODE_ENCRYPT;
+       uint32_t oaep_hash = HASH_SHA1;
+
+       void *in_buffer = param[1].memref.buffer;
+       void *out_buffer = param[2].memref.buffer;
+       uint32_t in_size_guard = param[1].memref.size;
+       uint32_t out_size_guard = param[2].memref.size;
+
+       // Deserialize from REE buffer
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &wkey_id)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_wkey_pwd, &wkey_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &algo)) {
+               LOG("Failed to deserialize algo flag");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (algo == ALGO_RSA) {
+               if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &oaep_hash)) {
+                       LOG("Failed to deserialize oaep_hash flag");
+                       return TEE_ERROR_BAD_PARAMETERS;
+               }
+       } else {
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &ktw_id)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_ktw_pwd, &ktw_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &user_data)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       // Get Wrapping Key Handle
+       ret = KM_GetWrappingKeyHandle(&wkey_id, algo, with_wkey_pwd, &wkey_pwd_data, &wkey);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in KM_OpenKey()");
+               goto clean;
+       }
+       TEE_GetObjectInfo(wkey, &wkey_info);
+
+       if (!KM_CheckAlgoKeyType(KM_Algo2TeeAlgoWithHash(algo, oaep_hash), wkey_info.objectType) ) {
+               LOG("Invalid algo & objectType. algo=%x,objectType=%x", KM_Algo2TeeAlgo(algo), wkey_info.objectType);
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
+       ret = KM_GetSecretValue(&ktw_id, &ktw_data, with_ktw_pwd, &ktw_pwd_data);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to get TEE_ATTR_SECRET_VALUE from key to wrap.");
+               goto clean;
+       }
+
+       // Concatenate key|data
+       concatenated.data_size = ktw_data.data_size + user_data.data_size;
+       concatenated.data = TEE_Malloc(concatenated.data_size, 0);
+       if (concatenated.data == NULL) {
+               LOG("Failed to allocate buffer");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       memcpy(concatenated.data, ktw_data.data, ktw_data.data_size);
+       memcpy(concatenated.data + ktw_data.data_size, user_data.data, user_data.data_size);
+
+       // Do wrapping
+       // Get Wrapping Key. The Wrapping Key can be RSA Public Key.
+       ret = KM_DoCipherWrappedKeyWithRsa(wkey, algo, tee_enc_mode, oaep_hash, &concatenated, &wrapped_key);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to encrypt a key for wrapping. ret=%x", ret);
+               goto clean;
+       }
+
+       // Serialize to REE buffer
+       if (KM_Serialize(&out_buffer, &out_size_guard, wrapped_key.data, wrapped_key.data_size)) {
+               LOG("Error in serialization");
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
+clean:
+       TEE_CloseObject(wkey);
+       TEE_Free(wrapped_key.data);
+       TEE_Free(ktw_data.data);
+       TEE_Free(concatenated.data);
+       return ret;
+}
+
+TEE_Result KM_ExecCmdUnwrapConcatenatedData(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_SUCCESS;
+       TEE_ObjectHandle wkey = TEE_HANDLE_NULL;
+       TEE_ObjectHandle key = TEE_HANDLE_NULL;
+       TEE_ObjectInfo wkey_info;
+
+       KM_BinaryData wkey_id = {0, NULL}; // wkey = wrapping key
+       KM_BinaryData enc_key = {0, NULL};
+       KM_BinaryData ekey_id = {0, NULL}; // ekey = enc key
+       KM_BinaryData ekey_data = {0, NULL};
+       KM_BinaryData ekey_data_enc = {0, NULL};
+       KM_BinaryData tag = {0, NULL};
+       KM_BinaryData skey = {0, NULL};
+       KM_BinaryData user_data = {0, NULL};
+       KM_PwdData wkey_pwd_data;
+       KM_PwdData ekey_pwd_data;
+       uint32_t with_wkey_pwd = 0;
+       uint32_t with_ekey_pwd = 0;
+       uint32_t algo = 0;
+       uint32_t enc_key_type = 0;
+       uint32_t tee_enc_key_type = 0;
+       uint32_t tee_enc_mode = TEE_MODE_DECRYPT;
+       uint32_t oaep_hash = HASH_SHA1;
+       uint32_t key_size = 0;
+
+       void *in_buffer = param[1].memref.buffer;
+       void *out_buffer = param[2].memref.buffer;
+       uint32_t in_size_guard = param[1].memref.size;
+       uint32_t out_size_guard = param[2].memref.size;
+
+       // Deserialize from REE buffer
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &wkey_id)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_wkey_pwd, &wkey_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &algo)) {
+               LOG("Failed to deserialize algo flag");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (algo == ALGO_RSA) {
+               if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &oaep_hash)) {
+                       LOG("Failed to deserialize oaep_hash flag");
+                       return TEE_ERROR_BAD_PARAMETERS;
+               }
+       } else {
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &enc_key_type)) {
+               LOG("Failed to deserialize key type flag");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &enc_key)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_ekey_pwd, &ekey_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &ekey_id)) {
+               LOG("Error in deserialization");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &key_size)) {
+               LOG("Failed to deserialize key_size flag");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       // Parameter Check:
+       // For now, only TYPE_SKEY is allowed. And the TYPE_SKEY is trasnalted into TEE_TYPE_AES
+       if (enc_key_type != TYPE_SKEY) {
+               LOG("Unsupported Key Type. Only TYPE_SKEY is supported. Key Type = %d", enc_key_type);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+       tee_enc_key_type = TEE_TYPE_AES;
+
+       // Get Wrapping Key Handle
+       ret = KM_GetWrappingKeyHandle(&wkey_id, algo, with_wkey_pwd, &wkey_pwd_data, &wkey);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in KM_OpenKey()");
+               goto clean;
+       }
+       TEE_GetObjectInfo(wkey, &wkey_info);
+
+       if (!KM_CheckAlgoKeyType(KM_Algo2TeeAlgoWithHash(algo, oaep_hash), wkey_info.objectType) ) {
+               LOG("Invalid algo & objectType. algo=%x,objectType=%x", KM_Algo2TeeAlgo(algo), wkey_info.objectType);
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
+       // Do unwrapping
+       ret = KM_DoCipherWrappedKeyWithRsa(wkey, algo, tee_enc_mode, oaep_hash, &enc_key, &ekey_data);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to decrypt a key for unwrapping. ret=%x", ret);
+               goto clean;
+       }
+
+       // Split key|data
+       skey.data_size = key_size/8;
+       skey.data = TEE_Malloc(skey.data_size, 0);
+       if (skey.data == NULL) {
+               LOG("Failed to allocate buffer");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       memcpy(skey.data, ekey_data.data, skey.data_size);
+
+       user_data.data_size = ekey_data.data_size - skey.data_size;
+       user_data.data = TEE_Malloc(user_data.data_size, 0);
+       if (user_data.data == NULL) {
+               LOG("Failed to allocate buffer");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       memcpy(user_data.data, ekey_data.data + skey.data_size, user_data.data_size);
+
+       // Serialize to REE buffer.
+       if (KM_Serialize(&out_buffer, &out_size_guard, user_data.data, user_data.data_size)) {
+               LOG("Error in serialization");
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
+       // Encrypt & Save
+       if (with_ekey_pwd) {
+               ret = KM_EncryptBinary(&ekey_pwd_data, &skey, &ekey_data_enc, &tag);
+               if (TEE_SUCCESS != ret) {
+                       LOG("Failed to encrypt new key");
+                       goto clean;
+               }
+               // Serialize to REE buffer. If needed, also the tag ID
+               if (KM_Serialize(&out_buffer, &out_size_guard, tag.data, tag.data_size)) {
+                       LOG("Error in serialization");
+                       ret = TEE_ERROR_BAD_PARAMETERS;
+               }
+               ret = KM_CreateKey(tee_enc_key_type, ekey_data_enc.data_size * 8, ekey_data_enc.data, &key);
+       } else {
+               ret = KM_CreateKey(tee_enc_key_type, skey.data_size * 8, skey.data, &key);
+       }
+       if (ret != TEE_SUCCESS) {
+               if (ret == TEE_ERROR_NOT_SUPPORTED)
+                       ret = TEE_ERROR_BAD_PARAMETERS;
+               LOG("Failed to create key");
+               goto clean;
+       }
+
+       ret = KM_SaveKey(NULL, 0, key, ekey_id.data, ekey_id.data_size);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to save generated key");
+               goto clean;
+       }
+
+clean:
+       TEE_CloseObject(wkey);
+       TEE_CloseObject(key);
+       TEE_Free(tag.data);
+       TEE_Free(ekey_data.data);
+       TEE_Free(ekey_data_enc.data);
+       TEE_Free(skey.data);
+       TEE_Free(user_data.data);
+       return ret;
+}
index 5e7772f39d05369b06b8845fb5814fd4829f7a70..9bd3cca4095423714dfabf63ee8ba3e33ffcec84 100644 (file)
@@ -218,6 +218,16 @@ TEE_Result TA_InvokeCommandEntryPoint(
                ret = KM_ExecCmdGetMaxChunkSize(param);
                break;
        }
+       case CMD_WRAP_CONCATENATED_DATA: {
+               LOGD("!!! Wraps concatenated key|data with wrapping key !!!");
+               ret = KM_ExecCmdWrapConcatenatedData(param);
+               break;
+       }
+       case CMD_UNWRAP_CONCATENATED_DATA: {
+               LOGD("!!! Unwraps concatenated key|data with wrapping key !!!");
+               ret = KM_ExecCmdUnwrapConcatenatedData(param);
+               break;
+       }
        default: {
                LOG("Unknown commandID=%d.", commandID);
                ret = TEE_ERROR_BAD_PARAMETERS;