Browse Source

first pre alpha code for QNX + CAAM

manual run of RNG init and JDKEK print

job ring does initial rng

is successful on some red key blob operations

caam red key blob test pass

ecdsa sign/verify

ecdsa ecdh/sign/verify with black secure key

ecdsa ecdh/sign/verify with black secure key

initial cmac addition

initial cmac addition

black blob encap

black keys with cmac

add invalidate memory

refactoring and clean up

more code cleanup

add files for dist and remove some printf's

remove unneeded macro guard

use resource manager
Jacob Barthelmeh 3 years ago
parent
commit
749425e1e8
54 changed files with 5507 additions and 742 deletions
  1. 6 0
      .gitignore
  2. 34 0
      IDE/QNX/CAAM-DRIVER/Makefile
  3. 33 0
      IDE/QNX/example-client/Makefile
  4. 261 0
      IDE/QNX/example-client/client-tls.c
  5. 33 0
      IDE/QNX/example-cmac/Makefile
  6. 105 0
      IDE/QNX/example-cmac/cmac-test.c
  7. 33 0
      IDE/QNX/example-server/Makefile
  8. 392 0
      IDE/QNX/example-server/server-tls.c
  9. 11 0
      IDE/QNX/include.am
  10. 1 1
      IDE/include.am
  11. 26 1
      configure.ac
  12. 38 16
      src/ssl.c
  13. 2 0
      src/tls.c
  14. 6 0
      src/tls13.c
  15. 41 7
      wolfcrypt/src/aes.c
  16. 13 1
      wolfcrypt/src/asn.c
  17. 47 1
      wolfcrypt/src/cmac.c
  18. 38 0
      wolfcrypt/src/cryptocb.c
  19. 115 6
      wolfcrypt/src/ecc.c
  20. 12 1
      wolfcrypt/src/include.am
  21. 2 1
      wolfcrypt/src/md5.c
  22. 1 1
      wolfcrypt/src/port/caam/caam_aes.c
  23. 629 334
      wolfcrypt/src/port/caam/caam_driver.c
  24. 207 0
      wolfcrypt/src/port/caam/caam_error.c
  25. 0 289
      wolfcrypt/src/port/caam/caam_init.c
  26. 1221 0
      wolfcrypt/src/port/caam/caam_qnx.c
  27. 172 0
      wolfcrypt/src/port/caam/wolfcaam_cmac.c
  28. 466 0
      wolfcrypt/src/port/caam/wolfcaam_ecdsa.c
  29. 605 0
      wolfcrypt/src/port/caam/wolfcaam_init.c
  30. 349 0
      wolfcrypt/src/port/caam/wolfcaam_qnx.c
  31. 17 13
      wolfcrypt/src/random.c
  32. 2 1
      wolfcrypt/src/sha.c
  33. 6 3
      wolfcrypt/src/sha256.c
  34. 4 2
      wolfcrypt/src/sha512.c
  35. 2 2
      wolfcrypt/src/wc_port.c
  36. 17 6
      wolfcrypt/test/test.c
  37. 7 0
      wolfssl/wolfcrypt/cmac.h
  38. 22 0
      wolfssl/wolfcrypt/cryptocb.h
  39. 6 0
      wolfssl/wolfcrypt/ecc.h
  40. 5 0
      wolfssl/wolfcrypt/include.am
  41. 1 1
      wolfssl/wolfcrypt/md5.h
  42. 232 37
      wolfssl/wolfcrypt/port/caam/caam_driver.h
  43. 29 0
      wolfssl/wolfcrypt/port/caam/caam_error.h
  44. 70 0
      wolfssl/wolfcrypt/port/caam/caam_qnx.h
  45. 94 9
      wolfssl/wolfcrypt/port/caam/wolfcaam.h
  46. 36 0
      wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h
  47. 42 0
      wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h
  48. 4 0
      wolfssl/wolfcrypt/settings.h
  49. 1 1
      wolfssl/wolfcrypt/sha.h
  50. 1 1
      wolfssl/wolfcrypt/sha256.h
  51. 1 1
      wolfssl/wolfcrypt/sha512.h
  52. 2 1
      wolfssl/wolfcrypt/types.h
  53. 4 0
      wolfssl/wolfcrypt/wc_port.h
  54. 3 5
      wolfssl/wolfcrypt/wolfmath.h

+ 6 - 0
.gitignore

@@ -355,6 +355,12 @@ IDE/XCODE/Index
 /IDE/Renesas/e2studio/Projects/test/*.launch
 /IDE/Renesas/e2studio/Projects/test/*.scfg
 
+# QNX CAAM
+/IDE/QNX/example-server/server-tls
+/IDE/QNX/example-client/client-tls
+/IDE/QNX/example-cmac/cmac-test
+/IDE/QNX/CAAM-DRIVER/wolfCrypt
+
 # Emacs
 *~
 

+ 34 - 0
IDE/QNX/CAAM-DRIVER/Makefile

@@ -0,0 +1,34 @@
+ARTIFACT = wolfCrypt
+
+#Build architecture/variant string, possible values: x86, armv7le, etc...
+PLATFORM = armv7le
+OUTPUT_DIR = build
+TARGET = $(ARTIFACT)
+
+CC = qcc -Vgcc_nto$(PLATFORM)
+CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
+LD = $(CC)
+
+INCLUDES += -I../../../wolfssl/wolfcrypt/port/caam/
+CCFLAGS += -O2 -Wall
+
+SRCS = \
+    ../../../wolfcrypt/src/port/caam/caam_driver.c \
+    ../../../wolfcrypt/src/port/caam/caam_error.c \
+    ../../../wolfcrypt/src/port/caam/caam_qnx.c \
+
+OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS))))
+
+$(OUTPUT_DIR)/%.o: %.c
+	@mkdir -p $(dir $@)
+	$(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $<
+
+$(TARGET):$(OBJS)
+	$(LD) -o $(TARGET) $(LDFLAGS) $(OBJS) $(LIBS)
+
+all: $(TARGET)
+
+clean:
+	rm -rf $(OUTPUT_DIR) $(ARTIFACT)
+
+rebuild: clean all

+ 33 - 0
IDE/QNX/example-client/Makefile

@@ -0,0 +1,33 @@
+ARTIFACT = client-tls
+
+#Build architecture/variant string, possible values: x86, armv7le, etc...
+PLATFORM = armv7le
+OUTPUT_DIR = build
+TARGET = $(ARTIFACT)
+
+CC = qcc -Vgcc_nto$(PLATFORM)
+CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
+LD = $(CC)
+
+INCLUDES += -I../../../
+LIBS += -L../../../src/.libs/ -lwolfssl
+LIBS += -lsocket -lm
+CCFLAGS += -O2 -Wall
+
+SRCS = client-tls.c
+
+OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS))))
+
+$(OUTPUT_DIR)/%.o: %.c
+	@mkdir -p $(dir $@)
+	$(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $<
+
+$(TARGET):$(OBJS)
+	$(LD) -o $(TARGET) $(OBJS) $(LIBS)
+
+all: $(TARGET)
+
+clean:
+	rm -rf $(OUTPUT_DIR) $(ARTIFACT)
+
+rebuild: clean all

+ 261 - 0
IDE/QNX/example-client/client-tls.c

@@ -0,0 +1,261 @@
+/* client-tls.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL. (formerly known as CyaSSL)
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* socket includes */
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+/* wolfSSL */
+#include <wolfssl/options.h>
+#include <wolfssl/ssl.h>
+
+/* malloc out buffer and fill it with converted DER to PEM
+ * returns pem size on success
+ */
+static int convertDerToPem(int type, char* file, unsigned char **out)
+{
+    int derSz, pemSz;
+    unsigned char der[4096];
+    unsigned char *pem;
+    FILE* f;
+
+    f = fopen(file, "rb");
+    if (f == NULL) {
+        fprintf(stderr, "unable to open cert file %s\n", file);
+        return -1;
+    }
+    derSz = fread(der, 1, sizeof(der), f);
+    fclose(f);
+
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, type);
+    if (pemSz <= 0) {
+        fprintf(stderr, "issue getting pem size needed\n");
+        return -1;
+    }
+
+    pem = (unsigned char*)malloc(pemSz);
+    if (pem == NULL) {
+        fprintf(stderr, "issue malloc'ing pem size needed\n");
+        return -1;
+    }
+
+    pemSz = wc_DerToPemEx(der, derSz, pem, pemSz, NULL, type);
+    if (pemSz <= 0) {
+        fprintf(stderr, "issue %d converting der to pem\n", pemSz);
+        free(pem);
+        return -1;
+    }
+    *out = pem;
+    return pemSz;
+}
+
+
+int main(int argc, char** argv)
+{
+    int                sockfd;
+    struct sockaddr_in servAddr;
+    char               buff[256];
+    size_t             len;
+    int                ret;
+    int                port;
+
+    int pemSz;
+    unsigned char *pem;
+    FILE* f;
+
+    /* declare wolfSSL objects */
+    WOLFSSL_CTX* ctx;
+    WOLFSSL*     ssl;
+
+    /* Check for proper calling convention */
+    if (argc != 6) {
+        printf("usage: %s <port> <IPv4 address> <CA PEM> <cert DER> <key DER>\n",
+                argv[0]);
+        return 0;
+    }
+    port = atoi(argv[1]);
+
+    /* Create a socket that uses an internet IPv4 address,
+     * Sets the socket to be stream based (TCP),
+     * 0 means choose the default protocol. */
+    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+        fprintf(stderr, "ERROR: failed to create the socket\n");
+        ret = -1;
+        goto end;
+    }
+
+    /* Initialize the server address struct with zeros */
+    memset(&servAddr, 0, sizeof(servAddr));
+
+    /* Fill in the server address */
+    servAddr.sin_family = AF_INET;             /* using IPv4      */
+    servAddr.sin_port   = htons(port); /* on DEFAULT_PORT */
+
+    /* Get the server IPv4 address from the command line call */
+    if (inet_pton(AF_INET, argv[2], &servAddr.sin_addr) != 1) {
+        fprintf(stderr, "ERROR: invalid address\n");
+        ret = -1;
+        goto end;
+    }
+
+    /* Connect to the server */
+    if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr)))
+         == -1) {
+        fprintf(stderr, "ERROR: failed to connect\n");
+        goto end;
+    }
+
+    /*---------------------------------*/
+    /* Start of security */
+    /*---------------------------------*/
+    /* Initialize wolfSSL */
+    if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) {
+        fprintf(stderr, "ERROR: Failed to initialize the library\n");
+        goto socket_cleanup;
+    }
+
+    /* Create and initialize WOLFSSL_CTX */
+    if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) {
+        fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
+        ret = -1;
+        goto socket_cleanup;
+    }
+
+    /* load cert and convert DER to PEM using dynamic length */
+    pemSz = convertDerToPem(CERT_TYPE, argv[4], &pem);
+    if (pemSz <= 0) {
+        fprintf(stderr, "ERROR: converting DER cert to PEM\n");
+        ret = -1;
+        goto socket_cleanup;
+    }
+
+    if (wolfSSL_CTX_use_certificate_buffer(ctx, pem, pemSz,
+                WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) {
+        fprintf(stderr, "issue loading in pem cert\n");
+        ret = -1;
+        free(pem);
+        goto socket_cleanup;
+    }
+    free(pem);
+
+    /* load key and convert DER to PEM using dynamic length */
+    pemSz = convertDerToPem(PRIVATEKEY_TYPE, argv[5], &pem);
+    if (pemSz <= 0) {
+        fprintf(stderr, "ERROR: converting DER key to PEM\n");
+        ret = -1;
+        goto socket_cleanup;
+    }
+
+    if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, pem, pemSz,
+                WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) {
+        fprintf(stderr, "issue loading in pem key\n");
+        ret = -1;
+        free(pem);
+        goto socket_cleanup;
+    }
+    free(pem);
+
+    /* Load client certificates into WOLFSSL_CTX */
+    f = fopen(argv[3], "rb");
+    if (f == NULL) {
+        fprintf(stderr, "unable to open %s\n", argv[3]);
+        ret = -1;
+        goto socket_cleanup;
+    }
+    fseek(f, 0, SEEK_END);
+    pemSz = ftell(f);
+    rewind(f);
+    pem = malloc(pemSz);
+    pemSz = fread(pem, 1, pemSz, f);
+    fclose(f);
+
+    ret = wolfSSL_CTX_load_verify_buffer(ctx, pem, pemSz, WOLFSSL_FILETYPE_PEM);
+    if (ret != SSL_SUCCESS) {
+        fprintf(stderr, "ERROR %d: failed to load %s, please check the file.\n",
+                ret, argv[3]);
+        free(pem);
+        goto ctx_cleanup;
+    }
+    free(pem);
+
+    /* Create a WOLFSSL object */
+    if ((ssl = wolfSSL_new(ctx)) == NULL) {
+        fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
+        ret = -1;
+        goto ctx_cleanup;
+    }
+
+    /* Attach wolfSSL to the socket */
+    if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) {
+        fprintf(stderr, "ERROR: Failed to set the file descriptor\n");
+        goto cleanup;
+    }
+
+    /* Connect to wolfSSL on the server side */
+    if ((ret = wolfSSL_connect(ssl)) != SSL_SUCCESS) {
+        fprintf(stderr, "ERROR: failed to connect to wolfSSL\n");
+        goto cleanup;
+    }
+
+    /* Get a message for the server from stdin */
+    printf("Message for server: ");
+    memset(buff, 0, sizeof(buff));
+    if (fgets(buff, sizeof(buff), stdin) == NULL) {
+        fprintf(stderr, "ERROR: failed to get message for server\n");
+        ret = -1;
+        goto cleanup;
+    }
+    len = strnlen(buff, sizeof(buff));
+
+    /* Send the message to the server */
+    if ((ret = wolfSSL_write(ssl, buff, len)) != len) {
+        fprintf(stderr, "ERROR: failed to write entire message\n");
+        fprintf(stderr, "%d bytes of %d bytes were sent", ret, (int) len);
+        goto cleanup;
+    }
+
+    /* Read the server data into our buff array */
+    memset(buff, 0, sizeof(buff));
+    if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) {
+        fprintf(stderr, "ERROR: failed to read\n");
+        goto cleanup;
+    }
+
+    /* Print to stdout any data the server sends */
+    printf("Server: %s\n", buff);
+
+    /* Cleanup and return */
+cleanup:
+    wolfSSL_free(ssl);      /* Free the wolfSSL object                  */
+ctx_cleanup:
+    wolfSSL_CTX_free(ctx);  /* Free the wolfSSL context object          */
+    wolfSSL_Cleanup();      /* Cleanup the wolfSSL environment          */
+socket_cleanup:
+    close(sockfd);          /* Close the connection to the server       */
+end:
+    return ret;               /* Return reporting a success               */
+}

+ 33 - 0
IDE/QNX/example-cmac/Makefile

