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 #ifdef __cplusplus
168 }
169 #endif
170 
171 #endif /* __TFM_PLAT_OTP_H__ */
172