#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_QNX_CAAM) && (defined(__QNX__) || defined(__QNXNTO__))
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <devctl.h>
#include <errno.h>
int caamFd = -1;
static wolfSSL_Mutex caamMutex;
int wc_CAAMInitInterface()
{
if (wc_InitMutex(&caamMutex) != 0) {
WOLFSSL_MSG("Could not init mutex");
return -1;
}
caamFd = open("/dev/wolfCrypt", O_RDWR);
if (caamFd < 0) {
WOLFSSL_MSG("Could not open /dev/wolfCrypt");
return -1;
}
return 0;
}
void wc_CAAMFreeInterface()
{
wc_FreeMutex(&caamMutex);
if (caamFd >= 0)
close(caamFd);
}
#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_AESCTR __DIOTF(_DCMD_ALL, CAAM_AESCTR, iov_t)
#define WC_CAAM_AESCBC __DIOTF(_DCMD_ALL, CAAM_AESCBC, 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)
#define MAX_IN_IOVS 6
#define MAX_OUT_IOVS 3
int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf,
int sz)
{
int ret, inIdx = 0, outIdx = 0;
int cmd = 0;
iov_t in[MAX_IN_IOVS], out[MAX_OUT_IOVS];
CAAM_ADDRESS privkey;
if (args != NULL) {
SETIOV(&in[inIdx], args, sizeof(unsigned int) * 4);
inIdx = inIdx + 1;
}
else {
unsigned int localArgs[4] = {0};
SETIOV(&in[inIdx], localArgs, sizeof(unsigned int) * 4);
inIdx = inIdx + 1;
}
switch (type) {
case CAAM_ENTROPY:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_TRNG_CMD;
break;
case CAAM_GET_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_GET_PART;
break;
case CAAM_FREE_PART:
cmd = WC_CAAM_FREE_PART;
break;
case CAAM_FIND_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_FIND_PART;
break;
case CAAM_READ_PART:
SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length));
outIdx = outIdx + 1;
cmd = WC_CAAM_READ_PART;
break;
case CAAM_WRITE_PART:
SETIOV(&in[inIdx], (buf->TheAddress), (buf->Length));
inIdx = inIdx + 1;
cmd = WC_CAAM_WRITE_PART;
break;
case CAAM_ECDSA_KEYPAIR:
SETIOV(&out[outIdx], buf[0].TheAddress, buf[0].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], args, sizeof(unsigned int) * 4);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_KEYPAIR;
break;
case CAAM_ECDSA_VERIFY:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[3].TheAddress, buf[3].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_ECDSA_VERIFY;
break;
case CAAM_ECDSA_SIGN:
if (args[0] == 1) {
privkey = buf[0].TheAddress;
SETIOV(&in[inIdx], &privkey, sizeof(unsigned int));
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
}
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_SIGN;
break;
case CAAM_ECDSA_ECDH:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
if (args[0] == CAAM_BLACK_KEY_SM) {
privkey = buf[1].TheAddress;
SETIOV(&in[inIdx], &privkey, sizeof(unsigned int));
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
}
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_ECDSA_ECDH;
break;
case CAAM_BLOB_ENCAP:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
if (args[0] == 1) {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ);
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
}
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_BLOB_ENCAP;
break;
case CAAM_BLOB_DECAP:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
if (args[0] == 1) {
SETIOV(&out[outIdx], buf[2].TheAddress,
buf[2].Length + WC_CAAM_MAC_SZ);
outIdx = outIdx + 1;
}
else {
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
}
cmd = WC_CAAM_BLOB_DECAP;
break;
case CAAM_AESECB:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESECB;
break;
case CAAM_AESCBC:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESCBC;
break;
case CAAM_AESCTR:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
cmd = WC_CAAM_AESCTR;
break;
case CAAM_AESCCM:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
if ((args[0] & 0xFFFF) == CAAM_ENC) {
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[4].TheAddress, buf[4].Length);
inIdx = inIdx + 1;
}
SETIOV(&in[inIdx], buf[5].TheAddress, buf[5].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_AESCCM;
break;
case CAAM_AESGCM:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
outIdx = outIdx + 1;
if ((args[0] & 0xFFFF) == CAAM_ENC) {
SETIOV(&out[outIdx], buf[4].TheAddress, buf[4].Length);
outIdx = outIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[4].TheAddress, buf[4].Length);
inIdx = inIdx + 1;
}
SETIOV(&in[inIdx], buf[5].TheAddress, buf[5].Length);
inIdx = inIdx + 1;
cmd = WC_CAAM_AESGCM;
break;
case CAAM_CMAC:
{
int i;
if (args[2] == 1) {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length + 16);
inIdx = inIdx + 1;
}
else {
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
}
SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
inIdx = inIdx + 1;
args[3] = 0;
for (i = 2; i < sz && i < MAX_IN_IOVS; i++) {
SETIOV(&in[inIdx], buf[i].TheAddress, buf[i].Length);
inIdx = inIdx + 1;
args[3] += buf[i].Length;
}
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length);
outIdx = outIdx + 1;
}
cmd = WC_CAAM_CMAC;
break;
case CAAM_FIFO_S:
SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
inIdx = inIdx + 1;
SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ);
outIdx = outIdx + 1;
cmd = WC_CAAM_FIFO_S;
break;
default:
WOLFSSL_MSG("Unknown/unsupported type");
return -1;
}
ret = wc_LockMutex(&caamMutex);
if (ret == 0) {
ret = devctlv(caamFd, cmd, inIdx, outIdx, in, out, NULL);
wc_UnLockMutex(&caamMutex);
}
if (ret != 0) {
if (ret == EFAULT) {
WOLFSSL_MSG("bad address on one of the in/out buffers");
return -1;
}
if (ret == EAGAIN && type == CAAM_ENTROPY) {
return CAAM_WAITING;
}
return -1;
}
return Success;
}
#endif