1 /*
2 * Copyright (C) 2016 Freescale Semiconductor, Inc.
3 * Copyright 2017 NXP
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <assert.h>
30 #include <lk/compiler.h>
31 #include <lk/reg.h>
32 #include <malloc.h>
33 #include <openssl/digest.h>
34 #include <openssl/hkdf.h>
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/mman.h>
40 #include <trusty/sys/mman.h>
41 #include <uapi/err.h>
42
43 #include <imx-regs.h>
44 #include "caam.h"
45 #include "fsl_caam_internal.h"
46
47 #define TLOG_TAG "caam_drv"
48 #include <trusty_log.h>
49
50 struct caam_job_rings {
51 uint32_t in[1]; /* single entry input ring */
52 uint32_t out[2]; /* single entry output ring (consists of two words) */
53 };
54
55 /*
56 * According to CAAM docs max number of descriptors in single sequence is 64
57 * You can chain them though
58 */
59 #define MAX_DSC_NUM 64
60
61 struct caam_job {
62 uint32_t dsc[MAX_DSC_NUM]; /* job descriptors */
63 uint32_t dsc_used; /* number of filled entries */
64 uint32_t status; /* job result */
65 };
66
67 static struct caam_job_rings* g_rings;
68 static struct caam_job* g_job;
69
70 const uint32_t rng_inst_dsc[] = {
71 RNG_INST_DESC1, RNG_INST_DESC2, RNG_INST_DESC3,
72 RNG_INST_DESC4, RNG_INST_DESC5, RNG_INST_DESC6,
73 RNG_INST_DESC7, RNG_INST_DESC8, RNG_INST_DESC9};
74
75 #if WITH_CAAM_SELF_TEST
76 static void caam_test(void);
77 #endif
78
caam_clk_get(void)79 static void caam_clk_get(void) {
80 uint32_t val;
81
82 /* make sure clock is on */
83 val = readl(ccm_base + CCM_CAAM_CCGR_OFFSET);
84 #if defined(MACH_IMX6)
85 val |= (3 << 8) | (3 < 10) | (3 << 12);
86 #elif defined(MACH_IMX7)
87 val = (3 << 0); /* Always enabled (for now) */
88 #else
89 #error Unsupported IMX architecture
90 #endif
91 writel(val, ccm_base + CCM_CAAM_CCGR_OFFSET);
92 }
93
setup_job_rings(void)94 static void setup_job_rings(void) {
95 int rc;
96 struct dma_pmem pmem;
97
98 /* Initialize job ring addresses */
99 memset(g_rings, 0, sizeof(*g_rings));
100 rc = prepare_dma(g_rings, sizeof(g_rings), DMA_FLAG_TO_DEVICE, &pmem);
101 if (rc != 1) {
102 TLOGE("prepare_dma failed: %d\n", rc);
103 abort();
104 }
105
106 writel((uint32_t)pmem.paddr + offsetof(struct caam_job_rings, in),
107 CAAM_IRBAR0); // input ring address
108 writel((uint32_t)pmem.paddr + offsetof(struct caam_job_rings, out),
109 CAAM_ORBAR0); // output ring address
110
111 /* Initialize job ring sizes */
112 writel(countof(g_rings->in), CAAM_IRSR0);
113 writel(countof(g_rings->in), CAAM_ORSR0);
114 }
115
run_job(struct caam_job * job)116 static void run_job(struct caam_job* job) {
117 int ret;
118 uint32_t job_pa;
119 struct dma_pmem pmem;
120
121 /* prepare dma job */
122 ret = prepare_dma(job->dsc, job->dsc_used * sizeof(uint32_t),
123 DMA_FLAG_TO_DEVICE, &pmem);
124 assert(ret == 1);
125 job_pa = (uint32_t)pmem.paddr;
126
127 /* Add job to input ring */
128 g_rings->out[0] = 0;
129 g_rings->out[1] = 0;
130 g_rings->in[0] = job_pa;
131
132 ret = prepare_dma(g_rings, sizeof(g_rings), DMA_FLAG_TO_DEVICE, &pmem);
133 assert(ret == 1);
134
135 /* get clock */
136 caam_clk_get();
137
138 /* start job */
139 writel(1, CAAM_IRJAR0);
140
141 /* Wait for job ring to complete the job: 1 completed job expected */
142 while (readl(CAAM_ORSFR0) != 1)
143 ;
144
145 finish_dma(g_rings->out, sizeof(g_rings->out), DMA_FLAG_FROM_DEVICE);
146
147 /* check that descriptor address is the one expected in the out ring */
148 assert(g_rings->out[0] == job_pa);
149
150 job->status = g_rings->out[1];
151
152 /* remove job */
153 writel(1, CAAM_ORJRR0);
154 }
155
init_caam_env(void)156 int init_caam_env(void) {
157 caam_base = mmap(NULL, CAAM_REG_SIZE, PROT_READ | PROT_WRITE,
158 MMAP_FLAG_IO_HANDLE, CAAM_MMIO_ID, 0);
159 if (caam_base == MAP_FAILED) {
160 TLOGE("caam base mapping failed!\n");
161 return ERR_GENERIC;
162 }
163
164 sram_base = mmap(NULL, CAAM_SEC_RAM_SIZE, PROT_READ | PROT_WRITE,
165 MMAP_FLAG_IO_HANDLE, CAAM_SEC_RAM_MMIO_ID, 0);
166 if (sram_base == MAP_FAILED) {
167 TLOGE("caam secure ram base mapping failed!\n");
168 return ERR_GENERIC;
169 }
170
171 ccm_base = mmap(NULL, CCM_REG_SIZE, PROT_READ | PROT_WRITE,
172 MMAP_FLAG_IO_HANDLE, CCM_MMIO_ID, 0);
173 if (ccm_base == MAP_FAILED) {
174 TLOGE("ccm base mapping failed!\n");
175 return ERR_GENERIC;
176 }
177
178 TLOGD("caam bases: %p, %p, %p\n", caam_base, sram_base, ccm_base);
179
180 /* allocate rings */
181 assert(sizeof(struct caam_job_rings) <= 16); /* TODO handle alignment */
182 g_rings = memalign(16, sizeof(struct caam_job_rings));
183 if (!g_rings) {
184 TLOGE("out of memory allocating rings\n");
185 return ERR_NO_MEMORY;
186 }
187
188 /* allocate jobs */
189 g_job = memalign(MAX_DSC_NUM * sizeof(uint32_t), sizeof(struct caam_job));
190 if (!g_job) {
191 TLOGE("out of memory allocating job\n");
192 return ERR_NO_MEMORY;
193 }
194
195 caam_open();
196 #if WITH_CAAM_SELF_TEST
197 caam_test();
198 #endif
199
200 return 0;
201 }
202
caam_open(void)203 void caam_open(void) {
204 uint32_t temp_reg;
205
206 /* switch on CAAM clock */
207 caam_clk_get();
208
209 /* Initialize job ring addresses */
210 setup_job_rings();
211
212 /* HAB disables interrupts for JR0 so do the same here */
213 temp_reg = readl(CAAM_JRCFGR0_LS) | JRCFG_LS_IMSK;
214 writel(temp_reg, CAAM_JRCFGR0_LS);
215
216 /* if RNG already instantiated then skip it */
217 if ((readl(CAAM_RDSTA) & RDSTA_IF0) != RDSTA_IF0) {
218 /* Enter TRNG Program mode */
219 writel(RTMCTL_PGM, CAAM_RTMCTL);
220
221 /* Set OSC_DIV field to TRNG */
222 temp_reg = readl(CAAM_RTMCTL) | (RNG_TRIM_OSC_DIV << 2);
223 writel(temp_reg, CAAM_RTMCTL);
224
225 /* Set delay */
226 writel(((RNG_TRIM_ENT_DLY << 16) | 0x09C4), CAAM_RTSDCTL);
227 writel((RNG_TRIM_ENT_DLY >> 1), CAAM_RTFRQMIN);
228 writel((RNG_TRIM_ENT_DLY << 4), CAAM_RTFRQMAX);
229
230 /* Resume TRNG Run mode */
231 temp_reg = readl(CAAM_RTMCTL) ^ RTMCTL_PGM;
232 writel(temp_reg, CAAM_RTMCTL);
233
234 temp_reg = readl(CAAM_RTMCTL) | RTMCTL_ERR;
235 writel(temp_reg, CAAM_RTMCTL);
236
237 /* init rng job */
238 assert(sizeof(rng_inst_dsc) <= sizeof(g_job->dsc));
239 memcpy(g_job->dsc, rng_inst_dsc, sizeof(rng_inst_dsc));
240 g_job->dsc_used = countof(rng_inst_dsc);
241
242 run_job(g_job);
243
244 if (g_job->status & JOB_RING_STS) {
245 TLOGE("job failed (0x%08x)\n", g_job->status);
246 abort();
247 }
248
249 /* ensure that the RNG was correctly instantiated */
250 temp_reg = readl(CAAM_RDSTA);
251 if (temp_reg != (RDSTA_IF0 | RDSTA_SKVN)) {
252 TLOGE("Bad RNG state 0x%X\n", temp_reg);
253 abort();
254 }
255 }
256
257 return;
258 }
259
caam_decap_blob(const uint8_t * kmod,size_t kmod_size,uint8_t * plain,const uint8_t * blob,uint32_t size)260 uint32_t caam_decap_blob(const uint8_t* kmod,
261 size_t kmod_size,
262 uint8_t* plain,
263 const uint8_t* blob,
264 uint32_t size) {
265 int ret;
266 uint32_t kmod_pa;
267 uint32_t blob_pa;
268 uint32_t plain_pa;
269 struct dma_pmem pmem;
270
271 assert(size + CAAM_KB_HEADER_LEN < 0xFFFFu);
272 assert(kmod_size == 16);
273
274 ret = prepare_dma((void*)kmod, kmod_size, DMA_FLAG_TO_DEVICE, &pmem);
275 if (ret != 1) {
276 TLOGE("failed (%d) to prepare dma buffer\n", ret);
277 return CAAM_FAILURE;
278 }
279 kmod_pa = (uint32_t)pmem.paddr;
280
281 ret = prepare_dma((void*)blob, size + CAAM_KB_HEADER_LEN,
282 DMA_FLAG_TO_DEVICE, &pmem);
283 if (ret != 1) {
284 TLOGE("failed (%d) to prepare dma buffer\n", ret);
285 return CAAM_FAILURE;
286 }
287 blob_pa = (uint32_t)pmem.paddr;
288
289 ret = prepare_dma((void*)plain, size, DMA_FLAG_FROM_DEVICE, &pmem);
290 if (ret != 1) {
291 TLOGE("failed (%d) to prepare dma buffer\n", ret);
292 return CAAM_FAILURE;
293 }
294 plain_pa = (uint32_t)pmem.paddr;
295
296 g_job->dsc[0] = 0xB0800008;
297 g_job->dsc[1] = 0x14400010;
298 g_job->dsc[2] = kmod_pa;
299 g_job->dsc[3] = 0xF0000000 | (0x0000ffff & (size + CAAM_KB_HEADER_LEN));
300 g_job->dsc[4] = blob_pa;
301 g_job->dsc[5] = 0xF8000000 | (0x0000ffff & (size));
302 g_job->dsc[6] = plain_pa;
303 g_job->dsc[7] = 0x860D0000;
304 g_job->dsc_used = 8;
305
306 run_job(g_job);
307
308 if (g_job->status & JOB_RING_STS) {
309 TLOGE("job failed (0x%08x)\n", g_job->status);
310 return CAAM_FAILURE;
311 }
312
313 finish_dma(plain, size, DMA_FLAG_FROM_DEVICE);
314 return CAAM_SUCCESS;
315 }
316
caam_gen_blob(const uint8_t * kmod,size_t kmod_size,const uint8_t * plain,uint8_t * blob,uint32_t size)317 uint32_t caam_gen_blob(const uint8_t* kmod,
318 size_t kmod_size,
319 const uint8_t* plain,
320 uint8_t* blob,
321 uint32_t size) {
322 int ret;
323 uint32_t kmod_pa;
324 uint32_t blob_pa;
325 uint32_t plain_pa;
326 struct dma_pmem pmem;
327
328 assert(size + CAAM_KB_HEADER_LEN < 0xFFFFu);
329 assert(kmod_size == 16);
330
331 ret = prepare_dma((void*)kmod, kmod_size, DMA_FLAG_TO_DEVICE, &pmem);
332 if (ret != 1) {
333 TLOGE("failed (%d) to prepare dma buffer\n", ret);
334 return CAAM_FAILURE;
335 }
336 kmod_pa = (uint32_t)pmem.paddr;
337
338 ret = prepare_dma((void*)plain, size, DMA_FLAG_TO_DEVICE, &pmem);
339 if (ret != 1) {
340 TLOGE("failed (%d) to prepare dma buffer\n", ret);
341 return CAAM_FAILURE;
342 }
343 plain_pa = (uint32_t)pmem.paddr;
344
345 ret = prepare_dma((void*)blob, size + CAAM_KB_HEADER_LEN,
346 DMA_FLAG_FROM_DEVICE, &pmem);
347 if (ret != 1) {
348 TLOGE("failed (%d) to prepare dma buffer\n", ret);
349 return CAAM_FAILURE;
350 }
351 blob_pa = (uint32_t)pmem.paddr;
352
353 g_job->dsc[0] = 0xB0800008;
354 g_job->dsc[1] = 0x14400010;
355 g_job->dsc[2] = kmod_pa;
356 g_job->dsc[3] = 0xF0000000 | (0x0000ffff & (size));
357 g_job->dsc[4] = plain_pa;
358 g_job->dsc[5] = 0xF8000000 | (0x0000ffff & (size + CAAM_KB_HEADER_LEN));
359 g_job->dsc[6] = blob_pa;
360 g_job->dsc[7] = 0x870D0000;
361 g_job->dsc_used = 8;
362
363 run_job(g_job);
364
365 if (g_job->status & JOB_RING_STS) {
366 TLOGE("job failed (0x%08x)\n", g_job->status);
367 return CAAM_FAILURE;
368 }
369
370 finish_dma(blob, size + CAAM_KB_HEADER_LEN, DMA_FLAG_FROM_DEVICE);
371 return CAAM_SUCCESS;
372 }
373
caam_aes_op(const uint8_t * key,size_t key_size,const uint8_t * in,uint8_t * out,size_t len,bool enc)374 uint32_t caam_aes_op(const uint8_t* key,
375 size_t key_size,
376 const uint8_t* in,
377 uint8_t* out,
378 size_t len,
379 bool enc) {
380 int ret;
381 uint32_t in_pa;
382 uint32_t out_pa;
383 uint32_t key_pa;
384 struct dma_pmem pmem;
385
386 assert(key_size == 16);
387 assert(len <= 0xFFFFu);
388 assert(len % 16 == 0);
389
390 ret = prepare_dma((void*)key, key_size, DMA_FLAG_TO_DEVICE, &pmem);
391 if (ret != 1) {
392 TLOGE("failed (%d) to prepare dma buffer\n", ret);
393 return CAAM_FAILURE;
394 }
395 key_pa = (uint32_t)pmem.paddr;
396
397 ret = prepare_dma((void*)in, len, DMA_FLAG_TO_DEVICE, &pmem);
398 if (ret != 1) {
399 TLOGE("failed (%d) to prepare dma buffer\n", ret);
400 return CAAM_FAILURE;
401 }
402 in_pa = (uint32_t)pmem.paddr;
403
404 ret = prepare_dma(out, len, DMA_FLAG_FROM_DEVICE, &pmem);
405 if (ret != 1) {
406 TLOGE("failed (%d) to prepare dma buffer\n", ret);
407 return CAAM_FAILURE;
408 }
409 out_pa = (uint32_t)pmem.paddr;
410
411 /*
412 * Now AES key use aeskey.
413 * aeskey is derived from the first 16 bytes of RPMB key.
414 */
415 g_job->dsc[0] = 0xb0800008;
416 g_job->dsc[1] = 0x02000010;
417 g_job->dsc[2] = key_pa;
418 g_job->dsc[3] = enc ? 0x8210020D : 0x8210020C;
419 g_job->dsc[4] = 0x22120000 | (0x0000ffff & len);
420 g_job->dsc[5] = in_pa;
421 g_job->dsc[6] = 0x60300000 | (0x0000ffff & len);
422 g_job->dsc[7] = out_pa;
423 g_job->dsc_used = 8;
424
425 run_job(g_job);
426
427 if (g_job->status & JOB_RING_STS) {
428 TLOGE("job failed (0x%08x)\n", g_job->status);
429 return CAAM_FAILURE;
430 }
431
432 finish_dma(out, len, DMA_FLAG_FROM_DEVICE);
433 return CAAM_SUCCESS;
434 }
435
caam_hwrng(uint8_t * out,size_t len)436 uint32_t caam_hwrng(uint8_t* out, size_t len) {
437 int ret;
438 struct dma_pmem pmem;
439
440 while (len) {
441 ret = prepare_dma(out, len,
442 DMA_FLAG_FROM_DEVICE | DMA_FLAG_ALLOW_PARTIAL, &pmem);
443 if (ret != 1) {
444 TLOGE("failed (%d) to prepare dma buffer\n", ret);
445 return CAAM_FAILURE;
446 }
447
448 g_job->dsc[0] = 0xB0800004;
449 g_job->dsc[1] = 0x82500000;
450 g_job->dsc[2] = 0x60340000 | (0x0000ffff & pmem.size);
451 g_job->dsc[3] = (uint32_t)pmem.paddr;
452 g_job->dsc_used = 4;
453
454 run_job(g_job);
455
456 if (g_job->status & JOB_RING_STS) {
457 TLOGE("job failed (0x%08x)\n", g_job->status);
458 return CAAM_FAILURE;
459 }
460
461 finish_dma(out, pmem.size, DMA_FLAG_FROM_DEVICE);
462
463 len -= pmem.size;
464 out += pmem.size;
465 }
466
467 return CAAM_SUCCESS;
468 }
469
caam_get_keybox(void)470 void* caam_get_keybox(void) {
471 return sram_base;
472 }
473
caam_hash(uint8_t * in,uint8_t * out,uint32_t len)474 uint32_t caam_hash(uint8_t* in, uint8_t* out, uint32_t len) {
475 int ret;
476 uint32_t in_pa;
477 uint32_t out_pa;
478 struct dma_pmem pmem;
479
480 assert(len <= 0xFFFFu);
481
482 ret = prepare_dma((void*)in, len, DMA_FLAG_TO_DEVICE, &pmem);
483 if (ret != 1) {
484 TLOGE("failed (%d) to prepare dma buffer\n", ret);
485 return CAAM_FAILURE;
486 }
487 in_pa = (uint32_t)pmem.paddr;
488
489 ret = prepare_dma(out, len, DMA_FLAG_FROM_DEVICE, &pmem);
490 if (ret != 1) {
491 TLOGE("failed (%d) to prepare dma buffer\n", ret);
492 return CAAM_FAILURE;
493 }
494 out_pa = (uint32_t)pmem.paddr;
495
496 g_job->dsc[0] = 0xB0800006;
497 g_job->dsc[1] = 0x8441000D;
498 g_job->dsc[2] = 0x24140000 | (0x0000ffff & len);
499 g_job->dsc[3] = in_pa;
500 g_job->dsc[4] = 0x54200000 | 20;
501 g_job->dsc[5] = out_pa;
502 g_job->dsc_used = 6;
503
504 run_job(g_job);
505
506 if (g_job->status & JOB_RING_STS) {
507 TLOGE("job failed (0x%08x)\n", g_job->status);
508 return CAAM_FAILURE;
509 }
510
511 finish_dma(out, len, DMA_FLAG_FROM_DEVICE);
512 return CAAM_SUCCESS;
513 }
514
caam_gen_kdfv1_root_key(uint8_t * out,uint32_t size)515 uint32_t caam_gen_kdfv1_root_key(uint8_t* out, uint32_t size) {
516 int ret;
517 uint32_t pa;
518 struct dma_pmem pmem;
519
520 assert(size == 32);
521
522 ret = prepare_dma((void*)out, size, DMA_FLAG_FROM_DEVICE, &pmem);
523 if (ret != 1) {
524 TLOGE("failed (%d) to prepare dma buffer\n", ret);
525 return CAAM_FAILURE;
526 }
527 pa = (uint32_t)pmem.paddr;
528
529 /*
530 * This sequence uses caam blob generation protocol in
531 * master key verification mode to generate unique for device
532 * persistent 256-bit sequence that we will be using a root key
533 * for our key derivation function v1. This is the only known way
534 * on this platform of producing persistent unique device key that
535 * does not require persistent storage. Dsc[2..5] effectively contains
536 * 16 bytes of randomly generated salt that gets mixed (among other
537 * things) with device master key to produce result.
538 */
539 g_job->dsc[0] = 0xB080000B;
540 g_job->dsc[1] = 0x14C00010;
541 g_job->dsc[2] = 0x7083A393; /* salt word 0 */
542 g_job->dsc[3] = 0x2CC0C9F7; /* salt word 1 */
543 g_job->dsc[4] = 0xFC5D2FC0; /* salt word 2 */
544 g_job->dsc[5] = 0x2C4B04E7; /* salt word 3 */
545 g_job->dsc[6] = 0xF0000000;
546 g_job->dsc[7] = 0;
547 g_job->dsc[8] = 0xF8000030;
548 g_job->dsc[9] = pa;
549 g_job->dsc[10] = 0x870D0002;
550 g_job->dsc_used = 11;
551
552 run_job(g_job);
553
554 if (g_job->status & JOB_RING_STS) {
555 TLOGE("job failed (0x%08x)\n", g_job->status);
556 return CAAM_FAILURE;
557 }
558
559 finish_dma(out, size, DMA_FLAG_FROM_DEVICE);
560 return CAAM_SUCCESS;
561 }
562
563 #if WITH_CAAM_SELF_TEST
564
565 /*
566 * HWRNG
567 */
caam_hwrng_test(void)568 static void caam_hwrng_test(void) {
569 DECLARE_SG_SAFE_BUF(out1, 32);
570 DECLARE_SG_SAFE_BUF(out2, 32);
571
572 caam_hwrng(out1, sizeof(out1));
573 caam_hwrng(out2, sizeof(out2));
574
575 if (memcmp(out1, out2, sizeof(out1)) == 0)
576 TLOGI("caam hwrng test FAILED!!!\n");
577 else
578 TLOGI("caam hwrng test PASS!!!\n");
579 }
580
581 /*
582 * Blob
583 */
caam_blob_test(void)584 static void caam_blob_test(void) {
585 uint i = 0;
586 DECLARE_SG_SAFE_BUF(keymd, 16);
587 DECLARE_SG_SAFE_BUF(plain, 32);
588 DECLARE_SG_SAFE_BUF(plain_bak, 32);
589 DECLARE_SG_SAFE_BUF(blob, 128);
590
591 /* generate random key mod */
592 caam_hwrng(keymd, sizeof(keymd));
593
594 /* build known input */
595 for (i = 0; i < sizeof(plain); i++) {
596 plain[i] = i + '0';
597 plain_bak[i] = plain[i];
598 }
599
600 /* encap blob */
601 caam_gen_blob(keymd, 16, plain, blob, sizeof(plain));
602 memset(plain, 0xff, sizeof(plain));
603
604 /* decap blob */
605 caam_decap_blob(keymd, 16, plain, blob, sizeof(plain));
606
607 /* compare with original */
608 if (memcmp(plain, plain_bak, sizeof(plain)))
609 TLOGI("caam blob test FAILED!!!\n");
610 else
611 TLOGI("caam blob test PASS!!!\n");
612 }
613
614 /*
615 * AES
616 */
caam_aes_test(void)617 static void caam_aes_test(void) {
618 DECLARE_SG_SAFE_BUF(key, 16);
619 DECLARE_SG_SAFE_BUF(buf1, 32);
620 DECLARE_SG_SAFE_BUF(buf2, 32);
621 DECLARE_SG_SAFE_BUF(buf3, 32);
622
623 /* generate random key */
624 caam_hwrng(key, sizeof(key));
625
626 /* create input */
627 for (uint i = 0; i < sizeof(buf1); i++) {
628 buf1[i] = i + '0';
629 }
630
631 /* reset output */
632 memset(buf2, 0x55, sizeof(buf2));
633 memset(buf3, 0xAA, sizeof(buf3));
634
635 /* encrypt same data twice */
636 caam_aes_op(key, 16, buf1, buf2, sizeof(buf1), true);
637 caam_aes_op(key, 16, buf1, buf3, sizeof(buf1), true);
638
639 /* compare results */
640 if (memcmp(buf2, buf3, sizeof(buf1)))
641 TLOGI("caam AES enc test FAILED!!!\n");
642 else
643 TLOGI("caam AES enc test PASS!!!\n");
644
645 /* decrypt res */
646 caam_aes_op(key, 16, buf3, buf2, sizeof(buf3), false);
647
648 /* compare with original */
649 if (memcmp(buf1, buf2, sizeof(buf1)))
650 TLOGI("caam AES enc test FAILED!!!\n");
651 else
652 TLOGI("caam AES enc test PASS!!!\n");
653 }
654
655 /*
656 * HASH (SHA-1)
657 */
caam_hash_test(void)658 static void caam_hash_test(void) {
659 DECLARE_SG_SAFE_BUF(in, 32);
660 DECLARE_SG_SAFE_BUF(hash1, 32);
661 DECLARE_SG_SAFE_BUF(hash2, 32);
662
663 /* generate input */
664 for (uint i = 0; i < sizeof(in); i++) {
665 in[i] = i + '1';
666 }
667
668 /* reset output */
669 memset(hash1, 0x55, sizeof(hash1));
670 memset(hash2, 0xAA, sizeof(hash2));
671
672 /* invoke hash twice */
673 caam_hash(in, hash1, sizeof(in));
674 caam_hash(in, hash2, sizeof(in));
675
676 /* compare results */
677 if (memcmp(hash1, hash2, 20) != 0)
678 TLOGI("caam hash test FAILED!!!\n");
679 else
680 TLOGI("caam hash test PASS!!!\n");
681 }
682
caam_kdfv1_root_key_test(void)683 static void caam_kdfv1_root_key_test(void) {
684 DECLARE_SG_SAFE_BUF(out1, 32);
685 DECLARE_SG_SAFE_BUF(out2, 32);
686
687 caam_gen_kdfv1_root_key(out1, 32);
688 caam_gen_kdfv1_root_key(out2, 32);
689
690 if (memcmp(out1, out2, 32) != 0)
691 TLOGI("caam gen kdf root key test FAILED!!!\n");
692 else
693 TLOGI("caam gen kdf root key test PASS!!!\n");
694 }
695
caam_test(void)696 static void caam_test(void) {
697 caam_hwrng_test();
698 caam_blob_test();
699 caam_kdfv1_root_key_test();
700 caam_aes_test();
701 caam_hash_test();
702 }
703
704 #endif /* WITH_CAAM_SELF_TEST */
705