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 /* BL2 ROTPK must be contiguous */ 36 PLAT_OTP_ID_BL2_ROTPK_0, 37 PLAT_OTP_ID_BL2_ROTPK_1, 38 PLAT_OTP_ID_BL2_ROTPK_2, 39 PLAT_OTP_ID_BL2_ROTPK_3, 40 41 /* BL2 NV counters must be contiguous */ 42 PLAT_OTP_ID_NV_COUNTER_BL2_0, 43 PLAT_OTP_ID_NV_COUNTER_BL2_1, 44 PLAT_OTP_ID_NV_COUNTER_BL2_2, 45 PLAT_OTP_ID_NV_COUNTER_BL2_3, 46 47 PLAT_OTP_ID_NV_COUNTER_NS_0, 48 PLAT_OTP_ID_NV_COUNTER_NS_1, 49 PLAT_OTP_ID_NV_COUNTER_NS_2, 50 51 PLAT_OTP_ID_KEY_BL2_ENCRYPTION, 52 PLAT_OTP_ID_BL1_2_IMAGE, 53 PLAT_OTP_ID_BL1_2_IMAGE_HASH, 54 PLAT_OTP_ID_BL2_IMAGE_HASH, 55 PLAT_OTP_ID_BL1_ROTPK_0, 56 57 PLAT_OTP_ID_NV_COUNTER_BL1_0, 58 59 PLAT_OTP_ID_ENTROPY_SEED, 60 61 PLAT_OTP_ID_SECURE_DEBUG_PK, 62 63 PLAT_OTP_ID_MAX = UINT32_MAX, 64 }; 65 #else 66 #include "platform_otp_ids.h" 67 #endif /* PLATFORM_DEFAULT_OTP */ 68 69 /* These are separate from the tfm_security_lifecycle_t definitions because here 70 * the possible transitions are encoded by using the property that OTP bits can 71 * be changed from a 0 to a 1, but not from a 1 to a 0. 72 * 73 * For example: 74 * If the device is in PLAT_OTP_LCS_SECURED, it can transition to 75 * PLAT_OTP_LCS_DECOMMISSIONED by setting bit 3, but cannot transition back to 76 * PLAT_OTP_LCS_PSA_ROT_PROVISIONING as that would require setting bit 2 to 0, 77 * which cannot be done as per OTP semantics. 78 * 79 * NON_PSA_ROT_DEBUG and RECOVERABLE_PSA_ROT_DEBUG must be handled separately to 80 * OTP memory as they are reversible transitions from SECURED, and OTP cannot 81 * handle reversible transitions. 82 */ 83 enum plat_otp_lcs_t { 84 PLAT_OTP_LCS_ASSEMBLY_AND_TEST = 0x0, 85 PLAT_OTP_LCS_PSA_ROT_PROVISIONING = 0x1, 86 PLAT_OTP_LCS_SECURED = 0x3, 87 PLAT_OTP_LCS_DECOMMISSIONED = 0x7, 88 PLAT_OTP_LCS_UNKNOWN = 0xF, 89 PLAT_OTP_LCS_MAX = UINT32_MAX, 90 }; 91 92 /** 93 * \brief Initialises OTP storage. 94 * 95 * \return TFM_PLAT_ERR_SUCCESS if the 96 * initialization succeeds, otherwise 97 * TFM_PLAT_ERR_SYSTEM_ERR 98 */ 99 enum tfm_plat_err_t tfm_plat_otp_init(void); 100 101 /** 102 * \brief Reads the given OTP element. 103 * 104 * \param[in] id ID of the element to read. 105 * \param[in] out_len Size of the buffer to read the element 106 * into in bytes. 107 * \param[out] out Buffer to read the element into. 108 * 109 * \note If the size of the internal OTP 110 * representation of the item is different 111 * to out_len, then the smaller of the two 112 * is the amount of bytes that must be 113 * read. 114 * 115 * \retval TFM_PLAT_ERR_SUCCESS The element is read successfully. 116 * \retval TFM_PLAT_ERR_UNSUPPORTED The given element has not been 117 * instanciated in OTP memory by this 118 * particular platform. 119 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 120 */ 121 enum tfm_plat_err_t tfm_plat_otp_read(enum tfm_otp_element_id_t id, 122 size_t out_len, uint8_t *out); 123 124 /** 125 * \brief Writes the specified bytes to the given 126 * OTP element. 127 * 128 * \param[in] id ID of the element to write. 129 * \param[in] in_len Size of the buffer to write to the 130 * element in bytes. 131 * \param[in] in Pointer to the buffer to write to the 132 * element. 133 * 134 * \note This function must implement the OTP 135 * writing semantics, where any bit 136 * currently set to 1 cannot be set to 0. 137 * If such a write is requested, the 138 * function should return an error code and 139 * not alter the contents of OTP memory. 140 * 141 * \note If the size of the internal OTP 142 * representation of the item is smaller 143 * than in_len, this function must return 144 * an error other than TFM_PLAT_ERR_SUCCESS 145 * and not write any OTP. 146 * 147 * \retval TFM_PLAT_ERR_SUCCESS The OTP is written successfully 148 * \retval TFM_PLAT_ERR_UNSUPPORTED The element is not supported. 149 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 150 */ 151 enum tfm_plat_err_t tfm_plat_otp_write(enum tfm_otp_element_id_t id, 152 size_t in_len, const uint8_t *in); 153 154 /** 155 * \brief Returns the size of a given OTP element. 156 * 157 * \param[in] id ID of the element. 158 * \param[out] size Size of the element. 159 * 160 * \retval TFM_PLAT_ERR_SUCCESS The size is returned successfully. 161 * \retval TFM_PLAT_ERR_UNSUPPORTED The element is not supported. 162 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 163 */ 164 enum tfm_plat_err_t tfm_plat_otp_get_size(enum tfm_otp_element_id_t id, 165 size_t *size); 166 167 /** 168 * \brief Enable a secure provisioning mode, if 169 * supported. 170 * 171 * \retval TFM_PLAT_ERR_SUCCESS The mode was enabled successfully. 172 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 173 */ 174 enum tfm_plat_err_t tfm_plat_otp_secure_provisioning_start(void); 175 176 /** 177 * \brief Disable the secure provisioning mode 178 * once provisioning has finished. 179 * 180 * \retval TFM_PLAT_ERR_SUCCESS The mode was disabled successfully. 181 * \retval TFM_PLAT_ERR_SYSTEM_ERR An unspecified error occurred. 182 */ 183 enum tfm_plat_err_t tfm_plat_otp_secure_provisioning_finish(void); 184 185 #ifdef __cplusplus 186 } 187 #endif 188 189 #endif /* __TFM_PLAT_OTP_H__ */ 190