diff --git a/IDE/include.am b/IDE/include.am index 474ebf78c..86d1541b0 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -38,6 +38,7 @@ include IDE/XilinxSDK/include.am include IDE/VisualDSP/include.am include IDE/QNX/include.am include IDE/WINCE/include.am +include IDE/iotsafe/include.am EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif EXTRA_DIST+= IDE/OPENSTM32/README.md diff --git a/IDE/iotsafe/Makefile b/IDE/iotsafe/Makefile new file mode 100644 index 000000000..5f047abc6 --- /dev/null +++ b/IDE/iotsafe/Makefile @@ -0,0 +1,113 @@ +# Makefile +# +# Copyright (C) 2006-2021 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# +CROSS_COMPILE:=arm-none-eabi- +CC:=$(CROSS_COMPILE)gcc +LD:=$(CROSS_COMPILE)gcc +LSCRIPT:=target.ld + +WOLFSSL_ROOT=$(PWD)/../.. +WOLFSSL_BUILD=build/wolfssl + + +OBJCOPY:=$(CROSS_COMPILE)objcopy + +CFLAGS:=-mthumb -g -ggdb -Wall -Wno-main -Wstack-usage=65535 -Wno-unused -I$(WOLFSSL_ROOT) -I. +CFLAGS+=-lc -lg -lm -Wno-pointer-sign +#CFLAGS+=-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -lm +CFLAGS+=-mcpu=cortex-m3 +CFLAGS+=-DWOLFSSL_USER_SETTINGS +ASFLAGS+=-mthumb -mlittle-endian -mthumb-interwork -ggdb -ffreestanding -mcpu=cortex-m3 +LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -mthumb -mthumb-interwork -mlittle-endian +#LDFLAGS+=-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -lm +LDFLAGS+=-mcpu=cortex-m3 +LDFLAGS+=-lc -lg -lm + + +OBJS:=main.o startup.o devices.o memory-tls.o + +WOLFSSL_OBJS += \ + $(WOLFSSL_BUILD)/internal.o \ + $(WOLFSSL_BUILD)/wolfio.o \ + $(WOLFSSL_BUILD)/keys.o \ + $(WOLFSSL_BUILD)/crl.o \ + $(WOLFSSL_BUILD)/ssl.o \ + $(WOLFSSL_BUILD)/tls.o \ + $(WOLFSSL_BUILD)/wolfcrypt/aes.o \ + $(WOLFSSL_BUILD)/wolfcrypt/asn.o \ + $(WOLFSSL_BUILD)/wolfcrypt/chacha.o \ + $(WOLFSSL_BUILD)/wolfcrypt/chacha20_poly1305.o \ + $(WOLFSSL_BUILD)/wolfcrypt/coding.o \ + $(WOLFSSL_BUILD)/wolfcrypt/curve25519.o \ + $(WOLFSSL_BUILD)/wolfcrypt/dh.o \ + $(WOLFSSL_BUILD)/wolfcrypt/dsa.o \ + $(WOLFSSL_BUILD)/wolfcrypt/error.o \ + $(WOLFSSL_BUILD)/wolfcrypt/ecc.o \ + $(WOLFSSL_BUILD)/wolfcrypt/ed25519.o \ + $(WOLFSSL_BUILD)/wolfcrypt/rsa.o \ + $(WOLFSSL_BUILD)/wolfcrypt/fe_low_mem.o \ + $(WOLFSSL_BUILD)/wolfcrypt/fe_operations.o \ + $(WOLFSSL_BUILD)/wolfcrypt/ge_low_mem.o \ + $(WOLFSSL_BUILD)/wolfcrypt/ge_operations.o \ + $(WOLFSSL_BUILD)/wolfcrypt/hash.o \ + $(WOLFSSL_BUILD)/wolfcrypt/hmac.o \ + $(WOLFSSL_BUILD)/wolfcrypt/integer.o \ + $(WOLFSSL_BUILD)/wolfcrypt/logging.o \ + $(WOLFSSL_BUILD)/wolfcrypt/md5.o \ + $(WOLFSSL_BUILD)/wolfcrypt/memory.o \ + $(WOLFSSL_BUILD)/wolfcrypt/poly1305.o \ + $(WOLFSSL_BUILD)/wolfcrypt/pwdbased.o \ + $(WOLFSSL_BUILD)/wolfcrypt/random.o \ + $(WOLFSSL_BUILD)/wolfcrypt/sha.o \ + $(WOLFSSL_BUILD)/wolfcrypt/sha256.o \ + $(WOLFSSL_BUILD)/wolfcrypt/sha512.o \ + $(WOLFSSL_BUILD)/wolfcrypt/wc_encrypt.o \ + $(WOLFSSL_BUILD)/wolfcrypt/wc_port.o \ + $(WOLFSSL_BUILD)/wolfcrypt/wolfmath.o \ + $(WOLFSSL_BUILD)/wolfcrypt/iotsafe.o \ + $(WOLFSSL_BUILD)/tls13.o + +OBJS_SPMATH:= $(WOLFSSL_BUILD)/wolfcrypt/sp_c32.o \ + $(WOLFSSL_BUILD)/wolfcrypt/sp_int.o + +OBJS+=$(WOLFSSL_OBJS) $(OBJS_SPMATH) + +vpath %.c $(dir $(WOLFSSL_ROOT)/src) +vpath %.c $(dir $(WOLFSSL_ROOT)/wolfcrypt/src) + +CFLAGS+=-g -ggdb3 +#CFLAGS+=-O2 + +#all: image.bin + +image.bin: image.elf + $(OBJCOPY) -O binary $^ $@ + +image.elf: $(WOLFSSL_BUILD)/wolfcrypt $(OBJS) $(LSCRIPT) + $(LD) $(LDFLAGS) $(OBJS) -o $@ + +$(WOLFSSL_BUILD)/wolfcrypt: + mkdir -p $(@) + +%.o:%.S + $(CC) -c -o $(@) $(CFLAGS) $^ + +%.o:%.c + $(CC) -c -o $(@) $(CFLAGS) $^ + +$(WOLFSSL_BUILD)/%.o: $(WOLFSSL_ROOT)/src/%.c + $(CC) -c -o $(@) $(CFLAGS) $^ + +$(WOLFSSL_BUILD)/wolfcrypt/%.o: $(WOLFSSL_ROOT)/wolfcrypt/src/%.c + $(CC) -c -o $(@) $(CFLAGS) $^ + +$(WOLFSSL_BUILD)/wolfcrypt/iotsafe.o: $(WOLFSSL_ROOT)/wolfcrypt/src/port/iotsafe/iotsafe.c + $(CC) -c -o $(@) $(CFLAGS) $^ + +clean: + rm -f image.bin image.elf *.o image.map + rm -rf build diff --git a/IDE/iotsafe/README.md b/IDE/iotsafe/README.md new file mode 100644 index 000000000..847d98d1f --- /dev/null +++ b/IDE/iotsafe/README.md @@ -0,0 +1,83 @@ +## wolfSSL IoT-Safe Example + + +### Evaluation Platform + + * ST [P-L496G-CELL02](https://www.st.com/en/evaluation-tools/p-l496g-cell02.html) + +including: + * STM32L496AGI6-based low-power discovery mother board + * STMiQuectel BG96 modem, plugged into the 'STMod+' connector + * IoT-Safe capable SIM card + +### Description + +This example firmware will run an example TLS 1.2 server using wolfSSL, and a +TLS 1.2 client, on the same host, using an IoT-safe applet supporting the +[IoT.05-v1-IoT standard](https://www.gsma.com/iot/wp-content/uploads/2019/12/IoT.05-v1-IoT-Security-Applet-Interface-Description.pdf). + +The client and server routines alternate their execution in a single-threaded, +cooperative loop. + +Client and server communicate to each other using memory buffers to establish a +TLS session without the use of TCP/IP sockets. + +### IoT-Safe interface + +In this example, the client is the IoT-safe capable endpoint. First, it creates +a wolfSSL context `cli_ctx` normally: + +``` + wolfSSL_CTX_iotsafe_enable(cli_ctx); +``` + +In order to activate IoT-safe support in this context, the following function is +called: + +``` + printf("Client: Enabling IoT Safe in CTX\n"); + wolfSSL_CTX_iotsafe_enable(cli_ctx); +``` + + +Additionally, after the SSL session creation, shown below: + +``` + printf("Creating new SSL\n"); + cli_ssl = wolfSSL_new(cli_ctx); +``` + +the client associates the pre-provisioned keys and the available slots in the +IoT safe applet to the current session: + + +``` + wolfSSL_iotsafe_on(cli_ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID, PEER_PUBKEY_ID, + PEER_CERT_ID); + +``` + +The applet that has been tested with this demo has the current configuration: + + Key slot | Name | Description + -------|--------|------------------ + 0x02 | `PRIVKEY_ID` | pre-provisioned with client ECC key + 0x03 | `ECDH_KEYPAIR_ID` | can store a keypair generated in the applet, used for shared key derivation + 0x04 | `PEER_PUBKEY_ID` | used to store the server's public key for key derivation + 0x05 | `PEER_CERT_ID` | used to store the server's public key to authenticate the peer + + +The following file is used to read the client's certificate: + + File Slot | Name | Description + ----------|------|------------ + 0x03 | `CRT_FILE_ID` | pre-provisioned with client certificate + + +### Compiling and running + +From this directory, run 'make', then use your favorite flash programming +software to upload the firmware `image.bin` to the target board. + + + diff --git a/IDE/iotsafe/ca-cert.c b/IDE/iotsafe/ca-cert.c new file mode 100644 index 000000000..3a9839f17 --- /dev/null +++ b/IDE/iotsafe/ca-cert.c @@ -0,0 +1,432 @@ +/* ca-cert.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 + */ + + +/* Certificate + keys for IoT safe example */ + +/* ./certs/ca-ecc-cert.der, ECC */ +static const unsigned char ca_ecc_cert_der_256[] = +{ + 0x30, 0x82, 0x02, 0x8A, 0x30, 0x82, 0x02, 0x30, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x83, 0x47, 0x7C, 0x81, + 0xD6, 0x0D, 0x1C, 0x4E, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x97, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, + 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, + 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, 0x31, 0x30, + 0x31, 0x39, 0x34, 0x39, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x32, + 0x33, 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, 0x39, 0x35, + 0x33, 0x5A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, + 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x02, 0xD3, 0xD9, 0x6E, 0xD6, 0x01, 0x8E, + 0x45, 0xC8, 0xB9, 0x90, 0x31, 0xE5, 0xC0, 0x4C, 0xE3, 0x9E, + 0xAD, 0x29, 0x38, 0x98, 0xBA, 0x10, 0xD6, 0xE9, 0x09, 0x2A, + 0x80, 0xA9, 0x2E, 0x17, 0x2A, 0xB9, 0x8A, 0xBF, 0x33, 0x83, + 0x46, 0xE3, 0x95, 0x0B, 0xE4, 0x77, 0x40, 0xB5, 0x3B, 0x43, + 0x45, 0x33, 0x0F, 0x61, 0x53, 0x7C, 0x37, 0x44, 0xC1, 0xCB, + 0xFC, 0x80, 0xCA, 0xE8, 0x43, 0xEA, 0xA7, 0xA3, 0x63, 0x30, + 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, 0x42, 0xDE, 0x18, + 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, 0xEA, 0xC3, 0xF3, + 0xA5, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, + 0x42, 0xDE, 0x18, 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, + 0xEA, 0xC3, 0xF3, 0xA5, 0x21, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0A, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xC5, 0x83, + 0xFF, 0x1E, 0x51, 0xF7, 0xA1, 0xE9, 0xF1, 0x42, 0xC4, 0xBE, + 0xED, 0x38, 0xBD, 0x38, 0x32, 0x8F, 0xAE, 0x3F, 0xC7, 0x6D, + 0x11, 0x90, 0xE9, 0x99, 0xAB, 0x61, 0xA2, 0xDB, 0xA7, 0x4B, + 0x02, 0x20, 0x28, 0x40, 0xD9, 0xBA, 0x45, 0xCC, 0xA6, 0xEA, + 0xFA, 0x3F, 0x3E, 0x71, 0x44, 0x8E, 0x02, 0x03, 0x2F, 0x41, + 0x0B, 0x56, 0x78, 0x2D, 0xA6, 0xE8, 0x5E, 0xF6, 0xFF, 0xDA, + 0x62, 0x8C, 0xF9, 0xDF +}; +static const int sizeof_ca_ecc_cert_der_256 = sizeof(ca_ecc_cert_der_256); + +/* ./certs/ca-cert.der, 2048-bit */ +static const unsigned char ca_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xE9, 0x30, 0x82, 0x03, 0xD1, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xAA, 0xD3, 0x3F, 0xAC, + 0x18, 0x0A, 0x37, 0x4D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, 0x31, 0x30, + 0x31, 0x39, 0x34, 0x39, 0x35, 0x32, 0x5A, 0x17, 0x0D, 0x32, + 0x33, 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, 0x39, 0x35, + 0x32, 0x5A, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, + 0x14, 0xB2, 0x1E, 0x84, 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, + 0xF2, 0x4D, 0x75, 0x10, 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, + 0x7D, 0x03, 0x98, 0xD3, 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, + 0xF1, 0xD8, 0xB0, 0x7D, 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, + 0x21, 0x4D, 0x80, 0xCB, 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, + 0x45, 0x7D, 0xC9, 0x72, 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, + 0x69, 0x52, 0x10, 0x03, 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, + 0x8B, 0x62, 0x56, 0x1B, 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, + 0x95, 0xAD, 0x0A, 0x9B, 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, + 0x76, 0x50, 0x30, 0x5B, 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, + 0xA7, 0xA2, 0x7A, 0x8D, 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, + 0xF2, 0x7C, 0x95, 0xB0, 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, + 0xCD, 0x77, 0x25, 0xEF, 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, + 0x3D, 0xCA, 0x63, 0x5B, 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, + 0x2F, 0x19, 0xD1, 0x3C, 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, + 0xC9, 0xE5, 0xC2, 0xD7, 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, + 0x73, 0x1B, 0x42, 0x2D, 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, + 0xAB, 0x7A, 0x36, 0x3F, 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, + 0xCE, 0x6A, 0x14, 0x38, 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, + 0xCB, 0x68, 0x7F, 0x71, 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, + 0x56, 0x2F, 0xA3, 0x26, 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, + 0xD7, 0x38, 0x99, 0x08, 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, + 0x13, 0x49, 0x08, 0x16, 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, + 0x31, 0x67, 0x23, 0x4E, 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, + 0x04, 0xD9, 0x0B, 0xEC, 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, + 0x36, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x3A, 0x30, 0x82, 0x01, 0x36, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, 0x11, + 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, + 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, + 0x80, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, + 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, + 0xE8, 0xD5, 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, + 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, + 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0xAA, 0xD3, 0x3F, 0xAC, 0x18, 0x0A, 0x37, 0x4D, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x1D, + 0x11, 0x04, 0x15, 0x30, 0x13, 0x82, 0x0B, 0x65, 0x78, 0x61, + 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x87, 0x04, + 0x7F, 0x00, 0x00, 0x01, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x62, 0x98, 0xC8, 0x58, 0xCF, + 0x56, 0x03, 0x86, 0x5B, 0x1B, 0x71, 0x49, 0x7D, 0x05, 0x03, + 0x5D, 0xE0, 0x08, 0x86, 0xAD, 0xDB, 0x4A, 0xDE, 0xAB, 0x22, + 0x96, 0xA8, 0xC3, 0x59, 0x68, 0xC1, 0x37, 0x90, 0x40, 0xDF, + 0xBD, 0x89, 0xD0, 0xBC, 0xDA, 0x8E, 0xEF, 0x87, 0xB2, 0xC2, + 0x62, 0x52, 0xE1, 0x1A, 0x29, 0x17, 0x6A, 0x96, 0x99, 0xC8, + 0x4E, 0xD8, 0x32, 0xFE, 0xB8, 0xD1, 0x5C, 0x3B, 0x0A, 0xC2, + 0x3C, 0x5F, 0xA1, 0x1E, 0x98, 0x7F, 0xCE, 0x89, 0x26, 0x21, + 0x1F, 0x64, 0x9C, 0x15, 0x7A, 0x9C, 0xEF, 0xFB, 0x1D, 0x85, + 0x6A, 0xFA, 0x98, 0xCE, 0xA8, 0xA9, 0xAB, 0xC3, 0xA2, 0xC0, + 0xEB, 0x87, 0xED, 0xBC, 0x21, 0xDF, 0xF3, 0x07, 0x5B, 0xAE, + 0xFD, 0x40, 0xD4, 0xAE, 0x20, 0xD0, 0x76, 0x8A, 0x31, 0x0A, + 0xA2, 0x62, 0x7C, 0x61, 0x0D, 0xCE, 0x5D, 0x9A, 0x1E, 0xE4, + 0x20, 0x88, 0x51, 0x49, 0xFB, 0x77, 0xA9, 0xCD, 0x4D, 0xC6, + 0xBF, 0x54, 0x99, 0x33, 0xEF, 0x4B, 0xA0, 0x73, 0x70, 0x6D, + 0x2E, 0xD9, 0x3D, 0x08, 0xF6, 0x12, 0x39, 0x31, 0x68, 0xC6, + 0x61, 0x5C, 0x41, 0xB5, 0x1B, 0xF4, 0x38, 0x7D, 0xFC, 0xBE, + 0x73, 0x66, 0x2D, 0xF7, 0xCA, 0x5B, 0x2C, 0x5B, 0x31, 0xAA, + 0xCF, 0xF6, 0x7F, 0x30, 0xE4, 0x12, 0x2C, 0x8E, 0xD6, 0x38, + 0x51, 0xE6, 0x45, 0xEE, 0xD5, 0xDA, 0xC3, 0x83, 0xD6, 0xED, + 0x5E, 0xEC, 0xD6, 0xB6, 0x14, 0xB3, 0x93, 0x59, 0xE1, 0x55, + 0x4A, 0x7F, 0x04, 0xDF, 0xCE, 0x65, 0xD4, 0xDF, 0x18, 0x4F, + 0xDD, 0xB4, 0x45, 0x7F, 0xA6, 0x56, 0x30, 0xC4, 0x05, 0x44, + 0x98, 0x9D, 0x4F, 0x26, 0x6D, 0x84, 0x80, 0xA0, 0x5E, 0xED, + 0x23, 0xD1, 0x48, 0x87, 0x0E, 0x05, 0x06, 0x91, 0x3B, 0xB0, + 0x3C, 0xBB, 0x8C, 0x8F, 0x3C, 0x7B, 0x4C, 0x4F, 0xA1, 0xCA, + 0x98 +}; +static const int sizeof_ca_cert_der_2048 = sizeof(ca_cert_der_2048); + + +/* ./certs/ecc-key.der, ECC */ +static const unsigned char ecc_key_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x45, 0xB6, 0x69, + 0x02, 0x73, 0x9C, 0x6C, 0x85, 0xA1, 0x38, 0x5B, 0x72, 0xE8, + 0xE8, 0xC7, 0xAC, 0xC4, 0x03, 0x8D, 0x53, 0x35, 0x04, 0xFA, + 0x6C, 0x28, 0xDC, 0x34, 0x8D, 0xE1, 0xA8, 0x09, 0x8C, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, 0xAC, + 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, 0x3C, + 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, 0x2B, + 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, 0x02, + 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, 0x97, + 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, 0x02, + 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, + 0xD8 +}; +static const int sizeof_ecc_key_der_256 = sizeof(ecc_key_der_256); + +/* ./certs/ecc-client-key.der, ECC */ +static const unsigned char ecc_clikey_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xF8, 0xCF, 0x92, + 0x6B, 0xBD, 0x1E, 0x28, 0xF1, 0xA8, 0xAB, 0xA1, 0x23, 0x4F, + 0x32, 0x74, 0x18, 0x88, 0x50, 0xAD, 0x7E, 0xC7, 0xEC, 0x92, + 0xF8, 0x8F, 0x97, 0x4D, 0xAF, 0x56, 0x89, 0x65, 0xC7, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, + 0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, + 0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, + 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, + 0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, + 0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, + 0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, + 0xB4 +}; +static const int sizeof_ecc_clikey_der_256 = sizeof(ecc_clikey_der_256); + +/* ./certs/client-ecc-cert.der, ECC */ +static const unsigned char cliecc_cert_der_256[] = +{ + 0x30, 0x82, 0x03, 0x49, 0x30, 0x82, 0x02, 0xEE, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xE7, 0x4A, 0x4F, 0xE5, + 0x56, 0x97, 0xCA, 0xC3, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x8D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, + 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, + 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, 0x31, 0x30, + 0x31, 0x39, 0x34, 0x39, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x32, + 0x33, 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, 0x39, 0x35, + 0x33, 0x5A, 0x30, 0x81, 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, + 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x06, 0x4F, + 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, 0x0E, 0x30, 0x0C, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, 0x53, 0x61, 0x6C, 0x65, + 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x45, + 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, 0x0F, 0x44, 0x50, 0x9A, + 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, 0x4D, 0xF5, 0x70, 0x7B, + 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, 0xEC, 0x5A, 0x4C, 0xA2, + 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, 0xEF, 0xA2, 0x35, 0x12, + 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, 0x95, 0x06, 0xCC, 0x01, + 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, 0xF7, 0xBD, 0xA9, 0xB2, + 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, 0xB4, 0xA3, 0x82, 0x01, + 0x33, 0x30, 0x82, 0x01, 0x2F, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xEB, 0xD4, 0x4B, 0x59, + 0x6B, 0x95, 0x61, 0x3F, 0x51, 0x57, 0xB6, 0x04, 0x4D, 0x89, + 0x41, 0x88, 0x44, 0x5C, 0xAB, 0xF2, 0x30, 0x81, 0xC2, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xBA, 0x30, 0x81, 0xB7, + 0x80, 0x14, 0xEB, 0xD4, 0x4B, 0x59, 0x6B, 0x95, 0x61, 0x3F, + 0x51, 0x57, 0xB6, 0x04, 0x4D, 0x89, 0x41, 0x88, 0x44, 0x5C, + 0xAB, 0xF2, 0xA1, 0x81, 0x93, 0xA4, 0x81, 0x90, 0x30, 0x81, + 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, + 0x6E, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x05, 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, + 0x69, 0x65, 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, + 0x61, 0x73, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x82, 0x09, 0x00, 0xE7, 0x4A, 0x4F, 0xE5, 0x56, + 0x97, 0xCA, 0xC3, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1C, 0x06, + 0x03, 0x55, 0x1D, 0x11, 0x04, 0x15, 0x30, 0x13, 0x82, 0x0B, + 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, + 0x6D, 0x87, 0x04, 0x7F, 0x00, 0x00, 0x01, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x1D, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, + 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, + 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x0A, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, + 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xE3, 0xBB, + 0xCA, 0x0E, 0x31, 0x2D, 0x39, 0x1D, 0x94, 0x25, 0x81, 0x90, + 0xD5, 0x11, 0xF9, 0x09, 0x6D, 0x58, 0x16, 0x23, 0xBE, 0x9F, + 0xA9, 0x18, 0x64, 0x83, 0x3C, 0x25, 0x03, 0x58, 0x58, 0x39, + 0x02, 0x21, 0x00, 0xA4, 0xAA, 0xB3, 0xF0, 0x09, 0xC9, 0x0C, + 0x2F, 0xF7, 0xB1, 0xD4, 0x8E, 0x9F, 0xA6, 0xB6, 0xAB, 0x1A, + 0xC7, 0x37, 0xED, 0x70, 0x4D, 0x34, 0x04, 0xA0, 0x9B, 0x3D, + 0x84, 0x86, 0x10, 0xA0, 0xF0 +}; +static const int sizeof_cliecc_cert_der_256 = sizeof(cliecc_cert_der_256); + +/* ./certs/server-ecc.der, ECC */ +static const unsigned char serv_ecc_der_256[] = +{ + 0x30, 0x82, 0x02, 0xA1, 0x30, 0x82, 0x02, 0x47, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x30, 0x0A, 0x06, 0x08, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, + 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, + 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, + 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, + 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, + 0x31, 0x30, 0x31, 0x39, 0x34, 0x39, 0x35, 0x33, 0x5A, 0x17, + 0x0D, 0x32, 0x33, 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, + 0x39, 0x35, 0x33, 0x5A, 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, + 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, + 0x45, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x31, 0x0C, 0x30, + 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, 0x45, 0x43, + 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, 0xAC, + 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, 0x3C, + 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, 0x2B, + 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, 0x02, + 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, 0x97, + 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, 0x02, + 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, + 0xD8, 0xA3, 0x81, 0x89, 0x30, 0x81, 0x86, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x5D, 0x5D, + 0x26, 0xEF, 0xAC, 0x7E, 0x36, 0xF9, 0x9B, 0x76, 0x15, 0x2B, + 0x4A, 0x25, 0x02, 0x23, 0xEF, 0xB2, 0x89, 0x30, 0x30, 0x1F, + 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, 0x42, 0xDE, 0x18, 0xB9, + 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, 0xEA, 0xC3, 0xF3, 0xA5, + 0x21, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x03, + 0xA8, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, + 0x30, 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x01, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xF8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, + 0x40, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, + 0x61, 0x6F, 0xE8, 0xB9, 0xAD, 0xCC, 0xC9, 0x1A, 0x81, 0x17, + 0x02, 0x64, 0x07, 0xC3, 0x18, 0x44, 0x01, 0x81, 0x76, 0x18, + 0x9D, 0x6D, 0x3D, 0x7D, 0xCB, 0xC1, 0x5A, 0x76, 0x4A, 0xAD, + 0x71, 0x55, 0x02, 0x21, 0x00, 0xCD, 0x22, 0x35, 0x04, 0x19, + 0xC2, 0x23, 0x21, 0x02, 0x88, 0x4B, 0x51, 0xDA, 0xDB, 0x51, + 0xAB, 0x54, 0x8C, 0xCB, 0x38, 0xAC, 0x8E, 0xBB, 0xEE, 0x18, + 0x07, 0xBF, 0x88, 0x36, 0x88, 0xFF, 0xD5 +}; +static const int sizeof_serv_ecc_der_256 = sizeof(serv_ecc_der_256); diff --git a/IDE/iotsafe/devices.c b/IDE/iotsafe/devices.c new file mode 100644 index 000000000..77933f1d7 --- /dev/null +++ b/IDE/iotsafe/devices.c @@ -0,0 +1,459 @@ +/* devices.c + * + * Copyright (C) 2006-2021 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 + */ + +/* Minimalist BSP for IoT-Safe example based on + * ST P-L596G-CELL02 + Quectel BG96 modem + */ + +#include +#include +#include +#include "devices.h" +#define RTSCTS 0 +#define AUTOBR 0 +#define NVIC_UART1_IRQN (37) +#define NVIC_UART2_IRQN (38) + +static char modem_rx_buf[256]; +static uint32_t modem_rx_idx = 0; +static uint32_t modem_parser_idx = 0; + +static void usart1_init(void) +{ + uint32_t reg; + + /* Enable PWR */ + RCC_APB1_ENR |= PWR_APB1_CLOCK_ER_VAL; + /* Enable GPIOG */ + RCC_AHB2_ENR |= GPIOG_AHB2_CLOCK_ER_VAL; + + + /* Enable VDDIO2 */ + while ((PWR_CR2 & PWR_CR2_IOSV) == 0) { + PWR_CR2 |= PWR_CR2_IOSV; + printf("Turning on VDDIO2\n"); + sleep_ms(1000); + } + /* Enable GPIOB */ + RCC_AHB2_ENR |= GPIOB_AHB2_CLOCK_ER_VAL; + /* Set mode = AF */ + reg = GPIO_MODE(GPIOG_BASE) & ~(0x03 << (USART1_PIN_RX * 2)); + GPIO_MODE(GPIOG_BASE) = reg | (0x02 << (USART1_PIN_RX * 2)); + + reg = GPIO_MODE(GPIOB_BASE) & ~(0x03 << (USART1_PIN_TX * 2)); + GPIO_MODE(GPIOB_BASE) = reg | (0x02 << (USART1_PIN_TX * 2)); + + reg = GPIO_PUPD(GPIOG_BASE) & (0x03 << (USART1_PIN_RX * 2)); + + reg = GPIO_PUPD(GPIOB_BASE) & (0x03 << (USART1_PIN_TX * 2)); + GPIO_PUPD(GPIOB_BASE) = reg | (0x01 << (USART1_PIN_TX * 2)); + +#if RTSCTS + reg = GPIO_MODE(GPIOG_BASE) & ~(0x03 << (USART1_PIN_RTS * 2)); + GPIO_MODE(GPIOG_BASE) = reg | (0x02 << (USART1_PIN_RTS * 2)); + GPIO_PUPD(GPIOG_BASE) &= (0x03 << (USART1_PIN_RTS * 2)); + + reg = GPIO_MODE(GPIOG_BASE) & ~(0x03 << (USART1_PIN_CTS * 2)); + GPIO_MODE(GPIOG_BASE) = reg | (0x02 << (USART1_PIN_CTS * 2)); + GPIO_PUPD(GPIOG_BASE) &= (0x03 << (USART1_PIN_CTS * 2)); +#endif + + /* Set alternate functions */ + reg = GPIO_AFH(GPIOG_BASE) & ~(0xf << ((USART1_PIN_RX - 8) * 4)); + GPIO_AFH(GPIOG_BASE) = reg | (7 << ((USART1_PIN_RX - 8) * 4)); + reg = GPIO_AFL(GPIOB_BASE) & ~(0xf << ((USART1_PIN_TX) * 4)); + GPIO_AFL(GPIOB_BASE) = reg | (7 << ((USART1_PIN_TX) * 4)); + +#if RTSCTS + /* RTS/CTS alt fn */ + reg = GPIO_AFH(GPIOG_BASE) & ~(0xf << ((USART1_PIN_RTS - 8) * 4)); + GPIO_AFH(GPIOG_BASE) = reg | (USART1_AF << ((USART1_PIN_RTS - 8) * 4)); + reg = GPIO_AFH(GPIOG_BASE) & ~(0xf << ((USART1_PIN_CTS - 8) * 4)); + GPIO_AFH(GPIOG_BASE) = reg | (USART1_AF << ((USART1_PIN_CTS - 8) * 4)); +#endif + /* Enable USART clock */ + RCC_APB2_ENR |= USART1_APB2_CLOCK_ER_VAL; +} + +static void usart2_init(void) +{ + uint32_t reg; + RCC_AHB2_ENR |= GPIOD_AHB2_CLOCK_ER_VAL | GPIOA_AHB2_CLOCK_ER_VAL; + + /* Set mode = AF */ + reg = GPIO_MODE(GPIOD_BASE) & ~(0x03 << (USART2_PIN_RX * 2)); + GPIO_MODE(GPIOD_BASE) = reg | (0x02 << (USART2_PIN_RX * 2)); + + reg = GPIO_MODE(GPIOA_BASE) & ~(0x03 << (USART2_PIN_TX * 2)); + GPIO_MODE(GPIOA_BASE) = reg | (0x02 << (USART2_PIN_TX * 2)); + + /* Set alternate functions */ + reg = GPIO_AFL(GPIOD_BASE) & ~(0xf << ((USART2_PIN_RX) * 4)); + GPIO_AFL(GPIOD_BASE) = reg | (7 << ((USART2_PIN_RX) * 4)); + reg = GPIO_AFL(GPIOA_BASE) & ~(0xf << ((USART2_PIN_TX) * 4)); + GPIO_AFL(GPIOA_BASE) = reg | (7 << ((USART2_PIN_TX) * 4)); + + /* Enable USART clock */ + RCC_APB1_ENR |= USART2_APB1_CLOCK_ER_VAL; +} + +int usart_tx(uint32_t dev, const uint8_t c) +{ + volatile uint32_t reg; + do { + reg = USART_ISR(dev); + } while ((reg & USART_ISR_TXE) == 0); + USART_TDR(dev) = c; + return 1; +} + +int usart_rx(uint32_t dev, uint8_t *c) +{ + int ret = 0; + if (dev == USART1_BASE) { + if (modem_rx_idx > modem_parser_idx) { + *c = (uint8_t)(modem_rx_buf[modem_parser_idx++]); + if (modem_rx_idx == modem_parser_idx) { + modem_rx_idx = 0; + modem_parser_idx = 0; + } + ret = 1; + } + } else { + volatile uint32_t reg = USART_ISR(dev); + if ((reg & USART_ISR_RXNE) != 0) { + reg = USART_RDR(dev); + *c = (uint8_t)(reg & 0xff); + ret = 1; + } + } + return ret; +} + +int usart_init(uint32_t dev, uint32_t bitrate, uint8_t data, char parity, uint8_t stop) +{ + uint32_t reg; + int rtscts = 0; + + if (dev == USART1_BASE) { + usart1_init(); +#if RTSCTS + rtscts = 1; +#endif + } + else if (dev == USART2_BASE) + usart2_init(); + else + return -1; + /* Turn off the device */ + USART_CR1(dev) &= ~(USART_CR1_ENABLE); + + /* Configure for TX + RX */ + USART_CR1(dev) |= (USART_CR1_TX_ENABLE | USART_CR1_RX_ENABLE); + + /* Configure clock */ + USART_BRR(dev) = CLOCK_SPEED / (bitrate); + + /* Configure data bits */ + if (data == 8) + USART_CR1(dev) &= ~USART_CR1_SYMBOL_LEN; + else + USART_CR1(dev) |= USART_CR1_SYMBOL_LEN; + + /* Configure parity */ + switch (parity) { + case 'O': + USART_CR1(dev) |= USART_CR1_PARITY_ODD; + /* fall through to enable parity */ + /* FALL THROUGH */ + case 'E': + USART_CR1(dev) |= USART_CR1_PARITY_ENABLED; + break; + default: + USART_CR1(dev) &= ~(USART_CR1_PARITY_ENABLED | USART_CR1_PARITY_ODD); + } + /* Set stop bits (not supported) */ + (void)stop; + + /* Set rtscts */ + if (rtscts) + USART_CR3(dev) |= USART_CR3_CTSE | USART_CR3_RTSE; + +#if AUTOBR + /* Enable ABR */ + USART_CR2(dev) |= USART_CR2_ABREN; +#endif + + + if (dev == USART1_BASE) { + USART_CR1(dev) |= USART_CR1_RXNEIE | USART_CR1_PEIE; + USART_CR3(dev) |= USART_CR3_EIE; + nvic_irq_enable(NVIC_UART1_IRQN); + nvic_irq_setprio(NVIC_UART1_IRQN, 0); + } + + /* Turn on uart */ + USART_CR1(dev) |= USART_CR1_ENABLE; + return 0; +} + +/* STDOUT on USART2 */ +int _write(void *r, uint8_t *text, int len) +{ + char *p = (char *)text; + int i; + (void)r; + while(*p && (p < (char *)(text + len))) { + usart_tx(USART2_BASE, *p); + p++; + } + return len; +} + +/* newlib backend calls */ + +extern unsigned int _start_heap; +void * _sbrk(unsigned int incr) +{ + static unsigned char *heap = NULL; + void *old_heap = heap; + if (((incr >> 2) << 2) != incr) + incr = ((incr >> 2) + 1) << 2; + if (old_heap == NULL) + old_heap = heap = (unsigned char *)&_start_heap; + heap += incr; + return old_heap; +} +void * _sbrk_r(unsigned int incr) +{ + static unsigned char *heap = NULL; + void *old_heap = heap; + if (((incr >> 2) << 2) != incr) + incr = ((incr >> 2) + 1) << 2; + if (old_heap == NULL) + old_heap = heap = (unsigned char *)&_start_heap; + heap += incr; + return old_heap; +} + +int _close(int fd) +{ + return -1; +} + +int _fstat(int fd) +{ + return -1; +} + +int _lseek(int fd, int whence, int off) +{ + return -1; +} + +int _read(uint8_t *buf, int len) +{ + return -1; +} + +int _isatty(int fd) +{ + return 1; +} + +/* Clock + waitstates settings */ + +static void flash_set_waitstates(unsigned int waitstates) +{ + uint32_t reg = FLASH_ACR; + if ((reg & FLASH_ACR_LATENCY_MASK) != waitstates) + FLASH_ACR |= ((reg & ~FLASH_ACR_LATENCY_MASK) | waitstates); +} + +void clock_pll_on(void) +{ + uint32_t reg32; + uint32_t cpu_freq; + uint32_t hpre, ppre1, ppre2; + uint32_t flash_waitstates; + + /* Select clock parameters (CPU Speed = 80MHz) */ + cpu_freq = 80000000; + flash_waitstates = 4; + flash_set_waitstates(flash_waitstates); + + /* Configure + enable internal high-speed oscillator. */ + RCC_CR = (RCC_CR & (~RCC_CR_MSIRANGE_Msk)) | RCC_CR_MSIRANGE_6; + RCC_CR |= RCC_CR_MSIRGSEL; + RCC_CR |= RCC_CR_MSION; + + DMB(); + while ((RCC_CR & RCC_CR_MSIRDY) == 0) + ; + /* Select MSI as SYSCLK source. */ + reg32 = RCC_CFGR; + reg32 &= ~(RCC_CFGR_SW_MASK); + RCC_CFGR = (reg32 | RCC_CFGR_SW_MSI); + DMB(); + /* + * Set prescalers + */ + hpre = RCC_PRESCALER_DIV_NONE; + ppre1 = RCC_PRESCALER_DIV_NONE; + ppre2 = RCC_PRESCALER_DIV_NONE; + reg32 = RCC_CFGR; + reg32 &= ~(RCC_CFGR_HPRE_MASK << RCC_CFGR_HPRE_SHIFT); + RCC_CFGR = (hpre & RCC_CFGR_HPRE_MASK) << RCC_CFGR_HPRE_SHIFT; + DMB(); + reg32 = RCC_CFGR; + reg32 &= ~(RCC_CFGR_PPRE1_MASK << RCC_CFGR_PPRE1_SHIFT); + RCC_CFGR = (reg32 | (ppre1 << RCC_CFGR_PPRE1_SHIFT)); + DMB(); + reg32 &= ~(RCC_CFGR_PPRE2_MASK << RCC_CFGR_PPRE2_SHIFT); + RCC_CFGR = (reg32 | (ppre2 << RCC_CFGR_PPRE2_SHIFT)); + DMB(); + /* Set PLLCFGR parameter */ + RCC_PLLCFGR = PLLCFGR_PLLM | PLLCFGR_PLLN | + PLLCFGR_PLLP | PLLCFGR_PLLQ | + PLLCFGR_PLLR | RCC_PLLCFGR_PLLP_EN | + RCC_PLLCFGR_PLLQ_EN | RCC_PLLCFGR_PLLR_EN | + RCC_PLLCFGR_PLLSRC_MSI; + + /* Enable PLL oscillator and wait for it to stabilize. */ + RCC_CR |= RCC_CR_PLLON; + DMB(); + while ((RCC_CR & RCC_CR_PLLRDY) == 0) + ; + + /* Select PLL as SYSCLK source. */ + reg32 = RCC_CFGR; + reg32 &= ~(RCC_CFGR_SW_MASK); + RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL); + DMB(); + /* Wait for PLL clock to be selected (via SWS, bits 3:2) */ + while (((RCC_CFGR >> 2) & RCC_CFGR_SW_MASK) != RCC_CFGR_SW_PLL) + ; + + RCC_CCIPR |= (1 << 26); + + PWR_CR1 |= PWR_CR1_DBP; +} + + +/* Modem via STMod+ connector */ +static int stmod_en_init = 0; + +static void stmod_pin_init(void) +{ + uint32_t reg; + RCC_AHB2_ENR |= + GPIOA_AHB2_CLOCK_ER_VAL | + GPIOB_AHB2_CLOCK_ER_VAL | + GPIOC_AHB2_CLOCK_ER_VAL | + GPIOD_AHB2_CLOCK_ER_VAL | + GPIOI_AHB2_CLOCK_ER_VAL; + + /* 'enable' pin */ + reg = GPIO_MODE(STMOD_EN_PORT) & ~(0x03 << (STMOD_EN_PIN * 2)); + GPIO_MODE(STMOD_EN_PORT) = reg | (0x01 << (STMOD_EN_PIN * 2)); + + /* RST pin */ + reg = GPIO_MODE(STMOD_MODEM_RST_PORT) & ~(0x03 << (STMOD_MODEM_RST_PIN * 2)); + GPIO_MODE(STMOD_MODEM_RST_PORT) = reg | (0x01 << (STMOD_MODEM_RST_PIN * 2)); + + /* DTR pin */ + reg = GPIO_MODE(STMOD_MODEM_DTR_PORT) & ~(0x03 << (STMOD_MODEM_DTR_PIN * 2)); + GPIO_MODE(STMOD_MODEM_DTR_PORT) = reg | (0x01 << (STMOD_MODEM_DTR_PIN * 2)); + + /* Sim select pins */ + reg = GPIO_MODE(STMOD_SIM_SELECT0_PORT) & ~(0x03 << (STMOD_SIM_SELECT0_PIN * 2)); + GPIO_MODE(STMOD_SIM_SELECT0_PORT) = reg | (0x01 << (STMOD_SIM_SELECT0_PIN * 2)); + reg = GPIO_MODE(STMOD_SIM_SELECT1_PORT) & ~(0x03 << (STMOD_SIM_SELECT1_PIN * 2)); + GPIO_MODE(STMOD_SIM_SELECT1_PORT) = reg | (0x01 << (STMOD_SIM_SELECT1_PIN * 2)); + +} + +void stmod_modem_enable(void) +{ + if (!stmod_en_init) { + stmod_pin_init(); + stmod_en_init = 1; + } + + /* initial pin state */ + gpio_set(STMOD_EN_PORT, STMOD_EN_PIN); + gpio_set(STMOD_MODEM_RST_PORT, STMOD_MODEM_RST_PIN); + gpio_set(STMOD_MODEM_DTR_PORT, STMOD_MODEM_DTR_PIN); + sleep_ms(200); + gpio_clear(STMOD_MODEM_RST_PORT, STMOD_MODEM_RST_PIN); + gpio_clear(STMOD_EN_PORT, STMOD_EN_PIN); + sleep_ms(2500); + + /* ON/OFF sequence to clear state */ + gpio_set(STMOD_EN_PORT, STMOD_EN_PIN); + sleep_ms(700); + gpio_clear(STMOD_EN_PORT, STMOD_EN_PIN); + sleep_ms(1000); + gpio_set(STMOD_EN_PORT, STMOD_EN_PIN); + sleep_ms(50); + gpio_clear(STMOD_EN_PORT, STMOD_EN_PIN); + sleep_ms(30); + gpio_set(STMOD_EN_PORT, STMOD_EN_PIN); /* Modem is on. */ + printf("Modem booting...\n"); + sleep_ms(5000); + printf("Modem is on.\r\n"); + +} + +void stmod_modem_disable(void) +{ + if (!stmod_en_init) { + stmod_pin_init(); + stmod_en_init = 1; + } + gpio_clear(STMOD_EN_PORT, STMOD_EN_PIN); +} + +extern volatile unsigned jiffies; +void systick_enable(void) +{ + SYSTICK_RVR = ((CLOCK_SPEED / 1000) - 1); + SYSTICK_CVR = 0; + SYSTICK_CSR |= 0x07; +} + +void sleep_ms(unsigned ms) +{ + unsigned end = jiffies + ms; + while(jiffies < end) + __asm__ volatile("wfi"); +} + +void isr_usart1(void) +{ + uint32_t reg; + reg = USART_ISR(USART1_BASE); + if (reg & USART_ISR_RXNE) { + modem_rx_buf[modem_rx_idx++] = (char)USART_RDR(USART1_BASE); + } else { + USART_ICR(USART1_BASE) |= 2 | USART_ICR_CMCF; /* FECF + CMCF*/ + } +} diff --git a/IDE/iotsafe/devices.h b/IDE/iotsafe/devices.h new file mode 100644 index 000000000..e6ed5d776 --- /dev/null +++ b/IDE/iotsafe/devices.h @@ -0,0 +1,302 @@ +/* devices.h + * + * Copyright (C) 2006-2021 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 + */ + +/* Minimalist BSP for IoT-Safe example based on + * ST P-L596G-CELL02 + Quectel BG96 modem + */ +#ifndef STM32L496_DEVICES +#define STM32L496_DEVICES + +/* CPU clock speed */ +//#define CLOCK_SPEED 14200000 +//#define CLOCK_SPEED 6000000 +#define CLOCK_SPEED 40000000 + +/* Memory mapping */ +#define USART1_BASE (0x40013800UL) +#define USART2_BASE (0x40004400UL) +#define GPIOA_BASE (0x48000000UL) +#define GPIOB_BASE (0x48000400UL) +#define GPIOC_BASE (0x48000800UL) +#define GPIOD_BASE (0x48000C00UL) +#define GPIOE_BASE (0x48001000UL) +#define GPIOF_BASE (0x48001400UL) +#define GPIOG_BASE (0x48001800UL) +#define GPIOH_BASE (0x48001C00UL) +#define GPIOI_BASE (0x48002000UL) +#define RCC_BASE (0x40021000UL) +#define PWR_BASE (0x40007000UL) + + + +/* USART */ +#define USART_CR1(x) (*((volatile uint32_t *)(x + 0x00))) +#define USART_CR2(x) (*((volatile uint32_t *)(x + 0x04))) +#define USART_CR3(x) (*((volatile uint32_t *)(x + 0x08))) +#define USART_BRR(x) (*((volatile uint32_t *)(x + 0x0C))) +#define USART_ISR(x) (*((volatile uint32_t *)(x + 0x1C))) +#define USART_ICR(x) (*((volatile uint32_t *)(x + 0x20))) +#define USART_RDR(x) (*((volatile uint8_t *)(x + 0x24))) +#define USART_TDR(x) (*((volatile uint8_t *)(x + 0x28))) + +/* GPIO */ +#define GPIO_MODE(x) (*((volatile uint32_t *)(x + 0x00))) +#define GPIO_SPEED(x) (*((volatile uint32_t *)(x + 0x08))) +#define GPIO_PUPD(x) (*((volatile uint32_t *)(x + 0x0C))) +#define GPIO_AFL(x) (*((volatile uint32_t *)(x + 0x20))) +#define GPIO_AFH(x) (*((volatile uint32_t *)(x + 0x24))) +#define GPIO_BSSR(x) (*((volatile uint32_t *)(x + 0x18))) + + +/* RCC */ +#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) +#define RCC_CFGR (*(volatile uint32_t *)(RCC_BASE + 0x08)) +#define RCC_PLLCFGR (*(volatile uint32_t *)(RCC_BASE + 0x0C)) +#define RCC_CCIPR (*(volatile uint32_t *)(RCC_BASE + 0x88)) + +#define RCC_AHB1_ENR (*(volatile uint32_t *)(RCC_BASE + 0x48)) +#define RCC_AHB2_ENR (*(volatile uint32_t *)(RCC_BASE + 0x4C)) +#define RCC_AHB3_ENR (*(volatile uint32_t *)(RCC_BASE + 0x50)) +#define RCC_APB1_ENR (*(volatile uint32_t *)(RCC_BASE + 0x58)) +#define RCC_APB2_ENR (*(volatile uint32_t *)(RCC_BASE + 0x60)) + +/* PWR */ +#define PWR_CR1 (*(volatile uint32_t *)(PWR_BASE + 0x00)) +#define PWR_CR2 (*(volatile uint32_t *)(PWR_BASE + 0x04)) +#define PWR_SR2 (*(volatile uint32_t *)(PWR_BASE + 0x014)) + +#define PWR_CR1_DBP (1 << 8) +#define PWR_CR2_PVME2 (1 << 5) +#define PWR_CR2_IOSV (1 << 9) +#define PWR_SR2_PVMO2 (1 << 13) + + +/* FLASH registers + latency mask */ +#define FLASH_BASE 0x40022000 +#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00)) +#define FLASH_ACR_LATENCY_MASK (0x03) + +/* RCC: Periph enable flags */ +#define USART1_APB2_CLOCK_ER_VAL (1 << 14) +#define USART2_APB1_CLOCK_ER_VAL (1 << 17) +#define PWR_APB1_CLOCK_ER_VAL (1 << 28) +#define GPIOA_AHB2_CLOCK_ER_VAL (1 << 0) +#define GPIOB_AHB2_CLOCK_ER_VAL (1 << 1) +#define GPIOC_AHB2_CLOCK_ER_VAL (1 << 2) +#define GPIOD_AHB2_CLOCK_ER_VAL (1 << 3) +#define GPIOE_AHB2_CLOCK_ER_VAL (1 << 4) +#define GPIOF_AHB2_CLOCK_ER_VAL (1 << 5) +#define GPIOG_AHB2_CLOCK_ER_VAL (1 << 6) +#define GPIOH_AHB2_CLOCK_ER_VAL (1 << 7) +#define GPIOI_AHB2_CLOCK_ER_VAL (1 << 8) + +/* Pinout: USART */ +#define USART1_PIN_RX (10) /* PG10 */ +#define USART1_PIN_TX (6) /* PB6 */ +#define USART1_PIN_CTS (11) /* PG11 */ +#define USART1_PIN_RTS (12) /* PG12 */ +#define USART1_AF (7) + +#define USART2_PIN_RX (6) /* PD6 */ +#define USART2_PIN_TX (2) /* PA2 */ +#define USART2_AF (7) + + + +/* USART registers: flags */ + +#define USART_CR1_ENABLE (1 << 0) +#define USART_CR1_TX_ENABLE (1 << 3) +#define USART_CR1_RX_ENABLE (1 << 2) +#define USART_CR1_RXNEIE (1 << 5) +#define USART_CR1_PEIE (1 << 8) +#define USART_CR1_PARITY_ODD (1 << 9) +#define USART_CR1_PARITY_ENABLED (1 << 10) +#define USART_CR1_SYMBOL_LEN (1 << 28) +#define USART_CR2_ABREN (1 << 20) +#define USART_CR3_EIE (1 << 0) +#define USART_CR3_RTSE (1 << 8) +#define USART_CR3_CTSE (1 << 9) +#define USART_ISR_TXE (1 << 7) +#define USART_ISR_RXNE (1 << 5) +#define USART_ICR_CTSCF (1 << 9) +#define USART_ICR_CMCF (1 << 17) + +/* RCC_CR/CFGR/PLLCFGR values */ +#define RCC_PRESCALER_DIV_NONE 0 +#define RCC_PRESCALER_DIV_2 8 +#define RCC_PRESCALER_DIV_4 9 + +#define RCC_CR_PLLRDY (1 << 25) +#define RCC_CR_PLLON (1 << 24) +#define RCC_CR_MSIRGSEL (1 << 3) +#define RCC_CR_MSIRDY (1 << 1) +#define RCC_CR_MSION (1 << 0) +#define RCC_CR_HSIRDY (1 << 10) +#define RCC_CR_HSION (1 << 8) +#define RCC_CR_MSIRANGE_SHIFT 4 +#define RCC_CR_MSIRANGE_9 (0x09 << 4) +#define RCC_CR_MSIRANGE_6 (0x06 << 4) +#define RCC_CR_MSIRANGE_Msk (0x0F << 4) + +#define RCC_CFGR_HPRE_MASK 0x0F +#define RCC_CFGR_PPRE1_MASK 0x07 +#define RCC_CFGR_PPRE2_MASK 0x07 +#define RCC_CFGR_HPRE_SHIFT 4 +#define RCC_CFGR_PPRE1_SHIFT 8 +#define RCC_CFGR_PPRE2_SHIFT 11 +#define RCC_CFGR_SW_MSI 0x0 +#define RCC_CFGR_SW_PLL 0x3 +#define RCC_CFGR_SW_MASK 0x3 + +/* Bits 0:1 SRC */ +#define RCC_PLLCFGR_SRC_SHIFT 0 +#define RCC_PLLCFGR_PLLSRC_MSI 0x1 +#define RCC_PLLCFGR_PLLSRC_MASK 0x3 + +/* Bits 4:6 PLLM */ +//#define PLLCFGR_PLLM (0x4 << 4) +#define PLLCFGR_PLLM (0x1 << 4) +#define RCC_PLLCFGR_PLLM_MASK (0x7 << 4) + +/* Bits 8:14 PLLN */ +//#define PLLCFGR_PLLN (71 << 8) +#define PLLCFGR_PLLN (40 << 8) +#define RCC_PLLCFGR_PLLN_MASK (0x7f << 8) + +/* Bits 27:31 PLLPDIV */ +#define PLLCFGR_PLLP (2 << 27) +#define RCC_PLLCFGR_PLLP_MASK (0x1F << 27) + +/* Bits 21:22 PLLQ */ +#define PLLCFGR_PLLQ (0 << 21) +#define RCC_PLLCFGR_PLLQ_MASK (0x3 << 21) + +/* Bits 25:26 PLLR */ +//#define PLLCFGR_PLLR (2 << 25) +#define PLLCFGR_PLLR (0 << 25) +#define RCC_PLLCFGR_PLLR_MASK (0x3 << 25) + +/* Enablers */ +#define RCC_PLLCFGR_PLLP_EN (0 << 16) +#define RCC_PLLCFGR_PLLQ_EN (0 << 20) +#define RCC_PLLCFGR_PLLR_EN (1 << 24) + +/* Systick */ +#define SYSTICK_BASE (0xE000E010) +#define SYSTICK_CSR (*(volatile uint32_t *)(SYSTICK_BASE + 0x00)) +#define SYSTICK_RVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x04)) +#define SYSTICK_CVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x08)) +#define SYSTICK_CALIB (*(volatile uint32_t *)(SYSTICK_BASE + 0x0C)) + + +/* STMod+ connector pinout + * + * Connector STM32L4 + * pins pins + * + * 1 11 PG11 PH2 + * 2 12 PB6 PB2 + * 3 13 PG10 PA4 + * 4 14 PG12 PA0 + * 5 15 GND 5V + * 6 16 5V GND + * 7 17 PB8 PC7 + * 8 18 PI3 PC2 + * 9 19 PD3 PB12 + * 10 20 PB7 PC2 + * + */ + +#define STMOD_EN_PORT GPIOD_BASE +#define STMOD_EN_PIN 3 +#define STMOD_SIM_SELECT0_PORT GPIOC_BASE +#define STMOD_SIM_SELECT0_PIN 2 +#define STMOD_SIM_SELECT1_PORT GPIOI_BASE +#define STMOD_SIM_SELECT1_PIN 3 +#define STMOD_MODEM_RST_PORT GPIOB_BASE +#define STMOD_MODEM_RST_PIN 2 +#define STMOD_MODEM_DTR_PORT GPIOA_BASE +#define STMOD_MODEM_DTR_PIN 0 + +void stmod_modem_enable(void); +void stmod_modem_disable(void); + +/* inline functions for GPIO */ +static inline void gpio_set(uint32_t port, uint32_t pin) +{ + GPIO_BSSR(port) |= (1 << pin); +} + +static inline void gpio_clear(uint32_t port, uint32_t pin) +{ + GPIO_BSSR(port) |= (1 << (16 + pin)); +} + + +/* Exported functions (from devices.c) */ +void clock_pll_on(void); +int usart_init(uint32_t dev, uint32_t bitrate, uint8_t data, char parity, uint8_t stop); +int usart_tx(uint32_t dev, const uint8_t c); +int usart_rx(uint32_t dev, uint8_t *c); +void systick_enable(void); +void sleep_ms(unsigned ms); + + +/* Assembly helpers */ +#define DMB() __asm__ volatile ("dmb") + +/* Nvic */ +#define NVIC_ISER_BASE (0xE000E100) +#define NVIC_ICER_BASE (0xE000E180) +#define NVIC_ICPR_BASE (0xE000E280) +#define NVIC_IPRI_BASE (0xE000E400) + +static inline void nvic_irq_enable(uint8_t n) +{ + int i = n / 32; + volatile uint32_t *nvic_iser = ((volatile uint32_t *)(NVIC_ISER_BASE + 4 * i)); + *nvic_iser |= (1 << (n % 32)); +} + +static inline void nvic_irq_disable(uint8_t n) +{ + int i = n / 32; + volatile uint32_t *nvic_icer = ((volatile uint32_t *)(NVIC_ICER_BASE + 4 * i)); + *nvic_icer |= (1 << (n % 32)); +} + +static inline void nvic_irq_setprio(uint8_t n, uint8_t prio) +{ + volatile uint8_t *nvic_ipri = ((volatile uint8_t *)(NVIC_IPRI_BASE + n)); + *nvic_ipri = prio; +} + + +static inline void nvic_irq_clear(uint8_t n) +{ + int i = n / 32; + volatile uint8_t *nvic_icpr = ((volatile uint8_t *)(NVIC_ICPR_BASE + 4 * i)); + *nvic_icpr = (1 << (n % 32)); +} + + +#endif /* guard */ diff --git a/IDE/iotsafe/include.am b/IDE/iotsafe/include.am new file mode 100644 index 000000000..aa0ff598f --- /dev/null +++ b/IDE/iotsafe/include.am @@ -0,0 +1,17 @@ +# vim:ft=automake +# All paths should be given relative to the root + +EXTRA_DIST += IDE/iotsafe/README.md +EXTRA_DIST += IDE/iotsafe/Makefile +EXTRA_DIST += IDE/iotsafe/target.ld + +EXTRA_DIST += IDE/iotsafe/main.c +EXTRA_DIST += IDE/iotsafe/startup.c +EXTRA_DIST += IDE/iotsafe/startup.c +EXTRA_DIST += IDE/iotsafe/memory-tls.c +EXTRA_DIST += IDE/iotsafe/devices.c +EXTRA_DIST += IDE/iotsafe/ca-cert.c +EXTRA_DIST += IDE/iotsafe/devices.h +EXTRA_DIST += IDE/iotsafe/user_settings.h + +DISTCLEANFILES+= IDE/iotsafe/build diff --git a/IDE/iotsafe/main.c b/IDE/iotsafe/main.c new file mode 100644 index 000000000..64838d422 --- /dev/null +++ b/IDE/iotsafe/main.c @@ -0,0 +1,142 @@ +/* main.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 + */ + +/* IoT-safe example + * main for STM32L4 + */ + +#include +#include "devices.h" +#include +#include +#include +#include + +#define STDIO USART2_BASE +#define MODEM USART1_BASE + +#define RX_TIMEOUT 100 + + +extern volatile unsigned long jiffies; + + +int usart1_read(char *buf, int len) +{ + int i = 0; + char c; + int ret; + volatile unsigned long start = jiffies; + memset(buf, 0, len); + do { + ret = usart_rx(MODEM, &c); + if (ret > 0) { + buf[i++] = c; + if (c == '\n') { + return i; + } + } else { + __asm__ volatile("wfi"); + } + + } while(((jiffies - start) < RX_TIMEOUT) && (i < len)); + if (i == 0) { + return 0; + } + return i; +} + +int usart1_write(const char *buf, int len) +{ + int i = 0; + do { + usart_tx(MODEM, buf[i++]); + } while(i < len); + return len; +} + +extern int memory_tls_test(void); + +void main(void) +{ + uint32_t last_mark = 0; + int i; + char randombytes[16]; + int ret; + char c; + WC_RNG rng; + clock_pll_on(); + systick_enable(); + if (usart_init(STDIO, 115200, 8, 'N', 1) < 0) + while(1) + ; + printf("wolfSSL IoT-SAFE demo\n"); + + printf("Press a key to continue...\n"); + do { + ret = usart_rx(STDIO, &c); + } while (ret <= 0); + printf("%c\n", c); + + printf("Initializing modem...\n"); + stmod_modem_enable(); + sleep_ms(1000); + printf("System up and running\r\n"); + sleep_ms(1000); + + printf("Initializing wolfSSL...\n"); + wolfSSL_Init(); + wolfSSL_Debugging_ON(); + + printf("Initializing modem port\n"); + if(usart_init(MODEM, 115200, 8, 'N', 1) < 0) + while(1) + ; + printf("Initializing IoTSafe I/O...\n"); + wolfIoTSafe_SetCSIM_read_cb(usart1_read); + wolfIoTSafe_SetCSIM_write_cb(usart1_write); + + /* IoT-Safe system up and running. */ + printf("Initializing RNG...\n"); + wc_InitRng(&rng); + + printf("Getting RND...\n"); + wc_RNG_GenerateBlock(&rng, randombytes, 16); + wc_FreeRng(&rng); + printf("Random bytes: "); + for (i = 0; i < 16; i++) { + printf("%02X", randombytes[i]); + } + printf("\n"); + + memory_tls_test(); + + while(1) { + if (usart_rx(STDIO, &c)) { + usart_tx(MODEM, c); + usart_tx(STDIO, c); + } + if (usart_rx(MODEM, &c)) { + usart_tx(STDIO, c); + } + __asm__ volatile("wfi"); + } +} diff --git a/IDE/iotsafe/memory-tls.c b/IDE/iotsafe/memory-tls.c new file mode 100644 index 000000000..e1c9422ad --- /dev/null +++ b/IDE/iotsafe/memory-tls.c @@ -0,0 +1,384 @@ +/* memory-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 + */ + +/* IoT-safe client side demo + - server uses software crypto and buffers + - client uses IoT-Safe + + Client and server communicates in a cooperative + scheduling mechanism within the same thread. + Two buffers in memory are used for client<=>server communication. +*/ + +#include +#include +#include +#include + +#include +#include + +#include "ca-cert.c" + +/* IoTSAFE Certificate slots */ + +/* File Slot '03' is pre-provisioned with + * local certificate. + */ +#define CRT_CLIENT_FILE_ID 0x03 /* pre-provisioned */ + +/* File Slot '04' is pre-provisioned with the + * server's EC public key certificate + */ +#define CRT_SERVER_FILE_ID 0x04 + +/* IoTSAFE Key slots */ + +/* Key slot '02' is pre-provisioned with + * the client private key. + */ +#define PRIVKEY_ID 0x02 /* pre-provisioned */ + +/* Key slot '03' is used by wolfSSL to generate + * the ECDH key that will be used during the TLS + * session. + */ +#define ECDH_KEYPAIR_ID 0x03 + +/* Key slot '04' is used to store the public key + * received from the peer. + */ +#define PEER_PUBKEY_ID 0x04 + +/* Key slot '05' is used to store a public key + * used for ecc verification + */ +#define PEER_CERT_ID 0x05 + +/* The following define + * activates mutual authentication */ +#define CLIENT_AUTH + + +#define CLIENT_IOTSAFE +#define CA_ECC + +/* client messages to server in memory */ +#define TLS_BUFFERS_SZ (1024 * 8) +static unsigned char to_server[TLS_BUFFERS_SZ]; +static int server_bytes; +static int server_write_idx; +static int server_read_idx; + +/* server messages to client in memory */ +unsigned char to_client[TLS_BUFFERS_SZ]; +int client_bytes; +int client_write_idx; +int client_read_idx; + +/* server send callback */ +int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + if (client_write_idx + sz > TLS_BUFFERS_SZ) + return -SSL_ERROR_WANT_WRITE; + printf("=== Srv-Cli: %d\n", sz); + memcpy(&to_client[client_write_idx], buf, sz); + client_write_idx += sz; + client_bytes += sz; + return sz; +} + + +/* server recv callback */ +int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + + if (server_bytes - server_read_idx < sz) + return -SSL_ERROR_WANT_READ; + memcpy(buf, &to_server[server_read_idx], sz); + server_read_idx += sz; + + if (server_read_idx == server_write_idx) { + server_read_idx = server_write_idx = 0; + server_bytes = 0; + } + printf("=== Srv RX: %d\n", sz); + return sz; +} + + +/* client send callback */ +int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + if (server_write_idx + sz > TLS_BUFFERS_SZ) + return -SSL_ERROR_WANT_WRITE; + + printf("=== Cli->Srv: %d\n", sz); + memcpy(&to_server[server_write_idx], buf, sz); + server_write_idx += sz; + server_bytes += sz; + + return sz; +} + + +/* client recv callback */ +int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + + if (client_bytes - client_read_idx < sz) + return -SSL_ERROR_WANT_READ; + + memcpy(buf, &to_client[client_read_idx], sz); + client_read_idx += sz; + + if (client_read_idx == client_write_idx) { + client_read_idx = client_write_idx = 0; + client_bytes = 0; + } + printf("=== Cli RX: %d\n", sz); + return sz; +} + +static int client_state = 0; +static int server_state = 0; + +static uint8_t cert_buffer[2048]; +static uint32_t cert_buffer_size; + + +/* wolfSSL Client loop */ +static int client_loop(void) +{ + /* set up client */ + int ret; + static WOLFSSL_CTX *cli_ctx = NULL; + static WOLFSSL *cli_ssl = NULL; + + + printf("=== CLIENT step %d ===\n", client_state); + if (client_state == 0) { + printf("Client: Creating new CTX\n"); + cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (cli_ctx == NULL) { + printf("bad client ctx new"); + return 0; + } + printf("Client: Enabling IoT Safe in CTX\n"); + wolfSSL_CTX_iotsafe_enable(cli_ctx); + + printf("Loading CA\n"); + ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256, + sizeof_ca_ecc_cert_der_256, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + printf("Bad CA\n"); + return -1; + } + + cert_buffer_size = wolfIoTSafe_GetCert(CRT_SERVER_FILE_ID, cert_buffer, 2048); + if (cert_buffer_size < 1) { + printf("Bad server cert\n"); + return -1; + } + printf("Loaded Server certificate from IoT-Safe, size = %lu\n", + cert_buffer_size); + WOLFSSL_BUFFER(cert_buffer, cert_buffer_size); + if (wolfSSL_CTX_load_verify_buffer(cli_ctx, cert_buffer, cert_buffer_size, + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + printf("Cannot load server cert\n"); + return -1; + } + printf("Server certificate successfully imported.\n"); + wolfSSL_CTX_set_verify(cli_ctx, SSL_VERIFY_PEER, 0); + +#ifdef CLIENT_AUTH + cert_buffer_size = wolfIoTSafe_GetCert(CRT_CLIENT_FILE_ID, cert_buffer, 2048); + if (cert_buffer_size < 1) { + printf("Bad cli cert\n"); + return -1; + } + printf("Loaded Client certificate from IoT-Safe, size = %lu\n", cert_buffer_size); + WOLFSSL_BUFFER(cert_buffer, cert_buffer_size); + if (wolfSSL_CTX_use_certificate_buffer(cli_ctx, cert_buffer, + cert_buffer_size, SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + printf("Cannot load client cert\n"); + return -1; + } + printf("Client certificate successfully imported.\n"); +#endif + + /* Setting IO Send/Receive functions to local memory-based message + * passing (ClientSend, ClientRecv) + */ + wolfSSL_SetIOSend(cli_ctx, ClientSend); + wolfSSL_SetIORecv(cli_ctx, ClientRecv); + + printf("Creating new SSL\n"); + cli_ssl = wolfSSL_new(cli_ctx); + if (cli_ssl == NULL) { + printf("bad client new"); + return 0; + } + printf("Setting SSL options: non blocking\n"); + wolfSSL_set_using_nonblock(cli_ssl, 1); + printf("Setting SSL options: turn on IoT-safe for this socket\n"); + wolfSSL_iotsafe_on(cli_ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID, PEER_PUBKEY_ID, + PEER_CERT_ID); + client_state++; + } + + if (client_state == 1) { + int err; + printf("Connecting to server...\n"); + ret = wolfSSL_connect(cli_ssl); + if (ret != SSL_SUCCESS) { + if (wolfSSL_want_read(cli_ssl)) + return 0; + printf("error in client tls connect: %d\n", wolfSSL_get_error(cli_ssl, ret)); + client_state = 0; + wolfSSL_free(cli_ssl); + wolfSSL_CTX_free(cli_ctx); + cli_ssl = NULL; + cli_ctx = NULL; + return -1; + } + printf("Client connected! Sending hello message...\n"); + client_state++; + } + + ret = wolfSSL_write(cli_ssl, "hello iot-safe wolfSSL",22); + if (ret >= 0) { + printf("wolfSSL client success!\n"); + } else if (wolfSSL_get_error(cli_ssl, ret) != SSL_ERROR_WANT_WRITE) { + printf("error in client tls write"); + client_state = 0; + wolfSSL_free(cli_ssl); + wolfSSL_CTX_free(cli_ctx); + cli_ssl = NULL; + cli_ctx = NULL; + return -1; + } + /* clean up */ + wolfSSL_free(cli_ssl); + wolfSSL_CTX_free(cli_ctx); + return 1; +} + +uint8_t srv_cert[1260]; +uint32_t srv_cert_size; + +/* wolfSSL Server Loop */ +static int server_loop(void) +{ + static WOLFSSL_CTX* srv_ctx = NULL; + static WOLFSSL* srv_ssl = NULL; + unsigned char buf[80]; + int ret; + printf("=== SERVER step %d ===\n", server_state); + + if (server_state == 0) { + srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + if (srv_ctx == NULL) { + printf("bad server ctx new"); + return -1; + } +#ifdef CLIENT_AUTH + ret = wolfSSL_CTX_load_verify_buffer(srv_ctx, ca_ecc_cert_der_256, + sizeof_ca_ecc_cert_der_256, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + printf("Bad CA load: %d\n", ret); + } + ret = wolfSSL_CTX_load_verify_buffer(srv_ctx, cliecc_cert_der_256, + sizeof_cliecc_cert_der_256, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + printf("Bad Client cert load: %d\n", ret); + } + wolfSSL_CTX_set_verify(srv_ctx, SSL_VERIFY_PEER, 0); +#endif + + if (wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256, + sizeof_ecc_key_der_256, SSL_FILETYPE_ASN1) + != SSL_SUCCESS) { + printf("Cannot load server private key\n"); + } + if (wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256, + sizeof_serv_ecc_der_256, SSL_FILETYPE_ASN1) != SSL_SUCCESS) + { + printf("Cannot load server cert\n"); + } + wolfSSL_SetIOSend(srv_ctx, ServerSend); + wolfSSL_SetIORecv(srv_ctx, ServerRecv); + srv_ssl = wolfSSL_new(srv_ctx); + if (srv_ssl == NULL) { + printf("bad server new"); + return -1; + } + wolfSSL_set_using_nonblock(srv_ssl, 1); + server_state++; + } + + if (server_state == 1) { + /* accept tls connection without tcp sockets */ + ret = wolfSSL_accept(srv_ssl); + if (ret != SSL_SUCCESS) { + if (wolfSSL_want_read(srv_ssl)) + return 0; + printf("error in server tls accept"); + server_state = 0; + wolfSSL_free(srv_ssl); + wolfSSL_CTX_free(srv_ctx); + srv_ssl = NULL; + srv_ctx = NULL; + return -1; + } + printf("wolfSSL accept success!\n"); + server_state++; + } + if (server_state == 2) { + ret = wolfSSL_read(srv_ssl, buf, sizeof(buf)-1); + if (wolfSSL_get_error(srv_ssl, ret) == SSL_ERROR_WANT_READ) { + return 0; + } + if (ret < 0) { + printf("SERVER READ ERROR: %d\n", wolfSSL_get_error(srv_ssl, ret)); + return -1; + } + if (ret > 0) { + printf("++++++ Server received msg from client: '%s'\n", buf); + printf("IoT-Safe TEST SUCCESSFUL\n"); + } + } + return 0; +} + + +int memory_tls_test(void) +{ + int ret_s, ret_c; + + printf("Starting memory-tls test...\n"); + do { + ret_s = server_loop(); + ret_c = client_loop(); + + } while ((ret_s >= 0) && (ret_c >= 0)); + return 0; +} diff --git a/IDE/iotsafe/startup.c b/IDE/iotsafe/startup.c new file mode 100644 index 000000000..07c2e8a35 --- /dev/null +++ b/IDE/iotsafe/startup.c @@ -0,0 +1,227 @@ +/* startup.c + * + * Copyright (C) 2006-2021 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 + */ + +/* Startup routines for STM32L596G bare-metal example */ + +extern unsigned int _stored_data; +extern unsigned int _start_data; +extern unsigned int _end_data; +extern unsigned int _start_bss; +extern unsigned int _end_bss; +extern unsigned int _end_stack; +extern unsigned int _start_heap; + +//#define STACK_PAINTING + +static volatile unsigned int avail_mem = 0; + +#ifdef STACK_PAINTING +static unsigned int stack_ptr; +#endif + +extern void isr_usart1(void); + +extern void main(void); + +void isr_reset(void) { + register unsigned int *src, *dst; + src = (unsigned int *) &_stored_data; + dst = (unsigned int *) &_start_data; + /* Copy the .data section from flash to RAM. */ + while (dst < (unsigned int *)&_end_data) { + *dst = *src; + dst++; + src++; + } + + /* Initialize the BSS section to 0 */ + dst = &_start_bss; + while (dst < (unsigned int *)&_end_bss) { + *dst = 0U; + dst++; + } + + /* Paint the stack. */ + avail_mem = &_end_stack - &_start_heap; +#ifdef STACK_PAINTING + { + asm volatile("mrs %0, msp" : "=r"(stack_ptr)); + dst = ((unsigned int *)(&_end_stack)) - (8192 / sizeof(unsigned int)); ; + while ((unsigned int)dst < stack_ptr) { + *dst = 0xDEADC0DE; + dst++; + } + } +#endif + /* Run the program! */ + main(); +} + +void isr_fault(void) +{ + /* Panic. */ + while(1) ;; +} + + +void isr_memfault(void) +{ + /* Panic. */ + while(1) ;; +} + +void isr_busfault(void) +{ + /* Panic. */ + while(1) ;; +} + +void isr_usagefault(void) +{ + /* Panic. */ + while(1) ;; +} + + +void isr_empty(void) +{ + /* Ignore the event and continue */ +} + + +volatile unsigned jiffies = 0; +void isr_systick(void) +{ + jiffies++; +} + + + +__attribute__ ((section(".isr_vector"))) +void (* const IV[])(void) = +{ + (void (*)(void))(&_end_stack), + isr_reset, // Reset + isr_fault, // NMI + isr_fault, // HardFault + isr_memfault, // MemFault + isr_busfault, // BusFault + isr_usagefault, // UsageFault + 0, 0, 0, 0, // 4x reserved + isr_empty, // SVC + isr_empty, // DebugMonitor + 0, // reserved + isr_empty, // PendSV + isr_systick, // SysTick + + isr_empty, // NVIC_WWDG_IRQ 0 + isr_empty, // PVD_IRQ 1 + isr_empty, // TAMP_STAMP_IRQ 2 + isr_empty, // RTC_WKUP_IRQ 3 + isr_empty, // FLASH_IRQ 4 + isr_empty, // RCC_IRQ 5 + isr_empty, // EXTI0_IRQ 6 + isr_empty, // EXTI1_IRQ 7 + isr_empty, // EXTI2_IRQ 8 + isr_empty, // EXTI3_IRQ 9 + isr_empty, // EXTI4_IRQ 10 + isr_empty, // DMA1_STREAM0_IRQ 11 + isr_empty, // DMA1_STREAM1_IRQ 12 + isr_empty, // DMA1_STREAM2_IRQ 13 + isr_empty, // DMA1_STREAM3_IRQ 14 + isr_empty, // DMA1_STREAM4_IRQ 15 + isr_empty, // DMA1_STREAM5_IRQ 16 + isr_empty, // DMA1_STREAM6_IRQ 17 + isr_empty, // ADC_IRQ 18 + isr_empty, // CAN1_TX_IRQ 19 + isr_empty, // CAN1_RX0_IRQ 20 + isr_empty, // CAN1_RX1_IRQ 21 + isr_empty, // CAN1_SCE_IRQ 22 + isr_empty, // EXTI9_5_IRQ 23 + isr_empty, // TIM1_BRK_TIM9_IRQ 24 + isr_empty, // TIM1_UP_TIM10_IRQ 25 + isr_empty, // TIM1_TRG_COM_TIM11_IRQ 26 + isr_empty, // TIM1_CC_IRQ 27 + isr_empty, // TIM2_IRQ 28 + isr_empty, // TIM3_IRQ 29 + isr_empty, // TIM4_IRQ 30 + isr_empty, // I2C1_EV_IRQ 31 + isr_empty, // I2C1_ER_IRQ 32 + isr_empty, // I2C2_EV_IRQ 33 + isr_empty, // I2C2_ER_IRQ 34 + isr_empty, // SPI1_IRQ 35 + isr_empty, // SPI2_IRQ 36 + isr_usart1, // USART1_IRQ 37 + isr_empty, // USART2_IRQ 38 + isr_empty, // USART3_IRQ 39 + isr_empty, // EXTI15_10_IRQ 40 + isr_empty, // RTC_ALARM_IRQ 41 + isr_empty, // USB_FS_WKUP_IRQ 42 + isr_empty, // TIM8_BRK_TIM12_IRQ 43 + isr_empty, // TIM8_UP_TIM13_IRQ 44 + isr_empty, // TIM8_TRG_COM_TIM14_IRQ 45 + isr_empty, // TIM8_CC_IRQ 46 + isr_empty, // DMA1_STREAM7_IRQ 47 + isr_empty, // FSMC_IRQ + isr_empty, // SDIO_IRQ + isr_empty, // TIM5_IRQ + isr_empty, // SPI3_IRQ + isr_empty, // UART4_IRQ + isr_empty, // UART5_IRQ + isr_empty, // TIM6_DAC_IRQ + isr_empty, // TIM7_IRQ + isr_empty, // DMA2_STREAM0_IRQ + isr_empty, // DMA2_STREAM1_IRQ + isr_empty, // DMA2_STREAM2_IRQ + isr_empty, // DMA2_STREAM3_IRQ + isr_empty, // DMA2_STREAM4_IRQ + isr_empty, // ETH_IRQ + isr_empty, // ETH_WKUP_IRQ + isr_empty, // CAN2_TX_IRQ + isr_empty, // CAN2_RX0_IRQ + isr_empty, // CAN2_RX1_IRQ + isr_empty, // CAN2_SCE_IRQ + isr_empty, // OTG_FS_IRQ + isr_empty, // DMA2_STREAM5_IRQ + isr_empty, // DMA2_STREAM6_IRQ + isr_empty, // DMA2_STREAM7_IRQ + isr_empty, // USART6_IRQ + isr_empty, // I2C3_EV_IRQ + isr_empty, // I2C3_ER_IRQ + isr_empty, // OTG_HS_EP1_OUT_IRQ + isr_empty, // OTG_HS_EP1_IN_IRQ + isr_empty, // OTG_HS_WKUP_IRQ + isr_empty, // OTG_HS_IRQ + isr_empty, // DCMI_IRQ + isr_empty, // CRYP_IRQ + isr_empty, // HASH_RNG_IRQ + isr_empty, // FPU_IRQ + isr_empty, // UART7_IRQ + isr_empty, // UART8_IRQ + isr_empty, // SPI4_IRQ + isr_empty, // SPI5_IRQ + isr_empty, // SPI6_IRQ + isr_empty, // SAI1_IRQ + isr_empty, // LCD_TFT_IRQ + isr_empty, // LCD_TFT_ERR_IRQ + isr_empty, // DMA2D_IRQ + +}; diff --git a/IDE/iotsafe/target.ld b/IDE/iotsafe/target.ld new file mode 100644 index 000000000..710641c6a --- /dev/null +++ b/IDE/iotsafe/target.ld @@ -0,0 +1,76 @@ +/* target.ld + * + * 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 + */ + +/* IoT-safe example + * Linker script for STM32L4 + */ + + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1M + SRAM1_STACK (rw) : ORIGIN = 0x20000000, LENGTH = 16K + SRAM1(rw) : ORIGIN = 0x20000000 + 16K, LENGTH = 256K - 16K + SRAM2 (rw) : ORIGIN = 0x20040000, LENGTH = 64K +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + *(.text*) + *(.rodata*) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + *(.data*) + . = ALIGN(4); + _end_data = .; + } > SRAM1 + + .bss : + { + _start_bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + _end = .; + } > SRAM1 + +} + +PROVIDE(_start_heap = ORIGIN(SRAM2)); +PROVIDE(_end_stack = ORIGIN(SRAM1_STACK) + LENGTH(SRAM1_STACK)); diff --git a/IDE/iotsafe/user_settings.h b/IDE/iotsafe/user_settings.h new file mode 100644 index 000000000..306b16d70 --- /dev/null +++ b/IDE/iotsafe/user_settings.h @@ -0,0 +1,107 @@ +/* user_settings.h + * + * 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 + */ + +/* Example 'user-settings.h' for IoT-Safe demo */ + +#ifndef IOTSAFE_EXAMPLE_USER_SETTINGS_H +#define IOTSAFE_EXAMPLE_USER_SETTINGS_H +#include + +#define WOLFSSL_IOTSAFE +#define HAVE_IOTSAFE_HWRNG +#define HAVE_HASHDRBG +#define WOLFSSL_SMALL_STACK + +#define WOLFSSL_GENERAL_ALIGNMENT 4 +#define DEBUG_WOLFSSL +#define WOLFSSL_LOG_PRINTF +#define DEBUG_WOLFSSL_VERBOSE +#define SINGLE_THREADED +#define WOLFSSL_USER_IO + +#define TIME_OVERRIDES + +extern volatile unsigned long jiffies; +static inline long XTIME(long *x) { return jiffies;} +#define NO_ASN_TIME +#define WOLFSSL_USER_CURRTIME +#define NO_OLD_RNGNAME +#define SMALL_SESSION_CACHE +#define WOLFSSL_SMALL_STACK +#define TFM_ARM +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT + + +/* Connect IoT-safe with PK_CALLBACKS */ +#define HAVE_PK_CALLBACKS + +/* ECC definitions */ +# define HAVE_ECC +# define ECC_ALT_SIZE +# define WOLFSSL_HAVE_SP_ECC +# define USE_CERT_BUFFERS_256 + +/* SP math */ +#define WOLFSSL_SP_MATH +#define WOLFSSL_SP_MATH_ALL +#define WOLFSSL_SP_SMALL +#define WOLFSSL_HAVE_SP_DH +#define SP_WORD_SIZE 32 + +/* RSA */ +#define RSA_LOW_MEM +#define WC_RSA_BLINDING + +#define WOLFSSL_DH_CONST + +/* TLS settings */ +#define NO_OLD_TLS +#define HAVE_TLS_EXTENSIONS +#define HAVE_AES_DECRYPT +#define HAVE_AESGCM +#define GCM_SMALL +#define HAVE_AESCCM +#define WOLFSSL_AES_COUNTER +#define WOLFSSL_AES_DIRECT + +/* TLS 1.3 */ +#define WOLFSSL_TLS13 +#define HAVE_SUPPORTED_CURVES +#define HAVE_HKDF +#define HAVE_AEAD +#define WC_RSA_PSS +#define HAVE_FFDHE_2048 +#define HAVE_SHA384 +#define HAVE_SHA512 +#define NO_WRITEV +#define NO_FILESYSTEM +#define NO_MAIN_DRIVER + +#define NO_RC4 +#define NO_DES3 + +#define htons(x) __builtin_bswap16(x) +#define ntohs(x) __builtin_bswap16(x) +#define ntohl(x) __builtin_bswap32(x) +#define htonl(x) __builtin_bswap32(x) + +#endif /* IOTSAFE_EXAMPLE_USER_SETTINGS_H */ diff --git a/configure.ac b/configure.ac index 092cddad2..c91ee2e3a 100644 --- a/configure.ac +++ b/configure.ac @@ -6187,6 +6187,18 @@ yes) AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA" ;; esac +# IoT-Safe support +AC_ARG_ENABLE([iotsafe], + [AS_HELP_STRING([--enable-iotsafe],[Enables support for IoT-Safe secure applet (default: disabled)])], + [ ENABLED_IOTSAFE=$enableval ], + [ ENABLED_IOTSAFE=no ] + ) + +AC_ARG_ENABLE([iotsafe-hwrng], + [AS_HELP_STRING([--enable-iotsafe-hwrng],[Enables support for IoT-Safe RNG (default: disabled)])], + [ ENABLED_IOTSAFE_HWRNG=$enableval ], + [ ENABLED_IOTSAFE_HWRNG=no ] + ) # User Settings AC_ARG_ENABLE([usersettings], @@ -6419,6 +6431,18 @@ then fi fi +if test "$ENABLED_IOTSAFE" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IOTSAFE" + ENABLED_IOTSAFE=yes +fi + +if test "$ENABLED_IOTSAFE_HWRNG" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_IOTSAFE_HWRNG" + ENABLED_IOTSAFE_HWRNG=yes +fi + AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MAX_STRENGTH"]) @@ -6757,6 +6781,8 @@ 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"]) AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM" = "xqnx"]) +AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"]) +AM_CONDITIONAL([BUILD_IOTSAFE_HWRNG],[test "x$ENABLED_IOTSAFE_HWRNG" = "xyes"]) if test "$ax_enable_debug" = "yes" || test "$ENABLED_STACKSIZE" != "no" || @@ -7126,6 +7152,8 @@ echo " * Linux AF_ALG: $ENABLED_AFALG" echo " * Linux devcrypto: $ENABLED_DEVCRYPTO" echo " * Crypto callbacks: $ENABLED_CRYPTOCB" echo " * i.MX6 CAAM: $ENABLED_CAAM" +echo " * IoT-Safe: $ENABLED_IOTSAFE" +echo " * IoT-Safe HWRNG: $ENABLED_IOTSAFE_HWRNG" echo "" echo "---" diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index f8ac68330..77a1fae9b 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -213,6 +213,21 @@ \defgroup CertManager CertManager API \defgroup Compression Compression \defgroup Error Error Reporting + \defgroup IoTSafe IoT-Safe Module + IoT-Safe (IoT-SIM Applet For Secure End-2-End Communication) is a technology that leverage the SIM as robust, + scalable and standardized hardware Root of Trust to protect data communication. + + IoT-Safe SSL sessions use the SIM as Hardware Security Module, offloading all the crypto public + key operations and reducing the attack surface by restricting access to certificate and keys + to the SIM. + + IoT-Safe support can be enabled on an existing WOLFSSL_CTX contex, using wolfSSL_CTX_iotsafe_enable().\n + Session created within the context can set the parameters for IoT-Safe key and files usage, and enable + the public keys callback, with wolfSSL_iotsafe_on(). + + If compiled in, the module supports IoT-Safe random number generator as source of entropy for wolfCrypt. + + \defgroup Keys Key and Cert Conversion \defgroup Logging Logging \defgroup Math Math API diff --git a/doc/dox_comments/header_files/doxygen_pages.h b/doc/dox_comments/header_files/doxygen_pages.h index 262236297..765c0f472 100644 --- a/doc/dox_comments/header_files/doxygen_pages.h +++ b/doc/dox_comments/header_files/doxygen_pages.h @@ -17,6 +17,7 @@
  • \ref Base_Encoding
  • \ref Compression
  • \ref Error
  • +
  • \ref IoTSafe
  • \ref Keys
  • \ref Logging
  • \ref Math
  • diff --git a/doc/dox_comments/header_files/iotsafe.h b/doc/dox_comments/header_files/iotsafe.h new file mode 100644 index 000000000..fdcec2612 --- /dev/null +++ b/doc/dox_comments/header_files/iotsafe.h @@ -0,0 +1,256 @@ +/*! + \ingroup IoTSafe + \brief This function enables the IoT-Safe support on the given context. + + \param ctx pointer to the WOLFSSL_CTX object on which the IoT-safe support must be enabled + \return 0 on success + \return WC_HW_E on hardware error + + _Example_ + \code + WOLFSSL_CTX *ctx; + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!ctx) + return NULL; + wolfSSL_CTX_iotsafe_enable(ctx); + \endcode + + \sa wolfSSL_iotsafe_on + \sa wolfIoTSafe_SetCSIM_read_cb + \sa wolfIoTSafe_SetCSIM_write_cb +*/ +WOLFSSL_API int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx); + + +/*! + \ingroup IoTSafe + \brief This function connects the IoT-Safe TLS callbacks to the given SSL session. + + \param ssl pointer to the WOLFSSL object where the callbacks will be enabled + \param privkey_id id of the iot-safe applet slot containing the private key for the host + \param ecdh_keypair_slot id of the iot-safe applet slot to store the ECDH keypair + \param peer_pubkey_slot id of the iot-safe applet slot to store the other endpoint's public key for ECDH + \param peer_cert_slot id of the iot-safe applet slot to store the other endpoint's public key for verification + \return 0 upon success + \return NOT_COMPILED_IN if HAVE_PK_CALLBACKS is disabled + \return BAD_FUNC_ARG if the ssl pointer is invalid + + _Example_ + \code + // Define key ids for IoT-Safe + #define PRIVKEY_ID 0x02 + #define ECDH_KEYPAIR_ID 0x03 + #define PEER_PUBKEY_ID 0x04 + #define PEER_CERT_ID 0x05 + // Create new ssl session + WOLFSSL *ssl; + ssl = wolfSSL_new(ctx); + if (!ssl) + return NULL; + // Enable IoT-Safe and associate key slots + ret = wolfSSL_CTX_iotsafe_on(ssl, PRIVKEY_ID, ECDH_KEYPAIR_ID, PEER_PUBKEY_ID, PEER_CERT_ID); + \endcode + + \sa wolfSSL_CTX_iotsafe_enable +*/ +WOLFSSL_API int wolfSSL_iotsafe_on(WOLFSSL *ssl, byte privkey_id, + byte ecdh_keypair_slot, byte peer_pubkey_slot, byte peer_cert_slot); + + +/*! + \ingroup IoTSafe + \brief Associates a read callback for the AT+CSIM commands. This input function is + usually associated to a read event of a UART channel communicating with the modem. + The read callback associated is global and changes for all the contexts that use + IoT-safe support at the same time. + \param rf Read callback associated to a UART read event. The callback function takes + two arguments (buf, len) and return the number of characters read, up to len. When a + newline is encountered, the callback should return the number of characters received + so far, including the newline character. + + _Example_ + \code + + // USART read function, defined elsewhere + int usart_read(char *buf, int len); + + wolfIoTSafe_SetCSIM_read_cb(usart_read); + + \endcode + + \sa wolfIoTSafe_SetCSIM_write_cb +*/ +WOLFSSL_API void wolfIoTSafe_SetCSIM_read_cb(wolfSSL_IOTSafe_CSIM_read_cb rf); + +/*! + \ingroup IoTSafe + \brief Associates a write callback for the AT+CSIM commands. This output function is + usually associated to a write event on a UART channel communicating with the modem. + The write callback associated is global and changes for all the contexts that use + IoT-safe support at the same time. + \param rf Write callback associated to a UART write event. The callback function takes + two arguments (buf, len) and return the number of characters written, up to len. + + _Example_ + \code + // USART write function, defined elsewhere + int usart_write(const char *buf, int len); + wolfIoTSafe_SetCSIM_write_cb(usart_write); + \endcode + + \sa wolfIoTSafe_SetCSIM_read_cb +*/ +WOLFSSL_API void wolfIoTSafe_SetCSIM_write_cb(wolfSSL_IOTSafe_CSIM_write_cb wf); + + + +/*! + \ingroup IoTSafe + \brief Generate a random buffer of given size, using the IoT-Safe function + GetRandom. This function is automatically used by the wolfCrypt RNG object. + + \param out the buffer where the random sequence of bytes is stored. + \param sz the size of the random sequence to generate, in bytes + \return 0 upon success + +*/ +WOLFSSL_API int wolfIoTSafe_GetRandom(unsigned char* out, word32 sz); + + +/*! + \ingroup IoTSafe + \brief Import a certificate stored in a file on IoT-Safe applet, and + store it locally in memory. + + \param id The file id in the IoT-Safe applet where the certificate is stored + \param output the buffer where the certificate will be imported + \param sz the maximum size available in the buffer output + \return the length of the certificate imported + \return < 0 in case of failure + + _Example_ + \code + #define CRT_CLIENT_FILE_ID 0x03 + unsigned char cert_buffer[2048]; + // Get the certificate into the buffer + cert_buffer_size = wolfIoTSafe_GetCert(CRT_CLIENT_FILE_ID, cert_buffer, 2048); + if (cert_buffer_size < 1) { + printf("Bad cli cert\n"); + return -1; + } + printf("Loaded Client certificate from IoT-Safe, size = %lu\n", cert_buffer_size); + + // Use the certificate buffer as identity for the TLS client context + if (wolfSSL_CTX_use_certificate_buffer(cli_ctx, cert_buffer, + cert_buffer_size, SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + printf("Cannot load client cert\n"); + return -1; + } + printf("Client certificate successfully imported.\n"); + \endcode + +*/ +WOLFSSL_API int wolfIoTSafe_GetCert(uint8_t id, unsigned char *output, unsigned long sz); + + + +/*! + \ingroup IoTSafe + \brief Import an ECC 256-bit public key, stored in the IoT-Safe applet, into an ecc_key + object. + + \param key the ecc_key object that will contain the key imported from the IoT-Safe applet + \param id The key id in the IoT-Safe applet where the public key is stored + \return 0 upon success + \return < 0 in case of failure + + + \sa wc_iotsafe_ecc_export_public + \sa wc_iotsafe_ecc_export_private + +*/ +WOLFSSL_API int wc_iotsafe_ecc_import_public(ecc_key *key, byte key_id); + +/*! + \ingroup IoTSafe + \brief Export an ECC 256-bit public key, from ecc_key object to a writable public-key slot into the IoT-Safe applet. + \param key the ecc_key object containing the key to be exported + \param id The key id in the IoT-Safe applet where the public key will be stored + \return 0 upon success + \return < 0 in case of failure + + + \sa wc_iotsafe_ecc_import_public + \sa wc_iotsafe_ecc_export_private + +*/ +WOLFSSL_API int wc_iotsafe_ecc_export_public(ecc_key *key, byte key_id); + +/*! + \ingroup IoTSafe + \brief Export an ECC 256-bit key, from ecc_key object to a writable private-key slot into the IoT-Safe applet. + \param key the ecc_key object containing the key to be exported + \param id The key id in the IoT-Safe applet where the private key will be stored + \return 0 upon success + \return < 0 in case of failure + + + \sa wc_iotsafe_ecc_import_public + \sa wc_iotsafe_ecc_export_public + +*/ +WOLFSSL_API int wc_iotsafe_ecc_export_private(ecc_key *key, byte key_id); + +/*! + \ingroup IoTSafe + \brief Sign a pre-computed 256-bit HASH, using a private key previously stored, or pre-provisioned, + in the IoT-Safe applet. + + \param in pointer to the buffer containing the message hash to sign + \param inlen length of the message hash to sign + \param out buffer in which to store the generated signature + \param outlen max length of the output buffer. Will store the bytes + \param id key id in the IoT-Safe applet for the slot containing the private key to sign the payload + written to out upon successfully generating a message signature + \return 0 upon success + \return < 0 in case of failure + + \sa wc_iotsafe_ecc_verify_hash + \sa wc_iotsafe_ecc_gen_k + +*/ +WOLFSSL_API int wc_iotsafe_ecc_sign_hash(byte *in, word32 inlen, byte *out, word32 *outlen, byte key_id); + +/*! + \ingroup IoTSafe + \brief Verify an ECC signature against a pre-computed 256-bit HASH, using a public key previously stored, or pre-provisioned, + in the IoT-Safe applet. Result is written to res. 1 is valid, 0 is invalid. +Note: Do not use the return value to test for valid. Only use res. + + \return 0 upon success (even if the signature is not valid) + \return < 0 in case of failure. + + \param sig buffer containing the signature to verify + \param hash The hash (message digest) that was signed + \param hashlen The length of the hash (octets) + \param res Result of signature, 1==valid, 0==invalid + \param key_id The id of the slot where the public ECC key is stored in the IoT-Safe applet + + \sa wc_iotsafe_ecc_sign_hash + \sa wc_iotsafe_ecc_gen_k + +*/ +WOLFSSL_API int wc_iotsafe_ecc_verify_hash(byte *sig, word32 siglen, byte *hash, word32 hashlen, int *res, byte key_id); + +/*! + \ingroup IoTSafe + \brief Generate an ECC 256-bit keypair and store it in a (writable) slot into the IoT-Safe applet. + \param key_id The id of the slot where the ECC key pair is stored in the IoT-Safe applet. + \return 0 upon success + \return < 0 in case of failure. + + \sa wc_iotsafe_ecc_sign_hash + \sa wc_iotsafe_ecc_verify_hash +*/ +WOLFSSL_API int wc_iotsafe_ecc_gen_k(byte key_id); + diff --git a/src/include.am b/src/include.am index d5b0999e3..bd0b3bd27 100644 --- a/src/include.am +++ b/src/include.am @@ -604,4 +604,5 @@ endif endif !BUILD_CRYPTONLY + endif !BUILD_FIPS_RAND diff --git a/src/internal.c b/src/internal.c index f29dc5103..ada1c0bd2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -32783,6 +32783,27 @@ int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) return maxFragment; } + +#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_PK_CALLBACKS) + +IOTSAFE *wolfSSL_get_iotsafe_ctx(WOLFSSL *ssl) +{ + if (ssl == NULL) + return NULL; + return &ssl->iotsafe; + +} + +int wolfSSL_set_iotsafe_ctx(WOLFSSL *ssl, IOTSAFE *iotsafe) +{ + if ((ssl == NULL) || (iotsafe == NULL)) + return BAD_FUNC_ARG; + XMEMCPY(&ssl->iotsafe, iotsafe, sizeof(IOTSAFE)); + return 0; +} + +#endif + #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) /* create an instance of WOLFSSL_BY_DIR_HASH structure */ WOLFSSL_BY_DIR_HASH* wolfSSL_BY_DIR_HASH_new(void) diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 902b108f7..6f46307d5 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -156,6 +156,11 @@ if BUILD_CRYPTOAUTHLIB src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c endif +if BUILD_IOTSAFE +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/iotsafe/iotsafe.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 diff --git a/wolfcrypt/src/port/iotsafe/iotsafe.c b/wolfcrypt/src/port/iotsafe/iotsafe.c new file mode 100644 index 000000000..d7399755f --- /dev/null +++ b/wolfcrypt/src/port/iotsafe/iotsafe.c @@ -0,0 +1,1211 @@ +/* iotsafe.c + * + * Copyright (C) 2006-2021 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 + */ + +/* IoT-safe module for communication with IoT-safe applet on SIM card */ + +#include +#ifdef WOLFSSL_IOTSAFE +#include +#include +#include +#include +#include +#include + +static int wolfIoT_initialized = 0; + +/* Modem APDU interface + * + */ + +/* I/O calls */ +static wolfSSL_IOTSafe_CSIM_read_cb csim_read_cb = NULL; +static wolfSSL_IOTSafe_CSIM_write_cb csim_write_cb = NULL; + +#define GETRAND_CMD_SIZE (24 + 2) + +#define AT_CSIM_CMD_SIZE 13 +#define AT_CMD_HDR_SIZE 10 +#define AT_CMD_INS_POS (AT_CMD_HDR_SIZE - 8) +#define AT_CMD_P1_POS (AT_CMD_HDR_SIZE - 6) +#define AT_CMD_P2_POS (AT_CMD_HDR_SIZE - 4) +#define AT_CMD_LC_POS (AT_CMD_HDR_SIZE - 2) + +/* Size of "\r\n + null terminator */ +#define CSIM_CMD_ENDSTR_SIZE 4 + +/* Buffer for CSIM RX APDU */ +#define MAXBUF 1024 +static char csim_read_buf[MAXBUF]; +static char csim_cmd[IOTSAFE_CMDSIZE_MAX]; + +/* APDU layer: I/O */ +static int csim_read(char *buf, int len) +{ + if (csim_read_cb) + return csim_read_cb(buf, len); + else + return -WOLFSSL_ERROR_SYSCALL; +} + +static int csim_write(const char *buf, int len) +{ + if (csim_write_cb) + return csim_write_cb(buf, len); + else + return -WOLFSSL_ERROR_SYSCALL; +} + +/* APDU string parser/expect + */ +static int hex_to_bytes(const char *hex, unsigned char *output, unsigned long sz) +{ + word32 i; + for (i = 0; i < sz; i++) { + output[i] = 0; + if ((hex[i * 2] >= 'A') && (hex[i * 2] <= 'F')) + output[i] += (hex[i * 2] - 'A' + 10) << 4; + else if (hex[i * 2] >= '0' && (hex[i * 2] <= '9')) + output[i] += (hex[i * 2] - '0') << 4; + else { + WOLFSSL_MSG("hex_to_bytes: syntax error"); + return -1; + } + if ((hex[i * 2 + 1] >= 'A') && (hex[i * 2 + 1] <= 'F')) + output[i] += (hex[i * 2 + 1] - 'A' + 10); + else if (hex[i * 2 + 1] >= '0' && (hex[i * 2 + 1] <= '9')) + output[i] += (hex[i * 2 + 1] - '0'); + else { + WOLFSSL_MSG("hex conversion: syntax error"); + return -1; + } + } + return (int)sz; +} + +static int bytes_to_hex(const unsigned char *bytes, char *hex, unsigned long sz) +{ + word32 i; + for (i = 0; i < sz; i++) { + unsigned char val; + val = (bytes[i] >> 4) & 0x0F; + if (val > 9) + hex[2 * i] = 'A' + (val - 10); + else + hex[2 * i] = '0' + val; + val = (bytes[i] & 0x0F); + if (val > 9) + hex[2 * i + 1] = 'A' + (val - 10); + else + hex[2 * i + 1] = '0' + val; + } + return (int)(2 * sz); +} + +static int expect_tok(const char *cmd, int size, const char *tok, char **repl) +{ + int ret = 0; + char *r_found = NULL; + static char parser_line[MAXBUF / 2]; + if (repl) + *repl = NULL; + if (cmd) + ret = csim_write(cmd, size); + while (ret > 0) { + ret = csim_read(csim_read_buf, MAXBUF); + if (tok && (ret > 0) && !r_found) { + /* Mark the beginning of the match in the reply. */ + r_found = XSTRSTR(csim_read_buf, tok); + if (r_found) { + XSTRNCPY(parser_line, r_found, MAXBUF / 2 - 1); + /* Do not break here! * + * Keep reading until csim_read returns 0, or error */ + } + } + } + if ((ret >= 0) && (repl && r_found)) { + *repl = parser_line + XSTRLEN(tok); + } + if (r_found) { + ret = (int)XSTRLEN(*repl); + } + return ret; +} + +static int expect_ok(const char *cmd, int size) +{ + return expect_tok(cmd, size, "OK", NULL); +} + +/* Utilities + */ + +/* Conversion utility from hex string format to bytes */ +static int hexbuffer_conv(char *hex_str, unsigned char *output, unsigned long sz) +{ + int ret; + if (XSTRLEN(hex_str) != (2 * sz)) { + return -1; + } + ret = hex_to_bytes(hex_str, output, sz); + if (ret != (int)sz) + return ret; + return (int)sz; +} + +/* Search a TLV by tag in a buffer */ +static char *search_tlv(const char *haystack, int size, uint8_t tag) +{ + int i = 0; + uint8_t t; + uint8_t l; + while (i < size) { + if (hex_to_bytes(&haystack[i], &t, 1) < 0) + return NULL; + if (hex_to_bytes(&haystack[i + 2], &l, 1) < 0) + return NULL; + if (tag == t) { + return (char *)&haystack[i]; + } + if (l + i > size) + return NULL; + i += 4 + 2 * l; + } + return NULL; +} + +static int iotsafe_cmd_start(char *cmd, byte class, byte ins, byte p1, byte p2) +{ + byte lc = 0; + char *out; + XMEMSET(cmd, 0, IOTSAFE_CMDSIZE_MAX); + XSTRNCPY(cmd, "AT+CSIM= 10,\"", IOTSAFE_CMDSIZE_MAX - 1); + out = cmd + AT_CSIM_CMD_SIZE; + bytes_to_hex(&class, out, 1); + bytes_to_hex(&ins, out + AT_CMD_INS_POS, 1); + bytes_to_hex(&p1, out + AT_CMD_P1_POS, 1); + bytes_to_hex(&p2, out + AT_CMD_P2_POS, 1); + bytes_to_hex(&lc, out + AT_CMD_LC_POS, 1); + out[10] = 0; + return (int)XSTRLEN(cmd); +} + +static int iotsafe_cmd_add_tlv_ex(char *cmd, byte tag, uint16_t len, + const byte *val, int taglen_size) +{ + word32 cur_csim_len; + word32 off; + byte cur_lc; + char *out; + int ret; + byte *len_b = (byte *)&len; + char *len_csim_str = (cmd + AT_CSIM_CMD_SIZE - 5); + word32 cmdlen; + + cmdlen = XSTRLEN(cmd); + if (cmdlen < AT_CSIM_CMD_SIZE) + return BAD_FUNC_ARG; + + if ((taglen_size < 1) || (taglen_size > 2)) + return BAD_FUNC_ARG; + + /* Read out current CSIM len from the existing string. + * The generated command may have the format: + * "AT+CSIM= 68" (< 100: leading space) + * or + * "AT+CSIM=212" (>=100: same positions, leading hundreds) + * + */ + cur_csim_len = (word32)len_csim_str[2] - '0'; + cur_csim_len += (len_csim_str[1] - '0') * 10; + if (len_csim_str[0] >= '0' && + len_csim_str[0] <= '9') { + cur_csim_len += len_csim_str[0] * 100; + } else if (len_csim_str[0] != ' ') { + return BAD_FUNC_ARG; + } + + if ((cmdlen + cur_csim_len + CSIM_CMD_ENDSTR_SIZE) > IOTSAFE_CMDSIZE_MAX) { + return MEMORY_E; + } + + /* Read out current Lc parameter in the CSIM command, last byte in the + * header + */ + if (hex_to_bytes(cmd + AT_CSIM_CMD_SIZE + AT_CMD_LC_POS, &cur_lc, 1) < 0) + return BAD_FUNC_ARG; + + /* Increase Lc and CSIM length according to the TLV len */ + cur_lc += 1 + taglen_size + len; + cur_csim_len += 2 + (2 * taglen_size) + 2*len; + + /* Position the out buffer to the current end of string */ + out = cmd + XSTRLEN(cmd); + off = 0; + + /* Write Tag */ + bytes_to_hex(&tag, out, 1); + off += 2; + + /* Write Len */ + if (taglen_size == 2) { + bytes_to_hex(&len_b[1], out + 2, 1); + bytes_to_hex(&len_b[0], out + 4, 1); + off += 4; + } else { + bytes_to_hex(&len_b[0], out + 2, 1); + off += 2; + } + + /* Write Val */ + ret = bytes_to_hex(val, out + off, len); + off += ret; + + /* Terminate string */ + out[off] = 0; + + /* Write new CSIM command size */ + if (cur_csim_len > 99) + len_csim_str[0] = (cur_csim_len / 100) + '0'; + else + len_csim_str[0] = ' '; + len_csim_str[1] = ((cur_csim_len % 100) / 10) + '0'; + len_csim_str[2] = (cur_csim_len % 10) + '0'; + + /* Write new Lc value */ + bytes_to_hex(&cur_lc, cmd + AT_CSIM_CMD_SIZE + AT_CMD_LC_POS, 1); + return off; +} + +static int iotsafe_cmd_add_tlv16(char *cmd, byte tag, uint16_t len, + const byte *val) +{ + return iotsafe_cmd_add_tlv_ex(cmd, tag, len, val, 2); +} + +static int iotsafe_cmd_add_tlv(char *cmd, byte tag, byte len, const byte *val) +{ + return iotsafe_cmd_add_tlv_ex(cmd, tag, len, val, 1); +} + +static void iotsafe_cmd_complete(char *cmd) +{ + word32 cmdlen = XSTRLEN(cmd); + char *out; + if (cmdlen + CSIM_CMD_ENDSTR_SIZE > IOTSAFE_CMDSIZE_MAX) + return; + out = cmd + cmdlen; + out[0] = '"'; + out[1] = '\r'; + out[2] = '\n'; + out[3] = 0; +} + +/** IOT-Safe Commands + * + * + */ +static int expect_csim_response(const char *cmd, word32 size, char **reply) +{ + const char csim_response_hdr[] = "+CSIM:"; + uint8_t len = 0; + char *csim_reply; + int ret; + char *payload; + char *endstr; + ret = expect_tok(cmd, size, csim_response_hdr, &csim_reply); + while (ret == 0) { + ret = expect_tok("AT\r\n", 4, csim_response_hdr, &csim_reply); + } + if (ret < 1) + return ret; + payload = XSTRSTR(csim_reply, "\""); + if (!payload) + return -1; + payload++; + if (XSTRNCMP(payload, "61", 2) == 0) { + if (hex_to_bytes(payload + 2, &len, 1) == 1) { + iotsafe_cmd_start(csim_cmd,1,IOTSAFE_INS_GETRESPONSE, 0, 0); + bytes_to_hex(&len, csim_cmd + AT_CSIM_CMD_SIZE + AT_CMD_LC_POS, 1); + csim_cmd[AT_CSIM_CMD_SIZE + AT_CMD_HDR_SIZE] = 0; + iotsafe_cmd_complete(csim_cmd); + ret = expect_tok(csim_cmd, (int)XSTRLEN(csim_cmd), + csim_response_hdr, reply); + if (ret < 1) + return -1; + payload = XSTRSTR(*reply, "\""); + if (!payload) + return -1; + payload++; + } + } + ret -= 2; + if (ret >= 4) { + endstr = XSTRSTR(payload, "9000\""); + if (!endstr) + endstr = XSTRSTR(payload, "\""); + if (endstr) { + *endstr = 0; + ret = (int)XSTRLEN(payload); + } + } + payload[ret] = '\0'; + *reply = payload; + return ret; +} + +/* Internal initialization function. + * Load the IoT-Safe applet + */ + +static int iotsafe_init(void) +{ + char *reply; + const char atcmd_load_applet_str[]= + "AT+CSIM=24,\"01A4040007A0000005590010\"\r\n"; + int ret; + + do { + ret = expect_ok("ATE0\r\n", 6); + if (ret == 0) + ret = expect_tok(NULL, 0, NULL, NULL); + } while (ret == 0); + if (ret < 0) + return ret; + + WOLFSSL_MSG("ATE0 OK!\n"); + if (expect_csim_response(atcmd_load_applet_str, + (word32)XSTRLEN(atcmd_load_applet_str), &reply) < 1) { + WOLFSSL_MSG("FAIL: no Applet code response from iot-safe init\n"); + } else { + WOLFSSL_MSG("IoT Safe Applet INIT OK\r\n"); + } + if (expect_tok(NULL, 0, NULL, NULL) < 0) + return -1; + wolfIoT_initialized++; + return 0; +} + + +/* internal: Read File content into a buffer */ +static int iotsafe_readfile(uint8_t file_id, unsigned char *content, + int max_size) +{ + char *resp; + int ret; + char *filesz_s; + int file_sz = 0; + uint16_t off = 0; + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_GETDATA, + IOTSAFE_GETDATA_FILE, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_FILE_ID, 1, &file_id); + iotsafe_cmd_complete(csim_cmd); + + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + if (ret <= 0) { + return ret; + } + + filesz_s = search_tlv(resp + 4, ret, 0x20); + if ((filesz_s) && (XSTRLEN(filesz_s)) >= 8) { + uint8_t fs_msb, fs_lsb; + if (hex_to_bytes(filesz_s + 4, &fs_msb, 1) < 0) + return -1; + if (hex_to_bytes(filesz_s + 6, &fs_lsb, 1) < 0) + return -1; + file_sz = (fs_msb << 8) + fs_lsb; + WOLFSSL_MSG("Stat successful on file"); + } + + if (file_sz > max_size) + { + WOLFSSL_MSG("iotsafe_readfile: insufficient space in buffer"); + return -1; + } + + while (off < file_sz) { + byte off_p1, off_p2; + off_p1 = (off >> 8) & 0xff; + off_p2 = (off & 0xff); + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_READ_FILE, + off_p1, off_p2); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_FILE_ID, 1, &file_id); + iotsafe_cmd_complete(csim_cmd); + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + if (ret > 0) { + if (ret > 2 * 0xF3) + ret = 2 * 0xF3; + if (ret > 2 * (file_sz - off)) + ret = 2 * (file_sz - off); + if (hex_to_bytes(resp, content + off, (ret / 2)) < 0) { + return -1; + } + off += ret/2; + } else { + WOLFSSL_MSG("IoTSafe: Error reading file."); + return -1; + } + } + return off; +} + +static int iotsafe_getrandom(unsigned char* output, unsigned long sz) +{ + char *resp = NULL; + int ret; + byte len = (byte)sz; + if (sz == 0) + return BAD_FUNC_ARG; + if ( !wolfIoT_initialized) + { + if (iotsafe_init() < 0) + return WC_HW_E; + } + + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_GETRANDOM,0,0); + bytes_to_hex(&len, csim_cmd + AT_CSIM_CMD_SIZE + AT_CMD_LC_POS, 1); + csim_cmd[AT_CSIM_CMD_SIZE + AT_CMD_HDR_SIZE] = 0; + iotsafe_cmd_complete(csim_cmd); + + ret = expect_csim_response(csim_cmd, (word32)GETRAND_CMD_SIZE, &resp); + + if (ret <= 0) { + WOLFSSL_MSG("Unexpected reply from RAND"); + ret = WC_HW_E; + } else { + ret = hexbuffer_conv(resp, output, sz); + if (ret < 0) + ret = WC_HW_E; + else + ret = 0; + } + if (expect_tok(NULL, 0, NULL, NULL) < 0) + return WC_HW_E; + return ret; +} + + + +#ifdef HAVE_ECC + +static int iotsafe_gen_keypair(byte wr_slot) +{ + char *resp; + int ret = WC_HW_E; + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_GEN_KEYPAIR, 0, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PRIVKEY_ID, 1, &wr_slot); + iotsafe_cmd_complete(csim_cmd); + if (expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp) < 1) { + WOLFSSL_MSG("Unexpected reply from Keygen"); + ret = WC_HW_E; + } else { + ret = 0; + } + return ret; +} + +static int iotsafe_get_public_key(byte idx, ecc_key *key) +{ + int ret; + char *resp; + char *rkey, *ktype, *payload_str; + char Qx[IOTSAFE_ECC_KSIZE * 2 + 1], Qy[IOTSAFE_ECC_KSIZE * 2 + 1]; + + /* exporting generated public key */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_READ_KEY,0, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PUBKEY_ID, 1, &idx); + iotsafe_cmd_complete(csim_cmd); + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + if (ret < 1) { + WOLFSSL_MSG("Error exporting EPH public key from IoT-Safe"); + return WC_HW_E; + } + if (ret < IOTSAFE_TAG_ECC_KEY_FIELD_SZ + 2) { + WOLFSSL_MSG("Response from iot-safe: too short"); + return BAD_STATE_E; + } + rkey = search_tlv(resp, ret, IOTSAFE_TAG_ECC_KEY_FIELD); + if (!rkey) { + WOLFSSL_MSG("IoT safe Error in rkey response"); + return MISSING_KEY; + } + ktype = search_tlv(rkey + 4, IOTSAFE_TAG_ECC_KEY_FIELD_SZ, + IOTSAFE_TAG_ECC_KEY_TYPE); + if (!ktype) { + WOLFSSL_MSG("IoT safe Error in ktype response"); + return MISSING_KEY; + } + payload_str = search_tlv(ktype + 4, IOTSAFE_TAG_ECC_KEY_TYPE_SZ, + IOTSAFE_TAG_ECC_KEY_XY); + if (!payload_str) { + WOLFSSL_MSG("IoT safe: Error in payload response"); + return MISSING_KEY; + } + XMEMSET(Qx, 0, sizeof(Qx)); + XMEMSET(Qy, 0, sizeof(Qy)); + ret = wc_ecc_init(key); + if (ret < 0) { + WOLFSSL_MSG("Cannot initialize ecc key to store IoTSafe public key"); + return -1; + } + XSTRNCPY(Qx, payload_str + 6, IOTSAFE_ECC_KSIZE * 2); + XSTRNCPY(Qy, payload_str + 6 + IOTSAFE_ECC_KSIZE * 2, IOTSAFE_ECC_KSIZE * 2); + + ret = wc_ecc_import_raw_ex(key, Qx, Qy, NULL, IOTSAFE_ECC_KTYPE); + if (ret < 0) { + WOLFSSL_MSG("Could not import raw key into ecc key"); + return ret; + } + WOLFSSL_MSG("Get Public key: OK.\n"); + return 0; +} + +static int iotsafe_put_public_key(byte idx, ecc_key *key) +{ + char *resp; + int ret; + word32 qxlen=IOTSAFE_ECC_KSIZE, qylen=IOTSAFE_ECC_KSIZE; + byte ecc_pub_raw[IOTSAFE_TAG_ECC_KEY_FIELD_SZ] = { + IOTSAFE_TAG_ECC_KEY_TYPE, + IOTSAFE_TAG_ECC_KEY_TYPE_SZ, + IOTSAFE_TAG_ECC_KEY_XY, + IOTSAFE_TAG_ECC_KEY_XY_SZ, + IOTSAFE_TAG_ECC_KEY_XY_HDR_BYTE + }; + + /* Export raw Qx, Qy values */ + ret = wc_ecc_export_public_raw(key, ecc_pub_raw + 5, &qxlen, + ecc_pub_raw + 5 + IOTSAFE_ECC_KSIZE, &qylen); + if (ret != 0) { + WOLFSSL_MSG("IoT Safe: Could not export public key: Error"); + return ret; + } + + /* Put Public Init */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_PUT_PUBLIC_INIT, + 0, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PUBKEY_ID, 1, &idx); + iotsafe_cmd_complete(csim_cmd); + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) { + WOLFSSL_MSG("Unexpected reply when storing public key"); + ret = WC_HW_E; + } else { + do { + ret = expect_ok("AT\r\n", 4); + } while (ret == 0); + if (ret > 0) { + /* Put Public Update */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_PUT_PUBLIC_UPDATE, + IOTSAFE_DATA_LAST, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_ECC_KEY_FIELD, + IOTSAFE_TAG_ECC_KEY_FIELD_SZ, ecc_pub_raw); + iotsafe_cmd_complete(csim_cmd); + if (expect_csim_response(csim_cmd, + (word32)XSTRLEN(csim_cmd), &resp) < 0) { + WOLFSSL_MSG("Unexpected reply when storing public key (update)"); + ret = WC_HW_E; + } else { + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_PUT_PUBLIC_INIT, + 1, 0); + iotsafe_cmd_complete(csim_cmd); + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) + ret = WC_HW_E; + else + ret = 0; + } + } + } + return ret; +} + +static int iotsafe_sign_hash(byte privkey_idx, uint16_t hash_algo, + uint8_t sign_algo, const byte *hash, word32 hashLen, + byte *signature, word32 *sigLen) +{ + byte mode_of_operation = IOTSAFE_MOO_SIGN_ONLY; + uint16_t hash_algo_be = XHTONS(hash_algo); + int ret = WC_HW_E; + char *resp; + char R[2 * IOTSAFE_ECC_KSIZE + 1]; + char S[2 * IOTSAFE_ECC_KSIZE + 1]; + + R[2*IOTSAFE_ECC_KSIZE] = 0; + S[2*IOTSAFE_ECC_KSIZE] = 0; + WOLFSSL_MSG("Enter iotsafe_sign_hash"); + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_SIGN_INIT, 0, 1); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PRIVKEY_ID, 1, &privkey_idx); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_MODE_OF_OPERATION, 1, + &mode_of_operation); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_HASH_ALGO, 2, + (byte *)&hash_algo_be); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_SIGN_ALGO, 1, &sign_algo); + iotsafe_cmd_complete(csim_cmd); + + + if (sign_algo == IOTSAFE_SIGN_ECDSA) { + if (*sigLen < 2 * IOTSAFE_ECC_KSIZE) + return -1; + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) { + WOLFSSL_MSG("Unexpected reply from IoTsafe EC sign"); + return WC_HW_E; + } + /* Compose sign_update message with hash to sign */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, + IOTSAFE_INS_SIGN_UPDATE, + IOTSAFE_DATA_LAST, + 0x01); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_HASH_FIELD, hashLen, hash); + iotsafe_cmd_complete(csim_cmd); + + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + if (ret >= 0) { + byte sig_hdr[3]; + if (hex_to_bytes(resp, sig_hdr, 3) < 0) { + ret = BAD_FUNC_ARG; + } else if ((sig_hdr[0] == IOTSAFE_TAG_SIGNATURE_FIELD) && + (sig_hdr[1] == 0) && + (sig_hdr[2] == 2 * IOTSAFE_ECC_KSIZE)) { + XSTRNCPY(R, resp + 6, IOTSAFE_ECC_KSIZE * 2); + XSTRNCPY(S, resp + 6 + IOTSAFE_ECC_KSIZE * 2, + IOTSAFE_ECC_KSIZE * 2); + ret = wc_ecc_rs_to_sig(R, S, signature, sigLen); + } else { + ret = WC_HW_E; + } + } else { + WOLFSSL_MSG("Invalid response from EC sign update"); + } + + /* Terminate sign/sign session. */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_SIGN_INIT, 1, 1); + iotsafe_cmd_complete(csim_cmd); + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) { + ret = WC_HW_E; + } + } else { + ret = NOT_COMPILED_IN; /* RSA not yet supported */ + } + WOLFSSL_MSG("iotsafe_sign_hash return point"); + return ret; +} + +static int iotsafe_verify_hash(byte pubkey_idx, uint16_t hash_algo, + uint8_t sign_algo, + const byte *hash, word32 hashLen, + const byte *sig, word32 sigLen, + int *result) +{ + byte mode_of_operation = IOTSAFE_MOO_SIGN_ONLY; + uint16_t hash_algo_be = XHTONS(hash_algo); + int ret = 1; + char *resp; + *result = 0; + + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_VERIFY_INIT, 0, 1); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PUBKEY_ID, 1, &pubkey_idx); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_MODE_OF_OPERATION, 1, + &mode_of_operation); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_HASH_ALGO, 2, + (byte *)&hash_algo_be); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_SIGN_ALGO, 1, &sign_algo); + iotsafe_cmd_complete(csim_cmd); + + if (sign_algo == IOTSAFE_SIGN_ECDSA) { + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) { + WOLFSSL_MSG("Unexpected reply from IoTsafe EC verify"); + return WC_HW_E; + } + /* Compose verify_update message with hash + signature */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, + IOTSAFE_INS_VERIFY_UPDATE, + IOTSAFE_DATA_LAST, + 0x01); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_HASH_FIELD, hashLen, hash); + iotsafe_cmd_add_tlv16(csim_cmd, IOTSAFE_TAG_SIGNATURE_FIELD, + sigLen,sig); + iotsafe_cmd_complete(csim_cmd); + + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + if (ret < 0) { + WOLFSSL_MSG("Invalid response from EC verify update"); + } else if (ret > 0) { + if (XSTRCMP("6D01", resp) == 0) { + WOLFSSL_MSG("Invalid signature!"); + /* 6D01 : Invalid signature. Return 0 and set *result to 0 */ + *result = 0; + ret = 0; + } else { + ret = WC_HW_E; /* IoT-safe bus error */ + } + } + else if (ret == 0) { + *result = 1; + ret = 0; + } + + /* Terminate sign/verify session. */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_VERIFY_INIT,1,1); + iotsafe_cmd_complete(csim_cmd); + if (expect_ok(csim_cmd, (word32)XSTRLEN(csim_cmd)) <= 0) { + *result = 0; + ret = WC_HW_E; + } + } else { + /* TODO: RSA */ + ret = NOT_COMPILED_IN; + } + return ret; +} + + +/* + * Callbacks for IoT-Safe ECC/ECDH functions + * + * + */ + +#ifdef HAVE_PK_CALLBACKS +static int wolfIoT_ecc_keygen(WOLFSSL* ssl, struct ecc_key* key, + unsigned int keySz, int ecc_curve, void* ctx) +{ + int ret; + IOTSAFE *iotsafe = wolfSSL_get_iotsafe_ctx(ssl); + if (!iotsafe) + return BAD_FUNC_ARG; + WOLFSSL_MSG("IOTSAFE: Called wolfIoT_ecc_keygen"); + (void)ctx; + if (iotsafe->enabled) { + ret = iotsafe_gen_keypair(iotsafe->ecdh_keypair_slot); + if (ret < 0) + return ret; + ret = iotsafe_get_public_key(iotsafe->ecdh_keypair_slot, key); + } else { + WC_RNG *rng = wolfSSL_GetRNG(ssl); + ret = wc_ecc_init(key); + if (ret == 0) { + /* create new key */ + ret = wc_ecc_make_key_ex(rng, keySz, key, ecc_curve); + } + } + return ret; +} + + +static int wolfIoT_ecc_sign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + int ret; + IOTSAFE *iotsafe = wolfSSL_get_iotsafe_ctx(ssl); + if (!iotsafe) + return BAD_FUNC_ARG; + (void)ctx; + WOLFSSL_MSG("IOTSAFE: Called wolfIoT_ecc_sign\n"); + + if (iotsafe->enabled) { + ret = iotsafe_sign_hash(iotsafe->privkey_id, IOTSAFE_HASH_SHA256, + IOTSAFE_SIGN_ECDSA, + in, inSz, out, outSz); + return ret; + } else { + WC_RNG *rng; + word32 idx = 0; + ecc_key *myKey; + byte* keyBuf = (byte*)keyDer; +#ifndef WOLFSSL_SMALL_STACK + ecc_key _myKey; + myKey = &_myKey; +#else + myKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (myKey == NULL) + return MEMORY_E; +#endif + rng = wolfSSL_GetRNG(ssl); + ret = wc_ecc_init(myKey); + if (ret == 0) + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, myKey, keySz); + if (ret == 0) + ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, myKey); + wc_ecc_free(myKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(myKey, NULL, DYNAMIC_TYPE_ECC); +#endif + } + return ret; +} + +static int wolfIoT_ecc_verify(WOLFSSL *ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx) +{ + + int ret; + ecc_key *key; + word32 r_size = IOTSAFE_ECC_KSIZE, s_size = IOTSAFE_ECC_KSIZE; + word32 inOutIdx = 0; + IOTSAFE *iot = wolfSSL_get_iotsafe_ctx(ssl); + byte pubkey_slot = iot->peer_cert_slot; + byte *sig_raw; +#ifndef WOLFSSL_SMALL_STACK + byte _sig_raw[IOTSAFE_ECC_KSIZE* 2]; + ecc_key _key; + sig_raw = _sig_raw; + key = &_key; + if (!iot) + return BAD_FUNC_ARG; +#else + if (!iot) + return BAD_FUNC_ARG; + sig_raw = (byte*)XMALLOC(IOTSAFE_ECC_KSIZE * 2, NULL, DYNAMIC_TYPE_SIGNATURE); + if (sig_raw == NULL) + return MEMORY_E; + key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (key == NULL) { + XFREE(sig_raw, NULL, DYNAMIC_TYPE_SIGNATURE); + return MEMORY_E; + } +#endif + (void)ctx; + + /* Invalidate verification, by default. */ + *result = 0; + if (iot->enabled) { + WOLFSSL_MSG("IOTSAFE: Called wolfIoT_ecc_verify\n"); + /* Convert ECC signature into R,S */ + ret = wc_ecc_sig_to_rs(sig, sigSz, sig_raw, &r_size, sig_raw + + IOTSAFE_ECC_KSIZE, &s_size); + if (ret < 0) { + WOLFSSL_MSG("Unable to convert signature to R+S"); + return ret; + } + /* Store the server's public key in IoT-safe vault */ + /* Create an ecc object to handle the key */ + ret = wc_ecc_init(key); + if (ret != 0) + return ret; + + /* Import from keyDer argument */ + ret = wc_EccPublicKeyDecode(keyDer, &inOutIdx, key, keySz); + if (ret == 0) { + /* Store public key in IoT-safe slot */ + ret = iotsafe_put_public_key(pubkey_slot, key); + } + if (ret == 0) { + /* Call iotsafe_verify_hash with ECC256 + SHA256 */ + ret = iotsafe_verify_hash(pubkey_slot, + IOTSAFE_HASH_SHA256, IOTSAFE_SIGN_ECDSA, + hash, hashSz, sig_raw, 2 * IOTSAFE_ECC_KSIZE, + result); + } + } else { + word32 idx = 0; + ret = wc_ecc_init(key); + if (ret == 0) + ret = wc_EccPublicKeyDecode(keyDer, &idx, key, keySz); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, + key); + } + wc_ecc_free(key); +#ifdef WOLFSSL_SMALL_STACK + XFREE(sig_raw, NULL, DYNAMIC_TYPE_SIGNATURE); + XFREE(key, NULL, DYNAMIC_TYPE_ECC); +#endif + return ret; +} + +static int wolfIoT_ecc_shared_secret(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx) +{ + int ret; + char *resp; + ecc_key *tmpKey; + IOTSAFE *iotsafe = wolfSSL_get_iotsafe_ctx(ssl); + byte keypair_slot; + byte pubkey_idx; +#ifndef WOLFSSL_SMALL_STACK + ecc_key _tmpKey; + tmpKey = &_tmpKey; +#endif + if (iotsafe == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + tmpKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (tmpKey == NULL) + return MEMORY_E; +#endif + ret = wc_ecc_init(tmpKey); + if (ret != 0) { + return ret; + } + (void)ctx; + WOLFSSL_MSG("IOTSAFE: Called wolfIoT_ecc_shared_secret\n"); + + if (iotsafe->enabled) { + WOLFSSL_MSG("Generating ECDH key pair"); + keypair_slot = iotsafe->ecdh_keypair_slot; + pubkey_idx = iotsafe->peer_pubkey_slot; + ret = iotsafe_gen_keypair(keypair_slot); + if (ret < 0) { + WOLFSSL_MSG("Error generating IoT-safe key pair"); + } + + if (ret == 0) { + /* Importing generated public key */ + ret = iotsafe_get_public_key(keypair_slot, tmpKey); + if (ret < 0) { + ret = WC_HW_E; + } + } + + if (ret == 0) { + /* Exporting generated public key into DER buffer */ + ret = wc_ecc_export_x963(tmpKey, pubKeyDer, pubKeySz); + } + + if (ret == 0) { + /* Store received public key from other endpoint in applet */ + ret = iotsafe_put_public_key(pubkey_idx, otherKey); + } + if (ret == 0) { + do { + ret = expect_ok("AT\r\n", 4); + } while (ret == 0); + if (ret > 0) { + /* Generating shared secret + */ + iotsafe_cmd_start(csim_cmd, IOTSAFE_CLASS, IOTSAFE_INS_COMPUTE_DH, 0, 0); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PRIVKEY_ID, 1, &keypair_slot); + iotsafe_cmd_add_tlv(csim_cmd, IOTSAFE_TAG_PUBKEY_ID, 1, &pubkey_idx); + iotsafe_cmd_complete(csim_cmd); + ret = expect_csim_response(csim_cmd, (word32)XSTRLEN(csim_cmd), &resp); + } + } + if (ret <= 0) { + WOLFSSL_MSG("Unexpected reply in DH command"); + ret = WC_HW_E; + } else { + int out_len = hex_to_bytes(resp, out, ret / 2); + if (out_len < 0) { + ret = BAD_FUNC_ARG; + } else { + *outlen = (word32)out_len; + ret = 0; + } + } + } else { + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + WC_RNG *rng; + privKey = tmpKey; + pubKey = otherKey; + rng = wolfSSL_GetRNG(ssl); + ret = wc_ecc_make_key_ex(rng, 0, privKey, otherKey->dp->id); + if (ret == 0) + ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); + } + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = tmpKey; + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, + otherKey->dp->id); + } + else { + ret = BAD_FUNC_ARG; + } + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + } + } + wc_ecc_free(tmpKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpKey, NULL, DYNAMIC_TYPE_ECC); +#endif + return ret; +} + +#ifndef NO_DH +/* Public DH Key Callback support */ +static int wolfIoT_dh_agree(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz, + unsigned char* out, word32* outlen, + void* ctx) +{ + + WOLFSSL_MSG("IOTSAFE: Called wolfIoT_ecc_dh_agree\n"); + (void)ctx; + (void)ssl; + (void)key; + (void)priv; + (void)privSz; + (void)otherPubKeyDer; + (void)otherPubKeySz; + (void)out; + (void)outlen; + + /* return an error to notify user this function + * is not yet implemented + */ + return WC_HW_E; +} +#endif /* ! NO_DH */ + +#endif /* HAVE_PK_CALLBACKS */ + +/* Public API for ecc */ + +int wc_iotsafe_ecc_import_public(ecc_key *key, byte key_id) +{ + return iotsafe_get_public_key(key_id, key); +} + +int wc_iotsafe_ecc_export_public(ecc_key *key, byte key_id) +{ + return iotsafe_put_public_key(key_id, key); +} + +int wc_iotsafe_ecc_sign_hash(byte *in, word32 inlen, byte *out, + word32 *outlen, byte key_id) +{ + return iotsafe_sign_hash(key_id, IOTSAFE_HASH_SHA256, IOTSAFE_SIGN_ECDSA, + in, inlen, out, outlen); +} +int wc_iotsafe_ecc_verify_hash(byte *sig, word32 siglen, byte *hash, + word32 hashlen, int *res, byte key_id) +{ + int ret; + word32 r_size = IOTSAFE_ECC_KSIZE; + word32 s_size = IOTSAFE_ECC_KSIZE; + byte sig_raw[IOTSAFE_ECC_KSIZE * 2]; + + /* Invalidate result, by default. */ + *res = 0; + + /* Convert ECC signature into R,S */ + ret = wc_ecc_sig_to_rs(sig, siglen, sig_raw, &r_size, sig_raw + + IOTSAFE_ECC_KSIZE, &s_size); + if (ret == 0) + ret = iotsafe_verify_hash(key_id, IOTSAFE_HASH_SHA256, IOTSAFE_SIGN_ECDSA, + hash, hashlen, sig_raw, 2 * IOTSAFE_ECC_KSIZE, res); + return ret; +} +int wc_iotsafe_ecc_gen_k(byte key_id) +{ + return iotsafe_gen_keypair(key_id); +} + +#endif /* HAVE_ECC */ + +/* API for GetRandom, used as custom Rand seed or block. + * Returns 0 on success. */ +int wolfIoTSafe_GetRandom(unsigned char *out, word32 sz) +{ + return iotsafe_getrandom(out, sz); +} + +/* API for GetCert (proxy for Read File / Close File) + */ +int wolfIoTSafe_GetCert(uint8_t id, unsigned char *output, unsigned long sz) +{ + XMEMSET(output, 0, sz); + return iotsafe_readfile(id, output, (word32)sz); +} + +/* API to set target specific I/O callbacks */ +void wolfIoTSafe_SetCSIM_read_cb(wolfSSL_IOTSafe_CSIM_read_cb rf) +{ + csim_read_cb = rf; +} + +void wolfIoTSafe_SetCSIM_write_cb(wolfSSL_IOTSafe_CSIM_write_cb wf) +{ + csim_write_cb = wf; +} + +/* API to equip target wolfSSL CTX to the IoT-Safe subsystem. */ +int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx) +{ + + if ( !wolfIoT_initialized) + { + if (iotsafe_init() < 0) + return WC_HW_E; + } + #if defined(HAVE_PK_CALLBACKS) + #ifdef HAVE_ECC + wolfSSL_CTX_SetEccSignCb(ctx, wolfIoT_ecc_sign); + wolfSSL_CTX_SetEccVerifyCb(ctx, wolfIoT_ecc_verify); + wolfSSL_CTX_SetEccKeyGenCb(ctx, wolfIoT_ecc_keygen); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, wolfIoT_ecc_shared_secret); + #ifndef NO_DH + wolfSSL_CTX_SetDhAgreeCb(ctx, wolfIoT_dh_agree); + #endif /* NO_DH */ + WOLFSSL_MSG("ECC callbacks set to IoT_safe interface"); + #endif + #ifndef NO_RSA + /* wolfSSL_CTX_SetRsaSignCb(wolfIoT_rsa_sign); // TODO: RSA callbacks */ + #endif + #else + (void)ctx; + #endif + return 0; +} + +int wolfSSL_iotsafe_on(WOLFSSL *ssl, byte privkey_id, + byte ecdh_keypair_slot, byte peer_pubkey_slot, byte peer_cert_slot) +{ +#if defined(HAVE_PK_CALLBACKS) + int ret; + IOTSAFE iotsafe; + iotsafe.privkey_id = privkey_id; + iotsafe.ecdh_keypair_slot = ecdh_keypair_slot; + iotsafe.peer_pubkey_slot = peer_pubkey_slot; + iotsafe.peer_cert_slot = peer_cert_slot; + iotsafe.enabled = 1; + ret = wolfSSL_set_iotsafe_ctx(ssl, &iotsafe); + if (ret == 0) { + WOLFSSL_MSG("IOTSAFE is ON"); + } else { + WOLFSSL_MSG("Error setting IOT-Safe Context on SSL Session"); + } + return ret; +#else + (void)ssl; + (void)privkey_id; + (void)ecdh_keypair_slot; + (void)peer_cert_slot; + (void)peer_pubkey_slot; + return NOT_COMPILED_IN; +#endif +} +#endif /* WOLFSSL_IOTSAFE */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 5f32df457..5025a1ec0 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -173,6 +173,9 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) #include #endif +#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_IOTSAFE_HWRNG) +#include +#endif #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) static word32 intel_flags = 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7f3c08855..1c5eecf90 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -256,6 +256,10 @@ #define WC_MD5_DIGEST_SIZE 16 #endif +#ifdef WOLFSSL_IOTSAFE + #include +#endif + #ifdef __cplusplus extern "C" { @@ -4511,6 +4515,9 @@ struct WOLFSSL { #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; #endif +#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_PK_CALLBACKS) + IOTSAFE iotsafe; +#endif }; /* @@ -4700,6 +4707,11 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32); WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment); +#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_PK_CALLBACKS) +WOLFSSL_LOCAL IOTSAFE *wolfSSL_get_iotsafe_ctx(WOLFSSL *ssl); +WOLFSSL_LOCAL int wolfSSL_set_iotsafe_ctx(WOLFSSL *ssl, IOTSAFE *iotsafe); +#endif + #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) WOLFSSL_LOCAL int SetECKeyInternal(WOLFSSL_EC_KEY* eckey); WOLFSSL_LOCAL int SetECKeyExternal(WOLFSSL_EC_KEY* eckey); diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 6363aaeb3..574b0eeff 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -156,3 +156,7 @@ nobase_include_HEADERS+= wolfssl/wolfcrypt/port/caam/wolfcaam.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h endif + +if BUILD_IOTSAFE +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/iotsafe/iotsafe.h +endif diff --git a/wolfssl/wolfcrypt/port/iotsafe/iotsafe.h b/wolfssl/wolfcrypt/port/iotsafe/iotsafe.h new file mode 100644 index 000000000..66a980e77 --- /dev/null +++ b/wolfssl/wolfcrypt/port/iotsafe/iotsafe.h @@ -0,0 +1,174 @@ +/* iotsafe.h + * + * Copyright (C) 2006-2021 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 + */ + +/* IoT-safe module for communication with IoT-safe applet on SIM card */ + +#ifndef WOLFSSL_IOTSAFE_H +#define WOLFSSL_IOTSAFE_H + +#include + +#ifdef WOLFSSL_IOTSAFE +#include + +WOLFSSL_API int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx); + +WOLFSSL_API int wolfSSL_iotsafe_on(WOLFSSL *ssl, byte privkey_id, + byte ecdh_keypair_slot, byte peer_pubkey_slot, byte peer_cert_slot); + + +typedef int (*wolfSSL_IOTSafe_CSIM_write_cb)(const char*, int); +typedef int (*wolfSSL_IOTSafe_CSIM_read_cb)(char *, int); + +WOLFSSL_API void wolfIoTSafe_SetCSIM_read_cb(wolfSSL_IOTSafe_CSIM_read_cb rf); +WOLFSSL_API void wolfIoTSafe_SetCSIM_write_cb(wolfSSL_IOTSafe_CSIM_write_cb wf); + +WOLFSSL_API int wolfIoTSafe_GetRandom(unsigned char* out, word32 sz); +WOLFSSL_API int wolfIoTSafe_GetCert(uint8_t id, unsigned char *output, unsigned long sz); + +#ifdef HAVE_ECC +#include +#define IOTSAFE_ECC_KTYPE ECC_SECP256R1 +#define IOTSAFE_ECC_KSIZE 32 +WOLFSSL_API int wc_iotsafe_ecc_import_public(ecc_key *key, byte key_id); +WOLFSSL_API int wc_iotsafe_ecc_export_public(ecc_key *key, byte key_id); +WOLFSSL_API int wc_iotsafe_ecc_export_private(ecc_key *key, byte key_id); +WOLFSSL_API int wc_iotsafe_ecc_sign_hash(byte *in, word32 inlen, byte *out, word32 *outlen, byte key_id); +WOLFSSL_API int wc_iotsafe_ecc_verify_hash(byte *sig, word32 siglen, byte *hash, word32 hashlen, int *res, byte key_id); +WOLFSSL_API int wc_iotsafe_ecc_gen_k(byte key_id); +#endif + + +#ifdef HAVE_IOTSAFE_HWRNG + #ifndef HAVE_HASHDRBG + #define CUSTOM_RAND_GENERATE_BLOCK wolfIoTSafe_GetRandom + #else + #define CUSTOM_RAND_GENERATE_SEED wolfIoTSafe_GetRandom + #endif +#endif + +struct wc_IOTSAFE { + int enabled; + byte privkey_id; + byte ecdh_keypair_slot; + byte peer_pubkey_slot; + byte peer_cert_slot; +}; +typedef struct wc_IOTSAFE IOTSAFE; + +/* Default IOT-Safe Class */ +#define IOTSAFE_CLASS 0x81 + +/* Command codes */ +#define IOTSAFE_INS_PUT_PUBLIC_INIT 0x24 +#define IOTSAFE_INS_PUT_PUBLIC_UPDATE 0xD8 +#define IOTSAFE_INS_SIGN_INIT 0x2A +#define IOTSAFE_INS_SIGN_UPDATE 0x2B +#define IOTSAFE_INS_VERIFY_INIT 0x2C +#define IOTSAFE_INS_VERIFY_UPDATE 0x2D +#define IOTSAFE_INS_COMPUTE_DH 0x46 +#define IOTSAFE_INS_GETRANDOM 0x84 +#define IOTSAFE_INS_READ_FILE 0xB0 +#define IOTSAFE_INS_GEN_KEYPAIR 0xB9 +#define IOTSAFE_INS_GETRESPONSE 0xC0 +#define IOTSAFE_INS_GETDATA 0xCB +#define IOTSAFE_INS_READ_KEY 0xCD + +/* Tags */ +#define IOTSAFE_TAG_ECC_KEY_FIELD 0x34 +#define IOTSAFE_TAG_ECC_KEY_FIELD_SZ 0x45 +#define IOTSAFE_TAG_ECC_KEY_TYPE 0x49 +#define IOTSAFE_TAG_ECC_KEY_TYPE_SZ 0x43 +#define IOTSAFE_TAG_ECC_KEY_XY 0x86 +#define IOTSAFE_TAG_ECC_KEY_XY_SZ 0x41 +#define IOTSAFE_TAG_ECC_KEY_XY_HDR_BYTE 0x04 + +#define IOTSAFE_TAG_HASH_FIELD 0x9E +#define IOTSAFE_TAG_SIGNATURE_FIELD 0x33 +#define IOTSAFE_TAG_FILE_ID 0x83 +#define IOTSAFE_TAG_PRIVKEY_ID 0x84 +#define IOTSAFE_TAG_PUBKEY_ID 0x85 +#define IOTSAFE_TAG_HASH_ALGO 0x91 +#define IOTSAFE_TAG_SIGN_ALGO 0x92 +#define IOTSAFE_TAG_MODE_OF_OPERATION 0xA1 + +/* Flags - data */ +#define IOTSAFE_GETDATA_FILE 0xC3 +#define IOTSAFE_DATA_LAST 0x80 +#define IOTSAFE_CMDSIZE_MAX 512 + +/* IoT-safe tables of constants */ + +/* 2.5.1 Algorithms for hash */ +#define IOTSAFE_HASH_SHA256 0x0001 +#define IOTSAFE_HASH_SHA384 0x0002 +#define IOTSAFE_HASH_SHA512 0x0004 + +/* 2.5.2 Algorithms for signature */ +#define IOTSAFE_SIGN_RSA_PKCS15 0x01 +#define IOTSAFE_SIGN_RSA_PSS 0x02 +#define IOTSAFE_SIGN_ECDSA 0x04 + +/* 2.5.3 Algorithms for key agreement */ +#define IOTSAFE_KA_ECKA 0x01 + +/* 2.5.4 Algorithms for key derivation */ +#define IOTSAFE_KD_PRF_SHA256 0x01 +#define IOTSAFE_KD_HKDF 0x02 + +/* 2.5.14 Mode of Operation for signature commands */ +#define IOTSAFE_MOO_HASH_FULLTEXT 0x01 +#define IOTSAFE_MOO_HASH_LASTBLOCK 0x02 +#define IOTSAFE_MOO_SIGN_ONLY 0x03 + + +/* IoT-safe Public key format */ +#define IOTSAFE_TAG_PKEY_ID 0x85 +#define IOTSAFE_TAG_PKEY_ACCESS 0x60 + #define IOTSAFE_ACCESS_READ (1 << 0) + #define IOTSAFE_ACCESS_UPDATE (1 << 1) + +#define IOTSAFE_TAG_PKEY_OBJSTATE 0x4A /* 1 == active */ + +#define IOTSAFE_TAG_PKEY_TYPE 0x4B + #define IOTSAFE_KEYTYPE_RSA2048 0x03 + #define IOTSAFE_KEYTYPE_SECP256R1_PERSISTENT 0x13 + #define IOTSAFE_KEYTYPE_SECP256R1_VOLATILE 0x14 + #define IOTSAFE_KEYTYPE_BRAINPOOL_PERSISTENT 0x23 + #define IOTSAFE_KEYTYPE_BRAINPOOL_VOLATILE 0x24 + #define IOTSAFE_KEYTYPE_HMAC_CAPABLE 0xA0 + +#define IOTSAFE_TAG_PKEY_USAGE 0x4E + #define IOTSAFE_KEYUSAGE_GENERAL 0x01 + #define IOTSAFE_KEYUSAGE_CERT_VERIFY_TLS12 0x02 + #define IOTSAFE_KEYUSAGE_CERT_VERIFY_TLS13 0x03 + +#define IOTSAFE_TAG_PKEY_CRYPTO 0x61 + #define IOTSAFE_CRYPTO_SIGN_VERIFY (1 << 0) + #define IOTSAFE_CRYPTO_KEYGEN (1 << 1) + #define IOTSAFE_CRYPTO_KEYAGREE (1 << 2) + #define IOTSAFE_CRYPTO_KDF (1 << 3) + #define IOTSAFE_CRYPTO_ALL (0x0F) + +#define IOTSAFE_TAG_PKEY_SKA 0x6F + #define IOTSAFE_SKA_ECKA (1 << 0) +#endif /* WOLFSSL_IOTSAFE */ +#endif /* WOLFSSL_IOTSAFE_H */