Support ML-KEM derive hybrid 53/316553/12
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 22 Aug 2024 12:38:32 +0000 (14:38 +0200)
committerJan Wojtkowski <j.wojtkowski@samsung.com>
Tue, 3 Sep 2024 08:30:44 +0000 (10:30 +0200)
Change-Id: Ice5abca74f028193715437022ea9794e94d876fd

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

index a7defbcc9c3176be864dc8c661fdd624d9505b42..270e76c2d6e880b509c6e875afa16ae238a5f629 100644 (file)
@@ -58,6 +58,8 @@ TEE_Result KM_ExecCmdDestroyData(TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdDeriveKey(TEE_Param param[4]);
 
+TEE_Result KM_ExecCmdDeriveHybridKey(TEE_Param param[4]);
+
 TEE_Result KM_ExecCmdImportWrappedKey(TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdExportWrappedKey(TEE_Param param[4]);
index 856e07ccadb3284f430aac2132ed3895d8314c76..49cf1d1f8007e75c6a76617d85070299cfcf538e 100644 (file)
@@ -57,6 +57,7 @@ typedef enum {
        CMD_GENERATE_EC_KEYPAIR,    ///< Generate random EC key pair.
        CMD_GENERATE_KEM_KEYPAIR,   ///< Generate random KEM key pair.
        CMD_DERIVE,             ///< Derive secret or key
+       CMD_DERIVE_HYBRID,      ///< Derive secret or key
        CMD_IMPORT_WRAPPED_KEY, ///< Import a wrapped key
        CMD_EXPORT_WRAPPED_KEY, ///< Export a key in a wrapped form
        CMD_CIPHER_INIT,        ///< Initialize encryption/decryption context
index 9db25f842044b597049135800d2810566078fd6d..51fe988b5ecb6776ef3a37fc95886714180bd9eb 100644 (file)
@@ -1087,6 +1087,222 @@ clean:
        return ret;
 }
 
+TEE_Result KM_ExecCmdDeriveHybridKbkdf(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_SUCCESS;
+       TEE_ObjectHandle key_handle = TEE_HANDLE_NULL;
+
+       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;
+
+       uint32_t with_first_secret_pwd = 0, with_second_secret_pwd = 0;
+       KM_BinaryData first_secret_id = {0, NULL};
+       KM_BinaryData second_secret_id = {0, NULL};
+       KM_BinaryData label = {0, NULL};
+       KM_BinaryData context = {0, NULL};
+       KM_BinaryData fixed = {0, NULL};
+       KM_BinaryData obj_id = {0, NULL};
+       KM_BinaryData key_in_first = {0, NULL};
+       KM_BinaryData key_in_second = {0, NULL};
+       KM_BinaryData derived_key = {0, NULL};
+       KM_BinaryData encrypted_derived_key = {0, NULL};
+       KM_BinaryData tag = {0, NULL};
+       KM_PwdData first_secret_pwd_data, second_secret_pwd_data, pwd_data;
+       uint32_t outlen;
+       uint32_t prf;
+       uint32_t mode;
+       uint32_t ctrloc;
+       uint32_t rlen;
+       uint32_t llen;
+       uint32_t no_separator;
+       uint32_t with_pwd = 0;
+
+       // Deserialize data from REE
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &first_secret_id);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(first_secret_id), ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_first_secret_pwd, &first_secret_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of first secret flag and password, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &second_secret_id);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(second_secret_id), ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_second_secret_pwd, &second_secret_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of second secret flag and password, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &outlen);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of outlen flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &label);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(label), ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &context);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(context), ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &fixed);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(fixed), ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &prf);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of prf flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &mode);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of mode flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &ctrloc);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of ctrloc flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &rlen);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of rlen flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &llen);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of llen flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlag(&in_buffer, &in_size_guard, &no_separator);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of no_separator flag, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_pwd, &pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of secret flag and password, ret = %x", ret);
+               goto clean;
+       }
+
+       ret = KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &obj_id);
+       if (ret != TEE_SUCCESS) {
+               LOG("Error in deserialization of hash(obj_id), ret = %x", ret);
+               goto clean;
+       }
+
+       // Get Key_In from permanent storage
+       ret = KM_GetSecretValue(&first_secret_id, &key_in_first, with_first_secret_pwd, &first_secret_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOGD_ID("Failed to get first Secret Value from object: ", first_secret_id.data, first_secret_id.data_size);
+               goto clean;
+       }
+
+       // Get Key_In from permanent storage
+       ret = KM_GetSecretValue(&second_secret_id, &key_in_second, with_second_secret_pwd, &second_secret_pwd_data);
+       if (ret != TEE_SUCCESS) {
+               LOGD_ID("Failed to get second Secret Value from object: ", second_secret_id.data, second_secret_id.data_size);
+               goto clean;
+       }
+
+       void *tmp;
+       uint32_t new_size = key_in_first.data_size + key_in_second.data_size;
+       tmp = TEE_Realloc(key_in_first.data, new_size);
+       if (tmp == NULL) {
+               LOG("Failed to reallocate buffer for concatenated keys");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+
+       key_in_first.data = tmp;
+       key_in_first.data_size = new_size;
+       memcpy(key_in_first.data + key_in_first.data_size, key_in_second.data, key_in_second.data_size);
+
+       // execute KBKDF
+       derived_key.data = (unsigned char *) TEE_Malloc(outlen, 0);
+       derived_key.data_size = outlen;
+       if (derived_key.data == NULL) {
+               LOG("Failed to allocate input buffer for derived_key");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+
+       ret = KM_KbkdfHmacCtr(key_in_first.data, key_in_first.data_size,
+                                                 prf, ctrloc, rlen, llen,
+                                                 label.data, label.data_size,
+                                                 context.data, context.data_size,
+                                                 fixed.data, fixed.data_size,
+                                                 no_separator,
+                                                 derived_key.data, outlen);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed in KM_KbkdfHmacCtr(): ret=%x", ret);
+               goto clean;
+       }
+
+       // Serialize data for sending to REE.
+       if (with_pwd) {
+               ret = KM_EncryptBinary(&pwd_data, &derived_key, &encrypted_derived_key, &tag);
+               if (ret != TEE_SUCCESS) {
+                       LOG("Failed to encrypt new key");
+                       goto clean;
+               }
+               // output tag
+               if (KM_Serialize(&out_buffer, &out_size_guard, tag.data, tag.data_size)) {
+                       LOG("Error in serialization");
+                       ret = TEE_ERROR_BAD_PARAMETERS;
+                       goto clean;
+               }
+               ret = KM_CreateKey(TEE_TYPE_AES, encrypted_derived_key.data_size * 8, encrypted_derived_key.data, &key_handle);
+       } else {
+               ret = KM_CreateKey(TEE_TYPE_AES, derived_key.data_size * 8, derived_key.data, &key_handle);
+       }
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to create key");
+               goto clean;
+       }
+
+       ret = KM_SaveKey(NULL, 0, key_handle, obj_id.data, obj_id.data_size);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to save generated key");
+               goto clean;
+       }
+
+       LOGD_ID("Derive KBKDF key: ", obj_id.data, obj_id.data_size);
+clean:
+       TEE_CloseObject(key_handle);
+       TEE_Free(key_in_first.data);
+       TEE_Free(key_in_second.data);
+       TEE_Free(derived_key.data);
+       TEE_Free(encrypted_derived_key.data);
+       TEE_Free(tag.data);
+
+       return ret;
+}
 
 static TEE_Result KM_CopyEcdhPrivateAttributes(TEE_ObjectHandle dest_key,
                                                                                                TEE_ObjectHandle src_key)
