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)
}
}
+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)
{