1 /* caam_qnx.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 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25 
26 #include <wolfssl/wolfcrypt/settings.h>
27 
28 #if defined(__QNX__) || defined(__QNXNTO__)
29 
30 #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
31 #include <wolfssl/version.h>
32 
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <pthread.h>
39 #include <sys/iofunc.h>
40 #include <sys/dispatch.h>
41 #include <sys/neutrino.h>
42 #include <sys/resmgr.h>
43 #include <devctl.h>
44 
45 /* virtual address for accessing CAAM addresses */
46 uintptr_t virtual_base = 0;
47 
48 /* keep track of which ID memory belongs to so it can be free'd up */
49 #define MAX_PART 7
50 pthread_mutex_t sm_mutex;
51 CAAM_ADDRESS sm_ownerId[MAX_PART];
52 
53 /* variables for I/O of resource manager */
54 resmgr_connect_funcs_t connect_funcs;
55 resmgr_io_funcs_t      io_funcs;
56 dispatch_t             *dpp;
57 resmgr_attr_t          rattr;
58 dispatch_context_t     *ctp;
59 iofunc_attr_t          ioattr;
60 
61 int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb);
62 int io_open (resmgr_context_t *ctp, io_open_t  *msg, RESMGR_HANDLE_T *handle,
63         void *extra);
64 int io_read (resmgr_context_t *ctp, io_read_t  *msg, RESMGR_OCB_T *ocb);
65 int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb);
66 int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb);
67 
68 
69 /* read the contents at offset from BASE address */
CAAM_READ(unsigned int ofst)70 unsigned int CAAM_READ(unsigned int ofst) {
71     return in32(virtual_base + ofst);
72 }
73 
74 
75 /* takes in offset from BASE address */
CAAM_WRITE(unsigned int ofst,unsigned int in)76 void CAAM_WRITE(unsigned int ofst, unsigned int in)
77 {
78     out32(virtual_base + ofst, in);
79 }
80 
81 
82 /* Sets the base address to use for read/write
83  * returns 0 on success
84  */
CAAM_SET_BASEADDR()85 int CAAM_SET_BASEADDR()
86 {
87     /* address range for CAAM is CAAM_BASE plus 0x10000 */
88     virtual_base = mmap_device_io(0x00010000, CAAM_BASE);
89     if (virtual_base == (uintptr_t)MAP_FAILED) {
90         WOLFSSL_MSG("Unable to map virtual memory");
91         return -1;
92     }
93     return 0;
94 }
95 
96 
97 /* cleans up having set the base address */
CAAM_UNSET_BASEADDR()98 void CAAM_UNSET_BASEADDR()
99 {
100     munmap_device_io(virtual_base, 0x00010000);
101 }
102 
103 /* convert a virtual address to a physical address
104  * returns the physical address on success
105  */
CAAM_ADR_TO_PHYSICAL(void * in,int inSz)106 CAAM_ADDRESS CAAM_ADR_TO_PHYSICAL(void* in, int inSz)
107 {
108     off64_t ofst = 0;
109     int ret, count = 0;;
110 
111     if (in == NULL)
112         return 0;
113 
114     if (inSz == 0)
115         inSz = 1;
116 
117     do {
118         ret = mem_offset64(in, NOFD, inSz, &ofst, NULL);
119         if (ret != 0) {
120             WOLFSSL_MSG("posix offset failed");
121         #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
122             perror("posix offset failed : ");
123         #endif
124         }
125         msync(in, inSz, MS_INVALIDATE);
126         count++;
127     } while (ret != 0 && ret == -1 && count < 5);
128 
129     return (CAAM_ADDRESS)ofst;
130 }
131 
132 
133 /* convert a physical address to virtual address
134  * returns the virtual address on success
135  */
CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in,int len)136 CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int len)
137 {
138     void* ret;
139     ret = mmap_device_memory(NULL, len, PROT_READ | PROT_WRITE | PROT_NOCACHE,
140             0, in);
141     return (CAAM_ADDRESS)ret;
142 }
143 
144 
145 /* map a virtual address to a created coherent physical address
146  * returns the mapped address on success
147  */
CAAM_ADR_MAP(unsigned int in,int inSz,unsigned char copy)148 void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy)
149 {
150     int  sz;
151     void *vaddr;
152 
153     sz = inSz;
154     if (inSz == 0) {
155         sz = 1;
156     }
157 
158     vaddr = mmap(NULL, sz, PROT_READ | PROT_WRITE | PROT_NOCACHE,
159                     MAP_PHYS | MAP_SHARED | MAP_ANON, NOFD, 0);
160     if (vaddr == MAP_FAILED) {
161         WOLFSSL_MSG("Failed to map memory");
162     #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
163         perror("Failed to map memory : ");
164     #endif
165     }
166     else {
167         if (copy && in != 0 && inSz > 0) {
168             memcpy((unsigned char*)vaddr, (unsigned char*)in, inSz);
169         }
170 
171         if (msync(vaddr, sz, MS_SYNC) != 0) {
172             WOLFSSL_MSG("Failed to sync memory after copy");
173         }
174     }
175     return vaddr;
176 }
177 
178 
179 /* un map address, should be called when done with a mapped address */
CAAM_ADR_UNMAP(void * vaddr,unsigned int out,int outSz,unsigned char copy)180 void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz,
181         unsigned char copy)
182 {
183     int sz;
184 
185     sz = outSz;
186     if (outSz == 0)
187         sz = 1;
188 
189     if (msync(vaddr, sz, MS_SYNC) != 0) {
190     #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
191         perror("Failed to sync output");
192     #endif
193         /* even though the address was not synced up still try to copy and
194            unmap it */
195     }
196 
197     if (copy && out != 0 && outSz > 0) {
198         memcpy((unsigned char*)out, (unsigned char*)vaddr, outSz);
199     }
200     munmap(vaddr, sz);
201 }
202 
203 
204 /* synchronize virtual buffer with physical
205  * return 0 on success */
CAAM_ADR_SYNC(void * vaddr,int sz)206 int CAAM_ADR_SYNC(void* vaddr, int sz)
207 {
208     if (msync(vaddr, sz, MS_SYNC) != 0) {
209     #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
210         perror("address sync failed");
211     #endif
212         return -1;
213     }
214     return 0;
215 }
216 
217 
218 /* macros for QNX devctl commands */
219 #define WC_TRNG_CMD __DIOTF(_DCMD_ALL, CAAM_ENTROPY, iov_t)
220 #define WC_CAAM_GET_PART __DIOTF(_DCMD_ALL, CAAM_GET_PART, iov_t)
221 #define WC_CAAM_FREE_PART __DIOT(_DCMD_ALL, CAAM_FREE_PART, iov_t)
222 #define WC_CAAM_FIND_PART __DIOTF(_DCMD_ALL, CAAM_FIND_PART, iov_t)
223 #define WC_CAAM_READ_PART __DIOTF(_DCMD_ALL, CAAM_READ_PART, iov_t)
224 #define WC_CAAM_WRITE_PART __DIOT(_DCMD_ALL, CAAM_WRITE_PART, iov_t)
225 
226 #define WC_CAAM_ECDSA_KEYPAIR __DIOTF(_DCMD_ALL, CAAM_ECDSA_KEYPAIR, iov_t)
227 #define WC_CAAM_ECDSA_VERIFY __DIOT(_DCMD_ALL, CAAM_ECDSA_VERIFY, iov_t)
228 #define WC_CAAM_ECDSA_SIGN __DIOTF(_DCMD_ALL, CAAM_ECDSA_SIGN, iov_t)
229 #define WC_CAAM_ECDSA_ECDH __DIOTF(_DCMD_ALL, CAAM_ECDSA_ECDH, iov_t)
230 
231 #define WC_CAAM_BLOB_ENCAP __DIOTF(_DCMD_ALL, CAAM_BLOB_ENCAP, iov_t)
232 #define WC_CAAM_BLOB_DECAP __DIOTF(_DCMD_ALL, CAAM_BLOB_DECAP, iov_t)
233 
234 #define WC_CAAM_CMAC __DIOTF(_DCMD_ALL, CAAM_CMAC, iov_t)
235 
236 #define WC_CAAM_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t)
237 
238 
239 /* partAddr is virtual address
240  * partSz   size expected to access
241  *
242  * returns 0 on ok
243  */
sanityCheckPartitionAddress(CAAM_ADDRESS partAddr,int partSz)244 static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz)
245 {
246     if (partAddr < CAAM_PAGE || partAddr > CAAM_PAGE * MAX_PART ||
247             partSz > 4096) {
248         WOLFSSL_MSG("error in physical address range");
249         return -1;
250     }
251     return 0;
252 }
253 
254 
255 /* return 0 on success */
getArgs(unsigned int args[4],resmgr_context_t * ctp,io_devctl_t * msg,unsigned int * idx,unsigned int maxIdx)256 static int getArgs(unsigned int args[4], resmgr_context_t *ctp, io_devctl_t *msg,
257         unsigned int *idx, unsigned int maxIdx)
258 {
259     int expectedSz;
260     iov_t in_iov;
261 
262     expectedSz = sizeof(unsigned int) * 4;
263     if (*idx + expectedSz > maxIdx) {
264         WOLFSSL_MSG("not enough for arguments");
265         return -1;
266     }
267 
268     SETIOV(&in_iov, args, expectedSz);
269     if (resmgr_msgreadv(ctp, &in_iov, 1, *idx) != expectedSz) {
270         WOLFSSL_MSG("unexpected msg size read");
271         return -1;
272     }
273     *idx += expectedSz;
274     return 0;
275 }
276 
277 
278 /* helper function to setup and run CMAC operation
279  * returns EOK on success
280  */
doCMAC(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)281 static int doCMAC(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
282         unsigned int idx)
283 {
284     DESCSTRUCT  desc;
285     CAAM_BUFFER tmp[3];
286     iov_t in_iovs[3], out_iov;
287 
288     int msgSz = 0, ret, numBuf, keySz;
289     unsigned char ctx[32];    /* running CMAC context is a constant 32 bytes */
290     unsigned char keybuf[32 + BLACK_KEY_MAC_SZ];/*max AES key size is 32 + MAC*/
291     unsigned char *buf = NULL;
292 
293     numBuf = 2; /* start with 2 (key + ctx) for case with no msg input */
294     keySz  = args[1];
295     if (args[2] == 1) { /* is it a black key? */
296         keySz = keySz + BLACK_KEY_MAC_SZ;
297     }
298     SETIOV(&in_iovs[0], keybuf, keySz);
299     SETIOV(&in_iovs[1], ctx, sizeof(ctx));
300     msgSz = args[3];
301     if (msgSz < 0) {
302         WOLFSSL_MSG("CMAC msg size was a negative value");
303         return EBADMSG;
304     }
305 
306     if (msgSz > 0) {
307         buf = (unsigned char*)CAAM_ADR_MAP(0, msgSz, 0);
308         if (buf == NULL) {
309             return ECANCELED;
310         }
311         SETIOV(&in_iovs[2], buf, msgSz);
312         numBuf = numBuf + 1; /* increase buffer size by one when adding msg */
313     }
314 
315     ret = resmgr_msgreadv(ctp, in_iovs, numBuf, idx);
316     if (ret < (msgSz + keySz + sizeof(ctx))) {
317         /* sanity check that enough data was sent */
318         if (buf != NULL)
319             CAAM_ADR_UNMAP(buf, 0, msgSz, 0);
320         return EOVERFLOW;
321     }
322 
323     tmp[0].TheAddress = (CAAM_ADDRESS)keybuf;
324     tmp[0].Length = args[1];
325 
326     tmp[1].TheAddress = (CAAM_ADDRESS)ctx;
327     tmp[1].Length = sizeof(ctx);
328 
329     if (msgSz > 0) {
330         tmp[2].TheAddress = (CAAM_ADDRESS)buf;
331         tmp[2].Length     = msgSz;
332     }
333     caamDescInit(&desc, CAAM_CMAC, args, tmp, numBuf);
334     ret = caamAesCmac(&desc, numBuf, args);
335     if (msgSz > 0) {
336         if (buf != NULL)
337             CAAM_ADR_UNMAP(buf, 0, msgSz, 0);
338     }
339 
340     if (ret != Success) {
341         return EBADMSG;
342     }
343     SETIOV(&out_iov, ctx, sizeof(ctx));
344 
345     /* extra sanity check that out buffer is large enough */
346     if (sizeof(ctx) > msg->o.nbytes) {
347         return EOVERFLOW;
348     }
349     ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
350     if (ret < 0) {
351         return ECANCELED;
352     }
353 
354     return EOK;
355 }
356 
357 
358 /* helper function to setup and run TRNG operation
359  * returns EOK on success
360  */
doTRNG(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)361 static int doTRNG(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
362         unsigned int idx)
363 {
364     int length, ret;
365     unsigned char *buf;
366     iov_t out_iov;
367 
368     length = args[0];
369 
370     /* sanity check that length out is not over the edge */
371     if (length > msg->o.nbytes) {
372         WOLFSSL_MSG("Length too large for TRNG out size available");
373         return EOVERFLOW;
374     }
375 
376     if (length > 0) {
377         buf = (unsigned char*)CAAM_ADR_MAP(0, length, 0);
378         if (buf == NULL) {
379             return ECANCELED;
380         }
381 
382         ret = caamTRNG(buf, length);
383         if (ret == CAAM_WAITING) {
384             /* waiting for more entropy */
385             CAAM_ADR_UNMAP(buf, 0, length, 0);
386             return EAGAIN;
387         }
388 
389         SETIOV(&out_iov, buf, length);
390         ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
391         CAAM_ADR_UNMAP(buf, 0, length, 0);
392         if (ret < 0) {
393             return ECANCELED;
394         }
395     }
396     return EOK;
397 }
398 
399 
400 /* helper function to setup and run BLOB operation
401  * returns EOK on success
402  */
doBLOB(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)403 static int doBLOB(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
404         unsigned int idx)
405 {
406     int WC_CAAM_BLOB_SZ = 48; /* extra blob size from manual */
407     int dir, ret, inSz, outSz;
408     DESCSTRUCT  desc;
409     CAAM_BUFFER tmp[3];
410     iov_t in_iovs[2], out_iov;
411 
412     unsigned char *inBuf, *outBuf;
413     unsigned char keymod[BLACK_BLOB_KEYMOD_SZ];
414     /* 16 is max size for keymod (8 with red blobs and 16 with black) */
415 
416     if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
417         dir = CAAM_BLOB_ENCAP;
418     }
419     else {
420         dir = CAAM_BLOB_DECAP;
421     }
422 
423     inSz = args[2];
424     if (inSz < 0) {
425         return EBADMSG;
426     }
427 
428     if (args[0] == 1 && dir == CAAM_BLOB_ENCAP) {
429         inSz = inSz + BLACK_KEY_MAC_SZ;
430     }
431 
432     SETIOV(&in_iovs[0], keymod, args[3]);
433     if ((inSz + args[3]) > (ctp->size - idx)) {
434         return EOVERFLOW;
435     }
436 
437     inBuf = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0);
438     if (inBuf == NULL) {
439         return ECANCELED;
440     }
441     SETIOV(&in_iovs[1], inBuf, inSz);
442     ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
443     if (ret < inSz + args[3]) {
444         return EBADMSG;
445     }
446 
447     /* key mod */
448     tmp[0].TheAddress = (CAAM_ADDRESS)keymod;
449     tmp[0].Length = args[3];
450 
451     /* input */
452     tmp[1].TheAddress = (CAAM_ADDRESS)inBuf;
453     tmp[1].Length = args[2];
454 
455     /* output */
456     outSz = args[2];
457     if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
458         outSz = outSz + WC_CAAM_BLOB_SZ;
459     }
460     else {
461         outSz = outSz - WC_CAAM_BLOB_SZ;
462     }
463     if (outSz < 0) {
464         return EBADMSG;
465     }
466 
467     if (args[0] == 1 && dir == CAAM_BLOB_DECAP) {
468         outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz + BLACK_KEY_MAC_SZ, 0);
469     }
470     else {
471         outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0);
472     }
473     if (outBuf == NULL) {
474         CAAM_ADR_UNMAP(inBuf, 0, inSz, 0);
475         return ECANCELED;
476     }
477     tmp[2].TheAddress = (CAAM_ADDRESS)outBuf;
478     tmp[2].Length     = outSz;
479 
480     caamDescInit(&desc, dir, args, tmp, 3);
481     ret = caamBlob(&desc);
482     CAAM_ADR_UNMAP(inBuf, 0, inSz, 0);
483 
484     /* adjust outSz for MAC tag at the end of black key */
485     if (args[0] == 1 && dir == CAAM_BLOB_DECAP) {
486         outSz = outSz + BLACK_KEY_MAC_SZ;
487     }
488 
489     if (ret != Success) {
490         CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
491         return ECANCELED;
492     }
493 
494     CAAM_ADR_SYNC(outBuf, outSz);
495     SETIOV(&out_iov, outBuf, outSz);
496     if (outSz > msg->o.nbytes) {
497         CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
498         return EOVERFLOW;
499     }
500     ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
501     CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
502     if (ret < 0) {
503         return ECANCELED;
504     }
505     return EOK;
506 }
507 
508 
509 /* helper function to setup and make ECC key
510  * returns EOK on success
511  */
doECDSA_KEYPAIR(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx,iofunc_ocb_t * ocb)512 static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
513         unsigned int idx, iofunc_ocb_t *ocb)
514 {
515     int ret;
516     DESCSTRUCT desc;
517     CAAM_BUFFER tmp[2];
518     iov_t in_iovs[2], out_iovs[3];
519 
520     SETIOV(&in_iovs[0], &tmp[0], sizeof(CAAM_BUFFER));
521     SETIOV(&in_iovs[1], &tmp[1], sizeof(CAAM_BUFFER));
522     ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
523 
524     caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2);
525     ret = caamECDSAMake(&desc, tmp, args);
526     if (ret != Success) {
527         return ECANCELED;
528     }
529 
530     SETIOV(&out_iovs[0], &tmp[0], sizeof(CAAM_BUFFER));
531     SETIOV(&out_iovs[1], &tmp[1], sizeof(CAAM_BUFFER));
532     SETIOV(&out_iovs[2], args, sizeof(int) * 4);
533     ret = resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o));
534     if (ret < 0) {
535         return ECANCELED;
536     }
537 
538     /* claim ownership of a secure memory location */
539     pthread_mutex_lock(&sm_mutex);
540     sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb;
541     pthread_mutex_unlock(&sm_mutex);
542 
543     return EOK;
544 }
545 
546 
547 /* helper function to setup and do ECC verify
548  * returns EOK on success
549  */
doECDSA_VERIFY(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)550 static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg,
551         unsigned int args[4], unsigned int idx)
552 {
553     DESCSTRUCT  desc;
554     CAAM_BUFFER tmp[5];
555     iov_t in_iovs[4];
556     int ret, pubSz;
557 
558     unsigned char *hash, *pubkey = NULL, *r, *s;
559     CAAM_ADDRESS securePub;
560 
561     if (args[0] == 1) {
562         pubSz = sizeof(CAAM_ADDRESS);
563 
564         SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
565     }
566     else {
567         pubSz  = args[3]*2;
568         pubkey = (unsigned char*)CAAM_ADR_MAP(0, pubSz, 0);
569         if (pubkey == NULL) {
570             return ECANCELED;
571         }
572 
573         SETIOV(&in_iovs[0], pubkey, args[3]*2);
574     }
575 
576     hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0);
577     if (hash == NULL) {
578         if (pubkey != NULL)
579             CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
580         return ECANCELED;
581     }
582     SETIOV(&in_iovs[1], hash, args[2]);
583 
584     r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
585     if (r == NULL) {
586         if (pubkey != NULL)
587             CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
588         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
589         return ECANCELED;
590     }
591     SETIOV(&in_iovs[2], r, args[3]);
592 
593     s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
594     if (s == NULL) {
595         if (pubkey != NULL)
596             CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
597         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
598         CAAM_ADR_UNMAP(r, 0, args[3], 0);
599         return ECANCELED;
600     }
601     SETIOV(&in_iovs[3], s, args[3]);
602 
603     ret = resmgr_msgreadv(ctp, in_iovs, 4, idx);
604     if (((args[3] * 2) + args[2] + pubSz) > ret) {
605         if (pubkey != NULL)
606             CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
607         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
608         CAAM_ADR_UNMAP(r, 0, args[3], 0);
609         CAAM_ADR_UNMAP(s, 0, args[3], 0);
610         return EOVERFLOW;
611     }
612 
613     /* setup CAAM buffers to pass to driver */
614     if (args[0] == 1) {
615         tmp[0].TheAddress = securePub;
616     }
617     else {
618         tmp[0].TheAddress = (CAAM_ADDRESS)pubkey;
619     }
620     tmp[0].Length = args[3]*2;
621 
622     tmp[1].TheAddress = (CAAM_ADDRESS)hash;
623     tmp[1].Length = args[2];
624 
625     tmp[2].TheAddress = (CAAM_ADDRESS)r;
626     tmp[2].Length = args[3];
627 
628     tmp[3].TheAddress = (CAAM_ADDRESS)s;
629     tmp[3].Length = args[3];
630 
631     if (pubkey != NULL)
632         CAAM_ADR_SYNC(pubkey, pubSz);
633     CAAM_ADR_SYNC(hash, args[2]);
634     CAAM_ADR_SYNC(r, args[3]);
635     CAAM_ADR_SYNC(s, args[3]);
636     caamDescInit(&desc, CAAM_ECDSA_VERIFY, args, tmp, 4);
637     ret = caamECDSAVerify(&desc, tmp, 4, args);
638 
639     /* free all buffers before inspecting the return value */
640     CAAM_ADR_UNMAP(hash, 0, args[2], 0);
641     CAAM_ADR_UNMAP(r, 0, args[3], 0);
642     CAAM_ADR_UNMAP(s, 0, args[3], 0);
643     if (pubkey != NULL)
644         CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
645 
646     if (ret != Success) {
647         return EBADMSG;
648     }
649     return EOK;
650 }
651 
652 
653 /* helper function to setup and do ECC sign
654  * returns EOK on success
655  */
doECDSA_SIGN(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)656 static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg,
657         unsigned int args[4], unsigned int idx)
658 {
659     int ret, keySz;
660     DESCSTRUCT  desc;
661     CAAM_BUFFER tmp[4];
662 
663     unsigned char *key = NULL, *hash, *r, *s;
664     CAAM_ADDRESS blackKey;
665 
666     iov_t in_iovs[2], out_iovs[2];
667 
668     if (args[0] == 1) {
669         keySz = sizeof(CAAM_ADDRESS);
670         SETIOV(&in_iovs[0], &blackKey, sizeof(CAAM_ADDRESS));
671     }
672     else {
673         keySz = args[3];
674         key   = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0);
675         if (key == NULL) {
676             return ECANCELED;
677         }
678         SETIOV(&in_iovs[0], key, keySz);
679     }
680 
681     hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0);
682     if (hash == NULL) {
683         if (key != NULL)
684             CAAM_ADR_UNMAP(key, 0, keySz, 0);
685         return ECANCELED;
686     }
687     SETIOV(&in_iovs[1], hash, args[2]);
688     ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
689     if ((keySz + args[2]) > ret) {
690         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
691         if (key != NULL)
692             CAAM_ADR_UNMAP(key, 0, keySz, 0);
693         return EOVERFLOW;
694     }
695 
696 
697     /* setup CAAM buffers to pass to driver */
698     if (args[0] == 1) {
699         tmp[0].TheAddress = blackKey;
700     }
701     else {
702         tmp[0].TheAddress = (CAAM_ADDRESS)key;
703     }
704     tmp[0].Length = args[3];
705 
706     tmp[1].TheAddress = (CAAM_ADDRESS)hash;
707     tmp[1].Length = args[2];
708 
709     r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
710     if (r == NULL) {
711         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
712         if (key != NULL)
713             CAAM_ADR_UNMAP(key, 0, keySz, 0);
714         return ECANCELED;
715     }
716     tmp[2].TheAddress = (CAAM_ADDRESS)r;
717     tmp[2].Length = args[3];
718 
719     s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
720     if (s == NULL) {
721         CAAM_ADR_UNMAP(r, 0, args[3], 0);
722         CAAM_ADR_UNMAP(hash, 0, args[2], 0);
723         if (key != NULL)
724             CAAM_ADR_UNMAP(key, 0, keySz, 0);
725         return ECANCELED;
726     }
727     tmp[3].TheAddress = (CAAM_ADDRESS)s;
728     tmp[3].Length = args[3];
729 
730     caamDescInit(&desc, CAAM_ECDSA_SIGN, args, tmp, 4);
731     ret = caamECDSASign(&desc, 4, args);
732     CAAM_ADR_UNMAP(hash, 0, args[2], 0);
733     if (key != NULL)
734         CAAM_ADR_UNMAP(key, 0, keySz, 0);
735     if (ret != Success) {
736         CAAM_ADR_UNMAP(s, 0, args[3], 0);
737         CAAM_ADR_UNMAP(r, 0, args[3], 0);
738         return EBADMSG;
739     }
740 
741     if ((args[3] * 2) > msg->o.nbytes) {
742         CAAM_ADR_UNMAP(s, 0, args[3], 0);
743         CAAM_ADR_UNMAP(r, 0, args[3], 0);
744         return EOVERFLOW;
745     }
746 
747     CAAM_ADR_SYNC(r, args[3]);
748     CAAM_ADR_SYNC(s, args[3]);
749     SETIOV(&out_iovs[0], r, args[3]);
750     SETIOV(&out_iovs[1], s, args[3]);
751 
752     ret = resmgr_msgwritev(ctp, &out_iovs[0], 2, sizeof(msg->o));
753     CAAM_ADR_UNMAP(s, 0, args[3], 0);
754     CAAM_ADR_UNMAP(r, 0, args[3], 0);
755     if (ret < 0) {
756         return ECANCELED;
757     }
758     return EOK;
759 }
760 
761 
762 /* helper function to setup and get an ECC shared secret
763  * returns EOK on success
764  */
doECDSA_ECDH(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)765 static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg,
766         unsigned int args[4], unsigned int idx)
767 {
768     int ret;
769     DESCSTRUCT desc;
770     CAAM_BUFFER tmp[3];
771     int expectedSz = 0;
772     iov_t in_iovs[2], out_iov;
773 
774     unsigned char *pubkey = NULL, *key = NULL, *shared;
775     CAAM_ADDRESS securePub, blackKey;
776 
777     /* when using memory in secure partition just send the address */
778     if (args[1] == 1) {
779         SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
780         expectedSz += sizeof(CAAM_ADDRESS);
781     }
782     else {
783         pubkey = (unsigned char*)CAAM_ADR_MAP(0, args[3]*2, 0);
784         if (pubkey == NULL) {
785             return ECANCELED;
786         }
787 
788         SETIOV(&in_iovs[0], pubkey, args[3]*2);
789         expectedSz += args[3]*2;
790     }
791 
792     if (args[0] == 1) {
793         SETIOV(&in_iovs[1], &blackKey, sizeof(CAAM_ADDRESS));
794         expectedSz += sizeof(CAAM_ADDRESS);
795     }
796     else {
797         key = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
798         if (key == NULL) {
799             if (pubkey != NULL)
800                 CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
801             return ECANCELED;
802         }
803 
804         SETIOV(&in_iovs[1], key, args[3]);
805         expectedSz += args[3];
806     }
807 
808     ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
809     if (expectedSz > ret) {
810         if (pubkey != NULL)
811             CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
812         if (key != NULL)
813             CAAM_ADR_UNMAP(key, 0, args[3], 0);
814         return ECANCELED;
815     }
816 
817     /* setup CAAM buffers to pass to driver */
818     if (args[1] == 1) {
819         tmp[0].TheAddress = securePub;
820     }
821     else {
822         tmp[0].TheAddress = (CAAM_ADDRESS)pubkey;
823     }
824     tmp[0].Length = args[3]*2;
825 
826     if (args[0] == 1) {
827         tmp[1].TheAddress = blackKey;
828     }
829     else {
830         tmp[1].TheAddress = (CAAM_ADDRESS)key;
831     }
832     tmp[1].Length = args[3];
833 
834     shared = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
835     if (shared == NULL) {
836         if (pubkey != NULL)
837             CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
838         if (key != NULL)
839             CAAM_ADR_UNMAP(key, 0, args[3], 0);
840         return ECANCELED;
841     }
842 
843     tmp[2].TheAddress = (CAAM_ADDRESS)shared;
844     tmp[2].Length = args[3];
845     caamDescInit(&desc, CAAM_ECDSA_ECDH, args, tmp, 3);
846     ret = caamECDSA_ECDH(&desc, 3, args);
847     if (pubkey != NULL)
848         CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
849     if (key != NULL)
850         CAAM_ADR_UNMAP(key, 0, args[3], 0);
851 
852     if (ret != Success) {
853         CAAM_ADR_UNMAP(shared, 0, args[3], 0);
854         return EBADMSG;
855     }
856 
857     if (args[3] > msg->o.nbytes) {
858         CAAM_ADR_UNMAP(shared, 0, args[3], 0);
859         return EOVERFLOW;
860     }
861     CAAM_ADR_SYNC(shared, args[3]);
862     SETIOV(&out_iov, shared, args[3]);
863     resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
864     CAAM_ADR_UNMAP(shared, 0, args[3], 0);
865     return EOK;
866 }
867 
868 
869 /* helper function to setup and cover data
870  * returns EOK on success
871  */
doFIFO_S(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)872 static int doFIFO_S(resmgr_context_t *ctp, io_devctl_t *msg,
873         unsigned int args[4], unsigned int idx)
874 {
875     int ret;
876     DESCSTRUCT desc;
877     CAAM_BUFFER tmp[2];
878     iov_t in_iov, out_iov;
879     unsigned char *inBuf, *outBuf;
880 
881     inBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1], 0);
882     if (inBuf == NULL) {
883         return ECANCELED;
884     }
885 
886     SETIOV(&in_iov, inBuf, args[1]);
887     ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
888     if (ret < args[1]) {
889         return EBADMSG;
890     }
891 
892     outBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1] + BLACK_KEY_MAC_SZ, 0);
893     if (outBuf == NULL) {
894         CAAM_ADR_UNMAP(inBuf, 0, args[1], 0);
895         return ECANCELED;
896     }
897 
898     tmp[0].TheAddress = (CAAM_ADDRESS)inBuf;
899     tmp[0].Length     = args[1];
900     tmp[1].TheAddress = (CAAM_ADDRESS)outBuf;
901     tmp[1].Length     = args[1]; /* tmp1 actually needs an additional 16 bytes
902                                   * for MAC */
903 
904     caamDescInit(&desc, CAAM_FIFO_S, args, tmp, 2);
905     ret = caamKeyCover(&desc, 2, args);
906     CAAM_ADR_UNMAP(inBuf, 0, args[1], 0);
907     if (ret != Success) {
908         CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
909         return EBADMSG;
910     }
911 
912     if (args[1] + BLACK_KEY_MAC_SZ > msg->o.nbytes) {
913         CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
914         WOLFSSL_MSG("would cause output buffer overflow");
915         return EOVERFLOW;
916     }
917 
918     SETIOV(&out_iov, outBuf, args[1] + BLACK_KEY_MAC_SZ);
919     resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
920     CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
921     return EOK;
922 }
923 
924 
925 /* helper function to get partition
926  * returns EOK on success
927  */
doGET_PART(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx,iofunc_ocb_t * ocb)928 static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg,
929         unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
930 {
931     int partNumber;
932     int partSz;
933     CAAM_ADDRESS partAddr;
934     iov_t out_iov;
935 
936     partNumber = args[0];
937     partSz     = args[1];
938 
939     partAddr = caamGetPartition(partNumber, partSz, 0);
940     if (partAddr == 0) {
941         return EBADMSG;
942     }
943 
944     SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS));
945     resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
946 
947     pthread_mutex_lock(&sm_mutex);
948     sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb;
949     pthread_mutex_unlock(&sm_mutex);
950     return EOK;
951 }
952 
953 
954 /* helper function to write to a partition
955  * returns EOK on success
956  */
doWRITE_PART(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)957 static int doWRITE_PART(resmgr_context_t *ctp, io_devctl_t *msg,
958         unsigned int args[4], unsigned int idx)
959 {
960     int partSz, ret;
961     CAAM_ADDRESS partAddr;
962     CAAM_ADDRESS vaddr;
963     unsigned char *buf;
964     iov_t in_iov;
965 
966     /* get arguments */
967     partAddr = args[0];
968     partSz   = args[1];
969 
970     buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0);
971     if (buf == NULL) {
972         return ECANCELED;
973     }
974 
975     SETIOV(&in_iov, buf, partSz);
976     ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
977     if (ret != partSz) {
978         CAAM_ADR_UNMAP(buf, 0, partSz, 0);
979         return EBADMSG;
980     }
981 
982     /* sanity check on address and length */
983     if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
984         CAAM_ADR_UNMAP(buf, 0, partSz, 0);
985         return EBADMSG;
986     }
987 
988     vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz);
989     if (vaddr == 0) {
990         CAAM_ADR_UNMAP(buf, 0, partSz, 0);
991         return ECANCELED;
992     }
993 
994     CAAM_ADR_UNMAP(buf, vaddr, partSz, 1);
995     CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0);
996     return EOK;
997 }
998 
999 
1000 /* helper function to read a partition
1001  * returns EOK on success
1002  */
doREAD_PART(resmgr_context_t * ctp,io_devctl_t * msg,unsigned int args[4],unsigned int idx)1003 static int doREAD_PART(resmgr_context_t *ctp, io_devctl_t *msg,
1004         unsigned int args[4], unsigned int idx)
1005 {
1006     int partSz;
1007     CAAM_ADDRESS partAddr;
1008     CAAM_ADDRESS vaddr;
1009     unsigned char *buf;
1010     iov_t out_iov;
1011 
1012     /* get arguments */
1013     partAddr = args[0];
1014     partSz   = args[1];
1015 
1016     if (partSz > msg->o.nbytes) {
1017         WOLFSSL_MSG("not enough space to store read bytes");
1018         return EOVERFLOW;
1019     }
1020 
1021     /* sanity check on address and length */
1022     if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
1023         return EBADMSG;
1024     }
1025 
1026     buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0);
1027     if (buf == NULL) {
1028         return ECANCELED;
1029     }
1030 
1031     vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz);
1032     if (vaddr == 0) {
1033         CAAM_ADR_UNMAP(buf, 0, partSz, 0);
1034         return ECANCELED;
1035     }
1036 
1037     memcpy(buf, (unsigned char*)vaddr, partSz);
1038     SETIOV(&out_iov, buf, partSz);
1039     resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
1040     CAAM_ADR_UNMAP(buf,   0, partSz, 0);
1041     CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0);
1042     return EOK;
1043 }
1044 
1045 
io_devctl(resmgr_context_t * ctp,io_devctl_t * msg,iofunc_ocb_t * ocb)1046 int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb)
1047 {
1048     int ret = EBADMSG;
1049     unsigned int idx = sizeof(msg->i);
1050     unsigned int args[4];
1051     iov_t out_iov;
1052 
1053     /* check if at least got the msg header */
1054     if( ctp->size < sizeof(msg->i) ) {
1055         return EBADMSG;
1056     }
1057 
1058     if ((ret = iofunc_devctl_default (ctp, msg, ocb)) != _RESMGR_DEFAULT) {
1059         return ret;
1060     }
1061 
1062     /* check callers access rights for read/write */
1063     if ((ret = iofunc_devctl_verify(ctp, msg, ocb,
1064                     _IO_DEVCTL_VERIFY_OCB_READ | _IO_DEVCTL_VERIFY_OCB_WRITE))
1065                     != EOK) {
1066         WOLFSSL_MSG("issue verify devctl");
1067         return ret;
1068     }
1069     /* _IO_DEVCTL_VERIFY_PRIV      : restrict to root */
1070     /* _IO_DEVCTL_VERIFY_ACC_ISUID : restrict to owner of device */
1071     /* _IO_DEVCTL_VERIFY_ACC_ISGID : restrict to group permissions */
1072 
1073     if (getArgs(args, ctp, msg, &idx, ctp->size) != 0) {
1074         WOLFSSL_MSG("issue reading arguments");
1075         return EBADMSG;
1076     }
1077 
1078     switch (msg->i.dcmd) {
1079         case WC_CAAM_CMAC:
1080             ret = doCMAC(ctp, msg, args, idx);
1081             break;
1082 
1083         case WC_TRNG_CMD:
1084             ret = doTRNG(ctp, msg, args, idx);
1085             break;
1086 
1087         case WC_CAAM_BLOB_ENCAP:
1088         case WC_CAAM_BLOB_DECAP:
1089             ret = doBLOB(ctp, msg, args, idx);
1090             break;
1091 
1092         case WC_CAAM_ECDSA_KEYPAIR:
1093             ret = doECDSA_KEYPAIR(ctp, msg, args, idx, ocb);
1094             break;
1095 
1096         case WC_CAAM_ECDSA_VERIFY:
1097             ret = doECDSA_VERIFY(ctp, msg, args, idx);
1098             break;
1099 
1100         case WC_CAAM_ECDSA_SIGN:
1101             ret = doECDSA_SIGN(ctp, msg, args, idx);
1102             break;
1103 
1104         case WC_CAAM_ECDSA_ECDH:
1105             ret = doECDSA_ECDH(ctp, msg, args, idx);
1106             break;
1107 
1108         case WC_CAAM_FIFO_S:
1109             ret = doFIFO_S(ctp, msg, args, idx);
1110             break;
1111 
1112         case WC_CAAM_GET_PART:
1113             ret = doGET_PART(ctp, msg, args, idx, ocb);
1114             break;
1115 
1116         case WC_CAAM_FREE_PART:
1117             caamFreePart(args[0]);
1118 
1119             pthread_mutex_lock(&sm_mutex);
1120             sm_ownerId[args[0]] = 0;
1121             pthread_mutex_unlock(&sm_mutex);
1122             ret = EOK;
1123             break;
1124 
1125         case WC_CAAM_FIND_PART:
1126             ret = caamFindUnusedPartition();
1127             if (ret < 0) {
1128                 /* none found, try again later */
1129                 return EAGAIN;
1130             }
1131             SETIOV(&out_iov, &ret, sizeof(ret));
1132             resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
1133             ret = EOK;
1134             break;
1135 
1136         case WC_CAAM_WRITE_PART:
1137             ret = doWRITE_PART(ctp, msg, args, idx);
1138             break;
1139 
1140         case WC_CAAM_READ_PART:
1141             ret = doREAD_PART(ctp, msg, args, idx);
1142             break;
1143 
1144         default:
1145             WOLFSSL_MSG("unknown option");
1146             return (ENOSYS);
1147     }
1148 
1149     return ret;
1150 }
1151 
1152 
io_open(resmgr_context_t * ctp,io_open_t * msg,RESMGR_HANDLE_T * handle,void * extra)1153 int io_open(resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle,
1154         void *extra)
1155 {
1156     WOLFSSL_MSG("starting up");
1157     return (iofunc_open_default (ctp, msg, handle, extra));
1158 }
1159 
1160 
io_close_ocb(resmgr_context_t * ctp,void * reserved,RESMGR_OCB_T * ocb)1161 int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
1162 {
1163     int i;
1164 
1165     WOLFSSL_MSG("shutting down");
1166 
1167     /* free up any dangling owned memory */
1168     pthread_mutex_lock(&sm_mutex);
1169     for (i = 0; i < MAX_PART; i++) {
1170         if (sm_ownerId[i] == (CAAM_ADDRESS)ocb) {
1171             sm_ownerId[i] = 0;
1172         #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
1173             printf("found dangiling partition at index %d\n", i);
1174         #endif
1175             caamFreePart(i);
1176         }
1177     }
1178     pthread_mutex_unlock(&sm_mutex);
1179     return iofunc_close_ocb_default(ctp, reserved, ocb);
1180 }
1181 
1182 
1183 #if 0
1184 static int getSupported(char* in)
1185 {
1186         //printf("CAAM Status [0x%8.8x]   = 0x%8.8x\n",
1187         //    CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS));
1188         printf("CAAM Version MS Register [0x%8.8x]  = 0x%8.8x\n",
1189             CAAM_VERSION_MS, CAAM_READ(CAAM_VERSION_MS));
1190         printf("CAAM Version LS Register [0x%8.8x]  = 0x%8.8x\n",
1191             CAAM_VERSION_LS, CAAM_READ(CAAM_VERSION_LS));
1192         printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n",
1193             CAMM_SUPPORT_MS, CAAM_READ(CAMM_SUPPORT_MS));
1194         printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n",
1195             CAMM_SUPPORT_LS, CAAM_READ(CAMM_SUPPORT_LS));
1196 
1197     return strlen(in)+1;
1198 }
1199 #endif
1200 
1201 char cannedResponse[] = {
1202         "wolfCrypt QNX CAAM driver version "
1203         LIBWOLFSSL_VERSION_STRING
1204         "\nSupports:\n"
1205         "\tAES-CMAC\n"
1206         "\tECC (sign, verify, ecdh, keygen)\n"
1207         "\tBlobs (black and red)\n"
1208 };
1209 
1210 /* read is only used to get banner info of the driver */
io_read(resmgr_context_t * ctp,io_read_t * msg,RESMGR_OCB_T * ocb)1211 int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
1212 {
1213     int status;
1214 
1215     /* check callers access rights */
1216     if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
1217         return (status);
1218     }
1219 
1220     /* only support read not pread */
1221     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
1222         return (ENOSYS);
1223     }
1224 
1225     if (ocb->offset == 0) { /* just fill up what can */
1226         int sz = min(msg->i.nbytes, sizeof(cannedResponse));
1227         MsgReply(ctp->rcvid, sz, cannedResponse, sz);
1228         ocb->offset += sz;
1229     }
1230     else {
1231         MsgReply(ctp->rcvid, EOK, NULL, 0);
1232     }
1233 
1234     return (_RESMGR_NOREPLY);
1235 }
1236 
1237 
io_write(resmgr_context_t * ctp,io_write_t * msg,RESMGR_OCB_T * ocb)1238 int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
1239 {
1240     (void)ctp;
1241     (void)msg;
1242     (void)ocb;
1243 
1244     /* write is not supported */
1245     return (ENOSYS);
1246 }
1247 
1248 
main(int argc,char * argv[])1249 int main(int argc, char *argv[])
1250 {
1251     int name;
1252     int i;
1253 
1254     pthread_mutex_init(&sm_mutex, NULL);
1255     for (i = 0; i < MAX_PART; i++) {
1256         sm_ownerId[i] = 0;
1257     }
1258 
1259     if (InitCAAM() != 0) {
1260         WOLFSSL_MSG("unable to start up caam driver!");
1261         exit(1);
1262     }
1263 
1264     dpp = dispatch_create();
1265     if (dpp == NULL) {
1266         exit (1);
1267     }
1268     memset(&rattr, 0, sizeof(rattr));
1269     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
1270             _RESMGR_IO_NFUNCS, &io_funcs);
1271 
1272     connect_funcs.open = io_open;
1273     io_funcs.close_ocb = io_close_ocb;
1274     io_funcs.read      = io_read;
1275     io_funcs.write     = io_write;
1276     io_funcs.devctl    = io_devctl;
1277 
1278     iofunc_attr_init (&ioattr, S_IFCHR | 0666, NULL, NULL);
1279     name = resmgr_attach(dpp, &rattr, "/dev/wolfCrypt",
1280             _FTYPE_ANY, 0, &connect_funcs, &io_funcs, &ioattr);
1281     if (name == -1) {
1282         exit (1);
1283     }
1284 
1285     ctp = dispatch_context_alloc(dpp);
1286     while (1) {
1287         ctp = dispatch_block(ctp);
1288         if (ctp == NULL) {
1289             CleanupCAAM();
1290             exit (1);
1291         }
1292         dispatch_handler(ctp);
1293     }
1294 
1295     pthread_mutex_destroy(&sm_mutex);
1296     CleanupCAAM();
1297     return 0;
1298 }
1299 
1300 #endif /* __QNX__ || __QNXNTO__ */
1301