diff --git a/maxq10xx/Makefile b/maxq10xx/Makefile new file mode 100644 index 00000000..ad7fe70c --- /dev/null +++ b/maxq10xx/Makefile @@ -0,0 +1,36 @@ +# MAXQ10xx Examples Makefile +CC = gcc +LIB_PATH = /usr/local +CFLAGS = -Wall -I$(LIB_PATH)/include +LIBS = -L$(LIB_PATH)/lib -lm + +# option variables +DYN_LIB = -lwolfssl +STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a +DEBUG_FLAGS = -g -DDEBUG +DEBUG_INC_PATHS = -MD +OPTIMIZE = -Os + +# Options +#CFLAGS+=$(DEBUG_FLAGS) +CFLAGS+=$(OPTIMIZE) +#LIBS+=$(STATIC_LIB) +LIBS+=$(DYN_LIB) + +# build targets +SRC=$(wildcard *.c) +TARGETS=$(patsubst %.c, %, $(SRC)) + +.PHONY: clean all + +all: $(TARGETS) + +debug: CFLAGS+=$(DEBUG_FLAGS) +debug: all + +# build template +%: %.c + $(CC) -o $@ $< $(CFLAGS) $(LIBS) + +clean: + rm -f $(TARGETS) diff --git a/maxq10xx/README.md b/maxq10xx/README.md new file mode 100644 index 00000000..ed69c908 --- /dev/null +++ b/maxq10xx/README.md @@ -0,0 +1,149 @@ +# wolfSSL with Analog Devices MAXQ10xx + +This example implements a very simple client application that uses the Analog +Devices MAXQ1065 or MAXQ1080 to do cryptographic operations. Please see the +product documentation for what operations are supported. + +NOTE: These instructions are for a MAXQ1065 or MAXQ1080 evaluation board plugged + into the 40-pin GPIO headers of a RaspberryPi. The SDK and example + application are built and executed on the RaspberryPi. + +## Building and Installing wolfSSL + +You need to have wolfSSL built via the MAXQ10xx SDK. Please contact Analog +Devices to request the SDK. Make sure you have all the required hardware and +software. Follow the instructions to build the SDK. Once completed, there will +be two instances of wolfSSL in the SDK directory; one for server operations +(`wolfssl`) and one for client operations (`maxq10xx-wolfssl`). The client +instance's cryptographic operations are performed by the MAXQ1065 or MAXQ1080. +Enter the `maxq10xx-wolfssl` and install the client instance: + +``` +cd /path/to/maxq10xx-sdk/maxq10xx-wolfssl +sudo make install +sudo ldconfig +``` + +This will put the appropriate header files and dynamic libraries in +`/usr/local/include` and `/usr/local/lib/`. + +NOTE: Do NOT install the instance for server operations (`wolfssl`). + +## Setting Up the MAXQ1065 or MAXQ1080 + +Follow the SDK instructions for generating and loading the desired cryptographic +artifacts into MAXQ1065 or MAXQ1080. This will depend on the TLS version and +algorithms you want to use. + +## Dummy Keys + +The build of wolfSSL uses our pkcallbacks configuration to allow MAXQ1065 or +MAXQ1080 to do the cryptographic operations. In order for wolfSSL to understand +the algorithms being used, on the command line we substitute the private key +with a dummy public key at runtime. You can generate these dummy public keys by +running the following commands: + +``` +openssl x509 -in .pem -pubkey -noout > ecc-p256-pub.pem +openssl x509 -in .pem -pubkey -noout > rsa-2048-pub.pem +``` + +`.pem` must be a certificate with an ECC P-256 public key in it. +`.pem` must be a certificate with an RSA 2048-bit public key in it. +For your convenience, they have already been provided. + +``` +make maxq10xx-wolfssl-client +``` + +## Running the Example + +The client and server are executed with different command-line parameters +depending on the desired algorithms and TLS version. First, go into the correct +locations in your shell: + +``` +cd /path/to/maxq10xx-sdk/wolfssl +``` + +``` +cd /path/to/wolfssl-examples/maxq10xx +``` + +Depending on which of the following algorithms and TLS versions, execute the +associated commands as shown. + +### TLS 1.2 PSK (MAXQ1065 or MAXQ1080) + +``` +./examples/server/server -s -v 3 -l PSK-AES128-CCM-8 +``` + +``` +./maxq10xx-wolfssl-client -tls12 -psk +``` + +### TLS 1.2 ECC (MAXQ1065 or MAXQ1080) + +``` +./examples/server/server -F -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 \ + -c ../pki/CA_secp256r1/cert_server_ECDSA_secp256r1_secp256r1.pem \ + -k ../pki/CA_secp256r1/privkey_server_ECDSA_secp256r1_secp256r1.pem \ + -A ../pki/CA_secp256r1/cert_CA.pem +``` + +``` +./maxq10xx-wolfssl-client -tls12 -ecc +``` + +### TLS 1.3 PSK (Only MAXQ1080) + +``` +./examples/server/server -v 4 -s -l TLS13-AES128-GCM-SHA256 +``` + +``` +./maxq10xx-wolfssl-client -tls13 -psk +``` + +### TLS 1.3 ECC (Only MAXQ1080) + +``` +./examples/server/server -F -v 4 -l TLS13-AES128-GCM-SHA256 \ + -c ../pki/CA_secp256r1/cert_server_ECDSA_secp256r1_secp256r1.pem \ + -k ../pki/CA_secp256r1/privkey_server_ECDSA_secp256r1_secp256r1.pem \ + -A ../pki/CA_secp256r1/cert_CA.pem +``` + +``` +./maxq10xx-wolfssl-client -tls13 -ecc +``` + +### TLS 1.3 RSA and FFDHE (Only MAXQ1080) + +``` +./examples/server/server -F -v 4 -l TLS13-AES128-GCM-SHA256 \ + -c ../pki/CA_RSA_2048/cert_server_RSA_2048_RSA_2048.pem \ + -k ../pki/CA_RSA_2048/privkey_server_RSA_2048_RSA_2048.pem \ + -A ../pki/CA_RSA_2048/cert_CA.pem +``` + +``` +./maxq10xx-wolfssl-client -tls13 -rsa +``` + +### Expected Output + +The server will print very little status information about the algorithms and +ciphersuite negotiated. It will wait for a message from the client. + +The client will give lots of debug and status logging. It will then prompt the +user for a message. You should type in something like "Hello, this is MAXQ!" and +press enter. + +The server will print out the message you typed, send the message "I hear you +fa shizzle!" and then terminate. + +The client will print the message it received from the server along with more +debug and status logging and then terminate. + diff --git a/maxq10xx/ecc-p256-pub.pem b/maxq10xx/ecc-p256-pub.pem new file mode 100644 index 00000000..c462fd50 --- /dev/null +++ b/maxq10xx/ecc-p256-pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEedj066yAnDwNDvUCfb0qgTutLVI3 +WdOLH7S4Rs+f3fmipHapKnu3BhCGW3L5CHeoCOedCgSigIsCNJdwS8z2jA== +-----END PUBLIC KEY----- diff --git a/maxq10xx/maxq10xx-wolfssl-client.c b/maxq10xx/maxq10xx-wolfssl-client.c new file mode 100644 index 00000000..22751884 --- /dev/null +++ b/maxq10xx/maxq10xx-wolfssl-client.c @@ -0,0 +1,389 @@ +/* maxq10xx-wolfssl-client.c + * + * Based on client-tls-pkcallback.c + * + * Copyright (C) 2006-2022 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-1301, USA + */ + +/* This example shows how to write a simple TLS client that uses the features + * of the Analog Devices MAXQ 1065 and 1080. */ + +#include +#include +#include +#include +#include +#include +#include + +/* wolfSSL */ +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include +#include +#include +#include +#include + +#if (defined(WOLFSSL_MAXQ1065) || defined(WOLFSSL_MAXQ108X)) && \ + defined(HAVE_PK_CALLBACKS) && defined(WOLF_CRYPTO_CB) && \ + !defined(NO_PSK) && !defined(HAVE_EXTENDED_MASTER) && \ + defined(NO_WOLFSSL_SERVER) + +/* -------------- */ +/* Configurations */ +/* -------------- */ + +/* Please define this if you want wolfSSL's debug output */ +#define WANT_DEBUG + +/* Please set the server's address and the port it listens on */ +#define DEFAULT_SERVER "127.0.0.1" +#define DEFAULT_PORT 11111 + +/* ------------------------------------ */ +/* No modifications required below here */ +/* ------------------------------------ */ + +/* identity is OpenSSL testing default for openssl s_client, keep same */ +static const char* kIdentityStr = "Client_identity"; + +static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)ssl; + (void)hint; + (void)key; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + XSTRNCPY(identity, kIdentityStr, id_max_len); + + /* For TLS 1.2, we indicate that MAXQ has the PSK. */ + return USE_HW_PSK; +} + +#ifdef WOLFSSL_TLS13 +static WC_INLINE unsigned int my_psk_client_cs_cb(WOLFSSL* ssl, + const char* hint, char* identity, unsigned int id_max_len, + unsigned char* key, unsigned int key_max_len, const char* ciphersuite) +{ + (void)ssl; + (void)hint; + (void)key; + (void)key_max_len; + +#ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + /* Multiple calls for each cipher suite. First identity byte indicates the + * number of identites seen so far for cipher suite. */ + if (identity[0] != 0) { + return 0; + } +#endif + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + XSTRNCPY(identity, kIdentityStr, id_max_len); + XSTRNCAT(identity, ciphersuite + XSTRLEN(ciphersuite) - 6, id_max_len); + + /* For TLS 1.3, we just return an unmodified key. */ + return 32; +} +#endif /* WOLFSSL_TLS13 */ + +static void print_usage() { + fprintf(stderr, "usage: ./maxq10xx-wolfssl-client [-tls12|-tls13] " + "[-ecc|-rsa|-psk] \n"); + fprintf(stderr, "Use `example/client/client -e` to get a list of cipher " + "suites.\n"); + fprintf(stderr, "Specifying a cipher suite is Optional.\n"); +} + +#define TLS12 1 +#define TLS13 2 + +#define ECC 1 +#define RSA 2 +#define PSK 3 + +static int tls_version = TLS12; +static int alg = ECC; +static char *key_file = NULL; +static char *ciphersuite = NULL; + +static int cmd_line_parse(int argc, char** argv) { + const size_t tls_vers_len = 6; + const size_t alg_len = 4; + + if ((argc != 3) && (argc != 4)) { + print_usage(); + return -1; + } + + if (strncmp("-tls12", argv[1], tls_vers_len) == 0) { + tls_version = TLS12; + } + else if (strncmp("-tls13", argv[1], tls_vers_len) == 0) { +#ifdef WOLFSSL_TLS13 + tls_version = TLS13; +#else + fprintf(stderr, "TLS 1.3 is not supported on MAXQ1065.\n"); + return -1; +#endif + } + else { + print_usage(); + return -1; + } + + if (strncmp("-ecc", argv[2], alg_len) == 0) { + alg = ECC; + key_file = "ecc-p256-pub.pem"; + } + else if (strncmp("-rsa", argv[2], alg_len) == 0) { + alg = RSA; + key_file = "rsa-2048-pub.pem"; + } + else if (strncmp("-psk", argv[2], alg_len) == 0) { + alg = PSK; + } + else { + print_usage(); + return -1; + } + + if (argc == 4) { + ciphersuite = argv[3]; + } + + return 0; +} + +int main(int argc, char** argv) +{ + int ret, err; + int sockfd = SOCKET_INVALID; + struct sockaddr_in servAddr; + char buff[256]; + size_t len; + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + + /* Command-line parameter check */ + ret = cmd_line_parse(argc, argv); + if (ret < 0) { + goto exit; + } + + /* 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 exit; + } + + /* 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 */ + + /* Get the server IPv4 address from the command line call */ + if (inet_pton(AF_INET, DEFAULT_SERVER, &servAddr.sin_addr) != 1) { + fprintf(stderr, "ERROR: invalid address\n"); + ret = -1; + goto exit; + } + + /* Connect to the server */ + if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) + == -1) { + fprintf(stderr, "ERROR: failed to connect\n"); + goto exit; + } + + /*---------------------------------------------------*/ + /* Start of wolfSSL initialization and configuration */ + /*---------------------------------------------------*/ +#ifdef WANT_DEBUG + wolfSSL_Debugging_ON(); +#endif + + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to initialize the library\n"); + goto exit; + } + + /* Create and initialize WOLFSSL_CTX */ +#ifdef WOLFSSL_TLS13 + if (tls_version == TLS13) + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + else +#endif /* WOLFSSL_TLS13 */ + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + + if (ctx == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + goto exit; + } + + /* At this point you would normally register a CA certificate, however, it + * resides in MAXQ10xx and has already been registered. */ + + /* Load the dummy private key; actually a public key. The actual private + * key resides in MAXQ 10xx. */ + if (key_file != NULL) { + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, key_file, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the " + "file.\n", key_file); + goto exit; + } + } + + /* If specified, set the ciphersuite. */ + if (ciphersuite != NULL) { + if (wolfSSL_CTX_set_cipher_list(ctx, ciphersuite) != WOLFSSL_SUCCESS) { + fprintf(stderr, "Invalid cipher suite.\n"); + print_usage(); + goto exit; + } + } + + if (alg == PSK) { + wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); +#ifdef WOLFSSL_TLS13 + if (tls_version == TLS13) { + wolfSSL_CTX_set_psk_client_cs_callback(ctx, my_psk_client_cs_cb); + } +#endif /* WOLFSSL_TLS13 */ + + if (ciphersuite != NULL) { + wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)ciphersuite); + } + } + + /* Validate peer certificate */ + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); + + /* Create a WOLFSSL object */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + ret = -1; + goto exit; + } + +#ifdef WOLFSSL_TLS13 + if (alg == RSA) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + ret = -1; + goto exit; + } + } +#endif /* WOLFSSL_TLS13 */ + + /* 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 exit; + } + + /* Connect to wolfSSL on the server side */ + do { + ret = wolfSSL_connect(ssl); + err = wolfSSL_get_error(ssl, ret); + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to connect to wolfSSL\n"); + goto exit; + } + + /* 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 exit; + } + 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 exit; + } + + /* 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 exit; + } + + /* Print to stdout any data the server sends */ + printf("Server: %s\n", buff); + + ret = 0; /* success */ + +exit: + /* Cleanup and return */ + if (sockfd != SOCKET_INVALID) + close(sockfd); + if (ssl != NULL) + wolfSSL_free(ssl); + if (ctx != NULL) + wolfSSL_CTX_free(ctx); + + wolfSSL_Cleanup(); + + return ret; +} + +#else + +int main(int argc, char** argv) +{ + printf("Warning: Required flags have not been used!\n" + "Please configure with the following flags:\n" + " --enable-pkcallbacks\n" + " --enable-cryptocb\n" + " --disable-extended-master\n" + " --enable-psk\n" + " --enable-aesccm\n" + " --with-maxq10xx=MAXQ108x|MAXQ1065\n" + " CFLAGS=-DNO_WOLFSSL_SERVER\n" +); + return -1; +} +#endif /* (WOLFSSL_MAXQ1065 || WOLFSSL_MAXQ108X) && HAVE_PK_CALLBACKS && + * WOLF_CRYPTO_CB && !NO_PSK && !HAVE_EXTENDED_MASTER && + * NO_WOLFSSL_SERVER */ diff --git a/maxq10xx/rsa-2048-pub.pem b/maxq10xx/rsa-2048-pub.pem new file mode 100644 index 00000000..56b36e97 --- /dev/null +++ b/maxq10xx/rsa-2048-pub.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0Z1C9aj1MSYFw+TQPBG +NaYDYaic3Y1LyvziYtMMas/C5Kok4m9AWo/87Bl19CVd1VCG4syl2+GtfEkA6WW7 +/dTLVZn+XtGb+dvbILRxcTWUUa/87OZGfwAhrULFwcguKN51PgncZ54Rkej9qAHe +SeikJh0K8wgGousYNgNCfljnDoMKazKYCyiGYuwmvdx37596z8Ii99W+OTg38cft +lTEMSmBy8MEswme6KgA62+cVZDYlngm1ox8VwNMMntDx2nXsw0nXwlOd9Rd+Tv9D +T9raIyGxIyxaOjsUsSyRipKUuJUgFY40jO+VuHIpvNxqlG4ISaib8zdB96ML+WFB +8QIDAQAB +-----END PUBLIC KEY-----