@@ -0,0 +1,33 @@
+ARTIFACT = cmac-test
+
+#Build architecture/variant string, possible values: x86, armv7le, etc...
+PLATFORM = armv7le
+OUTPUT_DIR = build
+TARGET = $(ARTIFACT)
+
+CC = qcc -Vgcc_nto$(PLATFORM)
+CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
+LD = $(CC)
+
+INCLUDES += -I../../../
+LIBS += -L../../../src/.libs/ -lwolfssl
+LIBS += -lsocket -lm
+CCFLAGS += -O2 -Wall
+
+SRCS = cmac-test.c
+
+OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS))))
+
+$(OUTPUT_DIR)/%.o: %.c
+	@mkdir -p $(dir $@)
+	$(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $<
+
+$(TARGET):$(OBJS)
+	$(LD) -o $(TARGET) $(OBJS) $(LIBS)
+
+all: $(TARGET)
+
+clean:
+	rm -rf $(OUTPUT_DIR) $(ARTIFACT)
+
+rebuild: clean all

+ 105 - 0
IDE/QNX/example-cmac/cmac-test.c

@@ -0,0 +1,105 @@
+/* cmac-test.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL. (formerly known as CyaSSL)
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/cmac.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+
+const byte k256[] =
+{
+    0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+
+
+static int createTag(const byte* key, int keySz, byte* msg, int msgSz,
+        byte* msg2, int msg2Sz)
+{
+    Cmac cmac;
+    byte tag[AES_BLOCK_SIZE];
+    word32 i, tagSz;
+    byte out[48];
+    word32 outSz;
+
+    XMEMSET(tag, 0, sizeof(tag));
+    tagSz = AES_BLOCK_SIZE;
+
+    outSz = 48;
+    wc_caamCoverKey((byte*)key, keySz, out, &outSz, 0);
+
+    if (wc_InitCmac(&cmac, NULL, keySz, WC_CMAC_AES, out) != 0) {
+        printf("Cmac init error\n");
+        return -1;
+    }
+
+    if (wc_CmacUpdate(&cmac, msg, msgSz) != 0) {
+        printf("message update error\n");
+        return -1;
+    }
+
+    if (msg2Sz > 0) {
+        if (wc_CmacUpdate(&cmac, msg2, msg2Sz) != 0) {
+            printf("message2 update error\n");
+            return -1;
+        }
+    }
+
+    if (wc_CmacFinal(&cmac, tag, &tagSz) != 0) {
+        printf("create tag error\n");
+        return -1;
+    }
+
+    printf("TAG :");
+    for (i = 0; i < tagSz; i++)
+        printf("%02X", tag[i]);
+    printf("\n");
+
+    return 0;
+}
+
+int main(int argc, char* argv[])
+{
+    uintptr_t virtual_base;
+    byte msg[256];
+    byte msg2[256];
+    int i;
+
+    printf("checking out permissions, can we call mmap_device_io?\n");
+    virtual_base = mmap_device_io(0x00010000, 0x02140000);
+    if (virtual_base == (uintptr_t)MAP_FAILED) {
+        perror("mmap_device_io failed for base address ");
+    }
+
+    wolfCrypt_Init();
+
+    XMEMSET(msg, 1, sizeof(msg));
+    XMEMSET(msg2, 9, sizeof(msg2));
+
+    for (i = 0; i < 256; i+=8) {
+        if (createTag(k256, sizeof(k256), msg, i, NULL, 0) != 0)
+            return -1;
+    }
+
+    wolfCrypt_Cleanup();
+    return 0;
+}

+ 33 - 0
IDE/QNX/example-server/Makefile

@@ -0,0 +1,33 @@
+ARTIFACT = server-tls
+
+#Build architecture/variant string, possible values: x86, armv7le, etc...
+PLATFORM = armv7le
+OUTPUT_DIR = build
+TARGET = $(ARTIFACT)
+
+CC = qcc -Vgcc_nto$(PLATFORM)
+CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
+LD = $(CC)
+
+INCLUDES += -I../../../
+LIBS += -L../../../src/.libs/ -lwolfssl
+LIBS += -lsocket -lm
+CCFLAGS += -O2 -Wall
+
+SRCS = server-tls.c
+
+OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS))))
+
+$(OUTPUT_DIR)/%.o: %.c
+	@mkdir -p $(dir $@)
+	$(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $<
+
+$(TARGET):$(OBJS)
+	$(LD) -o $(TARGET) $(OBJS) $(LIBS)
+
+all: $(TARGET)
+
+clean:
+	rm -rf $(OUTPUT_DIR) $(ARTIFACT)
+
+rebuild: clean all

+ 392 - 0
IDE/QNX/example-server/server-tls.c

@@ -0,0 +1,392 @@
+/* server-tls.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL. (formerly known as CyaSSL)
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* socket includes */
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+/* wolfSSL */
+#include <wolfssl/options.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/wolfcrypt/ecc.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h> /* functions for blob/cover*/
+
+#define DEFAULT_PORT 11111
+
+#undef  USE_CERT_BUFFERS_256
+#define USE_CERT_BUFFERS_256
+#include <wolfssl/certs_test.h>
+
+/* creates a blob then opens it, returns 0 on success */
+static int test_blob(byte* key, int keySz)
+{
+    int ret, i;
+    byte out[keySz + WC_CAAM_BLOB_SZ];
+    int  outSz;
+    int  keyOutSz;
+
+    byte keymod[16];
+    int  keymodSz = 16;
+
+    /* using a key mod of all 1's */
+    XMEMSET(keymod, 1, keymodSz);
+
+    /* example of creating black blog with key for later */
+    outSz = keySz + WC_CAAM_BLOB_SZ;
+    ret = wc_caamCreateBlob_ex(key, keySz, out, (word32*)&outSz,
+            WC_CAAM_BLOB_BLACK, keymod, keymodSz);
+    if (ret != 0) {
+        printf("Error creating black blob\n");
+        return -1;
+    }
+
+    printf("created black blob :");
+    for (i = 0; i < outSz; i++)
+        printf("%02X,", out[i]);
+    printf("\n");
+
+
+    /* open black blob and overwrite key, this is to show that the opened blob
+     * can be used for the upcoming TLS connection */
+    memset(key, 0, keySz);
+    keyOutSz = keySz;
+    ret = wc_caamOpenBlob_ex(out, outSz, key, (word32*)&keyOutSz,
+            WC_CAAM_BLOB_BLACK, keymod, keymodSz);
+    if (ret != 0) {
+        printf("Error opening black blob\n");
+    }
+
+    return ret;
+}
+
+
+/* example of covering an existing key and then making a black blob with it
+ * note that generating an ECC completely in secure memory already covered can
+ * be done by call wc_ecc_make_key */
+int cover(ecc_key* keyOut, const byte* der, word32 derSz)
+{
+    int ret;
+    ecc_key notSecure;
+    word32  idx = 0;
+
+    /* format bit plus public key x and y parameter */
+    byte x963[65];
+    word32 x963Sz = 65;
+
+    /* uncovered private key */
+    byte d[32];
+    word32 dSz = 32;
+
+    byte blackKey[48]; /* 16 bytes larger than key size to account for MAC and
+                        * potential padding */
+    word32 blackKeySz = 48;
+
+
+    /* The DER buffer for test case does not contain a black key, here we will
+     * extract the key information, cover it (make it a black key), and then
+     * import that into 'keyOut' which will create a secure partition on import.
+     *
+     * These steps of covering and importing can be avoided with a call to
+     * wc_ecc_make_key which creates a new black key that never leaves the CAAM.
+     * The cover process is only being used to make use of an existing key that
+     * matches the test certificate.
+     */
+    wc_ecc_init(&notSecure);
+    if (wc_EccPrivateKeyDecode(der, &idx, &notSecure, derSz) != 0) {
+        printf("Error extracting ECC der buffer\n");
+        ret = -1;
+        goto done;
+    }
+
+    /* Get the uncovered key values */
+    if (wc_ecc_export_private_raw(&notSecure, NULL, NULL, NULL, NULL, d, &dSz)
+            != 0) {
+        printf("Error getting ecc key values\n");
+        ret = -1;
+        goto done;
+    }
+
+    if (wc_ecc_export_x963(&notSecure, x963, &x963Sz) != 0) {
+        printf("Error getting ecc public key\n");
+        ret = -1;
+        goto done;
+    }
+
+    /* Cover up the private key (make it a black key, encrypting with AES-CCM)*/
+    XMEMSET(blackKey, 0, blackKeySz);
+    if (wc_caamCoverKey(d, dSz, blackKey, &blackKeySz, 0) != 0) {
+        printf("Error covering up the private key\n");
+        ret = -1;
+        goto done;
+    }
+
+    /* Sanity check to compare covered key versus plain text */
+    if (XMEMCMP(d, blackKey, dSz) == 0) {
+        printf("Something went wrong with key cover!!\n");
+        ret = -1;
+        goto done;
+    }
+
+    if (test_blob(blackKey, blackKeySz - 16) != 0) {/*-16 byte for MAC padding*/
+        printf("test blob failed\n");
+        ret = -1;
+        goto done;
+    }
+
+    /* zero out the plain text buffer and free key */
+    XMEMSET(d, 0, dSz);
+
+    /* Import the black key into a ecc_key structure (this step tries to create
+     * a partition of secure memory marked CPS)
+     */
+    ret = wc_ecc_import_private_key(blackKey, blackKeySz, x963, x963Sz, keyOut);
+    if (ret != 0) {
+        printf("Error importing black key into secure memory %d\n", ret);
+        wc_ecc_free(keyOut);
+        goto done;
+    }
+    printf("blackKeySz = %d, virtual secure address ecc_key.blackKey = 0x%08X\n",
+            blackKeySz, keyOut->blackKey);
+
+    ret = 0;
+done:
+
+    wc_ecc_free(&notSecure);
+    return ret;
+}
+
+
+/* callback function for creating ECC signatures */
+static int TLS_ECC_Sign_callback(WOLFSSL* ssl, const unsigned char* in,
+        unsigned int inSz, unsigned char* out, word32* outSz,
+        const unsigned char* keyDer, unsigned int keySz,
+        void* ctx)
+{
+    ecc_key* blackKey;
+
+    printf("Using ECC sign callback\n");
+
+    if (ctx == NULL) {
+        printf("Was expecting a black key passed along with WOLFSSH\n");
+        return -1;
+    }
+    blackKey = (ecc_key*)ctx;
+
+    return wc_ecc_sign_hash(in, inSz, out, outSz, NULL, blackKey);
+}
+
+
+/* callback function to do ECDH operation in TLS handshake */
+static int TLS_ECDH_callback(WOLFSSL* ssl, struct ecc_key* otherKey,
+        unsigned char* pubKeyDer, word32* pubKeySz,
+        unsigned char* out, word32* outlen,
+        int side, void* ctx)
+{
+    int ret= -1;
+
+    printf("Using ECDH callback\n");
+
+    if (ctx == NULL) {
+        printf("Was expecting a black key passed along with WOLFSSH\n");
+        return -1;
+    }
+
+    /* this is being called from client end */
+    if (side == WOLFSSL_CLIENT_END) {
+    }
+
+    /* this is being called from server end */
+    if (side == WOLFSSL_SERVER_END) {
+        ecc_key pub;
+
+        wc_ecc_init(&pub);
+        if (wc_ecc_import_x963(pubKeyDer, *pubKeySz, &pub) != 0) {
+            printf("Issue decoding the public key to generate shared secret\n");
+            wc_ecc_free(&pub);
+            return  -1;
+        }
+
+        /* otherKey is the ephemeral private key created with ECDHE cipher
+         * suites. As long as EccKeyGenCb has not been set this key was created
+         * with wc_ecc_make_key_ex, which when used with NIST P256 it will
+         * automatically try to create a secure black key
+         */
+        ret = wc_ecc_shared_secret(otherKey, &pub, out, outlen);
+        wc_ecc_free(&pub);
+    }
+
+    return ret;
+}
+
+
+int main()
+{
+    int                sockfd;
+    int                connd = 0;
+    struct sockaddr_in servAddr;
+    struct sockaddr_in clientAddr;
+    socklen_t          size = sizeof(clientAddr);
+    char               buff[256];
+    size_t             len;
+    int                ret;
+    const char*        reply = "I hear ya fa shizzle!\n";
+
+    ecc_key blackKey;
+
+    /* declare wolfSSL objects */
+    WOLFSSL_CTX* ctx = NULL;
+    WOLFSSL*     ssl = NULL;
+
+    /* Initialize wolfSSL */
+    if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
+        fprintf(stderr, "issue with wolfSSL_Init()\n");
+        return -1;
+    }
+    wolfSSL_Debugging_ON();
+    wc_ecc_init(&blackKey);
+
+    /* Create a socket that uses an internet IPv4 address,
+     * Sets the socket to be stream based (TCP),
+     * 0 means choose the default protocol. */
+    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+        fprintf(stderr, "ERROR: failed to create the socket\n");
+        goto end;
+    }
+
+    /* Create and initialize WOLFSSL_CTX */
+    if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) {
+        fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
+        goto end;
+    }
+
+    /* Load server certificates into WOLFSSL_CTX */
+    if (wolfSSL_CTX_use_certificate_buffer(ctx, serv_ecc_der_256,
+                sizeof_serv_ecc_der_256, SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
+        printf("error loading in certificate buffer\n");
+        goto end;
+    }
+
+//    wolfSSL_CTX_use_PrivateKey_buffer(ctx, ecc_key_der_256, sizeof_ecc_key_der_256, SSL_FILETYPE_ASN1);
+
+    if (cover(&blackKey, ecc_key_der_256, sizeof_ecc_key_der_256) != 0) {
+        printf("error covering up key\n");
+        goto end;
+    }
+
+    /* set signing callback to use during TLS connection */
+    wolfSSL_CTX_SetEccSignCb(ctx, TLS_ECC_Sign_callback);
+
+    /* set ECDH shared secret callback to use during TLS connection */
+    wolfSSL_CTX_SetEccSharedSecretCb(ctx, TLS_ECDH_callback);
+
+    /* Initialize the server address struct with zeros */
+    memset(&servAddr, 0, sizeof(servAddr));
+
+    /* Fill in the server address */
+    servAddr.sin_family      = AF_INET;             /* using IPv4      */
+    servAddr.sin_port        = htons(DEFAULT_PORT); /* on DEFAULT_PORT */
+    servAddr.sin_addr.s_addr = INADDR_ANY;          /* from anywhere   */
+
+    /* Bind the server socket to our port */
+    if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) {
+        fprintf(stderr, "ERROR: failed to bind\n");
+        goto end;
+    }
+
+    /* Listen for a new connection, allow 5 pending connections */
+    if (listen(sockfd, 5) == -1) {
+        fprintf(stderr, "ERROR: failed to listen\n");
+        goto end;
+    }
+
+    /* Continue to accept clients until shutdown is issued */
+    printf("Waiting for a connection...\n");
+
+    /* Accept client connections */
+    if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size)) == -1) {
+        fprintf(stderr, "ERROR: failed to accept the connection\n\n");
+        goto end;
+    }
+
+    /* Create a WOLFSSL object */
+    if ((ssl = wolfSSL_new(ctx)) == NULL) {
+        fprintf(stderr, "ERROR: failed to create WOLFSSL object\n");
+        goto end;
+    }
+
+    /* Attach wolfSSL to the socket */
+    wolfSSL_set_fd(ssl, connd);
+
+    /* associate the covered up black key with the WOLFSSH structure,
+     * this will then get passed as the last argument to the callbacks */
+    wolfSSL_SetEccSignCtx(ssl, (void*)&blackKey);
+    wolfSSL_SetEccSharedSecretCtx(ssl, (void*)&blackKey);
+
+    /* Establish TLS connection */
+    ret = wolfSSL_accept(ssl);
+    if (ret != SSL_SUCCESS) {
+        fprintf(stderr, "wolfSSL_accept error = %d\n",
+                wolfSSL_get_error(ssl, ret));
+        goto end;
+    }
+    printf("Client connected successfully\n");
+
+    /* Read the client data into our buff array */
+    memset(buff, 0, sizeof(buff));
+    if (wolfSSL_read(ssl, buff, sizeof(buff)-1) == -1) {
+        fprintf(stderr, "ERROR: failed to read\n");
+        goto end;
+    }
+
+    /* Print to stdout any data the client sends */
+    printf("Client: %s\n", buff);
+
+    /* Write our reply into buff */
+    memset(buff, 0, sizeof(buff));
+    memcpy(buff, reply, strlen(reply));
+    len = strnlen(buff, sizeof(buff));
+
+    /* Reply back to the client */
+    if (wolfSSL_write(ssl, buff, len) != len) {
+        fprintf(stderr, "ERROR: failed to write\n");
+        goto end;
+    }
+
+end:
+    /* Cleanup after this connection */
+    wolfSSL_free(ssl);      /* Free the wolfSSL object              */
+    close(connd);           /* Close the connection to the client   */
+    wc_ecc_free(&blackKey);
+
+    printf("Shutdown complete\n");
+
+    /* Cleanup and return */
+    wolfSSL_CTX_free(ctx);  /* Free the wolfSSL context object          */
+    wolfSSL_Cleanup();      /* Cleanup the wolfSSL environment          */
+    close(sockfd);          /* Close the socket listening for clients   */
+    return 0;               /* Return reporting a success               */
+}

+ 11 - 0
IDE/QNX/include.am

@@ -0,0 +1,11 @@
+# vim:ft=automake
+# included from Top Level Makefile.am
+# All paths should be given relative to the root
+
+EXTRA_DIST+= IDE/QNX/CAAM-DRIVER/Makefile
+EXTRA_DIST+= IDE/QNX/example-server/Makefile
+EXTRA_DIST+= IDE/QNX/example-server/server-tls.c
+EXTRA_DIST+= IDE/QNX/example-client/Makefile
+EXTRA_DIST+= IDE/QNX/example-client/client-tls.c
+EXTRA_DIST+= IDE/QNX/example-cmac/Makefile
+EXTRA_DIST+= IDE/QNX/example-cmac/cmac-test.c

+ 1 - 1
IDE/include.am

@@ -35,7 +35,7 @@ include IDE/M68K/include.am
 include IDE/HEXAGON/include.am
 include IDE/RISCV/include.am
 include IDE/XilinxSDK/include.am
-include IDE/VisualDSP/include.am
+include IDE/QNX/include.am
 
 EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif IDE/zephyr
 EXTRA_DIST+= IDE/OPENSTM32/README.md

+ 26 - 1
configure.ac

@@ -1419,6 +1419,23 @@ then
 fi
 
 
+# CAAM build
+AC_ARG_ENABLE([caam],
+    [AS_HELP_STRING([--enable-caam],[Enable wolfSSL support for CAAM (default: disabled)])],
+    [ ENABLED_CAAM=$enableval ],
+    [ ENABLED_CAAM=no ]
+    )
+if test "$ENABLED_CAAM" = "yes"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IMX6_CAAM"
+fi
+
+if test "$ENABLED_CAAM" = "qnx"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IMX6_CAAM -DWOLFSSL_QNX_CAAM"
+fi
+
+
 # INTEL AES-NI
 AC_ARG_ENABLE([aesni],
     [AS_HELP_STRING([--enable-aesni],[Enable wolfSSL AES-NI support (default: disabled)])],
@@ -2749,6 +2766,12 @@ AC_ARG_ENABLE([base16],
     [ ENABLED_BASE16=$enableval ],
     [ ENABLED_BASE16=no ]
     )
+
+if test "$ENABLED_CAAM" = "qnx"
+then
+    ENABLED_BASE16=yes
+fi
+
 if test "$ENABLED_BASE16" = "yes"
 then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE16"
@@ -5564,7 +5587,7 @@ AC_ARG_ENABLE([cryptocb],
     [ ENABLED_CRYPTOCB=no ]
     )
 
-if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes"
+if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" = "qnx"
 then
     ENABLED_CRYPTOCB=yes
 fi
@@ -6209,6 +6232,7 @@ AM_CONDITIONAL([BUILD_DES3],[test "x$ENABLED_DES3" = "xyes" || test "x$ENABLED_U
 AM_CONDITIONAL([BUILD_PKCS7],[test "x$ENABLED_PKCS7" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_SMIME],[test "x$ENABLED_SMIME" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_HASHFLAGS],[test "x$ENABLED_HASHFLAGS" = "xyes"])
+AM_CONDITIONAL([BUILD_CAAM],[test "x$ENABLED_CAAM" = "xyes" || test "x$ENABLED_CAAM" = "xqnx"])
 AM_CONDITIONAL([BUILD_LINUXKM],[test "$ENABLED_LINUXKM" = "yes"])
 AM_CONDITIONAL([BUILD_NO_LIBRARY],[test "$ENABLED_NO_LIBRARY" = "yes"])
 AM_CONDITIONAL([BUILD_RC2],[test "x$ENABLED_RC2" = "xyes"])
@@ -6556,6 +6580,7 @@ echo "   * Inline Code:                $ENABLED_INLINE"
 echo "   * Linux AF_ALG:               $ENABLED_AFALG"
 echo "   * Linux devcrypto:            $ENABLED_DEVCRYPTO"
 echo "   * Crypto callbacks:           $ENABLED_CRYPTOCB"
+echo "   * i.MX6 CAAM:                 $ENABLED_CAAM"
 echo ""
 echo "---"
 

+ 38 - 16
src/ssl.c

@@ -7492,36 +7492,48 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
         int type = 0;
         void *pkey = NULL;
 
+    #ifndef NO_RSA
         if (der->keyOID == RSAk) {
             type = DYNAMIC_TYPE_RSA;
         }
-        else if (der->keyOID == ECDSAk) {
+    #endif
+    #ifdef HAVE_ECC
+        if (der->keyOID == ECDSAk) {
             type = DYNAMIC_TYPE_ECC;
         }
+    #endif
         ret = CreateDevPrivateKey(&pkey, buff, size, type, ctx->privateKeyLabel,
                                   ctx->privateKeyId, ctx->heap,
                                   ctx->privateKeyDevId);
+    #ifndef NO_RSA
         if (ret == 0 && der->keyOID == RSAk) {
             ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, der->publicKey,
                                               der->pubKeySize);
             wc_FreeRsaKey((RsaKey*)pkey);
         }
-        else if (ret == 0 && der->keyOID == ECDSAk) {
+    #endif
+    #ifdef HAVE_ECC
+        if (ret == 0 && der->keyOID == ECDSAk) {
             ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, der->publicKey,
                                               der->pubKeySize);
             wc_ecc_free((ecc_key*)pkey);
         }
+    #endif
         if (pkey != NULL) {
             XFREE(pkey, ctx->heap, type);
         }
-        if (ret == 0) {
-            ret = WOLFSSL_SUCCESS;
-        }
-        else {
-            ret = WOLFSSL_FAILURE;
+        if (ret != CRYPTOCB_UNAVAILABLE) {
+            if (ret == 0) {
+                ret = WOLFSSL_SUCCESS;
+            }
+            else {
+                ret = WOLFSSL_FAILURE;
+            }
         }
     }
-    else
+
+    /* fall through if unavailable */
+    if (ret == CRYPTOCB_UNAVAILABLE)
 #endif
     {
         ret = wc_CheckPrivateKeyCert(buff, size, der);
@@ -8114,35 +8126,45 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl)
         int type = 0;
         void *pkey = NULL;
 
+    #ifndef NO_RSA
         if (der.keyOID == RSAk) {
             type = DYNAMIC_TYPE_RSA;
         }
-        else if (der.keyOID == ECDSAk) {
+    #endif
+    #ifdef HAVE_ECC
+        if (der.keyOID == ECDSAk) {
             type = DYNAMIC_TYPE_ECC;
         }
+    #endif
         ret = CreateDevPrivateKey(&pkey, buff, size, type,
                                   ssl->buffers.keyLabel,
                                   ssl->buffers.keyId, ssl->heap,
                                   ssl->buffers.keyDevId);
+    #ifndef NO_RSA
         if (ret == 0 && der.keyOID == RSAk) {
             ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, der.publicKey,
                                               der.pubKeySize);
-            if (ret == 0)
-                ret = 1;
+            if (ret == 0 && ret != CRYPTOCB_UNAVAILABLE)
+                ret = WOLFSSL_SUCCESS;
             wc_FreeRsaKey((RsaKey*)pkey);
         }
-        else if (ret == 0 && der.keyOID == ECDSAk) {
+    #endif
+    #ifdef HAVE_ECC
+        if (ret == 0 && der.keyOID == ECDSAk) {
             ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, der.publicKey,
                                               der.pubKeySize);
-            if (ret == 0)
-                ret = 1;
+            if (ret == 0 && ret != CRYPTOCB_UNAVAILABLE)
+                ret = WOLFSSL_SUCCESS;
             wc_ecc_free((ecc_key*)pkey);
         }
+    #endif
         if (pkey != NULL) {
             XFREE(pkey, ssl->heap, type);
         }
     }
-    else
+
+    /* fall through if unsupported */
+    if (ret != CRYPTOCB_UNAVAILABLE)
 #endif
         ret  = wc_CheckPrivateKeyCert(buff, size, &der);
     FreeDecodedCert(&der);
@@ -45901,7 +45923,7 @@ int wolfSSL_X509_NAME_print_ex_fp(XFILE file, WOLFSSL_X509_NAME* name,
 
     return ret;
 }
-#endif
+#endif /* NO_FILESYSTEM */
 
 #ifndef NO_WOLFSSL_STUB
 WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)

+ 2 - 0
src/tls.c

@@ -10006,6 +10006,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
     #endif /* HAVE_FIPS */
 #endif /* HAVE_ECC */
 
+#ifndef NO_DH
             /* Add FFDHE supported groups. */
         #ifdef HAVE_FFDHE_8192
             if (8192/8 >= ssl->options.minDhKeySz &&
@@ -10052,6 +10053,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
                     return ret;
             }
         #endif
+#endif
 
     (void)ssl;
     (void)extensions;

+ 6 - 0
src/tls13.c

@@ -1469,6 +1469,12 @@ end:
     #else
         return (word32)(ktime_get_real_ns() / (ktime_t)1000000);
     #endif
+#elif defined(WOLFSSL_QNX_CAAM)
+    word32 TimeNowInMilliseconds(void)
+    {
+        struct timespec now;
+        clock_gettime(CLOCK_REALTIME, &now);
+        return (word32)(now.tv_sec * 1000 + now.tv_nsec / 1000000);
     }
 #elif defined(FUSION_RTOS)
     /* The time in milliseconds.

+ 41 - 7
wolfcrypt/src/aes.c

@@ -840,7 +840,8 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
         }
     #endif /* HAVE_AES_DECRYPT */
 
-#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)) || \
+#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) \
+        && !defined(WOLFSSL_QNX_CAAM)) || \
       ((defined(WOLFSSL_AFALG) || defined(WOLFSSL_DEVCRYPTO_AES)) && \
         defined(HAVE_AESCCM))
         static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
@@ -2700,7 +2701,8 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
         }
     #endif
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) \
+    && !defined(WOLFSSL_QNX_CAAM)
       /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
 
 #elif defined(WOLFSSL_AFALG)
@@ -3048,7 +3050,35 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
     #if defined(HAVE_COLDFIRE_SEC)
         #error "Coldfire SEC doesn't yet support AES direct"
 
-    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    #elif defined(FREESCALE_LTC)
+        /* Allow direct access to one block encrypt */
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            byte *key;
+            uint32_t keySize;
+
+            key = (byte*)aes->key;
+            wc_AesGetKeySize(aes, &keySize);
+
+            LTC_AES_EncryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
+                key, keySize);
+        }
+
+        /* Allow direct access to one block decrypt */
+        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            byte *key;
+            uint32_t keySize;
+
+            key = (byte*)aes->key;
+            wc_AesGetKeySize(aes, &keySize);
+
+            LTC_AES_DecryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
+                key, keySize, kLTC_EncryptKey);
+        }
+
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
+        !defined(WOLFSSL_QNX_CAAM)
         /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
 
     #elif defined(WOLFSSL_AFALG)
@@ -3645,7 +3675,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
     {
         return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t*)in, sz, out);
     }
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
+        !defined(WOLFSSL_QNX_CAAM)
       /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
 
 #elif defined(WOLFSSL_AFALG)
