1 /*
2  *     Copyright 2021 MCUX
3  *     All rights reserved.
4  *
5  *     SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_css_pkc.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 #define TEMPORARY_KEY_SLOT_256 18u
14 /*******************************************************************************
15  * Prototypes
16  ******************************************************************************/
17 static status_t CSS_PRNG_KickOff(void);
18 static status_t CSS_check_key(uint8_t keyIdx, mcuxClCss_KeyProp_t *pKeyProp);
19 /*******************************************************************************
20  * Code
21  ******************************************************************************/
22 /*!
23  * brief CSS Init after power down.
24  *
25  * This function enable all CSS related clocks, enable CSS and start CSS PRNG.
26  * Normally all of these actions are done automatically by boot ROM, but if an application uses Power Down mode
27  * this function must be called before using CSS after wake-up.
28  *
29  * param base CSS peripheral address.
30  *
31  * return kStatus_Success upon success, kStatus_Fail otherwise
32  */
CSS_PowerDownWakeupInit(CSS_Type * base)33 status_t CSS_PowerDownWakeupInit(CSS_Type *base)
34 {
35     status_t status = kStatus_Fail;
36 
37     /* Enable all CSS related clocks */
38     ANACTRL->FRO192M_CTRL |= (ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK | ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK);
39     SYSCON->CSS_CLK_CTRL_SET =
40         (SYSCON_CSS_CLK_CTRL_SET_GDET_REFCLK_EN_SET_MASK | SYSCON_CSS_CLK_CTRL_SET_DTRNG_REFCLK_EN_SET_MASK);
41 
42     /* De-assert reset */
43     RESET_ClearPeripheralReset(kCSS_RST_SHIFT_RSTn);
44 
45     /* Enable CSS clock */
46     CLOCK_EnableClock(kCLOCK_Css);
47 
48     /* Enable CSS */
49     mcuxClCss_Enable_Async();
50     /* Wait until CSS is enabled */
51     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
52     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation) != token) && (MCUXCLCSS_STATUS_OK != result))
53     {
54         return kStatus_Fail;
55     }
56     MCUX_CSSL_FP_FUNCTION_CALL_END();
57 
58     /* Kick-off CSS PRNG */
59     status = CSS_PRNG_KickOff();
60     if (status != kStatus_Success)
61     {
62         return status;
63     }
64 
65     return kStatus_Success;
66 }
67 
68 /*!
69  * brief PKC Init after power down.
70  *
71  * This function enables RAM interleave, clocks, zeroize the PKC RAM and reset PKC peripheral.
72  * Normally all of these actions are done automatically by boot ROM, but if an application uses Power Down mode
73  * this function must be called before using PKC after wake-up.
74  *
75  * param base PKC peripheral address.
76  *
77  * return kStatus_Success upon success, kStatus_Fail otherwise
78  */
PKC_PowerDownWakeupInit(PKC_Type * base)79 status_t PKC_PowerDownWakeupInit(PKC_Type *base)
80 {
81     /* set PKC RAM to interleave mode */
82     SYSCON->RAM_INTERLEAVE = SYSCON_RAM_INTERLEAVE_INTERLEAVE_MASK;
83     /* Reset PKC */
84     RESET_PeripheralReset(kPKC_RST_SHIFT_RSTn);
85     /* enable PKC clock */
86     CLOCK_EnableClock(kCLOCK_Pkc);
87 
88     /* Zeroize the PKC RAM */
89     for (int i = 0; i < PKC_RAM_SIZE / sizeof(uint32_t); i++)
90     {
91         ((uint32_t *)PKC_RAM_ADDR)[i] = 0x0;
92     }
93 
94     return kStatus_Success;
95 }
96 
97 /*!
98  * brief PKC Init after power down.
99  *
100  * This function enables RAM interleave, clocks and reset PKC peripheral.
101  *
102  * param base PKC peripheral address.
103  *
104  * return kStatus_Success upon success, kStatus_Fail otherwise
105  */
PKC_InitNoZeroize(PKC_Type * base)106 status_t PKC_InitNoZeroize(PKC_Type *base)
107 {
108     /* set PKC RAM to interleave mode */
109     SYSCON->RAM_INTERLEAVE = SYSCON_RAM_INTERLEAVE_INTERLEAVE_MASK;
110     /* Reset PKC */
111     RESET_PeripheralReset(kPKC_RST_SHIFT_RSTn);
112     /* enable PKC clock */
113     CLOCK_EnableClock(kCLOCK_Pkc);
114 
115     return kStatus_Success;
116 }
117 
CSS_check_key(uint8_t keyIdx,mcuxClCss_KeyProp_t * pKeyProp)118 static status_t CSS_check_key(uint8_t keyIdx, mcuxClCss_KeyProp_t *pKeyProp)
119 {
120     /* Check if CSS required keys are available in CSS keystore */
121     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token,
122                                     mcuxClCss_GetKeyProperties(keyIdx, pKeyProp)); // Get key propertis from the CSS.
123     // mcuxClCss_GetKeyProperties is a flow-protected function: Check the protection token and the return value
124     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_GetKeyProperties) != token) || (MCUXCLCSS_STATUS_OK != result))
125         return kStatus_Fail;
126     MCUX_CSSL_FP_FUNCTION_CALL_END();
127 
128     return kStatus_Success;
129 }
130 
CSS_PRNG_KickOff(void)131 static status_t CSS_PRNG_KickOff(void)
132 {
133     mcuxClCss_KeyProp_t key_properties;
134     status_t status = kStatus_Fail;
135 
136     /* Check if PRNG already ready */
137     if((CSS->CSS_STATUS & CSS_CSS_STATUS_prng_rdy_MASK) == 0u)
138     {
139         /* Check if key slot 18 is available in CSS keystore */
140         /* Note if you are using slot 18 in your application, please change TEMPORARY_KEY_SLOT_256 to any unused slot */
141         status = CSS_check_key(TEMPORARY_KEY_SLOT_256, &key_properties);
142         if (status != kStatus_Success || key_properties.bits.kactv == 1u)
143         {
144             return kStatus_SlotUnavailable;
145         }
146 
147         /* delete empty temp keyslot; */
148         /* Even if KDELETE is requested to delete an inactive key, the css entropy level will be raised to low and the PRNG
149          * will go ready, */
150         MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED(result0, token0, mcuxClCss_KeyDelete_Async(TEMPORARY_KEY_SLOT_256));
151         if ((token0 != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_KeyDelete_Async)) || (result0 != MCUXCLCSS_STATUS_OK_WAIT))
152         {
153             return kStatus_Fail;
154         }
155 
156         MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED(result1, token1, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
157         if ((token1 != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation)) || (result1 != MCUXCLCSS_STATUS_OK))
158         {
159             return kStatus_Fail;
160         }
161     }
162 
163     return kStatus_Success;
164 }
165