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);