1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 #include "cc_pal_mutex.h"
9 #include "cc_pal_abort.h"
10 #include "chacha_driver.h"
11 #include "chacha_driver_ext_dma.h"
12 #include "driver_defs.h"
13 #include "cc_hal.h"
14 #include "cc_hal_plat.h"
15 #include "cc_regs.h"
16 #include "dx_crys_kernel.h"
17 #include "cc_util_pm.h"
18 
19 
20 extern CC_PalMutex CCSymCryptoMutex;
21 
22 /* chacha mode, poly1305 disabled, 256 bit key, 20 rounds, 64 bit iv, do not reset the block counter (overwritten by the context) */
23 #define CHACHA_CONTROL_REG_VAL        (1 << DX_CHACHA_CONTROL_REG_INIT_FROM_HOST_BIT_SHIFT)
24 #define CHACHA_CONTROL_REG_USE_IV_96  (1 << DX_CHACHA_CONTROL_REG_USE_IV_96BIT_BIT_SHIFT)
25 
26 /******************************************************************************
27 *               PRIVATE FUNCTIONS
28 ******************************************************************************/
29 
LoadChachaExtDmaState(uint32_t * pNonceBuf,chachaNonceSize_t nonceSizeFlag,uint32_t blockCounterLsb)30 static drvError_t LoadChachaExtDmaState(uint32_t *pNonceBuf, chachaNonceSize_t nonceSizeFlag, uint32_t blockCounterLsb)
31 {
32         /* verify user context pointer */
33         if (pNonceBuf == NULL) {
34                 return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
35         }
36 
37         /* write the initial counter value according to mode */
38         if (nonceSizeFlag == NONCE_SIZE_64) {
39                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB), 0);
40                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0), pNonceBuf[0]);
41                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1), pNonceBuf[1]);
42         }
43         else if (nonceSizeFlag == NONCE_SIZE_96) {
44                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_MSB), pNonceBuf[0]);
45                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_0), pNonceBuf[1]);
46                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_IV_1), pNonceBuf[2]);
47         }
48         else {
49                 return CHACHA_DRV_ILLEGAL_NONCE_SIZE_ERROR;
50         }
51         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_BLOCK_CNT_LSB), blockCounterLsb);
52 
53         return CHACHA_DRV_OK;
54 }
55 
LoadChachaKeyExtDma(uint32_t * pKey)56 static drvError_t LoadChachaKeyExtDma(uint32_t *pKey)
57 {
58         int enrtyNum = 0;
59 
60         /* verify user context pointer */
61         if (pKey == NULL) {
62             return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
63         }
64 
65         for (enrtyNum = 0; enrtyNum < CHACHA_256_BIT_KEY_SIZE_WORDS; ++enrtyNum) {
66             CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_KEY0) + (sizeof(uint32_t) * enrtyNum), pKey[enrtyNum]);
67         }
68 
69         return CHACHA_DRV_OK;
70 }
71 
72 /******************************************************************************
73 *               PUBLIC FUNCTIONS
74 ******************************************************************************/
InitChachaExtDma(uint32_t * pNonceBuf,chachaNonceSize_t nonceSizeFlag,uint32_t * keyBuf,uint32_t initialCounter,uint32_t dataLen)75 drvError_t InitChachaExtDma(uint32_t *pNonceBuf, chachaNonceSize_t nonceSizeFlag, uint32_t *keyBuf, uint32_t initialCounter, uint32_t dataLen)
76 {
77     uint32_t irrVal = 0;
78     uint32_t chachaCtrl = CHACHA_CONTROL_REG_VAL;
79     drvError_t drvRc = CHACHA_DRV_OK;
80     drvError_t rc = AES_DRV_OK;
81 
82     if (pNonceBuf == NULL || keyBuf == NULL) {
83         return CHACHA_DRV_INVALID_USER_CONTEXT_POINTER_ERROR;
84     }
85     /* lock mutex for more chacha hw operation */
86     drvRc = CC_PalMutexLock(&CCSymCryptoMutex, CC_INFINITE);
87     if (drvRc != 0) {
88         CC_PalAbort("Fail to acquire mutex\n");
89     }
90 
91     /* increase CC counter at the beginning of each operation */
92     drvRc = CC_IS_WAKE;
93     if (drvRc != 0) {
94         CC_PalAbort("Fail to increase PM counter\n");
95     }
96 
97     /* enable clock */
98     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CLK_ENABLE) ,SET_CLOCK_ENABLE);
99     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DMA_CLK_ENABLE) ,SET_CLOCK_ENABLE);
100 
101     /* make sure sym engines are ready to use */
102     CC_HAL_WAIT_ON_CRYPTO_BUSY();
103 
104     /* clear all interrupts before starting the engine */
105     CC_HalClearInterruptBit(0xFFFFFFFFUL);
106 
107     /* mask dma interrupts which are not required */
108     irrVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR));
109     CC_REG_FLD_SET(HOST_RGF, HOST_IMR, SRAM_TO_DIN_MASK, irrVal, 1);
110     CC_REG_FLD_SET(HOST_RGF, HOST_IMR, DOUT_TO_SRAM_MASK, irrVal, 1);
111     CC_REG_FLD_SET(HOST_RGF, HOST_IMR, MEM_TO_DIN_MASK, irrVal, 1);
112     CC_REG_FLD_SET(HOST_RGF, HOST_IMR, DOUT_TO_MEM_MASK, irrVal, 1);
113     CC_REG_FLD_SET(HOST_RGF, HOST_IMR, SYM_DMA_COMPLETED_MASK, irrVal, 1);
114     CC_HalMaskInterrupt(irrVal);
115 
116     /* configure DIN-CHACHA-DOUT */
117     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CRYPTO_CTL) ,CONFIG_DIN_CHACHA_DOUT_VAL);
118 
119     /* write the initial counter value */
120     drvRc = LoadChachaExtDmaState(pNonceBuf, nonceSizeFlag, initialCounter);
121     if (drvRc != CHACHA_DRV_OK) {
122             goto InitExit;
123     }
124 
125     /* load key */
126     drvRc = LoadChachaKeyExtDma(keyBuf);
127     if (drvRc != CHACHA_DRV_OK) {
128             goto InitExit;
129     }
130 
131     /* configure the CHACHA mode */
132     if (nonceSizeFlag == NONCE_SIZE_96) {
133         chachaCtrl |= CHACHA_CONTROL_REG_USE_IV_96;
134     }
135 
136     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CONTROL_REG), chachaCtrl);
137 
138     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DIN_CPU_DATA_SIZE) , dataLen);
139 
140     return CHACHA_DRV_OK;
141 
142 InitExit:
143 
144     rc = terminateChachaExtDma();
145     if (rc != 0) {
146         CC_PalAbort("Failed to terminateAesExtDma \n");
147     }
148     return drvRc;
149 }
150 
terminateChachaExtDma(void)151 drvError_t terminateChachaExtDma(void)
152 {
153     drvError_t rc = AES_DRV_OK;
154 
155     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, CHACHA_CLK_ENABLE) ,SET_CLOCK_DISABLE);
156     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, DMA_CLK_ENABLE) ,SET_CLOCK_DISABLE);
157 
158     /* decrease CC counter at the end of each operation */
159     rc = CC_IS_IDLE;
160     if (rc != 0) {
161         CC_PalAbort("Fail to decrease PM counter\n");
162     }
163 
164     /* unlock mutex for more aes hw operation */
165     rc = CC_PalMutexUnlock(&CCSymCryptoMutex);
166     if (rc != 0) {
167         CC_PalAbort("Fail to unlock mutex\n");
168     }
169     return rc;
170 }
171