// SPDX-License-Identifier: BSD-2-Clause
/*
 * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 */

#include <string.h>
#include <stdlib.h>
#include <types_ext.h>
#include <tee_api_types.h>
#include <trace.h>
#include <initcall.h>
#include <utee_defines.h>
#include <tegra_se_ccc.h>
#include <tegra_se_ccc_aes.h>
#include <tegra_se_ccc_errno.h>
#include <tegra_se_driver_aes.h>
#include <tegra_se_driver_rng.h>
#include <tegra_driver_srv_intf.h>

static TEE_Result tegra_se_init(void)
{
	status_t ret;
	tegra_drv_srv_intf_t *drv_srv_intf;

#if defined(CFG_TEGRA_SE_USE_TEST_KEYS)
	/* OEM_K1/OEM_K2: 0000000000000000000000000000000000000000000000000000000000000000 */
	const uint8_t test_oem_key[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	};

	TEE_Result err = TEE_SUCCESS;
	uint32_t bsi = 0;
#endif

#ifndef TEGRA_SE_CRYPTO_INITIALIZED
#define TEGRA_SE_CRYPTO_INITIALIZED
	/* This function will call tegra_se_map_device to map devices */
	ret = tegra_init_crypto_devices();
	if (ret != NO_ERROR) {
		return TEE_ERROR_GENERIC;
	}
#endif

#if defined(CFG_TEGRA_SE_USE_TEST_KEYS)
	err = tegra_fuse_get_bsi(&bsi);
	if (err != TEE_SUCCESS) {
		EMSG("Read fuse BSI failed: 0x%x", err);
		return TEE_ERROR_GENERIC;
	}

	if ((bsi & BSI_OEM_KEY_VALID_MASK) == 0) {
		ret = tegra_se_ccc_set_test_oem_keys(test_oem_key, test_oem_key);
		if (ret != NO_ERROR) {
			EMSG("Setting test OEM keys failed: %d", ret);
			return TEE_ERROR_GENERIC;
		}
		IMSG("Test OEM keys are being used. This is insecure for shipping products!");
	}
#endif

	drv_srv_intf = tegra_drv_srv_intf_get();
	if (drv_srv_intf != NULL) {
		drv_srv_intf->aes_encrypt = se_aes_encrypt;
		drv_srv_intf->aes_ecb_kdf = se_aes_ecb_kdf;
		drv_srv_intf->nist_sp_800_108_cmac_kdf = se_nist_sp_800_108_cmac_kdf;
		drv_srv_intf->write_aes_keyslot = se_write_aes_keyslot;
		drv_srv_intf->clear_aes_keyslots = se_clear_aes_keyslots;
#if defined(CFG_TEGRA_SE_RNG1)
		drv_srv_intf->rng_get_random = se_rng1_get_random;
#endif
	} else {
		return TEE_ERROR_NOT_SUPPORTED;
	}

	return TEE_SUCCESS;
}
service_init_late(tegra_se_init);
