diff options
-rw-r--r-- | arch/arm/boot/dts/imx6qdl.dtsi | 16 | ||||
-rw-r--r-- | drivers/crypto/caam/Kconfig | 6 | ||||
-rw-r--r-- | drivers/crypto/caam/Makefile | 6 | ||||
-rw-r--r-- | drivers/crypto/caam/ctrl.c | 19 | ||||
-rw-r--r-- | drivers/crypto/caam/intern.h | 5 | ||||
-rw-r--r-- | drivers/crypto/caam/secvio.c | 335 | ||||
-rw-r--r-- | drivers/crypto/caam/secvio.h | 64 | ||||
-rw-r--r-- | drivers/crypto/caam/sm.h | 88 | ||||
-rw-r--r-- | drivers/crypto/caam/sm_store.c | 896 | ||||
-rw-r--r-- | drivers/crypto/caam/sm_test.c | 844 | ||||
-rw-r--r-- | drivers/crypto/caam/snvsregs.h | 237 |
11 files changed, 2510 insertions, 6 deletions
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index bd6c7a0c266b..6de80a23995f 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi | |||
@@ -75,6 +75,11 @@ | |||
75 | interrupt-parent = <&intc>; | 75 | interrupt-parent = <&intc>; |
76 | ranges; | 76 | ranges; |
77 | 77 | ||
78 | caam_sm: caam-sm@00100000 { | ||
79 | compatible = "fsl,imx6q-caam-sm"; | ||
80 | reg = <0x00100000 0x3fff>; | ||
81 | }; | ||
82 | |||
78 | dma_apbh: dma-apbh@00110000 { | 83 | dma_apbh: dma-apbh@00110000 { |
79 | compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; | 84 | compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; |
80 | reg = <0x00110000 0x2000>; | 85 | reg = <0x00110000 0x2000>; |
@@ -85,6 +90,12 @@ | |||
85 | clocks = <&clks 106>; | 90 | clocks = <&clks 106>; |
86 | }; | 91 | }; |
87 | 92 | ||
93 | irq_sec_vio: caam_secvio { | ||
94 | compatible = "fsl,imx6q-caam-secvio"; | ||
95 | interrupts = <0 20 0x04>; | ||
96 | secvio_src = <0x8000001d>; | ||
97 | }; | ||
98 | |||
88 | gpmi: gpmi-nand@00112000 { | 99 | gpmi: gpmi-nand@00112000 { |
89 | compatible = "fsl,imx6q-gpmi-nand"; | 100 | compatible = "fsl,imx6q-gpmi-nand"; |
90 | #address-cells = <1>; | 101 | #address-cells = <1>; |
@@ -606,6 +617,11 @@ | |||
606 | fsl,anatop = <&anatop>; | 617 | fsl,anatop = <&anatop>; |
607 | }; | 618 | }; |
608 | 619 | ||
620 | caam_snvs: caam-snvs@020cc000 { | ||
621 | compatible = "fsl,imx6q-caam-snvs"; | ||
622 | reg = <0x020cc000 0x4000>; | ||
623 | }; | ||
624 | |||
609 | snvs@020cc000 { | 625 | snvs@020cc000 { |
610 | compatible = "fsl,sec-v4.0-mon", "simple-bus"; | 626 | compatible = "fsl,sec-v4.0-mon", "simple-bus"; |
611 | #address-cells = <1>; | 627 | #address-cells = <1>; |
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 493fe4073597..0df6f8c3aabe 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig | |||
@@ -107,7 +107,7 @@ config CRYPTO_DEV_FSL_CAAM_RNG_TEST | |||
107 | Selecting this will enable self-test for caam rng. | 107 | Selecting this will enable self-test for caam rng. |
108 | 108 | ||
109 | config CRYPTO_DEV_FSL_CAAM_SM | 109 | config CRYPTO_DEV_FSL_CAAM_SM |
110 | boolean "CAAM Secure Memory / Keystore API (EXPERIMENTAL)" | 110 | tristate "CAAM Secure Memory / Keystore API (EXPERIMENTAL)" |
111 | default n | 111 | default n |
112 | help | 112 | help |
113 | Enables use of a prototype kernel-level Keystore API with CAAM | 113 | Enables use of a prototype kernel-level Keystore API with CAAM |
@@ -130,7 +130,7 @@ config CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE | |||
130 | 9 => 512 bytes | 130 | 9 => 512 bytes |
131 | 131 | ||
132 | config CRYPTO_DEV_FSL_CAAM_SM_TEST | 132 | config CRYPTO_DEV_FSL_CAAM_SM_TEST |
133 | boolean "CAAM Secure Memory - Keystore Test/Example (EXPERIMENTAL)" | 133 | tristate "CAAM Secure Memory - Keystore Test/Example (EXPERIMENTAL)" |
134 | depends on CRYPTO_DEV_FSL_CAAM_SM | 134 | depends on CRYPTO_DEV_FSL_CAAM_SM |
135 | default n | 135 | default n |
136 | help | 136 | help |
@@ -139,7 +139,7 @@ config CRYPTO_DEV_FSL_CAAM_SM_TEST | |||
139 | encryption/decryption. | 139 | encryption/decryption. |
140 | 140 | ||
141 | config CRYPTO_DEV_FSL_CAAM_SECVIO | 141 | config CRYPTO_DEV_FSL_CAAM_SECVIO |
142 | boolean "CAAM/SNVS Security Violation Handler (EXPERIMENTAL)" | 142 | tristate "CAAM/SNVS Security Violation Handler (EXPERIMENTAL)" |
143 | depends on CRYPTO_DEV_FSL_CAAM | 143 | depends on CRYPTO_DEV_FSL_CAAM |
144 | default n | 144 | default n |
145 | help | 145 | help |
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index b7db9e9efea5..2141ac48b163 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile | |||
@@ -6,8 +6,8 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o | |||
6 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o | 6 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o |
7 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o | 7 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o |
8 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o | 8 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o |
9 | #obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM) += sm_store.o | 9 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM) += sm_store.o |
10 | #obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST) += sm_test.o | 10 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST) += sm_test.o |
11 | #obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO) += secvio.o | 11 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO) += secvio.o |
12 | 12 | ||
13 | caam-objs := ctrl.o jr.o error.o key_gen.o | 13 | caam-objs := ctrl.o jr.o error.o key_gen.o |
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 5bc978e8c719..04df1863128b 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "desc_constr.h" | 12 | #include "desc_constr.h" |
13 | #include "error.h" | 13 | #include "error.h" |
14 | #include "ctrl.h" | 14 | #include "ctrl.h" |
15 | #include "sm.h" | ||
15 | 16 | ||
16 | /* Used to capture the array of job rings */ | 17 | /* Used to capture the array of job rings */ |
17 | struct device **caam_jr_dev; | 18 | struct device **caam_jr_dev; |
@@ -236,6 +237,7 @@ static int caam_probe(struct platform_device *pdev) | |||
236 | struct device_node *nprop, *np; | 237 | struct device_node *nprop, *np; |
237 | struct caam_ctrl __iomem *ctrl; | 238 | struct caam_ctrl __iomem *ctrl; |
238 | struct caam_full __iomem *topregs; | 239 | struct caam_full __iomem *topregs; |
240 | struct snvs_full __iomem *snvsregs; | ||
239 | struct caam_drv_private *ctrlpriv; | 241 | struct caam_drv_private *ctrlpriv; |
240 | #ifdef CONFIG_DEBUG_FS | 242 | #ifdef CONFIG_DEBUG_FS |
241 | struct caam_perfmon *perfmon; | 243 | struct caam_perfmon *perfmon; |
@@ -265,6 +267,23 @@ static int caam_probe(struct platform_device *pdev) | |||
265 | /* Get the IRQ of the controller (for security violations only) */ | 267 | /* Get the IRQ of the controller (for security violations only) */ |
266 | ctrlpriv->secvio_irq = of_irq_to_resource(nprop, 0, NULL); | 268 | ctrlpriv->secvio_irq = of_irq_to_resource(nprop, 0, NULL); |
267 | 269 | ||
270 | /* Get SNVS register Page */ | ||
271 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-snvs"); | ||
272 | |||
273 | if (!np) | ||
274 | return -ENODEV; | ||
275 | |||
276 | snvsregs = of_iomap(np, 0); | ||
277 | ctrlpriv->snvs = snvsregs; | ||
278 | /* Get CAAM-SM node and of_iomap() and save */ | ||
279 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm"); | ||
280 | |||
281 | if (!np) | ||
282 | return -ENODEV; | ||
283 | |||
284 | ctrlpriv->sm_base = of_iomap(np, 0); | ||
285 | ctrlpriv->sm_size = 0x3fff; | ||
286 | |||
268 | /* | 287 | /* |
269 | * ARM targets tend to have clock control subsystems that can | 288 | * ARM targets tend to have clock control subsystems that can |
270 | * enable/disable clocking to our device. Turn clocking on to proceed | 289 | * enable/disable clocking to our device. Turn clocking on to proceed |
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 0311f8572822..6bb12f3098fe 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h | |||
@@ -70,6 +70,8 @@ struct caam_drv_private_jr { | |||
70 | struct caam_drv_private { | 70 | struct caam_drv_private { |
71 | 71 | ||
72 | struct device *dev; | 72 | struct device *dev; |
73 | struct device *smdev; | ||
74 | struct device *secviodev; | ||
73 | struct device **jrdev; /* Alloc'ed array per sub-device */ | 75 | struct device **jrdev; /* Alloc'ed array per sub-device */ |
74 | spinlock_t jr_alloc_lock; | 76 | spinlock_t jr_alloc_lock; |
75 | struct platform_device *pdev; | 77 | struct platform_device *pdev; |
@@ -79,6 +81,9 @@ struct caam_drv_private { | |||
79 | struct caam_deco **deco; /* DECO/CCB views */ | 81 | struct caam_deco **deco; /* DECO/CCB views */ |
80 | struct caam_assurance *ac; | 82 | struct caam_assurance *ac; |
81 | struct caam_queue_if *qi; /* QI control region */ | 83 | struct caam_queue_if *qi; /* QI control region */ |
84 | struct snvs_full __iomem *snvs; /* SNVS HP+LP register space */ | ||
85 | dma_addr_t __iomem *sm_base; /* Secure memory storage base */ | ||
86 | u32 sm_size; | ||
82 | 87 | ||
83 | /* | 88 | /* |
84 | * Detected geometry block. Filled in from device tree if powerpc, | 89 | * Detected geometry block. Filled in from device tree if powerpc, |
diff --git a/drivers/crypto/caam/secvio.c b/drivers/crypto/caam/secvio.c new file mode 100644 index 000000000000..defd93cb8887 --- /dev/null +++ b/drivers/crypto/caam/secvio.c | |||
@@ -0,0 +1,335 @@ | |||
1 | |||
2 | /* | ||
3 | * CAAM/SEC 4.x Security Violation Handler | ||
4 | * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved | ||
5 | */ | ||
6 | |||
7 | #include "compat.h" | ||
8 | #include "intern.h" | ||
9 | #include "secvio.h" | ||
10 | #include "regs.h" | ||
11 | |||
12 | /* | ||
13 | * These names are associated with each violation handler. | ||
14 | * The source names were taken from MX6, and are based on recommendations | ||
15 | * for most common SoCs. | ||
16 | */ | ||
17 | static const u8 *violation_src_name[] = { | ||
18 | "CAAM Security Violation", | ||
19 | "JTAG Alarm", | ||
20 | "Watchdog", | ||
21 | "(reserved)", | ||
22 | "External Boot", | ||
23 | "Tamper Detect", | ||
24 | }; | ||
25 | |||
26 | /* Top-level security violation interrupt */ | ||
27 | static irqreturn_t caam_secvio_interrupt(int irq, void *snvsdev) | ||
28 | { | ||
29 | struct device *dev = snvsdev; | ||
30 | struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); | ||
31 | u32 irqstate; | ||
32 | |||
33 | /* Check the HP secvio status register */ | ||
34 | irqstate = rd_reg32(&svpriv->svregs->hp.secvio_status) | | ||
35 | HP_SECVIOST_SECVIOMASK; | ||
36 | |||
37 | if (!irqstate) | ||
38 | return IRQ_NONE; | ||
39 | |||
40 | /* Mask out one or more causes for deferred service */ | ||
41 | clrbits32(&svpriv->svregs->hp.secvio_int_ctl, irqstate); | ||
42 | |||
43 | /* Now ACK causes */ | ||
44 | setbits32(&svpriv->svregs->hp.secvio_status, irqstate); | ||
45 | |||
46 | /* And run deferred service */ | ||
47 | preempt_disable(); | ||
48 | tasklet_schedule(&svpriv->irqtask[smp_processor_id()]); | ||
49 | preempt_enable(); | ||
50 | |||
51 | return IRQ_HANDLED; | ||
52 | } | ||
53 | |||
54 | /* Deferred service handler. Tasklet arg is simply the SNVS dev */ | ||
55 | static void caam_secvio_dispatch(unsigned long indev) | ||
56 | { | ||
57 | struct device *dev = (struct device *)indev; | ||
58 | struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); | ||
59 | unsigned long flags, cause; | ||
60 | int i; | ||
61 | |||
62 | |||
63 | /* | ||
64 | * Capture the interrupt cause, using masked interrupts as | ||
65 | * identification. This only works if all are enabled; if | ||
66 | * this changes in the future, a "cause queue" will have to | ||
67 | * be built | ||
68 | */ | ||
69 | cause = rd_reg32(&svpriv->svregs->hp.secvio_int_ctl) & | ||
70 | (HP_SECVIO_INTEN_SRC5 | HP_SECVIO_INTEN_SRC4 | | ||
71 | HP_SECVIO_INTEN_SRC3 | HP_SECVIO_INTEN_SRC2 | | ||
72 | HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0); | ||
73 | |||
74 | /* Look through causes, call each handler if exists */ | ||
75 | for (i = 0; i < MAX_SECVIO_SOURCES; i++) | ||
76 | if (cause & (1 << i)) { | ||
77 | spin_lock_irqsave(&svpriv->svlock, flags); | ||
78 | svpriv->intsrc[i].handler(dev, i, | ||
79 | svpriv->intsrc[i].ext); | ||
80 | spin_unlock_irqrestore(&svpriv->svlock, flags); | ||
81 | }; | ||
82 | |||
83 | /* Re-enable now-serviced interrupts */ | ||
84 | setbits32(&svpriv->svregs->hp.secvio_int_ctl, cause); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Default cause handler, used in lieu of an application-defined handler. | ||
89 | * All it does at this time is print a console message. It could force a halt. | ||
90 | */ | ||
91 | static void caam_secvio_default(struct device *dev, u32 cause, void *ext) | ||
92 | { | ||
93 | struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); | ||
94 | |||
95 | dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n", | ||
96 | cause, svpriv->intsrc[cause].intname); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Install an application-defined handler for a specified cause | ||
101 | * Arguments: | ||
102 | * - dev points to SNVS-owning device | ||
103 | * - cause interrupt source cause | ||
104 | * - handler application-defined handler, gets called with dev | ||
105 | * source cause, and locally-defined handler argument | ||
106 | * - cause_description points to a string to override the default cause | ||
107 | * name, this can be used as an alternate for error | ||
108 | * messages and such. If left NULL, the default | ||
109 | * description string is used. | ||
110 | * - ext pointer to any extra data needed by the handler. | ||
111 | */ | ||
112 | int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, | ||
113 | void (*handler)(struct device *dev, u32 cause, | ||
114 | void *ext), | ||
115 | u8 *cause_description, void *ext) | ||
116 | { | ||
117 | unsigned long flags; | ||
118 | struct caam_drv_private_secvio *svpriv; | ||
119 | |||
120 | svpriv = dev_get_drvdata(dev); | ||
121 | |||
122 | if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5)) | ||
123 | return -EINVAL; | ||
124 | |||
125 | spin_lock_irqsave(&svpriv->svlock, flags); | ||
126 | svpriv->intsrc[cause].handler = handler; | ||
127 | if (cause_description != NULL) | ||
128 | svpriv->intsrc[cause].intname = cause_description; | ||
129 | if (ext != NULL) | ||
130 | svpriv->intsrc[cause].ext = ext; | ||
131 | spin_unlock_irqrestore(&svpriv->svlock, flags); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | EXPORT_SYMBOL(caam_secvio_install_handler); | ||
136 | |||
137 | /* | ||
138 | * Remove an application-defined handler for a specified cause (and, by | ||
139 | * implication, restore the "default". | ||
140 | * Arguments: | ||
141 | * - dev points to SNVS-owning device | ||
142 | * - cause interrupt source cause | ||
143 | */ | ||
144 | int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause) | ||
145 | { | ||
146 | unsigned long flags; | ||
147 | struct caam_drv_private_secvio *svpriv; | ||
148 | |||
149 | svpriv = dev_get_drvdata(dev); | ||
150 | |||
151 | if (cause > SECVIO_CAUSE_SOURCE_5) | ||
152 | return -EINVAL; | ||
153 | |||
154 | spin_lock_irqsave(&svpriv->svlock, flags); | ||
155 | svpriv->intsrc[cause].intname = violation_src_name[cause]; | ||
156 | svpriv->intsrc[cause].handler = caam_secvio_default; | ||
157 | svpriv->intsrc[cause].ext = NULL; | ||
158 | spin_unlock_irqrestore(&svpriv->svlock, flags); | ||
159 | return 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL(caam_secvio_remove_handler); | ||
162 | |||
163 | int caam_secvio_startup(struct platform_device *pdev) | ||
164 | { | ||
165 | struct device *ctrldev, *svdev; | ||
166 | struct caam_drv_private *ctrlpriv; | ||
167 | struct caam_drv_private_secvio *svpriv; | ||
168 | struct platform_device *svpdev; | ||
169 | struct device_node *np; | ||
170 | const void *prop; | ||
171 | int i, error, secvio_inten_src; | ||
172 | |||
173 | ctrldev = &pdev->dev; | ||
174 | ctrlpriv = dev_get_drvdata(ctrldev); | ||
175 | /* | ||
176 | * Set up the private block for secure memory | ||
177 | * Only one instance is possible | ||
178 | */ | ||
179 | svpriv = kzalloc(sizeof(struct caam_drv_private_secvio), GFP_KERNEL); | ||
180 | if (svpriv == NULL) { | ||
181 | dev_err(ctrldev, "can't alloc private mem for secvio\n"); | ||
182 | return -ENOMEM; | ||
183 | } | ||
184 | svpriv->parentdev = ctrldev; | ||
185 | |||
186 | /* Create the security violation dev */ | ||
187 | #ifdef CONFIG_OF | ||
188 | |||
189 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio"); | ||
190 | if (!np) | ||
191 | return -ENODEV; | ||
192 | |||
193 | ctrlpriv->secvio_irq = of_irq_to_resource(np, 0, NULL); | ||
194 | |||
195 | prop = of_get_property(np, "secvio_src", NULL); | ||
196 | if (prop) | ||
197 | secvio_inten_src = of_read_ulong(prop, 1); | ||
198 | else | ||
199 | secvio_inten_src = HP_SECVIO_INTEN_ALL; | ||
200 | |||
201 | printk(KERN_ERR "secvio_inten_src = %x\n", secvio_inten_src); | ||
202 | |||
203 | svpdev = of_platform_device_create(np, NULL, ctrldev); | ||
204 | if (!svpdev) | ||
205 | return -ENODEV; | ||
206 | |||
207 | #else | ||
208 | svpdev = platform_device_register_data(ctrldev, "caam_secvio", 0, | ||
209 | svpriv, | ||
210 | sizeof(struct caam_drv_private_secvio)); | ||
211 | |||
212 | secvio_inten_src = HP_SECVIO_INTEN_ALL; | ||
213 | #endif | ||
214 | if (svpdev == NULL) { | ||
215 | kfree(svpriv); | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | svdev = &svpdev->dev; | ||
219 | dev_set_drvdata(svdev, svpriv); | ||
220 | ctrlpriv->secviodev = svdev; | ||
221 | svpriv->svregs = ctrlpriv->snvs; | ||
222 | |||
223 | /* | ||
224 | * Now we have all the dev data set up. Init interrupt | ||
225 | * source descriptions | ||
226 | */ | ||
227 | for (i = 0; i < MAX_SECVIO_SOURCES; i++) { | ||
228 | svpriv->intsrc[i].intname = violation_src_name[i]; | ||
229 | svpriv->intsrc[i].handler = caam_secvio_default; | ||
230 | } | ||
231 | |||
232 | /* Connect main handler */ | ||
233 | for_each_possible_cpu(i) | ||
234 | tasklet_init(&svpriv->irqtask[i], caam_secvio_dispatch, | ||
235 | (unsigned long)svdev); | ||
236 | |||
237 | error = request_irq(ctrlpriv->secvio_irq, caam_secvio_interrupt, | ||
238 | IRQF_SHARED, "caam_secvio", svdev); | ||
239 | if (error) { | ||
240 | dev_err(svdev, "can't connect secvio interrupt\n"); | ||
241 | irq_dispose_mapping(ctrlpriv->secvio_irq); | ||
242 | ctrlpriv->secvio_irq = 0; | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | /* Enable all sources */ | ||
247 | wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, secvio_inten_src); | ||
248 | |||
249 | dev_info(svdev, "security violation service handlers armed\n"); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | void caam_secvio_shutdown(struct platform_device *pdev) | ||
255 | { | ||
256 | struct device *ctrldev, *svdev; | ||
257 | struct caam_drv_private *priv; | ||
258 | struct caam_drv_private_secvio *svpriv; | ||
259 | int i; | ||
260 | |||
261 | ctrldev = &pdev->dev; | ||
262 | priv = dev_get_drvdata(ctrldev); | ||
263 | svdev = priv->secviodev; | ||
264 | svpriv = dev_get_drvdata(svdev); | ||
265 | |||
266 | /* Shut off all sources */ | ||
267 | |||
268 | wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, 0); | ||
269 | |||
270 | /* Remove tasklets and release interrupt */ | ||
271 | for_each_possible_cpu(i) | ||
272 | tasklet_kill(&svpriv->irqtask[i]); | ||
273 | |||
274 | free_irq(priv->secvio_irq, svdev); | ||
275 | |||
276 | kfree(svpriv); | ||
277 | } | ||
278 | |||
279 | |||
280 | #ifdef CONFIG_OF | ||
281 | static void __exit caam_secvio_exit(void) | ||
282 | { | ||
283 | struct device_node *dev_node; | ||
284 | struct platform_device *pdev; | ||
285 | |||
286 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
287 | if (!dev_node) { | ||
288 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); | ||
289 | if (!dev_node) | ||
290 | return; | ||
291 | } | ||
292 | |||
293 | pdev = of_find_device_by_node(dev_node); | ||
294 | if (!pdev) | ||
295 | return; | ||
296 | |||
297 | of_node_get(dev_node); | ||
298 | |||
299 | caam_secvio_shutdown(pdev); | ||
300 | |||
301 | } | ||
302 | |||
303 | static int __init caam_secvio_init(void) | ||
304 | { | ||
305 | struct device_node *dev_node; | ||
306 | struct platform_device *pdev; | ||
307 | |||
308 | /* | ||
309 | * Do of_find_compatible_node() then of_find_device_by_node() | ||
310 | * once a functional device tree is available | ||
311 | */ | ||
312 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
313 | if (!dev_node) { | ||
314 | dev_node = of_find_compatible_node(NULL, NULL, | ||
315 | "arm,imx6-caam-secvio"); | ||
316 | if (!dev_node) | ||
317 | return -ENODEV; | ||
318 | } | ||
319 | |||
320 | pdev = of_find_device_by_node(dev_node); | ||
321 | if (!pdev) | ||
322 | return -ENODEV; | ||
323 | |||
324 | of_node_put(dev_node); | ||
325 | |||
326 | return caam_secvio_startup(pdev); | ||
327 | } | ||
328 | |||
329 | module_init(caam_secvio_init); | ||
330 | module_exit(caam_secvio_exit); | ||
331 | |||
332 | MODULE_LICENSE("Dual BSD/GPL"); | ||
333 | MODULE_DESCRIPTION("FSL CAAM/SNVS Security Violation Handler"); | ||
334 | MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); | ||
335 | #endif | ||
diff --git a/drivers/crypto/caam/secvio.h b/drivers/crypto/caam/secvio.h new file mode 100644 index 000000000000..b0efe20bdc5d --- /dev/null +++ b/drivers/crypto/caam/secvio.h | |||
@@ -0,0 +1,64 @@ | |||
1 | |||
2 | /* | ||
3 | * CAAM Security Violation Handler | ||
4 | * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved | ||
5 | */ | ||
6 | |||
7 | #ifndef SECVIO_H | ||
8 | #define SECVIO_H | ||
9 | |||
10 | #include "snvsregs.h" | ||
11 | |||
12 | |||
13 | /* | ||
14 | * Defines the published interfaces to install/remove application-specified | ||
15 | * handlers for catching violations | ||
16 | */ | ||
17 | |||
18 | #define MAX_SECVIO_SOURCES 6 | ||
19 | |||
20 | /* these are the untranslated causes */ | ||
21 | enum secvio_cause { | ||
22 | SECVIO_CAUSE_SOURCE_0, | ||
23 | SECVIO_CAUSE_SOURCE_1, | ||
24 | SECVIO_CAUSE_SOURCE_2, | ||
25 | SECVIO_CAUSE_SOURCE_3, | ||
26 | SECVIO_CAUSE_SOURCE_4, | ||
27 | SECVIO_CAUSE_SOURCE_5 | ||
28 | }; | ||
29 | |||
30 | /* These are common "recommended" cause definitions for most devices */ | ||
31 | #define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0 | ||
32 | #define SECVIO_CAUSE JTAG_ALARM SECVIO_CAUSE_SOURCE_1 | ||
33 | #define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2 | ||
34 | #define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4 | ||
35 | #define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5 | ||
36 | |||
37 | int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, | ||
38 | void (*handler)(struct device *dev, u32 cause, | ||
39 | void *ext), | ||
40 | u8 *cause_description, void *ext); | ||
41 | int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause); | ||
42 | |||
43 | /* | ||
44 | * Private data definitions for the secvio "driver" | ||
45 | */ | ||
46 | |||
47 | struct secvio_int_src { | ||
48 | const u8 *intname; /* Points to a descriptive name for source */ | ||
49 | void *ext; /* Extended data to pass to the handler */ | ||
50 | void (*handler)(struct device *dev, u32 cause, void *ext); | ||
51 | }; | ||
52 | |||
53 | struct caam_drv_private_secvio { | ||
54 | struct device *parentdev; /* points back to the controller */ | ||
55 | spinlock_t svlock ____cacheline_aligned; | ||
56 | struct tasklet_struct irqtask[NR_CPUS]; | ||
57 | struct snvs_full __iomem *svregs; /* both HP and LP domains */ | ||
58 | |||
59 | /* Registered handlers for each violation */ | ||
60 | struct secvio_int_src intsrc[MAX_SECVIO_SOURCES]; | ||
61 | |||
62 | }; | ||
63 | |||
64 | #endif /* SECVIO_H */ | ||
diff --git a/drivers/crypto/caam/sm.h b/drivers/crypto/caam/sm.h new file mode 100644 index 000000000000..88dc0cd93d79 --- /dev/null +++ b/drivers/crypto/caam/sm.h | |||
@@ -0,0 +1,88 @@ | |||
1 | |||
2 | /* | ||
3 | * CAAM Secure Memory/Keywrap API Definitions | ||
4 | * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. | ||
5 | */ | ||
6 | |||
7 | #ifndef SM_H | ||
8 | #define SM_H | ||
9 | |||
10 | |||
11 | /* Storage access permissions */ | ||
12 | #define SM_PERM_READ 0x01 | ||
13 | #define SM_PERM_WRITE 0x02 | ||
14 | #define SM_PERM_BLOB 0x03 | ||
15 | |||
16 | |||
17 | /* Keystore maintenance functions */ | ||
18 | void sm_init_keystore(struct device *dev); | ||
19 | u32 sm_detect_keystore_units(struct device *dev); | ||
20 | int sm_establish_keystore(struct device *dev, u32 unit); | ||
21 | void sm_release_keystore(struct device *dev, u32 unit); | ||
22 | void caam_sm_shutdown(struct platform_device *pdev); | ||
23 | int caam_sm_example_init(struct platform_device *pdev); | ||
24 | |||
25 | /* Keystore accessor functions */ | ||
26 | extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, | ||
27 | u32 *slot); | ||
28 | extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot); | ||
29 | extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, | ||
30 | const u8 *key_data, u32 key_length); | ||
31 | extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, | ||
32 | u32 key_length, u8 *key_data); | ||
33 | extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, | ||
34 | u32 inslot, u32 outslot, u16 secretlen, | ||
35 | u8 *keymod, u16 keymodlen); | ||
36 | extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, | ||
37 | u32 inslot, u32 outslot, u16 secretlen, | ||
38 | u8 *keymod, u16 keymodlen); | ||
39 | |||
40 | /* Data structure to hold per-slot information */ | ||
41 | struct keystore_data_slot_info { | ||
42 | u8 allocated; /* Track slot assignments */ | ||
43 | u32 key_length; /* Size of the key */ | ||
44 | }; | ||
45 | |||
46 | /* Data structure to hold keystore information */ | ||
47 | struct keystore_data { | ||
48 | void *base_address; /* Base of the Secure Partition */ | ||
49 | u32 slot_count; /* Number of slots in the keystore */ | ||
50 | struct keystore_data_slot_info *slot; /* Per-slot information */ | ||
51 | }; | ||
52 | |||
53 | /* store the detected attributes of a secure memory page */ | ||
54 | struct sm_page_descriptor { | ||
55 | u16 phys_pagenum; /* may be discontiguous */ | ||
56 | u16 own_part; /* Owning partition */ | ||
57 | void *pg_base; /* Calculated virtual address */ | ||
58 | struct keystore_data *ksdata; | ||
59 | }; | ||
60 | |||
61 | struct caam_drv_private_sm { | ||
62 | struct device *parentdev; /* this ends up as the controller */ | ||
63 | struct device *smringdev; /* ring that owns this instance */ | ||
64 | spinlock_t kslock ____cacheline_aligned; | ||
65 | |||
66 | /* Default parameters for geometry */ | ||
67 | u32 max_pages; /* maximum pages this instance can support */ | ||
68 | u32 top_partition; /* highest partition number in this instance */ | ||
69 | u32 top_page; /* highest page number in this instance */ | ||
70 | u32 page_size; /* page size */ | ||
71 | u32 slot_size; /* selected size of each storage block */ | ||
72 | |||
73 | /* Partition/Page Allocation Map */ | ||
74 | u32 localpages; /* Number of pages we can access */ | ||
75 | struct sm_page_descriptor *pagedesc; /* Allocated per-page */ | ||
76 | |||
77 | /* Installed handlers for keystore access */ | ||
78 | int (*data_init)(struct device *dev, u32 unit); | ||
79 | void (*data_cleanup)(struct device *dev, u32 unit); | ||
80 | int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot); | ||
81 | int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot); | ||
82 | void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle); | ||
83 | u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle); | ||
84 | u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle); | ||
85 | u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle); | ||
86 | }; | ||
87 | |||
88 | #endif /* SM_H */ | ||
diff --git a/drivers/crypto/caam/sm_store.c b/drivers/crypto/caam/sm_store.c new file mode 100644 index 000000000000..6e63aa3807e5 --- /dev/null +++ b/drivers/crypto/caam/sm_store.c | |||
@@ -0,0 +1,896 @@ | |||
1 | |||
2 | /* | ||
3 | * CAAM Secure Memory Storage Interface | ||
4 | * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Loosely based on the SHW Keystore API for SCC/SCC2 | ||
7 | * Experimental implementation and NOT intended for upstream use. Expect | ||
8 | * this interface to be amended significantly in the future once it becomes | ||
9 | * integrated into live applications. | ||
10 | * | ||
11 | * Known issues: | ||
12 | * | ||
13 | * - Executes one instance of an secure memory "driver". This is tied to the | ||
14 | * fact that job rings can't run as standalone instances in the present | ||
15 | * configuration. | ||
16 | * | ||
17 | * - It does not expose a userspace interface. The value of a userspace | ||
18 | * interface for access to secrets is a point for further architectural | ||
19 | * discussion. | ||
20 | * | ||
21 | * - Partition/permission management is not part of this interface. It | ||
22 | * depends on some level of "knowledge" agreed upon between bootloader, | ||
23 | * provisioning applications, and OS-hosted software (which uses this | ||
24 | * driver). | ||
25 | * | ||
26 | * - No means of identifying the location or purpose of secrets managed by | ||
27 | * this interface exists; "slot location" and format of a given secret | ||
28 | * needs to be agreed upon between bootloader, provisioner, and OS-hosted | ||
29 | * application. | ||
30 | */ | ||
31 | |||
32 | #include "compat.h" | ||
33 | #include "regs.h" | ||
34 | #include "jr.h" | ||
35 | #include "desc.h" | ||
36 | #include "intern.h" | ||
37 | #include "error.h" | ||
38 | #include "sm.h" | ||
39 | |||
40 | #ifdef SM_DEBUG_CONT | ||
41 | void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc) | ||
42 | { | ||
43 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
44 | u32 i, *smdata; | ||
45 | |||
46 | dev_info(dev, "physical page %d content at 0x%08x\n", | ||
47 | pgdesc->phys_pagenum, pgdesc->pg_base); | ||
48 | smdata = pgdesc->pg_base; | ||
49 | for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4) | ||
50 | dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
51 | (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2], | ||
52 | smdata[i+3]); | ||
53 | } | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * Construct a secure memory blob encapsulation job descriptor | ||
58 | * | ||
59 | * - desc pointer to hold new (to be allocated) pointer to the generated | ||
60 | * descriptor for later use. Calling thread can kfree the | ||
61 | * descriptor after execution. | ||
62 | * - keymod Physical pointer to key modifier (contiguous piece). | ||
63 | * - keymodsz Size of key modifier in bytes (should normally be 8). | ||
64 | * - secretbuf Physical pointer (within an accessible secure memory page) | ||
65 | * of the secret to be encapsulated. | ||
66 | * - outbuf Physical pointer (within an accessible secure memory page) | ||
67 | * of the encapsulated output. This will be larger than the | ||
68 | * input secret because of the added encapsulation data. | ||
69 | * - secretsz Size of input secret, in bytes. | ||
70 | * - auth If nonzero, use AES-CCM for encapsulation, else use ECB | ||
71 | * | ||
72 | * Note: this uses 32-bit pointers at present | ||
73 | */ | ||
74 | #define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ | ||
75 | static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, | ||
76 | dma_addr_t secretbuf, dma_addr_t outbuf, | ||
77 | u16 secretsz, bool auth) | ||
78 | { | ||
79 | u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; | ||
80 | u16 dsize, idx; | ||
81 | |||
82 | memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); | ||
83 | idx = 1; | ||
84 | |||
85 | /* Load key modifier */ | ||
86 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | | ||
87 | ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | | ||
88 | (keymodsz & LDST_LEN_MASK); | ||
89 | |||
90 | tmpdesc[idx++] = (u32)keymod; | ||
91 | |||
92 | /* Encapsulate to secure memory */ | ||
93 | tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz; | ||
94 | tmpdesc[idx++] = (u32)secretbuf; | ||
95 | |||
96 | /* Add space for BKEK and MAC tag */ | ||
97 | tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16)); | ||
98 | |||
99 | tmpdesc[idx++] = (u32)outbuf; | ||
100 | tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | | ||
101 | OP_PCL_BLOB_PTXT_SECMEM; | ||
102 | if (auth) | ||
103 | tmpdesc[idx] |= OP_PCL_BLOB_EKT; | ||
104 | |||
105 | idx++; | ||
106 | tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); | ||
107 | dsize = idx * sizeof(u32); | ||
108 | |||
109 | tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); | ||
110 | if (tdesc == NULL) | ||
111 | return 0; | ||
112 | |||
113 | memcpy(tdesc, tmpdesc, dsize); | ||
114 | *desc = tdesc; | ||
115 | return dsize; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Construct a secure memory blob decapsulation job descriptor | ||
120 | * | ||
121 | * - desc pointer to hold new (to be allocated) pointer to the generated | ||
122 | * descriptor for later use. Calling thread can kfree the | ||
123 | * descriptor after execution. | ||
124 | * - keymod Physical pointer to key modifier (contiguous piece). | ||
125 | * - keymodsz Size of key modifier in bytes (should normally be 16). | ||
126 | * - blobbuf Physical pointer (within an accessible secure memory page) | ||
127 | * of the blob to be decapsulated. | ||
128 | * - outbuf Physical pointer (within an accessible secure memory page) | ||
129 | * of the decapsulated output. | ||
130 | * - secretsz Size of input blob, in bytes. | ||
131 | * - auth If nonzero, assume AES-CCM for decapsulation, else use ECB | ||
132 | * | ||
133 | * Note: this uses 32-bit pointers at present | ||
134 | */ | ||
135 | static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, | ||
136 | dma_addr_t blobbuf, dma_addr_t outbuf, | ||
137 | u16 blobsz, bool auth) | ||
138 | { | ||
139 | u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; | ||
140 | u16 dsize, idx; | ||
141 | |||
142 | memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); | ||
143 | idx = 1; | ||
144 | |||
145 | /* Load key modifier */ | ||
146 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | | ||
147 | ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | | ||
148 | (keymodsz & LDST_LEN_MASK); | ||
149 | |||
150 | tmpdesc[idx++] = (u32)keymod; | ||
151 | |||
152 | /* Compensate BKEK + MAC tag */ | ||
153 | tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16); | ||
154 | |||
155 | tmpdesc[idx++] = (u32)blobbuf; | ||
156 | tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz; | ||
157 | tmpdesc[idx++] = (u32)outbuf; | ||
158 | |||
159 | /* Decapsulate from secure memory partition to black blob */ | ||
160 | tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB | | ||
161 | OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK; | ||
162 | if (auth) | ||
163 | tmpdesc[idx] |= OP_PCL_BLOB_EKT; | ||
164 | |||
165 | idx++; | ||
166 | tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); | ||
167 | dsize = idx * sizeof(u32); | ||
168 | |||
169 | tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); | ||
170 | if (tdesc == NULL) | ||
171 | return 0; | ||
172 | |||
173 | memcpy(tdesc, tmpdesc, dsize); | ||
174 | *desc = tdesc; | ||
175 | return dsize; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Pseudo-synchronous ring access functions for carrying out key | ||
180 | * encapsulation and decapsulation | ||
181 | */ | ||
182 | |||
183 | struct sm_key_job_result { | ||
184 | int error; | ||
185 | struct completion completion; | ||
186 | }; | ||
187 | |||
188 | void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context) | ||
189 | { | ||
190 | struct sm_key_job_result *res = context; | ||
191 | |||
192 | res->error = err; /* save off the error for postprocessing */ | ||
193 | complete(&res->completion); /* mark us complete */ | ||
194 | } | ||
195 | |||
196 | static int sm_key_job(struct device *ksdev, u32 *jobdesc) | ||
197 | { | ||
198 | struct sm_key_job_result testres; | ||
199 | struct caam_drv_private_sm *kspriv; | ||
200 | int rtn = 0; | ||
201 | |||
202 | kspriv = dev_get_drvdata(ksdev); | ||
203 | |||
204 | init_completion(&testres.completion); | ||
205 | |||
206 | rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done, | ||
207 | &testres); | ||
208 | if (!rtn) { | ||
209 | wait_for_completion_interruptible(&testres.completion); | ||
210 | rtn = testres.error; | ||
211 | } | ||
212 | return rtn; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * Following section establishes the default methods for keystore access | ||
217 | * They are NOT intended for use external to this module | ||
218 | * | ||
219 | * In the present version, these are the only means for the higher-level | ||
220 | * interface to deal with the mechanics of accessing the phyiscal keystore | ||
221 | */ | ||
222 | |||
223 | |||
224 | int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) | ||
225 | { | ||
226 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
227 | struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; | ||
228 | u32 i; | ||
229 | #ifdef SM_DEBUG | ||
230 | dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size); | ||
231 | #endif | ||
232 | |||
233 | if (size > smpriv->slot_size) | ||
234 | return -EKEYREJECTED; | ||
235 | |||
236 | for (i = 0; i < ksdata->slot_count; i++) { | ||
237 | if (ksdata->slot[i].allocated == 0) { | ||
238 | ksdata->slot[i].allocated = 1; | ||
239 | (*slot) = i; | ||
240 | #ifdef SM_DEBUG | ||
241 | dev_info(dev, "slot_alloc(): new slot %d allocated\n", | ||
242 | *slot); | ||
243 | #endif | ||
244 | return 0; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | return -ENOSPC; | ||
249 | } | ||
250 | EXPORT_SYMBOL(slot_alloc); | ||
251 | |||
252 | int slot_dealloc(struct device *dev, u32 unit, u32 slot) | ||
253 | { | ||
254 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
255 | struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; | ||
256 | u8 __iomem *slotdata; | ||
257 | |||
258 | #ifdef SM_DEBUG | ||
259 | dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot); | ||
260 | #endif | ||
261 | if (slot >= ksdata->slot_count) | ||
262 | return -EINVAL; | ||
263 | slotdata = ksdata->base_address + slot * smpriv->slot_size; | ||
264 | |||
265 | if (ksdata->slot[slot].allocated == 1) { | ||
266 | /* Forcibly overwrite the data from the keystore */ | ||
267 | memset(ksdata->base_address + slot * smpriv->slot_size, 0, | ||
268 | smpriv->slot_size); | ||
269 | |||
270 | ksdata->slot[slot].allocated = 0; | ||
271 | #ifdef SM_DEBUG | ||
272 | dev_info(dev, "slot_dealloc(): slot %d released\n", slot); | ||
273 | #endif | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | return -EINVAL; | ||
278 | } | ||
279 | EXPORT_SYMBOL(slot_dealloc); | ||
280 | |||
281 | void *slot_get_address(struct device *dev, u32 unit, u32 slot) | ||
282 | { | ||
283 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
284 | struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; | ||
285 | |||
286 | if (slot >= ksdata->slot_count) | ||
287 | return NULL; | ||
288 | |||
289 | #ifdef SM_DEBUG | ||
290 | dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot, | ||
291 | (u32)ksdata->base_address + slot * smpriv->slot_size); | ||
292 | #endif | ||
293 | |||
294 | return ksdata->base_address + slot * smpriv->slot_size; | ||
295 | } | ||
296 | |||
297 | u32 slot_get_base(struct device *dev, u32 unit, u32 slot) | ||
298 | { | ||
299 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
300 | struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; | ||
301 | |||
302 | /* | ||
303 | * There could potentially be more than one secure partition object | ||
304 | * associated with this keystore. For now, there is just one. | ||
305 | */ | ||
306 | |||
307 | (void)slot; | ||
308 | |||
309 | #ifdef SM_DEBUG | ||
310 | dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n", | ||
311 | slot, (u32)ksdata->base_address); | ||
312 | #endif | ||
313 | |||
314 | return (u32)(ksdata->base_address); | ||
315 | } | ||
316 | |||
317 | u32 slot_get_offset(struct device *dev, u32 unit, u32 slot) | ||
318 | { | ||
319 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
320 | struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; | ||
321 | |||
322 | if (slot >= ksdata->slot_count) | ||
323 | return -EINVAL; | ||
324 | |||
325 | #ifdef SM_DEBUG | ||
326 | dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot, | ||
327 | slot * smpriv->slot_size); | ||
328 | #endif | ||
329 | |||
330 | return slot * smpriv->slot_size; | ||
331 | } | ||
332 | |||
333 | u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot) | ||
334 | { | ||
335 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
336 | |||
337 | |||
338 | #ifdef SM_DEBUG | ||
339 | dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot, | ||
340 | smpriv->slot_size); | ||
341 | #endif | ||
342 | /* All slots are the same size in the default implementation */ | ||
343 | return smpriv->slot_size; | ||
344 | } | ||
345 | |||
346 | |||
347 | |||
348 | int kso_init_data(struct device *dev, u32 unit) | ||
349 | { | ||
350 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
351 | int retval = -EINVAL; | ||
352 | struct keystore_data *keystore_data = NULL; | ||
353 | u32 slot_count; | ||
354 | u32 keystore_data_size; | ||
355 | |||
356 | /* | ||
357 | * Calculate the required size of the keystore data structure, based | ||
358 | * on the number of keys that can fit in the partition. | ||
359 | */ | ||
360 | slot_count = smpriv->page_size / smpriv->slot_size; | ||
361 | #ifdef SM_DEBUG | ||
362 | dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count); | ||
363 | #endif | ||
364 | |||
365 | keystore_data_size = sizeof(struct keystore_data) + | ||
366 | slot_count * | ||
367 | sizeof(struct keystore_data_slot_info); | ||
368 | |||
369 | keystore_data = kzalloc(keystore_data_size, GFP_KERNEL); | ||
370 | |||
371 | if (keystore_data == NULL) { | ||
372 | retval = -ENOSPC; | ||
373 | goto out; | ||
374 | } | ||
375 | |||
376 | #ifdef SM_DEBUG | ||
377 | dev_info(dev, "kso_init_data: keystore data size = %d\n", | ||
378 | keystore_data_size); | ||
379 | #endif | ||
380 | |||
381 | /* | ||
382 | * Place the slot information structure directly after the keystore data | ||
383 | * structure. | ||
384 | */ | ||
385 | keystore_data->slot = (struct keystore_data_slot_info *) | ||
386 | (keystore_data + 1); | ||
387 | keystore_data->slot_count = slot_count; | ||
388 | |||
389 | smpriv->pagedesc[unit].ksdata = keystore_data; | ||
390 | smpriv->pagedesc[unit].ksdata->base_address = | ||
391 | smpriv->pagedesc[unit].pg_base; | ||
392 | |||
393 | retval = 0; | ||
394 | |||
395 | out: | ||
396 | if (retval != 0) | ||
397 | if (keystore_data != NULL) | ||
398 | kfree(keystore_data); | ||
399 | |||
400 | |||
401 | return retval; | ||
402 | } | ||
403 | |||
404 | void kso_cleanup_data(struct device *dev, u32 unit) | ||
405 | { | ||
406 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
407 | struct keystore_data *keystore_data = NULL; | ||
408 | |||
409 | if (smpriv->pagedesc[unit].ksdata != NULL) | ||
410 | keystore_data = smpriv->pagedesc[unit].ksdata; | ||
411 | |||
412 | /* Release the allocated keystore management data */ | ||
413 | kfree(smpriv->pagedesc[unit].ksdata); | ||
414 | |||
415 | return; | ||
416 | } | ||
417 | |||
418 | |||
419 | |||
420 | /* | ||
421 | * Keystore management section | ||
422 | */ | ||
423 | |||
424 | void sm_init_keystore(struct device *dev) | ||
425 | { | ||
426 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
427 | |||
428 | smpriv->data_init = kso_init_data; | ||
429 | smpriv->data_cleanup = kso_cleanup_data; | ||
430 | smpriv->slot_alloc = slot_alloc; | ||
431 | smpriv->slot_dealloc = slot_dealloc; | ||
432 | smpriv->slot_get_address = slot_get_address; | ||
433 | smpriv->slot_get_base = slot_get_base; | ||
434 | smpriv->slot_get_offset = slot_get_offset; | ||
435 | smpriv->slot_get_slot_size = slot_get_slot_size; | ||
436 | #ifdef SM_DEBUG | ||
437 | dev_info(dev, "sm_init_keystore(): handlers installed\n"); | ||
438 | #endif | ||
439 | } | ||
440 | EXPORT_SYMBOL(sm_init_keystore); | ||
441 | |||
442 | /* Return available pages/units */ | ||
443 | u32 sm_detect_keystore_units(struct device *dev) | ||
444 | { | ||
445 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
446 | |||
447 | return smpriv->localpages; | ||
448 | } | ||
449 | EXPORT_SYMBOL(sm_detect_keystore_units); | ||
450 | |||
451 | /* | ||
452 | * Do any keystore specific initializations | ||
453 | */ | ||
454 | int sm_establish_keystore(struct device *dev, u32 unit) | ||
455 | { | ||
456 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
457 | |||
458 | #ifdef SM_DEBUG | ||
459 | dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit); | ||
460 | #endif | ||
461 | |||
462 | if (smpriv->data_init == NULL) | ||
463 | return -EINVAL; | ||
464 | |||
465 | /* Call the data_init function for any user setup */ | ||
466 | return smpriv->data_init(dev, unit); | ||
467 | } | ||
468 | EXPORT_SYMBOL(sm_establish_keystore); | ||
469 | |||
470 | void sm_release_keystore(struct device *dev, u32 unit) | ||
471 | { | ||
472 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
473 | |||
474 | #ifdef SM_DEBUG | ||
475 | dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit); | ||
476 | #endif | ||
477 | if ((smpriv != NULL) && (smpriv->data_cleanup != NULL)) | ||
478 | smpriv->data_cleanup(dev, unit); | ||
479 | |||
480 | return; | ||
481 | } | ||
482 | EXPORT_SYMBOL(sm_release_keystore); | ||
483 | |||
484 | /* | ||
485 | * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to | ||
486 | * the keystore | ||
487 | */ | ||
488 | int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) | ||
489 | { | ||
490 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
491 | int retval = -EINVAL; | ||
492 | |||
493 | spin_lock(&smpriv->kslock); | ||
494 | |||
495 | if ((smpriv->slot_alloc == NULL) || | ||
496 | (smpriv->pagedesc[unit].ksdata == NULL)) | ||
497 | goto out; | ||
498 | |||
499 | retval = smpriv->slot_alloc(dev, unit, size, slot); | ||
500 | |||
501 | out: | ||
502 | spin_unlock(&smpriv->kslock); | ||
503 | return retval; | ||
504 | } | ||
505 | EXPORT_SYMBOL(sm_keystore_slot_alloc); | ||
506 | |||
507 | int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot) | ||
508 | { | ||
509 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
510 | int retval = -EINVAL; | ||
511 | |||
512 | spin_lock(&smpriv->kslock); | ||
513 | |||
514 | if ((smpriv->slot_alloc == NULL) || | ||
515 | (smpriv->pagedesc[unit].ksdata == NULL)) | ||
516 | goto out; | ||
517 | |||
518 | retval = smpriv->slot_dealloc(dev, unit, slot); | ||
519 | out: | ||
520 | spin_unlock(&smpriv->kslock); | ||
521 | return retval; | ||
522 | } | ||
523 | EXPORT_SYMBOL(sm_keystore_slot_dealloc); | ||
524 | |||
525 | int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, | ||
526 | const u8 *key_data, u32 key_length) | ||
527 | { | ||
528 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
529 | int retval = -EINVAL; | ||
530 | u32 slot_size; | ||
531 | u32 i; | ||
532 | u8 __iomem *slot_location; | ||
533 | |||
534 | spin_lock(&smpriv->kslock); | ||
535 | |||
536 | slot_size = smpriv->slot_get_slot_size(dev, unit, slot); | ||
537 | |||
538 | if (key_length > slot_size) { | ||
539 | retval = -EFBIG; | ||
540 | goto out; | ||
541 | } | ||
542 | |||
543 | slot_location = smpriv->slot_get_address(dev, unit, slot); | ||
544 | |||
545 | for (i = 0; i < key_length; i++) | ||
546 | slot_location[i] = key_data[i]; | ||
547 | |||
548 | retval = 0; | ||
549 | |||
550 | out: | ||
551 | spin_unlock(&smpriv->kslock); | ||
552 | return retval; | ||
553 | } | ||
554 | EXPORT_SYMBOL(sm_keystore_slot_load); | ||
555 | |||
556 | int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, | ||
557 | u32 key_length, u8 *key_data) | ||
558 | { | ||
559 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
560 | int retval = -EINVAL; | ||
561 | u8 __iomem *slot_addr; | ||
562 | u32 slot_size; | ||
563 | |||
564 | spin_lock(&smpriv->kslock); | ||
565 | |||
566 | slot_addr = smpriv->slot_get_address(dev, unit, slot); | ||
567 | slot_size = smpriv->slot_get_slot_size(dev, unit, slot); | ||
568 | |||
569 | if (key_length > slot_size) { | ||
570 | retval = -EKEYREJECTED; | ||
571 | goto out; | ||
572 | } | ||
573 | |||
574 | memcpy(key_data, slot_addr, key_length); | ||
575 | retval = 0; | ||
576 | |||
577 | out: | ||
578 | spin_unlock(&smpriv->kslock); | ||
579 | return retval; | ||
580 | } | ||
581 | EXPORT_SYMBOL(sm_keystore_slot_read); | ||
582 | |||
583 | int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot, | ||
584 | u32 outslot, u16 secretlen, u8 *keymod, | ||
585 | u16 keymodlen) | ||
586 | { | ||
587 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
588 | int retval = 0; | ||
589 | u32 slot_length, dsize, jstat; | ||
590 | u32 __iomem *encapdesc = NULL; | ||
591 | u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; | ||
592 | dma_addr_t keymod_dma; | ||
593 | |||
594 | /* Ensure that the full blob will fit in the key slot */ | ||
595 | slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); | ||
596 | if ((secretlen + 48) > slot_length) | ||
597 | goto out; | ||
598 | |||
599 | /* Get the base addresses of both keystore slots */ | ||
600 | inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); | ||
601 | outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); | ||
602 | |||
603 | /* Build the key modifier */ | ||
604 | lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); | ||
605 | memcpy(lkeymod, keymod, keymodlen); | ||
606 | keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); | ||
607 | dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); | ||
608 | |||
609 | /* Build the encapsulation job descriptor */ | ||
610 | dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen, | ||
611 | __pa(inpslotaddr), __pa(outslotaddr), | ||
612 | secretlen, 0); | ||
613 | if (!dsize) { | ||
614 | dev_err(dev, "can't alloc an encap descriptor\n"); | ||
615 | retval = -ENOMEM; | ||
616 | goto out; | ||
617 | } | ||
618 | jstat = sm_key_job(dev, encapdesc); | ||
619 | |||
620 | dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); | ||
621 | kfree(encapdesc); | ||
622 | |||
623 | out: | ||
624 | return retval; | ||
625 | |||
626 | } | ||
627 | EXPORT_SYMBOL(sm_keystore_slot_encapsulate); | ||
628 | |||
629 | int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot, | ||
630 | u32 outslot, u16 secretlen, u8 *keymod, | ||
631 | u16 keymodlen) | ||
632 | { | ||
633 | struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); | ||
634 | int retval = 0; | ||
635 | u32 slot_length, dsize, jstat; | ||
636 | u32 __iomem *decapdesc = NULL; | ||
637 | u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; | ||
638 | dma_addr_t keymod_dma; | ||
639 | |||
640 | /* Ensure that the decap data will fit in the key slot */ | ||
641 | slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); | ||
642 | if (secretlen > slot_length) | ||
643 | goto out; | ||
644 | |||
645 | /* Get the base addresses of both keystore slots */ | ||
646 | inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); | ||
647 | outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); | ||
648 | |||
649 | /* Build the key modifier */ | ||
650 | lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); | ||
651 | memcpy(lkeymod, keymod, keymodlen); | ||
652 | keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); | ||
653 | dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); | ||
654 | |||
655 | /* Build the decapsulation job descriptor */ | ||
656 | dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen, | ||
657 | __pa(inpslotaddr), __pa(outslotaddr), | ||
658 | secretlen, 0); | ||
659 | if (!dsize) { | ||
660 | dev_err(dev, "can't alloc a decap descriptor\n"); | ||
661 | retval = -ENOMEM; | ||
662 | goto out; | ||
663 | } | ||
664 | jstat = sm_key_job(dev, decapdesc); | ||
665 | |||
666 | dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); | ||
667 | kfree(decapdesc); | ||
668 | |||
669 | out: | ||
670 | return retval; | ||
671 | |||
672 | } | ||
673 | EXPORT_SYMBOL(sm_keystore_slot_decapsulate); | ||
674 | |||
675 | |||
676 | /* | ||
677 | * Initialization/shutdown subsystem | ||
678 | * Assumes statically-invoked startup/shutdown from the controller driver | ||
679 | * for the present time, to be reworked when a device tree becomes | ||
680 | * available. This code will not modularize in present form. | ||
681 | * | ||
682 | * Also, simply uses ring 0 for execution at the present | ||
683 | */ | ||
684 | |||
685 | int caam_sm_startup(struct platform_device *pdev) | ||
686 | { | ||
687 | struct device *ctrldev, *smdev; | ||
688 | struct caam_drv_private *ctrlpriv; | ||
689 | struct caam_drv_private_sm *smpriv; | ||
690 | struct caam_drv_private_jr *jrpriv; /* need this for reg page */ | ||
691 | struct platform_device *sm_pdev; | ||
692 | struct sm_page_descriptor *lpagedesc; | ||
693 | u32 page, pgstat, lpagect, detectedpage; | ||
694 | |||
695 | struct device_node *np; | ||
696 | ctrldev = &pdev->dev; | ||
697 | ctrlpriv = dev_get_drvdata(ctrldev); | ||
698 | |||
699 | /* | ||
700 | * Set up the private block for secure memory | ||
701 | * Only one instance is possible | ||
702 | */ | ||
703 | smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL); | ||
704 | if (smpriv == NULL) { | ||
705 | dev_err(ctrldev, "can't alloc private mem for secure memory\n"); | ||
706 | return -ENOMEM; | ||
707 | } | ||
708 | smpriv->parentdev = ctrldev; /* copy of parent dev is handy */ | ||
709 | |||
710 | /* Create the dev */ | ||
711 | #ifdef CONFIG_OF | ||
712 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm"); | ||
713 | sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev); | ||
714 | #else | ||
715 | sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0, | ||
716 | smpriv, | ||
717 | sizeof(struct caam_drv_private_sm)); | ||
718 | #endif | ||
719 | if (sm_pdev == NULL) { | ||
720 | kfree(smpriv); | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | smdev = &sm_pdev->dev; | ||
724 | dev_set_drvdata(smdev, smpriv); | ||
725 | ctrlpriv->smdev = smdev; | ||
726 | |||
727 | /* | ||
728 | * Collect configuration limit data for reference | ||
729 | * This batch comes from the partition data/vid registers in perfmon | ||
730 | */ | ||
731 | smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) | ||
732 | & SMPART_MAX_NUMPG_MASK) >> | ||
733 | SMPART_MAX_NUMPG_SHIFT) + 1; | ||
734 | smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) | ||
735 | & SMPART_MAX_PNUM_MASK) >> | ||
736 | SMPART_MAX_PNUM_SHIFT) + 1; | ||
737 | smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) | ||
738 | & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1; | ||
739 | smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid) | ||
740 | & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT); | ||
741 | smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE; | ||
742 | |||
743 | #ifdef SM_DEBUG | ||
744 | dev_info(smdev, "max pages = %d, top partition = %d\n", | ||
745 | smpriv->max_pages, smpriv->top_partition); | ||
746 | dev_info(smdev, "top page = %d, page size = %d (total = %d)\n", | ||
747 | smpriv->top_page, smpriv->page_size, | ||
748 | smpriv->top_page * smpriv->page_size); | ||
749 | dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size); | ||
750 | #endif | ||
751 | |||
752 | /* | ||
753 | * Now probe for partitions/pages to which we have access. Note that | ||
754 | * these have likely been set up by a bootloader or platform | ||
755 | * provisioning application, so we have to assume that we "inherit" | ||
756 | * a configuration and work within the constraints of what it might be. | ||
757 | * | ||
758 | * Assume use of the zeroth ring in the present iteration (until | ||
759 | * we can divorce the controller and ring drivers, and then assign | ||
760 | * an SM instance to any ring instance). | ||
761 | */ | ||
762 | smpriv->smringdev = ctrlpriv->jrdev[0]; | ||
763 | jrpriv = dev_get_drvdata(smpriv->smringdev); | ||
764 | lpagect = 0; | ||
765 | lpagedesc = kzalloc(sizeof(struct sm_page_descriptor) | ||
766 | * smpriv->max_pages, GFP_KERNEL); | ||
767 | if (lpagedesc == NULL) { | ||
768 | kfree(smpriv); | ||
769 | return -ENOMEM; | ||
770 | } | ||
771 | |||
772 | for (page = 0; page < smpriv->max_pages; page++) { | ||
773 | wr_reg32(&jrpriv->rregs->sm_cmd, | ||
774 | ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) | | ||
775 | (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)); | ||
776 | pgstat = rd_reg32(&jrpriv->rregs->sm_status); | ||
777 | if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT) | ||
778 | == SMCS_PGOWN_OWNED) { /* our page? */ | ||
779 | lpagedesc[page].phys_pagenum = | ||
780 | (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT; | ||
781 | lpagedesc[page].own_part = | ||
782 | (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK; | ||
783 | lpagedesc[page].pg_base = ctrlpriv->sm_base + | ||
784 | ((smpriv->page_size * page) / sizeof(u32)); | ||
785 | lpagect++; | ||
786 | #ifdef SM_DEBUG | ||
787 | dev_info(smdev, | ||
788 | "physical page %d, owning partition = %d\n", | ||
789 | lpagedesc[page].phys_pagenum, | ||
790 | lpagedesc[page].own_part); | ||
791 | #endif | ||
792 | } | ||
793 | } | ||
794 | |||
795 | smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect, | ||
796 | GFP_KERNEL); | ||
797 | if (smpriv->pagedesc == NULL) { | ||
798 | kfree(lpagedesc); | ||
799 | kfree(smpriv); | ||
800 | return -ENOMEM; | ||
801 | } | ||
802 | smpriv->localpages = lpagect; | ||
803 | |||
804 | detectedpage = 0; | ||
805 | for (page = 0; page < smpriv->max_pages; page++) { | ||
806 | if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */ | ||
807 | memcpy(&smpriv->pagedesc[detectedpage], | ||
808 | &lpagedesc[page], | ||
809 | sizeof(struct sm_page_descriptor)); | ||
810 | #ifdef SM_DEBUG_CONT | ||
811 | sm_show_page(smdev, &smpriv->pagedesc[detectedpage]); | ||
812 | #endif | ||
813 | detectedpage++; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | kfree(lpagedesc); | ||
818 | |||
819 | sm_init_keystore(smdev); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | void caam_sm_shutdown(struct platform_device *pdev) | ||
825 | { | ||
826 | struct device *ctrldev, *smdev; | ||
827 | struct caam_drv_private *priv; | ||
828 | struct caam_drv_private_sm *smpriv; | ||
829 | |||
830 | ctrldev = &pdev->dev; | ||
831 | priv = dev_get_drvdata(ctrldev); | ||
832 | smdev = priv->smdev; | ||
833 | smpriv = dev_get_drvdata(smdev); | ||
834 | |||
835 | kfree(smpriv->pagedesc); | ||
836 | kfree(smpriv); | ||
837 | } | ||
838 | EXPORT_SYMBOL(caam_sm_shutdown); | ||
839 | #ifdef CONFIG_OF | ||
840 | static void __exit caam_sm_exit(void) | ||
841 | { | ||
842 | struct device_node *dev_node; | ||
843 | struct platform_device *pdev; | ||
844 | |||
845 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
846 | if (!dev_node) { | ||
847 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); | ||
848 | if (!dev_node) | ||
849 | return; | ||
850 | } | ||
851 | |||
852 | pdev = of_find_device_by_node(dev_node); | ||
853 | if (!pdev) | ||
854 | return; | ||
855 | |||
856 | of_node_put(dev_node); | ||
857 | |||
858 | caam_sm_shutdown(pdev); | ||
859 | |||
860 | return; | ||
861 | } | ||
862 | |||
863 | static int __init caam_sm_init(void) | ||
864 | { | ||
865 | struct device_node *dev_node; | ||
866 | struct platform_device *pdev; | ||
867 | |||
868 | /* | ||
869 | * Do of_find_compatible_node() then of_find_device_by_node() | ||
870 | * once a functional device tree is available | ||
871 | */ | ||
872 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
873 | if (!dev_node) { | ||
874 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); | ||
875 | if (!dev_node) | ||
876 | return -ENODEV; | ||
877 | } | ||
878 | |||
879 | pdev = of_find_device_by_node(dev_node); | ||
880 | if (!pdev) | ||
881 | return -ENODEV; | ||
882 | |||
883 | of_node_get(dev_node); | ||
884 | |||
885 | caam_sm_startup(pdev); | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | module_init(caam_sm_init); | ||
891 | module_exit(caam_sm_exit); | ||
892 | |||
893 | MODULE_LICENSE("Dual BSD/GPL"); | ||
894 | MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore"); | ||
895 | MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); | ||
896 | #endif | ||
diff --git a/drivers/crypto/caam/sm_test.c b/drivers/crypto/caam/sm_test.c new file mode 100644 index 000000000000..43590ca52155 --- /dev/null +++ b/drivers/crypto/caam/sm_test.c | |||
@@ -0,0 +1,844 @@ | |||
1 | /* | ||
2 | * Secure Memory / Keystore Exemplification Module | ||
3 | * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved | ||
4 | * | ||
5 | * Serves as a functional example, and as a self-contained unit test for | ||
6 | * the functionality contained in sm_store.c. | ||
7 | * | ||
8 | * The example function, caam_sm_example_init(), runs a thread that: | ||
9 | * | ||
10 | * - initializes a set of fixed keys | ||
11 | * - stores one copy in clear buffers | ||
12 | * - stores them again in secure memory | ||
13 | * - extracts stored keys back out for use | ||
14 | * - intializes 3 data buffers for a test: | ||
15 | * (1) containing cleartext | ||
16 | * (2) to hold ciphertext encrypted with an extracted black key | ||
17 | * (3) to hold extracted cleartext decrypted with an equivalent clear key | ||
18 | * | ||
19 | * The function then builds simple job descriptors that reference the key | ||
20 | * material and buffers as initialized, and executes an encryption job | ||
21 | * with a black key, and a decryption job using a the same key held in the | ||
22 | * clear. The output of the decryption job is compared to the original | ||
23 | * cleartext; if they don't compare correctly, one can assume a key problem | ||
24 | * exists, where the function will exit with an error. | ||
25 | * | ||
26 | * This module can use a substantial amount of refactoring, which may occur | ||
27 | * after the API gets some mileage. Furthermore, expect this module to | ||
28 | * eventually disappear once the API is integrated into "real" software. | ||
29 | */ | ||
30 | |||
31 | #include "compat.h" | ||
32 | #include "intern.h" | ||
33 | #include "desc.h" | ||
34 | #include "error.h" | ||
35 | #include "jr.h" | ||
36 | #include "sm.h" | ||
37 | |||
38 | static u8 skeymod[] = { | ||
39 | 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, | ||
40 | 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 | ||
41 | }; | ||
42 | static u8 symkey[] = { | ||
43 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
44 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
45 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | ||
46 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f | ||
47 | }; | ||
48 | |||
49 | static u8 symdata[] = { | ||
50 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07, | ||
51 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
52 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | ||
53 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | ||
54 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | ||
55 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, | ||
56 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | ||
57 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, | ||
58 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | ||
59 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | ||
60 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, | ||
61 | 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, | ||
62 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | ||
63 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | ||
64 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, | ||
65 | 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, | ||
66 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | ||
67 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, | ||
68 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, | ||
69 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, | ||
70 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | ||
71 | 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, | ||
72 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, | ||
73 | 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, | ||
74 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | ||
75 | 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, | ||
76 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, | ||
77 | 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, | ||
78 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, | ||
79 | 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, | ||
80 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, | ||
81 | 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff | ||
82 | }; | ||
83 | |||
84 | static int mk_job_desc(u32 *desc, dma_addr_t key, u16 keysz, dma_addr_t indata, | ||
85 | dma_addr_t outdata, u16 sz, u32 cipherdir, u32 keymode) | ||
86 | { | ||
87 | desc[1] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK) | keymode; | ||
88 | desc[2] = (u32)key; | ||
89 | desc[3] = CMD_OPERATION | OP_TYPE_CLASS1_ALG | OP_ALG_AAI_ECB | | ||
90 | cipherdir; | ||
91 | desc[4] = CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | | ||
92 | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1 | sz; | ||
93 | desc[5] = (u32)indata; | ||
94 | desc[6] = CMD_FIFO_STORE | FIFOST_TYPE_MESSAGE_DATA | sz; | ||
95 | desc[7] = (u32)outdata; | ||
96 | |||
97 | desc[0] = CMD_DESC_HDR | HDR_ONE | (8 & HDR_DESCLEN_MASK); | ||
98 | return 8 * sizeof(u32); | ||
99 | } | ||
100 | |||
101 | struct exec_test_result { | ||
102 | int error; | ||
103 | struct completion completion; | ||
104 | }; | ||
105 | |||
106 | void exec_test_done(struct device *dev, u32 *desc, u32 err, void *context) | ||
107 | { | ||
108 | struct exec_test_result *res = context; | ||
109 | |||
110 | if (err) { | ||
111 | char tmp[CAAM_ERROR_STR_MAX]; | ||
112 | dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); | ||
113 | } | ||
114 | |||
115 | res->error = err; | ||
116 | complete(&res->completion); | ||
117 | } | ||
118 | |||
119 | static int exec_test_job(struct device *ksdev, u32 *jobdesc) | ||
120 | { | ||
121 | struct exec_test_result testres; | ||
122 | struct caam_drv_private_sm *kspriv; | ||
123 | int rtn = 0; | ||
124 | |||
125 | kspriv = dev_get_drvdata(ksdev); | ||
126 | |||
127 | init_completion(&testres.completion); | ||
128 | |||
129 | rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done, | ||
130 | &testres); | ||
131 | if (!rtn) { | ||
132 | wait_for_completion_interruptible(&testres.completion); | ||
133 | rtn = testres.error; | ||
134 | } | ||
135 | return rtn; | ||
136 | } | ||
137 | |||
138 | |||
139 | int caam_sm_example_init(struct platform_device *pdev) | ||
140 | { | ||
141 | struct device *ctrldev, *ksdev; | ||
142 | struct caam_drv_private *ctrlpriv; | ||
143 | struct caam_drv_private_sm *kspriv; | ||
144 | u32 unit, units, jdescsz; | ||
145 | int stat, jstat, rtnval = 0; | ||
146 | u8 __iomem *syminp, *symint, *symout = NULL; | ||
147 | dma_addr_t syminp_dma, symint_dma, symout_dma; | ||
148 | u8 __iomem *black_key_des, *black_key_aes128; | ||
149 | u8 __iomem *black_key_aes256; | ||
150 | dma_addr_t black_key_des_dma, black_key_aes128_dma; | ||
151 | dma_addr_t black_key_aes256_dma; | ||
152 | u8 __iomem *clear_key_des, *clear_key_aes128, *clear_key_aes256; | ||
153 | dma_addr_t clear_key_des_dma, clear_key_aes128_dma; | ||
154 | dma_addr_t clear_key_aes256_dma; | ||
155 | u32 __iomem *jdesc; | ||
156 | u32 keyslot_des, keyslot_aes128, keyslot_aes256 = 0; | ||
157 | |||
158 | jdesc = NULL; | ||
159 | black_key_des = black_key_aes128 = black_key_aes256 = NULL; | ||
160 | clear_key_des = clear_key_aes128 = clear_key_aes256 = NULL; | ||
161 | |||
162 | /* We can lose this cruft once we can get a pdev by name */ | ||
163 | ctrldev = &pdev->dev; | ||
164 | ctrlpriv = dev_get_drvdata(ctrldev); | ||
165 | ksdev = ctrlpriv->smdev; | ||
166 | kspriv = dev_get_drvdata(ksdev); | ||
167 | if (kspriv == NULL) | ||
168 | return -ENODEV; | ||
169 | |||
170 | /* Now that we have the dev for the single SM instance, connect */ | ||
171 | #ifdef SM_TEST_DETAIL | ||
172 | dev_info(ksdev, "caam_sm_test_init() running\n"); | ||
173 | #endif | ||
174 | /* Probe to see what keystores are available to us */ | ||
175 | units = sm_detect_keystore_units(ksdev); | ||
176 | if (!units) | ||
177 | dev_err(ksdev, "caam_sm_test: no keystore units available\n"); | ||
178 | |||
179 | /* | ||
180 | * MX6 bootloader stores some stuff in unit 0, so let's | ||
181 | * use 1 or above | ||
182 | */ | ||
183 | if (units < 2) { | ||
184 | dev_err(ksdev, "caam_sm_test: insufficient keystore units\n"); | ||
185 | return -ENODEV; | ||
186 | } | ||
187 | unit = 1; | ||
188 | |||
189 | #ifdef SM_TEST_DETAIL | ||
190 | dev_info(ksdev, "caam_sm_test: %d keystore units available\n", units); | ||
191 | #endif | ||
192 | |||
193 | /* Initialize/Establish Keystore */ | ||
194 | sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */ | ||
195 | |||
196 | /* | ||
197 | * Top of main test thread | ||
198 | */ | ||
199 | |||
200 | /* Allocate test data blocks (input, intermediate, output) */ | ||
201 | syminp = kmalloc(256, GFP_KERNEL | GFP_DMA); | ||
202 | symint = kmalloc(256, GFP_KERNEL | GFP_DMA); | ||
203 | symout = kmalloc(256, GFP_KERNEL | GFP_DMA); | ||
204 | if ((syminp == NULL) || (symint == NULL) || (symout == NULL)) { | ||
205 | rtnval = -ENOMEM; | ||
206 | dev_err(ksdev, "caam_sm_test: can't get test data buffers\n"); | ||
207 | goto freemem; | ||
208 | } | ||
209 | |||
210 | /* Allocate storage for 3 black keys: encapsulated 8, 16, 32 */ | ||
211 | black_key_des = kmalloc(16, GFP_KERNEL | GFP_DMA); /* padded to 16... */ | ||
212 | black_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); | ||
213 | black_key_aes256 = kmalloc(16, GFP_KERNEL | GFP_DMA); | ||
214 | if ((black_key_des == NULL) || (black_key_aes128 == NULL) || | ||
215 | (black_key_aes256 == NULL)) { | ||
216 | rtnval = -ENOMEM; | ||
217 | dev_err(ksdev, "caam_sm_test: can't black key buffers\n"); | ||
218 | goto freemem; | ||
219 | } | ||
220 | |||
221 | clear_key_des = kmalloc(8, GFP_KERNEL | GFP_DMA); | ||
222 | clear_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); | ||
223 | clear_key_aes256 = kmalloc(32, GFP_KERNEL | GFP_DMA); | ||
224 | if ((clear_key_des == NULL) || (clear_key_aes128 == NULL) || | ||
225 | (clear_key_aes256 == NULL)) { | ||
226 | rtnval = -ENOMEM; | ||
227 | dev_err(ksdev, "caam_sm_test: can't get clear key buffers\n"); | ||
228 | goto freemem; | ||
229 | } | ||
230 | |||
231 | /* Allocate storage for job descriptor */ | ||
232 | jdesc = kmalloc(8 * sizeof(u32), GFP_KERNEL | GFP_DMA); | ||
233 | if (jdesc == NULL) { | ||
234 | rtnval = -ENOMEM; | ||
235 | dev_err(ksdev, "caam_sm_test: can't get descriptor buffers\n"); | ||
236 | goto freemem; | ||
237 | } | ||
238 | |||
239 | #ifdef SM_TEST_DETAIL | ||
240 | dev_info(ksdev, "caam_sm_test: all buffers allocated\n"); | ||
241 | #endif | ||
242 | |||
243 | /* Load up input data block, clear outputs */ | ||
244 | memcpy(syminp, symdata, 256); | ||
245 | memset(symint, 0, 256); | ||
246 | memset(symout, 0, 256); | ||
247 | #ifdef SM_TEST_DETAIL | ||
248 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
249 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
250 | syminp[0], syminp[1], syminp[2], syminp[3], | ||
251 | syminp[4], syminp[5], syminp[6], syminp[7]); | ||
252 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
253 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
254 | symint[0], symint[1], symint[2], symint[3], | ||
255 | symint[4], symint[5], symint[6], symint[7]); | ||
256 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
257 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
258 | symout[0], symout[1], symout[2], symout[3], | ||
259 | symout[4], symout[5], symout[6], symout[7]); | ||
260 | |||
261 | dev_info(ksdev, "caam_sm_test: data buffers initialized\n"); | ||
262 | #endif | ||
263 | |||
264 | /* Load up clear keys */ | ||
265 | memcpy(clear_key_des, symkey, 8); | ||
266 | memcpy(clear_key_aes128, symkey, 16); | ||
267 | memcpy(clear_key_aes256, symkey, 32); | ||
268 | |||
269 | #ifdef SM_TEST_DETAIL | ||
270 | dev_info(ksdev, "caam_sm_test: all clear keys loaded\n"); | ||
271 | #endif | ||
272 | |||
273 | /* | ||
274 | * Place clear keys in keystore. | ||
275 | * All the interesting stuff happens here. | ||
276 | */ | ||
277 | /* 8 bit DES key */ | ||
278 | stat = sm_keystore_slot_alloc(ksdev, unit, 8, &keyslot_des); | ||
279 | if (stat) | ||
280 | goto freemem; | ||
281 | #ifdef SM_TEST_DETAIL | ||
282 | dev_info(ksdev, "caam_sm_test: 8 byte key slot in %d\n", keyslot_des); | ||
283 | #endif | ||
284 | stat = sm_keystore_slot_load(ksdev, unit, keyslot_des, clear_key_des, | ||
285 | 8); | ||
286 | if (stat) { | ||
287 | #ifdef SM_TEST_DETAIL | ||
288 | dev_info(ksdev, "caam_sm_test: can't load 8 byte key in %d\n", | ||
289 | keyslot_des); | ||
290 | #endif | ||
291 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
292 | goto freemem; | ||
293 | } | ||
294 | |||
295 | /* 16 bit AES key */ | ||
296 | stat = sm_keystore_slot_alloc(ksdev, unit, 16, &keyslot_aes128); | ||
297 | if (stat) { | ||
298 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
299 | goto freemem; | ||
300 | } | ||
301 | #ifdef SM_TEST_DETAIL | ||
302 | dev_info(ksdev, "caam_sm_test: 16 byte key slot in %d\n", | ||
303 | keyslot_aes128); | ||
304 | #endif | ||
305 | stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes128, | ||
306 | clear_key_aes128, 16); | ||
307 | if (stat) { | ||
308 | #ifdef SM_TEST_DETAIL | ||
309 | dev_info(ksdev, "caam_sm_test: can't load 16 byte key in %d\n", | ||
310 | keyslot_aes128); | ||
311 | #endif | ||
312 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); | ||
313 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
314 | goto freemem; | ||
315 | } | ||
316 | |||
317 | /* 32 bit AES key */ | ||
318 | stat = sm_keystore_slot_alloc(ksdev, unit, 32, &keyslot_aes256); | ||
319 | if (stat) { | ||
320 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); | ||
321 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
322 | goto freemem; | ||
323 | } | ||
324 | #ifdef SM_TEST_DETAIL | ||
325 | dev_info(ksdev, "caam_sm_test: 32 byte key slot in %d\n", | ||
326 | keyslot_aes256); | ||
327 | #endif | ||
328 | stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes256, | ||
329 | clear_key_aes256, 32); | ||
330 | if (stat) { | ||
331 | #ifdef SM_TEST_DETAIL | ||
332 | dev_info(ksdev, "caam_sm_test: can't load 32 byte key in %d\n", | ||
333 | keyslot_aes128); | ||
334 | #endif | ||
335 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); | ||
336 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); | ||
337 | sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
338 | goto freemem; | ||
339 | } | ||
340 | |||
341 | /* Encapsulate all keys as SM blobs */ | ||
342 | stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_des, | ||
343 | keyslot_des, 8, skeymod, 8); | ||
344 | if (stat) { | ||
345 | dev_info(ksdev, "caam_sm_test: can't encapsulate DES key\n"); | ||
346 | goto freekeys; | ||
347 | } | ||
348 | |||
349 | stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes128, | ||
350 | keyslot_aes128, 16, skeymod, 8); | ||
351 | if (stat) { | ||
352 | dev_info(ksdev, "caam_sm_test: can't encapsulate AES128 key\n"); | ||
353 | goto freekeys; | ||
354 | } | ||
355 | |||
356 | stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes256, | ||
357 | keyslot_aes256, 32, skeymod, 8); | ||
358 | if (stat) { | ||
359 | dev_info(ksdev, "caam_sm_test: can't encapsulate AES256 key\n"); | ||
360 | goto freekeys; | ||
361 | } | ||
362 | |||
363 | /* Now decapsulate as black key blobs */ | ||
364 | stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_des, | ||
365 | keyslot_des, 8, skeymod, 8); | ||
366 | if (stat) { | ||
367 | dev_info(ksdev, "caam_sm_test: can't decapsulate DES key\n"); | ||
368 | goto freekeys; | ||
369 | } | ||
370 | |||
371 | stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes128, | ||
372 | keyslot_aes128, 16, skeymod, 8); | ||
373 | if (stat) { | ||
374 | dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); | ||
375 | goto freekeys; | ||
376 | } | ||
377 | |||
378 | stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes256, | ||
379 | keyslot_aes256, 32, skeymod, 8); | ||
380 | if (stat) { | ||
381 | dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); | ||
382 | goto freekeys; | ||
383 | } | ||
384 | |||
385 | /* Extract 8/16/32 byte black keys */ | ||
386 | sm_keystore_slot_read(ksdev, unit, keyslot_des, 8, black_key_des); | ||
387 | sm_keystore_slot_read(ksdev, unit, keyslot_aes128, 16, | ||
388 | black_key_aes128); | ||
389 | sm_keystore_slot_read(ksdev, unit, keyslot_aes256, 32, | ||
390 | black_key_aes256); | ||
391 | |||
392 | #ifdef SM_TEST_DETAIL | ||
393 | dev_info(ksdev, "caam_sm_test: all black keys extracted\n"); | ||
394 | #endif | ||
395 | |||
396 | /* DES encrypt using 8 byte black key */ | ||
397 | black_key_des_dma = dma_map_single(ksdev, black_key_des, 8, | ||
398 | DMA_TO_DEVICE); | ||
399 | dma_sync_single_for_device(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); | ||
400 | syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); | ||
401 | dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
402 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); | ||
403 | |||
404 | jdescsz = mk_job_desc(jdesc, black_key_des_dma, 8, syminp_dma, | ||
405 | symint_dma, 256, | ||
406 | OP_ALG_ENCRYPT | OP_ALG_ALGSEL_DES, 0); | ||
407 | |||
408 | #ifdef SM_TEST_DETAIL | ||
409 | dev_info(ksdev, "jobdesc:\n"); | ||
410 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
411 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
412 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
413 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
414 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
415 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
416 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
417 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
418 | #endif | ||
419 | |||
420 | jstat = exec_test_job(ksdev, jdesc); | ||
421 | |||
422 | dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
423 | dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
424 | dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
425 | dma_unmap_single(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); | ||
426 | |||
427 | #ifdef SM_TEST_DETAIL | ||
428 | dev_info(ksdev, "input block:\n"); | ||
429 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
430 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
431 | syminp[0], syminp[1], syminp[2], syminp[3], | ||
432 | syminp[4], syminp[5], syminp[6], syminp[7]); | ||
433 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
434 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
435 | syminp[8], syminp[9], syminp[10], syminp[11], | ||
436 | syminp[12], syminp[13], syminp[14], syminp[15]); | ||
437 | dev_info(ksdev, "intermediate block:\n"); | ||
438 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
439 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
440 | symint[0], symint[1], symint[2], symint[3], | ||
441 | symint[4], symint[5], symint[6], symint[7]); | ||
442 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
443 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
444 | symint[8], symint[9], symint[10], symint[11], | ||
445 | symint[12], symint[13], symint[14], symint[15]); | ||
446 | dev_info(ksdev, "caam_sm_test: encrypt cycle with 8 byte key\n"); | ||
447 | #endif | ||
448 | |||
449 | /* DES decrypt using 8 byte clear key */ | ||
450 | clear_key_des_dma = dma_map_single(ksdev, clear_key_des, 8, | ||
451 | DMA_TO_DEVICE); | ||
452 | dma_sync_single_for_device(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); | ||
453 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); | ||
454 | dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
455 | symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); | ||
456 | |||
457 | jdescsz = mk_job_desc(jdesc, clear_key_des_dma, 8, symint_dma, | ||
458 | symout_dma, 256, | ||
459 | OP_ALG_DECRYPT | OP_ALG_ALGSEL_DES, 0); | ||
460 | |||
461 | #ifdef SM_TEST_DETAIL | ||
462 | dev_info(ksdev, "jobdesc:\n"); | ||
463 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
464 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
465 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
466 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
467 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
468 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
469 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
470 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
471 | #endif | ||
472 | |||
473 | jstat = exec_test_job(ksdev, jdesc); | ||
474 | |||
475 | dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
476 | dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
477 | dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
478 | dma_unmap_single(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); | ||
479 | |||
480 | #ifdef SM_TEST_DETAIL | ||
481 | dev_info(ksdev, "intermediate block:\n"); | ||
482 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
483 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
484 | symint[0], symint[1], symint[2], symint[3], | ||
485 | symint[4], symint[5], symint[6], symint[7]); | ||
486 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
487 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
488 | symint[8], symint[9], symint[10], symint[11], | ||
489 | symint[12], symint[13], symint[14], symint[15]); | ||
490 | dev_info(ksdev, "decrypted block:\n"); | ||
491 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
492 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
493 | symout[0], symout[1], symout[2], symout[3], | ||
494 | symout[4], symout[5], symout[6], symout[7]); | ||
495 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
496 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
497 | symout[8], symout[9], symout[10], symout[11], | ||
498 | symout[12], symout[13], symout[14], symout[15]); | ||
499 | dev_info(ksdev, "caam_sm_test: decrypt cycle with 8 byte key\n"); | ||
500 | #endif | ||
501 | |||
502 | /* Check result */ | ||
503 | if (memcmp(symout, syminp, 256)) { | ||
504 | dev_info(ksdev, "caam_sm_test: 8-byte key test mismatch\n"); | ||
505 | rtnval = -1; | ||
506 | goto freekeys; | ||
507 | } else | ||
508 | dev_info(ksdev, "caam_sm_test: 8-byte key test match OK\n"); | ||
509 | |||
510 | /* AES-128 encrypt using 16 byte black key */ | ||
511 | black_key_aes128_dma = dma_map_single(ksdev, black_key_aes128, 16, | ||
512 | DMA_TO_DEVICE); | ||
513 | dma_sync_single_for_device(ksdev, black_key_aes128_dma, 16, | ||
514 | DMA_TO_DEVICE); | ||
515 | syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); | ||
516 | dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
517 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); | ||
518 | |||
519 | jdescsz = mk_job_desc(jdesc, black_key_aes128_dma, 16, syminp_dma, | ||
520 | symint_dma, 256, | ||
521 | OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); | ||
522 | |||
523 | #ifdef SM_TEST_DETAIL | ||
524 | dev_info(ksdev, "jobdesc:\n"); | ||
525 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
526 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
527 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
528 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
529 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
530 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
531 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
532 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
533 | #endif | ||
534 | |||
535 | jstat = exec_test_job(ksdev, jdesc); | ||
536 | |||
537 | dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
538 | dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
539 | dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
540 | dma_unmap_single(ksdev, black_key_aes128_dma, 16, DMA_TO_DEVICE); | ||
541 | |||
542 | #ifdef SM_TEST_DETAIL | ||
543 | dev_info(ksdev, "input block:\n"); | ||
544 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
545 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
546 | syminp[0], syminp[1], syminp[2], syminp[3], | ||
547 | syminp[4], syminp[5], syminp[6], syminp[7]); | ||
548 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
549 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
550 | syminp[8], syminp[9], syminp[10], syminp[11], | ||
551 | syminp[12], syminp[13], syminp[14], syminp[15]); | ||
552 | dev_info(ksdev, "intermediate block:\n"); | ||
553 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
554 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
555 | symint[0], symint[1], symint[2], symint[3], | ||
556 | symint[4], symint[5], symint[6], symint[7]); | ||
557 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
558 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
559 | symint[8], symint[9], symint[10], symint[11], | ||
560 | symint[12], symint[13], symint[14], symint[15]); | ||
561 | dev_info(ksdev, "caam_sm_test: encrypt cycle with 16 byte key\n"); | ||
562 | #endif | ||
563 | |||
564 | /* AES-128 decrypt using 16 byte clear key */ | ||
565 | clear_key_aes128_dma = dma_map_single(ksdev, clear_key_aes128, 16, | ||
566 | DMA_TO_DEVICE); | ||
567 | dma_sync_single_for_device(ksdev, clear_key_aes128_dma, 16, | ||
568 | DMA_TO_DEVICE); | ||
569 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); | ||
570 | dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
571 | symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); | ||
572 | |||
573 | jdescsz = mk_job_desc(jdesc, clear_key_aes128_dma, 16, symint_dma, | ||
574 | symout_dma, 256, | ||
575 | OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); | ||
576 | |||
577 | #ifdef SM_TEST_DETAIL | ||
578 | dev_info(ksdev, "jobdesc:\n"); | ||
579 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
580 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
581 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
582 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
583 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
584 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
585 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
586 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
587 | #endif | ||
588 | jstat = exec_test_job(ksdev, jdesc); | ||
589 | |||
590 | dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
591 | dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
592 | dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
593 | dma_unmap_single(ksdev, clear_key_aes128_dma, 16, DMA_TO_DEVICE); | ||
594 | |||
595 | #ifdef SM_TEST_DETAIL | ||
596 | dev_info(ksdev, "intermediate block:\n"); | ||
597 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
598 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
599 | symint[0], symint[1], symint[2], symint[3], | ||
600 | symint[4], symint[5], symint[6], symint[7]); | ||
601 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
602 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
603 | symint[8], symint[9], symint[10], symint[11], | ||
604 | symint[12], symint[13], symint[14], symint[15]); | ||
605 | dev_info(ksdev, "decrypted block:\n"); | ||
606 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
607 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
608 | symout[0], symout[1], symout[2], symout[3], | ||
609 | symout[4], symout[5], symout[6], symout[7]); | ||
610 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
611 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
612 | symout[8], symout[9], symout[10], symout[11], | ||
613 | symout[12], symout[13], symout[14], symout[15]); | ||
614 | dev_info(ksdev, "caam_sm_test: decrypt cycle with 16 byte key\n"); | ||
615 | #endif | ||
616 | |||
617 | /* Check result */ | ||
618 | if (memcmp(symout, syminp, 256)) { | ||
619 | dev_info(ksdev, "caam_sm_test: 16-byte key test mismatch\n"); | ||
620 | rtnval = -1; | ||
621 | goto freekeys; | ||
622 | } else | ||
623 | dev_info(ksdev, "caam_sm_test: 16-byte key test match OK\n"); | ||
624 | |||
625 | /* AES-256 encrypt using 32 byte black key */ | ||
626 | black_key_aes256_dma = dma_map_single(ksdev, black_key_aes256, 32, | ||
627 | DMA_TO_DEVICE); | ||
628 | dma_sync_single_for_device(ksdev, black_key_aes256_dma, 32, | ||
629 | DMA_TO_DEVICE); | ||
630 | syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); | ||
631 | dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
632 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); | ||
633 | |||
634 | jdescsz = mk_job_desc(jdesc, black_key_aes256_dma, 32, syminp_dma, | ||
635 | symint_dma, 256, | ||
636 | OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); | ||
637 | |||
638 | #ifdef SM_TEST_DETAIL | ||
639 | dev_info(ksdev, "jobdesc:\n"); | ||
640 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
641 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
642 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
643 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
644 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
645 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
646 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
647 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
648 | #endif | ||
649 | |||
650 | jstat = exec_test_job(ksdev, jdesc); | ||
651 | |||
652 | dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
653 | dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); | ||
654 | dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); | ||
655 | dma_unmap_single(ksdev, black_key_aes256_dma, 32, DMA_TO_DEVICE); | ||
656 | |||
657 | #ifdef SM_TEST_DETAIL | ||
658 | dev_info(ksdev, "input block:\n"); | ||
659 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
660 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
661 | syminp[0], syminp[1], syminp[2], syminp[3], | ||
662 | syminp[4], syminp[5], syminp[6], syminp[7]); | ||
663 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
664 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
665 | syminp[8], syminp[9], syminp[10], syminp[11], | ||
666 | syminp[12], syminp[13], syminp[14], syminp[15]); | ||
667 | dev_info(ksdev, "intermediate block:\n"); | ||
668 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
669 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
670 | symint[0], symint[1], symint[2], symint[3], | ||
671 | symint[4], symint[5], symint[6], symint[7]); | ||
672 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
673 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
674 | symint[8], symint[9], symint[10], symint[11], | ||
675 | symint[12], symint[13], symint[14], symint[15]); | ||
676 | dev_info(ksdev, "caam_sm_test: encrypt cycle with 32 byte key\n"); | ||
677 | #endif | ||
678 | |||
679 | /* AES-256 decrypt using 32-byte black key */ | ||
680 | clear_key_aes256_dma = dma_map_single(ksdev, clear_key_aes256, 32, | ||
681 | DMA_TO_DEVICE); | ||
682 | dma_sync_single_for_device(ksdev, clear_key_aes256_dma, 32, | ||
683 | DMA_TO_DEVICE); | ||
684 | symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); | ||
685 | dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
686 | symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); | ||
687 | |||
688 | jdescsz = mk_job_desc(jdesc, clear_key_aes256_dma, 32, symint_dma, | ||
689 | symout_dma, 256, | ||
690 | OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); | ||
691 | |||
692 | #ifdef SM_TEST_DETAIL | ||
693 | dev_info(ksdev, "jobdesc:\n"); | ||
694 | dev_info(ksdev, "0x%08x\n", jdesc[0]); | ||
695 | dev_info(ksdev, "0x%08x\n", jdesc[1]); | ||
696 | dev_info(ksdev, "0x%08x\n", jdesc[2]); | ||
697 | dev_info(ksdev, "0x%08x\n", jdesc[3]); | ||
698 | dev_info(ksdev, "0x%08x\n", jdesc[4]); | ||
699 | dev_info(ksdev, "0x%08x\n", jdesc[5]); | ||
700 | dev_info(ksdev, "0x%08x\n", jdesc[6]); | ||
701 | dev_info(ksdev, "0x%08x\n", jdesc[7]); | ||
702 | #endif | ||
703 | |||
704 | jstat = exec_test_job(ksdev, jdesc); | ||
705 | |||
706 | dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
707 | dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); | ||
708 | dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); | ||
709 | dma_unmap_single(ksdev, clear_key_aes256_dma, 32, DMA_TO_DEVICE); | ||
710 | |||
711 | #ifdef SM_TEST_DETAIL | ||
712 | dev_info(ksdev, "intermediate block:\n"); | ||
713 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
714 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
715 | symint[0], symint[1], symint[2], symint[3], | ||
716 | symint[4], symint[5], symint[6], symint[7]); | ||
717 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
718 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
719 | symint[8], symint[9], symint[10], symint[11], | ||
720 | symint[12], symint[13], symint[14], symint[15]); | ||
721 | dev_info(ksdev, "decrypted block:\n"); | ||
722 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
723 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
724 | symout[0], symout[1], symout[2], symout[3], | ||
725 | symout[4], symout[5], symout[6], symout[7]); | ||
726 | dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ | ||
727 | "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
728 | symout[8], symout[9], symout[10], symout[11], | ||
729 | symout[12], symout[13], symout[14], symout[15]); | ||
730 | dev_info(ksdev, "caam_sm_test: decrypt cycle with 32 byte key\n"); | ||
731 | #endif | ||
732 | |||
733 | /* Check result */ | ||
734 | if (memcmp(symout, syminp, 256)) { | ||
735 | dev_info(ksdev, "caam_sm_test: 32-byte key test mismatch\n"); | ||
736 | rtnval = -1; | ||
737 | goto freekeys; | ||
738 | } else | ||
739 | dev_info(ksdev, "caam_sm_test: 32-byte key test match OK\n"); | ||
740 | |||
741 | |||
742 | /* Remove 8/16/32 byte keys from keystore */ | ||
743 | freekeys: | ||
744 | stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); | ||
745 | if (stat) | ||
746 | dev_info(ksdev, "caam_sm_test: can't release slot %d\n", | ||
747 | keyslot_des); | ||
748 | |||
749 | stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); | ||
750 | if (stat) | ||
751 | dev_info(ksdev, "caam_sm_test: can't release slot %d\n", | ||
752 | keyslot_aes128); | ||
753 | |||
754 | stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); | ||
755 | if (stat) | ||
756 | dev_info(ksdev, "caam_sm_test: can't release slot %d\n", | ||
757 | keyslot_aes256); | ||
758 | |||
759 | |||
760 | /* Free resources */ | ||
761 | freemem: | ||
762 | #ifdef SM_TEST_DETAIL | ||
763 | dev_info(ksdev, "caam_sm_test: cleaning up\n"); | ||
764 | #endif | ||
765 | kfree(syminp); | ||
766 | kfree(symint); | ||
767 | kfree(symout); | ||
768 | kfree(clear_key_des); | ||
769 | kfree(clear_key_aes128); | ||
770 | kfree(clear_key_aes256); | ||
771 | kfree(black_key_des); | ||
772 | kfree(black_key_aes128); | ||
773 | kfree(black_key_aes256); | ||
774 | kfree(jdesc); | ||
775 | |||
776 | /* Disconnect from keystore and leave */ | ||
777 | sm_release_keystore(ksdev, unit); | ||
778 | |||
779 | return rtnval; | ||
780 | } | ||
781 | EXPORT_SYMBOL(caam_sm_example_init); | ||
782 | |||
783 | void caam_sm_example_shutdown(void) | ||
784 | { | ||
785 | /* unused in present version */ | ||
786 | struct device_node *dev_node; | ||
787 | struct platform_device *pdev; | ||
788 | |||
789 | /* | ||
790 | * Do of_find_compatible_node() then of_find_device_by_node() | ||
791 | * once a functional device tree is available | ||
792 | */ | ||
793 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
794 | if (!dev_node) { | ||
795 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); | ||
796 | if (!dev_node) | ||
797 | return; | ||
798 | } | ||
799 | |||
800 | pdev = of_find_device_by_node(dev_node); | ||
801 | if (!pdev) | ||
802 | return; | ||
803 | |||
804 | of_node_get(dev_node); | ||
805 | |||
806 | } | ||
807 | |||
808 | static int __init caam_sm_test_init(void) | ||
809 | { | ||
810 | struct device_node *dev_node; | ||
811 | struct platform_device *pdev; | ||
812 | |||
813 | /* | ||
814 | * Do of_find_compatible_node() then of_find_device_by_node() | ||
815 | * once a functional device tree is available | ||
816 | */ | ||
817 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); | ||
818 | if (!dev_node) { | ||
819 | dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); | ||
820 | if (!dev_node) | ||
821 | return -ENODEV; | ||
822 | } | ||
823 | |||
824 | pdev = of_find_device_by_node(dev_node); | ||
825 | if (!pdev) | ||
826 | return -ENODEV; | ||
827 | |||
828 | of_node_put(dev_node); | ||
829 | |||
830 | caam_sm_example_init(pdev); | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | |||
836 | /* Module-based initialization needs to wait for dev tree */ | ||
837 | #ifdef CONFIG_OF | ||
838 | module_init(caam_sm_test_init); | ||
839 | module_exit(caam_sm_example_shutdown); | ||
840 | |||
841 | MODULE_LICENSE("Dual BSD/GPL"); | ||
842 | MODULE_DESCRIPTION("FSL CAAM Keystore Usage Example"); | ||
843 | MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); | ||
844 | #endif | ||
diff --git a/drivers/crypto/caam/snvsregs.h b/drivers/crypto/caam/snvsregs.h new file mode 100644 index 000000000000..677e8906e3d0 --- /dev/null +++ b/drivers/crypto/caam/snvsregs.h | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * SNVS hardware register-level view | ||
3 | * | ||
4 | * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved | ||
5 | */ | ||
6 | |||
7 | #ifndef SNVSREGS_H | ||
8 | #define SNVSREGS_H | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | #include <linux/io.h> | ||
12 | |||
13 | /* | ||
14 | * SNVS High Power Domain | ||
15 | * Includes security violations, HA counter, RTC, alarm | ||
16 | */ | ||
17 | struct snvs_hp { | ||
18 | u32 lock; | ||
19 | u32 cmd; | ||
20 | u32 ctl; | ||
21 | u32 secvio_int_en; /* Security Violation Interrupt Enable */ | ||
22 | u32 secvio_int_ctl; /* Security Violation Interrupt Control */ | ||
23 | u32 status; | ||
24 | u32 secvio_status; /* Security Violation Status */ | ||
25 | u32 ha_counteriv; /* High Assurance Counter IV */ | ||
26 | u32 ha_counter; /* High Assurance Counter */ | ||
27 | u32 rtc_msb; /* Real Time Clock/Counter MSB */ | ||
28 | u32 rtc_lsb; /* Real Time Counter LSB */ | ||
29 | u32 time_alarm_msb; /* Time Alarm MSB */ | ||
30 | u32 time_alarm_lsb; /* Time Alarm LSB */ | ||
31 | }; | ||
32 | |||
33 | #define HP_LOCK_HAC_LCK 0x00040000 | ||
34 | #define HP_LOCK_HPSICR_LCK 0x00020000 | ||
35 | #define HP_LOCK_HPSVCR_LCK 0x00010000 | ||
36 | #define HP_LOCK_MKEYSEL_LCK 0x00000200 | ||
37 | #define HP_LOCK_TAMPCFG_LCK 0x00000100 | ||
38 | #define HP_LOCK_TAMPFLT_LCK 0x00000080 | ||
39 | #define HP_LOCK_SECVIO_LCK 0x00000040 | ||
40 | #define HP_LOCK_GENP_LCK 0x00000020 | ||
41 | #define HP_LOCK_MONOCTR_LCK 0x00000010 | ||
42 | #define HP_LOCK_CALIB_LCK 0x00000008 | ||
43 | #define HP_LOCK_SRTC_LCK 0x00000004 | ||
44 | #define HP_LOCK_ZMK_RD_LCK 0x00000002 | ||
45 | #define HP_LOCK_ZMK_WT_LCK 0x00000001 | ||
46 | |||
47 | #define HP_CMD_NONPRIV_AXS 0x80000000 | ||
48 | #define HP_CMD_HAC_STOP 0x00080000 | ||
49 | #define HP_CMD_HAC_CLEAR 0x00040000 | ||
50 | #define HP_CMD_HAC_LOAD 0x00020000 | ||
51 | #define HP_CMD_HAC_CFG_EN 0x00010000 | ||
52 | #define HP_CMD_SNVS_MSTR_KEY 0x00002000 | ||
53 | #define HP_CMD_PROG_ZMK 0x00001000 | ||
54 | #define HP_CMD_SW_LPSV 0x00000400 | ||
55 | #define HP_CMD_SW_FSV 0x00000200 | ||
56 | #define HP_CMD_SW_SV 0x00000100 | ||
57 | #define HP_CMD_LP_SWR_DIS 0x00000020 | ||
58 | #define HP_CMD_LP_SWR 0x00000010 | ||
59 | #define HP_CMD_SSM_SFNS_DIS 0x00000004 | ||
60 | #define HP_CMD_SSM_ST_DIS 0x00000002 | ||
61 | #define HP_CMD_SMM_ST 0x00000001 | ||
62 | |||
63 | #define HP_CTL_TIME_SYNC 0x00010000 | ||
64 | #define HP_CTL_CAL_VAL_SHIFT 10 | ||
65 | #define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT) | ||
66 | #define HP_CTL_CALIB_EN 0x00000100 | ||
67 | #define HP_CTL_PI_FREQ_SHIFT 4 | ||
68 | #define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT) | ||
69 | #define HP_CTL_PI_EN 0x00000008 | ||
70 | #define HP_CTL_TIMEALARM_EN 0x00000002 | ||
71 | #define HP_CTL_RTC_EN 0x00000001 | ||
72 | |||
73 | #define HP_SECVIO_INTEN_EN 0x10000000 | ||
74 | #define HP_SECVIO_INTEN_SRC5 0x00000020 | ||
75 | #define HP_SECVIO_INTEN_SRC4 0x00000010 | ||
76 | #define HP_SECVIO_INTEN_SRC3 0x00000008 | ||
77 | #define HP_SECVIO_INTEN_SRC2 0x00000004 | ||
78 | #define HP_SECVIO_INTEN_SRC1 0x00000002 | ||
79 | #define HP_SECVIO_INTEN_SRC0 0x00000001 | ||
80 | #define HP_SECVIO_INTEN_ALL 0x8000003f | ||
81 | |||
82 | #define HP_SECVIO_ICTL_CFG_SHIFT 30 | ||
83 | #define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT) | ||
84 | #define HP_SECVIO_ICTL_CFG5_SHIFT 5 | ||
85 | #define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT) | ||
86 | #define HP_SECVIO_ICTL_CFG_DISABLE 0 | ||
87 | #define HP_SECVIO_ICTL_CFG_NONFATAL 1 | ||
88 | #define HP_SECVIO_ICTL_CFG_FATAL 2 | ||
89 | #define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010 | ||
90 | #define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008 | ||
91 | #define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004 | ||
92 | #define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002 | ||
93 | #define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001 | ||
94 | |||
95 | #define HP_STATUS_ZMK_ZERO 0x80000000 | ||
96 | #define HP_STATUS_OTPMK_ZERO 0x08000000 | ||
97 | #define HP_STATUS_OTPMK_SYN_SHIFT 16 | ||
98 | #define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT) | ||
99 | #define HP_STATUS_SSM_ST_SHIFT 8 | ||
100 | #define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT) | ||
101 | #define HP_STATUS_SSM_ST_INIT 0 | ||
102 | #define HP_STATUS_SSM_ST_HARDFAIL 1 | ||
103 | #define HP_STATUS_SSM_ST_SOFTFAIL 3 | ||
104 | #define HP_STATUS_SSM_ST_INITINT 8 | ||
105 | #define HP_STATUS_SSM_ST_CHECK 9 | ||
106 | #define HP_STATUS_SSM_ST_NONSECURE 11 | ||
107 | #define HP_STATUS_SSM_ST_TRUSTED 13 | ||
108 | #define HP_STATUS_SSM_ST_SECURE 15 | ||
109 | |||
110 | #define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */ | ||
111 | #define HP_SECVIOST_ZMK_SYN_SHIFT 16 | ||
112 | #define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT) | ||
113 | #define HP_SECVIOST_SECVIO5 0x00000020 | ||
114 | #define HP_SECVIOST_SECVIO4 0x00000010 | ||
115 | #define HP_SECVIOST_SECVIO3 0x00000008 | ||
116 | #define HP_SECVIOST_SECVIO2 0x00000004 | ||
117 | #define HP_SECVIOST_SECVIO1 0x00000002 | ||
118 | #define HP_SECVIOST_SECVIO0 0x00000001 | ||
119 | #define HP_SECVIOST_SECVIOMASK 0x0000003f | ||
120 | |||
121 | /* | ||
122 | * SNVS Low Power Domain | ||
123 | * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK | ||
124 | */ | ||
125 | struct snvs_lp { | ||
126 | u32 lock; | ||
127 | u32 ctl; | ||
128 | u32 mstr_key_ctl; /* Master Key Control */ | ||
129 | u32 secvio_ctl; /* Security Violation Control */ | ||
130 | u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */ | ||
131 | u32 tamper_det_cfg; /* Tamper Detectors Configuration */ | ||
132 | u32 status; | ||
133 | u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */ | ||
134 | u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */ | ||
135 | u32 time_alarm; /* Time Alarm */ | ||
136 | u32 smc_msb; /* Secure Monotonic Counter MSB */ | ||
137 | u32 smc_lsb; /* Secure Monotonic Counter LSB */ | ||
138 | u32 pwr_glitch_det; /* Power Glitch Detector */ | ||
139 | u32 gen_purpose; | ||
140 | u32 zmk[8]; /* Zeroizable Master Key */ | ||
141 | }; | ||
142 | |||
143 | #define LP_LOCK_MKEYSEL_LCK 0x00000200 | ||
144 | #define LP_LOCK_TAMPDET_LCK 0x00000100 | ||
145 | #define LP_LOCK_TAMPFLT_LCK 0x00000080 | ||
146 | #define LP_LOCK_SECVIO_LCK 0x00000040 | ||
147 | #define LP_LOCK_GENP_LCK 0x00000020 | ||
148 | #define LP_LOCK_MONOCTR_LCK 0x00000010 | ||
149 | #define LP_LOCK_CALIB_LCK 0x00000008 | ||
150 | #define LP_LOCK_SRTC_LCK 0x00000004 | ||
151 | #define LP_LOCK_ZMK_RD_LCK 0x00000002 | ||
152 | #define LP_LOCK_ZMK_WT_LCK 0x00000001 | ||
153 | |||
154 | #define LP_CTL_CAL_VAL_SHIFT 10 | ||
155 | #define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT) | ||
156 | #define LP_CTL_CALIB_EN 0x00000100 | ||
157 | #define LP_CTL_SRTC_INVAL_EN 0x00000010 | ||
158 | #define LP_CTL_WAKE_INT_EN 0x00000008 | ||
159 | #define LP_CTL_MONOCTR_EN 0x00000004 | ||
160 | #define LP_CTL_TIMEALARM_EN 0x00000002 | ||
161 | #define LP_CTL_SRTC_EN 0x00000001 | ||
162 | |||
163 | #define LP_MKEYCTL_ZMKECC_SHIFT 8 | ||
164 | #define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT) | ||
165 | #define LP_MKEYCTL_ZMKECC_EN 0x00000010 | ||
166 | #define LP_MKEYCTL_ZMKECC_VAL 0x00000008 | ||
167 | #define LP_MKEYCTL_ZMKECC_PROG 0x00000004 | ||
168 | #define LP_MKEYCTL_MKSEL_SHIFT 0 | ||
169 | #define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT) | ||
170 | #define LP_MKEYCTL_MK_OTP 0 | ||
171 | #define LP_MKEYCTL_MK_ZMK 2 | ||
172 | #define LP_MKEYCTL_MK_COMB 3 | ||
173 | |||
174 | #define LP_SECVIO_CTL_SRC5 0x20 | ||
175 | #define LP_SECVIO_CTL_SRC4 0x10 | ||
176 | #define LP_SECVIO_CTL_SRC3 0x08 | ||
177 | #define LP_SECVIO_CTL_SRC2 0x04 | ||
178 | #define LP_SECVIO_CTL_SRC1 0x02 | ||
179 | #define LP_SECVIO_CTL_SRC0 0x01 | ||
180 | |||
181 | #define LP_TAMPFILT_EXT2_EN 0x80000000 | ||
182 | #define LP_TAMPFILT_EXT2_SHIFT 24 | ||
183 | #define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT) | ||
184 | #define LP_TAMPFILT_EXT1_EN 0x00800000 | ||
185 | #define LP_TAMPFILT_EXT1_SHIFT 16 | ||
186 | #define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT) | ||
187 | #define LP_TAMPFILT_WM_EN 0x00000080 | ||
188 | #define LP_TAMPFILT_WM_SHIFT 0 | ||
189 | #define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT) | ||
190 | |||
191 | #define LP_TAMPDET_OSC_BPS 0x10000000 | ||
192 | #define LP_TAMPDET_VRC_SHIFT 24 | ||
193 | #define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT) | ||
194 | #define LP_TAMPDET_HTDC_SHIFT 20 | ||
195 | #define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT) | ||
196 | #define LP_TAMPDET_LTDC_SHIFT 16 | ||
197 | #define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT) | ||
198 | #define LP_TAMPDET_POR_OBS 0x00008000 | ||
199 | #define LP_TAMPDET_PFD_OBS 0x00004000 | ||
200 | #define LP_TAMPDET_ET2_EN 0x00000400 | ||
201 | #define LP_TAMPDET_ET1_EN 0x00000200 | ||
202 | #define LP_TAMPDET_WMT2_EN 0x00000100 | ||
203 | #define LP_TAMPDET_WMT1_EN 0x00000080 | ||
204 | #define LP_TAMPDET_VT_EN 0x00000040 | ||
205 | #define LP_TAMPDET_TT_EN 0x00000020 | ||
206 | #define LP_TAMPDET_CT_EN 0x00000010 | ||
207 | #define LP_TAMPDET_MCR_EN 0x00000004 | ||
208 | #define LP_TAMPDET_SRTCR_EN 0x00000002 | ||
209 | |||
210 | #define LP_STATUS_SECURE | ||
211 | #define LP_STATUS_NONSECURE | ||
212 | #define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */ | ||
213 | #define LP_STATUS_EXT_SECVIO 0x00010000 | ||
214 | #define LP_STATUS_ET2 0x00000400 | ||
215 | #define LP_STATUS_ET1 0x00000200 | ||
216 | #define LP_STATUS_WMT2 0x00000100 | ||
217 | #define LP_STATUS_WMT1 0x00000080 | ||
218 | #define LP_STATUS_VTD 0x00000040 | ||
219 | #define LP_STATUS_TTD 0x00000020 | ||
220 | #define LP_STATUS_CTD 0x00000010 | ||
221 | #define LP_STATUS_PGD 0x00000008 | ||
222 | #define LP_STATUS_MCR 0x00000004 | ||
223 | #define LP_STATUS_SRTCR 0x00000002 | ||
224 | #define LP_STATUS_LPTA 0x00000001 | ||
225 | |||
226 | /* Full SNVS register page, including version/options */ | ||
227 | struct snvs_full { | ||
228 | struct snvs_hp hp; | ||
229 | struct snvs_lp lp; | ||
230 | u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */ | ||
231 | |||
232 | /* Version / Revision / Option ID space - end of register page */ | ||
233 | u32 vid; /* 0xbf8 HP Version ID (VID 1) */ | ||
234 | u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */ | ||
235 | }; | ||
236 | |||
237 | #endif /* SNVSREGS_H */ | ||