@@ -4048,7 +4079,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
             return ret;
         }
 
-    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
+        !defined(WOLFSSL_QNX_CAAM)
         /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
 
     #elif defined(WOLFSSL_AFALG)
@@ -7632,7 +7664,8 @@ int wc_AesCcmCheckTagSize(int sz)
 #elif defined(HAVE_COLDFIRE_SEC)
     #error "Coldfire SEC doesn't currently support AES-CCM mode"
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
+        !defined(WOLFSSL_QNX_CAAM)
     /* implemented in wolfcrypt/src/port/caam_aes.c */
 
 #elif defined(WOLFSSL_SILABS_SE_ACCEL)
@@ -8323,7 +8356,8 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize)
 #endif /* !WOLFSSL_TI_CRYPT */
 
 #ifdef HAVE_AES_ECB
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
+        !defined(WOLFSSL_QNX_CAAM)
     /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
 
 #elif defined(WOLFSSL_AFALG)

+ 13 - 1
wolfcrypt/src/asn.c

@@ -114,6 +114,10 @@ ASN Options:
     #include <wolfssl/wolfcrypt/ed448.h>
 #endif
 
+#ifdef WOLFSSL_QNX_CAAM
+	#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
+
 #ifndef NO_RSA
     #include <wolfssl/wolfcrypt/rsa.h>
 #if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
@@ -16339,6 +16343,14 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
 
     /* private */
     privSz = key->dp->size;
+
+#ifdef WOLFSSL_QNX_CAAM
+    /* check if is a black key, and add MAC size if so */
+    if (key->blackKey > 0) {
+        privSz = privSz + WC_CAAM_MAC_SZ;
+    }
+#endif
+
 #ifndef WOLFSSL_NO_MALLOC
     prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
                          key->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -16350,7 +16362,7 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
         return BUFFER_E;
     }
 #endif
-    prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
+    prvidx += SetOctetString8Bit(privSz, &prv[prvidx]);
     ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
     if (ret < 0) {
     #ifndef WOLFSSL_NO_MALLOC

+ 47 - 1
wolfcrypt/src/cmac.c

@@ -51,6 +51,10 @@
 #include <wolfssl/wolfcrypt/aes.h>
 #include <wolfssl/wolfcrypt/cmac.h>
 
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
 
 static void ShiftAndXorRb(byte* out, byte* in)
 {
@@ -79,10 +83,27 @@ int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
 
     (void)unused;
 
-    if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES)
+    if (cmac == NULL || keySz == 0 || type != WC_CMAC_AES)
         return BAD_FUNC_ARG;
 
     XMEMSET(cmac, 0, sizeof(Cmac));
+
+    #ifdef WOLFSSL_QNX_CAAM
+        cmac->devId = 7; //always use caam devid when available
+    #endif
+    #ifdef WOLF_CRYPTO_CB
+        if (cmac->devId != INVALID_DEVID) {
+            ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL,
+                    type, unused);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
     ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
     if (ret == 0) {
         byte l[AES_BLOCK_SIZE];
@@ -99,9 +120,22 @@ int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
 
 int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
 {
+    #ifdef WOLF_CRYPTO_CB
+    int ret;
+    #endif
+
     if ((cmac == NULL) || (in == NULL && inSz != 0))
         return BAD_FUNC_ARG;
 
+    #ifdef WOLF_CRYPTO_CB
+        if (cmac->devId != INVALID_DEVID) {
+            ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz,
+                    NULL, NULL, 0, NULL);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
     while (inSz != 0) {
         word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz);
         XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
@@ -127,6 +161,9 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
 
 int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
 {
+    #ifdef WOLF_CRYPTO_CB
+    int ret;
+    #endif
     const byte* subKey;
 
     if (cmac == NULL || out == NULL || outSz == NULL)
@@ -135,6 +172,15 @@ int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
     if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ)
         return BUFFER_E;
 
+    #ifdef WOLF_CRYPTO_CB
+        if (cmac->devId != INVALID_DEVID) {
+            ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz, 0, NULL);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+
     if (cmac->bufferSz == AES_BLOCK_SIZE) {
         subKey = cmac->k1;
     }

+ 38 - 0
wolfcrypt/src/cryptocb.c

@@ -706,5 +706,43 @@ int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz)
     return wc_CryptoCb_TranslateErrorCode(ret);
 }
 #endif /* !WC_NO_RNG */
+#ifdef WOLFSSL_CMAC
+int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
+        const byte* in, word32 inSz, byte* out, word32* outSz, int type,
+        void* ctx)
+{
+    int ret = CRYPTOCB_UNAVAILABLE;
+    CryptoCb* dev;
+
+    /* locate registered callback */
+    if (cmac) {
+        dev = wc_CryptoCb_FindDevice(cmac->devId);
+    }
+    else {
+        /* locate first callback and try using it */
+        dev = wc_CryptoCb_FindDeviceByIndex(0);
+    }
+
+    if (dev && dev->cb) {
+        wc_CryptoInfo cryptoInfo;
+        XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
+        cryptoInfo.algo_type = WC_ALGO_TYPE_CMAC;
+
+        cryptoInfo.cmac.cmac  = cmac;
+        cryptoInfo.cmac.ctx   = ctx;
+        cryptoInfo.cmac.key   = key;
+        cryptoInfo.cmac.in    = in;
+        cryptoInfo.cmac.out   = out;
+        cryptoInfo.cmac.outSz = outSz;
+        cryptoInfo.cmac.keySz = keySz;
+        cryptoInfo.cmac.inSz  = inSz;
+        cryptoInfo.cmac.type  = type;
+
+        ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
+    }
+
+    return wc_CryptoCb_TranslateErrorCode(ret);
+}
+#endif
 
 #endif /* WOLF_CRYPTO_CB */

+ 115 - 6
wolfcrypt/src/ecc.c

@@ -159,6 +159,10 @@ ECC Curve Sizes:
     #include <wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h>
 #endif
 
+#if defined(WOLFSSL_QNX_CAAM)
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
+
 #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
     #define GEN_MEM_ERR MP_MEM
 #elif defined(USE_FAST_MATH)
@@ -4793,6 +4797,11 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
     (void)devId;
 #endif
 
+    //@TODO for now set as CAAM operation for all
+#ifdef WOLFSSL_QNX_CAAM
+    key->devId = 7;//WOLFSSL_CAAM_DEVID
+#endif
+
 #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A)
     key->slot = ATECC_INVALID_SLOT;
 #else
@@ -5126,8 +5135,7 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
 #endif
 #endif
 
-    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
-                                                                rng == NULL) {
+    if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
         return ECC_BAD_ARG_E;
     }
 
@@ -5140,6 +5148,11 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
     }
 #endif
 
+    if (rng == NULL) {
+        WOLFSSL_MSG("rng was NULL");
+        return ECC_BAD_ARG_E;
+    }
+
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
     /* handle async cases */
     err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key);
@@ -5742,6 +5755,13 @@ int wc_ecc_free(ecc_key* key)
     wc_ecc_free_async(key);
 #endif
 
+#ifdef WOLFSSL_QNX_CAAM
+    /* free secure memory */
+    if (key->blackKey > 0) {
+       caamFreePart(key->partNum); 
+    }
+#endif
+
 #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A)
     atmel_ecc_free(key->slot);
     key->slot = ATECC_INVALID_SLOT;
@@ -7209,6 +7229,22 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
    if (key->type == ECC_PRIVATEKEY_ONLY)
        return ECC_PRIVATEONLY_E;
 
+#ifdef WOLFSSL_QNX_CAAM
+    /* check if public key in secure memory */
+    if (key->securePubKey > 0) {
+        int keySz = wc_ecc_size(key);
+
+        /* store byte point type */
+        out[0] = ECC_POINT_UNCOMP;
+
+        if (caamReadPartition((CAAM_ADDRESS)key->securePubKey, out+1, keySz*2) != 0)
+            return WC_HW_E;
+
+        *outLen = 1 + 2*keySz;
+        return MP_OKAY;
+    }
+#endif
+
    if (key->type == 0 || wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL){
        return ECC_BAD_ARG_E;
    }
@@ -7673,6 +7709,18 @@ int wc_ecc_check_key(ecc_key* key)
         XMEMSET(b, 0, sizeof(mp_int));
     #endif
 
+    #ifdef WOLFSSL_QNX_CAAM
+    /* NIST P256 keys can be black encrypted ones */
+    if (key->blackKey > 0 && wc_ecc_size(key) == 32) {
+        /* encrypted key was used */
+        #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+        #endif
+        FREE_CURVE_SPECS();
+        return 0;
+    }
+    #endif
+
     /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
     /* pubkey point cannot be at infinity */
     if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
@@ -7994,16 +8042,40 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
     /* private key, d */
     if (d != NULL) {
         if (dLen == NULL ||
-            (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY))
+            (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY)) {
             return BAD_FUNC_ARG;
+        }
 
     #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A)
         /* Hardware cannot export private portion */
         return NOT_COMPILED_IN;
     #else
-        err = wc_export_int(&key->k, d, dLen, keySz, encType);
-        if (err != MP_OKAY)
-            return err;
+        if (encType == WC_TYPE_BLACK_KEY) {
+            #ifdef WOLFSSL_QNX_CAAM
+            if (key->blackKey > 0) {
+                if (*dLen < keySz + WC_CAAM_MAC_SZ) {
+                    *dLen = keySz + WC_CAAM_MAC_SZ;
+                    return BUFFER_E;
+                }
+
+                if (caamReadPartition(key->blackKey, d, keySz + WC_CAAM_MAC_SZ) != 0)
+                    return WC_HW_E;
+
+                *dLen = keySz + WC_CAAM_MAC_SZ;
+            }
+            else {
+                WOLFSSL_MSG("No black key stored in structure");
+                return BAD_FUNC_ARG;
+            }
+            #else
+            return NOT_COMPILED_IN;
+            #endif
+        }
+        else {
+            err = wc_export_int(&key->k, d, dLen, keySz, encType);
+            if (err != MP_OKAY)
+                return err;
+        }
     #endif
     }
 
@@ -8039,6 +8111,14 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
         return BAD_FUNC_ARG;
     }
 
+#ifdef WOLFSSL_QNX_CAAM
+    /* check if black key in secure memory */
+    if (key->blackKey > 0) {
+        return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen,
+            WC_TYPE_BLACK_KEY);
+    }
+#endif
+
     return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen,
         WC_TYPE_UNSIGNED_BIN);
 }
@@ -8150,6 +8230,35 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
         {
             ret = silabs_ecc_import_private(key, key->dp->size);
         }
+#elif defined(WOLFSSL_QNX_CAAM)
+    if ((wc_ecc_size(key) + WC_CAAM_MAC_SZ) == (int)privSz) {
+        int part = caamFindUnusuedPartition();
+        if (part >= 0) {
+            CAAM_ADDRESS vaddr = caamGetPartition(part, privSz*3);
+            if (vaddr == 0) {
+                WOLFSSL_MSG("Unable to get partition");
+                return MEMORY_E;
+            }
+            if (caamWriteToPartition(vaddr, priv, privSz) != 0)
+                return WC_HW_E;
+
+            key->blackKey = (word32)vaddr;
+
+            if (pub != NULL) {
+                /* +1 to account for x963 compressed bit */
+                if (caamWriteToPartition(vaddr + privSz, pub + 1, pubSz - 1) != 0)
+                    return WC_HW_E;
+                key->securePubKey = (word32)vaddr + privSz;
+            }
+        }
+        else {
+            WOLFSSL_MSG("Unable to find an unused partition");
+            return MEMORY_E;
+        }
+    }
+    else {
+        WOLFSSL_MSG("Importing key that is not a black key!");
+        ret = mp_read_unsigned_bin(&key->k, priv, privSz);
     }
 #else
 

+ 12 - 1
wolfcrypt/src/include.am

@@ -64,9 +64,13 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
               wolfcrypt/src/port/xilinx/xil-aesgcm.c \
               wolfcrypt/src/port/caam/caam_aes.c \
               wolfcrypt/src/port/caam/caam_driver.c \
-              wolfcrypt/src/port/caam/caam_init.c \
+              wolfcrypt/src/port/caam/caam_error.c \
               wolfcrypt/src/port/caam/caam_sha.c \
               wolfcrypt/src/port/caam/caam_doc.pdf \
+              wolfcrypt/src/port/caam/wolfcaam_init.c \
+              wolfcrypt/src/port/caam/wolfcaam_qnx.c \
+              wolfcrypt/src/port/caam/wolfcaam_ecdsa.c \
+              wolfcrypt/src/port/caam/wolfcaam_cmac.c \
               wolfcrypt/src/port/silabs/silabs_aes.c \
               wolfcrypt/src/port/silabs/silabs_ecc.c \
               wolfcrypt/src/port/silabs/silabs_hash.c \
@@ -132,3 +136,10 @@ endif
 if BUILD_CRYPTOAUTHLIB
 src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c
 endif
+
+if BUILD_CAAM
+src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_init.c
+src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_qnx.c
+src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_ecdsa.c
+src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_cmac.c
+endif

+ 2 - 1
wolfcrypt/src/md5.c

@@ -174,7 +174,8 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len)
 #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
 #define HAVE_MD5_CUST_API
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
 /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */
 #define HAVE_MD5_CUST_API
 #else

+ 1 - 1
wolfcrypt/src/port/caam/caam_aes.c

@@ -142,7 +142,7 @@ int  wc_AesCbcEncrypt(Aes* aes, byte* out,
         arg[1] = keySz;
         arg[2] = blocks * AES_BLOCK_SIZE;
 
-        if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) {
+        if ((ret = wc_caamAddAndWait(buf, 4, arg, CAAM_AESCBC)) != 0) {
             WOLFSSL_MSG("Error with CAAM AES CBC encrypt");
             return ret;
         }

File diff suppressed because it is too large
+ 629 - 334
wolfcrypt/src/port/caam/caam_driver.c


+ 207 - 0
wolfcrypt/src/port/caam/caam_error.c

@@ -0,0 +1,207 @@
+/* caam_error.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include "caam_driver.h"
+#include "caam_error.h"
+
+/* return a negative value if CAAM reset needed */
+int caamParseCCBError(unsigned int error)
+{
+    int ret = 0;
+    switch((error >> 4) & 0xF) {
+        case 0:
+            WOLFSSL_MSG("\tCHAID: CCB");
+            break;
+
+        case 1:
+            WOLFSSL_MSG("\tCHAID: AESA");
+            break;
+
+        case 2:
+            WOLFSSL_MSG("\tCHAID: DESA");
+            break;
+
+        case 3:
+            WOLFSSL_MSG("\tCHAID: AFHA (ARC4)");
+            break;
+
+        case 4:
+            WOLFSSL_MSG("\tCHAID: MDHA hash");
+            break;
+
+        case 5:
+            WOLFSSL_MSG("\tCHAID: RNG - ERRID:");
+            ret = -1; /* treat RNG errors as fatal */
+            switch(error & 0xF) {
+                case 3:
+                    WOLFSSL_MSG(" RNG instantiate error");
+                    break;
+
+                case 4:
+                    WOLFSSL_MSG(" RNG not instantiated error");
+                    break;
+
+                case 5:
+                    WOLFSSL_MSG(" RNG test instantiate error");
+                    break;
+
+                case 6:
+                    WOLFSSL_MSG(" RNG prediction resistance error");
+                    break;
+
+                default:
+                    WOLFSSL_MSG(" Unknown");
+            }
+            break;
+
+        case 8:
+            WOLFSSL_MSG("\tCHAID: PKHA");
+            break;
+
+        default:
+            WOLFSSL_MSG("\tCHAID: Unknown CCB error");
+    }
+    return ret;
+}
+
+
+/* return a negative value for an error that requires CAAM reset */
+int caamParseDECOError(unsigned int error)
+{
+    int ret = 0;
+    switch (error & 0xFF) {
+        case 0x04:
+            WOLFSSL_MSG("\tInvalid Descriptor Command");
+            break;
+
+        case 0x06:
+            WOLFSSL_MSG("\tInvalid KEY Command");
+            break;
+
+        case 0x07:
+            WOLFSSL_MSG("\tInvalid Load Command");
+            break;
+
+        case 0x08:
+            WOLFSSL_MSG("\tInvalid Store Command");
+            break;
+
+        case 0x09:
+            WOLFSSL_MSG("\tInvalid Operation Command");
+            break;
+
+        case 0x82:
+            WOLFSSL_MSG("\tInvalid PRB setting");
+            break;
+
+        case 0x86:
+            WOLFSSL_MSG("\tVerify ECC/RSA signature fail");
+            break;
+
+        default:
+            WOLFSSL_MSG("\tUnknown error");
+    }
+    return ret;
+}
+
+
+/* return a negative value if CAAM should be reset after error */
+int caamParseError(unsigned int error)
+{
+    int ret = 0;
+
+    /* print out of index of error
+    unsigned int idx;
+    idx = (error >> 8) & 0xFF;
+    printf("idx of error = %d\n", idx);
+    */
+
+    if ((error & 0x40000000) > 0) {
+        WOLFSSL_MSG("[DECO Error]");
+        ret = caamParseDECOError(error);
+    }
+
+    if ((error & 0x20000000) > 0) {
+        WOLFSSL_MSG("[CCB Error]");
+        ret = caamParseCCBError(error);
+    }
+    return ret;
+}
+
+
+/* parses a Job Ring Interrupt Status report
+ * returns 0 if there is no error */
+unsigned int caamParseJRError(unsigned int error)
+{
+    unsigned int err = (error >> 8) & 0x1F;
+
+    if (error & 0x10) {
+        WOLFSSL_MSG("Job Ring Interrupt ENTER_FAIL");
+    }
+
+    if (error & 0x20) {
+        WOLFSSL_MSG("Job Ring Interrupt EXIT_FAIL");
+    }
+
+    switch (err) {
+        case 0x00:
+            /* no error */
+            break;
+
+        case 0x01:
+            WOLFSSL_MSG("Error writing status to output ring");
+            break;
+
+        case 0x03:
+            WOLFSSL_MSG("Bad input ring address");
+            break;
+
+        case 0x04:
+            WOLFSSL_MSG("Bad output ring address");
+            break;
+
+        case 0x05:
+            WOLFSSL_MSG("Fatal, invalid write to input ring");
+            break;
+
+        case 0x06:
+            WOLFSSL_MSG("Invalid write to output ring");
+            break;
+
+        case 0x07:
+            WOLFSSL_MSG("Job ring released before halted");
+            break;
+
+        case 0x08:
+            WOLFSSL_MSG("Removed too many jobs");
+            break;
+
+        case 0x09:
+            WOLFSSL_MSG("Added too many jobs");
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown error");
+            break;
+    }
+    return err;
+}
+

+ 0 - 289
wolfcrypt/src/port/caam/caam_init.c

@@ -1,289 +0,0 @@
-/* caam_init.c
- *
- * Copyright (C) 2006-2020 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-    defined(WOLFSSL_IMX6_CAAM_BLOB)
-
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
-
-#define WC_CAAM_BLOB_SZ 48
-
-#ifndef WC_CAAM_PASSWORD
-    #define WC_CAAM_PASSWORD "!systempassword"
-#endif
-
-#if defined(__INTEGRITY) || defined(INTEGRITY)
-    #include <INTEGRITY.h>
-    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
-    static IODevice caam = NULLIODevice;
-#endif
-
-#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
-#include <stdio.h>
-#include <wolfssl/version.h>
-
-static void wc_caamBanner(void)
-{
-    printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n",
-        LIBWOLFSSL_VERSION_STRING);
-    printf("CAAM Status [0x%8.8x]   = 0x%8.8x\n",
-        CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS));
-    printf("CAAM Version MS Register [0x%8.8x]  = 0x%8.8x\n",
-        CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS));
-    printf("CAAM Version LS Register [0x%8.8x]  = 0x%8.8x\n",
-        CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS));
-    printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n",
-        CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS));
-    printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n",
-        CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS));
-    printf("********************************************************************\n\n");
-}
-#endif
-
-
-/* Allow runtime setting for CAAM IODevice in case user wants to use password
- * at run time.
- *
- * returns 0 on success
- *
- * NOTE this is how IODevice is defined in INTEGRITY "typedef struct
- *      IODeviceStruct        *IODevice;"
- */
-int wc_caamSetResource(IODevice ioDev)
-{
-    WOLFSSL_MSG("Setting CAAM driver");
-    caam = ioDev;
-
-    return 0;
-}
-
-/* Check hardware support
- *
- * returns 0 on success
- */
-int wc_caamInit(void)
-{
-    int    ret;
-    word32 reg;
-
-    /* get the driver up */
-    if (caam == NULLIODevice) {
-        WOLFSSL_MSG("Starting CAAM driver");
-        if ((ret = (int)RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver",
-            WC_CAAM_PASSWORD)) != (int)Success) {
-            WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?");
-            WOLFSSL_LEAVE("wc_caamInit: error from driver = ", ret);
-            ret = 0; /* not a hard failure because user can set resource */
-        }
-    }
-
-#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
-    /* print out CAAM version/info and wolfSSL version */
-    wc_caamBanner();
-#endif
-
-    /* check that for implemented modules
-     * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */
-    reg = WC_CAAM_READ(CAMM_SUPPORT_LS);
-
-    #ifndef WC_NO_RNG
-    if (((reg & 0x000F0000) >> 16) > 0) {
-        WOLFSSL_MSG("Found CAAM RNG hardware module");
-        if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) {
-             WOLFSSL_MSG("Error CAAM RNG has not been set up");
-        }
-    }
-    #endif
-
-    #ifndef NO_SHA256
-    if ((reg & 0x0000F000) > 0) {
-        WOLFSSL_MSG("Found CAAM MDHA module");
-    }
-    else {
-        WOLFSSL_MSG("Hashing not supported by CAAM");
-        return WC_HW_E;
-    }
-    #endif
-
-    #ifndef NO_AES
-    if ((reg & 0x0000000F) > 0) {
-        WOLFSSL_MSG("Found CAAM AES module");
-    }
-    else {
-        WOLFSSL_MSG("AES not supported by CAAM");
-        return WC_HW_E;
-    }
-    #endif
-
-    (void)ret;
-    return 0;
-}
-
-
-int wc_caamFree(void)
-{
-    return 0;
-}
-
-
-word32 wc_caamReadRegister(word32 reg)
-{
-    Value out = 0;
-
-    if (caam == NULLIODevice) {
-         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
-         return 0;
-    }
-
-    if (ReadIODeviceRegister(caam, reg, &out) != Success) {
-         WOLFSSL_MSG("Error reading register\n");
-    }
-
-    return (word32)out;
-}
-
-void wc_caamWriteRegister(word32 reg, word32 value)
-{
-    if (caam == NULLIODevice) {
-         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
-         return;
-    }
-
-    if (WriteIODeviceRegister(caam, reg, value) != Success) {
-         WOLFSSL_MSG("Error writing to register\n");
-    }
-}
-
-
-/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E
- * in the case that the driver is waiting for a resource or RAN_BLOCK_E if
- * waiting for entropy. */
-int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type)
-{
-    int ret;
-    if (caam == NULLIODevice) {
-        WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
-        return WC_HW_E;
-    }
-
-    if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf))
-         != Success) {
-    #if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
-        printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type);
-    #endif
-
-        /* if waiting for resource or RNG return waiting */
-        if (ret == Waiting) {
-            WOLFSSL_MSG("Waiting on entropy from driver");
-            return RAN_BLOCK_E;
-        }
-
-        if (ret == ResourceNotAvailable) {
-            WOLFSSL_MSG("Waiting on CAAM driver");
-            return WC_HW_WAIT_E;
-        }
-
-        return WC_HW_E;
-    }
-
-    (void)ret;
-    return 0;
-}
-
-
-int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
-{
-    Buffer in[3];
-    word32 arg[4];
-    int ret;
-    word32 local[2] = {0,0};
-
-    if (data == NULL || out == NULL || outSz == NULL ||
-            *outSz < dataSz + WC_CAAM_BLOB_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    in[0].BufferType = DataBuffer;
-    in[0].TheAddress = (Address)local;
-    in[0].Length = sizeof(local);
-
-    in[1].BufferType = DataBuffer;
-    in[1].TheAddress = (Address)data;
-    in[1].Length = dataSz;
-
-    in[2].BufferType = DataBuffer | LastBuffer;
-    in[2].TheAddress = (Address)out;
-    in[2].Length = dataSz + WC_CAAM_BLOB_SZ;
-
-    arg[2] = dataSz;
-
-    if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) {
-        WOLFSSL_MSG("Error with CAAM blob create");
-        return ret;
-    }
-
-    *outSz = dataSz + WC_CAAM_BLOB_SZ;
-    return 0;
-}
-
-
-int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
-{
-    Buffer in[3];
-    word32 arg[4];
-    int ret;
-    word32 local[2] = {0,0};
-
-    if (data == NULL || out == NULL || outSz == NULL ||
-            *outSz < dataSz - WC_CAAM_BLOB_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    in[0].BufferType = DataBuffer;
-    in[0].TheAddress = (Address)local;
-    in[0].Length = sizeof(local);
-
-    in[0].BufferType = DataBuffer;
-    in[0].TheAddress = (Address)data;
-    in[0].Length = dataSz;
-
-    in[1].BufferType = DataBuffer | LastBuffer;
-    in[1].TheAddress = (Address)out;
-    in[1].Length = dataSz - WC_CAAM_BLOB_SZ;
-
-    arg[2] = dataSz;
-
-    if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) {
-        WOLFSSL_MSG("Error with CAAM blob create");
-        return ret;
-    }
-
-    *outSz = dataSz - WC_CAAM_BLOB_SZ;
-    return 0;
-}
-
-#endif /* WOLFSSL_IMX6_CAAM */
-

