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

#ifndef __TEGRA_SE_KDF_H__
#define __TEGRA_SE_KDF_H__

#include <drivers/tegra/tegra_se_keyslot.h>
#include <tee_api_types.h>

#if defined(PLATFORM_FLAVOR_t234)
/*
 * SE AES ECB KDF - Derives root key from SE keyslot.
 *
 * derived_key		[out] pointer of the output buffer of the derived_key.
 * derived_key_len	[in] the length of the derived_key.
 * iv			[in] pointer of the initial vector.
 * iv_len		[in] the length of the initial vector.
 * keyslot		[in] SE keyslot.
 */

TEE_Result tegra_se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len,
				uint8_t *iv, size_t iv_len,
				uint32_t keyslot);

/*
 * A hardware-based NIST-SP 800-108 KDF;
 *  derives keys from the SE keyslot.
 *
 *  Use this function only during OP-TEE initialization at boot time
 *  (the device boot stage). To derive keys from a key buffer at runtime,
 *  use nist_sp_800_108_cmac_kdf().
 *
 * keyslot	[in] the SE keyslot where the key stores.
 * key_len	[in] length in bytes of the input key.
 * *context	[in] a pointer to a NIST-SP 800-108 context string.
 * context_len  [in] length of the context string.
 * *label	[in] a pointer to a NIST-SP 800-108 label string.
 * label_len    [in] length of the label string.
 * dk_len	[in] length of the derived key in bytes;
 *		     may be 16 (128 bits) or any multiple of 16.
 * *out_dk	[out] a pointer to the derived key. The function stores
 *		      its result in this location.
 */
TEE_Result tegra_se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot,
					     uint32_t key_len,
					     char const *context,
					     uint32_t context_len,
					     char const *label,
					     uint32_t label_len,
					     uint32_t dk_len,
					     uint8_t *out_dk);

#elif defined(PLATFORM_FLAVOR_t264)
#define TEGRA_KEYMANIFEST_SIZE_KEY256			(2)
#define TEGRA_KEYMANIFEST_SIZE_SHIFT			(14)
#define TEGRA_KEYMANIFEST_USER_TZ			(2)
#define TEGRA_KEYMANIFEST_USER_SHIFT			(4)
#define TEGRA_KEYMANIFEST_PURPOSE_ENC			(0)
#define TEGRA_KEYMANIFEST_PURPOSE_CMAC			(1)
#define TEGRA_KEYMANIFEST_PURPOSE_HMAC			(2)
#define TEGRA_KEYMANIFEST_PURPOSE_KDK                   (6)
#define TEGRA_KEYMANIFEST_PURPOSE_SHIFT                 (8)

/* Identity key purpose manifest (keysize-user-purpose) */
#define KEYSIZE_256_TZ_ENC_MANIFEST \
	((uint32_t)((uint32_t)TEGRA_KEYMANIFEST_SIZE_KEY256 << TEGRA_KEYMANIFEST_SIZE_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_USER_TZ << TEGRA_KEYMANIFEST_USER_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_PURPOSE_ENC << TEGRA_KEYMANIFEST_PURPOSE_SHIFT))

#define KEYSIZE_256_TZ_CMAC_MANIFEST \
	((uint32_t)((uint32_t)TEGRA_KEYMANIFEST_SIZE_KEY256 << TEGRA_KEYMANIFEST_SIZE_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_USER_TZ << TEGRA_KEYMANIFEST_USER_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_PURPOSE_CMAC << TEGRA_KEYMANIFEST_PURPOSE_SHIFT))

#define KEYSIZE_256_TZ_HMAC_MANIFEST \
	((uint32_t)((uint32_t)TEGRA_KEYMANIFEST_SIZE_KEY256 << TEGRA_KEYMANIFEST_SIZE_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_USER_TZ << TEGRA_KEYMANIFEST_USER_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_PURPOSE_HMAC << TEGRA_KEYMANIFEST_PURPOSE_SHIFT))

#define KEYSIZE_256_TZ_KDK_MANIFEST \
	((uint32_t)((uint32_t)TEGRA_KEYMANIFEST_SIZE_KEY256 << TEGRA_KEYMANIFEST_SIZE_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_USER_TZ << TEGRA_KEYMANIFEST_USER_SHIFT) | \
	 (uint32_t)((uint32_t)TEGRA_KEYMANIFEST_PURPOSE_KDK << TEGRA_KEYMANIFEST_PURPOSE_SHIFT))

TEE_Result tegra_se_nist_sp_800_108_hmac_kdf_to_mem(se_aes_keyslot_t keyslot,
						    uint32_t key_len,
						    char const *label,
						    uint32_t label_len,
						    char const *context,
						    uint32_t context_len,
						    uint32_t dk_len,
						    uint8_t *out_dk);

TEE_Result tegra_se_nist_sp_800_108_hmac_kdf_to_ks(se_aes_keyslot_t source_keyslot,
						   char const *label,
						   uint32_t label_len,
						   char const *context,
						   uint32_t context_len,
						   uint32_t manifest,
						   se_aes_keyslot_t target_keyslot);
#endif

#endif
