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