+ 1221 - 0
wolfcrypt/src/port/caam/caam_qnx.c

@@ -0,0 +1,1221 @@
+/* caam_qnx.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include "caam_driver.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>
+
+/* virtual address for accessing CAAM addresses */
+uintptr_t virtual_base = 0;
+
+/* keep track of which ID memory belongs to so it can be free'd up */
+#define MAX_PART 7
+pthread_mutex_t sm_mutex;
+int sm_ownerId[MAX_PART];
+
+/* variables for I/O of resource manager */
+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);
+
+
+/* read the contents at offset from BASE address */
+unsigned int CAAM_READ(unsigned int ofst) {
+    return in32(virtual_base + ofst);
+}
+
+
+/* takes in offset from BASE address */
+void CAAM_WRITE(unsigned int ofst, unsigned int in)
+{
+    out32(virtual_base + ofst, in);
+}
+
+
+/* Sets the base address to use for read/write
+ * returns 0 on success
+ */
+int CAAM_SET_BASEADDR()
+{
+    /* address range for CAAM is CAAM_BASE plus 0x10000 */
+    virtual_base = mmap_device_io(0x00010000, CAAM_BASE);
+    if (virtual_base == (uintptr_t)MAP_FAILED) {
+        WOLFSSL_MSG("Unable to map virtual memory");
+        return -1;
+    }
+    return 0;
+}
+
+
+
+/* convert a virtual address to a physical address
+ * returns the physical address on success
+ */
+unsigned int 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("");
+        #endif
+        }
+        msync(in, inSz, MS_INVALIDATE);
+        count++;
+    } while (ret != 0 && ret == -1 && count < 5);
+
+    return (int)ofst;
+}
+
+
+/* convert a physical address to virtual address
+ * returns the virtual address on success
+ */
+CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int len)
+{
+    void* ret;
+    ret = mmap_device_memory(NULL, len, PROT_READ|PROT_WRITE, 0, in);
+    return (CAAM_ADDRESS)ret;
+}
+
+
+/* map a virtual address to a created coherent physical address
+ * returns the mapped address on success
+ */
+void* CAAM_ADR_MAP(unsigned int 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,
+                    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("");
+    #endif
+    }
+    else {
+        if (copy && in != 0 && inSz > 0) {
+            memcpy((unsigned char*)vaddr, (unsigned char*)in, inSz);
+        }
+
+        if (msync(vaddr, sz, MS_SYNC) != 0) {
+            WOLFSSL_MSG("Failed to sync memory after copy");
+        }
+    }
+    return vaddr;
+}
+
+
+/* un map address, should be called when done with a mapped address */
+void CAAM_ADR_UNMAP(void* vaddr, unsigned int 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
+        /* even though the address was not synced up still try to copy and
+           unmap it */
+    }
+
+    if (copy && outSz > 0) {
+        memcpy((unsigned char*)out, (unsigned char*)vaddr, outSz);
+    }
+    munmap(vaddr, sz);
+}
+
+
+/* syncoronize virtual buffer with physical
+ * return 0 on success */
+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;
+}
+
+
+/* macros for QNX devctl commands */
+#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_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t)
+
+
+/* partAddr is virtual address
+ * partSz   size expected to access
+ *
+ * returns 0 on ok
+ */
+static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz)
+{
+    unsigned int phys;
+
+    phys = CAAM_ADR_TO_PHYSICAL((void*)partAddr, partSz);
+    if (phys < CAAM_PAGE || (phys + partSz) > CAAM_PAGE*7) {
+        WOLFSSL_MSG("error in physical address range");
+        return -1;
+    }
+    return 0;
+}
+
+
+/* return 0 on success */
+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;
+}
+
+
+/* helper function to setup and run CMAC operation
+ * returns EOK on success
+ */
+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];    /* running CMAC context is a constant 32 bytes */
+    unsigned char keybuf[48]; /*max AES key size is 32 + 16 byte black key MAC*/
+    unsigned char *buf = NULL;
+
+    numBuf = 2; /* start with 2 (key + ctx) for case with no msg input */
+    keySz  = args[1];
+    if (args[2] == 1) { /* is it a black key? */
+        keySz = keySz + 16;
+    }
+    SETIOV(&in_iovs[0], keybuf, keySz);
+    SETIOV(&in_iovs[1], ctx, sizeof(ctx));
+    msgSz = args[3];
+
+    /* sanity check that enough data was sent */
+    if ((msgSz + keySz + sizeof(ctx)) > (ctp->size - idx)) {
+        return EOVERFLOW;
+    }
+
+    if (msgSz > 0) {
+        buf = (unsigned char*)malloc(msgSz);
+        if (buf == NULL) {
+            return ECANCELED;
+        }
+        SETIOV(&in_iovs[2], buf, msgSz);
+        numBuf = numBuf + 1; /* increase buffer size by one when adding msg */
+    }
+
+    ret = resmgr_msgreadv(ctp, in_iovs, numBuf, idx);
+    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)
+            free(buf);
+    }
+
+    if (ret != Success) {
+        return EBADMSG;
+    }
+
+    SETIOV(&out_iov, ctx, sizeof(ctx));
+
+    /* extra sanity check that out buffer is large enough */
+    if (sizeof(ctx) > msg->o.nbytes) {
+        return EOVERFLOW;
+    }
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+
+    return EOK;
+}
+
+
+/* helper function to setup and run TRNG operation
+ * returns EOK on success
+ */
+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];
+
+    /* sanity check that length out is not over the edge */
+    if (length > msg->o.nbytes) {
+        WOLFSSL_MSG("Length too large for TRNG out size available");
+        return EOVERFLOW;
+    }
+
+    if (length > 0) {
+        buf = (unsigned char*)malloc(length);
+        if (buf == NULL) {
+            return ECANCELED;
+        }
+
+        ret = caamTRNG(buf, length);
+        if (ret == CAAM_WAITING) {
+            /* waiting for more entropy */
+            free(buf);
+            return EAGAIN;
+        }
+
+        SETIOV(&out_iov, buf, length);
+        resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+        free(buf);
+    }
+    return EOK;
+}
+
+
+/* helper function to setup and run BLOB operation
+ * returns EOK on success
+ */
+static int doBLOB(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
+        unsigned int idx)
+{
+    int WC_CAAM_BLOB_SZ = 48; /* extra blob size from manual */
+    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[16]; /* 16 is max size for keymod
+                               * (8 with red blobs and 16 with black) */
+
+    if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
+        dir = CAAM_BLOB_ENCAP;
+    }
+    else {
+        dir = CAAM_BLOB_DECAP;
+    }
+    inSz = args[2];
+    if (args[0] == 1 && dir == CAAM_BLOB_ENCAP) {
+        /* black blob, add 16 for MAC */
+        inSz = inSz + 16;
+    }
+
+    SETIOV(&in_iovs[0], keymod, args[3]);
+    if ((inSz + args[3]) > (ctp->size - idx)) {
+        return EOVERFLOW;
+    }
+
+    inBuf = (unsigned char*)malloc(inSz);
+    if (inBuf == NULL) {
+        return ECANCELED;
+    }
+    SETIOV(&in_iovs[1], inBuf, inSz);
+    ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
+
+    /* key mod */
+    tmp[0].TheAddress = (CAAM_ADDRESS)keymod;
+    tmp[0].Length = args[3];
+
+    /* input */
+    tmp[1].TheAddress = (CAAM_ADDRESS)inBuf;
+    tmp[1].Length = args[2];
+
+    /* output */
+    outSz = args[2];
+    if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) {
+        outSz = outSz + WC_CAAM_BLOB_SZ;
+    }
+    else {
+        outSz = outSz - WC_CAAM_BLOB_SZ;
+    }
+
+    outBuf = (unsigned char*)malloc(outSz);
+    if (outBuf == NULL) {
+        free(inBuf);
+        return ECANCELED;
+    }
+    tmp[2].TheAddress = (CAAM_ADDRESS)outBuf;
+    tmp[2].Length     = outSz;
+
+    caamDescInit(&desc, dir, args, tmp, 3);
+    ret = caamBlob(&desc);
+    free(inBuf);
+    if (ret != Success) {
+        free(outBuf);
+        return ECANCELED;
+    }
+
+    SETIOV(&out_iov, outBuf, outSz);
+    if (outSz > msg->o.nbytes) {
+        free(outBuf);
+        return EOVERFLOW;
+    }
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+    free(outBuf);
+    return EOK;
+}
+
+
+/* helper function to setup and make ECC key
+ * returns EOK on success
+ */
+static int doECDSA_KEYPAIR(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_iovs[2], out_iovs[3];
+
+    if (((2 * sizeof(CAAM_BUFFER)) > (ctp->size - idx)) ||
+        (((sizeof(int) * 4) + (2 * sizeof(CAAM_BUFFER)))) > msg->o.nbytes) {
+            return EOVERFLOW;
+    }
+
+    SETIOV(&in_iovs[0], &tmp[0], sizeof(CAAM_BUFFER));
+    SETIOV(&in_iovs[1], &tmp[1], sizeof(CAAM_BUFFER));
+    ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
+
+    caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2);
+    ret = caamECDSAMake(&desc, tmp, args);
+    if (ret != Success) {
+        return ECANCELED;
+    }
+
+    SETIOV(&out_iovs[0], &tmp[0], sizeof(CAAM_BUFFER));
+    SETIOV(&out_iovs[1], &tmp[1], sizeof(CAAM_BUFFER));
+    SETIOV(&out_iovs[2], args, sizeof(int) * 4);
+    resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o));
+
+    pthread_mutex_lock(&sm_mutex);
+    sm_ownerId[args[2]] = ctp->rcvid;
+    pthread_mutex_unlock(&sm_mutex);
+
+    return EOK;
+}
+
+
+/* helper function to setup and do ECC verify
+ * returns EOK on success
+ */
+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] == 1) {
+        pubSz = sizeof(CAAM_ADDRESS);
+
+        SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
+    }
+    else {
+        pubSz  = args[3]*2;
+        pubkey = (unsigned char*)malloc(pubSz);
+        if (pubkey == NULL) {
+            return ECANCELED;
+        }
+
+        SETIOV(&in_iovs[0], pubkey, args[3]*2);
+    }
+
+    if (((args[3] * 2) + args[2] + pubSz) > (ctp->size - idx)) {
+        if (pubkey != NULL)
+            free(pubkey);
+        return EOVERFLOW;
+    }
+
+    hash = (unsigned char*)malloc(args[2]);
+    if (hash == NULL) {
+        if (pubkey != NULL)
+            free(pubkey);
+        return ECANCELED;
+    }
+    SETIOV(&in_iovs[1], hash, args[2]);
+
+    r = (unsigned char*)malloc(args[3]);
+    if (r == NULL) {
+        if (pubkey != NULL)
+            free(pubkey);
+        free(hash);
+        return ECANCELED;
+    }
+    SETIOV(&in_iovs[2], r, args[3]);
+
+    s = (unsigned char*)malloc(args[3]);
+    if (s == NULL) {
+        if (pubkey != NULL)
+            free(pubkey);
+        free(hash);
+        free(r);
+        return ECANCELED;
+    }
+    SETIOV(&in_iovs[3], s, args[3]);
+    ret = resmgr_msgreadv(ctp, in_iovs, 4, idx);
+
+    /* setup CAAM buffers to pass to driver */
+    if (args[0] == 1) {
+        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];
+
+    caamDescInit(&desc, CAAM_ECDSA_VERIFY, args, tmp, 4);
+    ret = caamECDSAVerify(&desc, tmp, 4, args);
+
+    /* free all buffers before inspecting the return value */
+    free(hash);
+    free(r);
+    free(s);
+    if (pubkey != NULL)
+        free(pubkey);
+
+    if (ret != Success) {
+        return EBADMSG;
+    }
+    return EOK;
+}
+
+
+/* helper function to setup and do ECC sign
+ * returns EOK on success
+ */
+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] == 1) {
+        keySz = sizeof(CAAM_ADDRESS);
+        SETIOV(&in_iovs[0], &blackKey, sizeof(CAAM_ADDRESS));
+    }
+    else {
+        keySz = args[3];
+        key   = (unsigned char*)malloc(keySz);
+        if (key == NULL) {
+            return ECANCELED;
+        }
+        SETIOV(&in_iovs[0], key, keySz);
+    }
+
+    if ((keySz + args[2]) > (ctp->size - idx)) {
+        if (key != NULL)
+            free(key);
+        return EOVERFLOW;
+    }
+
+    hash = (unsigned char*)malloc(args[2]);
+    if (hash == NULL) {
+        if (key != NULL)
+            free(key);
+        return ECANCELED;
+    }
+    SETIOV(&in_iovs[1], hash, args[2]);
+    ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
+
+    /* setup CAAM buffers to pass to driver */
+    if (args[0] == 1) {
+        tmp[0].TheAddress = blackKey;
+    }
+    else {
+        tmp[0].TheAddress = (CAAM_ADDRESS)key;
+    }
+    tmp[0].Length = args[3];
+
+    tmp[1].TheAddress = (CAAM_ADDRESS)hash;
+    tmp[1].Length = args[2];
+
+    r = (unsigned char*)malloc(args[3]);
+    if (r == NULL) {
+        free(hash);
+        if (key != NULL)
+            free(key);
+        return ECANCELED;
+    }
+    tmp[2].TheAddress = (CAAM_ADDRESS)r;
+    tmp[2].Length = args[3];
+
+    s = (unsigned char*)malloc(args[3]);
+    if (s == NULL) {
+        free(r);
+        free(hash);
+        if (key != NULL)
+            free(key);
+        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);
+
+    free(hash);
+    if (key != NULL)
+        free(key);
+
+    if (ret != Success) {
+        free(s);
+        free(r);
+        return EBADMSG;
+    }
+
+    if ((args[3] * 2) > msg->o.nbytes) {
+        free(s);
+        free(r);
+        return EOVERFLOW;
+    }
+
+    SETIOV(&out_iovs[0], r, args[3]);
+    SETIOV(&out_iovs[1], s, args[3]);
+    resmgr_msgwritev(ctp, &out_iovs[0], 2, sizeof(msg->o));
+
+    free(s);
+    free(r);
+    return EOK;
+}
+
+
+/* helper function to setup and get an ECC shared secret
+ * returns EOK on success
+ */
+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;
+
+    /* when using memory in secure partition just send the address */
+    if (args[1] == 1) {
+        SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS));
+        expectedSz += sizeof(CAAM_ADDRESS);
+    }
+    else {
+        pubkey = (unsigned char*)malloc(args[3]*2);
+        if (pubkey == NULL) {
+            return ECANCELED;
+        }
+
+        SETIOV(&in_iovs[0], pubkey, args[3]*2);
+        expectedSz += args[3]*2;
+    }
+
+    if (args[0] == 1) {
+        SETIOV(&in_iovs[1], &blackKey, sizeof(CAAM_ADDRESS));
+        expectedSz += sizeof(CAAM_ADDRESS);
+    }
+    else {
+        key = (unsigned char*)malloc(args[3]);
+        if (key == NULL) {
+            if (pubkey != NULL)
+                free(pubkey);
+            return ECANCELED;
+        }
+
+        SETIOV(&in_iovs[1], key, args[3]);
+        expectedSz += args[3];
+    }
+
+    if (idx + expectedSz > ctp->size) {
+        if (pubkey != NULL)
+            free(pubkey);
+        if (key != NULL)
+            free(key);
+        return EOVERFLOW;
+    }
+    ret = resmgr_msgreadv(ctp, in_iovs, 2, idx);
+
+    /* setup CAAM buffers to pass to driver */
+    if (args[1] == 1) {
+        tmp[0].TheAddress = securePub;
+    }
+    else {
+        tmp[0].TheAddress = (CAAM_ADDRESS)pubkey;
+    }
+    tmp[0].Length = args[3]*2;
+
+    if (args[0] == 1) {
+        tmp[1].TheAddress = blackKey;
+    }
+    else {
+        tmp[1].TheAddress = (CAAM_ADDRESS)key;
+    }
+    tmp[1].Length = args[3];
+
+    shared = (unsigned char*)malloc(args[3]);
+    if (shared == NULL) {
+        if (pubkey != NULL)
+            free(pubkey);
+        if (key != NULL)
+            free(key);
+        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)
+        free(pubkey);
+    if (key != NULL)
+        free(key);
+
+    if (ret != Success) {
+        free(shared);
+        return EBADMSG;
+    }
+
+    if (args[3] > msg->o.nbytes) {
+        free(shared);
+        return EOVERFLOW;
+    }
+    SETIOV(&out_iov, shared, args[3]);
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+    free(shared);
+    return EOK;
+}
+
+
+/* helper function to setup and cover data
+ * returns EOK on success
+ */
+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;
+
+    if (args[1] > (ctp->size - idx)) {
+        WOLFSSL_MSG("would cause input read overflow");
+        return EOVERFLOW;
+    }
+
+    inBuf = (unsigned char*)malloc(args[1]);
+    if (inBuf == NULL) {
+        return ECANCELED;
+    }
+
+    SETIOV(&in_iov, inBuf, args[1]);
+    ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
+
+    outBuf = (unsigned char*)malloc(args[1] + 16); /* plus 16 for MAC */
+    if (outBuf == NULL) {
+        free(inBuf);
+        return ECANCELED;
+    }
+
+    tmp[0].TheAddress = (CAAM_ADDRESS)inBuf;
+    tmp[0].Length     = args[1];
+    tmp[1].TheAddress = (CAAM_ADDRESS)outBuf;
+    tmp[1].Length     = args[1]; /* tmp1 actually needs an additional 16 bytes
+                                  * for MAC */
+
+    caamDescInit(&desc, CAAM_FIFO_S, args, tmp, 2);
+    ret = caamKeyCover(&desc, 2, args);
+    free(inBuf);
+
+    if (ret != Success) {
+        free(outBuf);
+        return EBADMSG;
+    }
+
+    if (args[1] + 16 > msg->o.nbytes) {
+        free(outBuf);
+        WOLFSSL_MSG("would cause output buffer overflow");
+        return EOVERFLOW;
+    }
+
+    SETIOV(&out_iov, outBuf, args[1] + 16);
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+    free(outBuf);
+    return EOK;
+}
+
+
+/* helper function to get partition
+ * returns EOK on success
+ */
+static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
+        unsigned int idx)
+{
+    int partNumber;
+    int partSz;
+    CAAM_ADDRESS partAddr;
+    iov_t out_iov;
+
+    partNumber = args[0];
+    partSz     = args[1];
+
+    partAddr = caamGetPartition(partNumber, partSz, NULL, 0);
+    SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS));
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+
+    pthread_mutex_lock(&sm_mutex);
+    sm_ownerId[partNumber] = ctp->rcvid;
+    pthread_mutex_unlock(&sm_mutex);
+    return EOK;
+}
+
+
+/* helper function to write to a partition
+ * returns EOK on success
+ */
+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;
+    unsigned char *buf;
+    iov_t in_iov;
+
+    if (args[1] > (ctp->size - idx)) {
+        return EOVERFLOW;
+    }
+
+    buf = (unsigned char*)malloc(args[1]);
+    if (buf == NULL) {
+        return ECANCELED;
+    }
+
+    SETIOV(&in_iov, buf, args[1]);
+    ret = resmgr_msgreadv(ctp, &in_iov, 1, idx);
+    if (ret != args[1]) {
+        free(buf);
+        return EBADMSG;
+    }
+
+    /* get arguments */
+    partAddr = args[0];
+    partSz   = args[1];
+
+    /* sanity check on address and length */
+    if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
+        free(buf);
+        return EBADMSG;
+    }
+
+    memcpy((unsigned int*)partAddr, buf, partSz);
+    return EOK;
+}
+
+
+/* helper function to read a partition
+ * returns EOK on success
+ */
+static int doREAD_PART(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
+        unsigned int idx)
+{
+    int partSz;
+    CAAM_ADDRESS partAddr;
+    unsigned char *buf;
+    iov_t out_iov;
+
+    /* get arguments */
+    partAddr = args[0];
+    partSz   = args[1];
+
+    if (partSz > msg->o.nbytes) {
+        WOLFSSL_MSG("not enough space to store read bytes");
+        return EOVERFLOW;
+    }
+
+    /* sanity check on address and length */
+    if (sanityCheckPartitionAddress(partAddr, partSz) != 0) {
+        return EBADMSG;
+    }
+
+    buf = (unsigned char*)malloc(partSz);
+    if (buf == NULL) {
+        return ECANCELED;
+    }
+    memcpy(buf, (unsigned int*)partAddr, partSz);
+    SETIOV(&out_iov, buf, partSz);
+    resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
+    free(buf);
+    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;
+
+    /* check if at least got the msg header */
+    if( ctp->size < sizeof(msg->i) ) {
+        return EBADMSG;
+    }
+
+    if ((ret = iofunc_devctl_default (ctp, msg, ocb)) != _RESMGR_DEFAULT) {
+        return ret;
+    }
+
+    /* check callers access rights for read/write */
+    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;
+    }
+    /* _IO_DEVCTL_VERIFY_PRIV      : restrict to root */
+    /* _IO_DEVCTL_VERIFY_ACC_ISUID : restrict to owner of device */
+    /* _IO_DEVCTL_VERIFY_ACC_ISGID : restrict to group permissions */
+
+    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_ECDSA_KEYPAIR:
+            ret = doECDSA_KEYPAIR(ctp, msg, args, idx);
+            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);
+            break;
+
+        case WC_CAAM_FREE_PART:
+            caamFreePart(args[0]);
+
+            pthread_mutex_lock(&sm_mutex);
+            sm_ownerId[args[0]] = -1;
+            pthread_mutex_unlock(&sm_mutex);
+            ret = EOK;
+            break;
+
+        case WC_CAAM_FIND_PART:
+            ret = caamFindUnusuedPartition();
+            if (ret < 0) {
+                /* none found, try again later */
+                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");
+
+    /* free up any dangling owned memory */
+    pthread_mutex_lock(&sm_mutex);
+    for (i = 0; i < MAX_PART; i++) {
+        if (sm_ownerId[i] == ctp->rcvid) {
+            sm_ownerId[i] = -1;
+            caamFreePart(i);
+        }
+    }
+    pthread_mutex_unlock(&sm_mutex);
+    return iofunc_close_ocb_default(ctp, reserved, ocb);
+}
+
+
+#if 0
+static int getSupported(char* in)
+{
+        //printf("CAAM Status [0x%8.8x]   = 0x%8.8x\n",
+        //    CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS));
+        printf("CAAM Version MS Register [0x%8.8x]  = 0x%8.8x\n",
+            CAAM_VERSION_MS, CAAM_READ(CAAM_VERSION_MS));
+        printf("CAAM Version LS Register [0x%8.8x]  = 0x%8.8x\n",
+            CAAM_VERSION_LS, CAAM_READ(CAAM_VERSION_LS));
+        printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n",
+            CAMM_SUPPORT_MS, CAAM_READ(CAMM_SUPPORT_MS));
+        printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n",
+            CAMM_SUPPORT_LS, CAAM_READ(CAMM_SUPPORT_LS));
+
+    return strlen(in)+1;
+}
+#endif
+
+char cannedResponse[] = {
+        "wolfCrypt QNX CAAM driver\n"
+        "Supports:\n"
+        "\tAES-CMAC\n"
+        "\tECC (sign, verify, ecdh, keygen)\n"
+        "\tBlobs (black and red)\n"
+};
+
+/* read is only used to get banner info of the driver */
+int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
+{
+    int status;
+
+    /* check callers access rights */
+    if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
+        return (status);
+    }
+
+    /* only support read not pread */
+    if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
+        return (ENOSYS);
+    }
+
+    if (ocb->offset == 0) { /* not doing anything fancy here, just fill up what can */
+        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;
+
+    /* write is not supported */
+    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] = -1;
+    }
+
+    if (InitCAAM() != 0) {
+        WOLFSSL_MSG("unable to start up caam driver!");
+        exit(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) {
+        ctp = dispatch_block(ctp);
+        if (ctp == NULL) {
+            caamJobRingFree();
+            exit (1);
+        }
+        dispatch_handler (ctp);
+    }
+
+    pthread_mutex_destroy(&sm_mutex);
+    caamJobRingFree();
+    return 0;
+}
+

