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