diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..03ba8b58a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +bin/ +Makefile.local +.DS_Store + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..5258cf589 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +sudo: false +language: bash +os: + - linux + +script: + # Download Arduino IDE + - wget -O arduino.tar.xz https://www.arduino.cc/download.php?f=/arduino-nightly-linux64.tar.xz + - tar xf arduino.tar.xz + - mv arduino-nightly $HOME/arduino_ide + # Download ESP8266 Arduino core + - cd $HOME/arduino_ide/hardware + - mkdir esp8266com + - cd esp8266com + - git clone https://github.com/esp8266/Arduino.git esp8266 + - cd esp8266 + - export ESP8266_ARDUINO_DIR="$PWD" + # Download toolchain and esptool + - cd tools + - python get.py + - export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" + # Build axTLS + - cd $TRAVIS_BUILD_DIR + - make + # Copy the library into Arduino core + - cp bin/libaxtls.a $ESP8266_ARDUINO_DIR/tools/sdk/lib/libaxtls.a + # Try building examples in ESP8266WiFi library from the ESP8266 Arduino core + - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 + - sleep 3 + - export DISPLAY=:1.0 + - export PATH="$HOME/arduino_ide:$PATH" + - which arduino + - cd $ESP8266_ARDUINO_DIR + - source tests/common.sh + - arduino --board esp8266com:esp8266:generic --save-prefs + - arduino --get-pref sketchbook.path + - build_sketches $HOME/arduino_ide $ESP8266_ARDUINO_DIR/libraries/ESP8266WiFi/examples/HTTPSRequest + # Feel free to add more test cases (for other environments) here + +notifications: + email: + on_success: change + on_failure: change diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..15c5e7223 --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +TOOLCHAIN_PREFIX := xtensa-lx106-elf- +CC := $(TOOLCHAIN_PREFIX)gcc +AR := $(TOOLCHAIN_PREFIX)ar +LD := $(TOOLCHAIN_PREFIX)gcc +OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy + + +XTENSA_LIBS ?= $(shell $(CC) -print-sysroot) + + +OBJ_FILES := \ + crypto/aes.o \ + crypto/bigint.o \ + crypto/hmac.o \ + crypto/md2.o \ + crypto/md5.o \ + crypto/rc4.o \ + crypto/rsa.o \ + crypto/sha1.o \ + ssl/asn1.o \ + ssl/gen_cert.o \ + ssl/loader.o \ + ssl/os_port.o \ + ssl/p12.o \ + ssl/tls1.o \ + ssl/tls1_clnt.o \ + ssl/tls1_svr.o \ + ssl/x509.o \ + crypto/crypto_misc.o \ + + +CPPFLAGS += -I$(XTENSA_LIBS)/include \ + -Icrypto \ + -Issl \ + -I. + +LDFLAGS += -L$(XTENSA_LIBS)/lib \ + -L$(XTENSA_LIBS)/arch/lib \ + + +CFLAGS+=-std=c99 -DESP8266 + +CFLAGS += -Wall -Os -g -O2 -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -D__ets__ -DICACHE_FLASH +BIN_DIR := bin +AXTLS_AR := $(BIN_DIR)/libaxtls.a + +all: $(AXTLS_AR) + +$(AXTLS_AR): | $(BIN_DIR) + +$(AXTLS_AR): $(OBJ_FILES) + for file in $(OBJ_FILES); do \ + $(OBJCOPY) \ + --rename-section .text=.irom0.text \ + --rename-section .literal=.irom0.literal \ + $$file; \ + done + $(AR) cru $@ $^ + +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +clean: + rm -rf $(OBJ_FILES) $(AXTLS_AR) + + +.PHONY: all clean diff --git a/README.md b/README.md new file mode 100644 index 000000000..e0e454a4b --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +Replacement for Espressif's libssl, kept as close as possible to [axTLS](http://axtls.sourceforge.net/) source. +Currently based on axTLS 1.4.9, will be upgraded to 1.5.3. + +[![Build status](https://travis-ci.org/igrr/axtls-8266.svg)](https://travis-ci.org/igrr/axtls-8266) + +This is not a self-sufficient library. Application has to provide the following symbols (list not complete yet): +``` +ax_port_malloc +ax_port_calloc +ax_port_realloc +ax_port_free +ax_port_read +ax_port_write +ax_port_open +ax_port_close +ax_get_file +phy_get_rand (provided by the IoT SDK) +ets_printf (in ESP8266 ROM) +ets_putc (in ESP8266 ROM) +gettimeofday +time +ctime +``` + +For use with LwIP raw TCP API, see [compat/README.md](compat/README.md) + +To build, add xtensa toolchain to your path, and run `make`. + +See [LICENSE](LICENSE) file for axTLS license. diff --git a/compat/README.md b/compat/README.md new file mode 100644 index 000000000..fff33837d --- /dev/null +++ b/compat/README.md @@ -0,0 +1,149 @@ +If you are using [LWIP raw tcp mode](http://lwip.wikia.com/wiki/Raw/TCP) and want to add SSL support below are the steps that can help you to achieve this with the help of [axTLS]( http://axtls.sourceforge.net/ ). + +First you have to include the `lwipr_compat.h` header. + +```C +#include "compat/lwipr_compat.h" +``` + +Then in the code block where you initialize the tcp raw connection you should call `axl_init`. +Take a look at the example below: + +```C +lwip_init(); + +/* + * The line below should be added AFTER the lwip_init code + * AND BEFORE the call to tcp_new() + * The parameter value 10 specifies how many SSL connections are expected + */ +axl_init(10); + +// .. some more code +tcp = tcp_new(); +tcp_sent(tcp, staticOnSent); +tcp_recv(tcp, staticOnReceive); +tcp_err(tcp, staticOnError); +tcp_poll(tcp, staticOnPoll, 4); +// ... and even more code +res = tcp_connect(tcp, &addr, port, staticOnConnected); + + +``` + +Now we should add in our `staticOnConnected` funciton code to create new ssl context and ssl object. +In the example below the `sslObj` and `sslContext` are defined as global + +```C +// global definitions +SSL *sslObj = NULL; +SSLCTX* sslContext = NULL; + +// and some more code... + +err_t staticOnConnected(void *arg, struct tcp_pcb *tcp, err_t err) +{ + int clientfd = -1; + uint32_t options = 0; + + if (tcp == NULL) { + /* @TODO: Take care to handle error conditions */ + return -1; + } + + clientfd = axl_append(tcp); + if(clientfd == -1) { + printf("Unable to add LWIP tcp -> clientfd mapping\n"); + return ERR_OK; + } + + printf("Connected: ClientId: %d\n", clientfd); +#ifdef SSL_DEBUG + options |= SSL_DISPLAY_STATES | SSL_DISPLAY_BYTES; +#endif + + // if you want to verify the server certificate later you can also add the following option + options |= SSL_SERVER_VERIFY_LATER + + sslContext = ssl_ctx_new(SSL_CONNECT_IN_PARTS | options, 1); // !!! SSL_CONNECT_IN_PARTS must be in the flags !!! + sslObj = ssl_client_new(sslContext, clientfd, NULL, 0); + + return ERR_OK; +} +``` + + +Once we are connected we can send and receive information. For the receiving part we can do the following + +```C +err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err) +{ + uint8_t *read_buf = NULL; + int read_bytes = 0; + + printf("Err: %d\n", err); + + if(tcp == NULL || p == NULL) { + /* @TODO: Take care to handle error conditions */ + return -1; + } + + read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p); + if(read_bytes > 0) { + printf("Got data: %s", read_buf); + // @TODO: Do something useful with the read_buf + } + + return ERR_OK; +} +``` + +In the receiving part you can also add debug code to display more information about the SSL handshake, once it was successul. + + +```C +err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err) +{ + static int show_info = 0; + const char *common_name = NULL; + + // .. + read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p); + if(read_bytes > 0) { + printf("Got data: %s", read_buf); + // @TODO: Do something useful with the read_buf + } + + if(!show_info && ssl_handshake_status(sslObj) == SSL_OK) { + common_name = ssl_get_cert_dn(sslObj, SSL_X509_CERT_COMMON_NAME); + if (common_name) { + printf("Common Name:\t\t\t%s\n", common_name); + } + + // These two funcitons below can be found in the axtls examples + display_session_id(sslObj); + display_cipher(sslObj); + show_info = 1; + } + + return ERR_OK; +} + +``` + + +And for the sending part we can use the following code sample as a start + +```C +void someSendingfunction() { + uint8_t *out_buf; + int out_bytes = 0; + + // ... take care to store something in the out_buf + + axl_ssl_write(sslObj, out_buf, out_bytes); +} + +``` + +Good luck and send your success stories at slaff@attachix.com. diff --git a/compat/lwipr_compat.c b/compat/lwipr_compat.c new file mode 100644 index 000000000..a334454fb --- /dev/null +++ b/compat/lwipr_compat.c @@ -0,0 +1,285 @@ +/* + * Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP) + * + * Created on: Jan 15, 2016 + * Author: Slavey Karadzhov + */ +#include "lwipr_compat.h" + +AxlTcpDataArray axlFdArray; + +#include + +/* High Level "public" functions */ + +/** + * Function that should be called once we are ready to use the axTLS - LWIP raw compatibility + */ +void axl_init(int capacity) { + ax_fd_init(&axlFdArray, capacity); +} + +/** + * Appends a tcp to the internal array. Returns client file descriptor + */ +int axl_append(struct tcp_pcb *tcp) { + return ax_fd_append(&axlFdArray, tcp); +} + +/** + * Frees the internal mapping from this tcp. Returns the number of occurrences of the tcp + */ +int axl_free(struct tcp_pcb *tcp) { + int i; + int occurances = 0; + + if(tcp == NULL) { + return 0; + } + + AxlTcpDataArray *vector = &axlFdArray; + AXL_DEBUG("AXL: Freeing %d tcp item", vector->size); + for (i = 0; i < vector->size; i++) { + if (vector->data[i].tcp == tcp) { + if(vector->data[i].tcp_pbuf != NULL) { + pbuf_free(vector->data[i].tcp_pbuf); + vector->data[i].tcp_pbuf = NULL; + } + vector->data[i].tcp = NULL; + vector->data[i].pbuf_offset = 0; + occurances++; + } + } + + return occurances; +} + +/** + * Reads data from the SSL over TCP stream. Returns decrypted data. + * @param SSL *sslObj + * @param uint8_t **in_data - pointer to the decrypted incoming data, or NULL if nothing was read + * @param void *arg - possible arguments passed to the tcp raw layer during initialization + * @param tcp_pcb *tcp - pointer to the raw tcp object + * @param pbuf *p - pointer to the buffer with the TCP packet data + * + * @return int + * 0 - when everything is fine but there are no symbols to process yet + * < 0 - when there is an error + * > 0 - the length of the clear text characters that were read + */ +int axl_ssl_read(SSL *ssl, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p) { + int read_bytes = 0; + int total_bytes = 0; + int clientfd = -1; + + AxlTcpData* data = NULL; + + if (ssl == NULL) { + return ERR_AXL_INVALID_SSL; + } + + clientfd = ax_fd_getfd(&axlFdArray, tcp); + if(clientfd == -1) { + return ERR_AXL_INVALID_CLIENTFD; + } + + data = ax_fd_get(&axlFdArray, clientfd); + if(data == NULL) { + return ERR_AXL_INVALID_CLIENTFD_DATA; + } + + if (p != NULL) { + data->tcp_pbuf = p; + data->pbuf_offset = 0; + } + + AXL_DEBUG("READY TO READ SOME DATA\n"); + + tcp_recved(tcp, p->tot_len); + do { + WATCHDOG_FEED(); + read_bytes = ssl_read(ssl, in_data); + AXL_DEBUG("axl_ssl_read: Read bytes: %d\n", read_bytes); + if(read_bytes < SSL_OK) { + /* An error has occurred. Give it back for further processing */ + total_bytes = read_bytes; + break; + } + total_bytes+= read_bytes; + } while (p->tot_len - data->pbuf_offset > 0); + + pbuf_free(p); + + return total_bytes; +} + +/* + * Lower Level LWIP RAW functions + */ + +/* + * The LWIP tcp raw version of the SOCKET_WRITE(A, B, C) + */ +int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed) { + AxlTcpData *data = NULL; + int tcp_len = 0; + err_t err = ERR_OK; + + data = ax_fd_get(&axlFdArray, clientfd); + if(data == NULL) { + return ERR_AXL_INVALID_CLIENTFD; + } + + if (data == NULL || data->tcp == NULL || buf == NULL || bytes_needed == 0) { + AXL_DEBUG("Return Zero.\n"); + return 0; + } + + if (tcp_sndbuf(data->tcp) < bytes_needed) { + tcp_len = tcp_sndbuf(data->tcp); + if(tcp_len == 0) { + AXL_DEBUG("The send buffer is full! We have problem.\n"); + return 0; + } + + } else { + tcp_len = bytes_needed; + } + + if (tcp_len > 2 * data->tcp->mss) { + tcp_len = 2 * data->tcp->mss; + } + + do { + err = tcp_write(data->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY); + if(err < SSL_OK) { + AXL_DEBUG("Got error: %d\n", err); + } + + if (err == ERR_MEM) { + AXL_DEBUG("Not enough memory to write data with length: %d (%d)\n", tcp_len, bytes_needed); + tcp_len /= 2; + } + } while (err == ERR_MEM && tcp_len > 1); + AXL_DEBUG("send_raw_packet length %d(%d)\n", tcp_len, bytes_needed); + if (err == ERR_OK) { + err = tcp_output(data->tcp); + if(err != ERR_OK) { + AXL_DEBUG("tcp_output got err: %d\n", err); + } + } + + return tcp_len; +} + +/* + * The LWIP tcp raw version of the SOCKET_READ(A, B, C) + */ +int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed) { + AxlTcpData *data = NULL; + uint8_t *read_buf = NULL; + uint8_t *pread_buf = NULL; + u16_t recv_len = 0; + + data = ax_fd_get(&axlFdArray, clientfd); + if (data == NULL) { + return ERR_AXL_INVALID_CLIENTFD_DATA; + } + + if(data->tcp_pbuf == NULL || data->tcp_pbuf->tot_len == 0) { + AXL_DEBUG("Nothing to read?! May be the connection needs resetting?\n"); + return 0; + } + + read_buf =(uint8_t*)calloc(data->tcp_pbuf->len + 1, sizeof(uint8_t)); + pread_buf = read_buf; + if (pread_buf != NULL){ + recv_len = pbuf_copy_partial(data->tcp_pbuf, read_buf, bytes_needed, data->pbuf_offset); + data->pbuf_offset += recv_len; + } + + if (recv_len != 0) { + memcpy(buf, read_buf, recv_len); + } + + if(bytes_needed < recv_len) { + AXL_DEBUG("Bytes needed: %d, Bytes read: %d\n", bytes_needed, recv_len); + } + + free(pread_buf); + pread_buf = NULL; + + return recv_len; +} + +int ax_get_file(const char *filename, uint8_t **buf) { + *buf = 0; + return 0; +} + +void ax_wdt_feed() { +} + +/* + * Utility functions + */ +void ax_fd_init(AxlTcpDataArray *vector, int capacity) { + vector->size = 0; + vector->capacity = capacity; + vector->data = (AxlTcpData*) malloc(sizeof(AxlTcpData) * vector->capacity); +} + +int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp) { + int index; + + ax_fd_double_capacity_if_full(vector); + index = vector->size++; + vector->data[index].tcp = tcp; + vector->data[index].tcp_pbuf = NULL; + vector->data[index].pbuf_offset = 0; + + return index; +} + +AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index) { + if (index >= vector->size || index < 0) { + AXL_DEBUG("Index %d out of bounds for vector of size %d\n", index, + vector->size); + return NULL; + } + return &(vector->data[index]); +} + +int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp) { + int i; + for (i = 0; i < vector->size; i++) { + if (vector->data[i].tcp == tcp) { + return i; + } + } + + return -1; +} + +void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp) { + AxlTcpData value; + while (index >= vector->size) { + ax_fd_append(vector, 0); + } + + value.tcp = tcp; + value.tcp_pbuf = NULL; + value.pbuf_offset = 0; + vector->data[index] = value; +} + +void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector) { + if (vector->size >= vector->capacity) { + vector->capacity *= 2; + vector->data = (AxlTcpData*)realloc(vector->data, sizeof(AxlTcpData) * vector->capacity); + } +} + +void ax_fd_free(AxlTcpDataArray *vector) { + free(vector->data); +} diff --git a/compat/lwipr_compat.h b/compat/lwipr_compat.h new file mode 100644 index 000000000..1a8846f94 --- /dev/null +++ b/compat/lwipr_compat.h @@ -0,0 +1,95 @@ +/* + * Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP) + * + * Created on: Jan 15, 2016 + * Author: Slavey Karadzhov + */ + +#ifndef LWIPR_COMPAT_H +#define LWIPR_COMPAT_H + +/* + * All those functions will run only if LWIP tcp raw mode is used + */ +#if LWIP_RAW==1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwipr_platform.h" +#include "ssl/ssl.h" +#include "ssl/tls1.h" + +#define ERR_AXL_INVALID_SSL -101 +#define ERR_AXL_INVALID_TCP -102 +#define ERR_AXL_INVALID_CLIENTFD -103 +#define ERR_AXL_INVALID_CLIENTFD_DATA -104 + +#define SOCKET_READ(A, B, C) ax_port_read(A, B, C) +#define SOCKET_WRITE(A, B, C) ax_port_write(A, B, C) + +/* + * Define the AXL_DEBUG function to add debug functionality + */ +#ifndef AXL_DEBUG + #define AXL_DEBUG(...) +#endif + +/** + * Define watchdog function to be called during CPU intensive operations. + */ +#ifndef WATCHDOG_FEED + #define WATCHDOG_FEED() +#endif + +typedef struct { + struct tcp_pcb *tcp; + struct pbuf *tcp_pbuf; + int pbuf_offset; +} AxlTcpData; + + +typedef struct { + int size; /* slots used so far */ + int capacity; /* total available slots */ + AxlTcpData *data; /* array of TcpData objects */ +} AxlTcpDataArray; + +/* + * High Level Functions - these are the ones that should be used directly + */ + +void axl_init(int capacity); +int axl_append(struct tcp_pcb *tcp); +int axl_free(struct tcp_pcb *tcp); + +#define axl_ssl_write(A, B, C) ssl_write(A, B, C) +int axl_ssl_read(SSL *sslObj, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p); + +/* + * Lower Level Socket Functions - used internally from axTLS + */ + +int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed); +int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed); + +/* + * Lower Level Utility functions + */ +void ax_fd_init(AxlTcpDataArray *vector, int capacity); +int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp); +AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index); +int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp); +void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp); +void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector); +void ax_fd_free(AxlTcpDataArray *vector); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW==1 */ + +#endif /* LWIPR_COMPAT_H */ diff --git a/compat/lwipr_platform.h b/compat/lwipr_platform.h new file mode 100644 index 000000000..518e8bf4e --- /dev/null +++ b/compat/lwipr_platform.h @@ -0,0 +1,27 @@ +/* + * lwipr_platform.h + * + * Created on: Feb 8, 2016 + * Author: slavey + * + */ + +#ifndef AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ +#define AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ + +/* Add here all platform specific things */ + + +// Some calls require the watchdog to be reset +#ifndef WATCHDOG_FEED + #define WATCHDOG_FEED() +#endif + + +/* SSL_DEBUG is for more information */ +#ifndef SSL_DEBUG + #define AXL_DEBUG(...) +#endif + + +#endif /* AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ */ diff --git a/crypto/aes.o b/crypto/aes.o deleted file mode 100644 index 2d10e6d61..000000000 Binary files a/crypto/aes.o and /dev/null differ diff --git a/crypto/bigint.c b/crypto/bigint.c index e9ca04cb9..3d44def09 100644 --- a/crypto/bigint.c +++ b/crypto/bigint.c @@ -1218,6 +1218,7 @@ bigint *bi_mont(BI_CTX *ctx, bigint *bixy) check(bixy); + ax_wdt_feed(); if (ctx->use_classical) /* just use classical instead */ { return bi_mod(ctx, bixy); @@ -1274,6 +1275,7 @@ bigint *bi_barrett(BI_CTX *ctx, bigint *bi) check(bi); check(bim); + ax_wdt_feed(); /* use Classical method instead - Barrett cannot help here */ if (bi->size > k*2) { diff --git a/crypto/bigint.o b/crypto/bigint.o deleted file mode 100644 index f693e65a5..000000000 Binary files a/crypto/bigint.o and /dev/null differ diff --git a/crypto/crypto_misc.c b/crypto/crypto_misc.c index 62eb6fe70..a2ea2e367 100644 --- a/crypto/crypto_misc.c +++ b/crypto/crypto_misc.c @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * * Neither the name of the axTLS project nor the names of its contributors - * may be used to endorse or promote products derived from this software + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -42,7 +42,12 @@ #include "wincrypt.h" #endif -#ifndef WIN32 +#ifdef ESP8266 +#define CONFIG_SSL_SKELETON_MODE 1 +uint32_t phy_get_rand(); +#endif + +#if defined(CONFIG_USE_DEV_URANDOM) static int rng_fd = -1; #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB) static HCRYPTPROV gCryptProv; @@ -59,20 +64,20 @@ static uint8_t entropy_pool[ENTROPY_POOL_SIZE]; const char * const unsupported_str = "Error: Feature not supported\n"; #ifndef CONFIG_SSL_SKELETON_MODE -/** +/** * Retrieve a file and put it into memory * @return The size of the file, or -1 on failure. */ int get_file(const char *filename, uint8_t **buf) { int total_bytes = 0; - int bytes_read = 0; + int bytes_read = 0; int filesize; FILE *stream = fopen(filename, "rb"); if (stream == NULL) { -#ifdef CONFIG_SSL_FULL_MODE +#ifdef CONFIG_SSL_FULL_MODE printf("file '%s' does not exist\n", filename); TTY_FLUSH(); #endif return -1; @@ -89,7 +94,7 @@ int get_file(const char *filename, uint8_t **buf) bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream); total_bytes += bytes_read; } while (total_bytes < filesize && bytes_read > 0); - + fclose(stream); return filesize; } @@ -106,25 +111,26 @@ EXP_FUNC void STDCALL RNG_initialize() #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) rng_fd = ax_open("/dev/urandom", O_RDONLY); #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB) - if (!CryptAcquireContext(&gCryptProv, + if (!CryptAcquireContext(&gCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { if (GetLastError() == NTE_BAD_KEYSET && - !CryptAcquireContext(&gCryptProv, - NULL, - NULL, - PROV_RSA_FULL, + !CryptAcquireContext(&gCryptProv, + NULL, + NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET)) { printf("CryptoLib: %x\n", unsupported_str, GetLastError()); exit(1); } } +#elif defined(ESP8266) #else /* start of with a stack to copy across */ int i; memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE); - srand((unsigned int)&i); + srand((unsigned int)&i); #endif } @@ -146,7 +152,7 @@ EXP_FUNC void STDCALL RNG_custom_init(const uint8_t *seed_buf, int size) */ EXP_FUNC void STDCALL RNG_terminate(void) { -#ifndef WIN32 +#if defined(CONFIG_USE_DEV_URANDOM) close(rng_fd); #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB) CryptReleaseContext(gCryptProv, 0); @@ -157,15 +163,22 @@ EXP_FUNC void STDCALL RNG_terminate(void) * Set a series of bytes with a random number. Individual bytes can be 0 */ EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data) -{ +{ #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) /* use the Linux default */ read(rng_fd, rand_data, num_rand_bytes); /* read from /dev/urandom */ #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB) /* use Microsoft Crypto Libraries */ CryptGenRandom(gCryptProv, num_rand_bytes, rand_data); +#elif defined(ESP8266) + for (size_t cb = 0; cb < num_rand_bytes; cb += 4) { + uint32_t r = phy_get_rand(); + size_t left = num_rand_bytes - cb; + left = (left < 4) ? left : 4; + memcpy(rand_data + cb, &r, left); + } #else /* nothing else to use, so use a custom RNG */ - /* The method we use when we've got nothing better. Use RC4, time + /* The method we use when we've got nothing better. Use RC4, time and a couple of random seeds to generate a random sequence */ RC4_CTX rng_ctx; struct timeval tv; @@ -175,10 +188,10 @@ EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data) int i; /* A proper implementation would use counters etc for entropy */ - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); ep = (uint64_t *)entropy_pool; ep[0] ^= ENTROPY_COUNTER1; - ep[1] ^= ENTROPY_COUNTER2; + ep[1] ^= ENTROPY_COUNTER2; /* use a digested version of the entropy pool as a key */ MD5_Init(&rng_digest_ctx); @@ -210,8 +223,9 @@ void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) for (i = 0; i < num_rand_bytes; i++) { - while (rand_data[i] == 0) /* can't be 0 */ - rand_data[i] = (uint8_t)(rand()); + while (rand_data[i] == 0) { + get_random(1, rand_data + i); + } } } @@ -263,7 +277,7 @@ static void print_hex(uint8_t hex) * @param data [in] The start of data to use * @param ... [in] Any additional arguments */ -EXP_FUNC void STDCALL print_blob(const char *format, +EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...) { int i; @@ -344,7 +358,7 @@ EXP_FUNC int STDCALL base64_decode(const char *in, int len, } /* check that we don't go past the output buffer */ - if (z > *outlen) + if (z > *outlen) goto error; } @@ -364,4 +378,3 @@ error: } #endif - diff --git a/crypto/hmac.o b/crypto/hmac.o deleted file mode 100644 index 69cf2c4ff..000000000 Binary files a/crypto/hmac.o and /dev/null differ diff --git a/crypto/md2.o b/crypto/md2.o deleted file mode 100644 index 46d054d9e..000000000 Binary files a/crypto/md2.o and /dev/null differ diff --git a/crypto/md5.o b/crypto/md5.o deleted file mode 100644 index 3bb00b7a4..000000000 Binary files a/crypto/md5.o and /dev/null differ diff --git a/crypto/rc4.o b/crypto/rc4.o deleted file mode 100644 index 104525cee..000000000 Binary files a/crypto/rc4.o and /dev/null differ diff --git a/crypto/rsa.c b/crypto/rsa.c index 143e66add..9d52c062f 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -146,7 +146,7 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, const int byte_size = ctx->num_octets; int i, size; bigint *decrypted_bi, *dat_bi; - uint8_t *block = (uint8_t *)alloca(byte_size); + uint8_t *block = (uint8_t *)malloc(byte_size); memset(out_data, 0, byte_size); /* initialise */ @@ -182,7 +182,7 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, /* get only the bit we want */ if (size > 0) memcpy(out_data, &block[i], size); - + free(block); return size ? size : -1; } diff --git a/crypto/rsa.o b/crypto/rsa.o deleted file mode 100644 index 320410453..000000000 Binary files a/crypto/rsa.o and /dev/null differ diff --git a/crypto/sha1.o b/crypto/sha1.o deleted file mode 100644 index ba9443f4f..000000000 Binary files a/crypto/sha1.o and /dev/null differ diff --git a/replacements/time.c b/replacements/time.c new file mode 100644 index 000000000..4972119bb --- /dev/null +++ b/replacements/time.c @@ -0,0 +1,147 @@ +/* + * time.c - ESP8266-specific functions for SNTP + * Copyright (c) 2015 Peter Dobler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library 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 Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +extern uint32_t system_get_time(void); +extern uint64_t system_mktime(uint32_t year, uint32_t mon, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec); + +static int errno_var = 0; + +int* __errno(void) { + // DEBUGV("__errno is called last error: %d (not current)\n", errno_var); + return &errno_var; +} + +unsigned long millis(void) +{ + return system_get_time() / 1000UL; +} + +unsigned long micros(void) +{ + return system_get_time(); +} + +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; +#endif + +extern char* sntp_asctime(const struct tm *t); +extern struct tm* sntp_localtime(const time_t *clock); + +// time gap in seconds from 01.01.1900 (NTP time) to 01.01.1970 (UNIX time) +#define DIFF1900TO1970 2208988800UL + +static int s_daylightOffset_sec = 0; +static long s_timezone_sec = 0; +static time_t s_bootTime = 0; + +// calculate offset used in gettimeofday +static void ensureBootTimeIsSet() +{ + if (!s_bootTime) + { + time_t now = sntp_get_current_timestamp(); + if (now) + { + s_bootTime = now - millis() / 1000; + } + } +} + +static void setServer(int id, const char* name_or_ip) +{ + if (name_or_ip) + { + //TODO: check whether server is given by name or IP + sntp_setservername(id, (char*) name_or_ip); + } +} + +void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) +{ + sntp_stop(); + + setServer(0, server1); + setServer(1, server2); + setServer(2, server3); + + s_timezone_sec = timezone; + s_daylightOffset_sec = daylightOffset_sec; + sntp_set_timezone(timezone/3600); + sntp_init(); +} + +int clock_gettime(clockid_t unused, struct timespec *tp) +{ + tp->tv_sec = millis() / 1000; + tp->tv_nsec = micros() * 1000; + return 0; +} + +// seconds since 1970 +time_t mktime(struct tm *t) +{ + // system_mktime expects month in range 1..12 + #define START_MONTH 1 + return DIFF1900TO1970 + system_mktime(t->tm_year, t->tm_mon + START_MONTH, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); +} + +time_t time(time_t * t) +{ + time_t seconds = sntp_get_current_timestamp(); + if (t) + { + *t = seconds; + } + return seconds; +} + +char* asctime(const struct tm *t) +{ + return sntp_asctime(t); +} + +struct tm* localtime(const time_t *clock) +{ + return sntp_localtime(clock); +} + +char* ctime(const time_t *t) +{ + struct tm* p_tm = localtime(t); + char* result = asctime(p_tm); + return result; +} + +int gettimeofday(struct timeval *tp, void *tzp) +{ + if (tp) + { + ensureBootTimeIsSet(); + tp->tv_sec = (s_bootTime + millis()) / 1000; + tp->tv_usec = micros() * 1000; + } + return 0; +} diff --git a/ssl/asn1.o b/ssl/asn1.o deleted file mode 100644 index 7f8f449c1..000000000 Binary files a/ssl/asn1.o and /dev/null differ diff --git a/ssl/cert.h b/ssl/cert.h deleted file mode 100644 index 30c7b6588..000000000 --- a/ssl/cert.h +++ /dev/null @@ -1,43 +0,0 @@ -unsigned char default_certificate[] = { - 0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xab, - 0x08, 0x18, 0xa7, 0x03, 0x07, 0x27, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34, - 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61, - 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, - 0x32, 0x36, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x32, - 0x34, 0x30, 0x39, 0x30, 0x33, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a, - 0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, - 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, - 0x81, 0x81, 0x00, 0xcd, 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, - 0xd4, 0x13, 0x30, 0x0e, 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, - 0x51, 0x09, 0x9d, 0x29, 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, - 0x80, 0xa1, 0x71, 0xdf, 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, - 0x90, 0x0a, 0xf9, 0xb7, 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, - 0x57, 0x41, 0x86, 0x60, 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, - 0x1b, 0xf6, 0xa2, 0x84, 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, - 0x91, 0xf8, 0x61, 0x04, 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, - 0xcc, 0x31, 0x01, 0x14, 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, - 0xd6, 0xc6, 0xc4, 0xbe, 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, - 0x7a, 0x86, 0x0e, 0x91, 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, - 0xb4, 0x94, 0x9a, 0xa8, 0x89, 0x72, 0x1d, 0x07, 0xe5, 0xb3, 0x6b, 0x88, - 0x21, 0xc2, 0x38, 0x36, 0x9e, 0x7a, 0x8c, 0x49, 0x48, 0x68, 0x0c, 0x06, - 0xe8, 0xdb, 0x1f, 0x4e, 0x05, 0xe6, 0x31, 0xe3, 0xfd, 0xe6, 0x0d, 0x6b, - 0xd8, 0x13, 0x17, 0xe0, 0x2d, 0x0d, 0xb8, 0x7e, 0xcb, 0x20, 0x6c, 0xa8, - 0x73, 0xa7, 0xfd, 0xe3, 0xa7, 0xfa, 0xf3, 0x02, 0x60, 0x78, 0x1f, 0x13, - 0x40, 0x45, 0xee, 0x75, 0xf5, 0x10, 0xfd, 0x8f, 0x68, 0x74, 0xd4, 0xac, - 0xae, 0x04, 0x09, 0x55, 0x2c, 0xdb, 0xd8, 0x07, 0x07, 0x65, 0x69, 0x27, - 0x6e, 0xbf, 0x5e, 0x61, 0x40, 0x56, 0x8b, 0xd7, 0x33, 0x3b, 0xff, 0x6e, - 0x53, 0x7e, 0x9d, 0x3f, 0xc0, 0x40, 0x3a, 0xab, 0xa0, 0x50, 0x4e, 0x80, - 0x47, 0x46, 0x0d, 0x1e, 0xdb, 0x4c, 0xf1, 0x1b, 0x5d, 0x3c, 0x2a, 0x54, - 0xa7, 0x4d, 0xfa, 0x7b, 0x72, 0x66, 0xc5 -}; -unsigned int default_certificate_len = 475; diff --git a/ssl/config.h b/ssl/config.h index 3404b5be5..c1764e5ab 100644 --- a/ssl/config.h +++ b/ssl/config.h @@ -46,9 +46,9 @@ #undef CONFIG_SSL_USE_PKCS12 #define CONFIG_SSL_EXPIRY_TIME 24 #define CONFIG_X509_MAX_CA_CERTS 150 -#define CONFIG_SSL_MAX_CERTS 3 +#define CONFIG_SSL_MAX_CERTS 1 #undef CONFIG_SSL_CTX_MUTEXING -//#define CONFIG_USE_DEV_URANDOM 1 +#undef CONFIG_USE_DEV_URANDOM #undef CONFIG_WIN32_USE_CRYPTO_LIB #undef CONFIG_OPENSSL_COMPATIBLE #undef CONFIG_PERFORMANCE_TESTING diff --git a/ssl/crypto_misc.h b/ssl/crypto_misc.h index 1fd514eeb..0201f5b5e 100644 --- a/ssl/crypto_misc.h +++ b/ssl/crypto_misc.h @@ -76,6 +76,7 @@ struct _x509_ctx uint8_t sig_type; RSA_CTX *rsa_ctx; bigint *digest; + uint8_t *fingerprint; struct _x509_ctx *next; }; diff --git a/ssl/gen_cert.c b/ssl/gen_cert.c index c2fe381eb..ef223b27b 100644 --- a/ssl/gen_cert.c +++ b/ssl/gen_cert.c @@ -214,14 +214,14 @@ static void gen_utc_time(uint8_t *buf, int *offset) static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset) { - static const uint8_t pub_key_seq[] = + static const uint8_t pub_key_seq[] = { ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */ }; int seq_offset; int pub_key_size = rsa_ctx->num_octets; - uint8_t *block = (uint8_t *)alloca(pub_key_size); + uint8_t *block = (uint8_t *)malloc(pub_key_size); int seq_size = pre_adjust_with_size( ASN1_SEQUENCE, &seq_offset, buf, offset); buf[(*offset)++] = ASN1_INTEGER; @@ -236,6 +236,7 @@ static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset) set_gen_length(pub_key_size, buf, offset); memcpy(&buf[*offset], block, pub_key_size); + free(block); *offset += pub_key_size; memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq)); *offset += sizeof(pub_key_seq); @@ -282,8 +283,8 @@ static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14 }; - uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets); - uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE); + uint8_t *enc_block = (uint8_t *)malloc(rsa_ctx->num_octets); + uint8_t *block = (uint8_t *)malloc(sizeof(asn1_sig) + SHA1_SIZE); int sig_size; /* add the digest as an embedded asn.1 sequence */ @@ -297,6 +298,8 @@ static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, set_gen_length(sig_size+1, buf, offset); buf[(*offset)++] = 0; /* bit string is multiple of 8 */ memcpy(&buf[*offset], enc_block, sig_size); + free(enc_block); + free(block); *offset += sig_size; } @@ -342,7 +345,7 @@ EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const c { int ret = X509_OK, offset = 0, seq_offset; /* allocate enough space to load a new certificate */ - uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512); + uint8_t *buf = (uint8_t *)malloc(ssl_ctx->rsa_ctx->num_octets*2 + 512); uint8_t sha_dgst[SHA1_SIZE]; int seq_size = pre_adjust_with_size(ASN1_SEQUENCE, &seq_offset, buf, &offset); @@ -357,6 +360,7 @@ EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const c memcpy(*cert_data, buf, offset); error: + free(buf); return ret < 0 ? ret : offset; } diff --git a/ssl/gen_cert.o b/ssl/gen_cert.o deleted file mode 100644 index d31834c7a..000000000 Binary files a/ssl/gen_cert.o and /dev/null differ diff --git a/ssl/loader.c b/ssl/loader.c index 333fb18e9..6c7a6308c 100644 --- a/ssl/loader.c +++ b/ssl/loader.c @@ -434,11 +434,11 @@ int load_key_certs(SSL_CTX *ssl_ctx) else if (!(options & SSL_NO_DEFAULT_KEY)) { #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) - static const /* saves a few more bytes */ -#include "private_key.h" - - ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key, - default_private_key_len, NULL); + extern const unsigned char* default_private_key; + extern const unsigned int default_private_key_len; + if (default_private_key != NULL && default_private_key_len > 0) + ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key, + default_private_key_len, NULL); #endif } @@ -462,9 +462,10 @@ int load_key_certs(SSL_CTX *ssl_ctx) else if (!(options & SSL_NO_DEFAULT_KEY)) { #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) - static const /* saves a few bytes and RAM */ -#include "cert.h" - ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, + extern const unsigned char* default_certificate; + extern const unsigned int default_certificate_len; + if (default_certificate != NULL && default_certificate_len > 0) + ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, default_certificate, default_certificate_len, NULL); #endif } diff --git a/ssl/loader.o b/ssl/loader.o deleted file mode 100644 index 17758504e..000000000 Binary files a/ssl/loader.o and /dev/null differ diff --git a/ssl/os_port.c b/ssl/os_port.c index 6a71000b4..b8a2b19a8 100644 --- a/ssl/os_port.c +++ b/ssl/os_port.c @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * * Neither the name of the axTLS project nor the names of its contributors - * may be used to endorse or promote products derived from this software + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -37,17 +37,18 @@ #include #include #include +#include #include "os_port.h" #ifdef WIN32 /** - * gettimeofday() not in Win32 + * gettimeofday() not in Win32 */ EXP_FUNC void STDCALL gettimeofday(struct timeval* t, void* timezone) -{ +{ #if defined(_WIN32_WCE) t->tv_sec = time(NULL); - t->tv_usec = 0; /* 1sec precision only */ + t->tv_usec = 0; /* 1sec precision only */ #else struct _timeb timebuffer; _ftime(&timebuffer); @@ -86,7 +87,7 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size) RegQueryValueEx(hKey, "Domain", NULL, &datatype, buf, &bufferlength); RegCloseKey(hKey); - return 0; + return 0; } #endif @@ -96,63 +97,3 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size) static const char * out_of_mem_str = "out of memory"; static const char * file_open_str = "Could not open file \"%s\""; - -/* - * Some functions that call display some error trace and then call abort(). - * This just makes life much easier on embedded systems, since we're - * suffering major trauma... - */ -EXP_FUNC void * STDCALL ax_malloc(size_t s) -{ - void *x; - - if ((x = malloc(s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s) -{ - void *x; - - if ((x = realloc(y, s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s) -{ - void *x; - - if ((x = calloc(n, s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC int STDCALL ax_open(const char *pathname, int flags) -{ - int x; - - if ((x = open(pathname, flags)) < 0) - exit_now(file_open_str, pathname); - - return x; -} - -/** - * This is a call which will deliberately exit an application, but will - * display some information before dying. - */ -void exit_now(const char *format, ...) -{ - va_list argp; - - va_start(argp, format); - vfprintf(stderr, format, argp); - va_end(argp); - abort(); -} - diff --git a/ssl/os_port.h b/ssl/os_port.h index d63a48ddc..c11ec3bd3 100644 --- a/ssl/os_port.h +++ b/ssl/os_port.h @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * * Neither the name of the axTLS project nor the names of its contributors - * may be used to endorse or promote products derived from this software + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -44,9 +44,6 @@ extern "C" { #include "os_int.h" #include - - - #ifdef WIN32 #define STDCALL __stdcall #define EXP_FUNC __declspec(dllexport) @@ -62,8 +59,29 @@ extern "C" { #if defined(ESP8266) +#include "util/time.h" +#include +// #define alloca(size) __builtin_alloca(size) +#define TTY_FLUSH() +#ifdef putc +#undef putc +#endif +#define putc(x, f) ets_putc(x) +#ifdef printf +#undef printf +#endif +#define printf(...) ets_printf(__VA_ARGS__) +#define SOCKET_READ(A,B,C) ax_port_read(A,B,C) +#define SOCKET_WRITE(A,B,C) ax_port_write(A,B,C) +#define SOCKET_CLOSE(A) ax_port_close(A) +#define get_file ax_get_file +#define EWOULDBLOCK EAGAIN +#define hmac_sha1 ax_hmac_sha1 +#define hmac_md5 ax_hmac_md5 + +void ax_wdt_feed(); #elif defined(WIN32) @@ -113,7 +131,7 @@ extern "C" { /* This fix gets around a problem where a win32 application on a cygwin xterm doesn't display regular output (until a certain buffer limit) - but it works - fine under a normal DOS window. This is a hack to get around the issue - + fine under a normal DOS window. This is a hack to get around the issue - see http://www.khngai.com/emacs/tty.php */ #define TTY_FLUSH() if (!_isatty(_fileno(stdout))) fflush(stdout); @@ -152,16 +170,27 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size); #endif /* Not Win32 */ /* some functions to mutate the way these work */ -#define malloc(A) ax_malloc(A) +#define malloc(A) ax_port_malloc(A, __FILE__, __LINE__) #ifndef realloc -#define realloc(A,B) ax_realloc(A,B) +#define realloc(A,B) ax_port_realloc(A,B, __FILE__, __LINE__) #endif -#define calloc(A,B) ax_calloc(A,B) +#define calloc(A,B) ax_port_calloc(A,B, __FILE__, __LINE__) +#define free(x) ax_port_free(x) -EXP_FUNC void * STDCALL ax_malloc(size_t s); -EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s); -EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s); -EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); +EXP_FUNC void * STDCALL ax_port_malloc(size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_realloc(void *y, size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_calloc(size_t n, size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_free(void*); +EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); + +inline uint32_t htonl(uint32_t n){ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +#define ntohl htonl #ifdef CONFIG_PLATFORM_LINUX void exit_now(const char *format, ...) __attribute((noreturn)); @@ -177,7 +206,7 @@ void exit_now(const char *format, ...); #define SSL_CTX_MUTEX_DESTROY(A) CloseHandle(A) #define SSL_CTX_LOCK(A) WaitForSingleObject(A, INFINITE) #define SSL_CTX_UNLOCK(A) ReleaseMutex(A) -#else +#else #include #define SSL_CTX_MUTEX_TYPE pthread_mutex_t #define SSL_CTX_MUTEX_INIT(A) pthread_mutex_init(&A, NULL) @@ -196,4 +225,4 @@ void exit_now(const char *format, ...); } #endif -#endif +#endif diff --git a/ssl/os_port.o b/ssl/os_port.o deleted file mode 100644 index 6c20927b3..000000000 Binary files a/ssl/os_port.o and /dev/null differ diff --git a/ssl/p12.o b/ssl/p12.o deleted file mode 100644 index 8b874f138..000000000 Binary files a/ssl/p12.o and /dev/null differ diff --git a/ssl/private_key.h b/ssl/private_key.h deleted file mode 100644 index ce7985c5a..000000000 --- a/ssl/private_key.h +++ /dev/null @@ -1,54 +0,0 @@ -unsigned char default_private_key[] = { - 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcd, - 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, 0xd4, 0x13, 0x30, 0x0e, - 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, 0x51, 0x09, 0x9d, 0x29, - 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, 0x80, 0xa1, 0x71, 0xdf, - 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, 0x90, 0x0a, 0xf9, 0xb7, - 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, 0x57, 0x41, 0x86, 0x60, - 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, 0x1b, 0xf6, 0xa2, 0x84, - 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, 0x91, 0xf8, 0x61, 0x04, - 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, 0xcc, 0x31, 0x01, 0x14, - 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, 0xd6, 0xc6, 0xc4, 0xbe, - 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, 0x7a, 0x86, 0x0e, 0x91, - 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, - 0x02, 0x81, 0x81, 0x00, 0x95, 0xaa, 0x6e, 0x11, 0xf5, 0x6a, 0x8b, 0xa2, - 0xc6, 0x48, 0xc6, 0x7c, 0x37, 0x6b, 0x1f, 0x55, 0x10, 0x76, 0x26, 0x24, - 0xc3, 0xf2, 0x5c, 0x5a, 0xdd, 0x2e, 0xf3, 0xa4, 0x1e, 0xbc, 0x7b, 0x1c, - 0x80, 0x10, 0x85, 0xbc, 0xd8, 0x45, 0x3c, 0xb8, 0xb2, 0x06, 0x53, 0xb5, - 0xd5, 0x7a, 0xe7, 0x0e, 0x92, 0xe6, 0x42, 0xc2, 0xe2, 0x2a, 0xd5, 0xd1, - 0x03, 0x9f, 0x6f, 0x53, 0x74, 0x68, 0x72, 0x8e, 0xbf, 0x03, 0xbb, 0xab, - 0xbd, 0xa1, 0xf9, 0x81, 0x7d, 0x12, 0xd4, 0x9d, 0xb6, 0xae, 0x4c, 0xad, - 0xca, 0xa8, 0xc9, 0x80, 0x8d, 0x0d, 0xd5, 0xd0, 0xa1, 0xbf, 0xec, 0x60, - 0x48, 0x49, 0xed, 0x97, 0x0f, 0x5e, 0xed, 0xfc, 0x39, 0x15, 0x96, 0x9e, - 0x5d, 0xe2, 0xb4, 0x5d, 0x2e, 0x04, 0xdc, 0x08, 0xa2, 0x65, 0x29, 0x2d, - 0x37, 0xfb, 0x62, 0x90, 0x1b, 0x7b, 0xe5, 0x3a, 0x58, 0x05, 0x55, 0xc1, - 0x02, 0x41, 0x00, 0xfc, 0x69, 0x28, 0xc9, 0xa8, 0xc4, 0x5c, 0xe3, 0xd0, - 0x5e, 0xaa, 0xda, 0xde, 0x87, 0x74, 0xdb, 0xcb, 0x40, 0x78, 0x8e, 0x1d, - 0x12, 0x96, 0x16, 0x61, 0x3f, 0xb3, 0x3e, 0xa3, 0x0d, 0xdc, 0x49, 0xa5, - 0x25, 0x87, 0xc5, 0x97, 0x85, 0x9d, 0xbb, 0xb4, 0xf0, 0x44, 0xfd, 0x6c, - 0xe8, 0xd2, 0x8c, 0xec, 0x33, 0x81, 0x46, 0x1e, 0x10, 0x12, 0x33, 0x16, - 0x95, 0x00, 0x4f, 0x75, 0xb4, 0xe5, 0x79, 0x02, 0x41, 0x00, 0xd0, 0xeb, - 0x65, 0x07, 0x10, 0x3b, 0xd9, 0x03, 0xeb, 0xdc, 0x6f, 0x4b, 0x8f, 0xc3, - 0x87, 0xce, 0x76, 0xd6, 0xc5, 0x14, 0x21, 0x4e, 0xe7, 0x4f, 0x1b, 0xe8, - 0x05, 0xf8, 0x84, 0x1a, 0xe0, 0xc5, 0xd6, 0xe3, 0x08, 0xb3, 0x54, 0x57, - 0x02, 0x1f, 0xd4, 0xd9, 0xfb, 0xff, 0x40, 0xb1, 0x56, 0x1c, 0x60, 0xf7, - 0xac, 0x91, 0xf3, 0xd3, 0xc6, 0x7f, 0x84, 0xfd, 0x84, 0x9d, 0xea, 0x26, - 0xee, 0xc9, 0x02, 0x41, 0x00, 0xa6, 0xcf, 0x1c, 0x6c, 0x81, 0x03, 0x1c, - 0x5c, 0x56, 0x05, 0x6a, 0x26, 0x70, 0xef, 0xd6, 0x13, 0xb7, 0x74, 0x28, - 0xf7, 0xca, 0x50, 0xd1, 0x2d, 0x83, 0x21, 0x64, 0xe4, 0xdd, 0x3f, 0x38, - 0xb8, 0xd6, 0xd2, 0x41, 0xb3, 0x1c, 0x9a, 0xea, 0x0d, 0xf5, 0xda, 0xdf, - 0xcd, 0x17, 0x9f, 0x9a, 0x1e, 0x15, 0xaf, 0x48, 0x1c, 0xbd, 0x9b, 0x63, - 0x5b, 0xad, 0xed, 0xd4, 0xa1, 0xae, 0xa9, 0x59, 0x09, 0x02, 0x40, 0x4e, - 0x08, 0xce, 0xa8, 0x8f, 0xc0, 0xba, 0xf3, 0x83, 0x02, 0xc8, 0x33, 0x62, - 0x14, 0x77, 0xc2, 0x7f, 0x93, 0x02, 0xf3, 0xdc, 0xe9, 0x1a, 0xee, 0xea, - 0x8e, 0x84, 0xc4, 0x69, 0x9b, 0x9c, 0x7f, 0x69, 0x1f, 0x4e, 0x1d, 0xa5, - 0x90, 0x06, 0x44, 0x1b, 0x7d, 0xfc, 0x69, 0x40, 0x21, 0xbc, 0xf7, 0x46, - 0xa4, 0xdc, 0x39, 0x7b, 0xe8, 0x8b, 0x49, 0x10, 0x44, 0x9d, 0x67, 0x5a, - 0x91, 0x86, 0x39, 0x02, 0x40, 0x41, 0x2c, 0x4e, 0xfe, 0xd9, 0x90, 0x89, - 0x00, 0x5c, 0x94, 0x0a, 0x4a, 0x7e, 0x1b, 0x1a, 0x80, 0x06, 0x01, 0x37, - 0xda, 0x50, 0x61, 0x9d, 0x9c, 0xfe, 0x25, 0x7f, 0xd8, 0xd4, 0xc4, 0x9e, - 0x81, 0xf2, 0x0c, 0x1e, 0x38, 0x21, 0x1e, 0x90, 0x3f, 0xd4, 0xba, 0x6c, - 0x53, 0xcb, 0xf0, 0x77, 0x79, 0x9b, 0xf1, 0xfa, 0x3f, 0x81, 0xdc, 0xf3, - 0x21, 0x02, 0x6d, 0xb7, 0x95, 0xc3, 0x2e, 0xce, 0xd5 -}; -unsigned int default_private_key_len = 609; diff --git a/ssl/ssl.h b/ssl/ssl.h index 198efc689..11debcb94 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -83,6 +83,7 @@ extern "C" { #define SSL_DISPLAY_CERTS 0x00200000 #define SSL_DISPLAY_RSA 0x00400000 #define SSL_CONNECT_IN_PARTS 0x00800000 +#define SSL_READ_BLOCKING 0x01000000 /* errors that can be generated */ #define SSL_OK 0 @@ -241,10 +242,11 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd); * can be null if no session resumption is being used or required. This option * is not used in skeleton mode. * @param sess_id_size The size of the session id (max 32) + * @param host_name If non-zero, host name to be sent to server for SNI support * @return An SSL object reference. Use ssl_handshake_status() to check * if a handshake succeeded. */ -EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size); +EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, const char* host_name); /** * @brief Free any used resources on this connection. @@ -371,6 +373,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code); */ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl); +/** + * @brief Check if certificate fingerprint (SHA1) matches the one given. + * + * @param ssl [in] An SSL object reference. + * @param fp [in] SHA1 fingerprint to match against + * @return SSL_OK if the certificate is verified. + */ +EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp); + /** * @brief Retrieve an X.509 distinguished name component. * diff --git a/ssl/tls1.c b/ssl/tls1.c index 428c9ea56..f8ec6b0a7 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -50,26 +50,28 @@ static const char * client_finished = "client finished"; static int do_handshake(SSL *ssl, uint8_t *buf, int read_len); static int set_key_block(SSL *ssl, int is_write); static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len); -static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt); +static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached); static int send_raw_packet(SSL *ssl, uint8_t protocol); +static void certificate_free(SSL* ssl); +static int increase_bm_data_size(SSL *ssl, size_t size); /** * The server will pick the cipher based on the order that the order that the * ciphers are listed. This order is defined at compile time. */ #ifdef CONFIG_SSL_SKELETON_MODE -const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = +const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = { SSL_RC4_128_SHA }; #else static void session_free(SSL_SESSION *ssl_sessions[], int sess_index); -const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = +const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = #ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */ -{ SSL_RC4_128_SHA, SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES128_SHA, SSL_AES256_SHA}; #elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */ -{ SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES128_SHA, SSL_AES256_SHA}; #else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */ -{ SSL_AES256_SHA, SSL_AES128_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES256_SHA, SSL_AES128_SHA}; #endif #endif /* CONFIG_SSL_SKELETON_MODE */ @@ -108,40 +110,14 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] = { /* AES256-SHA */ SSL_AES256_SHA, /* AES256-SHA */ 32, /* key size */ - 16, /* iv size */ + 16, /* iv size */ 2*(SHA1_SIZE+32+16), /* key block size */ 16, /* block padding size */ SHA1_SIZE, /* digest size */ hmac_sha1, /* hmac algorithm */ (crypt_func)AES_cbc_encrypt, /* encrypt */ (crypt_func)AES_cbc_decrypt /* decrypt */ - }, - { /* RC4-SHA */ - SSL_RC4_128_SHA, /* RC4-SHA */ - 16, /* key size */ - 0, /* iv size */ - 2*(SHA1_SIZE+16), /* key block size */ - 0, /* no padding */ - SHA1_SIZE, /* digest size */ - hmac_sha1, /* hmac algorithm */ - (crypt_func)RC4_crypt, /* encrypt */ - (crypt_func)RC4_crypt /* decrypt */ - }, - /* - * This protocol is from SSLv2 days and is unlikely to be used - but was - * useful for testing different possible digest algorithms. - */ - { /* RC4-MD5 */ - SSL_RC4_128_MD5, /* RC4-MD5 */ - 16, /* key size */ - 0, /* iv size */ - 2*(MD5_SIZE+16), /* key block size */ - 0, /* no padding */ - MD5_SIZE, /* digest size */ - hmac_md5, /* hmac algorithm */ - (crypt_func)RC4_crypt, /* encrypt */ - (crypt_func)RC4_crypt /* decrypt */ - }, + } }; #endif @@ -273,10 +249,9 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) free(ssl->encrypt_ctx); free(ssl->decrypt_ctx); disposable_free(ssl); -#ifdef CONFIG_SSL_CERT_VERIFICATION - x509_free(ssl->x509_ctx); -#endif - + certificate_free(ssl); + free(ssl->bm_all_data); + free(ssl->host_name); free(ssl); } @@ -285,21 +260,23 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) */ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) { - int ret = basic_read(ssl, in_data); + int ret = SSL_OK; + do { + ret= basic_read(ssl, in_data); - /* check for return code so we can send an alert */ - if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) - { - if (ret != SSL_ERROR_CONN_LOST) + /* check for return code so we can send an alert */ + if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) { - send_alert(ssl, ret); -#ifndef CONFIG_SSL_SKELETON_MODE - /* something nasty happened, so get rid of this session */ - kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl); -#endif + if (ret != SSL_ERROR_CONN_LOST) + { + send_alert(ssl, ret); + #ifndef CONFIG_SSL_SKELETON_MODE + /* something nasty happened, so get rid of this session */ + kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl); + #endif + } } - } - + } while (IS_SET_SSL_FLAG(SSL_READ_BLOCKING) && (ssl->got_bytes < ssl->need_bytes) && ret == 0 && !IS_SET_SSL_FLAG(SSL_NEED_RECORD)); return ret; } @@ -309,14 +286,18 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { int n = out_len, nw, i, tot = 0; - /* maximum size of a TLS packet is around 16kB, so fragment */ + + if (ssl->can_free_certificates) { + certificate_free(ssl); + } + do { nw = n; - if (nw > RT_MAX_PLAIN_LENGTH) /* fragment if necessary */ - nw = RT_MAX_PLAIN_LENGTH; + if (nw > ssl->max_plain_length) /* fragment if necessary */ + nw = ssl->max_plain_length; if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA, &out_data[tot], nw)) <= 0) @@ -564,18 +545,24 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) { SSL *ssl = (SSL *)calloc(1, sizeof(SSL)); ssl->ssl_ctx = ssl_ctx; + ssl->max_plain_length = 1460*4; + ssl->bm_all_data = (uint8_t*) calloc(1, ssl->max_plain_length + RT_EXTRA); ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */ ssl->client_fd = client_fd; ssl->flag = SSL_NEED_RECORD; - ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */ + ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; /* space at the start */ ssl->hs_status = SSL_NOT_OK; /* not connected */ #ifdef CONFIG_ENABLE_VERIFICATION ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx; + ssl->can_free_certificates = false; #endif disposable_new(ssl); /* a bit hacky but saves a few bytes of memory */ ssl->flag |= ssl_ctx->options; + if (IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS) && IS_SET_SSL_FLAG(SSL_READ_BLOCKING)) { + CLR_SSL_FLAG(SSL_READ_BLOCKING); + } SSL_CTX_LOCK(ssl_ctx->mutex); if (ssl_ctx->head == NULL) @@ -590,6 +577,11 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl_ctx->tail = ssl; } + ssl->encrypt_ctx = malloc(sizeof(AES_CTX)); + ssl->decrypt_ctx = malloc(sizeof(AES_CTX)); + + ssl->host_name = NULL; + SSL_CTX_UNLOCK(ssl_ctx->mutex); return ssl; } @@ -646,19 +638,36 @@ static void increment_write_sequence(SSL *ssl) static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, const uint8_t *buf, int buf_len, uint8_t *hmac_buf) { - int hmac_len = buf_len + 8 + SSL_RECORD_SIZE; - uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10); + const size_t prefix_size = 8 + SSL_RECORD_SIZE; + bool hmac_inplace = (uint32_t)buf - (uint32_t)ssl->bm_data >= prefix_size; + uint8_t tmp[prefix_size]; + int hmac_len = buf_len + prefix_size; + uint8_t *t_buf; + if (hmac_inplace) { + t_buf = ((uint8_t*)buf) - prefix_size; + memcpy(tmp, t_buf, prefix_size); + } else { + t_buf = (uint8_t *)malloc(hmac_len+10); + } - memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? + memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? ssl->write_sequence : ssl->read_sequence, 8); memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE); - memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len); + if (!hmac_inplace) { + memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len); + } - ssl->cipher_info->hmac(t_buf, hmac_len, - (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ? - ssl->server_mac : ssl->client_mac, + ssl->cipher_info->hmac(t_buf, hmac_len, + (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ? + ssl->server_mac : ssl->client_mac, ssl->cipher_info->digest_size, hmac_buf); + if (hmac_inplace) { + memcpy(t_buf, tmp, prefix_size); + } + else { + free(t_buf); + } #if 0 print_blob("record", hmac_header, SSL_RECORD_SIZE); print_blob("buf", buf, buf_len); @@ -899,14 +908,18 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) /** * Retrieve (and initialise) the context of a cipher. */ -static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) +static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached) { switch (ssl->cipher) { #ifndef CONFIG_SSL_SKELETON_MODE case SSL_AES128_SHA: { - AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX)); + AES_CTX *aes_ctx; + if (cached) + aes_ctx = (AES_CTX*) cached; + else + aes_ctx = (AES_CTX*) malloc(sizeof(AES_CTX)); AES_set_key(aes_ctx, key, iv, AES_MODE_128); if (is_decrypt) @@ -919,7 +932,12 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) case SSL_AES256_SHA: { - AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX)); + AES_CTX *aes_ctx; + if (cached) + aes_ctx = (AES_CTX*) cached; + else + aes_ctx = (AES_CTX*) malloc(sizeof(AES_CTX)); + AES_set_key(aes_ctx, key, iv, AES_MODE_256); if (is_decrypt) @@ -934,7 +952,12 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) #endif case SSL_RC4_128_SHA: { - RC4_CTX *rc4_ctx = (RC4_CTX *)malloc(sizeof(RC4_CTX)); + RC4_CTX* rc4_ctx; + if (cached) + rc4_ctx = (RC4_CTX*) cached; + else + rc4_ctx = (RC4_CTX*) malloc(sizeof(RC4_CTX)); + RC4_setup(rc4_ctx, key, 16); return (void *)rc4_ctx; } @@ -979,7 +1002,7 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) #endif return SSL_ERROR_CONN_LOST; } - +#ifndef ESP8266 /* keep going until the write buffer has some space */ if (sent != pkt_size) { @@ -991,6 +1014,7 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0) return SSL_ERROR_CONN_LOST; } +#endif } SET_SSL_FLAG(SSL_NEED_RECORD); /* reset for next time */ @@ -1073,11 +1097,12 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length) ssl->cipher_info->iv_size) { uint8_t iv_size = ssl->cipher_info->iv_size; - uint8_t *t_buf = alloca(msg_length + iv_size); + uint8_t *t_buf = malloc(msg_length + iv_size); memcpy(t_buf + iv_size, ssl->bm_data, msg_length); get_random(iv_size, t_buf); msg_length += iv_size; memcpy(ssl->bm_data, t_buf, msg_length); + free(t_buf); } /* now encrypt the packet */ @@ -1164,7 +1189,7 @@ static int set_key_block(SSL *ssl, int is_write) } #endif - free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx); + // free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx); /* now initialise the ciphers */ if (is_client) @@ -1172,18 +1197,18 @@ static int set_key_block(SSL *ssl, int is_write) finished_digest(ssl, server_finished, ssl->dc->final_finish_mac); if (is_write) - ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0); + ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0, ssl->encrypt_ctx); else - ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1); + ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1, ssl->decrypt_ctx); } else { finished_digest(ssl, client_finished, ssl->dc->final_finish_mac); if (is_write) - ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0); + ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0, ssl->encrypt_ctx); else - ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1); + ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1, ssl->decrypt_ctx); } ssl->cipher_info = ciph_info; @@ -1199,6 +1224,10 @@ int basic_read(SSL *ssl, uint8_t **in_data) int read_len, is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT); uint8_t *buf = ssl->bm_data; + if (ssl->can_free_certificates) { + certificate_free(ssl); + } + read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_read_index], ssl->need_bytes-ssl->got_bytes); @@ -1271,10 +1300,23 @@ int basic_read(SSL *ssl, uint8_t **in_data) /* do we violate the spec with the message size? */ if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET) { - ret = SSL_ERROR_INVALID_PROT_MSG; + printf("ssl->need_bytes=%d violates spec\r\n", ssl->need_bytes, RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET); + ret = SSL_ERROR_INVALID_PROT_MSG; goto error; } + /* is the allocated buffer large enough to handle all the data? if not, increase its size*/ + if (ssl->need_bytes > ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET) + { + printf("ssl->need_bytes=%d > %d\r\n", ssl->need_bytes, ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET); + ret = increase_bm_data_size(ssl, ssl->need_bytes + BM_RECORD_OFFSET - RT_EXTRA); + if (ret != SSL_OK) + { + ret = SSL_ERROR_INVALID_PROT_MSG; + goto error; + } + } + CLR_SSL_FLAG(SSL_NEED_RECORD); memcpy(ssl->hmac_header, buf, 3); /* store for hmac */ ssl->record_type = buf[0]; @@ -1386,6 +1428,25 @@ error: return ret; } +int increase_bm_data_size(SSL *ssl, size_t size) +{ + if (ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { + return SSL_OK; + } + size_t required = (size + 1023) & ~(1023); // round up to 1k + required = (required < RT_MAX_PLAIN_LENGTH) ? required : RT_MAX_PLAIN_LENGTH; + uint8_t* new_bm_all_data = (uint8_t*) realloc(ssl->bm_all_data, required + RT_EXTRA); + if (!new_bm_all_data) { + printf("failed to grow plain buffer\r\n"); + ssl->hs_status = SSL_ERROR_DEAD; + return SSL_ERROR_CONN_LOST; + } + ssl->bm_all_data = new_bm_all_data; + ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; + ssl->max_plain_length = required; + return SSL_OK; +} + /** * Do some basic checking of data and then perform the appropriate handshaking. */ @@ -1640,7 +1701,18 @@ void disposable_free(SSL *ssl) free(ssl->dc); ssl->dc = NULL; } + ssl->can_free_certificates = true; +} +static void certificate_free(SSL* ssl) +{ +#ifdef CONFIG_SSL_CERT_VERIFICATION + if (ssl->x509_ctx) { + x509_free(ssl->x509_ctx); + ssl->x509_ctx = 0; + } + ssl->can_free_certificates = false; +#endif } #ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */ @@ -1884,6 +1956,25 @@ error: return ret; } +EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) +{ + if (ssl->x509_ctx == NULL || ssl->x509_ctx->fingerprint == NULL) + return 1; + int res = memcmp(ssl->x509_ctx->fingerprint, fp, SHA1_SIZE); + if (res != 0) { + printf("cert FP: "); + for (int i = 0; i < SHA1_SIZE; ++i) { + printf("%02X ", ssl->x509_ctx->fingerprint[i]); + } + printf("\r\ntest FP: "); + for (int i = 0; i < SHA1_SIZE; ++i) { + printf("%02X ", fp[i]); + } + printf("\r\n"); + } + return res; +} + #endif /* CONFIG_SSL_CERT_VERIFICATION */ /** diff --git a/ssl/tls1.h b/ssl/tls1.h index 414a17343..e03eef9be 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -82,7 +82,7 @@ extern "C" { #ifdef CONFIG_SSL_SKELETON_MODE #define NUM_PROTOCOLS 1 #else -#define NUM_PROTOCOLS 4 +#define NUM_PROTOCOLS 2 #endif #define PARANOIA_CHECK(A, B) if (A < B) { \ @@ -175,10 +175,11 @@ struct _SSL const cipher_info_t *cipher_info; void *encrypt_ctx; void *decrypt_ctx; - uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA]; + uint8_t *bm_all_data; uint8_t *bm_data; uint16_t bm_index; uint16_t bm_read_index; + size_t max_plain_length; struct _SSL *next; /* doubly linked list */ struct _SSL *prev; struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */ @@ -188,14 +189,15 @@ struct _SSL #endif #ifdef CONFIG_SSL_CERT_VERIFICATION X509_CTX *x509_ctx; + bool can_free_certificates; #endif - uint8_t session_id[SSL_SESSION_ID_SIZE]; uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */ uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */ uint8_t read_sequence[8]; /* 64 bit sequence number */ uint8_t write_sequence[8]; /* 64 bit sequence number */ uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */ + char *host_name; /* Needed for the SNI support */ }; typedef struct _SSL SSL; diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 196b40ed3..c02d903eb 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -48,7 +48,7 @@ static int send_cert_verify(SSL *ssl); * Establish a new SSL connection to an SSL server. */ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const - uint8_t *session_id, uint8_t sess_id_size) + uint8_t *session_id, uint8_t sess_id_size, const char* host_name) { SSL *ssl = ssl_new(ssl_ctx, client_fd); ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */ @@ -66,6 +66,10 @@ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */ } + if(host_name != NULL && strlen(host_name) > 0) { + ssl->host_name = (char *)strdup(host_name); + } + SET_SSL_FLAG(SSL_IS_CLIENT); do_client_connect(ssl); return ssl; @@ -119,7 +123,10 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); - disposable_free(ssl); /* free up some memory */ + disposable_free(ssl); + if (ssl->ssl_ctx->options & SSL_READ_BLOCKING) { + ssl->flag |= SSL_READ_BLOCKING; + } /* note: client renegotiation is not allowed after this */ break; @@ -217,6 +224,26 @@ static int send_client_hello(SSL *ssl) buf[offset++] = 1; /* no compression */ buf[offset++] = 0; + + if (ssl->host_name != NULL) { + unsigned int host_len = strlen(ssl->host_name); + + buf[offset++] = 0; + buf[offset++] = host_len+9; /* extensions length */ + + buf[offset++] = 0; + buf[offset++] = 0; /* server_name(0) (65535) */ + buf[offset++] = 0; + buf[offset++] = host_len+5; /* server_name length */ + buf[offset++] = 0; + buf[offset++] = host_len+3; /* server_list length */ + buf[offset++] = 0; /* host_name(0) (255) */ + buf[offset++] = 0; + buf[offset++] = host_len; /* host_name length */ + strncpy((char*) &buf[offset], ssl->host_name, host_len); + offset += host_len; + } + buf[3] = offset - 4; /* handshake size */ return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset); diff --git a/ssl/x509.c b/ssl/x509.c index cb007fbbc..a291f2012 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -119,6 +119,12 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) bi_ctx = x509_ctx->rsa_ctx->bi_ctx; + x509_ctx->fingerprint = malloc(SHA1_SIZE); + SHA1_CTX sha_fp_ctx; + SHA1_Init(&sha_fp_ctx); + SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); + SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx); + #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ /* use the appropriate signature algorithm (SHA1/MD5/MD2) */ if (x509_ctx->sig_type == SIG_TYPE_MD5) @@ -245,6 +251,11 @@ void x509_free(X509_CTX *x509_ctx) bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest); } + if (x509_ctx->fingerprint) + { + free(x509_ctx->fingerprint); + } + if (x509_ctx->subject_alt_dnsnames) { for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i) @@ -270,7 +281,7 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, int i, size; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; - uint8_t *block = (uint8_t *)alloca(sig_len); + uint8_t *block = (uint8_t *)malloc(sig_len); /* decrypt */ dat_bi = bi_import(ctx, sig, sig_len); @@ -297,7 +308,7 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, bir = bi_import(ctx, sig_ptr, len); } } - + free(block); /* save a few bytes of memory */ bi_clear_cache(ctx); return bir; diff --git a/tools/make_certs.sh b/tools/make_certs.sh new file mode 100755 index 000000000..d521e9218 --- /dev/null +++ b/tools/make_certs.sh @@ -0,0 +1,186 @@ +#!/bin/sh +# +# Copyright (c) 2007, Cameron Rich +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the axTLS project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +AXDIR=`pwd`/`dirname $0` +CWD=`mktemp -d` && cd $dir +cd $CWD + +# +# Generate the certificates and keys for testing. +# + +PROJECT_NAME="axTLS Project" + +# Generate the openssl configuration files. +cat > ca_cert.conf << EOF +[ req ] +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] + O = $PROJECT_NAME Dodgy Certificate Authority +EOF + +cat > certs.conf << EOF +[ req ] +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] + O = $PROJECT_NAME + CN = 127.0.0.1 +EOF + +cat > device_cert.conf << EOF +[ req ] +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] + O = $PROJECT_NAME Device Certificate +EOF + +# private key generation +openssl genrsa -out axTLS.ca_key.pem 1024 +openssl genrsa -out axTLS.key_512.pem 512 +openssl genrsa -out axTLS.key_1024.pem 1024 +openssl genrsa -out axTLS.key_1042.pem 1042 +openssl genrsa -out axTLS.key_2048.pem 2048 +openssl genrsa -out axTLS.key_4096.pem 4096 +openssl genrsa -out axTLS.device_key.pem 1024 +openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512 +openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 512 + + +# convert private keys into DER format +openssl rsa -in axTLS.key_512.pem -out axTLS.key_512 -outform DER +openssl rsa -in axTLS.key_1024.pem -out axTLS.key_1024 -outform DER +openssl rsa -in axTLS.key_1042.pem -out axTLS.key_1042 -outform DER +openssl rsa -in axTLS.key_2048.pem -out axTLS.key_2048 -outform DER +openssl rsa -in axTLS.key_4096.pem -out axTLS.key_4096 -outform DER +openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER + +# cert requests +openssl req -out axTLS.ca_x509.req -key axTLS.ca_key.pem -new \ + -config ./ca_cert.conf +openssl req -out axTLS.x509_512.req -key axTLS.key_512.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_1024.req -key axTLS.key_1024.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_1042.req -key axTLS.key_1042.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_2048.req -key axTLS.key_2048.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_4096.req -key axTLS.key_4096.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_device.req -key axTLS.device_key.pem -new \ + -config ./device_cert.conf +openssl req -out axTLS.x509_aes128.req -key axTLS.key_aes128.pem \ + -new -config ./certs.conf -passin pass:abcd +openssl req -out axTLS.x509_aes256.req -key axTLS.key_aes256.pem \ + -new -config ./certs.conf -passin pass:abcd + +# generate the actual certs. +openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509.pem \ + -sha1 -days 5000 -signkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_512.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_1042.req -out axTLS.x509_1042.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \ + -md5 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_4096.req -out axTLS.x509_4096.pem \ + -md5 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_device.req -out axTLS.x509_device.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.x509_512.pem -CAkey axTLS.key_512.pem +openssl x509 -req -in axTLS.x509_aes128.req \ + -out axTLS.x509_aes128.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_aes256.req \ + -out axTLS.x509_aes256.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem + +# note: must be root to do this +DATE_NOW=`date` +if date -s "Jan 1 2025"; then +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_before.pem \ + -sha1 -CAcreateserial -days 365 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +date -s "$DATE_NOW" +touch axTLS.x509_bad_before.pem +fi +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_after.pem \ + -sha1 -CAcreateserial -days -365 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem + +# some cleanup +rm axTLS*.req +rm axTLS.srl +rm *.conf + +# need this for the client tests +openssl x509 -in axTLS.ca_x509.pem -outform DER -out axTLS.ca_x509.cer +openssl x509 -in axTLS.x509_512.pem -outform DER -out axTLS.x509_512.cer +openssl x509 -in axTLS.x509_1024.pem -outform DER -out axTLS.x509_1024.cer +openssl x509 -in axTLS.x509_1042.pem -outform DER -out axTLS.x509_1042.cer +openssl x509 -in axTLS.x509_2048.pem -outform DER -out axTLS.x509_2048.cer +openssl x509 -in axTLS.x509_4096.pem -outform DER -out axTLS.x509_4096.cer +openssl x509 -in axTLS.x509_device.pem -outform DER -out axTLS.x509_device.cer + +# generate pkcs8 files (use RC4-128 for encryption) +openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8 +openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8 +openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8 +openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8 + +# generate pkcs12 files (use RC4-128 for encryption) +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_with_CA" -out axTLS.withCA.p12 -password pass:abcd +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_without_CA" -out axTLS.withoutCA.p12 -password pass:abcd +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -out axTLS.noname.p12 -password pass:abcd + +# PEM certificate chain +cat axTLS.ca_x509.pem >> axTLS.x509_device.pem + +# set default key/cert for use in the server +xxd -i axTLS.x509_1024.cer | sed -e \ + "s/axTLS_x509_1024_cer/default_certificate/" > $AXDIR/../ssl/cert.h +xxd -i axTLS.key_1024 | sed -e \ + "s/axTLS_key_1024/default_private_key/" > $AXDIR/../ssl/private_key.h diff --git a/util/time.h b/util/time.h new file mode 100644 index 000000000..78e37b1d3 --- /dev/null +++ b/util/time.h @@ -0,0 +1,11 @@ +#ifndef TIME_H +#define TIME_H + +struct timeval +{ + time_t tv_sec; + long tv_usec; +}; + + +#endif //TIME_H