+ 172 - 0
wolfcrypt/src/port/caam/wolfcaam_cmac.c

@@ -0,0 +1,172 @@
+/* wolfcaam_cmac.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM)
+
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h>
+
+/* returns 0 on success */
+int wc_CAAM_Cmac(Cmac* cmac, const byte* key, word32 keySz, const byte* in,
+        word32 inSz, byte* out, word32* outSz, int type, void* ctx)
+{
+    word32 args[4] = {0};
+    CAAM_BUFFER buf[9];
+    word32 idx = 0;
+    byte scratch[AES_BLOCK_SIZE];
+    int ret;
+    int blocks = 0;
+
+    byte* pt = (byte*)in;
+    int   sz = inSz;
+    (void)type;
+
+    args[0] = 0;
+    if (outSz != NULL && *outSz > 16) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (key != NULL || ctx != NULL) {
+        XMEMSET(&cmac->aes, 0, sizeof(Aes));
+        if (ctx != NULL) {
+            cmac->blackKey = 1;
+            XMEMCPY((byte*)cmac->aes.key, (byte*)ctx, keySz + 16);
+        }
+        else {
+            cmac->blackKey = 0;
+            XMEMCPY((byte*)cmac->aes.key, (byte*)key, keySz);
+        }
+        cmac->keylen = keySz;
+        cmac->initialized = 0;
+        cmac->bufferSz = 0;
+        XMEMSET(cmac->buffer, 0, AES_BLOCK_SIZE);
+        return 0;
+    }
+
+    buf[idx].TheAddress = (CAAM_ADDRESS)cmac->aes.key;
+    buf[idx].Length =  cmac->keylen;
+    idx++;
+
+    buf[idx].TheAddress = (CAAM_ADDRESS)cmac->ctx;
+    buf[idx].Length = sizeof(cmac->ctx);
+    idx++;
+
+    if (in != NULL) {
+        args[0] |= CAAM_ALG_UPDATE;
+
+        /* first take care of any left overs */
+        if (cmac->bufferSz > 0) {
+            word32 add = min(sz, AES_BLOCK_SIZE - cmac->bufferSz);
+            XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add);
+
+            cmac->bufferSz += add;
+            pt += add;
+            sz -= add;
+        }
+
+        /* flash out temporary storage for block size if full and more data
+         * is coming, otherwise hold it until final operation */
+        if (cmac->bufferSz == AES_BLOCK_SIZE && (sz > 0)) {
+            buf[idx].TheAddress = (CAAM_ADDRESS)scratch;
+            buf[idx].Length = cmac->bufferSz;
+            idx++;
+            blocks++;
+            cmac->bufferSz = 0;
+            XMEMCPY(scratch, (byte*)cmac->buffer, AES_BLOCK_SIZE);
+        }
+
+        /* In order to trigger read of CTX state there needs to be some data
+         * saved until final call */
+        if ((sz >= AES_BLOCK_SIZE) && (sz % AES_BLOCK_SIZE == 0)) {
+
+            if (cmac->bufferSz > 0) {
+                /* this case should never be hit */
+                return BAD_FUNC_ARG;
+            }
+
+            XMEMCPY(&cmac->buffer[0], pt + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+            cmac->bufferSz = AES_BLOCK_SIZE;
+            sz -= AES_BLOCK_SIZE;
+        }
+
+        if (sz >= AES_BLOCK_SIZE) {
+            buf[idx].TheAddress = (CAAM_ADDRESS)pt;
+            buf[idx].Length = sz - (sz % AES_BLOCK_SIZE);
+            blocks += sz / AES_BLOCK_SIZE;
+            sz -= buf[idx].Length;
+            pt += buf[idx].Length;
+            idx++;
+        }
+
+    }
+
+    if (out != NULL) {
+        /* handle any leftovers */
+        if (cmac->bufferSz > 0) {
+            buf[idx].TheAddress = (CAAM_ADDRESS)cmac->buffer;
+            buf[idx].Length = cmac->bufferSz;
+            idx++;
+        }
+
+        args[0] |= CAAM_ALG_FINAL;
+        blocks++; /* always run on final call */
+    }
+
+    /* set key size */
+    args[1] = cmac->keylen;
+    args[2] = cmac->blackKey;
+
+    /* only call down to CAAM if we have a full block to do or is final */
+    if (blocks > 0) {
+        if (cmac->initialized == 0) {
+            args[0] |= CAAM_ALG_INIT;
+            cmac->initialized = 1;
+        }
+
+        ret = wc_caamAddAndWait(buf, idx, args, CAAM_CMAC);
+        if (ret != 0) {
+            return -1;
+        }
+    }
+
+    if (out != NULL) {
+        XMEMCPY(out, cmac->ctx, *outSz);
+    }
+
+    /* store leftovers */
+    if (sz > 0) {
+        word32 add = min(sz, AES_BLOCK_SIZE - cmac->bufferSz);
+        XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add);
+        cmac->bufferSz += add;
+    }
+
+    return 0;
+}
+
+#endif

+ 466 - 0
wolfcrypt/src/port/caam/wolfcaam_ecdsa.c

