^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/fips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "cc_driver.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "cc_fips.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static void fips_dsr(unsigned long devarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct cc_fips_handle {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct tasklet_struct tasklet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct notifier_block nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct cc_drvdata *drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* The function called once at driver entry point to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * whether TEE FIPS error occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static bool cc_get_tee_fips_status(struct cc_drvdata *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) reg = cc_ioread(drvdata, CC_REG(GPR_HOST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Did the TEE report status? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (reg & CC_FIPS_SYNC_TEE_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Yes. Is it OK? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return (reg & CC_FIPS_SYNC_MODULE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* No. It's either not in use or will be reported later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * This function should push the FIPS REE library status towards the TEE library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * by writing the error state to HOST_GPR0 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void cc_set_ree_fips_status(struct cc_drvdata *drvdata, bool status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int val = CC_FIPS_SYNC_REE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (drvdata->hw_rev < CC_HW_REV_712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) val |= (status ? CC_FIPS_SYNC_MODULE_OK : CC_FIPS_SYNC_MODULE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cc_iowrite(drvdata, CC_REG(HOST_GPR0), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* Push REE side FIPS test failure to TEE side */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int cc_ree_fips_failure(struct notifier_block *nb, unsigned long unused1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void *unused2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct cc_fips_handle *fips_h =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) container_of(nb, struct cc_fips_handle, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct cc_drvdata *drvdata = fips_h->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct device *dev = drvdata_to_dev(drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) cc_set_ree_fips_status(drvdata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dev_info(dev, "Notifying TEE of FIPS test failure...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) void cc_fips_fini(struct cc_drvdata *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct cc_fips_handle *fips_h = drvdata->fips_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (drvdata->hw_rev < CC_HW_REV_712 || !fips_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) atomic_notifier_chain_unregister(&fips_fail_notif_chain, &fips_h->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Kill tasklet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) tasklet_kill(&fips_h->tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) drvdata->fips_handle = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) void fips_handler(struct cc_drvdata *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct cc_fips_handle *fips_handle_ptr = drvdata->fips_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (drvdata->hw_rev < CC_HW_REV_712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) tasklet_schedule(&fips_handle_ptr->tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static inline void tee_fips_error(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (fips_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) panic("ccree: TEE reported cryptographic error in fips mode!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dev_err(dev, "TEE reported error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * This function check if cryptocell tee fips error occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * and in such case triggers system error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void cc_tee_handle_fips_error(struct cc_drvdata *p_drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct device *dev = drvdata_to_dev(p_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!cc_get_tee_fips_status(p_drvdata))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) tee_fips_error(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Deferred service handler, run as interrupt-fired tasklet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void fips_dsr(unsigned long devarg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct cc_drvdata *drvdata = (struct cc_drvdata *)devarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 irq, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) irq = (drvdata->irq & (CC_GPR0_IRQ_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) cc_tee_handle_fips_error(drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* after verifying that there is nothing to do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * unmask AXI completion interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) val = (CC_REG(HOST_IMR) & ~irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* The function called once at driver entry point .*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int cc_fips_init(struct cc_drvdata *p_drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct cc_fips_handle *fips_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct device *dev = drvdata_to_dev(p_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (p_drvdata->hw_rev < CC_HW_REV_712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fips_h = devm_kzalloc(dev, sizeof(*fips_h), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (!fips_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) p_drvdata->fips_handle = fips_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev_dbg(dev, "Initializing fips tasklet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) fips_h->drvdata = p_drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fips_h->nb.notifier_call = cc_ree_fips_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) atomic_notifier_chain_register(&fips_fail_notif_chain, &fips_h->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) cc_tee_handle_fips_error(p_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }