1 /* 2 * Copyright (c) 2021-2022, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #ifndef __TFM_PLAT_OTP_H__ 9 #define __TFM_PLAT_OTP_H__ 10 11 #include <stdint.h> 12 #include <stddef.h> 13 #include "tfm_plat_defs.h" 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 #ifdef PLATFORM_DEFAULT_OTP 20 enum tfm_otp_element_id_t { 21 PLAT_OTP_ID_HUK = 0, 22 PLAT_OTP_ID_GUK, 23 PLAT_OTP_ID_IAK, 24 PLAT_OTP_ID_IAK_LEN, 25 PLAT_OTP_ID_IAK_TYPE, 26 PLAT_OTP_ID_IAK_ID, 27 28 PLAT_OTP_ID_BOOT_SEED, 29 PLAT_OTP_ID_LCS, 30 PLAT_OTP_ID_IMPLEMENTATION_ID, 31 PLAT_OTP_ID_CERT_REF, 32 PLAT_OTP_ID_VERIFICATION_SERVICE_URL, 33 PLAT_OTP_ID_PROFILE_DEFINITION, 34 35 PLAT_OTP_ID_BL2_ROTPK_0, 36 PLAT_OTP_ID_BL2_ROTPK_1, 37 PLAT_OTP_ID_BL2_ROTPK_2, 38 PLAT_OTP_ID_BL2_ROTPK_3, 39 40 PLAT_OTP_ID_NV_COUNTER_BL2_0, 41 PLAT_OTP_ID_NV_COUNTER_BL2_1, 42 PLAT_OTP_ID_NV_COUNTER_BL2_2, 43 PLAT_OTP_ID_NV_COUNTER_BL2_3, 44 45 PLAT_OTP_ID_NV_COUNTER_NS_0, 46 PLAT_OTP_ID_NV_COUNTER_NS_1, 47 PLAT_OTP_ID_NV_COUNTER_NS_2, 48 49 PLAT_OTP_ID_KEY_BL2_ENCRYPTION, 50 PLAT_OTP_ID_BL1_2_IMAGE, 51 PLAT_OTP_ID_BL1_2_IMAGE_HASH, 52 PLAT_OTP_ID_BL2_IMAGE_HASH, 53 PLAT_OTP_ID_BL1_ROTPK_0, 54 55 PLAT_OTP_ID_NV_COUNTER_BL1_0, 56 57 PLAT_OTP_ID_ENTROPY_SEED, 58 59 PLAT_OTP_ID_SECURE_DEBUG_PK, 60 61 PLAT_OTP_ID_MAX = UINT32_MAX, 62 }; 63 #else 64 #include "platform_otp_ids.h" 65 #endif /* PLATFORM_DEFAULT_OTP */ 66 67 /* These are separate from the tfm_security_lifecycle_t definitions because here 68 * the possible transitions are encoded by using the property that OTP bits can 69 * be changed from a 0 to a 1, but not from a 1 to a 0. 70 * 71 * For example: 72 * If the device is in PLAT_OTP_LCS_SECURED, it can transition to 73 * PLAT_OTP_LCS_DECOMMISSIONED by setting bit 3, but cannot transition back to 74 * PLAT_OTP_LCS_PSA_ROT_PROVISIONING as that would require setting bit 2 to 0, 75 * which cannot be done as per OTP semantics. 76 * 77 * NON_PSA_ROT_DEBUG and RECOVERABLE_PSA_ROT_DEBUG must be handled separately to 78 * OTP memory as they are reversible transitions from SECURED, and OTP cannot 79 * handle reversible transitions. 80 */ 81 enum plat_otp_lcs_t { 82 PLAT_OTP_LCS_ASSEMBLY_AND_TEST = 0x0, 83 PLAT_OTP_LCS_PSA_ROT_PROVISIONING = 0x1, 84 PLAT_OTP_LCS_SECURED = 0x3, 85 PLAT_OTP_LCS_DECOMMISSIONED = 0x7, 86 PLAT_OTP_LCS_UNKNOWN = 0xF, 87 PLAT_OTP_LCS_MAX = UINT32_MAX, 88 }; 89 90 /** 91 * \brief Initialises OTP storage. 92 * 93 * \return TFM_PLAT_ERR_SUCCESS if the 94 * initialization succeeds, otherwise 95 * TFM_PLAT_ERR_SYSTEM_ERR 96 */ 97 enum tfm_plat_err_t tfm_plat_otp_init(void); 98 99 /** 100 * \brief Reads the given OTP element. 101 * 102 * \param[in] id ID of the element to read. 103 * \param[in] out_len Size of the buffer to read the element 104 * into in bytes. 105 * \param[out] out Buffer to read the element into. 106 * 107 * \note If the size of the internal OTP 108 * representation of the item is different 109 * to out_len, then the smaller of the two 110 * is the amount of bytes that must be 111 * read. 112 * 113 * \retval TFM_PLAT_ERR_SUCCESS The element is read successfully. 114 * \retval TFM_PLAT_ERR_UNSUPPORTED The given element has not been 115 * instanciated in OTP memory by this 116 * particular platform. 117 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 118 */ 119 enum tfm_plat_err_t tfm_plat_otp_read(enum tfm_otp_element_id_t id, 120 size_t out_len, uint8_t *out); 121 122 /** 123 * \brief Writes the specified bytes to the given 124 * OTP element. 125 * 126 * \param[in] id ID of the element to write. 127 * \param[in] in_len Size of the buffer to write to the 128 * element in bytes. 129 * \param[in] in Pointer to the buffer to write to the 130 * element. 131 * 132 * \note This function must implement the OTP 133 * writing semantics, where any bit 134 * currently set to 1 cannot be set to 0. 135 * If such a write is requested, the 136 * function should return an error code and 137 * not alter the contents of OTP memory. 138 * 139 * \note If the size of the internal OTP 140 * representation of the item is smaller 141 * than in_len, this function must return 142 * an error other than TFM_PLAT_ERR_SUCCESS 143 * and not write any OTP. 144 * 145 * \retval TFM_PLAT_ERR_SUCCESS The OTP is written successfully 146 * \retval TFM_PLAT_ERR_UNSUPPORTED The element is not supported. 147 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 148 */ 149 enum tfm_plat_err_t tfm_plat_otp_write(enum tfm_otp_element_id_t id, 150 size_t in_len, const uint8_t *in); 151 152 /** 153 * \brief Returns the size of a given OTP element. 154 * 155 * \param[in] id ID of the element. 156 * \param[out] size Size of the element. 157 * 158 * \retval TFM_PLAT_ERR_SUCCESS The size is returned successfully. 159 * \retval TFM_PLAT_ERR_UNSUPPORTED The element is not supported. 160 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 161 */ 162 enum tfm_plat_err_t tfm_plat_otp_get_size(enum tfm_otp_element_id_t id, 163 size_t *size); 164 165 #ifdef __cplusplus 166 } 167 #endif 168 169 #endif /* __TFM_PLAT_OTP_H__ */ 170