@@ -0,0 +1,466 @@
+/* wolfcaam_ecdsa.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM)
+
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h>
+
+#include <wolfssl/wolfcrypt/coding.h>
+#include <wolfssl/wolfcrypt/asn.h>
+
+#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
+#include <stdio.h>
+#endif
+
+/* helper function get the ECDSEL value, this is a value that signals the
+ * hardware to use preloaded curve parameters
+ */
+static word32 GetECDSEL(int curveId, word32 PD_BIT)
+{
+    word32 ecdsel = 0;
+
+    switch (curveId) {
+        case ECC_SECP192R1:
+            ecdsel = (PD_BIT | CAAM_ECDSA_P192);
+            break;
+
+        case ECC_SECP224R1:
+            ecdsel = (PD_BIT | CAAM_ECDSA_P224);
+            break;
+
+        case ECC_CURVE_DEF:
+        case ECC_SECP256R1:
+            ecdsel = (PD_BIT | CAAM_ECDSA_P256);
+            break;
+
+        case ECC_SECP384R1:
+            ecdsel = (PD_BIT | CAAM_ECDSA_P384);
+            break;
+
+        case ECC_SECP521R1:
+            ecdsel = (PD_BIT | CAAM_ECDSA_P521);
+            break;
+
+        default:
+            WOLFSSL_MSG("not using preset curve parameters");
+    }
+
+    return ecdsel;
+}
+
+
+/* create signature using CAAM
+ * returns MP_OKAY on success
+ */
+int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, word32* outlen,
+        WC_RNG *rng, ecc_key *key)
+{
+    const ecc_set_type* dp;
+    word32 args[4] = {0};
+    CAAM_BUFFER buf[9]  = {0};
+    int ret, keySz;
+    word32 ecdsel = 0;
+    byte r[MAX_ECC_BYTES] = {0};
+    byte s[MAX_ECC_BYTES] = {0};
+    word32 outSz;
+    word32 idx = 0;
+
+    byte pk[MAX_ECC_BYTES] = {0};
+
+    (void)rng;
+    if (key->dp != NULL) {
+        dp = key->dp;
+    }
+    else {
+        dp = wc_ecc_get_curve_params(key->idx);
+    }
+
+    if (dp->id != ECC_SECP256R1) {
+        WOLFSSL_MSG("Limiting CAAM to P256 for now");
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    /* check for known predetermined parameters */
+    ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD);
+    if (ecdsel == 0) {
+        WOLFSSL_MSG("Unsupported curve type\n");
+        return BAD_FUNC_ARG;
+    }
+
+    keySz  = wc_ecc_size(key);
+
+    /* private key */
+    if (key->blackKey > 0) {
+        buf[idx].TheAddress = (CAAM_ADDRESS)key->blackKey;
+        buf[idx].Length = keySz;
+        args[0] = 1; /* is a black key */
+    }
+    else {
+        outSz = mp_unsigned_bin_size(&key->k);
+        mp_to_unsigned_bin(&key->k, pk);
+        buf[idx].TheAddress = (CAAM_ADDRESS)pk;
+        buf[idx].Length = outSz;
+        args[0] = 0; /* non black key */
+    }
+    idx++;
+
+    /* hash to sign */
+    buf[idx].TheAddress = (CAAM_ADDRESS)in;
+    buf[idx].Length = inlen;
+    idx++;
+
+    /* r output */
+    buf[idx].TheAddress = (CAAM_ADDRESS)r;
+    buf[idx].Length = keySz;
+    idx++;
+
+    /* s output */
+    buf[idx].TheAddress = (CAAM_ADDRESS)s;
+    buf[idx].Length = keySz;
+    idx++;
+
+    args[1] = ecdsel;
+    args[2] = inlen;
+    args[3] = keySz;
+
+    ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_SIGN);
+    if (ret != 0)
+        return -1;
+
+    /* convert signature from raw bytes to signature format */
+    {
+        mp_int mpr, mps;
+    
+        mp_init(&mpr);
+        mp_init(&mps);
+    
+        mp_read_unsigned_bin(&mpr, r, 32);
+        mp_read_unsigned_bin(&mps, s, 32);
+
+        ret = StoreECC_DSA_Sig(out, outlen, &mpr, &mps);
+        mp_free(&mpr);
+        mp_free(&mps);
+        if (ret != 0) {
+            WOLFSSL_MSG("Issue converting to signature\n");
+            return -1;
+        }
+    }
+
+    return MP_OKAY;
+}
+
+
+/* verify with individual r and s signature parts
+ * returns MP_OKAY on success and sets 'res' to 1 if verified
+ */
+static int wc_CAAM_EccVerify_ex(mp_int* r, mp_int *s, const byte* hash,
+        word32 hashlen, int* res, ecc_key* key)
+{
+    const ecc_set_type* dp;
+    word32 args[4] = {0};
+    CAAM_BUFFER buf[9] = {0};
+    int ret;
+    int rSz, sSz;
+    word32 idx = 0;
+    word32 ecdsel = 0;
+
+    byte rbuf[MAX_ECC_BYTES] = {0};
+    byte sbuf[MAX_ECC_BYTES] = {0};
+
+    byte qx[MAX_ECC_BYTES] = {0};
+    byte qy[MAX_ECC_BYTES] = {0};
+    byte qxy[MAX_ECC_BYTES * 2] = {0};
+    byte tmp[MAX_ECC_BYTES * 2] = {0};
+    word32 qxLen, qyLen;
+
+    if (key->dp != NULL) {
+        dp = key->dp;
+    }
+    else {
+        dp = wc_ecc_get_curve_params(key->idx);
+    }
+
+    /* right now only support P256 @TODO */
+    if (dp->id != ECC_SECP256R1) {
+        WOLFSSL_MSG("Only support P256 verify with CAAM for now");
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    /* check for known predetermined parameters */
+    ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD);
+
+    if (ecdsel == 0) {
+        WOLFSSL_MSG("Curve parameters not supported");
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    /* Wx,y public key */
+    if (key->securePubKey > 0) {
+        int keySz = wc_ecc_size(key);
+
+        buf[idx].TheAddress = (CAAM_ADDRESS)key->securePubKey;
+        buf[idx].Length = keySz * 2;
+        args[0] = 1; /* using public key in secure memory */
+    }
+    else {
+        qxLen = qyLen = MAX_ECC_BYTES;
+        wc_ecc_export_public_raw(key, qx, &qxLen, qy, &qyLen);
+        XMEMCPY(qxy, qx, qxLen);
+        XMEMCPY(qxy+qxLen, qy, qyLen);
+        buf[idx].TheAddress = (CAAM_ADDRESS)qxy;
+        buf[idx].Length = qxLen + qyLen;
+    }
+    idx++;
+
+    buf[idx].TheAddress = (CAAM_ADDRESS)hash;
+    buf[idx].Length = hashlen;
+    idx++;
+
+    rSz = mp_unsigned_bin_size(r);
+    mp_to_unsigned_bin(r, rbuf);
+
+    buf[idx].TheAddress = (CAAM_ADDRESS)rbuf;
+    buf[idx].Length = rSz;
+    idx++;
+
+    sSz = mp_unsigned_bin_size(s);
+    mp_to_unsigned_bin(s, sbuf);
+
+    buf[idx].TheAddress = (CAAM_ADDRESS)sbuf;
+    buf[idx].Length = sSz;
+    idx++;
+
+    /* temporary scratch buffer, the manual calls for it and HW expects it */
+    buf[idx].TheAddress = (CAAM_ADDRESS)tmp;
+    buf[idx].Length = sizeof(tmp);
+    idx++;
+
+    args[1] = ecdsel;
+    args[2] = hashlen;
+    args[3] = wc_ecc_size(key);
+    ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_VERIFY);
+
+    *res = 0;
+    if (ret == 0)
+        *res = 1;
+
+    return MP_OKAY;
+}
+
+
+/* Verify with ASN1 syntax around the signature
+ * returns MP_OKAY on success
+ */
+int wc_CAAM_EccVerify(const byte* sig, word32 siglen, const byte* hash,
+        word32 hashlen, int* res, ecc_key* key)
+{
+    int ret;
+    mp_int r, s;
+
+
+    mp_init(&r);
+    mp_init(&s);
+    DecodeECC_DSA_Sig(sig, siglen, &r, &s);
+    ret = wc_CAAM_EccVerify_ex(&r, &s, hash, hashlen, res, key);
+
+    mp_free(&r);
+    mp_free(&s);
+    return ret;
+}
+
+
+/* Does ECDH operation using CAAM and returns MP_OKAY on success */
+int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out,
+        word32* outlen)
+{
+    const ecc_set_type* dp;
+    word32 args[4] = {0};
+    CAAM_BUFFER buf[9]  = {0};
+    int ret, keySz;
+    word32 ecdsel = 0; /* ecc parameters in hardware */
+    word32 outSz;
+    word32 idx    = 0;
+
+    byte pk[MAX_ECC_BYTES] = {0};
+    byte qx[MAX_ECC_BYTES] = {0};
+    byte qy[MAX_ECC_BYTES] = {0};
+    byte qxy[MAX_ECC_BYTES * 2] = {0};
+    word32 qxSz, qySz;
+
+    if (private_key->dp != NULL) {
+        dp = private_key->dp;
+    }
+    else {
+        dp = wc_ecc_get_curve_params(private_key->idx);
+    }
+
+    if (dp->id != ECC_SECP256R1) {
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    /* check for known predetermined parameters */
+    ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_KEYGEN_PD);
+    if (ecdsel == 0) { /* predefined value not known, loading all parameters */
+        WOLFSSL_MSG("Unsupported curve parameters");
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    keySz = wc_ecc_size(private_key);
+    if (*outlen < (word32)keySz) {
+        WOLFSSL_MSG("out buffer is to small");
+        return BUFFER_E;
+    }
+
+    /* public key */
+    if (public_key->securePubKey > 0) {
+        buf[idx].TheAddress = (CAAM_ADDRESS)public_key->securePubKey;
+        buf[idx].Length = keySz * 2;
+        args[1] = 1; /* using public key with secure memory address */
+    }
+    else {
+        qxSz = qySz = MAX_ECC_BYTES;
+        wc_ecc_export_public_raw(public_key, qx, &qxSz, qy, &qySz);
+        XMEMCPY(qxy, qx, qxSz);
+        XMEMCPY(qxy+qxSz, qy, qySz);
+        buf[idx].TheAddress = (CAAM_ADDRESS)qxy;
+        buf[idx].Length = qxSz + qySz;
+    }
+    idx++;
+
+    /* private key */
+    if (private_key->blackKey > 0) {
+        buf[idx].TheAddress = (CAAM_ADDRESS)private_key->blackKey;
+        buf[idx].Length = keySz;
+        args[0] = 1; /* is a black key */
+    }
+    else {
+        outSz = mp_unsigned_bin_size(&private_key->k);
+        mp_to_unsigned_bin(&private_key->k, pk);
+        buf[idx].TheAddress = (CAAM_ADDRESS)pk;
+        buf[idx].Length = outSz;
+        args[0] = 0; /* non black key */
+    }
+    idx++;
+
+    /* output shared secret */
+    buf[idx].TheAddress = (CAAM_ADDRESS)out;
+    buf[idx].Length = keySz;
+    idx++;
+
+    args[2] = ecdsel;
+    args[3] = keySz;
+    ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_ECDH);
+    if (ret == 0) {
+        *outlen = keySz;
+        return MP_OKAY;
+    }
+    else {
+        return -1;
+    }
+}
+
+
+/* [ private black key ] [ x , y ] */
+int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId)
+{
+    word32 args[4] = {0};
+    CAAM_BUFFER buf[2]  = {0};
+    word32 ecdsel = 0;
+
+    int ret;
+
+    byte s[MAX_ECC_BYTES] = {0};
+    byte xy[MAX_ECC_BYTES*2] = {0};
+
+    key->type = ECC_PRIVATEKEY;
+
+    /* if set to default curve then assume SECP256R1 */
+    if (keySize == 32 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP256R1;
+
+    if (curveId != ECC_SECP256R1) {
+        /* currently only implemented P256 support */
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    ecdsel = GetECDSEL(curveId, CAAM_ECDSA_KEYGEN_PD);
+    if (ecdsel == 0) {
+        WOLFSSL_MSG("unknown key type or size");
+        return CRYPTOCB_UNAVAILABLE;
+    }
+
+    (void)rng;
+
+    buf[0].TheAddress = (CAAM_ADDRESS)s;
+    buf[0].Length     = keySize;
+    buf[1].TheAddress = (CAAM_ADDRESS)xy;
+    buf[1].Length     = keySize*2;
+
+    args[0] = 1; /* Creating Black Key */
+    args[1] = ecdsel;
+
+    ret = wc_caamAddAndWait(buf, 2, args, CAAM_ECDSA_KEYPAIR);
+    if (args[0] == 1 && ret == 0) { 
+        key->blackKey     = (word32)buf[0].TheAddress;
+        key->securePubKey = (word32)buf[1].TheAddress;
+        key->partNum = args[2];
+        return MP_OKAY;
+    }
+    if (args[0] == 0 && ret == 0) {
+        if (wc_ecc_import_unsigned(key, xy, xy + keySize,
+                   s, curveId) != 0) {
+            WOLFSSL_MSG("issue importing key");
+            return -1;
+        }
+        return MP_OKAY;
+    }
+    return -1;
+}
+
+
+/* if dealing with a black encrypted key then it can not be checked */
+int wc_CAAM_EccCheckPrivKey(ecc_key* key, const byte* pubKey, word32 pubKeySz) {
+    (void)pubKey;
+    (void)pubKeySz;
+
+    if (key->dp->id == ECC_SECP256R1 && key->blackKey > 0) {
+        return 0;
+    }
+    return CRYPTOCB_UNAVAILABLE;
+}
+
+#endif /* HAVE_ECC && WOLFSSL_QNX_CAAM */

+ 605 - 0
wolfcrypt/src/port/caam/wolfcaam_init.c

@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB)
+
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+
+#define WC_CAAM_BLOB_SZ 48
+
+/* determine which porting header to include */
+#if defined(__INTEGRITY) || defined(INTEGRITY)
+    #ifndef WC_CAAM_PASSWORD
+        #define WC_CAAM_PASSWORD "!systempassword"
+    #endif
+
+    #include <INTEGRITY.h>
+    static IODevice caam = NULLIODevice;
+    #define CAAM_SEND_REQUEST(type, sz, arg, buf) \
+        SynchronousSendIORequest(caam, (type), (const Value*)(arg), (buf))
+#endif
+
+
+
+#if defined(__INTEGRITY) || defined(INTEGRITY)
+/* Allow runtime setting for CAAM IODevice in case user wants to use password
+ * at run time.
+ *
+ * returns 0 on success
+ *
+ * NOTE this is how IODevice is defined in INTEGRITY "typedef struct
+ *      IODeviceStruct        *IODevice;"
+ */
+int wc_caamSetResource(IODevice ioDev)
+{
+    WOLFSSL_MSG("Setting CAAM driver");
+    caam = ioDev;
+    return 0;
+}
+#endif
+
+
+/* used to route crypto operations through crypto callback */
+static int wc_CAAM_router(int devId, wc_CryptoInfo* info, void* ctx)
+{
+    int ret = CRYPTOCB_UNAVAILABLE;
+
+    (void)ctx;
+    (void)devId;
+    switch (info->algo_type) {
+        case WC_ALGO_TYPE_PK:
+            switch (info->pk.type) {
+                case WC_PK_TYPE_ECDSA_SIGN:
+                    ret = wc_CAAM_EccSign(info->pk.eccsign.in,
+                            info->pk.eccsign.inlen, info->pk.eccsign.out,
+                            info->pk.eccsign.outlen, info->pk.eccsign.rng,
+                            info->pk.eccsign.key);
+                    break;
+
+                case WC_PK_TYPE_ECDSA_VERIFY:
+                    ret = wc_CAAM_EccVerify(info->pk.eccverify.sig,
+                            info->pk.eccverify.siglen, info->pk.eccverify.hash,
+                            info->pk.eccverify.hashlen, info->pk.eccverify.res,
+                            info->pk.eccverify.key);
+                    break;
+
+                case WC_PK_TYPE_EC_KEYGEN:
+                    ret = wc_CAAM_MakeEccKey(info->pk.eckg.rng,
+                            info->pk.eckg.size, info->pk.eckg.key,
+                            info->pk.eckg.curveId);
+                    break;
+
+                case WC_PK_TYPE_ECDH:
+                    ret = wc_CAAM_Ecdh(info->pk.ecdh.private_key,
+                            info->pk.ecdh.public_key, info->pk.ecdh.out,
+                            info->pk.ecdh.outlen);
+                   break;
+
+                case WC_PK_TYPE_EC_CHECK_PRIV_KEY:
+                    ret = wc_CAAM_EccCheckPrivKey(info->pk.ecc_check.key,
+                            info->pk.ecc_check.pubKey,
+                            info->pk.ecc_check.pubKeySz);
+                   break;
+
+                default:
+                    WOLFSSL_MSG("unsupported public key operation");
+            }
+            break;
+
+        case WC_ALGO_TYPE_CMAC:
+        #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && \
+            defined(WOLFSSL_AES_DIRECT)
+            ret = wc_CAAM_Cmac(info->cmac.cmac, info->cmac.key,
+                    info->cmac.keySz, info->cmac.in, info->cmac.inSz,
+                    info->cmac.out, info->cmac.outSz, info->cmac.type,
+                    info->cmac.ctx);
+        #else
+            WOLFSSL_MSG("CMAC not compiled in");
+            ret = NOT_COMPILED_IN;
+        #endif
+            break;
+
+        case WC_ALGO_TYPE_NONE:
+        case WC_ALGO_TYPE_HASH:
+        case WC_ALGO_TYPE_CIPHER:
+        case WC_ALGO_TYPE_RNG:
+        case WC_ALGO_TYPE_SEED:
+        case WC_ALGO_TYPE_HMAC:
+        default:
+            WOLFSSL_MSG("Not implemented yet with CAAM");
+    }
+
+    return ret;
+}
+
+
+/* Check hardware support
+ *
+ * returns 0 on success
+ */
+int wc_caamInit(void)
+{
+    int    ret;
+
+    WOLFSSL_MSG("Starting interface with CAAM driver");
+    if (CAAM_INIT_INTERFACE() != 0) {
+        WOLFSSL_MSG("Error initializing CAAM");
+        return -1;
+    }
+
+#if 0
+    /* check that for implemented modules
+     * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG, 28-31 public key module  */
+    reg = WC_CAAM_READ(CAMM_SUPPORT_LS);
+
+    #ifndef WC_NO_RNG
+    if (((reg & 0x000F0000) >> 16) > 0) {
+        WOLFSSL_MSG("Found CAAM RNG hardware module");
+        if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) {
+             WOLFSSL_MSG("Error CAAM RNG has not been set up");
+        }
+    }
+    #endif
+
+    #ifndef NO_SHA256
+    if ((reg & 0x0000F000) > 0) {
+        WOLFSSL_MSG("Found CAAM MDHA module");
+    }
+    else {
+        WOLFSSL_MSG("Hashing not supported by CAAM");
+        return WC_HW_E;
+    }
+    #endif
+
+    #ifndef NO_AES
+    if ((reg & 0x0000000F) > 0) {
+        WOLFSSL_MSG("Found CAAM AES module");
+    }
+    else {
+        WOLFSSL_MSG("AES not supported by CAAM");
+        return WC_HW_E;
+    }
+    #endif
+
+    #ifdef HAVE_ECC
+    if ((reg & 0xF0000000) > 0) {
+        WOLFSSL_MSG("Found CAAM Public Key module");
+    }
+    else {
+        WOLFSSL_MSG("Public Key not supported by CAAM");
+    }
+    #endif
+#endif
+
+    (void)ret;
+    ret = wc_CryptoDev_RegisterDevice(WOLFSSL_CAAM_DEVID, wc_CAAM_router, NULL);
+    return 0;
+}
+
+
+/* free up all resources used for CAAM */
+int wc_caamFree(void)
+{
+    CAAM_FREE_INTERFACE();
+    return 0;
+}
+
+
+#ifndef WOLFSSL_QNX_CAAM
+word32 wc_caamReadRegister(word32 reg)
+{
+    word32 out = 0;
+
+    if (caam == NULLIODevice) {
+         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+         return 0;
+    }
+
+    if (ReadIODeviceRegister(caam, reg, &out) != Success) {
+         WOLFSSL_MSG("Error reading register\n");
+    }
+
+    return (word32)out;
+}
+
+void wc_caamWriteRegister(word32 reg, word32 value)
+{
+    if (caam == NULLIODevice) {
+         WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+         return;
+    }
+
+    if (WriteIODeviceRegister(caam, reg, value) != Success) {
+         WOLFSSL_MSG("Error writing to register\n");
+    }
+}
+#endif
+
+
+/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E
+ * in the case that the driver is waiting for a resource or RAN_BLOCK_E if
+ * waiting for entropy. */
+int wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4], word32 type)
+{
+    int ret;
+#ifdef DEBUG_WOLFSSL
+    static int wait = 0;
+#endif
+
+#ifndef WOLFSSL_QNX_CAAM
+    if (caam == NULLIODevice) {
+        WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
+        return WC_HW_E;
+    }
+#endif
+
+    if ((ret = CAAM_SEND_REQUEST(type, sz, arg, buf)) != Success) {
+        /* if waiting for resource or RNG return waiting */
+        if (ret == CAAM_WAITING) {
+        #ifdef DEBUG_WOLFSSL
+            if (wait == 0) {
+                wait = 1;
+                WOLFSSL_MSG("Waiting on entropy from driver");
+            }
+            fprintf(stderr, ".");
+        #endif
+            return RAN_BLOCK_E;
+        }
+
+        if (ret == ResourceNotAvailable) {
+            WOLFSSL_MSG("Waiting on CAAM driver");
+            return WC_HW_WAIT_E;
+        }
+
+        return WC_HW_E;
+    }
+#ifdef DEBUG_WOLFSSL
+    if (wait) {
+        wait = 0;
+        fprintf(stderr, "\n");
+    }
+#endif
+
+    (void)ret;
+    return 0;
+}
+
+
+/* Create a red or black blob
+ *
+ * mod : key modifier, expected 8 bytes for RED key types and 16 for BLACK
+ *       if 'mod' is null than 0's are used
+ *
+ * returns 0 on success
+ */
+int wc_caamCreateBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz,
+        int type, byte* mod, word32 modSz)
+{
+    CAAM_BUFFER in[3];
+    word32 arg[4];
+    int ret;
+    byte local[16] = {0};
+    byte* keyMod;
+    int   keyModSz;
+
+    keyMod = mod;
+    XMEMSET(local, 0, sizeof(local));
+    if (data == NULL || out == NULL || outSz == NULL ||
+            *outSz < dataSz + WC_CAAM_BLOB_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (type == WC_CAAM_BLOB_RED) {
+        arg[0] = 0;  
+        if (mod != NULL) {
+            if (modSz != 8) {
+                WOLFSSL_MSG("bad key mod red size");
+                return BAD_FUNC_ARG;
+            }
+        }
+        keyModSz = 8;
+    }
+    else if (type == WC_CAAM_BLOB_BLACK) {
+        arg[0] = 1;
+        if (mod != NULL) {
+            if (modSz != 16) {
+                WOLFSSL_MSG("bad key mod black size");
+                return BAD_FUNC_ARG;
+            }
+        }
+        keyModSz = 16;
+    }
+    else {
+        WOLFSSL_MSG("unknown blob type!");
+        return BAD_FUNC_ARG;
+    }
+
+    if (mod == NULL) {
+        WOLFSSL_MSG("using local all 0's key modifier");
+        keyMod = local;
+    }
+
+    in[0].BufferType = DataBuffer;
+    in[0].TheAddress = (CAAM_ADDRESS)keyMod;
+    in[0].Length = keyModSz;
+
+    in[1].BufferType = DataBuffer;
+    in[1].TheAddress = (CAAM_ADDRESS)data;
+    in[1].Length = dataSz;
+
+    in[2].BufferType = DataBuffer | LastBuffer;
+    in[2].TheAddress = (CAAM_ADDRESS)out;
+    in[2].Length = dataSz + WC_CAAM_BLOB_SZ;
+
+    arg[2] = dataSz;
+    arg[3] = keyModSz;
+
+    if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_ENCAP)) != 0) {
+        WOLFSSL_MSG("Error with CAAM blob create");
+        return ret;
+    }
+
+    *outSz = dataSz + WC_CAAM_BLOB_SZ;
+    return 0;
+}
+
+
+/* create a red key blob
+ * returns 0 on success */
+int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
+{
+    return wc_caamCreateBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED,
+            NULL, 0);
+}
+
+
+/* uncover black or red keys
+ * returns 0 on success */
+int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz,
+        int type, byte* mod, word32 modSz)
+{
+    CAAM_BUFFER in[3];
+    word32      arg[4];
+    int   ret;
+    byte  local[16];
+    byte* keyMod;
+    int   keyModSz;
+
+    keyMod = mod;
+    XMEMSET(local, 0, sizeof(local));
+
+    if (data == NULL || out == NULL || outSz == NULL ||
+            *outSz < dataSz - WC_CAAM_BLOB_SZ) {
+        WOLFSSL_MSG("NULL argument or outSz is too small");
+        return BAD_FUNC_ARG;
+    }
+
+    if (type == WC_CAAM_BLOB_RED) {
+        arg[0] = 0;  
+        if (mod != NULL) {
+            if (modSz != 8) {
+                WOLFSSL_MSG("bad key mod red size");
+                return BAD_FUNC_ARG;
+            }
+        }
+        keyModSz = 8;
+    }
+    else if (type == WC_CAAM_BLOB_BLACK) {
+        arg[0] = 1;
+        if (mod != NULL) {
+            if (modSz != 16) {
+                WOLFSSL_MSG("bad key mod black size");
+                return BAD_FUNC_ARG;
+            }
+        }
+        keyModSz = 16;
+    }
+    else {
+        WOLFSSL_MSG("unknown blob type!");
+        return BAD_FUNC_ARG;
+    }
+
+    if (mod == NULL) {
+        WOLFSSL_MSG("using local all 0's key modifier");
+        keyMod = local;
+    }
+
+    in[0].BufferType = DataBuffer;
+    in[0].TheAddress = (CAAM_ADDRESS)keyMod;
+    in[0].Length = keyModSz;
+
+    in[1].BufferType = DataBuffer;
+    in[1].TheAddress = (CAAM_ADDRESS)data;
+    in[1].Length = dataSz;
+
+    in[2].BufferType = DataBuffer | LastBuffer;
+    in[2].TheAddress = (CAAM_ADDRESS)out;
+    in[2].Length = dataSz - WC_CAAM_BLOB_SZ;
+
+    arg[2] = dataSz;
+    arg[3] = keyModSz;
+
+    if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_DECAP)) != 0) {
+        WOLFSSL_MSG("Error with CAAM blob open");
+        return ret;
+    }
+
+    *outSz = dataSz - WC_CAAM_BLOB_SZ;
+    return 0;
+}
+
+
+/* open a red blob
+ * returns 0 on success */
+int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
+{
+    return wc_caamOpenBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED,
+            NULL, 0);
+}
+
+
+/* outSz gets set to key size plus 16 for mac and padding 
+ * return 0 on success
+ */
+int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, int flag)
+{
+    CAAM_BUFFER buf[2];
+    word32 arg[4];
+    int ret;
+    (void)flag;
+
+    if (*outSz < inSz + WC_CAAM_MAC_SZ) {
+        return BUFFER_E;
+    }
+
+    buf[0].BufferType = DataBuffer;
+    buf[0].TheAddress = (CAAM_ADDRESS)in;
+    buf[0].Length = inSz;
+
+    buf[1].BufferType = DataBuffer;
+    buf[1].TheAddress = (CAAM_ADDRESS)out;
+    buf[1].Length = inSz;
+
+    arg[0] = 0x00140000; /* AES-CCM */
+    arg[1] = inSz;
+    if ((ret = wc_caamAddAndWait(buf, 2, arg, CAAM_FIFO_S)) != 0) {
+        WOLFSSL_MSG("Error with CAAM blob create");
+        return ret;
+    }
+
+    *outSz = inSz + WC_CAAM_MAC_SZ;
+    return 0;
+}
+
+
+int caamFindUnusuedPartition()
+{
+    CAAM_BUFFER buf[1];
+    word32 arg[4];
+    int ret = 0;
+
+    buf[0].BufferType = DataBuffer;
+    buf[0].TheAddress = (CAAM_ADDRESS)&ret;
+    buf[0].Length = sizeof(int);
+
+    if ((wc_caamAddAndWait(buf, 1, arg, CAAM_FIND_PART)) != 0) {
+        WOLFSSL_MSG("Error finding a partition to use");
+        return -1;
+    }
+
+    return ret;
+}
+
+
+CAAM_ADDRESS caamGetPartition(int part, int sz)
+{
+    CAAM_BUFFER buf[1];
+    word32 arg[4];
+    CAAM_ADDRESS ret = 0;
+
+    buf[0].BufferType = DataBuffer;
+    buf[0].TheAddress = (CAAM_ADDRESS)(&ret);
+    buf[0].Length = sizeof(int);
+
+    arg[0] = part;
+    arg[1] = sz;
+
+    if ((wc_caamAddAndWait(buf, 1, arg, CAAM_GET_PART)) != 0) {
+        WOLFSSL_MSG("Error getting a partition");
+        return -1;
+    }
+
+    return ret;
+}
+
+
+/* Internal function to free a secure partition
+ * return 0 on success */
+int caamFreePart(int partNum)
+{
+    word32 arg[4];
+
+    arg[0] = partNum;
+
+    if ((wc_caamAddAndWait(NULL, 0, arg, CAAM_FREE_PART)) != 0) {
+        WOLFSSL_MSG("Error freeing a partition");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* Internal function to help write to a secure partition
+ * return 0 on success */
+int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz)
+{
+    CAAM_BUFFER buf[1];
+    word32 arg[4];
+
+    buf[0].BufferType = DataBuffer;
+    buf[0].TheAddress = (CAAM_ADDRESS)in;
+    buf[0].Length = inSz;
+
+    arg[0] = addr;
+    arg[1] = inSz;
+
+    if ((wc_caamAddAndWait(buf, 1, arg, CAAM_WRITE_PART)) != 0) {
+        WOLFSSL_MSG("Error writing to a partition");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* Internal function to help read from a secure partition
+ * return 0 on success */
+int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz)
+{
+    CAAM_BUFFER buf[1];
+    word32 arg[4];
+
+    buf[0].BufferType = DataBuffer;
+    buf[0].TheAddress = (CAAM_ADDRESS)out;
+    buf[0].Length = outSz;
+
+    arg[0] = addr;
+    arg[1] = outSz;
+
+    if ((wc_caamAddAndWait(buf, 1, arg, CAAM_READ_PART)) != 0) {
+        WOLFSSL_MSG("Error reading a partition");
+        return -1;
+    }
+
+    return 0;
+}
+
+#endif /* WOLFSSL_IMX6_CAAM */
+

+ 349 - 0
wolfcrypt/src/port/caam/wolfcaam_qnx.c

@@ -0,0 +1,349 @@
+/* wolfcaam_qnx.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(WOLFSSL_QNX_CAAM)
+
+#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>
+
+/* for devctl use */
+int caamFd = -1;
+wolfSSL_Mutex caamMutex;
+
+/* return 0 on success */
+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_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t)
+
+#define MAX_IN_IOVS 5
+#define MAX_OUT_IOVS 3
+
+/* Do a synchronous operations and block till done
+ * returns 0 on success */
+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 pubkey, 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:
+        /* set input to get lengths */
+        SETIOV(&in[inIdx], &buf[0], sizeof(CAAM_BUFFER));
+        inIdx = inIdx + 1;
+
+        SETIOV(&in[inIdx], &buf[1], sizeof(CAAM_BUFFER));
+        inIdx = inIdx + 1;
+
+        /* set output to store directly to CAAM_BUFFER's */
+        SETIOV(&out[outIdx], &buf[0], sizeof(CAAM_BUFFER));
+        outIdx = outIdx + 1;
+
+        SETIOV(&out[outIdx], &buf[1], sizeof(CAAM_BUFFER));
+        outIdx = outIdx + 1;
+
+        /* get args for updated partition number used */
+        SETIOV(&out[outIdx], args, sizeof(unsigned int) * 4);
+        outIdx = outIdx + 1;
+
+        cmd = WC_CAAM_ECDSA_KEYPAIR;
+        break;
+
+    case CAAM_ECDSA_VERIFY:
+        /* public key */
+        if (args[0] == 1) {
+            pubkey = buf[0].TheAddress;
+            SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS));
+            inIdx = inIdx + 1;
+        }
+        else {
+            SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
+            inIdx = inIdx + 1;
+        }
+
+        /* msg */
+        SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
+        inIdx = inIdx + 1;
+
+        /* r */
+        SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length);
+        inIdx = inIdx + 1;
+
+        /* s */
+        SETIOV(&in[inIdx], buf[3].TheAddress, buf[3].Length);
+        inIdx = inIdx + 1;
+
+        cmd = WC_CAAM_ECDSA_VERIFY;
+        break;
+
+    case CAAM_ECDSA_SIGN:
+        /* private key */
+        if (args[0] == 1) {
+            privkey = buf[0].TheAddress;
+            SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS));
+            inIdx = inIdx + 1;
+        }
+        else {
+            SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
+            inIdx = inIdx + 1;
+        }
+
+        /* msg */
+        SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
+        inIdx = inIdx + 1;
+
+        /* r out */
+        SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length);
+        outIdx = outIdx + 1;
+
+        /* s out */
+        SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length);
+        outIdx = outIdx + 1;
+
+        cmd = WC_CAAM_ECDSA_SIGN;
+        break;
+
+    case CAAM_ECDSA_ECDH:
+        /* when using memory in secure partition just send the address */
+        if (args[1] == 1) {
+            pubkey = buf[0].TheAddress;
+            SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS));
+            inIdx = inIdx + 1;
+        }
+        else {
+            SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length);
+            inIdx = inIdx + 1;
+        }
+
+        /* private key */
+        if (args[0] == 1) {
+            privkey = buf[1].TheAddress;
+            SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS));
+            inIdx = inIdx + 1;
+        }
+        else {
+            SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length);
+            inIdx = inIdx + 1;
+        }
+
+        /* shared secret */
+        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_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;
+
+            /* get input buffers */
+            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;
+    }
+
+    wc_LockMutex(&caamMutex);
+    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

