From 749425e1e8af95ffeedfc3a137e483af8aa86382 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 7 Aug 2020 14:40:44 -0600 Subject: [PATCH] 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 --- .gitignore | 6 + IDE/QNX/CAAM-DRIVER/Makefile | 34 + IDE/QNX/example-client/Makefile | 33 + IDE/QNX/example-client/client-tls.c | 261 +++ IDE/QNX/example-cmac/Makefile | 33 + IDE/QNX/example-cmac/cmac-test.c | 105 + IDE/QNX/example-server/Makefile | 33 + IDE/QNX/example-server/server-tls.c | 392 ++++ IDE/QNX/include.am | 11 + IDE/include.am | 2 +- configure.ac | 27 +- src/ssl.c | 54 +- src/tls.c | 2 + src/tls13.c | 6 + wolfcrypt/src/aes.c | 48 +- wolfcrypt/src/asn.c | 14 +- wolfcrypt/src/cmac.c | 48 +- wolfcrypt/src/cryptocb.c | 38 + wolfcrypt/src/ecc.c | 121 +- wolfcrypt/src/include.am | 13 +- wolfcrypt/src/md5.c | 3 +- wolfcrypt/src/port/caam/caam_aes.c | 2 +- wolfcrypt/src/port/caam/caam_driver.c | 2105 +++++++++++------- wolfcrypt/src/port/caam/caam_error.c | 207 ++ wolfcrypt/src/port/caam/caam_init.c | 289 --- wolfcrypt/src/port/caam/caam_qnx.c | 1221 ++++++++++ wolfcrypt/src/port/caam/wolfcaam_cmac.c | 172 ++ wolfcrypt/src/port/caam/wolfcaam_ecdsa.c | 466 ++++ wolfcrypt/src/port/caam/wolfcaam_init.c | 605 +++++ wolfcrypt/src/port/caam/wolfcaam_qnx.c | 349 +++ wolfcrypt/src/random.c | 30 +- wolfcrypt/src/sha.c | 3 +- wolfcrypt/src/sha256.c | 9 +- wolfcrypt/src/sha512.c | 6 +- wolfcrypt/src/wc_port.c | 4 +- wolfcrypt/test/test.c | 23 +- wolfssl/wolfcrypt/cmac.h | 7 + wolfssl/wolfcrypt/cryptocb.h | 22 + wolfssl/wolfcrypt/ecc.h | 6 + wolfssl/wolfcrypt/include.am | 5 + wolfssl/wolfcrypt/md5.h | 2 +- wolfssl/wolfcrypt/port/caam/caam_driver.h | 267 ++- wolfssl/wolfcrypt/port/caam/caam_error.h | 29 + wolfssl/wolfcrypt/port/caam/caam_qnx.h | 70 + wolfssl/wolfcrypt/port/caam/wolfcaam.h | 105 +- wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h | 36 + wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h | 42 + wolfssl/wolfcrypt/settings.h | 4 + wolfssl/wolfcrypt/sha.h | 2 +- wolfssl/wolfcrypt/sha256.h | 2 +- wolfssl/wolfcrypt/sha512.h | 2 +- wolfssl/wolfcrypt/types.h | 3 +- wolfssl/wolfcrypt/wc_port.h | 4 + wolfssl/wolfcrypt/wolfmath.h | 8 +- 54 files changed, 6135 insertions(+), 1256 deletions(-) create mode 100644 IDE/QNX/CAAM-DRIVER/Makefile create mode 100644 IDE/QNX/example-client/Makefile create mode 100644 IDE/QNX/example-client/client-tls.c create mode 100644 IDE/QNX/example-cmac/Makefile create mode 100644 IDE/QNX/example-cmac/cmac-test.c create mode 100644 IDE/QNX/example-server/Makefile create mode 100644 IDE/QNX/example-server/server-tls.c create mode 100644 IDE/QNX/include.am create mode 100644 wolfcrypt/src/port/caam/caam_error.c delete mode 100644 wolfcrypt/src/port/caam/caam_init.c create mode 100644 wolfcrypt/src/port/caam/caam_qnx.c create mode 100644 wolfcrypt/src/port/caam/wolfcaam_cmac.c create mode 100644 wolfcrypt/src/port/caam/wolfcaam_ecdsa.c create mode 100644 wolfcrypt/src/port/caam/wolfcaam_init.c create mode 100644 wolfcrypt/src/port/caam/wolfcaam_qnx.c create mode 100644 wolfssl/wolfcrypt/port/caam/caam_error.h create mode 100644 wolfssl/wolfcrypt/port/caam/caam_qnx.h create mode 100644 wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h create mode 100644 wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h diff --git a/.gitignore b/.gitignore index e4b39ed6e..3fc51de44 100644 --- a/.gitignore +++ b/.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 *~ diff --git a/IDE/QNX/CAAM-DRIVER/Makefile b/IDE/QNX/CAAM-DRIVER/Makefile new file mode 100644 index 000000000..5e08b4724 --- /dev/null +++ b/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 diff --git a/IDE/QNX/example-client/Makefile b/IDE/QNX/example-client/Makefile new file mode 100644 index 000000000..5e76d4bd1 --- /dev/null +++ b/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 diff --git a/IDE/QNX/example-client/client-tls.c b/IDE/QNX/example-client/client-tls.c new file mode 100644 index 000000000..09d4a48b3 --- /dev/null +++ b/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 +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +/* wolfSSL */ +#include +#include + +/* 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 \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 */ +} diff --git a/IDE/QNX/example-cmac/Makefile b/IDE/QNX/example-cmac/Makefile new file mode 100644 index 000000000..13b9afc5e --- /dev/null +++ b/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 diff --git a/IDE/QNX/example-cmac/cmac-test.c b/IDE/QNX/example-cmac/cmac-test.c new file mode 100644 index 000000000..c15bb82ef --- /dev/null +++ b/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 +#include +#include + +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; +} diff --git a/IDE/QNX/example-server/Makefile b/IDE/QNX/example-server/Makefile new file mode 100644 index 000000000..f8fa25d94 --- /dev/null +++ b/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 diff --git a/IDE/QNX/example-server/server-tls.c b/IDE/QNX/example-server/server-tls.c new file mode 100644 index 000000000..e1884283e --- /dev/null +++ b/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 +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +/* wolfSSL */ +#include +#include +#include +#include /* functions for blob/cover*/ + +#define DEFAULT_PORT 11111 + +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 +#include + +/* 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(¬Secure); + if (wc_EccPrivateKeyDecode(der, &idx, ¬Secure, derSz) != 0) { + printf("Error extracting ECC der buffer\n"); + ret = -1; + goto done; + } + + /* Get the uncovered key values */ + if (wc_ecc_export_private_raw(¬Secure, NULL, NULL, NULL, NULL, d, &dSz) + != 0) { + printf("Error getting ecc key values\n"); + ret = -1; + goto done; + } + + if (wc_ecc_export_x963(¬Secure, 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(¬Secure); + 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 */ +} diff --git a/IDE/QNX/include.am b/IDE/QNX/include.am new file mode 100644 index 000000000..be4e6c0e5 --- /dev/null +++ b/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 diff --git a/IDE/include.am b/IDE/include.am index 17b5e8ab8..21932626b 100644 --- a/IDE/include.am +++ b/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 diff --git a/configure.ac b/configure.ac index 4e3dec2dd..5d36139ed 100644 --- a/configure.ac +++ b/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 "---" diff --git a/src/ssl.c b/src/ssl.c index aa324b07e..3f08418fd 100644 --- a/src/ssl.c +++ b/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) diff --git a/src/tls.c b/src/tls.c index 0df44fc9b..6e713b7c4 100644 --- a/src/tls.c +++ b/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; diff --git a/src/tls13.c b/src/tls13.c index 83e78a7ab..720762194 100644 --- a/src/tls13.c +++ b/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. diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index b08a5c69f..413e1df66 100644 --- a/wolfcrypt/src/aes.c +++ b/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) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9b7908890..a62b5bf64 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -114,6 +114,10 @@ ASN Options: #include #endif +#ifdef WOLFSSL_QNX_CAAM + #include +#endif + #ifndef NO_RSA #include #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 diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 916b5ea80..c049e622c 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -51,6 +51,10 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#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; } diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index b0957e85b..683d0cd00 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/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 */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4db120b0d..1618af558 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -159,6 +159,10 @@ ECC Curve Sizes: #include #endif +#if defined(WOLFSSL_QNX_CAAM) + #include +#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 diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 196feb42b..3ccdf9ca4 100644 --- a/wolfcrypt/src/include.am +++ b/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 diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 7bc2489e8..038d46c7d 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -174,7 +174,8 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) #include #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 diff --git a/wolfcrypt/src/port/caam/caam_aes.c b/wolfcrypt/src/port/caam/caam_aes.c index c83e6c931..5487623c9 100644 --- a/wolfcrypt/src/port/caam/caam_aes.c +++ b/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; } diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index 5d44f2da8..84e9c5b2b 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -19,78 +19,53 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + +#if (defined(__INTEGRITY) || defined(INTEGRITY)) || \ + (defined(__QNX__) || defined(__QNXNTO__)) + #if defined(__INTEGRITY) || defined(INTEGRITY) + /* build into Integrity kernel */ + #include + #define CAAM_READ(reg) *(volatile unsigned int*)(CAAM_BASE | (reg)) + #define CAAM_WRITE(reg, in) *(volatile unsigned int*)(CAAM_BASE | (reg)) = (in); + typedef UINT4 unsigned int + #define WOLFSSL_MSG db_printf +#endif -/* build into Integrity kernel */ -#include -#include "wolfssl/wolfcrypt/port/caam/caam_driver.h" +#if defined(__QNX__) || defined(__QNXNTO__) + #include + #include + #include + #include -#define CAAM_READ(reg) *(volatile unsigned int*)(reg) -#define CAAM_WRITE(reg, in) *(volatile unsigned int*)(reg) = (in); + #include "caam_qnx.h" +#endif -#define DESC_COUNT 1 -#define MAX_BUF 20 -#define BUFFER_COUNT (MAX_BUF * DESC_COUNT) +#include "caam_driver.h" +#include "caam_error.h" -/* CAAM descriptors can only be 64 unsigned ints */ -#define MAX_DESC_SZ 64 +#include /* for memcpy / memset */ -/* 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 0xF2100000 -#define MAX_READ_REG 0XF2110000 struct JobRing { - Address JobIn; - Address JobOut; - Address Desc; + CAAM_ADDRESS JobIn; + CAAM_ADDRESS JobOut; + CAAM_ADDRESS Desc; + void* VirtualIn; + void* VirtualOut; + void* VirtualDesc; Value page; /* page allocation for descriptor to use */ -}; - -struct buffer { - Address data; - Address dataSz; -}; - -/* CAAM descriptor */ -struct DescStruct { - struct IORequestStruct TheIORequest; - struct CAAM_DEVICE* caam; - struct buffer buf[MAX_BUF]; /* buffers holding data input address */ - UINT4 desc[MAX_DESC_SZ]; /* max size of 64 word32 */ - UINT4 aadSzBuf[4]; /* Formatted AAD size for CCM */ - UINT4 alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page - align */ - UINT4 iv[MAX_CTX]; /* AES IV and also hash state */ - UINT4 ctxBuf[MAX_CTX]; /* key */ - Address output; /* address to output buffer */ - 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 lastFifo; - Value type; - Value state; - Value DescriptorCount; - Boolean running; /* True if building/running descriptor is - in process */ + CAAM_MUTEX jr_lock; }; struct CAAM_DEVICE { +#if defined(__INTEGRITY) || defined(INTEGRITY) struct IODeviceVectorStruct caamVector; struct IODescriptorStruct IODescriptorArray[BUFFER_COUNT]; struct DescStruct DescArray[DESC_COUNT]; volatile Value InterruptStatus; CALL HandleInterruptCall; +#endif struct JobRing ring; }; @@ -98,175 +73,407 @@ struct CAAM_DEVICE { static struct CAAM_DEVICE caam; +/* function declarations */ +Error caamAddJob(DESCSTRUCT* desc); +Error caamDoJob(DESCSTRUCT* desc); + + /****************************************************************************** Internal CAAM Job Ring and partition functions ****************************************************************************/ +#ifdef CAAM_DEBUG_MODE +/* runs a descriptor in debug mode */ +static Error caamDebugDesc(struct DescStruct* desc) +{ + int z; + int sz; + unsigned int flag = 0x20000000; + + /* clear and set desc size */ + sz = desc->desc[0] & 0x0000007F; + CAAM_WRITE(CAAM_DECORR, 1); /* ask for DECO permissions */ + printf("CAAM_DECORR = 0x%08X\n", CAAM_READ(CAAM_DECORR)); + printf("STATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04)); + + printf("Descriptor input :\n"); + /* write descriptor into descriptor buffer */ + for (z = 0; z < sz; z++) { + CAAM_WRITE(CAAM_DODESB + (z*4), desc->desc[z]); + printf("\t0x%08X\n", desc->desc[z]); + } + printf("\n"); + + printf("command size = %d\n", sz); + if (sz > 4) { + flag |= 0x10000000; + } + + CAAM_WRITE(CAAM_DODAR+4, desc->caam->ring.Desc); + /* set WHL bit since we loaded the entire descriptor */ + CAAM_WRITE(CAAM_DOJQCR_MS, flag); + + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04)); + + /* DECO buffer */ + printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4)); + printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044)); + for (z = 0; z < sz; z++) + printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4))); + + + //D0JQCR_LS + printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804)); + printf("Desc = 0x%08X\n", desc->caam->ring.Desc); + + + /* DECO buffer */ + printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4)); + printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044)); + for (z = 0; z < sz; z++) + printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4))); + + printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804)); + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + while (CAAM_READ(0x8E04) & 0x80000000) { + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04)); + sleep(1); + } + CAAM_WRITE(CAAM_DECORR, 0); /* free DECO */ + printf("done with debug job\n"); + return Success; +} +#endif /* CAAM_DEBUG_MODE */ + + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +static void printSecureMemoryInfo() +{ + unsigned int SMVID_MS, SMVID_LS; + + printf("SMSTA = 0x%08X\n", CAAM_READ(0x1FB4)); + printf("SMPO = 0x%08X\n", CAAM_READ(CAAM_SM_SMPO)); + SMVID_MS = CAAM_READ(CAAM_SM_SMVID_MS); + SMVID_LS = CAAM_READ(CAAM_SM_SMVID_LS); + printf("\tNumber Partitions : %d\n", (SMVID_MS >> 12 & 0xF)); + printf("\tNumber Pages : %d\n", (SMVID_MS & 0x3FF)); + printf("\tPage Size : 2^%d\n", ((SMVID_LS >> 16) & 0x7)); +} +#endif + /* flush job ring and reset */ static Error caamReset(void) { int t = 100000; /* time out counter for flushing job ring */ /* make sure interrupts are masked in JRCFGR0_LS register */ - CAAM_WRITE(CAAM_BASE | 0x1054, CAAM_READ(CAAM_BASE | 0x1054) | 1); + CAAM_WRITE(0x1054, CAAM_READ(0x1054) | 1); /* flush and reset job rings using JRCR0 register */ - CAAM_WRITE(CAAM_BASE | 0x106C, 1); + CAAM_WRITE(0x106C, 1); /* check register JRINTR for if halt is in progress */ - while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x104C) & 0x4) == 0x4)) t--; + while (t > 0 && ((CAAM_READ(0x104C) & 0x4) == 0x4)) t--; if (t == 0) { /*unrecoverable failure, the job ring is locked, up hard reset needed*/ - return NotRestartable; + return -1;//NotRestartable; } /* now that flush has been done restart the job ring */ t = 100000; - CAAM_WRITE(CAAM_BASE | 0x106C, 1); - while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x106C) & 1) == 1)) t--; + CAAM_WRITE(0x106C, 1); + while (t > 0 && ((CAAM_READ(0x106C) & 1) == 1)) t--; if (t == 0) { /*unrecoverable failure, reset bit did not return to 0 */ - return NotRestartable; + return -1;//NotRestartable; } /* reset most registers and state machines in CAAM using MCFGR register also reset DMA */ - CAAM_WRITE(CAAM_BASE | 0x0004, 0x90000000); + CAAM_WRITE(0x0004, 0x90000000); + + /* DAR 0x0120 can be used to check if hung */ + + /* DDR */ + CAAM_WRITE(0x0124, 1); return Success; } -/* returns MemoryMapMayNotBeEmpty if page/par is already owned - * returns Success on success - * all other returns is an error state - */ -static Error caamCreatePartition(unsigned char page, unsigned char par) + +/* free the page and dealloc */ +static Error caamFreePage(unsigned char page) { - /* check ownership of partition */ - if ((CAAM_READ(CAAM_BASE | 0x1FBC) & (0x3 << (par * 2))) > 0) { - return MemoryMapMayNotBeEmpty; + /* owns the page can dealloc it */ + CAAM_WRITE(CAAM_SM_CMD, (page << 16) | 0x2); + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + } + if ((CAAM_READ(CAAM_SM_STATUS) & 0x00003000) > 0) { + /* error while deallocating page */ + WOLFSSL_MSG("error while deallocating page"); + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + } + WOLFSSL_MSG("free'd page"); + return Success; +} + +/* free the partition and dealloc */ +Error caamFreePart(int part) +{ + unsigned int status; + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("freeing partition %d\n", part); + #endif + CAAM_WRITE(CAAM_SM_CMD, (part << 8) | 0x3); + + status = CAAM_READ(CAAM_SM_STATUS); + while ((status & 0x00004000) > 0 && (status & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + status = CAAM_READ(CAAM_SM_STATUS); } - /* set generic all access permissions, gets reset later */ - CAAM_WRITE(CAAM_BASE | (0x1108 + (par * 16)), 0xF); - CAAM_WRITE(CAAM_BASE | (0x110C + (par * 16)), 0xF); - CAAM_WRITE(CAAM_BASE | (0x1104 + (par * 16)), 0xFF); - - /* check ownership of page */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); - /* wait for inquiry cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + if (((status & 0x00003000) > 0) || ((status & 0x0000C000) > 0)) { + /* error while deallocating page */ + WOLFSSL_MSG("error while deallocating partition"); + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ } - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) == 0xC0) { - /* owns the page can dealloc it */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x2); - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) {} - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - /* error while deallocating page */ - return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + WOLFSSL_MSG("free'd partition"); + return Success; +} + + +/* find all partitions we own and free them */ +static Error caamFreeAllPart() +{ + unsigned int SMPO; + int i; + + WOLFSSL_MSG("Free all partitions"); + SMPO = CAAM_READ(0x1FBC); + for (i = 0; i < 15; i++) { + if ((SMPO & (0x3 << (i * 2))) == (0x3U << (i * 2))) { + caamFreePart(i); } } - else { - /* check if owned by someone else */ - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) != 0) { + + return 0; +} + + +/* search through the partitions to find an unused one + * returns negative value on failure, on success returns 0 or greater + */ +int caamFindUnusuedPartition() +{ + unsigned int SMPO; + int i, ret = -1; + + SMPO = CAAM_READ(0x1FBC); + for (i = 0; i < 15; i++) { + if ((SMPO & (0x3 << (i * 2))) == 0) { + ret = i; + break; + } + } + + return ret; +} + + +/* flag contains how the parition is set i.e CSP flag and read/write access + * it also contains if locked + */ +static Error caamCreatePartition(unsigned char page, unsigned char par, + unsigned int flag) +{ + + unsigned int status; + + /* check ownership of partition */ + status = CAAM_READ(0x1FBC); + if ((status & (0x3 << (par * 2))) > 0) { + if ((status & (0x3 << (par * 2))) == (0x3U << (par * 2))) { + WOLFSSL_MSG("we own this partition!"); + } + else { return MemoryMapMayNotBeEmpty; } } - /* allocate page to partition */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | (par << 8) | 0x1); + CAAM_WRITE(0x1A04 + (par * 16), flag); + + /* dealloc page if we own it */ + CAAM_WRITE(CAAM_SM_CMD, (page << 16) | 0x5); + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + } + if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0xC0) { + if (caamFreePage(page) != Success) { + return MemoryMapMayNotBeEmpty; + } + } + else if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0x00) { + WOLFSSL_MSG("page available and un-owned"); + } + else { + WOLFSSL_MSG("we don't own the page..."); + return -1; + } + + CAAM_WRITE(CAAM_SM_CMD, (page << 16) | (par << 8) | 0x1); /* wait for alloc cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { - } - - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - return MemoryOperationNotPerformed; - } - - /* double check ownership now of page */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); - /* wait for inquiry cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { - } - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000000F) == 0 || - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - /* page not owned */ - return MemoryOperationNotPerformed; + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); } return Success; } -/* Gets the status of a job. Returns Waiting if no output jobs ready to be +/* return a mapped address to the partition on success, returns 0 on fail */ +CAAM_ADDRESS caamGetPartition(int part, int partSz, unsigned int* phys, + unsigned int flag) +{ + int err; + CAAM_ADDRESS vaddr; + unsigned int local; + + (void)flag; /* flag is for future changes to flag passed when creating */ + + /* create and claim the partition */ + err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (err != Success) { + WOLFSSL_MSG("Error creating partiions for secure ecc key"); + return 0; + } + + /* map secure partition to virtual address */ + local = (CAAM_PAGE + (part << 12)); + vaddr = CAAM_ADR_TO_VIRTUAL(local, partSz); + if (phys != NULL) { + *phys = local; + } + return vaddr; +} + + +/* Gets the status of a job. Returns CAAM_WAITING if no output jobs ready to be * read. - * If no jobs are done then return Waiting + * If no jobs are done then return CAAM_WAITING * If jobs are done but does not match desc then return NoActivityReady * Status holds the error values if any */ -static Error caamGetJob(struct CAAM_DEVICE* dev, UINT4* status) +static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) { - UINT4 reg = CAAM_READ(CAAM_BASE | 0x1044); /* JRSTAR0 status */ + unsigned int reg; if (status) { *status = 0; } - /* check for DECO, CCB, and Job Ring error state JRSTAR0 register */ - if (((reg & 0xF0000000) == 0x20000000) || /* CCB error */ - ((reg & 0xF0000000) == 0x40000000)|| /* DECO error */ - ((reg & 0xF0000000) == 0x60000000)) { /* Job Ring error */ - - if ((reg & 0x0000000F) > 0) { - *status = reg; - return Failure; - } - } +#ifdef CAAM_DEBUG_MODE + (void)dev; + return Success; +#endif /* Check number of done jobs in output list */ - reg = CAAM_READ(CAAM_BASE | 0x103C); + reg = CAAM_READ(0x103C); +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("number of jobs in output list = 0x%08X\n", reg); +#endif if ((reg & 0x000003FF) > 0) { - UINT4* out = (UINT4*)(dev->ring.JobOut); - if (status) { - *status = out[1]; + unsigned int *pt; + + if (CAAM_ADR_SYNC(caam.ring.VirtualOut, (2 * CAAM_JOBRING_SIZE * + sizeof(unsigned int))) != 0) { + return -1; } - if ((dev->ring.Desc ^ 0xF0000000) != out[0]) { - db_printf("CAAM job completed vs expected mismatch"); - return NoActivityReady; - } - - if (out[1] > 0) { - return Failure; + /* sanity check on job out */ + pt = (unsigned int*)caam.ring.VirtualOut; + if (pt[0] != caam.ring.Desc) { + return -1; } + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("\tjob 0x%08X done - result 0x%08X\n", pt[0], pt[1]); + #endif + *status = pt[1]; /* increment jobs removed */ - CAAM_WRITE(CAAM_BASE | 0x1034, 1); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("removing job from list\n"); + fflush(stdout); + #endif + CAAM_WRITE(0x1034, 1); } else { /* check if the CAAM is idle and not processing any descriptors */ - if ((CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000002) == 2 /* idle */ - && (CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000001) == 0) { + if ((CAAM_READ(0x0FD4) & 0x00000002) == 2 /* idle */ + && (CAAM_READ(0x0FD4) & 0x00000001) == 0) { + WOLFSSL_MSG("caam is idle....."); return NoActivityReady; } - - return Waiting; + return CAAM_WAITING; } + (void)dev; - return Success; + CAAM_WRITE(JRCFGR_JR0_LS, 0); + if (*status == 0) { + return Success; + } + return Failure; } +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +/* debug print out JDKEK */ +static void print_jdkek() +{ + int i; + + printf("JDKEK = "); + for (i = 0; i < 8; i++) { + printf("%08X ", CAAM_READ(0x0400 + (i*4))); + } + printf("\n"); +} +#endif + + +/* 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 */ +}; + + + /* Initialize CAAM RNG * returns 0 on success */ -static int caamInitRng(struct CAAM_DEVICE* dev) +int caamInitRng(struct CAAM_DEVICE* dev); +int caamInitRng(struct CAAM_DEVICE* dev) { - UINT4 reg, status; + DESCSTRUCT desc; + unsigned int reg, status; int ret = 0; + memset(&desc, 0, sizeof(DESCSTRUCT)); + /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */ + /* check out the status and see if already setup */ CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM); CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | 0x40); /* reset */ @@ -288,81 +495,151 @@ static int caamInitRng(struct CAAM_DEVICE* dev) reg |= CAAM_CTLERR; CAAM_WRITE(CAAM_RTMCTL, reg); - /* check input slot is available and then add */ - if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { - UINT4* in = (UINT4*)dev->ring.JobIn; + /* check out the status and see if already setup */ + reg = CAAM_READ(CAAM_RDSTA); + if (((reg >> 16) & 0xF) > 0) { + WOLFSSL_MSG("RNG is in error state"); + caamReset(); + } - memcpy((unsigned char*)dev->ring.Desc, (unsigned char*)wc_rng_start, - sizeof(wc_rng_start)); + if (reg & (1 << 30)) { + WOLFSSL_MSG("JKDKEK rng was setup using a non determinstic key"); + return 0; + } - in[0] = dev->ring.Desc ^ 0xF0000000; /* physical address */ + if (CAAM_READ(0x1014) > 0) { + int i; + #ifdef CAAM_DEBUG_MODE + for (i = 0; i < 6; i++) + desc.desc[desc.idx++] = wc_rng_start[i]; + + desc.caam = dev; + ret = caamDoJob(&desc); + #else + unsigned int *pt = (unsigned int*)caam.ring.VirtualDesc; + for (i = 0; i < 6; i++) + pt[i] = wc_rng_start[i]; + pt = (unsigned int*)caam.ring.VirtualIn; + pt[0] = (unsigned int)caam.ring.Desc; + + /* start process */ + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("incrementing job count\n"); + fflush(stdout); + #endif CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + #endif } else { - return Waiting; + return CAAM_WAITING; } do { ret = caamGetJob(dev, &status); - /* @TODO use a better way to chill out CPU. */ - } while (ret == Waiting); + CAAM_CPU_CHILL(); + } while (ret == CAAM_WAITING); - return ret; + if (ret == Success) + return 0; + return -1; } -static Error caamDoJob(struct DescStruct* desc) +/* Take in a descriptor and add it to the job list */ +Error caamAddJob(DESCSTRUCT* desc) { - Error ret; - UINT4 status; - /* clear and set desc size */ desc->desc[0] &= 0xFFFFFF80; - desc->desc[0] += desc->idx; + desc->desc[0] += desc->idx + (desc->startIdx << 16); + CAAM_LOCK_MUTEX(&caam.ring.jr_lock); /* check input slot is available and then add */ - if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { - UINT4* in = (UINT4*)desc->caam->ring.JobIn; + if (CAAM_READ(0x1014) > 0) { + int i; + unsigned int *pt; - memcpy((unsigned char*)desc->caam->ring.Desc, (unsigned char*)desc->desc, - (desc->idx + 1) * sizeof(UINT4)); + pt = (unsigned int*)caam.ring.VirtualDesc; + #if defined(WOLFSSL_CAAM_PRINT) + printf("Doing Job :\n"); + #endif + for (i = 0; i < desc->idx; i++) { + pt[i] = desc->desc[i]; + #if defined(WOLFSSL_CAAM_PRINT) + printf("\tCMD %02d [%p] = 0x%08X\n", i+1, pt + i, + desc->desc[i]); + #endif + } - in[0] = desc->caam->ring.Desc ^ 0xF0000000; /* physical address */ + pt = (unsigned int*)caam.ring.VirtualIn; + pt[0] = (unsigned int)caam.ring.Desc; + + if (CAAM_ADR_SYNC(caam.ring.VirtualDesc, + desc->idx * sizeof(unsigned int)) != 0) { + return -1; + } + + if (CAAM_ADR_SYNC(caam.ring.VirtualIn, + CAAM_JOBRING_SIZE * sizeof(unsigned int)) != 0) { + return -1; + } + + #ifdef CAAM_DEBUG_MODE + caamDebugDesc(desc); + #else + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("started job 0x%08X done\n", (unsigned int)caam.ring.Desc); + #endif CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + #endif } else { - return Waiting; + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("SLOT = 0x%08X, IRJAR0 = 0x%08X\n", CAAM_READ(0x1014), + CAAM_READ(CAAM_IRJAR0)); + printf("Number of job in done queue = 0x%08X\n", CAAM_READ(0x103C)); + #endif + CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock); + return CAAM_WAITING; + } + CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock); + return Success; +} + + +/* Synchronous job completion, add it to job queue and wait till finished */ +Error caamDoJob(DESCSTRUCT* desc) +{ + Error ret; + unsigned int status; + + ret = caamAddJob(desc); + if (ret != Success) { + return ret; } do { ret = caamGetJob(desc->caam, &status); - /* @TODO use a better way to chill out CPU. */ - } while (ret == Waiting); + CAAM_CPU_CHILL(); + } while (ret == CAAM_WAITING); + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("job status = 0x%08X, ret = %d\n", status, ret); + #endif if (status != 0 || ret != Success) { - #if 0 - /* Used during testing to print out descriptor */ - { - char msg[2048]; - char* pt = msg; - int z; - - memset(msg, 0, sizeof(msg)); - for (z = 0; z < desc->idx; z++) { - snprintf(pt, sizeof(msg) - (z * 21), "desc[%d] = 0x%8.8x, ", - z, desc->desc[z]); - pt += 21; - } - snprintf(pt, sizeof(msg) - (z * 21), "status = 0x%8.8x\n", status); - if (desc->buf[0].data != 0) { /* for testing */ - memcpy((char*)desc->buf[0].data, msg, sizeof(msg)); - } - } - #endif - - /* try to reset after error */ - caamReset(); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + int i; + for (i = 0; i < desc->idx; i++) { + printf("\tCMD %02d = 0x%08X\n", i+1, desc->desc[i]); + } + printf("\n"); + #endif + /* consider any job ring errors as fatal, and try reset */ + if (caamParseJRError(CAAM_READ(JRINTR_JR0)) != 0) { + caamReset(); + } + caamParseError(status); return ret; } @@ -370,188 +647,79 @@ static Error caamDoJob(struct DescStruct* desc) } -/* handle input or output buffers - * NOTES: if sz == 0 then read all the rest of the buffers available - * when align == 1 then there is no alignment constraints - * - * returns the data size in bytes on success. With failure a negative value is - * returned. - */ -static int caamAddIO(struct DescStruct* desc, UINT4 options, UINT4 sz, - UINT4 align, UINT4* idx) -{ - int i, outSz = 0; - - if (align == 0) { - return -1; /* programming error */ - } - - for (i = *idx; i < desc->DescriptorCount; i++) { - /* input must be a multiple of "align" bytes */ - struct buffer* buf = &desc->buf[i]; - int blocks = buf->dataSz / align; - Address data = buf->data; - Address dataSz = buf->dataSz; - - if (outSz >= sz && sz != 0) { - break; - } - - if (dataSz % align > 0) { - /* store potential overlap */ - int tmpSz = dataSz % align; - int add = (tmpSz < (align - desc->alignIdx)) ? tmpSz : - align - desc->alignIdx; - unsigned char* local = (unsigned char*)desc->alignBuf; - - /* if already something in the buffer then add from front */ - if (desc->alignIdx > 0) { - memcpy((unsigned char*)&local[desc->alignIdx], - (unsigned char*)data, add); - data += add; - } - else { - memcpy((unsigned char*)&local[desc->alignIdx], - (unsigned char*)data + (blocks * align), add); - } - dataSz -= add; - desc->alignIdx += add; - } - - if (desc->alignIdx == align) { - desc->lastFifo = desc->idx; - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = options + desc->alignIdx; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); - ASP_FlushCaches((Address)desc->alignBuf, desc->alignIdx); - outSz += desc->alignIdx; - } - - if (blocks > 0) { - desc->lastFifo = desc->idx; - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = options + (blocks * align); - desc->desc[desc->idx++] = BSP_VirtualToPhysical(data); - outSz += (blocks * align); - - /* only one buffer available for align cases so exit here and make - a new descriptor after running current one */ - if (desc->alignIdx == align) { - desc->alignIdx = 0; - i++; /* start at next buffer */ - break; - } - } - } - - *idx = i; - return outSz; -} - - -/****************************************************************************** - IODevice Register Read and Write - ****************************************************************************/ - -static Error caamReadRegister(IODeviceVector ioCaam, Value reg, Value *out) -{ - if (reg < MIN_READ_REG || reg > MAX_READ_REG) { - return IllegalRegisterNumber; - } - - switch (reg) { - case CAAM_STATUS: - case CAAM_VERSION_MS: - case CAAM_VERSION_LS: - case CAMM_SUPPORT_MS: - case CAMM_SUPPORT_LS: - case CAAM_RTMCTL: - *out = CAAM_READ(reg); - break; - - default: - return IllegalRegisterNumber; - } - - (void)ioCaam; - return Success; -} - - -static Error caamWriteRegister(IODeviceVector ioCaam, Value reg, Value in) -{ - /* Should be no need for writes */ - return OperationNotAllowedOnTheUniversalIODevice; -} - - /****************************************************************************** CAAM Blob Operations ****************************************************************************/ -/* limit on size due to size of job ring being 64 word32's */ -static Error caamBlob(struct DescStruct* desc) +/* limit on size due to size of job ring being 64 unsigned int's */ +int caamBlob(DESCSTRUCT* desc) { + void *vaddrOut, *vaddr, *keymod; Error err; - UINT4 keyType = 0x00000C08; /* default red */ - UINT4 i = 0; - int sz = 0, ret; + unsigned int keyType = 0x00000C08; /* default red */ + unsigned int i = 0; + int inputSz; + int outputSz; if (desc->idx + 3 > MAX_DESC_SZ) { return Failure; } - /*default to Red Key type, with offset of 12 and 8 byte load to context 2*/ - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | CAAM_IMM | keyType); + /* doing black blobs */ + if (desc->state) { + WOLFSSL_MSG("making a black blob"); + keyType = 0x00000010; + } + + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | keyType); /* add key modifier */ - if (i < desc->DescriptorCount) { - UINT4* pt; - Address data = desc->buf[i].data; - Address dataSz = desc->buf[i].dataSz; + keymod = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(keymod, desc->buf[i].dataSz); + i++; - pt = (UINT4*)data; - if (dataSz < 8) { /* expecting 8 bytes for key modifier*/ - return TooManyBuffers; - } - desc->desc[desc->idx++] = pt[0]; - desc->desc[desc->idx++] = pt[1]; + inputSz = desc->buf[i].dataSz; + if (desc->state && (desc->type == CAAM_BLOB_ENCAP)) { + /* black keys with CCM have mac at the end */ + inputSz += 16; } + vaddr = CAAM_ADR_MAP(desc->buf[i].data, inputSz, 1); + /* add input */ - while (sz < desc->inputSz && i < desc->DescriptorCount) { - ret = caamAddIO(desc, CAAM_SEQI, desc->inputSz - sz, 1, &i); - if (ret < 0) { /* handle error case */ - return TooManyBuffers; - } - sz += ret; - } + desc->desc[desc->idx++] = CAAM_SEQI + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr, inputSz); + i++; desc->outputIdx = i; - /* add output */ - if (caamAddIO(desc, CAAM_SEQO, 0, 1, &i) < 0) { - return TooManyBuffers; + outputSz = desc->buf[i].dataSz; + if (desc->state && (desc->type == CAAM_BLOB_DECAP)) { + /* black keys with CCM have mac at the end */ + outputSz += 16; } + vaddrOut = CAAM_ADR_MAP(desc->buf[i].data, outputSz, 0); + /* add output */ + desc->desc[desc->idx++] = CAAM_SEQO + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddrOut, outputSz); if (desc->idx + 1 > MAX_DESC_SZ) { return Failure; } - desc->desc[desc->idx++] = CAAM_OP | CAAM_OPID_BLOB | desc->type; + desc->desc[desc->idx] = CAAM_OP | CAAM_OPID_BLOB | desc->type; - if ((err = caamDoJob(desc)) != Success) { - return err; + if (desc->state) { + desc->desc[desc->idx] |= 0x104; /* EKT and Black_key (key is covered) */ } + desc->idx++; + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); - /* flush output buffers */ - for (i = desc->outputIdx; i < desc->DescriptorCount; i++) { - ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); - } + CAAM_ADR_UNMAP(keymod, desc->buf[0].data, desc->buf[0].dataSz, 0); + CAAM_ADR_UNMAP(vaddr, desc->buf[1].data, inputSz, 0); + CAAM_ADR_UNMAP(vaddrOut, desc->buf[2].data, outputSz, 1); - return Success; + return err; } @@ -559,15 +727,142 @@ static Error caamBlob(struct DescStruct* desc) CAAM AES Operations ****************************************************************************/ +int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) +{ + Error err; + unsigned int keySz; + unsigned int macSz = 0; + void *vaddr[4] = {0}; + unsigned int vidx = 0; + unsigned int ctx; + unsigned int isBlackKey; + int i; + + isBlackKey = args[2]; + keySz = args[1]; + + /* Get CTX physical address */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[1].data, desc->buf[1].dataSz, 1); + ctx = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[1].dataSz); + vidx++; + + /* LOAD KEY */ + desc->desc[desc->idx] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + keySz; + if (isBlackKey) { + desc->desc[desc->idx] |= CAAM_LOAD_BLACK_KEY; + macSz = 16; /* copy over 16 additional bytes to account for mac */ + } + desc->idx++; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[0].data, desc->buf[0].dataSz + macSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[0].dataSz + macSz); + #if 0 + { + unsigned int p; byte* pt = (byte*)vaddr[vidx]; + printf("Using key [%d]:", desc->buf[0].dataSz + macSz); + for (p = 0; p < keySz; p++) + printf("%02X", pt[p]); + printf("\n"); + } + #endif + vidx++; + + /* Load in CTX only when not initialization */ + if ((desc->state & CAAM_ALG_INIT) == 0) { + int ofst = 0; + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + + desc->buf[1].dataSz; + desc->desc[desc->idx++] = ctx; + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[0]; + printf("loading in CTX [%d] :", desc->buf[1].dataSz); + for (z = 0; z < 32; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + } + + /* add protinfo to operation command */ + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | desc->state; + + + /* add in all input buffers */ + for (i = 2; i < sz; i++) { + desc->desc[desc->idx] = (CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_MSG) + + desc->buf[i].dataSz; + if (i+1 == sz) { + /* this is the last input buffer, signal the HW with LC1 bit */ + desc->desc[desc->idx] |= FIFOL_TYPE_LC1; + } + desc->idx++; + + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[vidx]; + printf("MSG [%d] :", desc->buf[i].dataSz); + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + + vidx++; + + } + + /* if there is no input buffers than add in a single FIFO LOAD to kick off + * the operation */ + if (sz == 2) { /* only key and ctx buffer */ + desc->desc[desc->idx++] = CAAM_FIFO_L | FIFOL_TYPE_LC1 | CAAM_CLASS1 | + FIFOL_TYPE_MSG; + vaddr[vidx] = CAAM_ADR_MAP(0, 0, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], 0); + vidx++; + } + + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | 32; + desc->desc[desc->idx++] = ctx; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[0]; + printf("CTX: "); + for (z = 0; z < 32; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + + CAAM_ADR_UNMAP(vaddr[0], desc->buf[1].data, desc->buf[1].dataSz, 1); + CAAM_ADR_UNMAP(vaddr[1], desc->buf[0].data, desc->buf[0].dataSz + macSz, 0); + for (vidx = 2, i = 2; i < sz; i++) { /* unmap the input buffers */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + } + return err; +} + + +#if defined(__INTEGRITY) || defined(INTEGRITY) /* returns amount written on success and negative value in error case. * Is different from caamAddIO in that it only adds a single input buffer * rather than multiple ones. */ -static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, - UINT4 totalSz) +static int caamAesInput(struct DescStruct* desc, unsigned int* idx, int align, + unsigned int totalSz) { int sz; - UINT4 i = *idx; + unsigned int i = *idx; /* handle alignment constraints on input */ if (desc->alignIdx > 0) { @@ -588,7 +883,7 @@ static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, if (desc->idx + 2 > MAX_DESC_SZ) { return -1; } - ASP_FlushCaches((Address)desc->alignBuf, sz); + ASP_FlushCaches((CAAM_ADDRESS)desc->alignBuf, sz); desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); @@ -628,12 +923,12 @@ static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, * ofst is the amount of leftover buffer from previous calls * inputSz is the amount of input in bytes that is being matched to output */ -static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz) +static Error caamAesOutput(struct DescStruct* desc, int* ofst, unsigned int inputSz) { int offset = *ofst; if (desc->output != 0 && offset > 0 && inputSz > 0) { - UINT4 addSz; + unsigned int addSz; /* handle potential leftovers */ addSz = (inputSz >= offset) ? offset : inputSz; @@ -695,7 +990,7 @@ static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz) /* check size of output and get starting buffer for it */ -static Error caamAesOutSz(struct DescStruct* desc, UINT4 i) +static Error caamAesOutSz(struct DescStruct* desc, unsigned int i) { int sz = 0; @@ -727,7 +1022,7 @@ static Error caamAes(struct DescStruct* desc) struct buffer* iv[3]; Value ofst = 0; Error err; - UINT4 i, totalSz = 0; + unsigned int i, totalSz = 0; int ctxIdx = 0; int ivIdx = 0; int offset = 0; @@ -749,7 +1044,7 @@ static Error caamAes(struct DescStruct* desc) struct buffer* buf = &desc->buf[i]; unsigned char* local = (unsigned char*)desc->ctxBuf; - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + if (sz < ctxSz && sz < (MAX_CTX * sizeof(unsigned int))) { ctx[ctxIdx] = buf; sz += buf->dataSz; @@ -767,14 +1062,14 @@ static Error caamAes(struct DescStruct* desc) if (sz > ctxSz) { return SizeIsTooLarge; } - if (ctxSz > (MAX_CTX * sizeof(UINT4)) - 16) { + if (ctxSz > (MAX_CTX * sizeof(unsigned int)) - 16) { return ArgumentError; } /* Flush cache of ctx buffer then : Add KEY Load command 0x0220000X Add address to read key from 0xXXXXXXXX */ - ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + ASP_FlushCaches((CAAM_ADDRESS)desc->ctxBuf, ctxSz); if (desc->idx + 2 > MAX_DESC_SZ) { return TransferFailed; } @@ -823,7 +1118,7 @@ static Error caamAes(struct DescStruct* desc) return SizeIsTooLarge; } - ASP_FlushCaches((Address)desc->iv, maxSz); + ASP_FlushCaches((CAAM_ADDRESS)desc->iv, maxSz); if (desc->idx + 2 > MAX_DESC_SZ) { return TransferFailed; } @@ -879,13 +1174,13 @@ static Error caamAes(struct DescStruct* desc) return TransferFailed; } desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + desc->desc[desc->idx++] = BSP_VirtualToPhysical((CAAM_ADDRESS)desc->iv); } if ((err = caamDoJob(desc)) != Success) { return err; } - ASP_FlushCaches((Address)desc->iv, 16); + ASP_FlushCaches((CAAM_ADDRESS)desc->iv, 16); } while (desc->lastIdx < desc->DescriptorCount || offset > 0); /* flush output buffers */ @@ -896,7 +1191,7 @@ static Error caamAes(struct DescStruct* desc) /* handle case with IV */ if (ivIdx > 0) { unsigned char* pt = (unsigned char*)desc->iv; - ASP_FlushCaches((Address)pt, 16); + ASP_FlushCaches((CAAM_ADDRESS)pt, 16); for (i = 0; i < ivIdx; i++) { memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); pt += iv[i]->dataSz; @@ -906,12 +1201,14 @@ static Error caamAes(struct DescStruct* desc) return Success; } +#endif /****************************************************************************** CAAM AEAD Operations ****************************************************************************/ +#if defined(__INTEGRITY) || defined(INTEGRITY) /* AEAD operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD) * -> Input -> Output * @@ -921,10 +1218,10 @@ static Error caamAead(struct DescStruct* desc) struct buffer* ctx[3]; struct buffer* iv[3]; Value ofst = 0; - UINT4 state = CAAM_ALG_INIT; - UINT4 totalSz = 0; + unsigned int state = CAAM_ALG_INIT; + unsigned int totalSz = 0; Error err; - UINT4 i; + unsigned int i; int ctxIdx = 0; int ivIdx = 0; int offset = 0; @@ -948,7 +1245,7 @@ static Error caamAead(struct DescStruct* desc) struct buffer* buf = &desc->buf[i]; unsigned char* local = (unsigned char*)desc->ctxBuf; - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + if (sz < ctxSz && sz < (MAX_CTX * sizeof(unsigned int))) { ctx[ctxIdx] = buf; sz += buf->dataSz; @@ -970,7 +1267,7 @@ static Error caamAead(struct DescStruct* desc) /* Flush cache of ctx buffer then : Add KEY Load command 0x0220000X Add address to read key from 0xXXXXXXXX */ - ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + ASP_FlushCaches((CAAM_ADDRESS)desc->ctxBuf, ctxSz); if (desc->idx + 2 > MAX_DESC_SZ) { return TransferFailed; } @@ -1026,7 +1323,7 @@ static Error caamAead(struct DescStruct* desc) offset = 0; } - ASP_FlushCaches((Address)desc->iv, ivSz); + ASP_FlushCaches((CAAM_ADDRESS)desc->iv, ivSz); if (desc->idx + 2 > MAX_DESC_SZ) { return TransferFailed; } @@ -1044,7 +1341,7 @@ static Error caamAead(struct DescStruct* desc) if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { if ((desc->type == CAAM_AESCCM) && (desc->aadSz > 0)) { /* set formatted AAD buffer size for CCM */ - ASP_FlushCaches((Address)desc->aadSzBuf, sizeof(desc->aadSzBuf)); + ASP_FlushCaches((CAAM_ADDRESS)desc->aadSzBuf, sizeof(desc->aadSzBuf)); desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_AAD + desc->aadSz; desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->aadSzBuf); @@ -1052,15 +1349,15 @@ static Error caamAead(struct DescStruct* desc) /* now set aadSz to unformatted version for getting buffers */ if (desc->aadSz == 2) { unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = (((UINT4)pt[0] & 0xFF) << 8) | - ((UINT4)pt[1] & 0xFF); + desc->aadSz = (((unsigned int)pt[0] & 0xFF) << 8) | + ((unsigned int)pt[1] & 0xFF); } else { unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = (((UINT4)pt[2] & 0xFF) << 24) | - (((UINT4)pt[3] & 0xFF) << 16) | - (((UINT4)pt[4] & 0xFF) << 8) | - ((UINT4)pt[5] & 0xFF); + desc->aadSz = (((unsigned int)pt[2] & 0xFF) << 24) | + (((unsigned int)pt[3] & 0xFF) << 16) | + (((unsigned int)pt[4] & 0xFF) << 8) | + ((unsigned int)pt[5] & 0xFF); } } @@ -1128,7 +1425,7 @@ static Error caamAead(struct DescStruct* desc) return TransferFailed; } desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | ivSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + desc->desc[desc->idx++] = BSP_VirtualToPhysical((CAAM_ADDRESS)desc->iv); if ((err = caamDoJob(desc)) != Success) { return err; @@ -1144,7 +1441,7 @@ static Error caamAead(struct DescStruct* desc) /* handle case with IV (This is also the output of MAC with AES-CCM) */ if (ivIdx > 0) { unsigned char* pt = (unsigned char*)desc->iv; - ASP_FlushCaches((Address)pt, ivSz); + ASP_FlushCaches((CAAM_ADDRESS)pt, ivSz); for (i = 0; i < ivIdx; i++) { memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); pt += iv[i]->dataSz; @@ -1154,176 +1451,443 @@ static Error caamAead(struct DescStruct* desc) return Success; } +#endif -/****************************************************************************** - CAAM SHA Operations - ****************************************************************************/ -static int shaSize(struct DescStruct* desc) -{ - /* sanity check on dataSz for context */ - switch (desc->type) { - case CAAM_MD5: - return CAAM_MD5_CTXSZ; - - case CAAM_SHA: - return CAAM_SHA_CTXSZ; - - case CAAM_SHA224: - return CAAM_SHA224_CTXSZ; - - case CAAM_SHA256: - return CAAM_SHA256_CTXSZ; - - case CAAM_SHA384: - return CAAM_SHA384_CTXSZ; - - case CAAM_SHA512: - return CAAM_SHA512_CTXSZ; - - default: - return 0; - } -} - -/* SHA operations - * start: the index to start traversing through buffers. It's needed to allow - * for HMAC to reuse this code. +/* ECDSA generate black key * * return Success on success. All other return values are considered a fail * case. */ -static Error caamSha(struct DescStruct* desc, int start) +int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) { - struct buffer* ctx[3]; Error err; - UINT4 i; - int sz = 0; - int ctxIdx = 0; - int offset = 0; + int part = 0; + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int phys; + void *vaddr[2]; - int ctxSz = shaSize(desc); - - /* get context */ - for (i = start; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->iv; - - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { - ctx[ctxIdx] = buf; - sz += buf->dataSz; - - if (ctx[ctxIdx]->dataSz + offset > (MAX_CTX * sizeof(UINT4))) { - return SizeIsTooLarge; - } - memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[ctxIdx]->data, - ctx[ctxIdx]->dataSz); - offset += ctx[ctxIdx]->dataSz; - ctxIdx++; - } - else { - break; - } + if (args != NULL) { + isBlackKey = args[0]; + pdECDSEL = args[1]; } - if (sz > ctxSz || ctxSz > (MAX_CTX * sizeof(UINT4))) { - return SizeIsTooLarge; + vaddr[0] = NULL; + vaddr[1] = NULL; + + desc->desc[desc->idx++] = pdECDSEL; + if (isBlackKey) { + /* create secure partition for private key out */ + part = caamFindUnusuedPartition(); + if (part < 0) { + WOLFSSL_MSG("error finding an unused partition for new key"); + return -1; + } + + /* create and claim the partition */ + err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (err != Success) { + WOLFSSL_MSG("error creating partition for secure ecc key"); + return -1; + } + + /* map secure partition to virtual address */ + phys = (CAAM_PAGE + (part << 12)); + buf[0].TheAddress = CAAM_ADR_TO_VIRTUAL(phys, + buf[0].Length + buf[1].Length + 16);/*add 16 for MAC on private*/ + desc->desc[desc->idx++] = phys; + + /* public x,y out */ + buf[1].TheAddress = buf[0].TheAddress + 16 + buf[0].Length; + desc->desc[desc->idx++] = phys + 16 + buf[0].Length; + } + else { + vaddr[0] = CAAM_ADR_MAP(0, buf[0].Length, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[0], buf[0].Length); + + vaddr[1] = CAAM_ADR_MAP(0, buf[1].Length, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], buf[1].Length); } - ASP_FlushCaches((Address)desc->iv, ctxSz); - /*Manage Context (current digest + 8 byte running message length)*/ - if ((desc->state & CAAM_ALG_INIT) != CAAM_ALG_INIT) { - /* don't load into the class 2 context register on inti. - Found that loading in caused context to not get set. */ - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2) + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; } + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; - /* add operation command */ - desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS2 | desc->state | - desc->type; - - /* Check case where there is no input. - In all cases the FIFO Load should be flushed. */ - if (i == desc->DescriptorCount) { - desc->lastFifo = desc->idx; - if (desc->idx + 1 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG | CAAM_IMM; - } - - /* save index for looping over input */ - desc->headIdx = desc->idx; do { - desc->idx = desc->headIdx; /* reset for each loop */ - if (i < desc->DescriptorCount) { - /* input must be a multiple of 64 bytes unless in final call */ - if (((desc->state & CAAM_ALG_FINAL) == CAAM_ALG_FINAL)) { - if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG), 0, 1, &i) < 0) { - return TooManyBuffers; - } - } - else { - if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG), 0, 64, &i) < 0) { - return TooManyBuffers; - } - } - } + err = caamDoJob(desc); + } while (err == CAAM_WAITING); - desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC2; - - /* set context out */ - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS2 + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); - - if ((err = caamDoJob(desc)) != Success) { - return err; - } - /* flush context output for each loop */ - ASP_FlushCaches((Address)desc->iv, ctxSz); - } while (i < desc->DescriptorCount); - - /* store context to buffers */ - { - unsigned char* pt = (unsigned char*)desc->iv; - for (i = 0; i < ctxIdx; i++) { - memcpy((unsigned char*)ctx[i]->data, pt, ctx[i]->dataSz); - pt += ctx[i]->dataSz; - ASP_FlushCaches(ctx[i]->data, ctx[i]->dataSz); - } + if (isBlackKey) { + /* store partition number holding black keys */ + if (err != Success) + caamFreePart(part); + else + args[2] = part; + } + else { + /* copy non black keys out to buffers */ + CAAM_ADR_UNMAP(vaddr[0], buf[0].TheAddress, buf[0].Length, 1); + CAAM_ADR_UNMAP(vaddr[1], buf[1].TheAddress, buf[1].Length, 1); } - return Success; + return err; +} + + +/* ECDSA verify signature + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSAVerify(DESCSTRUCT* desc, CAAM_BUFFER* buf, int sz, + unsigned int args[4]) +{ + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int msgSz = 0; + unsigned int vidx = 0; + unsigned int L; + int i = 0; + Error err; + void* vaddr[sz]; + + if (args != NULL) { + isBlackKey = args[0]; + pdECDSEL = args[1]; + msgSz = args[2]; + } + + if (pdECDSEL == 0) { + return -1; + } + else { + L = args[3]; /* keysize */ + desc->desc[desc->idx++] = pdECDSEL; + } + + /* public key */ + if (!isBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; + } + else { + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL((void*)desc->buf[i].data, + desc->buf[i].dataSz); + } + i++; + + /* message */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; i++; + + /* r */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; i++; + + /* s */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; i++; + + /* tmp buffer */ + vaddr[vidx] = CAAM_ADR_MAP(0, 2*L, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; i++; + + if (msgSz > 0) { + desc->desc[desc->idx++] = msgSz; + } + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (msgSz > 0) { + desc->desc[desc->idx] |= CAAM_ECDSA_MESREP_HASHED; + } + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (!isBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + } + i++; + + /* msg , r, s, tmp */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + + return err; +} + + +/* ECDSA generate signature + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4]) +{ + Error err; + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int msgSz = 0; + unsigned int vidx = 0; + int i = 0; + void* vaddr[sz]; + + if (args == NULL) { + return -1; + } + + isBlackKey = args[0]; + pdECDSEL = args[1]; + msgSz = args[2]; + if (pdECDSEL == 0) { + return -1; + } + + /* using parameters already in hardware */ + desc->desc[desc->idx++] = pdECDSEL; + + /* private key */ + if (!isBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; byte* pt; + printf("private :"); + pt = (byte*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL((void*)desc->buf[i].data, + desc->buf[i].dataSz); + } + i++; + + for (; i < sz; i++) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + #if 0 + { + unsigned int z; + byte *pt = (byte*)vaddr[vidx]; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; + } + + desc->desc[desc->idx++] = msgSz; + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey) { /* set flag to use AES-CCM with black key */ + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; + } + + /* add protinfo to operation command */ + desc->desc[desc->idx++] |= CAAM_ECDSA_MESREP_HASHED | CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (!isBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + } + i++; + + /* msg */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + + /* copy out the r and s values */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++; + + return err; +} + + +/* ECDH generate shared secret + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) +{ + Error err; + unsigned int isBlackKey = 0; + unsigned int peerBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int vidx = 0; + int i = 0; + void* vaddr[sz]; + + if (args != NULL) { + isBlackKey = args[0]; + peerBlackKey = args[1]; + pdECDSEL = args[2]; + } + + if (pdECDSEL == 0) { + return -1; + } + else { + /* using parameters already in hardware */ + desc->desc[desc->idx++] = pdECDSEL; + } + + /* public key */ + if (!peerBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; byte* pt; + printf("pubkey :"); + pt = (byte*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL((void*)desc->buf[i].data, + desc->buf[i].dataSz); + } + i++; + + /* private key */ + if (!isBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; byte* pt; + printf("private :"); + pt = (byte*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL((void*)desc->buf[i].data, + desc->buf[i].dataSz); + } + i++; + + /* shared output */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + i++; vidx++; + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; + } + + /* add protinfo to operation command */ + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (pdECDSEL == 0) { + /* unmap prime key */ + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; i++; + } + + if (!peerBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; + } + i++; + + if (!isBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; + } + i++; + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 1); + vidx++; i++; + + if (pdECDSEL == 0) { + /* unmap A , B*/ + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; i++; + } + return err; } /****************************************************************************** - CAAM TRNG Operations + IODevice Start, Transfer and Finish Buffer ****************************************************************************/ - -/* If Entropy is not ready then return Waiting */ -static Error caamRng(struct DescStruct* desc) +/* If Entropy is not ready then return CAAM_WAITING */ +int caamTRNG(unsigned char *out, int outSz) { int sz = 0; - int i; - - Address reg; /* RTENT reg to read */ - int ofst = sizeof(UINT4); + CAAM_ADDRESS reg; /* RTENT reg to read */ + unsigned char* local; + int ofst = sizeof(unsigned int); /* Check ENT_VAL bit to make sure entropy is ready */ - if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != - CAAM_ENTVAL) { - return Waiting; + if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != CAAM_ENTVAL) { + return CAAM_WAITING; } /* check state of TRNG */ @@ -1332,382 +1896,227 @@ static Error caamRng(struct DescStruct* desc) } /* read entropy from RTENT registers */ - reg = CAAM_RTENT0; + reg = CAAM_RTENT0; + sz = outSz; + local = out; - for (i = 0; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)buf->data; - sz = buf->dataSz; - - while (sz > 3 && reg <= CAAM_RTENT11) { - *((UINT4*)local) = CAAM_READ(reg); - reg += ofst; - local += ofst; - sz -= ofst; - } - - if (reg > CAAM_RTENT11 && sz > 0) { - return SizeIsTooLarge; - } - - /* handle non word32 size amount left over */ - if (sz > 0) { - UINT4 tmp = CAAM_READ(reg); - memcpy(local, (unsigned char*)&tmp, sz); - } - - ASP_FlushCaches(buf->data, buf->dataSz); + while (sz > 3 && reg <= CAAM_RTENT_MAX) { + unsigned int data = CAAM_READ(reg); + *((unsigned int*)local) = data; + reg += ofst; + local += ofst; + sz -= ofst; } + if (reg > CAAM_RTENT_MAX && sz > 0) { + return -1;//SizeIsTooLarge; + } - /* read RTENT11 to trigger new entropy generation */ - if (reg != CAAM_RTENT11) { - CAAM_READ(CAAM_RTENT11); + /* handle non unsigned int size amount left over */ + if (sz > 0) { + unsigned int tmp = CAAM_READ(reg); + memcpy(local, (unsigned char*)&tmp, sz); + } + + /* read the max RTENT to trigger new entropy generation */ + if (reg != CAAM_RTENT_MAX) { + CAAM_READ(CAAM_RTENT_MAX); } return Success; } -/****************************************************************************** - IODevice Start, Transfer and Finish Buffer - ****************************************************************************/ -/* args[0] holds the state such as encrypt/decrypt or init/update/final - * args[1] holds the ctx/key size - * args[2] holds the input size - * args[3] dependent on algo (such as AAD size with AES-CCM) */ -static Error caamTransferStart(IODeviceVector ioCaam, - Value type, const volatile Value args[4]) +/* cover a plain text key and make it a black key */ +int caamKeyCover(DESCSTRUCT* desc, int sz, unsigned int args[4]) { - struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam; - struct DescStruct* desc; + Error err; + unsigned int vidx = 0; + int i = 0; + void* vaddr[sz]; - /* currently only one desc is available for use */ - desc = &local->DescArray[0]; + (void)args; - /* check if the desc is idle before using */ - if (GetIORequestStatus((IORequest)desc) != IdleIORequest) { - return ResourceNotAvailable; - } + /* add input key */ + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1) + + desc->buf[i].dataSz; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; + i++; + /* add output */ + desc->desc[desc->idx++] = (CAAM_FIFO_S | CAAM_CLASS1 | desc->state) + + desc->buf[i].dataSz; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz + 16, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz + 16); + +#if 0 + /* sanity check can we load it? */ + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | 0x500000) + + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], desc->buf[1].dataSz); +#endif + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + CAAM_ADR_UNMAP(vaddr[0], desc->buf[0].data, desc->buf[0].dataSz, 0); + CAAM_ADR_UNMAP(vaddr[1], desc->buf[1].data, desc->buf[1].dataSz + 16, 1); + return err; +} + + +/****************************************************************************** + Init + ****************************************************************************/ + +/* initialize a DESCSTRUCT for an operation */ +void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4], + CAAM_BUFFER* buf, int sz) +{ + int i; + + desc->type = type; desc->idx = 0; desc->output = 0; desc->ctxOut = 0; desc->outputIdx = 0; desc->alignIdx = 0; desc->lastFifo = 0; - desc->state = args[0]; - desc->ctxSz = args[1]; - desc->inputSz = args[2]; + if (args == NULL) { + desc->state = 0; + desc->ctxSz = 0; + desc->inputSz = 0; + } + else { + desc->state = args[0]; + desc->ctxSz = args[1]; + desc->inputSz = args[2]; + } desc->aadSz = 0; + desc->DescriptorCount = sz; + desc->startIdx = 0; desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/ - switch (type) { - case CAAM_AESECB: - case CAAM_AESCBC: - if (desc->inputSz % 16 != 0) { - return ArgumentError; - } - /* fall through to break */ - case CAAM_AESCTR: - break; - - case CAAM_AESCCM: - memset((unsigned char*)desc->aadSzBuf, 0, sizeof(desc->aadSzBuf)); - if (args[3] > 0) { - /* encode the length in */ - if (args[3] <= 0xFEFF) { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = 2; - pt[0] = ((args[3] & 0xFF00) >> 8); - pt[1] = (args[3] & 0x00FF); - } - else if (args[3] <= 0xFFFFFFFF) { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = 6; - pt[0] = 0xFF; pt[1] = 0xFE; - pt[2] = ((args[3] & 0xFF000000) >> 24); - pt[3] = ((args[3] & 0x00FF0000) >> 16); - pt[4] = ((args[3] & 0x0000FF00) >> 8); - pt[5] = (args[3] & 0x000000FF); - } - } - break; - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - break; - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - break; - - case CAAM_ENTROPY: - break; - - default: - /* unknown type */ - return UsageNotSupported; + for (i = 0; i < sz; i++) { + desc->buf[i].data = buf[i].TheAddress; + desc->buf[i].dataSz = buf[i].Length; } - - desc->DescriptorCount = 0; - desc->type = type; - desc->running = true; - StartIORequest((IORequest)desc); - - /* For now only require READ permissions */ - SetIORequestBufferPermissions((IORequest)desc, MEMORY_READ); - return Success; } -static Error caamTransferBuffer(IODeviceVector TheIODeviceVector, - IORequest req, IODescriptor NewIODescriptor, - Address data, Address dataSz) +int InitCAAM(void) { - struct DescStruct* desc = (struct DescStruct*)req; - Error err; - - switch (desc->type) { - case CAAM_AESECB: - case CAAM_AESCTR: - case CAAM_AESCBC: - case CAAM_AESCCM: - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - case CAAM_ENTROPY: - { /* set buffer for transfer finish */ - struct buffer* buf; - if (desc->DescriptorCount >= MAX_BUF) { - return TooManyBuffers; - } - buf = &desc->buf[desc->DescriptorCount]; - buf->data = data; - buf->dataSz = dataSz; - } - err = Success; - break; - - default: - err = UsageNotSupported; - } - - if (err != Success) { - desc->running = false; - DismissIORequest(req); - return err; - } - - desc->DescriptorCount++; - return Success; -} - - -static Error caamTransferFinish(IODeviceVector ioCaam, IORequest req) -{ - struct DescStruct* desc = (struct DescStruct*)req; Error ret; - /* construct desc */ - switch (desc->type) { - case CAAM_AESECB: - case CAAM_AESCTR: - case CAAM_AESCBC: - ret = caamAes(desc); - break; - - case CAAM_AESCCM: - ret = caamAead(desc); - break; - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - ret = caamSha(desc, 0); - break; - - case CAAM_ENTROPY: - ret = caamRng(desc); - break; - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - ret = caamBlob(desc); - break; - - default: - ret = UsageNotSupported; - } - - desc->running = false; - DismissIORequest(req); - return ret; -} - - -/****************************************************************************** - IODevice Interrupt and Init - ****************************************************************************/ - -static Error caamTransferWrite(IODeviceVector ioCaam, - IORequest req, Value dataSz, const volatile Value *data) -{ - DismissIORequest(req); - return UsageNotSupported; -} - - -static void caamTransferAbort(IODeviceVector ioCaam, IORequest req) -{ - DismissIORequest(req); -} - - -static void caamTransferRecall(IODeviceVector ioCaam, IODescriptor req) -{ - -} - - -static void HandleInterrupt(Address id) -{ - struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)id; - Value InterruptStatus = INTERRUPT_AtomicWrite(&local->InterruptStatus, 0); - int i; - - /* Loop through descriptors and try to dismiss them */ - for (i = 0; i < DESC_COUNT; i++) { - struct DescStruct* desc = &local->DescArray[i]; - if (InterruptStatus & (1 << i)) { - desc->running = false; - if (GetIORequestStatus((IORequest)desc) == IORequestSuspended) { - ContinueIORequest((IORequest)desc); - } - else { - DismissIORequest((IORequest)desc); - } - } - } -} - - -static Error caamCreate(IODeviceVector ioCaam) -{ - return Success; -} - - -void InitCAAM(void) -{ - /* get IO vector and set it up */ - IODeviceVector ioCaam = &caam.caamVector; - unsigned int reg; - int i; - Error ret; - - - ioCaam->Create = &caamCreate; - ioCaam->ReadRegister = &caamReadRegister; - ioCaam->WriteRegister = &caamWriteRegister; - - ioCaam->TransferStart = &caamTransferStart; - ioCaam->TransferBuffer = &caamTransferBuffer; - ioCaam->TransferWrite = &caamTransferWrite; - ioCaam->TransferFinish = &caamTransferFinish; - ioCaam->TransferAbort = &caamTransferAbort; - ioCaam->TransferRecall = &caamTransferRecall; -#ifdef HARDWARE_CACHE_COHERENCY - ioCaam->IOSynchronizationNotRequired = 1; -#endif - - RegisterIODeviceVector(ioCaam, DRIVER_NAME); - RequestIOTerminationTask(ioCaam, 10); - - /* Initialize descriptors */ - for (i = 0; i < BUFFER_COUNT; i++) { - InitializeIODescriptor(ioCaam, &caam.IODescriptorArray[i]); - } - - /* Initialize Descriptors */ - for (i = 0; i < DESC_COUNT; i++) { - InitializeIORequest(ioCaam, &caam.DescArray[i].TheIORequest, - IOREQUEST_STANDARD); - caam.DescArray[i].running = false; - caam.DescArray[i].caam = &caam; - } - - - /* call interrupt to make IORequests available */ - caam.InterruptStatus = 0; - INTERRUPT_InitCall(&caam.HandleInterruptCall, - &HandleInterrupt, "Start up CAAM IORequest"); - - /* set clock speed for CAAM. Setting it here to allow for restricting - access */ - #define REGS_CCM_BASE (0xf20c4000) - #define HW_CCM_CCGR0_ADDR (0xf20c4068) - #define CG(x) (3 << (x*2)) - - reg = CG(6) | CG(5) | CG(4); - *(volatile unsigned int*)HW_CCM_CCGR0_ADDR = - *(volatile unsigned int*)HW_CCM_CCGR0_ADDR | reg; - - /* set up job ring */ - - /* @TODO create partition in physical memory for job rings - current partition security is set to the default */ - for (i = 1; i < CAAM_PAGE_MAX; i++) { - ret = caamCreatePartition(i, i); - if (ret == 0) { - break; - } - - if (ret != MemoryMapMayNotBeEmpty) { - INTERRUPT_Panic(); - } - } - + /* map to memory addresses needed for accessing CAAM */ + ret = CAAM_SET_BASEADDR(); if (ret != 0) { - INTERRUPT_Panic(); + return ret; } - caam.ring.page = i; - caam.ring.JobIn = (CAAM_PAGE + (i << 12)); - caam.ring.JobOut = caam.ring.JobIn + 16; - caam.ring.Desc = caam.ring.JobOut + 16; + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("CHANUM_MS = 0x%08X\n", CAAM_READ(0x0FF0)); + printf("DECO0MIDR_MS = 0x%08X\n", CAAM_READ(0x00A0)); + printf("SCFGR = 0x%08X\n", CAAM_READ(0x000C)); + print_jdkek(); + printSecureMemoryInfo(); + printf("JR0MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0010), + CAAM_READ(0x0014)); + printf("JR1MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0018), + CAAM_READ(0x001C)); + printf("JR2MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0020), + CAAM_READ(0x0024)); + #endif - /* set physical address of job rings */ - CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn ^ 0xF0000000); - CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut ^ 0xF0000000); + ret = Failure; + for (caam.ring.page = 1; caam.ring.page < 7; caam.ring.page++) { + ret = caamCreatePartition(caam.ring.page, caam.ring.page, + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (ret == Success) + break; + } + if (ret != Success) { + return -1; + } - /* Initialize job ring sizes to 1 */ - CAAM_WRITE(CAAM_IRSR0, 1); - CAAM_WRITE(CAAM_ORSR0, 1); + caam.ring.JobIn = CAAM_PAGE + (caam.ring.page << 12); + caam.ring.JobOut = caam.ring.JobIn + (CAAM_JOBRING_SIZE * + sizeof(unsigned int)); + caam.ring.Desc = caam.ring.JobOut + (2 * CAAM_JOBRING_SIZE * + sizeof(unsigned int)); + + CAAM_INIT_MUTEX(&caam.ring.jr_lock); + + caam.ring.VirtualIn = +// (void*)CAAM_ADR_TO_VIRTUAL(caam.ring.JobIn, +// CAAM_JOBRING_SIZE * sizeof(unsigned int)); + mmap_device_memory(NULL, + CAAM_JOBRING_SIZE * sizeof(unsigned int), + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.JobIn); + memset(caam.ring.VirtualIn, 0, CAAM_JOBRING_SIZE * sizeof(unsigned int)); + caam.ring.VirtualOut = +// (void*)CAAM_ADR_TO_VIRTUAL(caam.ring.JobOut, +// 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + mmap_device_memory(NULL, + 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int), + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.JobOut); + memset(caam.ring.VirtualOut, 0, 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + caam.ring.VirtualDesc = +// (void*)CAAM_ADR_TO_VIRTUAL(caam.ring.Desc, +// CAAM_DESC_MAX * CAAM_JOBRING_SIZE); + mmap_device_memory(NULL, + CAAM_DESC_MAX * CAAM_JOBRING_SIZE, + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.Desc); + memset(caam.ring.VirtualDesc, 0, CAAM_DESC_MAX * CAAM_JOBRING_SIZE); + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("extra wolfssl debug - Setting JOB IN 0x%08X\n", caam.ring.JobIn); + printf("extra wolfssl debug - Setting JOB OUT 0x%08X\n", caam.ring.JobOut); + printf("extra wolfssl debug - Setting DESC 0x%08X\n", caam.ring.Desc); + #endif + CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn); + CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut); + + /* Initialize job ring sizes */ + CAAM_WRITE(CAAM_IRSR0, CAAM_JOBRING_SIZE); + CAAM_WRITE(CAAM_ORSR0, CAAM_JOBRING_SIZE); /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */ - CAAM_WRITE((CAAM_BASE | 0x0004), CAAM_READ(CAAM_BASE | 0x0004) | 0x40000000); + CAAM_WRITE(0x0004, CAAM_READ(0x0004) | 0x40000000); /* start up RNG if not already started */ if (caamInitRng(&caam) != 0) { + WOLFSSL_MSG("Error initializing RNG"); INTERRUPT_Panic(); + return -1; } + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + print_jdkek(); + printf("FADR = 0x%08X\n", CAAM_READ(0x0FCC)); + printf("RTMCTL = 0x%08X\n", CAAM_READ(0x0600)); + #endif + WOLFSSL_MSG("Successfully initilazed CAAM driver"); + return 0; } + +int caamJobRingFree() +{ + CAAM_FREE_MUTEX(&caam.ring.jr_lock); + caamFreeAllPart(); + return 0; +} +#if defined(__INTEGRITY) || defined(INTEGRITY) void (*__ghsentry_bspuserinit_InitCAAM)(void) = &InitCAAM; #endif /* INTEGRITY */ +#endif diff --git a/wolfcrypt/src/port/caam/caam_error.c b/wolfcrypt/src/port/caam/caam_error.c new file mode 100644 index 000000000..a04391e31 --- /dev/null +++ b/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; +} + diff --git a/wolfcrypt/src/port/caam/caam_init.c b/wolfcrypt/src/port/caam/caam_init.c deleted file mode 100644 index 014341cd6..000000000 --- a/wolfcrypt/src/port/caam/caam_init.c +++ /dev/null @@ -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 - -#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ - defined(WOLFSSL_IMX6_CAAM_BLOB) - -#include -#include -#include - -#define WC_CAAM_BLOB_SZ 48 - -#ifndef WC_CAAM_PASSWORD - #define WC_CAAM_PASSWORD "!systempassword" -#endif - -#if defined(__INTEGRITY) || defined(INTEGRITY) - #include - #include - static IODevice caam = NULLIODevice; -#endif - -#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) -#include -#include - -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 */ - diff --git a/wolfcrypt/src/port/caam/caam_qnx.c b/wolfcrypt/src/port/caam/caam_qnx.c new file mode 100644 index 000000000..fa353ed0c --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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; +} + diff --git a/wolfcrypt/src/port/caam/wolfcaam_cmac.c b/wolfcrypt/src/port/caam/wolfcaam_cmac.c new file mode 100644 index 000000000..f67944a63 --- /dev/null +++ b/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 +#endif + +#include + +#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM) + +#include +#include +#include +#include + +/* 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 diff --git a/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c b/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c new file mode 100644 index 000000000..a53247b75 --- /dev/null +++ b/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 +#endif + +#include + +#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM) + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include + +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#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 */ diff --git a/wolfcrypt/src/port/caam/wolfcaam_init.c b/wolfcrypt/src/port/caam/wolfcaam_init.c new file mode 100644 index 000000000..4aacf0bef --- /dev/null +++ b/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 +#endif + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB) + +#include +#include +#include + +#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 + 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 */ + diff --git a/wolfcrypt/src/port/caam/wolfcaam_qnx.c b/wolfcrypt/src/port/caam/wolfcaam_qnx.c new file mode 100644 index 000000000..1540ae96d --- /dev/null +++ b/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 +#endif + +#include + +#if defined(WOLFSSL_QNX_CAAM) + +#include +#include +#include +#include +#include +#include + +/* 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 diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 15127b084..74089b8c2 100644 --- a/wolfcrypt/src/random.c +++ b/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 - #include 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 */ diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 63f4ed402..97e91a6f8 100644 --- a/wolfcrypt/src/sha.c +++ b/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) && \ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 50b8cf60f..aa336d3ab 100644 --- a/wolfcrypt/src/sha256.c +++ b/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) diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index ef09e5404..9bde2ec06 100644 --- a/wolfcrypt/src/sha512.c +++ b/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) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index cc7022e14..bf02950ca 100644 --- a/wolfcrypt/src/wc_port.c +++ b/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 #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; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 41cf264de..d734c3fd8 100644 --- a/wolfcrypt/test/test.c +++ b/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) { diff --git a/wolfssl/wolfcrypt/cmac.h b/wolfssl/wolfcrypt/cmac.h index 80f13ce97..de94ce32d 100644 --- a/wolfssl/wolfcrypt/cmac.h +++ b/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 }; diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 5981d0f00..ccb4e9626 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -58,6 +58,9 @@ #ifndef NO_DES3 #include #endif +#ifdef WOLFSSL_CMAC + #include +#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 diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index f0e95ba2b..57ad1d0ff 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/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]; diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 647714956..24465d9c4 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/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 \ diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index e2ee13c32..49143b6ac 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/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 diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h index cac1742c0..a1bb05bb0 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_driver.h +++ b/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 +#define CAAM_ORBAR2 0x3024 + //0x1024 +#define CAAM_ORSR2 0x302C +#define CAAM_ORJAR2 0x303C + +#define JRCFGR_JR0_LS 0x1054 + /* 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_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 CAAM_BASE + 0x8014 -#define CAAM_C1MR CAAM_BASE + 0x8004 +#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_.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_.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 */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_error.h b/wolfssl/wolfcrypt/port/caam/caam_error.h new file mode 100644 index 000000000..2f3bc3192 --- /dev/null +++ b/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 */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_qnx.h b/wolfssl/wolfcrypt/port/caam/caam_qnx.h new file mode 100644 index 000000000..7c1d48bab --- /dev/null +++ b/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 +#include +#include +#include +#include + +#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 */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h index 8c39605d7..1bc803252 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -23,13 +23,20 @@ #define WOLF_CRYPT_CAAM_INIT_H #include - -#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) - #include +/* include for porting layer */ +#ifdef WOLFSSL_QNX_CAAM + #include +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_QNX_CAAM) + + #if defined(__INTEGRITY) || defined(INTEGRITY) #include + 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 */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h new file mode 100644 index 000000000..3a015ab9e --- /dev/null +++ b/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 + +#ifndef WOLFCAAM_CMAC_H +#define WOLFCAAM_CMAC_H + +#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM) + +#include + +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 */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h new file mode 100644 index 000000000..213cde18c --- /dev/null +++ b/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 + +#ifndef WOLFCAAM_ECDSA_H +#define WOLFCAAM_ECDSA_H + +#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM) + +#include + +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 */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 6d180137e..bbbf40c0b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/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 diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 6203d648d..657a4ed07 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/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) diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 9538fed7b..646c042be 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/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" diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index f3e79a263..6b11f755b 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/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" diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index ef489f9e9..7062e79cf 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/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 */ diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 1ce533e8a..7e09ae386 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/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 */ diff --git a/wolfssl/wolfcrypt/wolfmath.h b/wolfssl/wolfcrypt/wolfmath.h index 3d9830a15..f421d2ab6 100644 --- a/wolfssl/wolfcrypt/wolfmath.h +++ b/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);