1 /* caam_driver.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22 #if (defined(__INTEGRITY) || defined(INTEGRITY)) || \
23 (defined(__QNX__) || defined(__QNXNTO__))
24
25 #if defined(__QNX__) || defined(__QNXNTO__)
26 #include <sys/mman.h>
27 #include <hw/inout.h>
28 #include <sys/iofunc.h>
29 #include <sys/neutrino.h>
30
31 #include <wolfssl/wolfcrypt/port/caam/caam_qnx.h>
32 #endif
33
34 #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
35 #include <wolfssl/wolfcrypt/port/caam/caam_error.h>
36
37 #include <string.h> /* for memcpy / memset */
38
39
40 struct JobRing {
41 CAAM_ADDRESS JobIn;
42 CAAM_ADDRESS JobOut;
43 CAAM_ADDRESS Desc;
44 void* VirtualIn;
45 void* VirtualOut;
46 void* VirtualDesc;
47 Value page; /* page allocation for descriptor to use */
48 CAAM_MUTEX jr_lock;
49 };
50
51 struct CAAM_DEVICE {
52 #if defined(__INTEGRITY) || defined(INTEGRITY)
53 struct IODeviceVectorStruct caamVector;
54 struct IODescriptorStruct IODescriptorArray[BUFFER_COUNT];
55 struct DescStruct DescArray[DESC_COUNT];
56 volatile Value InterruptStatus;
57 CALL HandleInterruptCall;
58 #endif
59 struct JobRing ring;
60 };
61
62 #define DRIVER_NAME "wolfSSL_CAAM_Driver"
63
64 static struct CAAM_DEVICE caam;
65
66 /* function declarations */
67 Error caamAddJob(DESCSTRUCT* desc);
68 Error caamDoJob(DESCSTRUCT* desc);
69
70
71 /******************************************************************************
72 Internal CAAM Job Ring and partition functions
73 ****************************************************************************/
74
75 #ifdef CAAM_DEBUG_MODE
76 /* runs a descriptor in debug mode */
caamDebugDesc(struct DescStruct * desc)77 static Error caamDebugDesc(struct DescStruct* desc)
78 {
79 int z;
80 int sz;
81 unsigned int flag = 0x20000000;
82
83 /* clear and set desc size */
84 sz = desc->desc[0] & 0x0000007F;
85 CAAM_WRITE(CAAM_DECORR, 1); /* ask for DECO permissions */
86 printf("CAAM_DECORR = 0x%08X\n", CAAM_READ(CAAM_DECORR));
87 printf("STATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS));
88 printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4));
89 printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04));
90
91 printf("Descriptor input :\n");
92 /* write descriptor into descriptor buffer */
93 for (z = 0; z < sz; z = z + 1) {
94 CAAM_WRITE(CAAM_DODESB + (z*4), desc->desc[z]);
95 printf("\t0x%08X\n", desc->desc[z]);
96 }
97 printf("\n");
98
99 printf("command size = %d\n", sz);
100 if (sz > 4) {
101 flag |= 0x10000000;
102 }
103
104 CAAM_WRITE(CAAM_DODAR+4, desc->caam->ring.Desc);
105 /* set WHL bit since we loaded the entire descriptor */
106 CAAM_WRITE(CAAM_DOJQCR_MS, flag);
107
108 printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4));
109 printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04));
110
111 /* DECO buffer */
112 printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4));
113 printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS));
114 printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044));
115 for (z = 0; z < sz; z = z + 1) {
116 printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4)));
117 }
118
119
120 //D0JQCR_LS
121 printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804));
122 printf("Desc = 0x%08X\n", desc->caam->ring.Desc);
123
124
125 /* DECO buffer */
126 printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4));
127 printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS));
128 printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044));
129 for (z = 0; z < sz; z = z + 1) {
130 printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4)));
131 }
132
133 printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804));
134 printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4));
135 while ((CAAM_READ(0x8E04) & 0x80000000U) != 0U) {
136 printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n",
137 CAAM_READ(0x8E04));
138 sleep(1);
139 }
140 CAAM_WRITE(CAAM_DECORR, 0); /* free DECO */
141 printf("done with debug job\n");
142 return Success;
143 }
144 #endif /* CAAM_DEBUG_MODE */
145
146
147 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
printSecureMemoryInfo()148 static void printSecureMemoryInfo()
149 {
150 unsigned int SMVID_MS, SMVID_LS;
151
152 printf("SMSTA = 0x%08X\n", CAAM_READ(0x1FB4));
153 printf("SMPO = 0x%08X\n", CAAM_READ(CAAM_SM_SMPO));
154 SMVID_MS = CAAM_READ(CAAM_SM_SMVID_MS);
155 SMVID_LS = CAAM_READ(CAAM_SM_SMVID_LS);
156 printf("\tNumber Partitions : %d\n", ((SMVID_MS >> 12) & 0xFU));
157 printf("\tNumber Pages : %d\n", (SMVID_MS & 0x3FFU));
158 printf("\tPage Size : 2^%d\n", ((SMVID_LS >> 16) & 0x7U));
159 }
160 #endif
161
162 /* flush job ring and reset */
caamReset(void)163 static Error caamReset(void)
164 {
165 int t = 100000; /* time out counter for flushing job ring */
166
167 /* make sure interrupts are masked in JRCFGR0_LS register */
168 CAAM_WRITE(0x1054, CAAM_READ(0x1054) | 1);
169
170 /* flush and reset job rings using JRCR0 register */
171 CAAM_WRITE(0x106C, 1);
172
173 /* check register JRINTR for if halt is in progress */
174 while (t > 0 && ((CAAM_READ(0x104C) & 0x4) == 0x4)) { t = t - 1; }
175 if (t == 0) {
176 /*unrecoverable failure, the job ring is locked, up hard reset needed*/
177 return -1;//NotRestartable;
178 }
179
180 /* now that flush has been done restart the job ring */
181 t = 100000;
182 CAAM_WRITE(0x106C, 1);
183 while (t > 0 && ((CAAM_READ(0x106C) & 1) == 1)) { t = t - 1; }
184 if (t == 0) {
185 /*unrecoverable failure, reset bit did not return to 0 */
186 return -1;//NotRestartable;
187 }
188
189 /* reset most registers and state machines in CAAM using MCFGR register
190 also reset DMA */
191 CAAM_WRITE(0x0004, 0x90000000);
192
193 /* DAR 0x0120 can be used to check if hung */
194
195 /* DDR */
196 CAAM_WRITE(0x0124, 1);
197
198 return Success;
199 }
200
201
202 /* free the page and dealloc */
caamFreePage(unsigned int page)203 static Error caamFreePage(unsigned int page)
204 {
205 /* owns the page can dealloc it */
206 CAAM_WRITE(CAAM_SM_CMD, (page << 16U) | 0x2U);
207 while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 &&
208 (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) {
209 CAAM_CPU_CHILL();
210 }
211 if ((CAAM_READ(CAAM_SM_STATUS) & 0x00003000) > 0) {
212 /* error while deallocating page */
213 WOLFSSL_MSG("error while deallocating page");
214 return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */
215 }
216 WOLFSSL_MSG("free'd page");
217 return Success;
218 }
219
220 /* free the partition and dealloc */
caamFreePart(unsigned int part)221 Error caamFreePart(unsigned int part)
222 {
223 unsigned int status;
224
225 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
226 printf("freeing partition %d\n", part);
227 #endif
228 CAAM_WRITE(CAAM_SM_CMD, (part << 8U) | 0x3U);
229
230 status = CAAM_READ(CAAM_SM_STATUS);
231 while (((status & 0x00004000U) > 0U) && ((status & 0x00003000U) == 0U)) {
232 CAAM_CPU_CHILL();
233 status = CAAM_READ(CAAM_SM_STATUS);
234 }
235
236 if (((status & 0x00003000U) > 0U) || ((status & 0x0000C000U) > 0U)) {
237 /* error while deallocating page */
238 WOLFSSL_MSG("error while deallocating partition");
239 return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */
240 }
241 WOLFSSL_MSG("free'd partition");
242 return Success;
243 }
244
245
246 /* find all partitions we own and free them */
caamFreeAllPart()247 static Error caamFreeAllPart()
248 {
249 unsigned int SMPO;
250 unsigned int i;
251
252 WOLFSSL_MSG("Free all partitions");
253 SMPO = CAAM_READ(0x1FBC);
254 for (i = 0; i < 15U; i = i + 1U) {
255 if ((SMPO & (0x3U << (i * 2U))) == (0x3U << (i * 2U))) {
256 caamFreePart(i);
257 }
258 }
259
260 return 0;
261 }
262
263
264 /* search through the partitions to find an unused one
265 * returns negative value on failure, on success returns 0 or greater
266 */
caamFindUnusedPartition()267 int caamFindUnusedPartition()
268 {
269 unsigned int SMPO;
270 unsigned int i;
271 int ret = -1;
272
273 SMPO = CAAM_READ(0x1FBC);
274 for (i = 0; i < 15U; i = i + 1) {
275 if ((SMPO & (0x3U << (i * 2U))) == 0U) {
276 ret = (int)i;
277 break;
278 }
279 }
280
281 return ret;
282 }
283
284
285 /* flag contains how the parition is set i.e CSP flag and read/write access
286 * it also contains if locked
287 */
caamCreatePartition(unsigned int page,unsigned int par,unsigned int flag)288 static Error caamCreatePartition(unsigned int page, unsigned int par,
289 unsigned int flag)
290 {
291
292 unsigned int status;
293
294 /* check ownership of partition */
295 status = CAAM_READ(0x1FBC);
296 if ((status & (0x3U << (par * 2))) > 0) {
297 if ((status & (0x3U << (par * 2))) == (0x3U << (par * 2))) {
298 WOLFSSL_MSG("we own this partition!");
299 }
300 else {
301 return MemoryMapMayNotBeEmpty;
302 }
303 }
304
305 CAAM_WRITE(0x1A04 + (par * 16), flag);
306
307 /* dealloc page if we own it */
308 CAAM_WRITE(CAAM_SM_CMD, (page << 16) | 0x5);
309 while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 &&
310 (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) {
311 CAAM_CPU_CHILL();
312 }
313 if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0xC0) {
314 if (caamFreePage(page) != Success) {
315 return MemoryMapMayNotBeEmpty;
316 }
317 }
318 else if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0x00) {
319 WOLFSSL_MSG("page available and un-owned");
320 }
321 else {
322 WOLFSSL_MSG("we don't own the page...");
323 return -1;
324 }
325
326 CAAM_WRITE(CAAM_SM_CMD, (page << 16) | (par << 8) | 0x1);
327 /* wait for alloc cmd to complete */
328 while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 &&
329 (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) {
330 CAAM_CPU_CHILL();
331 }
332
333 return Success;
334 }
335
336
337 /* return a partitions physical address on success, returns 0 on fail */
caamGetPartition(unsigned int part,int partSz,unsigned int flag)338 CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag)
339 {
340 int err;
341
342 (void)flag; /* flag is for future changes to flag passed when creating */
343
344 /* create and claim the partition */
345 err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK |
346 CAAM_SM_CSP | CAAM_SM_ALL_RW);
347 if (err != Success) {
348 WOLFSSL_MSG("Error creating partiions for secure ecc key");
349 return 0;
350 }
351
352 return (CAAM_ADDRESS)(CAAM_PAGE + (part << 12));
353 }
354
355
356 /* Gets the status of a job. Returns CAAM_WAITING if no output jobs ready to be
357 * read.
358 * If no jobs are done then return CAAM_WAITING
359 * If jobs are done but does not match desc then return NoActivityReady
360 * Status holds the error values if any */
caamGetJob(struct CAAM_DEVICE * dev,unsigned int * status)361 static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status)
362 {
363 unsigned int reg;
364 if (status) {
365 *status = 0;
366 }
367
368 #ifdef CAAM_DEBUG_MODE
369 (void)dev;
370 return Success;
371 #endif
372
373 /* Check number of done jobs in output list */
374 reg = CAAM_READ(0x103C);
375 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
376 printf("number of jobs in output list = 0x%08X\n", reg);
377 #endif
378 if ((reg & 0x000003FF) > 0) {
379 unsigned int *pt;
380
381 if (CAAM_ADR_SYNC(caam.ring.VirtualOut, (2 * CAAM_JOBRING_SIZE *
382 sizeof(unsigned int))) != 0) {
383 return -1;
384 }
385
386 /* sanity check on job out */
387 pt = (unsigned int*)caam.ring.VirtualOut;
388 if (pt[0] != caam.ring.Desc) {
389 return -1;
390 }
391 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
392 printf("\tjob 0x%08X done - result 0x%08X\n", pt[0], pt[1]);
393 #endif
394 *status = pt[1];
395
396 /* increment jobs removed */
397 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
398 printf("removing job from list\n");
399 fflush(stdout);
400 #endif
401 CAAM_WRITE(0x1034, 1);
402 }
403 else {
404 /* check if the CAAM is idle and not processing any descriptors */
405 if ((CAAM_READ(0x0FD4) & 0x00000002) == 2 /* idle */
406 && (CAAM_READ(0x0FD4) & 0x00000001) == 0) {
407 WOLFSSL_MSG("caam is idle.....");
408 return NoActivityReady;
409 }
410 return CAAM_WAITING;
411 }
412 (void)dev;
413
414 CAAM_WRITE(JRCFGR_JR0_LS, 0);
415 if (*status == 0) {
416 return Success;
417 }
418 return Failure;
419 }
420
421
422 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
423 /* debug print out JDKEK */
print_jdkek()424 static void print_jdkek()
425 {
426 int i;
427
428 printf("JDKEK = ");
429 for (i = 0; i < 8; i = i + 1) {
430 printf("%08X ", CAAM_READ(0x0400 + (i*4)));
431 }
432 printf("\n");
433 }
434 #endif
435
436
437 /* instantiate RNG and create JDKEK, TDKEK, and TDSK key */
438 #define WC_RNG_START_SIZE 6
439 static unsigned int wc_rng_start[WC_RNG_START_SIZE] = {
440 CAAM_HEAD | 0x00000006,
441 CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0
442 with TRNG */
443 CAAM_JUMP | 0x02000001, /* wait for Class1 RNG and jump to next cmd */
444 CAAM_LOAD | 0x00880004, /* Load to clear written register */
445 0x00000001, /* reset done interrupt */
446 CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000 /* Generate secure keys */
447 };
448
449
450 /* Initialize CAAM RNG
451 * returns 0 on success */
452 int caamInitRng(struct CAAM_DEVICE* dev);
caamInitRng(struct CAAM_DEVICE * dev)453 int caamInitRng(struct CAAM_DEVICE* dev)
454 {
455 DESCSTRUCT desc;
456 unsigned int reg, entropy_delay;
457 int ret = 0, i;
458
459 /* set up the job description for RNG initialization */
460 memset(&desc, 0, sizeof(DESCSTRUCT));
461 desc.desc[desc.idx++] = CAAM_HEAD; /* later will put size to header*/
462 for (i = 1; i < WC_RNG_START_SIZE; i++) {
463 desc.desc[desc.idx++] = wc_rng_start[i];
464 }
465 desc.caam = dev;
466
467 /* Attempt to start the RNG, first trying the fastest entropy delay value
468 * and increasing it after each failed attempt until either a success is hit
469 * or the max delay value is.
470 */
471 for (entropy_delay = CAAM_ENT_DLY; entropy_delay <= CAAM_ENT_DLY_MAX;
472 entropy_delay = entropy_delay + CAAM_ENT_DLY_INCREMENT) {
473
474 /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */
475 /* check out the status and see if already setup */
476 CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM);
477 CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | CAAM_RTMCTL_RESET);
478
479 /* Set up reading from TRNG */
480 CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | CAAM_TRNG);
481
482 /* Set up delay for TRNG
483 * Shift left with RTSDCTL because 0-15 is for sample number
484 * Also setting the max and min frequencies */
485 CAAM_WRITE(CAAM_RTSDCTL, (entropy_delay << 16) | CAAM_ENT_SAMPLE);
486 CAAM_WRITE(CAAM_RTFRQMIN, entropy_delay >> CAAM_ENT_MINSHIFT);
487 CAAM_WRITE(CAAM_RTFRQMAX, entropy_delay << CAAM_ENT_MAXSHIFT);
488
489 #ifdef WOLFSSL_CAAM_PRINT
490 printf("Attempt with entropy delay set to %d\n", entropy_delay);
491 printf("Min delay of %d and max of %d\n",
492 entropy_delay >> CAAM_ENT_MINSHIFT,
493 entropy_delay << CAAM_ENT_MAXSHIFT);
494 #endif
495
496 /* Set back to run mode and clear RTMCL error bit */
497 reg = CAAM_READ(CAAM_RTMCTL) & (~CAAM_PRGM);
498 CAAM_WRITE(CAAM_RTMCTL, reg);
499 reg = CAAM_READ(CAAM_RTMCTL);
500 reg |= CAAM_CTLERR;
501 CAAM_WRITE(CAAM_RTMCTL, reg);
502
503 /* check out the status and see if already setup */
504 reg = CAAM_READ(CAAM_RDSTA);
505 if (((reg >> 16) & 0xF) > 0) {
506 WOLFSSL_MSG("RNG is in error state, resetting");
507 caamReset();
508 }
509
510 if (reg & (1U << 30)) {
511 WOLFSSL_MSG("JKDKEK rng was setup using a non determinstic key");
512 return 0;
513 }
514
515 do {
516 ret = caamDoJob(&desc);
517 } while (ret == CAAM_WAITING);
518
519 /* if this entropy delay frequency succeeded then break out, otherwise
520 * try again with increasing the delay value */
521 if (ret == Success) {
522 WOLFSSL_MSG("Init RNG success");
523 break;
524 }
525 WOLFSSL_MSG("Increasing entropy delay");
526 }
527
528 if (ret == Success)
529 return 0;
530 return -1;
531 }
532
533
534 /* Take in a descriptor and add it to the job list */
caamAddJob(DESCSTRUCT * desc)535 Error caamAddJob(DESCSTRUCT* desc)
536 {
537 /* clear and set desc size */
538 desc->desc[0] &= 0xFFFFFF80;
539 desc->desc[0] += desc->idx + (desc->startIdx << 16);
540
541 CAAM_LOCK_MUTEX(&caam.ring.jr_lock);
542 /* check input slot is available and then add */
543 if (CAAM_READ(0x1014) > 0) {
544 int i;
545 unsigned int *pt;
546
547 pt = (unsigned int*)caam.ring.VirtualDesc;
548 #if defined(WOLFSSL_CAAM_PRINT)
549 printf("Doing Job :\n");
550 #endif
551 for (i = 0; i < desc->idx; i = i + 1) {
552 pt[i] = desc->desc[i];
553 #if defined(WOLFSSL_CAAM_PRINT)
554 printf("\tCMD %02d [%p] = 0x%08X\n", i+1, pt + i,
555 desc->desc[i]);
556 #endif
557 }
558
559 pt = (unsigned int*)caam.ring.VirtualIn;
560 pt[0] = (unsigned int)caam.ring.Desc;
561
562 if (CAAM_ADR_SYNC(caam.ring.VirtualDesc,
563 desc->idx * sizeof(unsigned int)) != 0) {
564 CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock);
565 return -1;
566 }
567
568 if (CAAM_ADR_SYNC(caam.ring.VirtualIn,
569 CAAM_JOBRING_SIZE * sizeof(unsigned int)) != 0) {
570 CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock);
571 return -1;
572 }
573
574 #ifdef CAAM_DEBUG_MODE
575 caamDebugDesc(desc);
576 #else
577 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
578 printf("started job 0x%08X done\n", (unsigned int)caam.ring.Desc);
579 #endif
580 CAAM_WRITE(CAAM_IRJAR0, 0x00000001);
581 #endif
582 }
583 else {
584 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
585 printf("SLOT = 0x%08X, IRJAR0 = 0x%08X\n", CAAM_READ(0x1014),
586 CAAM_READ(CAAM_IRJAR0));
587 printf("Number of job in done queue = 0x%08X\n", CAAM_READ(0x103C));
588 #endif
589 CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock);
590 return CAAM_WAITING;
591 }
592 CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock);
593 return Success;
594 }
595
596
597 /* Synchronous job completion, add it to job queue and wait till finished */
caamDoJob(DESCSTRUCT * desc)598 Error caamDoJob(DESCSTRUCT* desc)
599 {
600 Error ret;
601 unsigned int status;
602
603 ret = caamAddJob(desc);
604 if (ret != Success) {
605 return ret;
606 }
607
608 do {
609 ret = caamGetJob(desc->caam, &status);
610 CAAM_CPU_CHILL();
611 } while (ret == CAAM_WAITING);
612
613 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
614 printf("job status = 0x%08X, ret = %d\n", status, ret);
615 #endif
616
617 if (status != 0 || ret != Success) {
618 /* try to reset after error */
619 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
620 int i;
621 for (i = 0; i < desc->idx; i = i + 1) {
622 printf("\tCMD %02d = 0x%08X\n", i+1, desc->desc[i]);
623 }
624 printf("\n");
625 #endif
626 /* consider any job ring errors as fatal, and try reset */
627 if (caamParseJRError(CAAM_READ(JRINTR_JR0)) != 0) {
628 caamReset();
629 }
630 caamParseError(status);
631 return ret;
632 }
633
634 return Success;
635 }
636
637
638 /******************************************************************************
639 CAAM Blob Operations
640 ****************************************************************************/
641
642 /* limit on size due to size of job ring being 64 unsigned int's */
caamBlob(DESCSTRUCT * desc)643 int caamBlob(DESCSTRUCT* desc)
644 {
645 void *vaddrOut, *vaddr, *keymod;
646 Error err;
647 unsigned int keyType = 0x00000C08; /* default red */
648 unsigned int i = 0;
649 int inputSz;
650 int outputSz;
651
652 if (desc->idx + 3 > MAX_DESC_SZ) {
653 return Failure;
654 }
655
656 /* doing black blobs */
657 if (desc->state) {
658 WOLFSSL_MSG("making a black blob");
659 keyType = 0x00000010;
660 }
661
662 desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | keyType);
663
664 /* add key modifier */
665 keymod = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
666 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(keymod, desc->buf[i].dataSz);
667 i++;
668
669 inputSz = desc->buf[i].dataSz;
670 if (desc->state && (desc->type == CAAM_BLOB_ENCAP)) {
671 /* black keys with CCM have mac at the end */
672 inputSz += BLACK_KEY_MAC_SZ;
673 }
674
675 vaddr = CAAM_ADR_MAP(desc->buf[i].data, inputSz, 1);
676
677 /* add input */
678 desc->desc[desc->idx++] = CAAM_SEQI + desc->buf[i].dataSz;
679 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr, inputSz);
680 i++;
681 desc->outputIdx = i;
682
683 outputSz = desc->buf[i].dataSz;
684 if (desc->state && (desc->type == CAAM_BLOB_DECAP)) {
685 /* black keys with CCM have mac at the end */
686 outputSz += BLACK_KEY_MAC_SZ;
687 }
688 vaddrOut = CAAM_ADR_MAP(desc->buf[i].data, outputSz, 0);
689
690 /* add output */
691 desc->desc[desc->idx++] = CAAM_SEQO + desc->buf[i].dataSz;
692 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddrOut, outputSz);
693 if (desc->idx + 1 > MAX_DESC_SZ) {
694 return Failure;
695 }
696 desc->desc[desc->idx] = CAAM_OP | CAAM_OPID_BLOB | desc->type;
697
698 if (desc->state) {
699 desc->desc[desc->idx] |= 0x104; /* EKT and Black_key (key is covered) */
700 }
701 desc->idx++;
702 do {
703 err = caamDoJob(desc);
704 } while (err == CAAM_WAITING);
705
706 CAAM_ADR_UNMAP(keymod, desc->buf[0].data, desc->buf[0].dataSz, 0);
707 CAAM_ADR_UNMAP(vaddr, desc->buf[1].data, inputSz, 0);
708 CAAM_ADR_UNMAP(vaddrOut, desc->buf[2].data, outputSz, 1);
709
710 return err;
711 }
712
713
714 /******************************************************************************
715 CAAM AES Operations
716 ****************************************************************************/
717
caamAesCmac(DESCSTRUCT * desc,int sz,unsigned int args[4])718 int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4])
719 {
720 Error err;
721 unsigned int keySz;
722 unsigned int macSz = 0;
723 void *vaddr[4] = {0};
724 unsigned int vidx = 0;
725 unsigned int ctx;
726 unsigned int isBlackKey;
727 int i;
728
729 isBlackKey = args[2];
730 keySz = args[1];
731
732 /* Get CTX physical address */
733 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[1].data, desc->buf[1].dataSz, 1);
734 ctx = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[1].dataSz);
735 vidx++;
736
737 /* LOAD KEY */
738 desc->desc[desc->idx] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + keySz;
739 if (isBlackKey) {
740 desc->desc[desc->idx] |= CAAM_LOAD_BLACK_KEY;
741 macSz = BLACK_KEY_MAC_SZ;
742 }
743 desc->idx++;
744 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[0].data, desc->buf[0].dataSz + macSz, 1);
745 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
746 desc->buf[0].dataSz + macSz);
747 #if 0
748 {
749 unsigned int p; byte* pt = (byte*)vaddr[vidx];
750 printf("Using key [%d]:", desc->buf[0].dataSz + macSz);
751 for (p = 0; p < keySz; p++)
752 printf("%02X", pt[p]);
753 printf("\n");
754 }
755 #endif
756 vidx++;
757
758 /* Load in CTX only when not initialization */
759 if ((desc->state & CAAM_ALG_INIT) == 0) {
760 int ofst = 0;
761 desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) +
762 desc->buf[1].dataSz;
763 desc->desc[desc->idx++] = ctx;
764
765 #if 0
766 {
767 unsigned int z; byte* pt = (byte*)vaddr[0];
768 printf("loading in CTX [%d] :", desc->buf[1].dataSz);
769 for (z = 0; z < 32; z++)
770 printf("%02X", pt[z]);
771 printf("\n");
772 }
773 #endif
774 }
775
776 /* add protinfo to operation command */
777 desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | desc->state;
778
779 /* add in all input buffers */
780 for (i = 2; i < sz; i = i + 1) {
781 desc->desc[desc->idx] = (CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_MSG)
782 + desc->buf[i].dataSz;
783 if (i+1 == sz) {
784 /* this is the last input buffer, signal the HW with LC1 bit */
785 desc->desc[desc->idx] |= FIFOL_TYPE_LC1;
786 }
787 desc->idx++;
788
789 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
790 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
791 desc->buf[i].dataSz);
792
793 #if 0
794 {
795 unsigned int z; byte* pt = (byte*)vaddr[vidx];
796 printf("MSG [%d] :", desc->buf[i].dataSz);
797 for (z = 0; z < desc->buf[i].dataSz; z++)
798 printf("%02X", pt[z]);
799 printf("\n");
800 }
801 #endif
802
803 vidx++;
804 }
805
806 /* if there is no input buffers than add in a single FIFO LOAD to kick off
807 * the operation */
808 if (sz == 2) { /* only key and ctx buffer */
809 desc->desc[desc->idx++] = CAAM_FIFO_L | FIFOL_TYPE_LC1 | CAAM_CLASS1 |
810 FIFOL_TYPE_MSG;
811 vaddr[vidx] = CAAM_ADR_MAP(0, 0, 0);
812 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], 0);
813 vidx++;
814 }
815
816 desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | 32;
817 desc->desc[desc->idx++] = ctx;
818
819 do {
820 err = caamDoJob(desc);
821 } while (err == CAAM_WAITING);
822
823 #if 0
824 {
825 unsigned int z; byte* pt = (byte*)vaddr[0];
826 printf("CTX: ");
827 for (z = 0; z < 32; z++)
828 printf("%02X", pt[z]);
829 printf("\n");
830 }
831 #endif
832
833 vidx = 0;
834 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[1].data, desc->buf[1].dataSz, 1);
835 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[0].data, desc->buf[0].dataSz + macSz, 0);
836 if (sz == 2) {
837 CAAM_ADR_UNMAP(vaddr[vidx], 0, 0, 0);
838 }
839 else {
840 for (i = 2; i < sz; i = i + 1) { /* unmap the input buffers */
841 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data,
842 desc->buf[i].dataSz, 0);
843 }
844 }
845
846 return err;
847 }
848
849
850 /* ECDSA generate black key
851 *
852 * return Success on success. All other return values are considered a fail
853 * case.
854 */
caamECDSAMake(DESCSTRUCT * desc,CAAM_BUFFER * buf,unsigned int args[4])855 int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4])
856 {
857 Error err;
858 unsigned int part = 0;
859 unsigned int isBlackKey = 0;
860 unsigned int pdECDSEL = 0;
861 unsigned int phys;
862 void *vaddr[2];
863
864 if (args != NULL) {
865 isBlackKey = args[0];
866 pdECDSEL = args[1];
867 }
868 vaddr[0] = NULL;
869 vaddr[1] = NULL;
870
871 desc->desc[desc->idx++] = pdECDSEL;
872 if (isBlackKey == 1) {
873 /* create secure partition for private key out */
874 part = caamFindUnusedPartition();
875 if (part < 0) {
876 WOLFSSL_MSG("error finding an unused partition for new key");
877 return -1;
878 }
879
880 /* create and claim the partition */
881 err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK |
882 CAAM_SM_CSP | CAAM_SM_ALL_RW);
883 if (err != Success) {
884 WOLFSSL_MSG("error creating partition for secure ecc key");
885 return -1;
886 }
887
888 /* map secure partition to virtual address */
889 phys = (CAAM_PAGE + (part << 12));
890 buf[0].TheAddress = phys;
891 desc->desc[desc->idx++] = phys;
892
893 /* public x,y out */
894 buf[1].TheAddress = buf[0].TheAddress + BLACK_KEY_MAC_SZ + buf[0].Length;
895 desc->desc[desc->idx++] = phys + BLACK_KEY_MAC_SZ + buf[0].Length;
896 }
897 else {
898 vaddr[0] = CAAM_ADR_MAP(0, buf[0].Length, 0);
899 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[0], buf[0].Length);
900
901 vaddr[1] = CAAM_ADR_MAP(0, buf[1].Length, 0);
902 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], buf[1].Length);
903 }
904
905 /* add protinfo to operation command */
906 desc->startIdx = desc->idx;
907
908 /* add operation command OPTYPE PROTOID */
909 desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type;
910 if (isBlackKey == 1) {
911 desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM;
912 }
913 desc->desc[desc->idx++] |= CAAM_PKHA_ECC;
914
915 do {
916 err = caamDoJob(desc);
917 } while (err == CAAM_WAITING);
918
919 if (isBlackKey == 1) {
920 /* store partition number holding black keys */
921 if (err != Success)
922 caamFreePart(part);
923 else
924 args[2] = part;
925 }
926 else {
927 /* copy non black keys out to buffers */
928 CAAM_ADR_UNMAP(vaddr[0], buf[0].TheAddress, buf[0].Length, 1);
929 CAAM_ADR_UNMAP(vaddr[1], buf[1].TheAddress, buf[1].Length, 1);
930 }
931
932 return err;
933 }
934
935
936
937 /* ECDSA verify signature
938 *
939 * return Success on success. All other return values are considered a fail
940 * case.
941 */
caamECDSAVerify(DESCSTRUCT * desc,CAAM_BUFFER * buf,int sz,unsigned int args[4])942 int caamECDSAVerify(DESCSTRUCT* desc, CAAM_BUFFER* buf, int sz,
943 unsigned int args[4])
944 {
945 unsigned int isBlackKey = 0;
946 unsigned int pdECDSEL = 0;
947 unsigned int msgSz = 0;
948 unsigned int vidx = 0;
949 unsigned int L;
950 int i = 0;
951 Error err;
952 void *vaddr[MAX_ECDSA_VERIFY_ADDR];
953
954 if (args != NULL) {
955 isBlackKey = args[0];
956 pdECDSEL = args[1];
957 msgSz = args[2];
958 }
959
960 if (sz > MAX_ECDSA_VERIFY_ADDR) {
961 return -1;
962 }
963
964 if (pdECDSEL == 0) {
965 return -1;
966 }
967 else {
968 L = args[3]; /* keysize */
969 desc->desc[desc->idx++] = pdECDSEL;
970 }
971
972 /* public key */
973 if (!isBlackKey) {
974 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
975 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
976 desc->buf[i].dataSz);
977 vidx = vidx + 1;
978 }
979 else {
980 desc->desc[desc->idx++] = desc->buf[i].data;
981 }
982 i = i + 1;
983
984 /* message */
985 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
986 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
987 desc->buf[i].dataSz);
988 vidx = vidx + 1; i = i + 1;
989
990 /* r */
991 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
992 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
993 desc->buf[i].dataSz);
994 vidx = vidx + 1; i = i + 1;
995
996 /* s */
997 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
998 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
999 desc->buf[i].dataSz);
1000 vidx = vidx + 1; i = i + 1;
1001
1002 /* tmp buffer */
1003 vaddr[vidx] = CAAM_ADR_MAP(0, 2*L, 0);
1004 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], 2*L);
1005 if (msgSz > 0) {
1006 desc->desc[desc->idx++] = msgSz;
1007 }
1008
1009 /* add protinfo to operation command */
1010 desc->startIdx = desc->idx;
1011
1012 /* add operation command OPTYPE PROTOID */
1013 desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type;
1014 if (msgSz > 0) {
1015 desc->desc[desc->idx] |= CAAM_ECDSA_MESREP_HASHED;
1016 }
1017 desc->desc[desc->idx++] |= CAAM_PKHA_ECC;
1018
1019 do {
1020 err = caamDoJob(desc);
1021 } while (err == CAAM_WAITING);
1022
1023 vidx = 0; i = 0;
1024 if (!isBlackKey) {
1025 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0);
1026 }
1027 i = i + 1;
1028
1029 /* msg , r, s, tmp */
1030 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0);
1031 i = i + 1;
1032 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0);
1033 i = i + 1;
1034 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0);
1035 i = i + 1;
1036 CAAM_ADR_UNMAP(vaddr[vidx++], 0, 2*L, 0);
1037
1038 return err;
1039 }
1040
1041
1042 /* ECDSA generate signature
1043 *
1044 * return Success on success. All other return values are considered a fail
1045 * case.
1046 */
caamECDSASign(DESCSTRUCT * desc,int sz,unsigned int args[4])1047 int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4])
1048 {
1049 Error err;
1050 unsigned int isBlackKey = 0;
1051 unsigned int pdECDSEL = 0;
1052 unsigned int msgSz = 0;
1053 unsigned int vidx = 0;
1054 int i = 0;
1055 void *vaddr[MAX_ECDSA_SIGN_ADDR];
1056
1057 if ((args == NULL) || (sz > MAX_ECDSA_SIGN_ADDR)) {
1058 return -1;
1059 }
1060
1061 isBlackKey = args[0];
1062 pdECDSEL = args[1];
1063 msgSz = args[2];
1064 if (pdECDSEL == 0) {
1065 return -1;
1066 }
1067
1068 /* using parameters already in hardware */
1069 desc->desc[desc->idx++] = pdECDSEL;
1070
1071 /* private key */
1072 if (isBlackKey != 1) {
1073 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1074 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1075 desc->buf[i].dataSz);
1076 #if 0
1077 {
1078 unsigned int z; unsigned char* pt;
1079 printf("private :");
1080 pt = (unsigned char*)desc->buf[i].data;
1081 for (z = 0; z < desc->buf[i].dataSz; z++)
1082 printf("%02X", pt[z]);
1083 printf("\n");
1084 }
1085 #endif
1086 vidx++;
1087 }
1088 else {
1089 desc->desc[desc->idx++] = desc->buf[i].data;
1090 }
1091 i++;
1092
1093 for (; i < sz; i = i + 1) {
1094 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1095 #if 0
1096 {
1097 unsigned int z;
1098 unsigned char *pt = (unsigned char*)vaddr[vidx];
1099 printf("input index %d/%d\n", i, sz);
1100 for (z = 0; z < desc->buf[i].dataSz; z++)
1101 printf("%02X", pt[z]);
1102 printf("\n");
1103 }
1104 #endif
1105 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1106 desc->buf[i].dataSz);
1107 vidx++;
1108 }
1109
1110 desc->desc[desc->idx++] = msgSz;
1111
1112 /* add protinfo to operation command */
1113 desc->startIdx = desc->idx;
1114
1115 /* add operation command OPTYPE PROTOID */
1116 desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type;
1117 if (isBlackKey) { /* set flag to use AES-CCM with black key */
1118 desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM;
1119 }
1120
1121 /* add protinfo to operation command */
1122 desc->desc[desc->idx++] |= CAAM_ECDSA_MESREP_HASHED | CAAM_PKHA_ECC;
1123
1124 do {
1125 err = caamDoJob(desc);
1126 } while (err == CAAM_WAITING);
1127
1128 vidx = 0; i = 0;
1129 if (!isBlackKey) {
1130 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0);
1131 }
1132 i++;
1133
1134 /* msg */
1135 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++;
1136
1137 /* copy out the r and s values */
1138 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++;
1139 CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++;
1140
1141 return err;
1142 }
1143
1144
1145 /* ECDH generate shared secret
1146 *
1147 * return Success on success. All other return values are considered a fail
1148 * case.
1149 */
caamECDSA_ECDH(DESCSTRUCT * desc,int sz,unsigned int args[4])1150 int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4])
1151 {
1152 Error err;
1153 unsigned int isBlackKey = 0;
1154 unsigned int peerBlackKey = 0;
1155 unsigned int pdECDSEL = 0;
1156 unsigned int vidx = 0;
1157 int i = 0;
1158 void* vaddr[sz];
1159
1160 if (args != NULL) {
1161 isBlackKey = args[0];
1162 peerBlackKey = args[1];
1163 pdECDSEL = args[2];
1164 }
1165
1166 if (pdECDSEL == 0) {
1167 return -1;
1168 }
1169 else {
1170 /* using parameters already in hardware */
1171 desc->desc[desc->idx++] = pdECDSEL;
1172 }
1173
1174 /* public key */
1175 if (!peerBlackKey) {
1176 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1177 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1178 desc->buf[i].dataSz);
1179 #if 0
1180 {
1181 unsigned int z; byte* pt;
1182 printf("pubkey :");
1183 pt = (byte*)desc->buf[i].data;
1184 for (z = 0; z < desc->buf[i].dataSz; z++)
1185 printf("%02X", pt[z]);
1186 printf("\n");
1187 }
1188 #endif
1189 vidx++;
1190 }
1191 else {
1192 desc->desc[desc->idx++] = desc->buf[i].data;
1193 }
1194 i++;
1195
1196 /* private key */
1197 if (isBlackKey != 1) {
1198 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1199 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1200 desc->buf[i].dataSz);
1201 #if 0
1202 {
1203 unsigned int z; byte* pt;
1204 printf("private :");
1205 pt = (byte*)desc->buf[i].data;
1206 for (z = 0; z < desc->buf[i].dataSz; z++)
1207 printf("%02X", pt[z]);
1208 printf("\n");
1209 }
1210 #endif
1211 vidx++;
1212 }
1213 else {
1214 desc->desc[desc->idx++] = desc->buf[i].data;
1215 }
1216 i++;
1217
1218 /* shared output */
1219 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1220 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1221 desc->buf[i].dataSz);
1222 i++; vidx++;
1223
1224 /* add protinfo to operation command */
1225 desc->startIdx = desc->idx;
1226
1227 /* add operation command OPTYPE PROTOID */
1228 desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type;
1229 if (isBlackKey == 1) {
1230 desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM;
1231 }
1232
1233 /* add protinfo to operation command */
1234 desc->desc[desc->idx++] |= CAAM_PKHA_ECC;
1235
1236 do {
1237 err = caamDoJob(desc);
1238 } while (err == CAAM_WAITING);
1239
1240 vidx = 0; i = 0;
1241 if (pdECDSEL == 0) {
1242 /* unmap prime key */
1243 CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0);
1244 vidx++; i++;
1245 }
1246
1247 if (peerBlackKey != 1) {
1248 CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0);
1249 vidx++;
1250 }
1251 i++;
1252
1253 if (isBlackKey != 1) {
1254 CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0);
1255 vidx++;
1256 }
1257 i++;
1258 CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 1);
1259 vidx++; i++;
1260
1261 if (pdECDSEL == 0) {
1262 /* unmap A , B*/
1263 CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0);
1264 vidx++; i++;
1265 }
1266 return err;
1267 }
1268
1269
1270 /******************************************************************************
1271 IODevice Start, Transfer and Finish Buffer
1272 ****************************************************************************/
1273 /* If Entropy is not ready then return CAAM_WAITING */
caamTRNG(unsigned char * out,int outSz)1274 int caamTRNG(unsigned char *out, int outSz)
1275 {
1276 int sz = 0;
1277
1278 CAAM_ADDRESS reg; /* RTENT reg to read */
1279 unsigned char* local;
1280 int ofst = sizeof(unsigned int);
1281
1282 /* Check ENT_VAL bit to make sure entropy is ready */
1283 if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != CAAM_ENTVAL) {
1284 return CAAM_WAITING;
1285 }
1286
1287 /* check state of TRNG */
1288 if ((CAAM_READ(CAAM_RTSTATUS) & 0x0000FFFF) > 0) {
1289 return Failure;
1290 }
1291
1292 /* read entropy from RTENT registers */
1293 reg = CAAM_RTENT0;
1294 sz = outSz;
1295 local = out;
1296
1297 while (sz > 3 && reg <= CAAM_RTENT_MAX) {
1298 unsigned int data = CAAM_READ(reg);
1299 *((unsigned int*)local) = data;
1300 reg += ofst;
1301 local += ofst;
1302 sz -= ofst;
1303 }
1304
1305 if (reg > CAAM_RTENT_MAX && sz > 0) {
1306 return -1;
1307 }
1308
1309 /* handle non unsigned int size amount left over */
1310 if (sz > 0) {
1311 unsigned int tmp = CAAM_READ(reg);
1312 memcpy(local, (unsigned char*)&tmp, sz);
1313 }
1314
1315 /* read the max RTENT to trigger new entropy generation */
1316 if (reg != CAAM_RTENT_MAX) {
1317 CAAM_READ(CAAM_RTENT_MAX);
1318 }
1319
1320 return Success;
1321 }
1322
1323
1324 /* cover a plain text key and make it a black key */
caamKeyCover(DESCSTRUCT * desc,int sz,unsigned int args[4])1325 int caamKeyCover(DESCSTRUCT* desc, int sz, unsigned int args[4])
1326 {
1327 Error err;
1328 unsigned int vidx = 0;
1329 int i = 0;
1330 void* vaddr[2];
1331
1332 (void)args;
1333
1334 if (sz > 2) {
1335 return -1;
1336 }
1337
1338 /* add input key */
1339 desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1) +
1340 desc->buf[i].dataSz;
1341 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1);
1342 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1343 desc->buf[i].dataSz);
1344 vidx++;
1345 i++;
1346
1347 /* add output */
1348 desc->desc[desc->idx++] = (CAAM_FIFO_S | CAAM_CLASS1 | desc->state) +
1349 desc->buf[i].dataSz;
1350 vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz +
1351 BLACK_KEY_MAC_SZ, 0);
1352 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx],
1353 desc->buf[i].dataSz + BLACK_KEY_MAC_SZ);
1354
1355 #if 0
1356 /* sanity check can we load it? used for debugging and testing */
1357 desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | 0x500000) +
1358 desc->buf[i].dataSz;
1359 desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], desc->buf[1].dataSz);
1360 #endif
1361
1362 do {
1363 err = caamDoJob(desc);
1364 } while (err == CAAM_WAITING);
1365
1366 CAAM_ADR_UNMAP(vaddr[0], desc->buf[0].data, desc->buf[0].dataSz, 0);
1367 CAAM_ADR_UNMAP(vaddr[1], desc->buf[1].data, desc->buf[1].dataSz +
1368 BLACK_KEY_MAC_SZ, 1);
1369 return err;
1370 }
1371
1372
1373 /******************************************************************************
1374 Init
1375 ****************************************************************************/
1376
1377 /* initialize a DESCSTRUCT for an operation */
caamDescInit(DESCSTRUCT * desc,int type,unsigned int args[4],CAAM_BUFFER * buf,int sz)1378 void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4],
1379 CAAM_BUFFER* buf, int sz)
1380 {
1381 int i;
1382
1383 desc->type = type;
1384 desc->idx = 0;
1385 desc->output = 0;
1386 desc->ctxOut = 0;
1387 desc->outputIdx = 0;
1388 desc->alignIdx = 0;
1389 desc->lastFifo = 0;
1390 if (args == NULL) {
1391 desc->state = 0;
1392 desc->ctxSz = 0;
1393 desc->inputSz = 0;
1394 }
1395 else {
1396 desc->state = args[0];
1397 desc->ctxSz = args[1];
1398 desc->inputSz = args[2];
1399 }
1400 desc->aadSz = 0;
1401 desc->DescriptorCount = sz;
1402 desc->startIdx = 0;
1403 desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/
1404
1405 for (i = 0; i < sz; i = i + 1) {
1406 desc->buf[i].data = buf[i].TheAddress;
1407 desc->buf[i].dataSz = buf[i].Length;
1408 }
1409 }
1410
1411
InitCAAM(void)1412 int InitCAAM(void)
1413 {
1414 Error ret;
1415
1416 /* map to memory addresses needed for accessing CAAM */
1417 ret = CAAM_SET_BASEADDR();
1418 if (ret != 0) {
1419 return ret;
1420 }
1421
1422 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
1423 printf("CHANUM_MS = 0x%08X\n", CAAM_READ(0x0FF0));
1424 printf("DECO0MIDR_MS = 0x%08X\n", CAAM_READ(0x00A0));
1425 printf("SCFGR = 0x%08X\n", CAAM_READ(0x000C));
1426 print_jdkek();
1427 printSecureMemoryInfo();
1428 printf("JR0MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0010),
1429 CAAM_READ(0x0014));
1430 printf("JR1MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0018),
1431 CAAM_READ(0x001C));
1432 printf("JR2MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0020),
1433 CAAM_READ(0x0024));
1434 #endif
1435
1436 ret = Failure;
1437 for (caam.ring.page = 1; caam.ring.page < 7;
1438 caam.ring.page = caam.ring.page + 1) {
1439 ret = caamCreatePartition(caam.ring.page, caam.ring.page,
1440 CAAM_SM_CSP | CAAM_SM_ALL_RW);
1441 if (ret == Success)
1442 break;
1443 }
1444 if (ret != Success) {
1445 WOLFSSL_MSG("Failed to find a partition on startup");
1446 INTERRUPT_Panic();
1447 return -1;
1448 }
1449
1450 caam.ring.JobIn = CAAM_PAGE + (caam.ring.page << 12U);
1451 caam.ring.JobOut = caam.ring.JobIn + (CAAM_JOBRING_SIZE *
1452 sizeof(unsigned int));
1453 caam.ring.Desc = caam.ring.JobOut + (2 * CAAM_JOBRING_SIZE *
1454 sizeof(unsigned int));
1455
1456 CAAM_INIT_MUTEX(&caam.ring.jr_lock);
1457
1458 caam.ring.VirtualIn = mmap_device_memory(NULL,
1459 CAAM_JOBRING_SIZE * sizeof(unsigned int),
1460 PROT_READ | PROT_WRITE | PROT_NOCACHE,
1461 MAP_SHARED | MAP_PHYS, caam.ring.JobIn);
1462 if (caam.ring.VirtualIn == MAP_FAILED) {
1463 WOLFSSL_MSG("Error mapping virtual in");
1464 INTERRUPT_Panic();
1465 return -1;
1466 }
1467 memset(caam.ring.VirtualIn, 0, CAAM_JOBRING_SIZE * sizeof(unsigned int));
1468 caam.ring.VirtualOut = mmap_device_memory(NULL,
1469 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int),
1470 PROT_READ | PROT_WRITE | PROT_NOCACHE,
1471 MAP_SHARED | MAP_PHYS, caam.ring.JobOut);
1472 if (caam.ring.VirtualOut == MAP_FAILED) {
1473 WOLFSSL_MSG("Error mapping virtual out");
1474 INTERRUPT_Panic();
1475 return -1;
1476 }
1477 memset(caam.ring.VirtualOut, 0, 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int));
1478 caam.ring.VirtualDesc = mmap_device_memory(NULL,
1479 CAAM_DESC_MAX * CAAM_JOBRING_SIZE,
1480 PROT_READ | PROT_WRITE | PROT_NOCACHE,
1481 MAP_SHARED | MAP_PHYS, caam.ring.Desc);
1482 if (caam.ring.VirtualDesc == MAP_FAILED) {
1483 WOLFSSL_MSG("Error mapping virtual desc");
1484 INTERRUPT_Panic();
1485 return -1;
1486 }
1487 memset(caam.ring.VirtualDesc, 0, CAAM_DESC_MAX * CAAM_JOBRING_SIZE);
1488
1489 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
1490 printf("extra wolfssl debug - Setting JOB IN 0x%08X\n", caam.ring.JobIn);
1491 printf("extra wolfssl debug - Setting JOB OUT 0x%08X\n", caam.ring.JobOut);
1492 printf("extra wolfssl debug - Setting DESC 0x%08X\n", caam.ring.Desc);
1493 #endif
1494 CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn);
1495 CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut);
1496
1497 /* Initialize job ring sizes */
1498 CAAM_WRITE(CAAM_IRSR0, CAAM_JOBRING_SIZE);
1499 CAAM_WRITE(CAAM_ORSR0, CAAM_JOBRING_SIZE);
1500
1501 /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */
1502 CAAM_WRITE(0x0004, CAAM_READ(0x0004) | 0x40000000);
1503
1504 /* start up RNG if not already started */
1505 if (caamInitRng(&caam) != 0) {
1506 WOLFSSL_MSG("Error initializing RNG");
1507 INTERRUPT_Panic();
1508 return -1;
1509 }
1510
1511 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
1512 print_jdkek();
1513 printf("FADR = 0x%08X\n", CAAM_READ(0x0FCC));
1514 printf("RTMCTL = 0x%08X\n", CAAM_READ(0x0600));
1515 #endif
1516 WOLFSSL_MSG("Successfully initilazed CAAM driver");
1517 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
1518 fflush(stdout);
1519 #endif
1520 return 0;
1521 }
1522
1523
CleanupCAAM()1524 int CleanupCAAM()
1525 {
1526 CAAM_FREE_MUTEX(&caam.ring.jr_lock);
1527 CAAM_UNSET_BASEADDR();
1528 caamFreeAllPart();
1529 return 0;
1530 }
1531
1532 #endif /* __INTEGRITY || INTEGRITY || __QNX__ || __QNXNTO__ */
1533