+ 17 - 13
wolfcrypt/src/random.c

@@ -2306,13 +2306,14 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
 #elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
 
     #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
-    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
 
     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
     {
-        Buffer buf[1];
-        int ret  = 0;
-        int times = 1000, i;
+        unsigned int args[4] = {0};
+        CAAM_BUFFER buf[1];
+        int ret    = 0;
+        int times  = 1000, i; /* 1000 is an arbitrary number chosen */
+        word32 idx = 0;
 
         (void)os;
 
@@ -2320,25 +2321,28 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
             return BUFFER_E;
         }
 
-        buf[0].BufferType = DataBuffer | LastBuffer;
-        buf[0].TheAddress = (Address)output;
-        buf[0].Length     = sz;
-
         /* Check Waiting to make sure entropy is ready */
         for (i = 0; i < times; i++) {
-            ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
-            if (ret == Success) {
-                break;
+            buf[0].BufferType = DataBuffer | LastBuffer;
+            buf[0].TheAddress = (CAAM_ADDRESS)(output + idx);
+            buf[0].Length     = ((sz - idx) < 44)? sz-idx:44;
+
+            args[0] = buf[0].Length;
+            ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY);
+            if (ret == 0) {
+                idx += buf[0].Length;
+                if (idx == sz)
+                    break;
             }
 
             /* driver could be waiting for entropy */
-            if (ret != RAN_BLOCK_E) {
+            if (ret != RAN_BLOCK_E && ret != 0) {
                 return ret;
             }
             usleep(100);
         }
 
-        if (i == times && ret != Success) {
+        if (i == times && ret != 0) {
              return RNG_FAILURE_E;
         }
         else { /* Success case */

+ 2 - 1
wolfcrypt/src/sha.c

@@ -284,7 +284,8 @@
         return ret;
     }
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
     /* wolfcrypt/src/port/caam/caam_sha.c */
 
 #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \

+ 6 - 3
wolfcrypt/src/sha256.c

@@ -177,7 +177,8 @@ where 0 <= L < 2^64.
 
 
 #if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
-    (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \
+    (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH) || \
+     defined(WOLFSSL_QNX_CAAM)) && \
     !defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \
     (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)) && \
     (!defined(WOLFSSL_RENESAS_TSIP_CRYPT) || defined(NO_WOLFSSL_RENESAS_TSIP_HASH)) && \
@@ -583,7 +584,8 @@ static int InitSha256(wc_Sha256* sha256)
         return ret;
     }
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
     /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
 
 #elif defined(WOLFSSL_AFALG_HASH)
@@ -1353,7 +1355,8 @@ static int InitSha256(wc_Sha256* sha256)
         return ret;
     }
 
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
     /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
 
 #elif defined(WOLFSSL_AFALG_HASH)

+ 4 - 2
wolfcrypt/src/sha512.c

@@ -185,7 +185,8 @@
         }
 #endif
 
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
     /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
 
 #elif defined(WOLFSSL_SILABS_SHA384)
@@ -924,7 +925,8 @@ void wc_Sha512Free(wc_Sha512* sha512)
 /* -------------------------------------------------------------------------- */
 #ifdef WOLFSSL_SHA384
 
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
+    !defined(WOLFSSL_QNX_CAAM)
     /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
 
 #elif defined(WOLFSSL_SILABS_SHA512)

+ 2 - 2
wolfcrypt/src/wc_port.c

@@ -71,7 +71,7 @@
 #endif
 
 #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-    defined(WOLFSSL_IMX6_CAAM_BLOB)
+    defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB)
     #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
 #endif
 
@@ -266,7 +266,7 @@ int wolfCrypt_Init(void)
 #endif
 
 #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-    defined(WOLFSSL_IMX6_CAAM_BLOB)
+    defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB)
         if ((ret = wc_caamInit()) != 0) {
             return ret;
         }

+ 17 - 6
wolfcrypt/test/test.c

@@ -495,6 +495,7 @@ WOLFSSL_TEST_SUBROUTINE int mutex_test(void);
 #if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS)
 WOLFSSL_TEST_SUBROUTINE int memcb_test(void);
 #endif
+
 #ifdef WOLFSSL_IMX6_CAAM_BLOB
 WOLFSSL_TEST_SUBROUTINE int blob_test(void);
 #endif
@@ -1331,7 +1332,8 @@ initDefaultName();
 #endif
 
 #if defined(WOLF_CRYPTO_CB) && \
-    !(defined(HAVE_INTEL_QAT_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC))
+    !(defined(HAVE_INTEL_QAT_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC) || \
+      defined(WOLFSSL_QNX_CAAM))
     if ( (ret = cryptocb_test()) != 0)
         return err_sys("crypto callback test failed!\n", ret);
     else
@@ -1424,6 +1426,7 @@ initDefaultName();
         args.argc = argc;
         args.argv = argv;
 #endif
+        wolfSSL_Debugging_ON();
         if ((ret = wolfCrypt_Init()) != 0) {
             printf("wolfCrypt_Init failed %d\n", ret);
             err_sys("Error with wolfCrypt_Init!\n", -1003);
@@ -20178,6 +20181,7 @@ static int ecc_test_vector_item(const eccVector* vector)
             ret = wc_ecc_verify_hash(sig, sigSz, (byte*)vector->msg,
                                                vector->msgLen, &verify, userA);
     } while (ret == WC_PENDING_E);
+
     if (ret != 0)
         goto done;
     TEST_SLEEP();
@@ -20767,7 +20771,8 @@ static int ecc_test_make_pub(WC_RNG* rng)
 #endif /* !NO_ECC256 */
 
     /* create a new key since above test for loading key is not supported */
-#if defined(WOLFSSL_CRYPTOCELL) || defined(NO_ECC256)
+#if defined(WOLFSSL_CRYPTOCELL) || defined(NO_ECC256) || \
+    defined(WOLFSSL_QNX_CAAM)
     ret  = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key);
     if (ret != 0) {
         ERROR_OUT(-9861, done);
@@ -20827,6 +20832,7 @@ static int ecc_test_make_pub(WC_RNG* rng)
         ERROR_OUT(-9866, done);
     }
 
+#ifndef WOLFSSL_QNX_CAAM
     /* make private only key */
     wc_ecc_free(key);
     wc_ecc_init_ex(key, HEAP_HINT, devId);
@@ -20841,6 +20847,7 @@ static int ecc_test_make_pub(WC_RNG* rng)
     if (ret == 0) {
         ERROR_OUT(-9868, done);
     }
+#endif /* WOLFSSL_QNX_CAAM */
 
     /* make public key for shared secret */
     wc_ecc_init_ex(pub, HEAP_HINT, devId);
@@ -21858,7 +21865,9 @@ static int ecc_sig_test(WC_RNG* rng, ecc_key* key)
 #endif
 
 #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \
-    !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A)
+    !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
+    !defined(WOLFSSL_QNX_CAAM)
+
 static int ecc_exp_imp_test(ecc_key* key)
 {
     int        ret;
@@ -21988,7 +21997,7 @@ done:
 #endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */
 
 #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
-    !defined(WOLFSSL_CRYPTOCELL)
+    !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_QNX_CAAM)
 #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT)
 static int ecc_mulmod_test(ecc_key* key1)
 {
@@ -22146,13 +22155,14 @@ static int ecc_def_curve_test(WC_RNG *rng)
         goto done;
 #endif
 #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \
-    !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A)
+    !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
+    !defined(WOLFSSL_QNX_CAAM)
     ret = ecc_exp_imp_test(key);
     if (ret < 0)
         goto done;
 #endif
 #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
-    !defined(WOLFSSL_CRYPTOCELL)
+    !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_QNX_CAAM)
 #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT)
     ret = ecc_mulmod_test(key);
     if (ret < 0)
@@ -34038,6 +34048,7 @@ WOLFSSL_TEST_SUBROUTINE int blob_test(void)
 
 
     XMEMSET(blob, 0, sizeof(blob));
+    XMEMSET(out, 0, sizeof(out));
     outSz = sizeof(blob);
     ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz);
     if (ret != 0) {

+ 7 - 0
wolfssl/wolfcrypt/cmac.h

@@ -53,6 +53,13 @@ struct Cmac {
     byte k2[AES_BLOCK_SIZE];
     word32 bufferSz;
     word32 totalSz;
+#if defined(WOLF_CRYPTO_CB)
+    int devId;
+    byte ctx[32]; /* hold state for save and return */
+    word32 blackKey;
+    word32 keylen;
+    byte   initialized;
+#endif
 };
 
 

+ 22 - 0
wolfssl/wolfcrypt/cryptocb.h

@@ -58,6 +58,9 @@
 #ifndef NO_DES3
     #include <wolfssl/wolfcrypt/des3.h>
 #endif
+#ifdef WOLFSSL_CMAC
+    #include <wolfssl/wolfcrypt/cmac.h>
+#endif
 
 
 /* Crypto Information Structure for callbacks */
@@ -216,6 +219,19 @@ typedef struct wc_CryptoInfo {
         word32 sz;
     } seed;
 #endif
+#ifdef WOLFSSL_CMAC
+    struct {
+        Cmac* cmac;
+        void* ctx;
+        const byte* key;
+        const byte* in;
+        byte*       out;
+        word32* outSz;
+        word32  keySz;
+        word32  inSz;
+        int type;
+    } cmac;
+#endif
 } wc_CryptoInfo;
 
 
@@ -306,6 +322,12 @@ WOLFSSL_LOCAL int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz);
 WOLFSSL_LOCAL int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz);
 #endif
 
+#ifdef WOLFSSL_CMAC
+WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
+        const byte* in, word32 inSz, byte* out, word32* outSz, int type,
+        void* ctx);
+#endif
+
 #endif /* WOLF_CRYPTO_CB */
 
 #ifdef __cplusplus

+ 6 - 0
wolfssl/wolfcrypt/ecc.h

@@ -397,6 +397,12 @@ struct ecc_key {
     void* heap;         /* heap hint */
     ecc_point pubkey;   /* public key */
     mp_int    k;        /* private key */
+
+#ifdef WOLFSSL_QNX_CAAM
+    word32 blackKey;     /* address of key encrypted and in secure memory */
+    word32 securePubKey; /* address of public key in secure memory */
+    int    partNum; /* partition number*/
+#endif
 #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A)
     int  slot;        /* Key Slot Number (-1 unknown) */
     byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE];

+ 5 - 0
wolfssl/wolfcrypt/include.am

@@ -78,8 +78,13 @@ noinst_HEADERS+= \
                          wolfssl/wolfcrypt/port/nxp/dcp_port.h \
                          wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \
                          wolfssl/wolfcrypt/port/caam/caam_driver.h \
+                         wolfssl/wolfcrypt/port/caam/caam_error.h \
+                         wolfssl/wolfcrypt/port/caam/caam_qnx.h \
                          wolfssl/wolfcrypt/port/caam/wolfcaam.h \
                          wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \
+                         wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h \
+                         wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h \
+                         wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h \
                          wolfssl/wolfcrypt/port/silabs/silabs_aes.h \
                          wolfssl/wolfcrypt/port/silabs/silabs_ecc.h \
                          wolfssl/wolfcrypt/port/silabs/silabs_hash.h \

+ 1 - 1
wolfssl/wolfcrypt/md5.h

