2 * Copyright (C) 2012-2017 ARM Limited or its affiliates.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 /**************************************************************
18 * This file defines the driver FIPS internal function, used by the driver itself.
19 ***************************************************************/
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <crypto/des.h>
25 #include "ssi_config.h"
26 #include "ssi_driver.h"
30 #define FIPS_POWER_UP_TEST_CIPHER 1
31 #define FIPS_POWER_UP_TEST_CMAC 1
32 #define FIPS_POWER_UP_TEST_HASH 1
33 #define FIPS_POWER_UP_TEST_HMAC 1
34 #define FIPS_POWER_UP_TEST_CCM 1
35 #define FIPS_POWER_UP_TEST_GCM 1
37 static bool ssi_fips_support = 1;
38 module_param(ssi_fips_support, bool, 0644);
39 MODULE_PARM_DESC(ssi_fips_support, "FIPS supported flag: 0 - off , 1 - on (default)");
41 static void fips_dsr(unsigned long devarg);
43 struct ssi_fips_handle {
45 struct workqueue_struct *workq;
46 struct delayed_work fipswork;
48 struct tasklet_struct fipstask;
53 extern int ssi_fips_get_state(ssi_fips_state_t *p_state);
54 extern int ssi_fips_get_error(enum cc_fips_error *p_err);
55 extern int ssi_fips_ext_set_state(ssi_fips_state_t state);
56 extern int ssi_fips_ext_set_error(enum cc_fips_error err);
58 /* FIPS power-up tests */
59 extern enum cc_fips_error ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
60 extern enum cc_fips_error ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
61 extern enum cc_fips_error ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
62 extern enum cc_fips_error ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
63 extern enum cc_fips_error ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
64 extern enum cc_fips_error ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
65 extern size_t ssi_fips_max_mem_alloc_size(void);
68 /* The function called once at driver entry point to check whether TEE FIPS error occured.*/
69 static enum ssi_fips_error ssi_fips_get_tee_error(struct ssi_drvdata *drvdata)
72 void __iomem *cc_base = drvdata->cc_base;
74 regVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST));
75 if (regVal == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
76 return CC_REE_FIPS_ERROR_OK;
78 return CC_REE_FIPS_ERROR_FROM_TEE;
83 * This function should push the FIPS REE library status towards the TEE library.
84 * By writing the error state to HOST_GPR0 register. The function is called from
85 * driver entry point so no need to protect by mutex.
87 static void ssi_fips_update_tee_upon_ree_status(struct ssi_drvdata *drvdata, enum cc_fips_error err)
89 void __iomem *cc_base = drvdata->cc_base;
90 if (err == CC_REE_FIPS_ERROR_OK)
91 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_OK));
93 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_ERROR));
98 void ssi_fips_fini(struct ssi_drvdata *drvdata)
100 struct ssi_fips_handle *fips_h = drvdata->fips_handle;
103 return; /* Not allocated */
107 flush_workqueue(fips_h->workq);
108 destroy_workqueue(fips_h->workq);
112 tasklet_kill(&fips_h->fipstask);
114 memset(fips_h, 0, sizeof(struct ssi_fips_handle));
116 drvdata->fips_handle = NULL;
119 void fips_handler(struct ssi_drvdata *drvdata)
121 struct ssi_fips_handle *fips_handle_ptr =
122 drvdata->fips_handle;
124 queue_delayed_work(fips_handle_ptr->workq, &fips_handle_ptr->fipswork, 0);
126 tasklet_schedule(&fips_handle_ptr->fipstask);
133 static void fips_wq_handler(struct work_struct *work)
135 struct ssi_drvdata *drvdata =
136 container_of(work, struct ssi_drvdata, fipswork.work);
138 fips_dsr((unsigned long)drvdata);
142 /* Deferred service handler, run as interrupt-fired tasklet */
143 static void fips_dsr(unsigned long devarg)
145 struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg;
146 void __iomem *cc_base = drvdata->cc_base;
148 u32 teeFipsError = 0;
150 irq = (drvdata->irq & (SSI_GPR0_IRQ_MASK));
152 if (irq & SSI_GPR0_IRQ_MASK) {
153 teeFipsError = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST));
154 if (teeFipsError != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
155 ssi_fips_set_error(drvdata, CC_REE_FIPS_ERROR_FROM_TEE);
158 /* after verifing that there is nothing to do, Unmask AXI completion interrupt */
159 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR),
160 CC_HAL_READ_REGISTER(
161 CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq);
165 enum cc_fips_error cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata)
167 enum cc_fips_error fips_error = CC_REE_FIPS_ERROR_OK;
168 void *cpu_addr_buffer = NULL;
169 dma_addr_t dma_handle;
170 size_t alloc_buff_size = ssi_fips_max_mem_alloc_size();
171 struct device *dev = &drvdata->plat_dev->dev;
173 // allocate memory using dma_alloc_coherent - for phisical, consecutive and cache coherent buffer (memory map is not needed)
174 // the return value is the virtual address - use it to copy data into the buffer
175 // the dma_handle is the returned phy address - use it in the HW descriptor
176 FIPS_DBG("dma_alloc_coherent \n");
177 cpu_addr_buffer = dma_alloc_coherent(dev, alloc_buff_size, &dma_handle, GFP_KERNEL);
178 if (!cpu_addr_buffer)
179 return CC_REE_FIPS_ERROR_GENERAL;
181 FIPS_DBG("allocated coherent buffer - addr 0x%08X , size = %d \n", (size_t)cpu_addr_buffer, alloc_buff_size);
183 #if FIPS_POWER_UP_TEST_CIPHER
184 FIPS_DBG("ssi_cipher_fips_power_up_tests ...\n");
185 fips_error = ssi_cipher_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
186 FIPS_DBG("ssi_cipher_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
188 #if FIPS_POWER_UP_TEST_CMAC
189 if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) {
190 FIPS_DBG("ssi_cmac_fips_power_up_tests ...\n");
191 fips_error = ssi_cmac_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
192 FIPS_DBG("ssi_cmac_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
195 #if FIPS_POWER_UP_TEST_HASH
196 if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) {
197 FIPS_DBG("ssi_hash_fips_power_up_tests ...\n");
198 fips_error = ssi_hash_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
199 FIPS_DBG("ssi_hash_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
202 #if FIPS_POWER_UP_TEST_HMAC
203 if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) {
204 FIPS_DBG("ssi_hmac_fips_power_up_tests ...\n");
205 fips_error = ssi_hmac_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
206 FIPS_DBG("ssi_hmac_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
209 #if FIPS_POWER_UP_TEST_CCM
210 if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) {
211 FIPS_DBG("ssi_ccm_fips_power_up_tests ...\n");
212 fips_error = ssi_ccm_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
213 FIPS_DBG("ssi_ccm_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
216 #if FIPS_POWER_UP_TEST_GCM
217 if (likely(fips_error == CC_REE_FIPS_ERROR_OK)) {
218 FIPS_DBG("ssi_gcm_fips_power_up_tests ...\n");
219 fips_error = ssi_gcm_fips_power_up_tests(drvdata, cpu_addr_buffer, dma_handle);
220 FIPS_DBG("ssi_gcm_fips_power_up_tests - done. (fips_error = %d) \n", fips_error);
223 /* deallocate the buffer when all tests are done... */
224 FIPS_DBG("dma_free_coherent \n");
225 dma_free_coherent(dev, alloc_buff_size, cpu_addr_buffer, dma_handle);
232 /* The function checks if FIPS supported and FIPS error exists.*
233 * It should be used in every driver API.
235 int ssi_fips_check_fips_error(void)
237 ssi_fips_state_t fips_state;
239 if (ssi_fips_get_state(&fips_state) != 0) {
240 FIPS_LOG("ssi_fips_get_state FAILED, returning.. \n");
243 if (fips_state == CC_FIPS_STATE_ERROR) {
244 FIPS_LOG("ssi_fips_get_state: fips_state is %d, returning.. \n", fips_state);
251 /* The function sets the REE FIPS state.*
252 * It should be used while driver is being loaded.
254 int ssi_fips_set_state(ssi_fips_state_t state)
256 return ssi_fips_ext_set_state(state);
259 /* The function sets the REE FIPS error, and pushes the error to TEE library. *
260 * It should be used when any of the KAT tests fails.
262 int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, enum cc_fips_error err)
265 enum cc_fips_error current_err;
267 FIPS_LOG("ssi_fips_set_error - fips_error = %d \n", err);
269 // setting no error is not allowed
270 if (err == CC_REE_FIPS_ERROR_OK)
273 // If error exists, do not set new error
274 if (ssi_fips_get_error(¤t_err) != 0)
277 if (current_err != CC_REE_FIPS_ERROR_OK)
280 // set REE internal error and state
281 rc = ssi_fips_ext_set_error(err);
285 rc = ssi_fips_ext_set_state(CC_FIPS_STATE_ERROR);
289 // push error towards TEE libraray, if it's not TEE error
290 if (err != CC_REE_FIPS_ERROR_FROM_TEE)
291 ssi_fips_update_tee_upon_ree_status(p_drvdata, err);
297 /* The function called once at driver entry point .*/
298 int ssi_fips_init(struct ssi_drvdata *p_drvdata)
300 enum cc_fips_error rc = CC_REE_FIPS_ERROR_OK;
301 struct ssi_fips_handle *fips_h;
303 FIPS_DBG("CC FIPS code .. (fips=%d) \n", ssi_fips_support);
305 fips_h = kzalloc(sizeof(struct ssi_fips_handle), GFP_KERNEL);
307 ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
311 p_drvdata->fips_handle = fips_h;
314 SSI_LOG_DEBUG("Initializing fips workqueue\n");
315 fips_h->workq = create_singlethread_workqueue("arm_cc7x_fips_wq");
316 if (unlikely(!fips_h->workq)) {
317 SSI_LOG_ERR("Failed creating fips work queue\n");
318 ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
320 goto ssi_fips_init_err;
322 INIT_DELAYED_WORK(&fips_h->fipswork, fips_wq_handler);
324 SSI_LOG_DEBUG("Initializing fips tasklet\n");
325 tasklet_init(&fips_h->fipstask, fips_dsr, (unsigned long)p_drvdata);
328 /* init fips driver data */
329 rc = ssi_fips_set_state((ssi_fips_support == 0) ? CC_FIPS_STATE_NOT_SUPPORTED : CC_FIPS_STATE_SUPPORTED);
330 if (unlikely(rc != 0)) {
331 ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
333 goto ssi_fips_init_err;
336 /* Run power up tests (before registration and operating the HW engines) */
337 FIPS_DBG("ssi_fips_get_tee_error \n");
338 rc = ssi_fips_get_tee_error(p_drvdata);
339 if (unlikely(rc != CC_REE_FIPS_ERROR_OK)) {
340 ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_FROM_TEE);
342 goto ssi_fips_init_err;
345 FIPS_DBG("cc_fips_run_power_up_tests \n");
346 rc = cc_fips_run_power_up_tests(p_drvdata);
347 if (unlikely(rc != CC_REE_FIPS_ERROR_OK)) {
348 ssi_fips_set_error(p_drvdata, rc);
350 goto ssi_fips_init_err;
352 FIPS_LOG("cc_fips_run_power_up_tests - done ... fips_error = %d \n", rc);
354 /* when all tests passed, update TEE with fips OK status after power up tests */
355 ssi_fips_update_tee_upon_ree_status(p_drvdata, CC_REE_FIPS_ERROR_OK);
357 if (unlikely(rc != 0)) {
359 ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
360 goto ssi_fips_init_err;
366 ssi_fips_fini(p_drvdata);