#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#undef WC_NO_HARDEN
#define WC_NO_HARDEN
#include <wolfssl/wolfcrypt/settings.h>
#if defined(__QNX__) || defined(__QNXNTO__)
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#include <wolfssl/version.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <devctl.h>
#include <semaphore.h>
uintptr_t virtual_base = 0;
static void* localMemory = NULL;
static unsigned int localPhy = 0;
sem_t localMemSem;
#ifndef WOLFSSL_CAAM_QNX_MEMORY
#define WOLFSSL_CAAM_QNX_MEMORY 250000
#endif
#define MAX_PART 7
pthread_mutex_t sm_mutex;
CAAM_ADDRESS sm_ownerId[MAX_PART];
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
dispatch_t *dpp;
resmgr_attr_t rattr;
dispatch_context_t *ctp;
iofunc_attr_t ioattr;
int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb);
int io_open (resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle,
void *extra);
int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb);
int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb);
unsigned int CAAM_READ(CAAM_ADDRESS reg) {
return in32(reg);
}
void CAAM_WRITE(CAAM_ADDRESS reg, unsigned int in)
{
out32(reg, in);
}
int CAAM_SET_BASEADDR(CAAM_ADDRESS* baseAddr)
{
#ifndef __aarch64__
void* vaddr;
vaddr = (void*)mmap_device_io(0x0000FFFF, CAAM_BASE);
if (vaddr == MAP_FAILED) {
WOLFSSL_MSG("Unable to map virtual memory");
return -1;
}
*baseAddr = (CAAM_ADDRESS)vaddr;
#endif
return 0;
}
int CAAM_SET_JOBRING_ADDR(CAAM_ADDRESS* base, CAAM_ADDRESS* ringInPhy,
void** ringInVir)
{
void* vaddr;
#ifdef __aarch64__
*base = mmap_device_io(0x0000FFFF, CAAM_BASE + 0x00030000);
#else
*base = mmap_device_io(0x0000FFFF, CAAM_BASE + 0x00001000);
#endif
if (*base == (uintptr_t)MAP_FAILED) {
WOLFSSL_MSG("Unable to map virtual memory");
return -1;
}
vaddr = mmap(0, 1024, PROT_READ | PROT_WRITE | PROT_NOCACHE,
MAP_SHARED | MAP_PHYS | MAP_ANON, NOFD, 0);
if (vaddr == (void*)MAP_FAILED) {
WOLFSSL_MSG("mmap failed\n");
return -1;
}
*ringInPhy = CAAM_ADR_TO_PHYSICAL(vaddr, 1024);
*ringInVir = vaddr;
return 0;
}
void CAAM_UNSET_JOBRING_ADDR(CAAM_ADDRESS base, CAAM_ADDRESS ringInPhy,
void* ringInVir)
{
munmap_device_io(base, 0x0000FFFF);
munmap(ringInVir, 1024);
}
void CAAM_UNSET_BASEADDR(CAAM_ADDRESS baseAddr)
{
#ifndef __aarch64__
munmap_device_io(baseAddr, 0x0000FFFF);
#endif
}
CAAM_ADDRESS CAAM_ADR_TO_PHYSICAL(void* in, int inSz)
{
off64_t ofst = 0;
int ret, count = 0;;
if (in == NULL)
return 0;
if (inSz == 0)
inSz = 1;
do {
ret = mem_offset64(in, NOFD, inSz, &ofst, NULL);
if (ret != 0) {
WOLFSSL_MSG("posix offset failed");
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
perror("posix offset failed : ");
#endif
}
msync(in, inSz, MS_INVALIDATE);
count++;
} while (ret != 0 && ret == -1 && count < 5);
return (CAAM_ADDRESS)ofst;
}
CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int len)
{
void* ret;
ret = mmap_device_memory(NULL, len, PROT_READ | PROT_WRITE | PROT_NOCACHE,
0, in);
return (CAAM_ADDRESS)ret;
}
void* CAAM_ADR_MAP(CAAM_ADDRESS in, int inSz, unsigned char copy)
{
int sz;
void *vaddr;
sz = inSz;
if (inSz == 0) {
sz = 1;
}
vaddr = mmap(NULL, sz, PROT_READ | PROT_WRITE | PROT_NOCACHE,
MAP_PHYS | MAP_SHARED | MAP_ANON, NOFD, 0);
if (vaddr == MAP_FAILED) {
WOLFSSL_MSG("Failed to map memory");
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
perror("Failed to map memory : ");
#endif
return NULL;
}
else {
if (copy && in != 0 && inSz > 0) {
memcpy(vaddr, (void*)in, inSz);
}
if (msync(vaddr, sz, MS_SYNC) != 0) {
WOLFSSL_MSG("Failed to sync memory after copy");
}
}
return vaddr;
}
void CAAM_ADR_UNMAP(void* vaddr, CAAM_ADDRESS out, int outSz,
unsigned char copy)
{
int sz;
sz = outSz;
if (outSz == 0)
sz = 1;
if (msync(vaddr, sz, MS_SYNC) != 0) {
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
perror("Failed to sync output");
#endif
}
if (copy && out != 0 && outSz > 0) {
memcpy((unsigned char*)out, (unsigned char*)vaddr, outSz);
}
munmap(vaddr, sz);
}
int CAAM_ADR_SYNC(void* vaddr, int sz)
{
if (msync(vaddr, sz, MS_SYNC) != 0) {
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
perror("address sync failed");
#endif
return -1;
}
return 0;
}
#define WC_TRNG_CMD __DIOTF(_DCMD_ALL, CAAM_ENTROPY, iov_t)
#define WC_CAAM_GET_PART __DIOTF(_DCMD_ALL, CAAM_GET_PART, iov_t)
#define WC_CAAM_FREE_PART __DIOT(_DCMD_ALL, CAAM_FREE_PART, iov_t)
#define WC_CAAM_FIND_PART __DIOTF(_DCMD_ALL, CAAM_FIND_PART, iov_t)
#define WC_CAAM_READ_PART __DIOTF(_DCMD_ALL, CAAM_READ_PART, iov_t)
#define WC_CAAM_WRITE_PART __DIOT(_DCMD_ALL, CAAM_WRITE_PART, iov_t)
#define WC_CAAM_ECDSA_KEYPAIR __DIOTF(_DCMD_ALL, CAAM_ECDSA_KEYPAIR, iov_t)
#define WC_CAAM_ECDSA_VERIFY __DIOT(_DCMD_ALL, CAAM_ECDSA_VERIFY, iov_t)
#define WC_CAAM_ECDSA_SIGN __DIOTF(_DCMD_ALL, CAAM_ECDSA_SIGN, iov_t)
#define WC_CAAM_ECDSA_ECDH __DIOTF(_DCMD_ALL, CAAM_ECDSA_ECDH, iov_t)
#define WC_CAAM_BLOB_ENCAP __DIOTF(_DCMD_ALL, CAAM_BLOB_ENCAP, iov_t)
#define WC_CAAM_BLOB_DECAP __DIOTF(_DCMD_ALL, CAAM_BLOB_DECAP, iov_t)
#define WC_CAAM_CMAC __DIOTF(_DCMD_ALL, CAAM_CMAC, iov_t)
#define WC_CAAM_AESECB __DIOTF(_DCMD_ALL, CAAM_AESECB, iov_t)
#define WC_CAAM_AESCBC __DIOTF(_DCMD_ALL, CAAM_AESCBC, iov_t)
#define WC_CAAM_AESCTR __DIOTF(_DCMD_ALL, CAAM_AESCTR, iov_t)
#define WC_CAAM_AESCCM __DIOTF(_DCMD_ALL, CAAM_AESCCM, iov_t)
#define WC_CAAM_AESGCM __DIOTF(_DCMD_ALL, CAAM_AESGCM, iov_t)
#define WC_CAAM_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t)
static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz)
{
if (partAddr < CAAM_PAGE || partAddr > CAAM_PAGE + (MAX_PART*4096) ||
partSz > 4096) {
WOLFSSL_MSG("error in physical address range");
return -1;
}
return 0;
}
static int getArgs(unsigned int args[4], resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int *idx, unsigned int maxIdx)
{
int expectedSz;
iov_t in_iov;
expectedSz = sizeof(unsigned int) * 4;
if (*idx + expectedSz > maxIdx) {
WOLFSSL_MSG("not enough for arguments");
return -1;
}
SETIOV(&in_iov, args, expectedSz);
if (resmgr_msgreadv(ctp, &in_iov, 1, *idx) != expectedSz) {
WOLFSSL_MSG("unexpected msg size read");
return -1;
}
*idx += expectedSz;
return 0;
}
static int doCMAC(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
unsigned int idx)
{
DESCSTRUCT desc;
CAAM_BUFFER tmp[3];
iov_t in_iovs[3], out_iov;
int msgSz = 0, ret, numBuf, keySz;
unsigned char ctx[32];
unsigned char keybuf[32 + BLACK_KEY_MAC_SZ];
unsigned char *buf = NULL;
numBuf = 2;
keySz = args[1];
if (args[2] == 1) {
keySz = keySz + BLACK_KEY_MAC_SZ;
}
SETIOV(&in_iovs[0], keybuf, keySz);
SETIOV(&in_iovs[1], ctx, sizeof(ctx));
msgSz = args[3];
if (msgSz < 0) {
WOLFSSL_MSG("CMAC msg size was a negative value");
return EBADMSG;
}
if (msgSz > 0) {
buf = (unsigned char*)CAAM_ADR_MAP(0, msgSz, 0);
if (buf == NULL) {
return ECANCELED;
}
SETIOV(&in_iovs[2], buf, msgSz);
numBuf = numBuf + 1;
}
ret = resmgr_msgreadv(ctp, in_iovs, numBuf, idx);
if (ret < (msgSz + keySz + sizeof(ctx))) {
if (buf != NULL)
CAAM_ADR_UNMAP(buf, 0, msgSz, 0);
return EOVERFLOW;
}
tmp[0].TheAddress = (CAAM_ADDRESS)keybuf;
tmp[0].Length = args[1];
tmp[1].TheAddress = (CAAM_ADDRESS)ctx;
tmp[1].Length = sizeof(ctx);
if (msgSz > 0) {
tmp[2].TheAddress = (CAAM_ADDRESS)buf;
tmp[2].Length = msgSz;
}
caamDescInit(&desc, CAAM_CMAC, args, tmp, numBuf);
ret = caamAesCmac(&desc, numBuf, args);
if (msgSz > 0) {
if (buf != NULL)
CAAM_ADR_UNMAP(buf, 0, msgSz, 0);
}
if (ret != Success) {
return EBADMSG;
}
SETIOV(&out_iov, ctx, sizeof(ctx));
if (sizeof(ctx) > msg->o.nbytes) {
return EOVERFLOW;
}
ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
if (ret < 0) {
return ECANCELED;
}
return EOK;
}
static int doTRNG(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
unsigned int idx)
{
int length, ret;
unsigned char *buf;
iov_t out_iov;
length = args[0];
if (length > msg->o.nbytes) {
WOLFSSL_MSG("Length too large for TRNG out size available");
return EOVERFLOW;
}
if (length > 0) {
buf = (unsigned char*)CAAM_ADR_MAP(0, length, 0);
if (buf == NULL) {
return ECANCELED;
}
ret = caamEntropy(buf, length);
if (ret == CAAM_WAITING) {
CAAM_ADR_UNMAP(buf, 0, length, 0);
return EAGAIN;
}
SETIOV(&out_iov, buf, length);
ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
DEBUG_PRINT_ARRAY(buf, length, "RNG data");
CAAM_ADR_UNMAP(buf, 0, length, 0);
if (ret < 0) {
return ECANCELED;
}
}
return EOK;
}
static int doBLOB(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
unsigned int idx)
{
int WC_CAAM_BLOB_SZ = 48;
int dir, ret, inSz, outSz;
DESCSTRUCT desc;
CAAM_BUFFER tmp[3];
iov_t in_iovs[2], out_iov;
unsigned char *inBuf, *outBuf;
unsigned char keymod[BLACK_BLOB_KEYMOD_SZ];
if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
dir = CAAM_BLOB_ENCAP;
}
else {
dir = CAAM_BLOB_DECAP;
}
inSz = args[2];
if (inSz < 0) {
return EBADMSG;
}
if (args[0] == 1 && dir == CAAM_BLOB_ENCAP) {
inSz = inSz + BLACK_KEY_MAC_SZ;
}
SETIOV(&in_iovs[0], keymod, args[3]);
if ((inSz + args[3]) > (ctp->size - idx)) {
return EOVERFLOW;
}
inBuf = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0);
if (inBuf == NULL) {
return ECANCELED;
}
SETIOV(&in_iovs[1], inBuf, inSz);
ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
if (ret < inSz + args[3]) {
return EBADMSG;
}
tmp[0].TheAddress = (CAAM_ADDRESS)keymod;
tmp[0].Length = args[3];
tmp[1].TheAddress = (CAAM_ADDRESS)inBuf;
tmp[1].Length = args[2];
outSz = args[2];
if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
outSz = outSz + WC_CAAM_BLOB_SZ;
}
else {
outSz = outSz - WC_CAAM_BLOB_SZ;
}
if (outSz < 0) {
return EBADMSG;
}
if (args[0] == 1 && dir == CAAM_BLOB_DECAP) {
outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz + BLACK_KEY_MAC_SZ, 0);
}
else {
outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0);
}
if (outBuf == NULL) {
CAAM_ADR_UNMAP(inBuf, 0, inSz, 0);
return ECANCELED;
}
tmp[2].TheAddress = (CAAM_ADDRESS)outBuf;
tmp[2].Length = outSz;
caamDescInit(&desc, dir, args, tmp, 3);
ret = caamBlob(&desc);
CAAM_ADR_UNMAP(inBuf, 0, inSz, 0);
if (args[0] == 1 && dir == CAAM_BLOB_DECAP) {
outSz = outSz + BLACK_KEY_MAC_SZ;
}
if (ret != Success) {
CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
return ECANCELED;
}
CAAM_ADR_SYNC(outBuf, outSz);
SETIOV(&out_iov, outBuf, outSz);
if (outSz > msg->o.nbytes) {
CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
return EOVERFLOW;
}
ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
CAAM_ADR_UNMAP(outBuf, 0, outSz, 0);
if (ret < 0) {
return ECANCELED;
}
return EOK;
}
static int doAEAD(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
unsigned int idx, int type)
{
int ret = EOK, i = 0;
DESCSTRUCT desc;
CAAM_BUFFER tmp[6];
iov_t in_iovs[6], out_iovs[2];
int inIdx = 0, outIdx = 0, algo;
unsigned char *key = NULL, *iv = NULL, *in = NULL, *out = NULL, *aad = NULL,
*tag = NULL;
int keySz, ivSz = 0, inSz, outSz, aadSz = 0, tagSz = 0;
memset(tmp, 0, sizeof(tmp));
keySz = args[1] & 0xFFFF;
key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0);
if (key == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], key, keySz);
inIdx++;
if (ret == EOK) {
ivSz = (args[1] >> 24) & 0xFF;
iv = (unsigned char*)CAAM_ADR_MAP(0, ivSz, 0);
if (iv == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], iv, ivSz);
inIdx++;
}
if (ret == EOK) {
inSz = args[2];
in = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0);
if (in == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], in, inSz);
inIdx++;
}
if (ret == EOK) {
outSz = args[2];
out = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0);
}
if (ret == EOK) {
tagSz = (args[1] >> 16) & 0xFF;
tag = (unsigned char*)CAAM_ADR_MAP(0, tagSz, 0);
if (tag == NULL) {
ret = ECANCELED;
}
}
if (ret == EOK) {
if ((args[0] & 0xFFFF) == CAAM_DEC) {
SETIOV(&in_iovs[inIdx], tag, tagSz);
inIdx++;
}
aadSz = (args[0] >> 16) & 0xFFFF;
if (aadSz > 0) {
aad = (unsigned char*)CAAM_ADR_MAP(0, aadSz, 0);
if (aad == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], aad, aadSz);
inIdx++;
}
}
if (ret == EOK) {
if (resmgr_msgreadv(ctp, in_iovs, inIdx, idx) < 0) {
ret = EBADMSG;
}
}
if (ret == EOK) {
switch (type) {
case WC_CAAM_AESCCM: algo = CAAM_AESCCM; break;
case WC_CAAM_AESGCM: algo = CAAM_AESGCM; break;
default:
WOLFSSL_MSG("Unknown/supported AES mode");
ret = ECANCELED;
}
}
if (ret == EOK) {
tmp[i].Length = keySz;
tmp[i].TheAddress = (CAAM_ADDRESS)key;
i++;
tmp[i].Length = ivSz;
tmp[i].TheAddress = (CAAM_ADDRESS)iv;
i++;
tmp[i].Length = inSz;
tmp[i].TheAddress = (CAAM_ADDRESS)in;
i++;
tmp[i].Length = outSz;
tmp[i].TheAddress = (CAAM_ADDRESS)out;
i++;
tmp[i].Length = tagSz;
tmp[i].TheAddress = (CAAM_ADDRESS)tag;
i++;
tmp[i].Length = aadSz;
tmp[i].TheAddress = (CAAM_ADDRESS)aad;
i++;
caamDescInit(&desc, algo, args, tmp, 6);
if (caamAead(&desc, tmp, args) != Success) {
ret = ECANCELED;
}
}
if (ret == EOK) {
CAAM_ADR_SYNC(out, outSz);
SETIOV(&out_iovs[0], out, outSz);
outIdx++;
if ((desc.state == CAAM_ENC &&
(type == WC_CAAM_AESCCM || type == WC_CAAM_AESGCM))) {
CAAM_ADR_SYNC(tag, tagSz);
SETIOV(&out_iovs[1], tag, tagSz);
outIdx++;
}
if (resmgr_msgwritev(ctp, &out_iovs[0], outIdx, sizeof(msg->o)) < 0) {
ret = ECANCELED;
}
}
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
if (iv != NULL)
CAAM_ADR_UNMAP(iv, 0, ivSz, 0);
if (in != NULL)
CAAM_ADR_UNMAP(in, 0, inSz, 0);
if (out != NULL)
CAAM_ADR_UNMAP(out, 0, outSz, 0);
if (tag != NULL)
CAAM_ADR_UNMAP(tag, 0, tagSz, 0);
if (aad != NULL)
CAAM_ADR_UNMAP(aad, 0, aadSz, 0);
return ret;
}
static int doAES(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
unsigned int idx, int type)
{
int ret = EOK, i = 0;
DESCSTRUCT desc;
CAAM_BUFFER tmp[6];
iov_t in_iovs[6], out_iovs[2];
int inIdx = 0, outIdx = 0;
int algo;
unsigned char *key = NULL, *iv = NULL, *in = NULL, *out = NULL;
unsigned char *pt = NULL;
int keySz, ivSz = 0, inSz, outSz;
unsigned int phyMem = 0;
memset(tmp, 0, sizeof(tmp));
keySz = args[1] & 0xFFFF;
inSz = args[2];
outSz = args[2];
if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) {
ivSz = 16;
}
if (keySz + inSz + outSz + ivSz < WOLFSSL_CAAM_QNX_MEMORY) {
if (sem_trywait(&localMemSem) == 0) {
key = localMemory;
phyMem = localPhy;
}
}
if (key == NULL) {
pt = (unsigned char*)CAAM_ADR_MAP(0, keySz + inSz + outSz + ivSz, 0);
key = pt;
}
if (key == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], key, keySz);
inIdx++;
if (ret == EOK) {
if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) {
ivSz = 16;
iv = key + keySz + inSz;
if (iv == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], iv, ivSz);
inIdx++;
}
}
if (ret == EOK) {
in = key + keySz;
if (in == NULL) {
ret = ECANCELED;
}
SETIOV(&in_iovs[inIdx], in, inSz);
inIdx++;
}
if (ret == EOK) {
out = key + keySz + inSz + ivSz;
if (out == NULL) {
ret = ECANCELED;
}
}
if (ret == EOK) {
if (resmgr_msgreadv(ctp, in_iovs, inIdx, idx) < 0) {
ret = ECANCELED;
}
}
if (ret == EOK) {
switch (type) {
case WC_CAAM_AESCBC: algo = CAAM_AESCBC; break;
case WC_CAAM_AESCTR: algo = CAAM_AESCTR; break;
case WC_CAAM_AESECB: algo = CAAM_AESECB; break;
default:
WOLFSSL_MSG("Unknown/supported AES mode");
ret = ECANCELED;
}
}
if (ret == EOK) {
tmp[i].Length = keySz;
tmp[i].TheAddress = (CAAM_ADDRESS)key;
i++;
if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) {
tmp[i].Length = ivSz;
tmp[i].TheAddress = (CAAM_ADDRESS)iv;
i++;
}
tmp[i].Length = inSz;
tmp[i].TheAddress = (CAAM_ADDRESS)in;
i++;
tmp[i].Length = outSz;
tmp[i].TheAddress = (CAAM_ADDRESS)out;
caamDescInit(&desc, algo, args, tmp, 6);
if (caamAesCombined(&desc, tmp, args, phyMem) != Success) {
ret = ECANCELED;
}
}
if (ret == EOK) {
CAAM_ADR_SYNC(key, keySz + inSz + ivSz + outSz);
if (type == WC_CAAM_AESCBC || type == WC_CAAM_AESCTR) {
SETIOV(&out_iovs[1], iv, ivSz);
outIdx++;
}
SETIOV(&out_iovs[0], out, outSz);
outIdx++;
if (resmgr_msgwritev(ctp, &out_iovs[0], outIdx, sizeof(msg->o)) < 0) {
ret = ECANCELED;
}
}
if (pt != NULL) {
CAAM_ADR_UNMAP(pt, 0, keySz + inSz + outSz + ivSz, 0);
}
else {
sem_post(&localMemSem);
}
return ret;
}
static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
{
int ret = EOK;
int keySz;
int privSz;
DESCSTRUCT desc;
CAAM_BUFFER tmp[2];
iov_t out_iovs[3];
unsigned char *priv = NULL, *pub = NULL;
privSz = keySz = args[3];
if (args[0] == CAAM_BLACK_KEY_CCM) {
privSz += BLACK_KEY_MAC_SZ;
}
if (args[0] == CAAM_BLACK_KEY_SM) {
privSz = sizeof(unsigned int);
}
tmp[0].Length = privSz;
priv = (unsigned char*)CAAM_ADR_MAP(0, privSz, 0);
if (priv == NULL) {
ret = ECANCELED;
}
tmp[0].TheAddress = (CAAM_ADDRESS)priv;
if (ret == EOK) {
tmp[1].Length = keySz * 2;
pub = (unsigned char*)CAAM_ADR_MAP(0, keySz * 2, 0);
if (pub == NULL) {
ret = ECANCELED;
}
tmp[1].TheAddress = (CAAM_ADDRESS)pub;
}
if (ret == EOK) {
caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2);
if (caamECDSAMake(&desc, tmp, args) != Success) {
ret = ECANCELED;
}
}
if (ret == EOK) {
SETIOV(&out_iovs[0], tmp[0].TheAddress, privSz);
SETIOV(&out_iovs[1], tmp[1].TheAddress, keySz * 2);
SETIOV(&out_iovs[2], args, sizeof(int) * 4);
if (resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o)) < 0) {
ret = ECANCELED;
}
}
if (ret == EOK && args[0] == CAAM_BLACK_KEY_SM) {
if (pthread_mutex_lock(&sm_mutex) != EOK) {
ret = ECANCELED;
}
else {
sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb;
pthread_mutex_unlock(&sm_mutex);
}
}
if (priv != NULL)
CAAM_ADR_UNMAP(priv, 0, privSz, 0);
if (pub != NULL)
CAAM_ADR_UNMAP(pub, 0, keySz*2, 0);
return ret;
}
static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
DESCSTRUCT desc;
CAAM_BUFFER tmp[5];
iov_t in_iovs[4];
int ret, pubSz;
unsigned char *hash, *pubkey = NULL, *r, *s;
CAAM_ADDRESS securePub;
if (args[0] == CAAM_BLACK_KEY_SM) {
pubSz = sizeof(CAAM_ADDRESS);
SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
}
else {
pubSz = args[3]*2;
pubkey = (unsigned char*)CAAM_ADR_MAP(0, pubSz, 0);
if (pubkey == NULL) {
return ECANCELED;
}
SETIOV(&in_iovs[0], pubkey, args[3]*2);
}
hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0);
if (hash == NULL) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
return ECANCELED;
}
SETIOV(&in_iovs[1], hash, args[2]);
r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
if (r == NULL) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
return ECANCELED;
}
SETIOV(&in_iovs[2], r, args[3]);
s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
if (s == NULL) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
return ECANCELED;
}
SETIOV(&in_iovs[3], s, args[3]);
ret = resmgr_msgreadv(ctp, in_iovs, 4, idx);
if (((args[3] * 2) + args[2] + pubSz) > ret) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
CAAM_ADR_UNMAP(s, 0, args[3], 0);
return EOVERFLOW;
}
if (args[0] == CAAM_BLACK_KEY_SM) {
tmp[0].TheAddress = securePub;
}
else {
tmp[0].TheAddress = (CAAM_ADDRESS)pubkey;
}
tmp[0].Length = args[3]*2;
tmp[1].TheAddress = (CAAM_ADDRESS)hash;
tmp[1].Length = args[2];
tmp[2].TheAddress = (CAAM_ADDRESS)r;
tmp[2].Length = args[3];
tmp[3].TheAddress = (CAAM_ADDRESS)s;
tmp[3].Length = args[3];
if (pubkey != NULL)
CAAM_ADR_SYNC(pubkey, pubSz);
CAAM_ADR_SYNC(hash, args[2]);
CAAM_ADR_SYNC(r, args[3]);
CAAM_ADR_SYNC(s, args[3]);
caamDescInit(&desc, CAAM_ECDSA_VERIFY, args, tmp, 4);
ret = caamECDSAVerify(&desc, tmp, 4, args);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
CAAM_ADR_UNMAP(s, 0, args[3], 0);
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0);
if (ret != Success) {
return EBADMSG;
}
return EOK;
}
static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
int ret, keySz;
DESCSTRUCT desc;
CAAM_BUFFER tmp[4];
unsigned char *key = NULL, *hash, *r, *s;
CAAM_ADDRESS blackKey;
iov_t in_iovs[2], out_iovs[2];
if (args[0] == CAAM_BLACK_KEY_SM) {
keySz = sizeof(CAAM_ADDRESS);
SETIOV(&in_iovs[0], &blackKey, sizeof(CAAM_ADDRESS));
}
else {
keySz = args[3];
if (args[0] == CAAM_BLACK_KEY_CCM) {
keySz += BLACK_KEY_MAC_SZ;
}
key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0);
if (key == NULL) {
return ECANCELED;
}
SETIOV(&in_iovs[0], key, keySz);
}
hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0);
if (hash == NULL) {
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
return ECANCELED;
}
SETIOV(&in_iovs[1], hash, args[2]);
ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
if ((keySz + args[2]) > ret) {
WOLFSSL_MSG("Overflow reading key and hash");
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
return EOVERFLOW;
}
if (args[0] == CAAM_BLACK_KEY_SM) {
tmp[0].TheAddress = blackKey;
tmp[0].Length = args[3];
}
else {
tmp[0].TheAddress = (CAAM_ADDRESS)key;
tmp[0].Length = keySz;
}
tmp[1].TheAddress = (CAAM_ADDRESS)hash;
tmp[1].Length = args[2];
r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
if (r == NULL) {
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
return ECANCELED;
}
tmp[2].TheAddress = (CAAM_ADDRESS)r;
tmp[2].Length = args[3];
s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
if (s == NULL) {
CAAM_ADR_UNMAP(r, 0, args[3], 0);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
return ECANCELED;
}
tmp[3].TheAddress = (CAAM_ADDRESS)s;
tmp[3].Length = args[3];
caamDescInit(&desc, CAAM_ECDSA_SIGN, args, tmp, 4);
ret = caamECDSASign(&desc, 4, args);
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, keySz, 0);
if (ret != Success) {
CAAM_ADR_UNMAP(s, 0, args[3], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
return EBADMSG;
}
if ((args[3] * 2) > msg->o.nbytes) {
CAAM_ADR_UNMAP(s, 0, args[3], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
return EOVERFLOW;
}
CAAM_ADR_SYNC(r, args[3]);
CAAM_ADR_SYNC(s, args[3]);
SETIOV(&out_iovs[0], r, args[3]);
SETIOV(&out_iovs[1], s, args[3]);
ret = resmgr_msgwritev(ctp, &out_iovs[0], 2, sizeof(msg->o));
CAAM_ADR_UNMAP(s, 0, args[3], 0);
CAAM_ADR_UNMAP(r, 0, args[3], 0);
if (ret < 0) {
return ECANCELED;
}
return EOK;
}
static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
int ret;
DESCSTRUCT desc;
CAAM_BUFFER tmp[3];
int expectedSz = 0;
iov_t in_iovs[2], out_iov;
unsigned char *pubkey = NULL, *key = NULL, *shared;
CAAM_ADDRESS securePub, blackKey;
if (args[1] == CAAM_BLACK_KEY_SM) {
SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
expectedSz += sizeof(CAAM_ADDRESS);
}
else {
pubkey = (unsigned char*)CAAM_ADR_MAP(0, args[3]*2, 0);
if (pubkey == NULL) {
return ECANCELED;
}
SETIOV(&in_iovs[0], pubkey, args[3]*2);
expectedSz += args[3]*2;
}
if (args[0] == CAAM_BLACK_KEY_SM) {
SETIOV(&in_iovs[1], &blackKey, sizeof(CAAM_ADDRESS));
expectedSz += sizeof(CAAM_ADDRESS);
}
else {
if (args[0] == CAAM_BLACK_KEY_CCM) {
key = (unsigned char*)CAAM_ADR_MAP(0, args[3] + BLACK_KEY_MAC_SZ, 0);
}
else {
key = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
}
if (key == NULL) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
return ECANCELED;
}
if (args[0] == CAAM_BLACK_KEY_CCM) {
SETIOV(&in_iovs[1], key, args[3] + BLACK_KEY_MAC_SZ);
expectedSz += args[3] + BLACK_KEY_MAC_SZ;
}
else {
SETIOV(&in_iovs[1], key, args[3]);
expectedSz += args[3];
}
}
ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
if (expectedSz > ret) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, args[3], 0);
return ECANCELED;
}
if (args[1] == CAAM_BLACK_KEY_SM) {
tmp[0].TheAddress = securePub;
}
else {
tmp[0].TheAddress = (CAAM_ADDRESS)pubkey;
}
tmp[0].Length = args[3]*2;
if (args[0] == CAAM_BLACK_KEY_SM) {
tmp[1].TheAddress = blackKey;
}
else {
tmp[1].TheAddress = (CAAM_ADDRESS)key;
}
tmp[1].Length = args[3];
shared = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0);
if (shared == NULL) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, args[3], 0);
return ECANCELED;
}
tmp[2].TheAddress = (CAAM_ADDRESS)shared;
tmp[2].Length = args[3];
caamDescInit(&desc, CAAM_ECDSA_ECDH, args, tmp, 3);
ret = caamECDSA_ECDH(&desc, 3, args);
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
if (key != NULL)
CAAM_ADR_UNMAP(key, 0, args[3], 0);
if (ret != Success) {
CAAM_ADR_UNMAP(shared, 0, args[3], 0);
return EBADMSG;
}
if (args[3] > msg->o.nbytes) {
CAAM_ADR_UNMAP(shared, 0, args[3], 0);
return EOVERFLOW;
}
CAAM_ADR_SYNC(shared, args[3]);
SETIOV(&out_iov, shared, args[3]);
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
CAAM_ADR_UNMAP(shared, 0, args[3], 0);
return EOK;
}
static int doFIFO_S(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
int ret;
DESCSTRUCT desc;
CAAM_BUFFER tmp[2];
iov_t in_iov, out_iov;
unsigned char *inBuf, *outBuf;
inBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1], 0);
if (inBuf == NULL) {
return ECANCELED;
}
SETIOV(&in_iov, inBuf, args[1]);
ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
if (ret < args[1]) {
return EBADMSG;
}
outBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1] + BLACK_KEY_MAC_SZ, 0);
if (outBuf == NULL) {
CAAM_ADR_UNMAP(inBuf, 0, args[1], 0);
return ECANCELED;
}
tmp[0].TheAddress = (CAAM_ADDRESS)inBuf;
tmp[0].Length = args[1];
tmp[1].TheAddress = (CAAM_ADDRESS)outBuf;
tmp[1].Length = args[1];
caamDescInit(&desc, CAAM_FIFO_S, args, tmp, 2);
ret = caamKeyCover(&desc, 2, args);
CAAM_ADR_UNMAP(inBuf, 0, args[1], 0);
if (ret != Success) {
CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
return EBADMSG;
}
if (args[1] + BLACK_KEY_MAC_SZ > msg->o.nbytes) {
CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
WOLFSSL_MSG("would cause output buffer overflow");
return EOVERFLOW;
}
SETIOV(&out_iov, outBuf, args[1] + BLACK_KEY_MAC_SZ);
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0);
return EOK;
}
static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
{
int partNumber;
int partSz;
CAAM_ADDRESS partAddr;
iov_t out_iov;
partNumber = args[0];
partSz = args[1];
partAddr = caamGetPartition(partNumber, partSz, 0);
if (partAddr == 0) {
return EBADMSG;
}
SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS));
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
if (pthread_mutex_lock(&sm_mutex) != EOK) {
return ECANCELED;
}
else {
sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb;
pthread_mutex_unlock(&sm_mutex);
}
return EOK;
}
static int doWRITE_PART(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
int partSz, ret;
CAAM_ADDRESS partAddr;
CAAM_ADDRESS vaddr;
unsigned char *buf;
iov_t in_iov;
partAddr = args[0];
partSz = args[1];
buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0);
if (buf == NULL) {
return ECANCELED;
}
SETIOV(&in_iov, buf, partSz);
ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
if (ret != partSz) {
CAAM_ADR_UNMAP(buf, 0, partSz, 0);
return EBADMSG;
}
if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
CAAM_ADR_UNMAP(buf, 0, partSz, 0);
return EBADMSG;
}
vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz);
if (vaddr == 0) {
CAAM_ADR_UNMAP(buf, 0, partSz, 0);
return ECANCELED;
}
CAAM_ADR_UNMAP(buf, vaddr, partSz, 1);
CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0);
return EOK;
}
static int doREAD_PART(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
{
int partSz;
CAAM_ADDRESS partAddr;
CAAM_ADDRESS vaddr;
unsigned char *buf;
iov_t out_iov;
partAddr = args[0];
partSz = args[1];
if (partSz > msg->o.nbytes) {
WOLFSSL_MSG("not enough space to store read bytes");
return EOVERFLOW;
}
if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
return EBADMSG;
}
buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0);
if (buf == NULL) {
return ECANCELED;
}
vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz);
if (vaddr == 0) {
CAAM_ADR_UNMAP(buf, 0, partSz, 0);
return ECANCELED;
}
memcpy(buf, (unsigned char*)vaddr, partSz);
SETIOV(&out_iov, buf, partSz);
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
CAAM_ADR_UNMAP(buf, 0, partSz, 0);
CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0);
return EOK;
}
int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb)
{
int ret = EBADMSG;
unsigned int idx = sizeof(msg->i);
unsigned int args[4];
iov_t out_iov;
if( ctp->size < sizeof(msg->i) ) {
return EBADMSG;
}
if ((ret = iofunc_devctl_default (ctp, msg, ocb)) != _RESMGR_DEFAULT) {
return ret;
}
if ((ret = iofunc_devctl_verify(ctp, msg, ocb,
_IO_DEVCTL_VERIFY_OCB_READ | _IO_DEVCTL_VERIFY_OCB_WRITE))
!= EOK) {
WOLFSSL_MSG("issue verify devctl");
return ret;
}
if (getArgs(args, ctp, msg, &idx, ctp->size) != 0) {
WOLFSSL_MSG("issue reading arguments");
return EBADMSG;
}
switch (msg->i.dcmd) {
case WC_CAAM_CMAC:
ret = doCMAC(ctp, msg, args, idx);
break;
case WC_TRNG_CMD:
ret = doTRNG(ctp, msg, args, idx);
break;
case WC_CAAM_BLOB_ENCAP:
case WC_CAAM_BLOB_DECAP:
ret = doBLOB(ctp, msg, args, idx);
break;
case WC_CAAM_AESECB:
case WC_CAAM_AESCTR:
case WC_CAAM_AESCBC:
ret = doAES(ctp, msg, args, idx, msg->i.dcmd);
break;
case WC_CAAM_AESCCM:
case WC_CAAM_AESGCM:
ret = doAEAD(ctp, msg, args, idx, msg->i.dcmd);
break;
case WC_CAAM_ECDSA_KEYPAIR:
ret = doECDSA_KEYPAIR(ctp, msg, args, idx, ocb);
break;
case WC_CAAM_ECDSA_VERIFY:
ret = doECDSA_VERIFY(ctp, msg, args, idx);
break;
case WC_CAAM_ECDSA_SIGN:
ret = doECDSA_SIGN(ctp, msg, args, idx);
break;
case WC_CAAM_ECDSA_ECDH:
ret = doECDSA_ECDH(ctp, msg, args, idx);
break;
case WC_CAAM_FIFO_S:
ret = doFIFO_S(ctp, msg, args, idx);
break;
case WC_CAAM_GET_PART:
ret = doGET_PART(ctp, msg, args, idx, ocb);
break;
case WC_CAAM_FREE_PART:
caamFreePart(args[0]);
if (pthread_mutex_lock(&sm_mutex) != EOK) {
ret = ECANCELED;
}
else {
sm_ownerId[args[0]] = 0;
pthread_mutex_unlock(&sm_mutex);
ret = EOK;
}
break;
case WC_CAAM_FIND_PART:
ret = caamFindUnusedPartition();
if (ret < 0) {
return EAGAIN;
}
SETIOV(&out_iov, &ret, sizeof(ret));
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
ret = EOK;
break;
case WC_CAAM_WRITE_PART:
ret = doWRITE_PART(ctp, msg, args, idx);
break;
case WC_CAAM_READ_PART:
ret = doREAD_PART(ctp, msg, args, idx);
break;
default:
WOLFSSL_MSG("unknown option");
return (ENOSYS);
}
return ret;
}
int io_open(resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle,
void *extra)
{
WOLFSSL_MSG("starting up");
return (iofunc_open_default (ctp, msg, handle, extra));
}
int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
{
int i;
WOLFSSL_MSG("shutting down");
if (pthread_mutex_lock(&sm_mutex) != EOK) {
return ECANCELED;
}
else {
for (i = 0; i < MAX_PART; i++) {
if (sm_ownerId[i] == (CAAM_ADDRESS)ocb) {
sm_ownerId[i] = 0;
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
printf("found dangiling partition at index %d\n", i);
#endif
caamFreePart(i);
}
}
pthread_mutex_unlock(&sm_mutex);
}
return iofunc_close_ocb_default(ctp, reserved, ocb);
}
#if 0#endif
char cannedResponse[] = {
"wolfCrypt QNX CAAM driver version "
LIBWOLFSSL_VERSION_STRING
"\nSupports:\n"
"\tAES-CMAC\n"
"\tAES (GCM/CCM/ECB/CBC/CTR)\n"
"\tECC (sign, verify, ecdh, keygen)\n"
"\tBlobs (black and red)\n"
};
int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
{
int status;
if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
return (status);
}
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
return (ENOSYS);
}
if (ocb->offset == 0) {
int sz = min(msg->i.nbytes, sizeof(cannedResponse));
MsgReply(ctp->rcvid, sz, cannedResponse, sz);
ocb->offset += sz;
}
else {
MsgReply(ctp->rcvid, EOK, NULL, 0);
}
return (_RESMGR_NOREPLY);
}
int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
{
(void)ctp;
(void)msg;
(void)ocb;
return (ENOSYS);
}
int main(int argc, char *argv[])
{
int name;
int i;
pthread_mutex_init(&sm_mutex, NULL);
for (i = 0; i < MAX_PART; i++) {
sm_ownerId[i] = 0;
}
if (InitCAAM() != 0) {
WOLFSSL_MSG("unable to start up caam driver!");
exit(1);
}
localMemory = (unsigned char*)CAAM_ADR_MAP(0, WOLFSSL_CAAM_QNX_MEMORY, 0);
localPhy = CAAM_ADR_TO_PHYSICAL(localMemory, WOLFSSL_CAAM_QNX_MEMORY);
sem_init(&localMemSem, 1, 1);
dpp = dispatch_create();
if (dpp == NULL) {
exit (1);
}
memset(&rattr, 0, sizeof(rattr));
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
connect_funcs.open = io_open;
io_funcs.close_ocb = io_close_ocb;
io_funcs.read = io_read;
io_funcs.write = io_write;
io_funcs.devctl = io_devctl;
iofunc_attr_init (&ioattr, S_IFCHR | 0666, NULL, NULL);
name = resmgr_attach(dpp, &rattr, "/dev/wolfCrypt",
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &ioattr);
if (name == -1) {
exit (1);
}
ctp = dispatch_context_alloc(dpp);
while (1) {
dispatch_context_t *current_ctp;
current_ctp = dispatch_block(ctp);
if (current_ctp == NULL) {
if (errno == EINTR)
continue;
perror("Error from dispatch_block ");
break;
}
else {
ctp = current_ctp;
dispatch_handler(ctp);
}
}
sem_destroy(&localMemSem);
pthread_mutex_destroy(&sm_mutex);
if (localMemory != NULL)
CAAM_ADR_UNMAP(localMemory, 0, WOLFSSL_CAAM_QNX_MEMORY, 0);
CleanupCAAM();
return 0;
}
#endif