@@ -71,7 +71,7 @@ enum {
 
 #ifdef WOLFSSL_TI_HASH
     #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
-#elif defined(WOLFSSL_IMX6_CAAM)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM)
     #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
 #else
 

+ 232 - 37
wolfssl/wolfcrypt/port/caam/caam_driver.h

@@ -22,11 +22,25 @@
 #ifndef CAAM_DRIVER_H
 #define CAAM_DRIVER_H
 
-#define CAAM_BASE 0xf2100000
+#if (defined(__QNX__) || defined(__QNXNTO__))
+    int InitCAAM(void);
+    #include "caam_qnx.h"
+#endif
+#if (defined(__INTEGRITY) || defined(INTEGRITY))
+    #define CAAM_BASE 0xf2100000
+    #define CAAM_PAGE 0xf0100000
+#endif
+
 
-#define CAAM_PAGE 0xf0100000
 #define CAAM_PAGE_MAX 6
 
+/* max size of 64 word32's */
+#define CAAM_DESC_MAX 256
+
+#ifndef CAAM_JOBRING_SIZE
+#define CAAM_JOBRING_SIZE 1
+#endif
+
 /******************************************************************************
   Basic Descriptors
   ****************************************************************************/
@@ -50,12 +64,16 @@
 #define CAAM_HEAD        0xB0800000
 #define CAAM_NWB         0x00200000
 
+    /* PROTOCOL OPERATION command */
+#define CAAM_PROT_UNIDI 0
 #define CAAM_BLOB_ENCAP 0x07000000
 #define CAAM_BLOB_DECAP 0x06000000
+#define CAAM_PKHA_OP    0x01000000
+
 #define CAAM_OPID_BLOB  0x000D0000
 
 /* algorithms modes and types */
-#define CAAM_CLASS1 0x02000000/* i.e. AES */
+#define CAAM_CLASS1 0x02000000/* i.e. AES, PKHA */
 #define CAAM_CLASS2 0x04000000/* i.e. hash algos */
 
 #define CAAM_ENC    0x00000001
@@ -90,6 +108,38 @@
 #define CAAM_HMAC_SHA384 0x00440010
 #define CAAM_HMAC_SHA512 0x00450010
 
+/* ECDSA ECDSEL (pre defined flags for ECDSA parameters i.e. order) */
+#define CAAM_ECDSEL_SHIFT 7
+#define CAAM_ECDSA_PD 0x00400000
+#define CAAM_ECDSA_KEYGEN_PD 0x02000000
+#define CAAM_ECDSA_P192 (0x00 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P224 (0x01 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P256 (0x02 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P384 (0x03 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P521 (0x04 << CAAM_ECDSEL_SHIFT)
+
+#define CAAM_ECDSA_BRAINPOOL_P256 (0x0B << CAAM_ECDSEL_SHIFT)
+
+    /* PKHA Operation ID ECDSA */
+#define CAAM_ECDSA_KEYPAIR 0x00140000
+#define CAAM_ECDSA_SIGN    0x00150000
+#define CAAM_ECDSA_VERIFY  0x00160000
+#define CAAM_ECDSA_ECDH    0x00170000
+
+#define CAAM_ECDSA_MESREP_HASHED (0x10 << 7)
+
+    /* key encryption bit */
+#define CAAM_PKHA_ECC 0x00000002
+#define CAAM_PKHA_ENC_PRI_AESCBC 0x00000004
+#define CAAM_PKHA_ENC_PRI_AESCCM (0x00000010 | CAAM_PKHA_ENC_PRI_AESCBC)
+#define CAAM_PKHA_NO_TIMING_RESISTANCE 0x40000000
+#define CAAM_LOAD_BLACK_KEY 0x500000
+
+    /* PKHA RSA */
+#define CAAM_OPID_RSA_ENCRYPT 0x00180000
+#define CAAM_OPID_RSA_DECRYPT 0x00190000
+
+
 #define CAAM_MD5_CTXSZ (16 + 8)
 #define CAAM_SHA_CTXSZ (20 + 8)
 #define CAAM_SHA224_CTXSZ (32 + 8)
@@ -117,16 +167,18 @@
 #define CAAM_PAGE_SZ 4096
 
 /* RNG Registers */
-#define CAAM_RTMCTL      CAAM_BASE + 0X0600
-#define CAAM_RTSDCTL     CAAM_BASE + 0X0610
-#define CAAM_RTFRQMIN    CAAM_BASE + 0X0618
-#define CAAM_RTFRQMAX    CAAM_BASE + 0X061C
-#define CAAM_RDSTA       CAAM_BASE + 0X06C0
-#define CAAM_RTSTATUS    CAAM_BASE + 0x063C
+#define CAAM_RTMCTL      0X0600
+#define CAAM_RTSDCTL     0X0610
+#define CAAM_RTFRQMIN    0X0618
+#define CAAM_RTFRQMAX    0X061C
+#define CAAM_RDSTA       0X06C0
+#define CAAM_RTSTATUS    0x063C
+#define CAAM_RDINT0      0x06D0
 
 /* each of the following 11 RTENT registers are an offset of 4 from RTENT0 */
-#define CAAM_RTENT0      CAAM_BASE + 0x0640
-#define CAAM_RTENT11     CAAM_BASE + 0x066C /* Max RTENT register */
+#define CAAM_RTENT0      0x0640
+#define CAAM_RTENT11     0x066C /* Max RTENT register */
+#define CAAM_RTENT_MAX   0x067C
 
 /* RNG Masks/Values */
 #ifndef CAAM_ENT_DLY
@@ -138,50 +190,193 @@
 #define CAAM_ENTVAL    0x00000400 /* checking RTMCTL for entropy ready */
 
 /* Input Job Ring Registers */
-#define CAAM_IRBAR0      CAAM_BASE + 0x1004
-#define CAAM_IRSR0       CAAM_BASE + 0x100C
-#define CAAM_IRJAR0      CAAM_BASE + 0x101C
+#define CAAM_IRBAR0      0x1004
+    //0x1004
+#define CAAM_IRSR0       0x100C
+#define CAAM_IRJAR0      0x101C
+
+#define CAAM_IRBAR2      0x3000
+#define CAAM_IRSR2       0x300C
+#define CAAM_IRJAR2      0x301C
+#define CAAM_IRSAR_JR2   0x3014
+
+
 
 /* Output Job Ring Registers */
-#define CAAM_ORBAR0      CAAM_BASE + 0x1024
-#define CAAM_ORSR0       CAAM_BASE + 0x102C
-#define CAAM_ORJAR0      CAAM_BASE + 0x103C
+#define CAAM_ORBAR0      0x1024
+    //0x1024
+#define CAAM_ORSR0       0x102C
+#define CAAM_ORJAR0      0x103C
 
 
-/* Status Registers */
-#define CAAM_STATUS      CAAM_BASE + 0x0FD4
-#define CAAM_VERSION_MS  CAAM_BASE + 0x0FE8
-#define CAAM_VERSION_LS  CAAM_BASE + 0x0FEC
-#define CAMM_SUPPORT_MS  CAAM_BASE + 0x0FF0
-#define CAMM_SUPPORT_LS  CAAM_BASE + 0x0FF4
+#define CAAM_ORBAR2      0x3024
+    //0x1024
+#define CAAM_ORSR2       0x302C
+#define CAAM_ORJAR2      0x303C
 
+#define JRCFGR_JR0_LS    0x1054
 
-#define CAAM_C1DSR_LS    CAAM_BASE + 0x8014
-#define CAAM_C1MR        CAAM_BASE + 0x8004
+/* Status Registers */
+#define CAAM_STATUS      0x0FD4
+#define CAAM_VERSION_MS  0x0FE8
+#define CAAM_VERSION_LS  0x0FEC
+#define CAMM_SUPPORT_MS  0x0FF0
+#define CAMM_SUPPORT_LS  0x0FF4
+
+#define CAAM_SM_CMD 0x1BE4
+#define CAAM_SM_SMPO 0x1FBC
+#define CAAM_SM_SMVID_MS 0x1FD8
+#define CAAM_SM_SMVID_LS 0x1FDC
+#define CAAM_SM_STATUS 0x1BEC
+#define CAAM_SM_CSP   0x00008000
+#define CAAM_SM_SMAP_LOCK 0x00002000
+#define CAAM_SM_SMAG_LOCK 0x00001000
+#define CAAM_SM_ALL_RW 0x000000FF
+
+#define CAAM_C1DSR_LS    0x8014
+#define CAAM_C1MR        0x8004
 
 
 /* output FIFO  is 16 entries deep and each entry has a two 4 byte registers */
-#define CAAM_FIFOO_MS    CAAM_BASE + 0x87F0
-#define CAAM_FIFOO_LS    CAAM_BASE + 0x87F4
+#define CAAM_FIFOO_MS    0x87F0
+#define CAAM_FIFOO_LS    0x87F4
 
 /* input FIFO is 16 entries deep with each entry having two 4 byte registers
    All data written to it from IP bus should be in big endian format */
-#define CAAM_FIFOI_LS    CAAM_BASE + 0x87E0
+#define CAAM_FIFOI_LS    0x87E0
 
 /* offset of 4 with range 0 .. 13 */
-#define CAAM_CTX1        CAAM_BASE + 0x8100
+#define CAAM_CTX1        0x8100
 #define CAAM_CTRIV       CAAM_CTX1 + 8 /* AES-CTR iv is in 2 and 3 */
 #define CAAM_CBCIV       CAAM_CTX1     /* AES-CBC iv is in 1 and 2 */
 
 
-/* instantiate RNG and create JDKEK, TDKEK, and TDSK key */
-static unsigned int wc_rng_start[] = {
-    CAAM_HEAD | 0x00000006,
-    CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0 with TRNG */
-    CAAM_JUMP | 0x02000001,  /* wait for Class1 RNG and jump to next cmd */
-    CAAM_LOAD | 0x00880004,  /* Load to clear written register */
-    0x00000001, /* reset done interrupt */
-    CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000   /* Generate secure keys */
+    /* debugging registers */
+#define CAAM_DECORR 0x009C /* used to set DECO into debug mode */
+#define CAAM_DODJR  0x8E00 /* for hung operations */
+#define CAAM_DOJQCR_MS 0x8800
+#define CAAM_DOOPSTA_MS 0x8810 /* DECO operation status register */
+#define CAAM_DODAR  0x8808 /* address of current descriptor */
+#define CAAM_DODESB 0x8A00 /* 64 registers that hold the current descriptor buffer */
+
+
+#define JRINTR_JR0 0x104C
+#define JRINTR_JR1 0x204C
+#define JRINTR_JR2 0x304C
+
+#define CAAM_SINGLE_STEP_MODE 0x40000000
+#define CAAM_STEP 0x80000000
+
+/* Port layer for CAAM driver, functions defined in caam_<env>.c */
+unsigned int CAAM_READ(unsigned int reg);
+void CAAM_WRITE(unsigned int reg, unsigned int in);
+int CAAM_SET_BASEADDR(void);
+unsigned int CAAM_ADR_TO_PHYSICAL(void* in, int inSz);
+void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy);
+void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz,
+        unsigned char copy);
+int CAAM_ADR_SYNC(void* vaddr, int sz);
+CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int length);
+
+
+
+    #ifndef WOLFSSL_CAAM_BUFFER
+    #define WOLFSSL_CAAM_BUFFER
+    typedef struct CAAM_BUFFER {
+        int BufferType;
+        CAAM_ADDRESS TheAddress;
+        int Length;
+    } CAAM_BUFFER;
+    #endif
+    unsigned int caamReadRegister(unsigned int reg);
+    void caamWriteRegister(unsigned int reg, unsigned int in);
+    int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, int sz);
+    int caamJobRingFree(void);
+
+
+/* Driver API that can be called by caam_<env>.c port layers */
+typedef struct DESCSTRUCT DESCSTRUCT;
+
+int caamKeyCover(DESCSTRUCT *desc, int sz, unsigned int args[4]);
+int caamTRNG(unsigned char *out, int outSz);
+int caamECDSA_ECDH(DESCSTRUCT *desc, int sz, unsigned int args[4]);
+int caamECDSASign(DESCSTRUCT *desc, int sz, unsigned int args[4]);
+int caamECDSAVerify(DESCSTRUCT *desc, CAAM_BUFFER *buf, int sz,
+        unsigned int args[4]);
+int caamECDSAMake(DESCSTRUCT *desc, CAAM_BUFFER *buf, unsigned int args[4]);
+
+
+int caamAesCmac(DESCSTRUCT *desc, int sz, unsigned int args[4]);
+int caamBlob(DESCSTRUCT *desc);
+
+CAAM_ADDRESS caamGetPartition(int part, int partSz, unsigned int* phys,
+        unsigned int flag);
+int caamFreePart(int part);
+int caamFindUnusuedPartition(void);
+
+
+
+void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4],
+        CAAM_BUFFER* buf, int sz);
+
+
+/* CAAM descriptor */
+#define DESC_COUNT 1
+#define MAX_BUF 20
+#define BUFFER_COUNT (MAX_BUF * DESC_COUNT)
+
+/* CAAM descriptors can only be 64 unsigned ints */
+#define MAX_DESC_SZ 64
+
+/* 64 byte buffer for when data crosses a page boundary */
+#define ALIGN_BUF 16
+
+/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */
+#define MAX_CTX 18
+
+#define MIN_READ_REG CAAM_BASE
+#define MAX_READ_REG (CAAM_BASE + 0x00010000)
+
+struct buffer {
+    CAAM_ADDRESS data;
+    CAAM_ADDRESS dataSz;
+};
+
+struct DESCSTRUCT {
+#if defined(__INTEGRITY) || defined(INTEGRITY)
+    struct IORequestStruct TheIORequest;
+#endif
+    struct CAAM_DEVICE*    caam;
+    struct buffer          buf[MAX_BUF]; /* buffers holding data input address */
+    unsigned int           desc[MAX_DESC_SZ]; /* max size of 64 word32 */
+    unsigned int           aadSzBuf[4];       /* Formatted AAD size for CCM */
+    unsigned int           alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page
+                                                   align */
+    unsigned int           iv[MAX_CTX]; /* AES IV and also hash state */
+    unsigned int           ctxBuf[MAX_CTX]; /* key */
+    CAAM_ADDRESS           output; /* address to output buffer */
+    CAAM_ADDRESS           ctxOut; /* address to update buffer holding state */
+    Value                  alignIdx;/* index for align buffer */
+    Value                  idx;     /* index for descriptor buffer */
+    Value                  headIdx; /* for first portion of descriptor buffer */
+    Value                  lastIdx; /* for last portion of descriptor buffer */
+    Value                  outputIdx; /* idx to output buffer in "buf" */
+    Value                  inputSz;   /* size of input buffer */
+    Value                  ctxSz;     /* size of CTX/Key buffer */
+    Value                  aadSz;     /* AAD size for CCM */
+    Value                  startIdx;  /* for telling header where to start */
+    Value                  lastFifo;
+    Value                  type;
+    Value                  state;
+    Value                  DescriptorCount;
+    Boolean                running; /* True if building/running descriptor is
+                                       in process */
 };
 
+/* wolfSSL specific flags */
+#define CAAM_FIND_PART 0xFFFFFFFF
+#define CAAM_GET_PART 0xFFFFFFFE
+#define CAAM_FREE_PART 0xFFFFFFFD
+#define CAAM_READ_PART 0xFFFFFFFC
+#define CAAM_WRITE_PART 0xFFFFFFFB
 #endif /* CAAM_DRIVER_H */

+ 29 - 0
wolfssl/wolfcrypt/port/caam/caam_error.h

@@ -0,0 +1,29 @@
+/* caam_error.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef CAAM_ERROR_H
+#define CAAM_ERROR_H
+
+int caamParseError(unsigned int error);
+int caamParseDECOError(unsigned int error);
+int caamParseCCBError(unsigned int error);
+unsigned int caamParseJRError(unsigned int error);
+#endif /* CAAM_ERROR_H */

+ 70 - 0
wolfssl/wolfcrypt/port/caam/caam_qnx.h

@@ -0,0 +1,70 @@
+/* caam_qnx.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* This file is porting low level QNX interactions, such as reading register */
+
+#ifndef CAAM_QNX_H
+#define CAAM_QNX_H
+
+#define WOLFSSL_MSG(in)
+
+#include <sys/mman.h>
+#include <hw/inout.h>
+#include <sys/iofunc.h>
+#include <sys/neutrino.h>
+#include <pthread.h>
+
+#define CAAM_MUTEX pthread_mutex_t
+#define CAAM_INIT_MUTEX(x) pthread_mutex_init((x), NULL)
+#define CAAM_FREE_MUTEX(x) pthread_mutex_destroy((x))
+#define CAAM_LOCK_MUTEX(x) pthread_mutex_lock((x))
+#define CAAM_UNLOCK_MUTEX(x) pthread_mutex_unlock((x))
+
+#define Error int
+#define Value int
+#define Boolean int
+#define CAAM_ADDRESS unsigned int
+#define Success 1
+#define Failure 0
+#define INTERRUPT_Panic()
+#define MemoryMapMayNotBeEmpty -1
+#define CAAM_WAITING -2
+#define NoActivityReady -1
+#define MemoryOperationNotPerformed -1
+
+#ifndef WOLFSSL_CAAM_BUFFER
+#define WOLFSSL_CAAM_BUFFER
+    typedef struct CAAM_BUFFER {
+        int BufferType;
+        CAAM_ADDRESS TheAddress;
+        int Length;
+    } CAAM_BUFFER;
+#endif
+
+/* check kernel and yield to same priority threads waiting */
+#define CAAM_CPU_CHILL() sched_yield()
+
+/* IMX6UL */
+#define CAAM_BASE 0x02140000
+#define CAAM_PAGE 0x00100000
+
+#endif /* CAAM_QNX_H */

+ 94 - 9
wolfssl/wolfcrypt/port/caam/wolfcaam.h

@@ -23,13 +23,20 @@
 #define WOLF_CRYPT_CAAM_INIT_H
 
 #include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/types.h>
 
-#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)
+/* include for porting layer */
+#ifdef WOLFSSL_QNX_CAAM
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h>
+#endif
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_QNX_CAAM)
 
-#include <wolfssl/wolfcrypt/types.h>
 
 #if defined(__INTEGRITY) || defined(INTEGRITY)
     #include <INTEGRITY.h>
+    typedef Buffer CAAM_BUFFER;
 #endif
 
 WOLFSSL_LOCAL int wc_caamInit(void);
@@ -39,25 +46,103 @@ WOLFSSL_LOCAL int wc_caamFreeRng(void);
 
 WOLFSSL_LOCAL word32 wc_caamReadRegister(word32 reg);
 WOLFSSL_LOCAL void wc_caamWriteRegister(word32 reg, word32 value);
-WOLFSSL_LOCAL int  wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type);
+WOLFSSL_LOCAL int  wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4],
+        word32 type);
 
-WOLFSSL_API int wc_caamSetResource(IODevice ioDev);
+WOLFSSL_LOCAL int caamFindUnusuedPartition(void);
+WOLFSSL_LOCAL CAAM_ADDRESS caamGetPartition(int part, int sz);
+WOLFSSL_LOCAL int caamFreePart(int partNum);
+WOLFSSL_LOCAL int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz);
+WOLFSSL_LOCAL int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz);
 
 WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out,
 	word32* outSz);
 WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out,
 	word32* outSz);
 
+WOLFSSL_API int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out,
+        word32* outSz, int type, byte* mod, word32 modSz);
+WOLFSSL_API int wc_caamCreateBlob_ex(byte* data, word32 dataSz, byte* out,
+        word32* outSz, int type, byte* mod, word32 modSz);
+WOLFSSL_API int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz,
+        int flag);
+
 /* additional size that is added by CAAM when creating a blob */
 #define WC_CAAM_BLOB_SZ 48
+#define WC_CAAM_MAC_SZ 16
+#define WC_CAAM_BLOB_RED   1
+#define WC_CAAM_BLOB_BLACK 2
 
-#ifndef WC_CAAM_READ
-    #define WC_CAAM_READ(reg)      wc_caamReadRegister((reg))
-#endif
-#ifndef WC_CAAM_WRITE
-    #define WC_CAAM_WRITE(reg, x)  wc_caamWriteRegister((reg), (x))
+#ifndef WOLFSSL_QNX_CAAM
+    WOLFSSL_API int wc_caamSetResource(IODevice ioDev);
+    #ifndef WC_CAAM_READ
+        #define WC_CAAM_READ(reg)      wc_caamReadRegister((reg))
+    #endif
+    #ifndef WC_CAAM_WRITE
+        #define WC_CAAM_WRITE(reg, x)  wc_caamWriteRegister((reg), (x))
+    #endif
 #endif
 
+
+#define CAAM_AESCTR 0x00100000
+#define CAAM_AESCBC 0x00100100
+#define CAAM_AESECB 0x00100200
+#define CAAM_AESCFB 0x00100300
+#define CAAM_AESOFB 0x00100400
+#define CAAM_CMAC   0x00100600
+#define CAAM_AESCCM 0x00100800
+
+#define CAAM_MD5    0x00400000
+#define CAAM_SHA    0x00410000
+#define CAAM_SHA224 0x00420000
+#define CAAM_SHA256 0x00430000
+#define CAAM_SHA384 0x00440000
+#define CAAM_SHA512 0x00450000
+
+#define CAAM_HMAC_MD5    0x00400010
+#define CAAM_HMAC_SHA    0x00410010
+#define CAAM_HMAC_SHA224 0x00420010
+#define CAAM_HMAC_SHA256 0x00430010
+#define CAAM_HMAC_SHA384 0x00440010
+#define CAAM_HMAC_SHA512 0x00450010
+
+#define CAAM_ECDSA_KEYPAIR 0x00140000
+#define CAAM_ECDSA_SIGN    0x00150000
+#define CAAM_ECDSA_VERIFY  0x00160000
+#define CAAM_ECDSA_ECDH    0x00170000
+
+#define CAAM_BLOB_ENCAP 0x07000000
+#define CAAM_BLOB_DECAP 0x06000000
+#define CAAM_FIFO_S   0x60000000
+
+#define CAAM_ENC    0x00000001
+#define CAAM_DEC    0x00000000
+#define CAAM_ALG_INIT   0x00000004
+#define CAAM_ALG_INITF  0x0000000C
+#define CAAM_ALG_UPDATE 0x00000000
+#define CAAM_ALG_FINAL  0x00000008
+
+/* ECDSA ECDSEL (pre defined flags for ECDSA parameters i.e. order) */
+#define CAAM_ECDSEL_SHIFT 7
+#define CAAM_ECDSA_PD 0x00400000
+#define CAAM_ECDSA_KEYGEN_PD 0x02000000
+#define CAAM_ECDSA_P192 (0x00 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P224 (0x01 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P256 (0x02 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P384 (0x03 << CAAM_ECDSEL_SHIFT)
+#define CAAM_ECDSA_P521 (0x04 << CAAM_ECDSEL_SHIFT)
+
+#define CAAM_ECDSA_BRAINPOOL_P256 (0x0B << CAAM_ECDSEL_SHIFT)
+
+#define CAAM_ENTROPY 0x00500001
+
+/* wolfSSL specific flags */
+#define CAAM_FIND_PART 0xFFFFFFFF
+#define CAAM_GET_PART 0xFFFFFFFE
+#define CAAM_FREE_PART 0xFFFFFFFD
+#define CAAM_READ_PART 0xFFFFFFFC
+#define CAAM_WRITE_PART 0xFFFFFFFB
+
 #endif /* WOLFSSL_IMX6_CAAM */
 
 #endif /* WOLF_CRYPT_CAAM_INIT_H */

+ 36 - 0
wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h

@@ -0,0 +1,36 @@
+/* wolfcaam_cmac.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCAAM_CMAC_H
+#define WOLFCAAM_CMAC_H
+
+#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM)
+
+#include <wolfssl/wolfcrypt/cmac.h>
+
+WOLFSSL_LOCAL int wc_CAAM_Cmac(Cmac* cmac, const byte* key, word32 keySz,
+        const byte* in, word32 inSz, byte* out, word32* outSz, int type,
+        void* ctx);
+#endif
+#endif /* WOLFCAAM_CMAC_H */

+ 42 - 0
wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h

@@ -0,0 +1,42 @@
+/* wolfcaam_ecdsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCAAM_ECDSA_H
+#define WOLFCAAM_ECDSA_H
+
+#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM)
+
+#include <wolfssl/wolfcrypt/ecc.h>
+
+WOLFSSL_LOCAL int wc_CAAM_EccSign(const byte* in, int inlen, byte* out,
+        word32* outlen, WC_RNG *rng, ecc_key *key);
+WOLFSSL_LOCAL int wc_CAAM_EccVerify(const byte* sig, word32 siglen,
+        const byte* hash, word32 hashlen, int* res, ecc_key* key);
+WOLFSSL_LOCAL int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key,
+        byte* out, word32* outlen);
+WOLFSSL_LOCAL int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key,
+        int curveId);
+WOLFSSL_LOCAL int wc_CAAM_EccCheckPrivKey(ecc_key* key, const byte* pubKey,
+        word32 pubKeySz);
+#endif /* HAVE_ECC && WOLFSSL_QNX_CAAM */
+#endif /* WOLFCAAM_ECDSA_H */

+ 4 - 0
wolfssl/wolfcrypt/settings.h

@@ -1652,6 +1652,10 @@ extern void uITRON4_free(void *p) ;
     /* large performance gain with HAVE_AES_ECB defined */
     #undef HAVE_AES_ECB
     #define HAVE_AES_ECB
+
+    //@TODO used for now until plugging in caam aes use with qnx
+    #undef WOLFSSL_AES_DIRECT
+    #define WOLFSSL_AES_DIRECT
 #endif
 #endif
 

+ 1 - 1
wolfssl/wolfcrypt/sha.h

@@ -102,7 +102,7 @@ enum {
 #if defined(WOLFSSL_TI_HASH)
     #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
 
-#elif defined(WOLFSSL_IMX6_CAAM)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM)
     #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
 #elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)

+ 1 - 1
wolfssl/wolfcrypt/sha256.h

@@ -122,7 +122,7 @@ enum {
 
 #ifdef WOLFSSL_TI_HASH
     #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
-#elif defined(WOLFSSL_IMX6_CAAM)
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM)
     #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
 #elif defined(WOLFSSL_AFALG_HASH)
     #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h"

+ 1 - 1
wolfssl/wolfcrypt/sha512.h

@@ -114,7 +114,7 @@ enum {
 };
 
 
-#ifdef WOLFSSL_IMX6_CAAM
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM)
     #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
 #elif defined (WOLFSSL_PSOC6_CRYPTO)
     #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h"

+ 2 - 1
wolfssl/wolfcrypt/types.h

@@ -789,8 +789,9 @@ decouple library dependencies with standard string, memory and so on.
         WC_ALGO_TYPE_RNG = 4,
         WC_ALGO_TYPE_SEED = 5,
         WC_ALGO_TYPE_HMAC = 6,
+        WC_ALGO_TYPE_CMAC = 7,
 
-        WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_HMAC
+        WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_CMAC
     };
 
     /* hash types */

+ 4 - 0
wolfssl/wolfcrypt/wc_port.h

@@ -758,6 +758,10 @@ WOLFSSL_API int wolfCrypt_Cleanup(void);
     #endif /* max */
 #endif /* USE_WINDOWS_API */
 
+#ifdef __QNXNTO__
+    #define WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MAX
+#endif
 
 /* TIME SECTION */
 /* Time functions */

+ 3 - 5
wolfssl/wolfcrypt/wolfmath.h

@@ -62,11 +62,9 @@ MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d);
 WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b);
 WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng);
 
-enum {
-    /* format type */
-    WC_TYPE_HEX_STR = 1,
-    WC_TYPE_UNSIGNED_BIN = 2,
-};
+#define WC_TYPE_HEX_STR 1
+#define WC_TYPE_UNSIGNED_BIN 2
+#define WC_TYPE_BLACK_KEY 3
 
 WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len,
     word32 keySz, int encType);

Some files were not shown because too many files changed in this diff