1 /*
2 * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stddef.h>
10 #include "cc_pal_mutex.h"
11 #include "cc_pal_abort.h"
12 #include "chacha_driver.h"
13 #include "driver_defs.h"
14 #include "cc_hal.h"
15 #include "cc_hal_plat.h"
16 #include "cc_sram_map.h"
17 #include "cc_regs.h"
18 #include "dx_crys_kernel.h"
19 #include "cc_util_pm.h"
20
21
22 extern CC_PalMutex CCSymCryptoMutex;
23
24 /* chacha mode, poly1305 disabled, 256 bit key, 20 rounds, 64 bit iv, do not reset the block counter (overwritten by the context) */
25 #define CHACHA_CONTROL_REG_VAL (1 << DX_CHACHA_CONTROL_REG_INIT_FROM_HOST_BIT_SHIFT)
26 #define CHACHA_CONTROL_REG_USE_IV_96 (1 << DX_CHACHA_CONTROL_REG_USE_IV_96BIT_BIT_SHIFT)
27
28 /******************************************************************************
29 * PRIVATE FUNCTIONS
30 ******************************************************************************/
31
InitChacha(ChachaContext_t * chachaCtx)32 static drvError_t InitChacha(ChachaContext_t *chachaCtx)
33 {
34 uint32_t irrVal = 0;
35
36 /* verify user context pointer */
37 if ( chachaCtx == NULL ) {
38 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
39 }
40
41 /* verify chacha valid input addr type */
42 if ( (chachaCtx->inputDataAddrType != SRAM_ADDR) &&
43 (chachaCtx->inputDataAddrType != DLLI_ADDR) ) {
44 return CHACHA_DRV_ILLEGAL_INPUT_ADDR_MEM_ERROR;
45 }
46
47 /* verify chacha valid output addr type */
48 if ( (chachaCtx->outputDataAddrType != SRAM_ADDR) &&
49 (chachaCtx->outputDataAddrType != DLLI_ADDR) ) {
50 return CHACHA_DRV_ILLEGAL_OUTPUT_ADDR_MEM_ERROR;
51 }
52
53 /* make sure sym engines are ready to use */
54 CC_HAL_WAIT_ON_CRYPTO_BUSY();
55
56 /* clear all interrupts before starting the engine */
57 CC_HalClearInterruptBit(0xFFFFFFFFUL);
58
59 /* mask dma interrupts which are not required */
60 irrVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR));
61 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, SRAM_TO_DIN_MASK, irrVal, 1);
62 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, DOUT_TO_SRAM_MASK, irrVal, 1);
63 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, MEM_TO_DIN_MASK, irrVal, 1);
64 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, DOUT_TO_MEM_MASK, irrVal, 1);
65 CC_REG_FLD_SET(HOST_RGF, HOST_IMR, SYM_DMA_COMPLETED_MASK, irrVal, 0);
66 CC_HalMaskInterrupt(irrVal);
67
68 /* configure DIN-CHACHA-DOUT */
69 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CRYPTO_CTL) ,CONFIG_DIN_CHACHA_DOUT_VAL);
70
71 return CHACHA_DRV_OK;
72 }
73
LoadChachaState(ChachaContext_t * chachaCtx)74 static drvError_t LoadChachaState(ChachaContext_t *chachaCtx)
75 {
76 /* verify user context pointer */
77 if (chachaCtx == NULL) {
78 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
79 }
80
81 /* write the initial counter value according to mode */
82 if (chachaCtx->nonceSize == NONCE_SIZE_64) {
83 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB), chachaCtx->blockCounterMsb);
84 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0), chachaCtx->nonceBuf[0]);
85 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1), chachaCtx->nonceBuf[1]);
86 }
87 else if (chachaCtx->nonceSize == NONCE_SIZE_96) {
88 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB), chachaCtx->nonceBuf[0]);
89 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0), chachaCtx->nonceBuf[1]);
90 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1), chachaCtx->nonceBuf[2]);
91 }
92 else {
93 return CHACHA_DRV_ILLEGAL_NONCE_SIZE_ERROR;
94 }
95 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_LSB), chachaCtx->blockCounterLsb);
96
97 return CHACHA_DRV_OK;
98 }
99
100
StoreChachaState(ChachaContext_t * chachaCtx)101 static drvError_t StoreChachaState(ChachaContext_t *chachaCtx)
102 {
103 /* verify user context pointer */
104 if (chachaCtx == NULL) {
105 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
106 }
107
108 /* read the initial counter value according to mode */
109 if (chachaCtx->nonceSize == NONCE_SIZE_64) {
110 chachaCtx->blockCounterMsb = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB));
111 chachaCtx->nonceBuf[0] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0));
112 chachaCtx->nonceBuf[1] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1));
113 }
114 else if (chachaCtx->nonceSize == NONCE_SIZE_96) {
115 chachaCtx->nonceBuf[0] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB));
116 chachaCtx->nonceBuf[1] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0));
117 chachaCtx->nonceBuf[2] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1));
118 }
119 else {
120 return CHACHA_DRV_ILLEGAL_NONCE_SIZE_ERROR;
121 }
122 chachaCtx->blockCounterLsb = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_LSB));
123
124 return CHACHA_DRV_OK;
125 }
126
LoadChachaKey(ChachaContext_t * chachaCtx)127 static drvError_t LoadChachaKey(ChachaContext_t *chachaCtx)
128 {
129 int enrtyNum = 0;
130
131 /* verify user context pointer */
132 if (chachaCtx == NULL) {
133 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
134 }
135
136 for (enrtyNum = 0; enrtyNum < CHACHA_256_BIT_KEY_SIZE_WORDS; ++enrtyNum) {
137 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_KEY0) + (sizeof(uint32_t) * enrtyNum), chachaCtx->keyBuf[enrtyNum]);
138 }
139
140 return CHACHA_DRV_OK;
141 }
142
143 /******************************************************************************
144 * PUBLIC FUNCTIONS
145 ******************************************************************************/
ProcessChacha(ChachaContext_t * chachaCtx,CCBuffInfo_t * pInputBuffInfo,CCBuffInfo_t * pOutputBuffInfo,uint32_t inDataSize)146 drvError_t ProcessChacha(ChachaContext_t *chachaCtx, CCBuffInfo_t *pInputBuffInfo, CCBuffInfo_t *pOutputBuffInfo, uint32_t inDataSize)
147 {
148 uint32_t irrVal = 0;
149 uint32_t chachaCtrl = CHACHA_CONTROL_REG_VAL;
150 drvError_t drvRc = CHACHA_DRV_OK;
151 uint32_t regVal = 0;
152 uint32_t inputDataAddr, outputDataAddr;
153
154 /* check input parameters */
155 if ( (pInputBuffInfo == NULL) || (pOutputBuffInfo == NULL)) {
156 return CHACHA_DRV_INVALID_USER_DATA_BUFF_POINTER_ERROR;
157 }
158
159 /* verify user context pointer */
160 if ( chachaCtx == NULL ) {
161 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
162 }
163 if (((chachaCtx->inputDataAddrType == SRAM_ADDR) && (inDataSize >= CC_SRAM_MAX_SIZE)) ||
164 ((chachaCtx->inputDataAddrType == DLLI_ADDR) && (inDataSize >= DLLI_MAX_BUFF_SIZE))) {
165 return CHACHA_DRV_ILLEGAL_MEM_SIZE_ERROR;
166 }
167
168 /* lock mutex for more chacha hw operation */
169 drvRc = CC_PalMutexLock(&CCSymCryptoMutex, CC_INFINITE);
170 if (drvRc != 0) {
171 CC_PalAbort("Fail to acquire mutex\n");
172 }
173
174 /* increase CC counter at the beginning of each operation */
175 drvRc = CC_IS_WAKE;
176 if (drvRc != 0) {
177 CC_PalAbort("Fail to increase PM counter\n");
178 }
179
180 /* enable clock */
181 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CLK_ENABLE) ,SET_CLOCK_ENABLE);
182 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DMA_CLK_ENABLE) ,SET_CLOCK_ENABLE);
183
184 drvRc = InitChacha(chachaCtx);
185 if (drvRc != CHACHA_DRV_OK) {
186 goto ProcessExit;
187 }
188
189 /* write the initial counter value */
190 drvRc = LoadChachaState(chachaCtx);
191 if (drvRc != CHACHA_DRV_OK) {
192 goto ProcessExit;
193 }
194
195 /* load key */
196 drvRc = LoadChachaKey(chachaCtx);
197 if (drvRc != CHACHA_DRV_OK) {
198 goto ProcessExit;
199 }
200
201 /* configure the CHACHA mode */
202 if (chachaCtx->nonceSize == NONCE_SIZE_96) {
203 chachaCtrl |= CHACHA_CONTROL_REG_USE_IV_96;
204 }
205
206 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CONTROL_REG), chachaCtrl);
207
208 inputDataAddr = pInputBuffInfo->dataBuffAddr;
209 outputDataAddr = pOutputBuffInfo->dataBuffAddr;
210
211 /* configure the HW with the correct data buffer attributes (secure/non-secure) */
212 CC_REG_FLD_SET(HOST_RGF, AHBM_HNONSEC, AHB_READ_HNONSEC, regVal, pInputBuffInfo->dataBuffNs);
213 CC_REG_FLD_SET(HOST_RGF, AHBM_HNONSEC, AHB_WRITE_HNONSEC, regVal, pOutputBuffInfo->dataBuffNs);
214 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, AHBM_HNONSEC) ,regVal);
215
216 /* configure destination address and size */
217 /* and set dout bit in irr */
218 if (chachaCtx->outputDataAddrType == DLLI_ADDR) {
219 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DST_LLI_WORD0) ,outputDataAddr);
220 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DST_LLI_WORD1) ,inDataSize);
221 } else {
222 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRAM_DEST_ADDR) ,outputDataAddr);
223 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DOUT_SRAM_BYTES_LEN) ,inDataSize);
224 }
225
226 /* configure source address and size */
227 if (chachaCtx->inputDataAddrType == DLLI_ADDR) {
228 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRC_LLI_WORD0) ,inputDataAddr);
229 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRC_LLI_WORD1) ,inDataSize);
230 } else {
231 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRAM_SRC_ADDR) ,inputDataAddr);
232 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DIN_SRAM_BYTES_LEN) ,inDataSize);
233 }
234
235 /* set dma completion bit in irr */
236 CC_REG_FLD_SET(HOST_RGF, HOST_IRR, SYM_DMA_COMPLETED, irrVal, 1);
237 drvRc = CC_HalWaitInterrupt(irrVal);
238 if (drvRc != CHACHA_DRV_OK) {
239 goto ProcessExit;
240 }
241 /* get machine state */
242 drvRc = StoreChachaState(chachaCtx);
243 if (drvRc != CHACHA_DRV_OK) {
244 goto ProcessExit;
245 }
246
247 ProcessExit:
248 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CLK_ENABLE) ,SET_CLOCK_DISABLE);
249 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DMA_CLK_ENABLE) ,SET_CLOCK_DISABLE);
250
251 /* decrease CC counter at the end of each operation */
252 if (CC_IS_IDLE != 0) {
253 CC_PalAbort("Fail to decrease PM counter\n");
254 }
255
256 /* release mutex */
257 if (CC_PalMutexUnlock(&CCSymCryptoMutex) != 0) {
258 CC_PalAbort("Fail to release mutex\n");
259 }
260
261 return drvRc;
262 }
263