@@ -1370,6 +1586,18 @@ TEE_Result KM_ExecCmdDeriveKey(TEE_Param param[4])
        }
 }
 
+TEE_Result KM_ExecCmdDeriveHybridKey(TEE_Param param[4])
+{
+       tz_algo_type algo= param[0].value.a;
+
+       if (algo == ALGO_KBKDF_DRV) {
+               return KM_ExecCmdDeriveHybridKbkdf(param);
+       } else {
+               LOG("Invalid algorithm, algo = %d", algo);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+}
+
 static TEE_Result KM_GetWrappingKeyHandle(KM_BinaryData *wkey_id, uint32_t algo,
                uint32_t with_wkey_pwd, KM_PwdData *wkey_pwd_data, TEE_ObjectHandle *wkey)
 {
index 7331c50e061bd0bea4ff12066d844e9e5b8804b8..fc60adfdab784609525e63321c0b6dad40f2f097 100644 (file)
@@ -183,6 +183,11 @@ TEE_Result TA_InvokeCommandEntryPoint(
                ret = KM_ExecCmdDeriveKey(param);
                break;
        }
+       case CMD_DERIVE_HYBRID: {
+               LOGD("!!! Hybrid deriving a key !!!");
+               ret = KM_ExecCmdDeriveHybridKey(param);
+               break;
+       }
        case CMD_IMPORT_WRAPPED_KEY: {
                LOGD("!!! Importing a wrapped key !!!");
                ret = KM_ExecCmdImportWrappedKey(param);