diff --git a/mplabx/small-psk-build/Makefile b/mplabx/small-psk-build/Makefile new file mode 100644 index 0000000000..7fac6ee904 --- /dev/null +++ b/mplabx/small-psk-build/Makefile @@ -0,0 +1,86 @@ +# Set to @ if you want to suppress command echo +CMD_ECHO = + +# Important directories +BUILD_DIR = ./Build + +# Toolchain location and prefix +TOOLCHAIN ?= + +# Tools selection +CC = $(TOOLCHAIN)gcc +AS = $(CC) +LD = $(CC) +AR = $(TOOLCHAIN)ar +NM = $(TOOLCHAIN)nm +OBJCOPY ?= $(TOOLCHAIN)objcopy +OBJDUMP ?= $(TOOLCHAIN)objdump +SIZE ?= $(TOOLCHAIN)size + +# Includes +USER_SETTINGS_DIR ?= . +INC = -I$(USER_SETTINGS_DIR) \ + -I../.. + +# Defines +DEF = -DWOLFSSL_USER_SETTINGS -DWOLFSSL_GENSEED_FORTEST +#DEF += -DUSE_LIBFUZZER +#CFLAGS = -fsanitize=fuzzer,address -g + +# LD: generate map +LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(BIN).map + +# LD: Entry point +LDFLAGS += -Wl,-ereset_handler + +# Math lib (for DH) +LIBS = -lm + +# Optimization level and place functions / data into separate sections to allow dead code removal +CFLAGS += -Os -ffunction-sections -fdata-sections -fno-builtin +# Remove unused sections and link time optimizations +LDFLAGS += -Wl,--gc-sections -flto + +# Debugging +#DBGFLAGS = -ggdb -g3 +CFLAGS += $(DBGFLAGS) +LDFLAGS += $(DBGFLAGS) + + +# FILES +SRC_C += ../../wolfcrypt/src/aes.c +SRC_C += ../../wolfcrypt/src/hmac.c +SRC_C += ../../wolfcrypt/src/random.c +SRC_C += ../../wolfcrypt/src/sha256.c +SRC_C += ../../wolfcrypt/src/misc.c +SRC_C += psk-ssl.c +SRC_C += psk-tls.c +SRC_C += example-client-psk.c + + +FILENAMES_C = $(notdir $(SRC_C)) +FILENAMES_C := $(filter-out evp.c, $(FILENAMES_C)) +OBJS_C = $(addprefix $(BUILD_DIR)/, $(FILENAMES_C:.c=.o)) +vpath %.c $(dir $(SRC_C)) + +APP = example-client-psk + +all: $(BUILD_DIR) $(BUILD_DIR)/$(APP) + @echo "" + $(CMD_ECHO) $(SIZE) $(BUILD_DIR)/$(APP) + +$(BUILD_DIR): + $(CMD_ECHO) mkdir -p $(BUILD_DIR) + +$(BUILD_DIR)/%.o: %.c + @echo "Compiling C file: $(notdir $<)" + $(CMD_ECHO) $(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $< + +$(BUILD_DIR)/$(APP): $(OBJS_C) + @echo "Linking object files:" + $(CMD_ECHO) $(CC) $(CFLAGS) $(DEF) $(INC) -o $@ $(OBJS_C) + + +clean: + rm -f $(BUILD_DIR)/*.o $(BUILD_DIR)/$(APP) + diff --git a/mplabx/small-psk-build/README.md b/mplabx/small-psk-build/README.md new file mode 100644 index 0000000000..0f945047fe --- /dev/null +++ b/mplabx/small-psk-build/README.md @@ -0,0 +1,14 @@ +NOT intended for general use! + +Crafted for a specific static PSK build using an AES-CBC 128 cipher suite with +TLS 1.2 client. When compiling with the Microchip toolchain additional source +files consumed a small amount of DATA memory. psk-tls.c and psk-ssl.c are the +combination of; src/ssl.c, src/tls.c, src/internal.c, src/keys.c, src/wolfio.c, +and wolfcrypt/src/kdf.c. The code has then been trimmed for the specific use +case and adjusted to flatten the call stack. The compiler used had a limit of +around 32 function calls deep for the call stack. The linker used also was +unable to effectivily trim out unused functions, hence a lot of the unused +functions were removed in psk-tls.c and psk-ssl.c. + +To build the example client using the gcc compiler run `make` from this +directory and then `./Build/example-client-psk`. diff --git a/mplabx/small-psk-build/example-client-psk.c b/mplabx/small-psk-build/example-client-psk.c new file mode 100644 index 0000000000..07301063ef --- /dev/null +++ b/mplabx/small-psk-build/example-client-psk.c @@ -0,0 +1,326 @@ +/* example-client-psk.c + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + **/ + +#include /* must include this to use wolfSSL security */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAXLINE 256 /* max text line length */ +#define SERV_PORT 11111 /* default port*/ +#define PSK_KEY_LEN 4 +#define DEFAULT_IP "127.0.0.1" +static int sockfd = SOCKET_INVALID; + +typedef struct cannedStruct { + int bufferLen; + byte buffer[4096]; + int bufferIdx; +} cannedStruct; + +#ifndef NO_PSK +/* + *psk client set up. + */ +static inline unsigned int My_Psk_Client_Cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)ssl; + (void)hint; + (void)key_max_len; + + /* identity is OpenSSL testing default for openssl s_client, keep same*/ + strncpy(identity, "Client_identity", id_max_len); + + /* test key n hex is 0x1a2b3c4d , in decimal 439,041,101, we're using + * unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return PSK_KEY_LEN; +} +#endif + +int my_IORecv(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + int recvd; + + if (ctx != NULL) { + cannedStruct *cannedData = (cannedStruct*)ctx; + recvd = sz; + if (recvd > (cannedData->bufferLen - cannedData->bufferIdx)) { + recvd = cannedData->bufferLen - cannedData->bufferIdx; + } + memcpy(buff, cannedData->buffer + cannedData->bufferIdx, recvd); + cannedData->bufferIdx += recvd; + if (recvd == 0) { + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + } + else { + /* Receive message from socket */ + if ((recvd = recv(sockfd, buff, sz, 0)) == -1) { + /* error encountered. Be responsible and report it in wolfSSL terms */ + + fprintf(stderr, "IO RECEIVE ERROR: "); + switch (errno) { + #if EAGAIN != EWOULDBLOCK + case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems, but not others */ + #endif + case EWOULDBLOCK: + fprintf(stderr, "would block\n"); + return WOLFSSL_CBIO_ERR_WANT_READ; + case ECONNRESET: + fprintf(stderr, "connection reset\n"); + return WOLFSSL_CBIO_ERR_CONN_RST; + case EINTR: + fprintf(stderr, "socket interrupted\n"); + return WOLFSSL_CBIO_ERR_ISR; + case ECONNREFUSED: + fprintf(stderr, "connection refused\n"); + return WOLFSSL_CBIO_ERR_WANT_READ; + case ECONNABORTED: + fprintf(stderr, "connection aborted\n"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + default: + fprintf(stderr, "general error\n"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (recvd == 0) { + printf("Connection closed\n"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + +#if 0 + { + FILE* f; + char fname[200]; + + sprintf(fname, "%d-recv.out", getpid()); + f=fopen(fname, "ab"); + fwrite(buff, 1, recvd, f); + fclose(f); + } +#endif + } + /* successful receive */ +#ifndef USE_LIBFUZZER + printf("my_IORecv: received %d bytes\n", sz); +#endif + return recvd; +} + + +int my_IOSend(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + /* By default, ctx will be a pointer to the file descriptor to write to. + * This can be changed by calling wolfSSL_SetIOWriteCtx(). */ + int sent; + + if (ctx != NULL) { + /* drop sent data */ + sent = sz; + } + else { + /* Receive message from socket */ + if ((sent = send(sockfd, buff, sz, 0)) == -1) { + fprintf(stderr, "IO SEND ERROR: "); + switch (errno) { + #if EAGAIN != EWOULDBLOCK + case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems */ + #endif + case EWOULDBLOCK: + fprintf(stderr, "would block\n"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + case ECONNRESET: + fprintf(stderr, "connection reset\n"); + return WOLFSSL_CBIO_ERR_CONN_RST; + case EINTR: + fprintf(stderr, "socket interrupted\n"); + return WOLFSSL_CBIO_ERR_ISR; + case EPIPE: + fprintf(stderr, "socket EPIPE\n"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + default: + fprintf(stderr, "general error\n"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (sent == 0) { + printf("Connection closed\n"); + return 0; + } + } + + /* successful send */ +#ifndef USE_LIBFUZZER + printf("my_IOSend: sent %d bytes\n", sz); +#endif + return sent; +} + +#define CIPHER_BYTE 0x00 +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE + +#define SUITE0 CIPHER_BYTE +#define SUITE1 TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RANDOM_SIZE 48 +#ifndef USE_LIBFUZZER +int main(int argc, char **argv) +#else +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) +#endif +{ + int ret, read = 0; + char recvline[MAXLINE]="Hello Server"; /* string to send to the server */ + struct sockaddr_in servaddr;; + byte ran[TLS_RANDOM_SIZE]; + byte *ptr; + WOLFSSL_METHOD* meth = NULL; + WOLFSSL* ssl = NULL; + cannedStruct cannedData; + + cannedData.bufferLen = 0; +#ifndef USE_LIBFUZZER + if (argc == 2) { + FILE* f = fopen(argv[1], "rb"); + + if (f == NULL) { + printf("Unable to open file %s\n", argv[1]); + return 1; + } + else { + cannedData.bufferLen = fread(cannedData.buffer, 1, 4096, f); + cannedData.bufferIdx = 0; + fclose(f); + } + } + else { + /* create a stream socket using tcp,internet protocal IPv4, + * full-duplex stream */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + /* places n zero-valued bytes in the address servaddr */ + memset(&servaddr, 0, sizeof(servaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + + /* converts IPv4 addresses from text to binary form */ + ret = inet_pton(AF_INET, DEFAULT_IP, &servaddr.sin_addr); + if (ret != 1) { + printf("inet_pton error\n"); + ret = -1; + goto exit; + } + + /* attempts to make a connection on a socket */ + ret = connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); + if (ret != 0) { + printf("Connection Error\n"); + ret = -1; + goto exit; + } + } +#else + cannedData.bufferLen = sz; + memcpy(cannedData.buffer, data, cannedData.bufferLen); + cannedData.bufferIdx = 0; +#endif + wolfSSL_Init(); /* initialize wolfSSL */ + + meth = wolfTLSv1_2_client_method(); + + /* creat wolfssl object after each tcp connect */ + memset(ran, 0, sizeof(ran)); + if ( (ssl = wolfSSL_new_leanpsk(meth, SUITE0, SUITE1, ran, + TLS_RANDOM_SIZE)) == NULL) { + fprintf(stderr, "wolfSSL_new_leanpsk error.\n"); + ret = -1; + goto exit; + } + wolfSSL_set_psk_client_callback(ssl, My_Psk_Client_Cb); + wolfSSL_SSLSetIORecv(ssl, my_IORecv); + wolfSSL_SSLSetIOSend(ssl, my_IOSend); + + if (cannedData.bufferLen > 0) { + wolfSSL_SetIOWriteCtx(ssl, (void*)&cannedData); + wolfSSL_SetIOReadCtx(ssl, (void*)&cannedData); + } + + ret = wolfSSL_connect(ssl); +#ifndef USE_LIBFUZZER + printf("ret of connect = %d\n", ret); +#endif + if (ret < 0) { + goto exit; + } + + /* write string to the server */ + if (wolfSSL_write_inline(ssl, recvline, strlen(recvline), MAXLINE) < 0) { + #ifndef USE_LIBFUZZER + printf("Write Error to Server\n"); + #endif + ret = -1; + goto exit; + } + + /* check if server ended before client could read a response */ + if ((read = wolfSSL_read_inline(ssl, recvline, MAXLINE, (void**)&ptr, + MAXLINE)) < 0 ) { + #ifndef USE_LIBFUZZER + printf("Client: Server Terminated Prematurely!\n"); + #endif + ret = -1; + goto exit; + } + + if (read > 0) { + /* show message from the server */ + ptr[read] = '\0'; + #ifndef USE_LIBFUZZER + printf("Server Message: %s\n", ptr); + #endif + } + + ret = 0; + +exit: + /* Cleanup and return */ + if (ssl) + wolfSSL_free(ssl); /* Free the wolfSSL object */ + if (sockfd != SOCKET_INVALID) + close(sockfd); /* Close the socket */ + if (meth) + free(meth); + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ + + return ret; /* Return reporting a success */ +} diff --git a/mplabx/small-psk-build/psk-ssl.c b/mplabx/small-psk-build/psk-ssl.c new file mode 100644 index 0000000000..5d5ea9d877 --- /dev/null +++ b/mplabx/small-psk-build/psk-ssl.c @@ -0,0 +1,7075 @@ +/* psk-ssl.c + * + * Copyright (C) 2006-2024 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 + */ + +/* combining all TLS 1.2 components needed for a bare static psk connection */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* + * WOLFSSL_SMALL_CERT_VERIFY: + * Verify the certificate signature without using DecodedCert. Doubles up + * on some code but allows smaller peak heap memory usage. + * Cannot be used with WOLFSSL_NONBLOCK_OCSP. + * WOLFSSL_ALT_CERT_CHAINS: + * Allows CA's to be presented by peer, but not part of a valid chain. + * Default wolfSSL behavior is to require validation of all presented peer + * certificates. This also allows loading intermediate CA's as trusted + * and ignoring no signer failures for CA's up the chain to root. + * WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT: + * Enable resending the previous DTLS handshake flight only on a network + * read timeout. By default we resend in two more cases, when we receive: + * - an out of order last msg of the peer's flight + * - a duplicate of the first msg from the peer's flight + * WOLFSSL_NO_DEF_TICKET_ENC_CB: + * No default ticket encryption callback. + * Server only. + * Application must set its own callback to use session tickets. + * WOLFSSL_TICKET_ENC_CHACHA20_POLY1305 + * Use ChaCha20-Poly1305 to encrypt/decrypt session tickets in default + * callback. Default algorithm if none defined and algorithms compiled in. + * Server only. + * WOLFSSL_TICKET_ENC_AES128_GCM + * Use AES128-GCM to encrypt/decrypt session tickets in default callback. + * Server only. Default algorithm if ChaCha20/Poly1305 not compiled in. + * WOLFSSL_TICKET_ENC_AES256_GCM + * Use AES256-GCM to encrypt/decrypt session tickets in default callback. + * Server only. + * WOLFSSL_TICKET_DECRYPT_NO_CREATE + * Default callback will not request creation of new ticket on successful + * decryption. + * Server only. + * WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE + * Once a normal TLS 1.3 handshake is complete, a session ticket message + * may be received by a client. To support detecting this, peek will + * return WOLFSSL_ERROR_WANT_READ. + * This define turns off this behaviour. + * WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY + * Verify hostname/ip address using alternate name (SAN) only and do not + * use the common name. Forces use of the alternate name, so certificates + * missing SAN will be rejected during the handshake + * WOLFSSL_CHECK_SIG_FAULTS + * Verifies the ECC signature after signing in case of faults in the + * calculation of the signature. Useful when signature fault injection is a + * possible attack. + * WOLFSSL_TLS13_IGNORE_AEAD_LIMITS + * Ignore the AEAD limits for messages specified in the RFC. After + * reaching the limit, we initiate a key update. We enforce the AEAD limits + * by default. + * https://www.rfc-editor.org/rfc/rfc8446#section-5.5 + * https://www.rfc-editor.org/rfc/rfc9147.html#name-aead-limits + * WOLFSSL_HARDEN_TLS + * Implement the recommendations specified in RFC9325. This macro needs to + * be defined to the desired number of bits of security. The currently + * implemented values are 112 and 128 bits. The following macros disable + * certain checks. + * - WOLFSSL_HARDEN_TLS_ALLOW_TRUNCATED_HMAC + * - WOLFSSL_HARDEN_TLS_ALLOW_OLD_TLS + * - WOLFSSL_HARDEN_TLS_NO_SCR_CHECK + * - WOLFSSL_HARDEN_TLS_NO_PKEY_CHECK + * - WOLFSSL_HARDEN_TLS_ALLOW_ALL_CIPHERSUITES + * WOLFSSL_NO_INIT_CTX_KEY + * Allows SSL objects to be created from a CTX without a loaded key/cert + * pair + */ + + +#ifdef EXTERNAL_OPTS_OPENVPN +#error EXTERNAL_OPTS_OPENVPN should not be defined\ + when building wolfSSL +#endif + +#ifndef WOLFCRYPT_ONLY + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA) + #include +#endif + +#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #ifndef NO_STDIO_FILESYSTEM + #ifdef FUSION_RTOS + #include + #else + #include + #endif + #endif +#endif + +#ifdef __sun + #include +#endif + + +#define ERROR_OUT(err, eLabel) { ret = (int)(err); goto eLabel; } + +#ifdef _MSC_VER + /* disable for while(0) cases at the .c level for now */ + #pragma warning(disable:4127) +#endif + +int LeanPSKMakeMasterSecret(WOLFSSL* ssl, byte* key_label); + +#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS) + #error \ +WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS +#endif + +#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION) + #error Cannot use both secure-renegotiation and renegotiation-indication +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef NO_WOLFSSL_CLIENT + static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size); +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + +enum processReply { + doProcessInit = 0, +#ifndef NO_WOLFSSL_SERVER + runProcessOldClientHello, +#endif + getRecordLayerHeader, + getData, + verifyEncryptedMessage, + decryptMessage, + verifyMessage, + runProcessingOneRecord, + runProcessingOneMessage +}; + + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) + +#ifdef WOLFSSL_TLS13 +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) +#endif +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + +int IsTLS(const WOLFSSL* ssl) +{ + if (ssl->version.major == (byte)SSLv3_MAJOR && + ssl->version.minor >= (byte)TLSv1_MINOR) + return 1; +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) + return 1; +#endif + + return 0; +} + +int IsTLS_ex(const ProtocolVersion pv) +{ + if (pv.major == (byte)SSLv3_MAJOR && + pv.minor >= (byte)TLSv1_MINOR) + return 1; + + return 0; +} + + +int IsAtLeastTLSv1_2(const WOLFSSL* ssl) +{ + if (ssl->version.major == (byte)SSLv3_MAJOR && + ssl->version.minor >= (byte)TLSv1_2_MINOR) + return 1; + + return 0; +} + +int IsAtLeastTLSv1_3(ProtocolVersion pv) +{ + int ret; + ret = (int)((pv.major == (byte)SSLv3_MAJOR && + pv.minor >= (byte)TLSv1_3_MINOR)); + + return ret; +} + +#ifdef WOLFSSL_LEANPSK +#define IsEncryptionOn(ssl, isSend) \ + (ssl)->keys->encryptionOn && ((isSend) ? \ + (ssl)->encryptSetup : (ssl)->decryptSetup) +#else +int IsEncryptionOn(const WOLFSSL* ssl, int isSend) +{ + return ssl->keys->encryptionOn && + (isSend ? ssl->encrypt.setup : ssl->decrypt.setup); +} +#endif + +void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) +{ + method->version = pv; + method->side = WOLFSSL_CLIENT_END; + method->downgrade = 0; +} + + +void InitCipherSpecs(CipherSpecs* cs) +{ + XMEMSET(cs, 0, sizeof(CipherSpecs)); + + cs->bulk_cipher_algorithm = INVALID_BYTE; + cs->cipher_type = INVALID_BYTE; + cs->mac_algorithm = INVALID_BYTE; + cs->kea = INVALID_BYTE; + cs->sig_algo = INVALID_BYTE; +} + + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +static word32 MacSize(const WOLFSSL* ssl) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + + return digestSz; +} +#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + + +int InitSSL_Suites(WOLFSSL* ssl) +{ + if (!ssl) + return BAD_FUNC_ARG; + + ssl->options.cipherSuite0 = CIPHER_BYTE; + ssl->options.cipherSuite = TLS_PSK_WITH_AES_128_CBC_SHA256; + + return WOLFSSL_SUCCESS; +} + + +int InitHandshakeHashes(WOLFSSL* ssl) +{ + int ret; + + /* make sure existing handshake hashes are free'd */ + if (ssl->hsHashes != NULL) { + FreeHandshakeHashes(ssl); + } + + /* allocate handshake hashes */ + ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, + DYNAMIC_TYPE_HASHES); + if (ssl->hsHashes == NULL) { + WOLFSSL_MSG("HS_Hashes Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes)); +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, + INVALID_DEVID); + if (ret != 0) + return ret; + #ifdef WOLFSSL_HASH_FLAGS + wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY); + #endif +#endif + return ret; +} + +void FreeHandshakeHashes(WOLFSSL* ssl) +{ + if (ssl->hsHashes) { + #ifndef NO_SHA256 + wc_Sha256Free(&ssl->hsHashes->hashSha256); + #endif + #if (defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + (defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3))) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->hsHashes->messages != NULL) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + #endif + + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + } +} + +/* called if user attempts to reuse WOLFSSL object for a new session. + * For example wolfSSL_clear() is called then wolfSSL_connect or accept */ +int ReinitSSL_leanpsk(WOLFSSL* ssl) +{ + int ret = 0; + + WOLFSSL_ENTER("ReinitSSL"); + + /* arrays */ + if (ssl->arrays == NULL) { + ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("SSL Arrays", ssl->arrays, sizeof(*ssl->arrays)); +#endif + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + } + + ssl->options.shutdownDone = 0; +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (ssl->session != NULL) + ssl->session->side = (byte)ssl->options.side; +#endif + + return ret; +} + +/* init everything to 0, NULL, default values before calling anything that may + fail so that destructor has a "good" state to cleanup + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + + 0 on success */ +int InitSSL_leanpsk(WOLFSSL* ssl, WOLFSSL_METHOD* method, byte ciphersuite0, + byte ciphersuite1, void* heap) +{ + int ret; + + XMEMSET(ssl, 0, sizeof(WOLFSSL)); + +#if defined(WOLFSSL_STATIC_MEMORY) + ssl->heap = heap; +#endif + + ssl->keys = (Keys*)XMALLOC(sizeof(Keys), heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->keys == NULL) + return MEMORY_E; + + ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; + ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; + + ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; + ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; + + /* initialize states */ + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.processReply = doProcessInit; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + +#ifdef HAVE_EXTENDED_MASTER + ssl->options.haveEMS = ctx->haveEMS; +#endif + ssl->options.useClientOrder = 0; + ssl->options.mutualAuth = 0; + + /* default alert state (none) */ + ssl->alert_history.last_rx.code = -1; + ssl->alert_history.last_rx.level = -1; + ssl->alert_history.last_tx.code = -1; + ssl->alert_history.last_tx.level = -1; + + ssl->encryptSetup = 0; + ssl->decryptSetup = 0; + InitCipherSpecs(&ssl->specs); + + /* all done with init, now can return errors, call other stuff */ + if ((ret = ReinitSSL_leanpsk(ssl)) != 0) { + WOLFSSL_MSG_EX("ReinitSSL failed. err = %d", ret); + return ret; + } + + if (method->side != (byte)WOLFSSL_NEITHER_END) + ssl->options.side = method->side; +#ifndef WOLFSSL_NO_DOWNGRADE + ssl->options.downgrade = method->downgrade; +#endif + ssl->version = method->version; + + if (ret == 0) { + /* Defer initializing suites until accept or connect */ + ret = InitSSL_Suites(ssl); + ssl->options.cipherSuite0 = CIPHER_BYTE; + ssl->options.cipherSuite = TLS_PSK_WITH_AES_128_CBC_SHA256; + } + + /* hsHashes */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) { + WOLFSSL_MSG_EX("InitHandshakeHashes failed. err = %d", ret); + return ret; + } + +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + ssl->session = wolfSSL_NewSession(ssl->heap); + if (ssl->session == NULL) { + WOLFSSL_MSG_EX("SSL Session Memory error. wolfSSL_NewSession " + "err = %d", ret); + return MEMORY_E; + } +#endif + + /* Returns 0 on success, not WOLFSSL_SUCCESS (1) */ + WOLFSSL_MSG_EX("InitSSL done. return 0 (success)"); + return 0; +} + + +/* free use of temporary arrays */ +void FreeArrays(WOLFSSL* ssl, int keep) +{ + if (ssl->arrays) { +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (keep && !IsAtLeastTLSv1_3(ssl->version)) { + /* keeps session id for user retrieval */ + XMEMCPY(ssl->session->sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session->sessionIDSz = ssl->arrays->sessionIDSz; + } +#endif + if (ssl->arrays->preMasterSecret) { +#ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN); +#endif + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = NULL; + } + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; +#ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ +#endif + } + XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays = NULL; +} + +void FreeKeyExchange(WOLFSSL* ssl) +{ + /* Cleanup signature buffer */ + if (ssl->buffers.sig.buffer) { + XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + ssl->buffers.sig.buffer = NULL; + ssl->buffers.sig.length = 0; + } + + /* Cleanup digest buffer */ + if (ssl->buffers.digest.buffer) { + /* Only free if digest buffer was not set using SetDigest */ + if (!ssl->options.dontFreeDigest) { + XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST); + } + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + ssl->options.dontFreeDigest = 0; + } + +#ifndef NO_DH + /* Free temp DH key */ + FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); +#endif +} + + +/* In case holding SSL object in array and don't want to free actual ssl */ +void SSL_ResourceFree(WOLFSSL* ssl) +{ + /* Note: any resources used during the handshake should be released in the + * function FreeHandshakeResources(). Be careful with the special cases + * like the RNG which may optionally be kept for the whole session. (For + * example with the RNG, it isn't used beyond the handshake except when + * using stream ciphers where it is retained. */ + + if (ssl->options.side == (byte)WOLFSSL_SERVER_END) { + WOLFSSL_MSG("Free'ing server ssl"); + } + else { + WOLFSSL_MSG("Free'ing client ssl"); + } + + FreeArrays(ssl, 0); + FreeKeyExchange(ssl); +#ifdef WOLFSSL_ASYNC_IO + /* Cleanup async */ + FreeAsyncCtx(ssl, 1); +#endif + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + ssl->options.weOwnRng = 0; + } + FreeHandshakeHashes(ssl); + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + +#ifndef WOLFSSL_NO_FORCE_ZERO + /* clear keys struct after session */ + ForceZero(ssl->keys, sizeof(Keys)); +#endif + if (ssl->keys != NULL) { + XFREE(ssl->keys, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#ifdef WOLFSSL_TLS13 + ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret)); + ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret)); + +#if defined(HAVE_ECH) + if (ssl->options.useEch == 1) { + FreeEchConfigs(ssl->echConfigs, ssl->heap); + ssl->echConfigs = NULL; + /* free the ech specific hashes */ + ssl->hsHashes = ssl->hsHashesEch; + FreeHandshakeHashes(ssl); + ssl->options.useEch = 0; + } +#endif /* HAVE_ECH */ +#endif /* WOLFSSL_TLS13 */ +#ifdef WOLFSSL_HAVE_TLS_UNIQUE + ForceZero(&ssl->clientFinished, TLS_FINISHED_SZ_MAX); + ForceZero(&ssl->serverFinished, TLS_FINISHED_SZ_MAX); + ssl->serverFinished_len = 0; + ssl->clientFinished_len = 0; +#endif +#ifndef NO_DH + #error expecting NO_DH defined +#endif /* !NO_DH */ +#ifndef NO_CERTS + ssl->keepCert = 0; /* make sure certificate is free'd */ + wolfSSL_UnloadCertsKeys(ssl); +#endif +#ifndef NO_RSA + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; +#endif +#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS) + XFREE(ssl->peerSceTsipEncRsaKeyIndex, ssl->heap, DYNAMIC_TYPE_RSA); + Renesas_cmn_Cleanup(ssl); +#endif + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, FORCED_FREE); + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + if (ssl->buffers.tls13CookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + } + XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); +#endif +#ifdef HAVE_TLS_EXTENSIONS +#if !defined(NO_TLS) + TLSX_FreeAll(ssl->extensions, ssl->heap); +#endif /* !NO_TLS */ +#endif /* HAVE_TLS_EXTENSIONS */ +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (ssl->session != NULL) + wolfSSL_FreeSession(ssl->ctx, ssl->session); +#endif +#ifdef WOLFSSL_STATIC_MEMORY + /* check if using fixed io buffers and free them */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #endif + void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN + WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; + WOLFSSL_HEAP* ctx_heap; + + ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED + if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + #endif + ctx_heap->curIO--; + if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + + /* check if handshake count has been decreased*/ + if (ssl_hint->haFlag && ctx_heap->curHa > 0) { + ctx_heap->curHa--; + } + #ifndef SINGLE_THREADED + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif + + /* check if tracking stats */ + if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { + XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); + } + #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ + XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ +} + +/* Free any handshake resources no longer needed */ +void FreeHandshakeResources(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("FreeHandshakeResources"); + + /* input buffer */ + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + + /* hsHashes */ + FreeHandshakeHashes(ssl); + + /* RNG */ + if (ssl->options.tls1_1 == 0u +#ifndef WOLFSSL_AEAD_ONLY + || ssl->specs.cipher_type == (byte)stream +#endif + ) { + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + ssl->options.weOwnRng = 0; + } + } + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \ + defined(HAVE_SESSION_TICKET) + if (!ssl->options.tls1_3) +#endif + /* arrays */ + if (ssl->options.saveArrays == 0u) + FreeArrays(ssl, 1); + +#ifdef WOLFSSL_STATIC_MEMORY + /* when done with handshake decrement current handshake count */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #endif + WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; + WOLFSSL_HEAP* ctx_heap; + + ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED + if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN + if (ctx_heap->curHa > 0) { + ctx_heap->curHa--; + } + ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */ + #endif + #ifndef SINGLE_THREADED + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ +} + + +/* heap argument is the heap hint used when creating SSL */ +void FreeSSL(WOLFSSL* ssl, void* heap) +{ + SSL_ResourceFree(ssl); + XFREE(ssl, heap, DYNAMIC_TYPE_SSL); + (void)heap; +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(ssl, sizeof(*ssl)); +#endif +} + +#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \ + !defined(WOLFSSL_NO_TLS12) || \ + ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM) || \ + defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) \ + && defined(HAVE_AEAD)) + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) +{ + if (verify) { + seq[0] = ssl->keys->peer_sequence_number_hi; + seq[1] = ssl->keys->peer_sequence_number_lo++; + if (seq[1] > ssl->keys->peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys->peer_sequence_number_hi++; + } + } + else { + seq[0] = ssl->keys->sequence_number_hi; + seq[1] = ssl->keys->sequence_number_lo++; + if (seq[1] > ssl->keys->sequence_number_lo) { + /* handle rollover */ + ssl->keys->sequence_number_hi++; + } + } +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ + + + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) +#endif + { + GetSEQIncrement(ssl, verifyOrder, seq); + } +#ifdef WOLFSSL_DTLS + else { + DtlsGetSEQ(ssl, verifyOrder, seq); + } +#endif + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ +#endif /* !NO_OLD_TLS || WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || + * ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM || WOLFSSL_SM4_GCM || + * WOLFSSL_SM4_CCM) && HAVE_AEAD) */ + +/* add record layer header for message */ +static void AddRecordHeader(byte* output, word32 length, byte type, + WOLFSSL* ssl, int epochOrder) +{ + RecordLayerHeader* rl; + + (void)epochOrder; + + /* record layer header */ + rl = (RecordLayerHeader*)output; + if (rl == NULL) { + return; + } + rl->type = type; + rl->pvMajor = ssl->version.major; /* type and version same in each */ + rl->pvMinor = ssl->version.minor; + +#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE + if (ssl->options.side == WOLFSSL_CLIENT_END + && ssl->options.connectState == CONNECT_BEGIN + && !ssl->options.resuming) { + rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade + : ssl->version.minor; + } +#endif + + c16toa((word16)length, rl->length); +} + + +#if !defined(WOLFSSL_NO_TLS12) || (defined(HAVE_SESSION_TICKET) && \ + !defined(NO_WOLFSSL_SERVER)) +/* add handshake header for message */ +static void AddHandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + if (hs == NULL) + return; + + hs->type = type; + c32to24(length, hs->length); /* type and length same for each */ +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsHandShakeHeader* dtls; + + /* dtls handshake header extensions */ + dtls = (DtlsHandShakeHeader*)output; + c16toa(ssl->keys->dtls_handshake_number++, dtls->message_seq); + c32to24(fragOffset, dtls->fragment_offset); + c32to24(fragLength, dtls->fragment_length); + } +#endif +} + +/* add both headers for handshake message */ +static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; + } +#endif + + AddRecordHeader(output, length + lengthAdj, handshake, ssl, CUR_ORDER); + AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} +#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */ + + +/* return bytes received, -1 on error */ +static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int recvd; + int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS; + +#ifdef WOLFSSL_QUIC + if (WOLFSSL_IS_QUIC(ssl)) { + /* QUIC only "reads" from data provided by the application + * via wolfSSL_provide_quic_data(). Transfer from there + * into the inputBuffer. */ + return wolfSSL_quic_receive(ssl, buf, sz); + } +#endif + + if (ssl->CBIORecv == NULL) { + WOLFSSL_MSG("Your IO Recv callback is null, please set"); + return -1; + } + +retry: + recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, + #ifndef WOLFSSL_LEANPSK_STATIC_IO + ssl->IOCB_ReadCtx + #else + NULL + #endif + ); + if (recvd < 0) { + switch (recvd) { + case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */ + #ifdef WOLFSSL_APACHE_HTTPD + #ifndef NO_BIO + if (ssl->biord) { + /* If retry and read flags are set, return WANT_READ */ + if ((ssl->biord->flags & WOLFSSL_BIO_FLAG_READ) && + (ssl->biord->flags & WOLFSSL_BIO_FLAG_RETRY)) { + return WANT_READ; + } + } + #endif + #endif + return -1; + + case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ + #ifndef WOLFSSL_LEANPSK + if (retryLimit > 0 && ssl->ctx->autoRetry && + !ssl->options.handShakeDone && !ssl->options.dtls) { + retryLimit--; + goto retry; + } + #endif + return WANT_READ; + + case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ + ssl->options.connReset = 1; + return -1; + + case WOLFSSL_CBIO_ERR_ISR: /* interrupt */ + /* see if we got our timeout */ + #ifdef WOLFSSL_CALLBACKS + if (ssl->toInfoOn) { + struct itimerval timeout; + getitimer(ITIMER_REAL, &timeout); + if (timeout.it_value.tv_sec == 0 && + timeout.it_value.tv_usec == 0) { + XSTRNCPY(ssl->timeoutInfo.timeoutName, + "recv() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + + WOLFSSL_MSG("Got our timeout"); + return WANT_READ; + } + } + #endif + goto retry; + + case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* peer closed connection */ + ssl->options.isClosed = 1; + return -1; + + case WOLFSSL_CBIO_ERR_TIMEOUT: + #ifdef WOLFSSL_DTLS +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { + /* TODO: support WANT_WRITE here */ + if (Dtls13RtxTimeout(ssl) < 0) { + WOLFSSL_MSG( + "Error trying to retransmit DTLS buffered message"); + return -1; + } + goto retry; + } +#endif /* WOLFSSL_DTLS13 */ + + if (IsDtlsNotSctpMode(ssl) && + ssl->options.handShakeState != HANDSHAKE_DONE && + DtlsMsgPoolTimeout(ssl) == 0 && + DtlsMsgPoolSend(ssl, 0) == 0) { + + /* retry read for DTLS during handshake only */ + goto retry; + } + #endif + return -1; + + default: + WOLFSSL_MSG("Unexpected recv return code"); + return recvd; + } + } + + return recvd; +} + + +/* Switch dynamic output buffer back to static, buffer is assumed clear */ +void ShrinkOutputBuffer(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Shrinking output buffer"); + if (ssl->buffers.outputBuffer.dynamicFlag != + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + XFREE(ssl->buffers.outputBuffer.buffer - + ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + } + ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; + ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; + ssl->buffers.outputBuffer.dynamicFlag = 0; + ssl->buffers.outputBuffer.offset = 0; + /* idx and length are assumed to be 0. */ +} + + +/* Switch dynamic input buffer back to static, keep any remaining input */ +/* forced free means cleaning up */ +/* Be *CAREFUL* where this function is called. ProcessReply relies on + * inputBuffer.idx *NOT* changing inside the ProcessReply function. ProcessReply + * calls ShrinkInputBuffer itself when it is safe to do so. Don't overuse it. */ +void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) +{ + int usedLength = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx; + if (!forcedFree && (usedLength > STATIC_BUFFER_LEN || + ssl->buffers.clearOutputBuffer.length > 0u)) + return; + + WOLFSSL_MSG("Shrinking input buffer"); + + if (!forcedFree && usedLength > 0) { + XMEMCPY(ssl->buffers.inputBuffer.staticBuffer, + ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, + usedLength); + } + + if (ssl->buffers.inputBuffer.dynamicFlag != + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + #ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + #endif + XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + } + ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; + ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; + ssl->buffers.inputBuffer.dynamicFlag = 0; + ssl->buffers.inputBuffer.offset = 0; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = (word32)usedLength; +} + + +int SendBuffered(WOLFSSL* ssl) +{ + int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS; + + if (ssl->CBIOSend == NULL && !WOLFSSL_IS_QUIC(ssl)) { + WOLFSSL_MSG("Your IO Send callback is null, please set"); + return SOCKET_ERROR_E; + } + +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.outputBuffer.idx == 0) { + WOLFSSL_MSG("Data to send"); + WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + } +#endif + +#ifdef WOLFSSL_QUIC + if (WOLFSSL_IS_QUIC(ssl)) { + return wolfSSL_quic_send(ssl); + } +#endif + + while (ssl->buffers.outputBuffer.length > 0u) { + int sent = 0; +retry: + sent = ssl->CBIOSend(ssl, + (char*)ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.idx, + (int)ssl->buffers.outputBuffer.length, + #ifndef WOLFSSL_LEANPSK_STATIC_IO + ssl->IOCB_WriteCtx + #else + NULL + #endif + ); + if (sent < 0) { + switch (sent) { + + case WOLFSSL_CBIO_ERR_WANT_WRITE: /* would block */ + return WANT_WRITE; + + case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ + ssl->options.connReset = 1; + break; + + case WOLFSSL_CBIO_ERR_ISR: /* interrupt */ + /* see if we got our timeout */ + #ifdef WOLFSSL_CALLBACKS + if (ssl->toInfoOn) { + struct itimerval timeout; + getitimer(ITIMER_REAL, &timeout); + if (timeout.it_value.tv_sec == 0 && + timeout.it_value.tv_usec == 0) { + XSTRNCPY(ssl->timeoutInfo.timeoutName, + "send() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + + WOLFSSL_MSG("Got our timeout"); + return WANT_WRITE; + } + } + #endif + continue; + + case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */ + ssl->options.connReset = 1; /* treat same as reset */ + break; + + default: + return SOCKET_ERROR_E; + } + + return SOCKET_ERROR_E; + } + + if (sent > (int)ssl->buffers.outputBuffer.length) { + WOLFSSL_MSG("SendBuffered() out of bounds read"); + return SEND_OOB_READ_E; + } + + ssl->buffers.outputBuffer.idx += sent; + ssl->buffers.outputBuffer.length -= sent; + } + + ssl->buffers.outputBuffer.idx = 0; + + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); + + return 0; +} + + +/* returns the current location in the output buffer to start writing to */ +byte* GetOutputBuffer(WOLFSSL* ssl) +{ + return ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx + + ssl->buffers.outputBuffer.length; +} + +/* sets the output buffer from an externally provided buffer */ +int SetOutputBuffer(WOLFSSL* ssl, byte* buf, int bufSz) +{ + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + /* data waiting to be sent, don't overwrite it */ + if (ssl->buffers.outputBuffer.length > 0u) { + return WANT_WRITE; + } + + ssl->buffers.outputBuffer.dynamicFlag = WOLFSSL_EXTERNAL_IO_BUFFER; + ssl->buffers.outputBuffer.buffer = buf; + ssl->buffers.outputBuffer.bufferSize = bufSz; + + return WOLFSSL_SUCCESS; +} + + +/* sets the input buffer from an externally provided buffer */ +int SetInputBuffer(WOLFSSL* ssl, byte* buf, int bufSz) +{ + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + ssl->buffers.inputBuffer.dynamicFlag = WOLFSSL_EXTERNAL_IO_BUFFER; + ssl->buffers.inputBuffer.buffer = buf; + ssl->buffers.inputBuffer.bufferSize = bufSz; + + return WOLFSSL_SUCCESS; +} + +/* Grow the output buffer */ +static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) +{ + byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 +#ifdef WOLFSSL_DTLS + byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : + RECORD_HEADER_SZ; +#else + byte hdrSz = RECORD_HEADER_SZ; +#endif + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + word32 newSz; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + /* the encrypted data will be offset from the front of the buffer by + the header, if the user wants encrypted alignment they need + to define their alignment requirement */ + + while (align < hdrSz) + align *= 2; +#endif + + if (ssl->buffers.outputBuffer.dynamicFlag == + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + WOLFSSL_MSG("External output buffer provided was too small"); + return BAD_FUNC_ARG; + } + + if (! WC_SAFE_SUM_WORD32(ssl->buffers.outputBuffer.idx, + ssl->buffers.outputBuffer.length, newSz)) + return BUFFER_E; + if (! WC_SAFE_SUM_WORD32(newSz, (word32)size, newSz)) + return BUFFER_E; + if (! WC_SAFE_SUM_WORD32(newSz, align, newSz)) + return BUFFER_E; + tmp = (byte*)XMALLOC(newSz, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + newSz -= align; + WOLFSSL_MSG("growing output buffer"); + + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + tmp += align - hdrSz; +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* can be from IO memory pool which does not need copy if same buffer */ + if (ssl->buffers.outputBuffer.length && + tmp == ssl->buffers.outputBuffer.buffer) { + ssl->buffers.outputBuffer.bufferSize = newSz; + return 0; + } +#endif + + if (ssl->buffers.outputBuffer.length) + XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.idx + + ssl->buffers.outputBuffer.length); + + if (ssl->buffers.outputBuffer.dynamicFlag) { + XFREE(ssl->buffers.outputBuffer.buffer - + ssl->buffers.outputBuffer.offset, ssl->heap, + DYNAMIC_TYPE_OUT_BUFFER); + } + ssl->buffers.outputBuffer.dynamicFlag = 1; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + ssl->buffers.outputBuffer.offset = align - hdrSz; + else +#endif + ssl->buffers.outputBuffer.offset = 0; + + ssl->buffers.outputBuffer.buffer = tmp; + ssl->buffers.outputBuffer.bufferSize = newSz; + return 0; +} + + +/* Grow the input buffer, should only be to read cert or big app data */ +int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) +{ + byte* tmp; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 +#ifdef WOLFSSL_DTLS + byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; +#else + byte align = 0; +#endif + byte hdrSz = DTLS_RECORD_HEADER_SZ; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + /* the encrypted data will be offset from the front of the buffer by + the dtls record header, if the user wants encrypted alignment they need + to define their alignment requirement. in tls we read record header + to get size of record and put actual data back at front, so don't need */ + + if (align) { + while (align < hdrSz) + align *= 2; + } +#endif + + if (usedLength < 0 || size < 0) { + WOLFSSL_MSG("GrowInputBuffer() called with negative number"); + return BAD_FUNC_ARG; + } + + if (ssl->buffers.inputBuffer.dynamicFlag == + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + WOLFSSL_MSG("External input buffer provided was too small"); + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(size + usedLength + align, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + WOLFSSL_MSG("growing input buffer"); + + if (tmp == NULL) + return MEMORY_E; + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + tmp += align - hdrSz; +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* can be from IO memory pool which does not need copy if same buffer */ + if (usedLength && tmp == ssl->buffers.inputBuffer.buffer) { + ssl->buffers.inputBuffer.bufferSize = size + usedLength; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = usedLength; + return 0; + } +#endif + + if (usedLength) + XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, usedLength); + + if (ssl->buffers.inputBuffer.dynamicFlag) { +#ifndef WOLFSSL_NO_FORCE_ZERO + if (IsEncryptionOn(ssl, 1)) { + ForceZero(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + } +#endif + XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + } + + ssl->buffers.inputBuffer.dynamicFlag = 1; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + ssl->buffers.inputBuffer.offset = align - hdrSz; + else +#endif + ssl->buffers.inputBuffer.offset = 0; + + ssl->buffers.inputBuffer.buffer = tmp; + ssl->buffers.inputBuffer.bufferSize = size + usedLength; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = (word32)usedLength; + + return 0; +} + + +/* Check available size into output buffer, make room if needed. + * This function needs to be called before anything gets put + * into the output buffers since it flushes pending data if it + * predicts that the msg will exceed MTU. */ +int CheckAvailableSize(WOLFSSL *ssl, int size) +{ + if (size < 0) { + WOLFSSL_MSG("CheckAvailableSize() called with negative number"); + return BAD_FUNC_ARG; + } + + if ((ssl->buffers.outputBuffer.bufferSize - + ssl->buffers.outputBuffer.length - + ssl->buffers.outputBuffer.idx) < (word32)size) { + if (GrowOutputBuffer(ssl, size) < 0) + return MEMORY_E; + } + + return 0; +} + +#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS + +int MsgCheckEncryption(WOLFSSL* ssl, byte type, byte encrypted) +{ +#ifdef WOLFSSL_QUIC + /* QUIC protects messages outside of the TLS scope */ + if (WOLFSSL_IS_QUIC(ssl) && IsAtLeastTLSv1_3(ssl->version)) + return 0; +#endif + /* Verify which messages always have to be encrypted */ + if (IsAtLeastTLSv1_3(ssl->version)) { + switch ((enum HandShakeType)type) { + case client_hello: + case server_hello: + case hello_verify_request: + case hello_retry_request: + case change_cipher_hs: + if (encrypted) { + WOLFSSL_MSG("Message can not be encrypted"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case hello_request: + case session_ticket: + case end_of_early_data: + case encrypted_extensions: + case certificate: + case server_key_exchange: + case certificate_request: + case server_hello_done: + case certificate_verify: + case client_key_exchange: + case finished: + case certificate_status: + case key_update: + if (!encrypted) { + WOLFSSL_MSG("Message always has to be encrypted"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case message_hash: + case no_shake: + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + } + else { + switch ((enum HandShakeType)type) { + case client_hello: + break; + case server_hello: + case hello_verify_request: + case hello_retry_request: + case certificate: + case server_key_exchange: + case certificate_request: + case server_hello_done: + case certificate_verify: + case client_key_exchange: + case certificate_status: + case session_ticket: + case change_cipher_hs: + if (encrypted) { + WOLFSSL_MSG("Message can not be encrypted in regular " + "handshake"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case hello_request: + case finished: + if (!encrypted) { + WOLFSSL_MSG("Message always has to be encrypted"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case key_update: + case encrypted_extensions: + case end_of_early_data: + case message_hash: + case no_shake: + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + } + return 0; +} + +static WC_INLINE int isLastMsg(const WOLFSSL* ssl, word32 msgSz) +{ + word32 extra = 0; + if (IsEncryptionOn(ssl, 0)) { + extra = ssl->keys->padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + extra += MacSize(ssl); +#endif + } + return (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) + msgSz + extra + == ssl->curSize; +} + +/* Check if the msg is the last msg in a record. This is also an easy way + * to check that a record doesn't span different key boundaries. */ +static int MsgCheckBoundary(const WOLFSSL* ssl, byte type, + byte version_negotiated, word32 msgSz) +{ + if (version_negotiated) { + if (IsAtLeastTLSv1_3(ssl->version)) { + switch ((enum HandShakeType)type) { + case hello_request: + case client_hello: + case server_hello: + case hello_verify_request: + case hello_retry_request: + case finished: + case end_of_early_data: + if (!isLastMsg(ssl, msgSz)) { + WOLFSSL_MSG("Message type is not last in record"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case session_ticket: + case encrypted_extensions: + case certificate: + case server_key_exchange: + case certificate_request: + case certificate_verify: + case client_key_exchange: + case certificate_status: + case key_update: + case change_cipher_hs: + break; + case server_hello_done: + case message_hash: + case no_shake: + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + } + else { + switch ((enum HandShakeType)type) { + case hello_request: + case client_hello: + case hello_verify_request: + if (!isLastMsg(ssl, msgSz)) { + WOLFSSL_MSG("Message type is not last in record"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case server_hello: + case session_ticket: + case end_of_early_data: + case certificate: + case server_key_exchange: + case certificate_request: + case server_hello_done: + case certificate_verify: + case client_key_exchange: + case finished: + case certificate_status: + case change_cipher_hs: + break; + case hello_retry_request: + case encrypted_extensions: + case key_update: + case message_hash: + case no_shake: + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + } + } + else { + switch ((enum HandShakeType)type) { + case hello_request: + case client_hello: + case hello_verify_request: + if (!isLastMsg(ssl, msgSz)) { + WOLFSSL_MSG("Message type is not last in record"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; + case server_hello: + case session_ticket: + case end_of_early_data: + case hello_retry_request: + case encrypted_extensions: + case certificate: + case server_key_exchange: + case certificate_request: + case server_hello_done: + case certificate_verify: + case client_key_exchange: + case finished: + case certificate_status: + case key_update: + case change_cipher_hs: + break; + case message_hash: + case no_shake: + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + } + return 0; +} + +#endif /* WOLFSSL_DISABLE_EARLY_SANITY_CHECKS */ + +#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS +/** + * This check is performed as soon as the handshake message type becomes known. + * These checks can not be delayed and need to be performed when the msg is + * received and not when it is processed (fragmentation may cause messages to + * be processed at a later time). This function CAN NOT be called on stored + * messages as it relies on the state of the WOLFSSL object right after + * receiving the message. + * + * @param ssl The current connection + * @param type The enum HandShakeType of the current message + * @param msgSz Size of the current message + * @return + */ +int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz) +{ + int ret = 0; + /* Version has only been negotiated after we either send or process a + * ServerHello message */ + byte version_negotiated = ssl->options.serverState >= SERVER_HELLO_COMPLETE; + + WOLFSSL_ENTER("EarlySanityCheckMsgReceived"); + + if (version_negotiated) + ret = MsgCheckEncryption(ssl, type, ssl->keys->decryptedCur == 1); + + if (ret == 0) + ret = MsgCheckBoundary(ssl, type, version_negotiated, msgSz); + + if (ret != 0 +#ifdef WOLFSSL_DTLS + && ssl->options.dtls && ssl->options.dtlsStateful +#endif + ) + SendAlert(ssl, alert_fatal, unexpected_message); + + WOLFSSL_LEAVE("EarlySanityCheckMsgReceived", ret); + + return ret; +} +#endif + +/* do all verify and sanity checks on record header */ +static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, + RecordLayerHeader* rh, word16 *size) +{ + byte tls12minor = 0; + + (void)tls12minor; + { + /* Set explicitly rather than make assumptions on struct layout */ + rh->type = ssl->buffers.inputBuffer.buffer[*inOutIdx]; + rh->pvMajor = ssl->buffers.inputBuffer.buffer[*inOutIdx + 1]; + rh->pvMinor = ssl->buffers.inputBuffer.buffer[*inOutIdx + 2]; + rh->length[0] = ssl->buffers.inputBuffer.buffer[*inOutIdx + 3]; + rh->length[1] = ssl->buffers.inputBuffer.buffer[*inOutIdx + 4]; + + *inOutIdx += RECORD_HEADER_SZ; + ato16(rh->length, size); + } + /* catch version mismatch */ + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) + { +#ifndef WOLFSSL_NO_DOWNGRADE + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) + + WOLFSSL_MSG("Client attempting to connect with different version"); + else if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.downgrade && + ssl->options.connectState < FIRST_REPLY_DONE) + WOLFSSL_MSG("Server attempting to accept with different version"); + else +#endif + { + WOLFSSL_MSG("SSL version error"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; /* only use requested version */ + } + } + + /* record layer length check */ +#ifdef HAVE_MAX_FRAGMENT + if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) { + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } +#else + if (*size > (word16)(MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) { + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } +#endif + + if (*size == 0u && rh->type != (byte)application_data) { + WOLFSSL_MSG("0 length, non-app data record."); + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } + + /* verify record type here as well */ + switch (rh->type) { + case handshake: + case change_cipher_spec: + case application_data: + case alert: + break; + case no_type: + default: + WOLFSSL_MSG("Unknown Record Type"); + WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + + /* haven't decrypted this record yet */ + ssl->keys->decryptedCur = 0; + + return 0; +} + +#ifndef WOLFSSL_NO_TLS12 +static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte *type, word32 *size, word32 totalSz) +{ + const byte *ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 + +static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz) +{ + (void)input; + + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO); + WOLFSSL_ENTER("DoHelloRequest"); + + if (size) /* must be 0 */ + return BUFFER_ERROR; + + if (IsEncryptionOn(ssl, 0)) { + /* If size == totalSz then we are in DtlsMsgDrain so no need to worry + * about padding */ + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (size != totalSz && + *inOutIdx + ssl->keys->padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += ssl->keys->padSz + digestSz; + } + else + #endif + { + /* access beyond input + size should be checked against totalSz */ + if (size != totalSz && + *inOutIdx + ssl->keys->padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys->padSz; + } + } + + if (ssl->options.side == (byte)WOLFSSL_SERVER_END) { + SendAlert(ssl, alert_fatal, unexpected_message); /* try */ + WOLFSSL_ERROR_VERBOSE(FATAL_ERROR); + return FATAL_ERROR; + } +#ifdef HAVE_SECURE_RENEGOTIATION + else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { + ssl->secure_renegotiation->startScr = 1; + WOLFSSL_LEAVE("DoHelloRequest", 0); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_DO); + return 0; + } +#endif + else { + return SendAlert(ssl, alert_warning, no_renegotiation); + } +} + + +int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, + word32 totalSz, int sniff) +{ + word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ); + + WOLFSSL_START(WC_FUNC_FINISHED_DO); + WOLFSSL_ENTER("DoFinished"); + + if (finishedSz != size) + return BUFFER_ERROR; + + /* check against totalSz + * If size == totalSz then we are in DtlsMsgDrain so no need to worry about + * padding */ + if (size != totalSz) { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + if (*inOutIdx + size + ssl->keys->padSz + MacSize(ssl) > totalSz) + return BUFFER_E; + } + else + #endif + { + if (*inOutIdx + size + ssl->keys->padSz > totalSz) + return BUFFER_E; + } + } + + if (sniff == NO_SNIFF) { + if (XMEMCMP((void*)(input + *inOutIdx), + (void*)&ssl->hsHashes->verifyHashes, size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + WOLFSSL_ERROR_VERBOSE(VERIFY_FINISHED_ERROR); + return VERIFY_FINISHED_ERROR; + } + } + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation) { + /* save peer's state */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + XMEMCPY(ssl->secure_renegotiation->server_verify_data, + input + *inOutIdx, TLS_FINISHED_SZ); + else + XMEMCPY(ssl->secure_renegotiation->client_verify_data, + input + *inOutIdx, TLS_FINISHED_SZ); + ssl->secure_renegotiation->verifySet = 1; + } +#endif +#ifdef WOLFSSL_HAVE_TLS_UNIQUE + if (ssl->options.side == WOLFSSL_CLIENT_END) { + XMEMCPY(ssl->serverFinished, + input + *inOutIdx, TLS_FINISHED_SZ); + ssl->serverFinished_len = TLS_FINISHED_SZ; + } + else { + XMEMCPY(ssl->clientFinished, + input + *inOutIdx, TLS_FINISHED_SZ); + ssl->clientFinished_len = TLS_FINISHED_SZ; + } +#endif + + /* force input exhaustion at ProcessReply consuming padSz */ + *inOutIdx += size + ssl->keys->padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); +#endif + + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + if (!ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + if (ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + WOLFSSL_LEAVE("DoFinished", 0); + WOLFSSL_END(WC_FUNC_FINISHED_DO); + + return 0; +} + +#ifndef WOLFSSL_NO_SANITY_CHECK_HANDSHAKE +/* Make sure no duplicates, no fast forward, or other problems; 0 on success */ +static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_CLIENT + case hello_request: + if (ssl->msgsReceived.got_hello_request) { + WOLFSSL_MSG("Duplicate HelloRequest received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case hello_verify_request: + if (ssl->msgsReceived.got_hello_verify_request) { + WOLFSSL_MSG("Duplicate HelloVerifyRequest received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + if (ssl->msgsReceived.got_hello_retry_request) { + WOLFSSL_MSG("Received HelloVerifyRequest after a " + "HelloRetryRequest"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + ssl->msgsReceived.got_hello_verify_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + if (ssl->msgsReceived.got_session_ticket) { + WOLFSSL_MSG("Duplicate SessionTicket received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + + case certificate: + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) { + if ( ssl->msgsReceived.got_server_hello == 0u) { + WOLFSSL_MSG("No ServerHello before Cert"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } +#endif + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_status: + if (ssl->msgsReceived.got_certificate_status) { + WOLFSSL_MSG("Duplicate CertificateStatus received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_status = 1; + + if (ssl->msgsReceived.got_certificate == 0u) { + WOLFSSL_MSG("No Certificate before CertificateStatus"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_server_key_exchange != 0u) { + WOLFSSL_MSG("CertificateStatus after ServerKeyExchange"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_key_exchange: + if (ssl->msgsReceived.got_server_key_exchange) { + WOLFSSL_MSG("Duplicate ServerKeyExchange received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_key_exchange = 1; + + if (ssl->msgsReceived.got_server_hello == 0u) { + WOLFSSL_MSG("No ServerHello before ServerKeyExchange"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("CertificateRequest received by server"); + WOLFSSL_ERROR_VERBOSE(SIDE_ERROR); + return SIDE_ERROR; + } + #endif + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello_done: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("ServerHelloDone received by server"); + WOLFSSL_ERROR_VERBOSE(SIDE_ERROR); + return SIDE_ERROR; + } + #endif + if (ssl->msgsReceived.got_server_hello_done) { + WOLFSSL_MSG("Duplicate ServerHelloDone received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello_done = 1; + + if (ssl->msgsReceived.got_certificate == 0u) { + if (ssl->specs.kea == (byte)psk_kea || + ssl->specs.kea == (byte)dhe_psk_kea || + ssl->specs.kea == (byte)ecdhe_psk_kea || + ssl->options.usingAnon_cipher) { + WOLFSSL_MSG("No Cert required"); + } + else { + WOLFSSL_MSG("No Certificate before ServerHelloDone"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } + if (ssl->msgsReceived.got_server_key_exchange == 0u) { + int pskNoServerHint = 0; /* not required in this case */ + + #ifndef NO_PSK + if (ssl->specs.kea == (byte)psk_kea && + ssl->arrays != NULL && + ssl->arrays->server_hint[0] == 0) + pskNoServerHint = 1; + #endif + if (ssl->specs.static_ecdh == 1u || + ssl->specs.kea == (byte)rsa_kea || + pskNoServerHint) { + WOLFSSL_MSG("No KeyExchange required"); + } + else { + WOLFSSL_MSG("No ServerKeyExchange before ServerDone"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } + break; +#endif + + case finished: + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + if (ssl->msgsReceived.got_change_cipher == 0u) { + WOLFSSL_MSG("Finished received before ChangeCipher"); + WOLFSSL_ERROR_VERBOSE(NO_CHANGE_CIPHER_E); + return NO_CHANGE_CIPHER_E; + } + break; + + case change_cipher_hs: + if (ssl->msgsReceived.got_change_cipher) { + WOLFSSL_MSG("Duplicate ChangeCipher received"); + WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E); + return DUPLICATE_MSG_E; + } + /* DTLS is going to ignore the CCS message if the client key + * exchange message wasn't received yet. */ +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) +#endif + ssl->msgsReceived.got_change_cipher = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) { + if (!ssl->options.resuming) { + if (ssl->msgsReceived.got_server_hello_done == 0u) { + WOLFSSL_MSG("No ServerHelloDone before ChangeCipher"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } + else { + if (ssl->msgsReceived.got_server_hello == 0u) { + WOLFSSL_MSG("No ServerHello before ChangeCipher on " + "Resume"); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } + #ifdef HAVE_SESSION_TICKET + if (ssl->expect_session_ticket) { + WOLFSSL_MSG("Expected session ticket missing"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + #endif + WOLFSSL_ERROR_VERBOSE(SESSION_TICKET_EXPECT_E); + return SESSION_TICKET_EXPECT_E; + } + #endif + } +#endif + break; + + default: + WOLFSSL_MSG("Unknown message type"); + WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); + return SANITY_MSG_E; + } + + return 0; +} +#endif /* WOLFSSL_NO_SANITY_CHECK_HANDSHAKE */ + +int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + word32 expectedIdx; + + WOLFSSL_ENTER("DoHandShakeMsgType"); + +#ifdef WOLFSSL_TLS13 + if (type == hello_retry_request) { + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } +#endif + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) { + WOLFSSL_MSG("Incomplete Data"); + WOLFSSL_ERROR_VERBOSE(INCOMPLETE_DATA); + return INCOMPLETE_DATA; + } + + expectedIdx = *inOutIdx + size + + (ssl->keys->encryptionOn ? ssl->keys->padSz : 0); +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead && ssl->keys->encryptionOn) + expectedIdx += MacSize(ssl); +#endif + +#ifndef WOLFSSL_NO_SANITY_CHECK_HANDSHAKE + /* sanity check msg received */ + if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + return ret; + } +#endif + + if (ssl->options.handShakeState == (byte)HANDSHAKE_DONE && + type != hello_request){ + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END && + ssl->options.serverState == (byte)NULL_STATE && + type != server_hello && + type != hello_request) { + WOLFSSL_MSG("First server message not server hello or " + "hello request"); + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END && + type == server_hello_done && + ssl->options.serverState < (byte)SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("Server hello done received before server hello in DTLS"); + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == (byte)WOLFSSL_SERVER_END && + ssl->options.clientState == (byte)NULL_STATE && + type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + /* hello_request not hashed */ + if (type != hello_request) { + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + size + HANDSHAKE_HEADER_SZ); + if (ret != 0) { + WOLFSSL_MSG("Incomplete handshake hashes"); + return ret; + } + } + +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (ssl->options.side == WOLFSSL_CLIENT_END) { + switch (type) { + case certificate: + case server_key_exchange: + case certificate_request: + case server_hello_done: + if (ssl->options.resuming) { + /* https://www.rfc-editor.org/rfc/rfc5077.html#section-3.4 + * Alternatively, the client MAY include an empty Session ID + * in the ClientHello. In this case, the client ignores the + * Session ID sent in the ServerHello and determines if the + * server is resuming a session by the subsequent handshake + * messages. + */ +#ifndef WOLFSSL_WPAS + if (ssl->session->sessionIDSz != 0) { + /* Fatal error. Only try to send an alert. RFC 5246 does not + * allow for reverting back to a full handshake after the + * server has indicated the intention to do a resumption. */ + (void)SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } +#endif + /* This can occur when ssl->sessionSecretCb is set. EAP-FAST + * (RFC 4851) allows for detecting server session resumption + * based on the msg received after the ServerHello. */ + WOLFSSL_MSG("Not resuming as thought"); + ssl->options.resuming = 0; + /* No longer resuming, reset peer authentication state. */ + ssl->options.peerAuthGood = 0; + } + } + } +#endif + + switch (type) { + + case hello_request: + WOLFSSL_MSG("processing hello request"); + ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz); + break; + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoServerHello(ssl, input, inOutIdx, size); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)) || \ + (defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) || + IsAtLeastTLSv1_3(ssl->version)) { + + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + #endif + { + ssl->options.cacheMessages = 0; + if ((ssl->hsHashes != NULL) && + (ssl->hsHashes->messages != NULL)) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); + XFREE(ssl->hsHashes->messages, ssl->heap, + DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + } + #endif + break; + + case server_key_exchange: + WOLFSSL_MSG("processing server key exchange"); + ret = DoServerKeyExchange(ssl, input, inOutIdx, size); + break; + +#endif + + case server_hello_done: + WOLFSSL_MSG("processing server hello done"); + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys->padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif + } + break; + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + if (ret == 0 && expectedIdx != *inOutIdx) { + WOLFSSL_MSG("Extra data in handshake message"); + #ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) + #endif + SendAlert(ssl, alert_fatal, decode_error); + ret = DECODE_E; + WOLFSSL_ERROR_VERBOSE(ret); + } + + WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); + return ret; +} + + +static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoHandShakeMsg"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) { + WOLFSSL_ERROR_VERBOSE(PARSE_ERROR); + return PARSE_ERROR; + } + +#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS + ret = EarlySanityCheckMsgReceived(ssl, type, size); + if (ret != 0) { + WOLFSSL_ERROR(ret); + return ret; + } +#endif + + if (size > (word32)MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + WOLFSSL_ERROR_VERBOSE(HANDSHAKE_SIZE_ERROR); + return HANDSHAKE_SIZE_ERROR; + } + + return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0u) { + byte type; + word32 size; + + if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size, + totalSz) != 0) { + WOLFSSL_ERROR_VERBOSE(PARSE_ERROR); + return PARSE_ERROR; + } + +#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS + ret = EarlySanityCheckMsgReceived(ssl, type, + min(inputLength - HANDSHAKE_HEADER_SZ, size)); + if (ret != 0) { + WOLFSSL_ERROR(ret); + return ret; + } +#endif + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > (word32)MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + WOLFSSL_ERROR_VERBOSE(HANDSHAKE_SIZE_ERROR); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + + if (ssl->arrays->pendingMsg != NULL) { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + } + + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + else { + word32 pendSz = + ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset; + + /* Catch the case where there may be the remainder of a fragmented + * handshake message and the next handshake message in the same + * record. */ + if (inputLength > pendSz) + inputLength = pendSz; + +#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS + ret = EarlySanityCheckMsgReceived(ssl, ssl->arrays->pendingMsgType, + inputLength); + if (ret != 0) { + WOLFSSL_ERROR(ret); + return ret; + } +#endif + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error != WC_PENDING_E) + #endif + { + if (ssl->arrays->pendingMsgOffset + inputLength > + ssl->arrays->pendingMsgSz) { + return MEMORY_E; + } + /* for async this copy was already done, do not replace, since + * contents may have been changed for inline operations */ + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + } + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = HANDSHAKE_HEADER_SZ; + ret = DoHandShakeMsgType(ssl, + ssl->arrays->pendingMsg, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - idx, + ssl->arrays->pendingMsgSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* setup to process fragment again */ + ssl->arrays->pendingMsgOffset -= inputLength; + *inOutIdx -= inputLength; + } + else + #endif + { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + } + + WOLFSSL_LEAVE("DoHandShakeMsg()", ret); + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_EXTRA_ALERTS +int SendFatalAlertOnly(WOLFSSL *ssl, int error) +{ + int why; + + /* already sent a more specific fatal alert */ + if (ssl->alert_history.last_tx.level == alert_fatal) + return 0; + + switch (error) { + /* not fatal errors */ + case WANT_WRITE: + case WANT_READ: + case ZERO_RETURN: +#ifdef WOLFSSL_NONBLOCK_OCSP + case OCSP_WANT_READ: +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + case WC_PENDING_E: +#endif + return 0; + + /* peer already disconnected and ssl is possibly in bad state + * don't try to send an alert */ + case SOCKET_ERROR_E: + return error; + + case BUFFER_ERROR: + case ASN_PARSE_E: + case COMPRESSION_ERROR: + why = decode_error; + break; + case VERIFY_FINISHED_ERROR: + case SIG_VERIFY_E: + why = decrypt_error; + break; + case DUPLICATE_MSG_E: + case NO_CHANGE_CIPHER_E: + case OUT_OF_ORDER_E: + why = unexpected_message; + break; + case ECC_OUT_OF_RANGE_E: + why = bad_record_mac; + break; + case MATCH_SUITE_ERROR: + case VERSION_ERROR: + default: + why = handshake_failure; + break; + } + + return SendAlert(ssl, alert_fatal, why); +} +#else +int SendFatalAlertOnly(WOLFSSL *ssl, int error) +{ + (void)ssl; + (void)error; + /* no op */ + return 0; +} +#endif /* WOLFSSL_EXTRA_ALERTS */ + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_AEAD + +#if (!defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))) || \ + (defined(HAVE_POLY1305) && defined(HAVE_CHACHA)) +static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) +{ + int i; + for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) { + if (++ssl->keys->aead_exp_IV[i]) return; + } +} +#endif +#endif /* HAVE_AEAD */ + + +#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + +#if !defined(NO_GCM_ENCRYPT_EXTRA) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) +/* The following type is used to share code between AES-GCM and AES-CCM. */ + typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + #define AES_AUTH_ENCRYPT_FUNC AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt_ex + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt_ex +#else + #define AES_AUTH_ENCRYPT_FUNC wc_AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt +#endif + +#endif +#endif /* !WOLFSSL_NO_TLS12 */ + +/* Check conditions for a cipher to have an explicit IV. + * + * ssl The SSL/TLS object. + * returns 1 if the cipher in use has an explicit IV and 0 otherwise. + */ +static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl) +{ +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return 0; +#endif + return (ssl->specs.cipher_type == (byte)aead) && + (ssl->specs.bulk_cipher_algorithm != (byte)wolfssl_chacha); +} + + +/* check cipher text size for sanity */ +static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 minLength = ssl->specs.hash_size; /* covers stream */ +#endif + +#ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == (byte)block) { +#ifdef HAVE_ENCRYPT_THEN_MAC + if (ssl->options.startedETMRead) { + if ((encryptSz - MacSize(ssl)) % ssl->specs.block_size) { + WOLFSSL_MSG("Block ciphertext not block size"); + WOLFSSL_ERROR_VERBOSE(SANITY_CIPHER_E); + return SANITY_CIPHER_E; + } + } + else +#endif + if (encryptSz % ssl->specs.block_size) { + WOLFSSL_MSG("Block ciphertext not block size"); + WOLFSSL_ERROR_VERBOSE(SANITY_CIPHER_E); + return SANITY_CIPHER_E; + } + + minLength++; /* pad byte */ + + if (ssl->specs.block_size > minLength) + minLength = ssl->specs.block_size; + + if (ssl->options.tls1_1) + minLength += ssl->specs.block_size; /* explicit IV */ + } + else +#endif + if (ssl->specs.cipher_type == (byte)aead) { + minLength = ssl->specs.aead_mac_size; /* authTag size */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + } + + if (encryptSz < minLength) { + WOLFSSL_MSG("Ciphertext not minimum size"); + WOLFSSL_ERROR_VERBOSE(SANITY_CIPHER_E); + return SANITY_CIPHER_E; + } + + return 0; +} + +#ifndef WOLFSSL_AEAD_ONLY +#ifdef WOLSSL_OLD_TIMINGPADVERIFY +#define COMPRESS_LOWER 64 +#define COMPRESS_UPPER 55 +#define COMPRESS_CONSTANT 13 + +#ifndef NO_OLD_TLS + +static WC_INLINE void Md5Rounds(int rounds, const byte* data, int sz) +{ + wc_Md5 md5; + int i; + + wc_InitMd5(&md5); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) + wc_Md5Update(&md5, data, sz); + wc_Md5Free(&md5); /* in case needed to release resources */ +} + + + +/* do a dummy sha round */ +static WC_INLINE void ShaRounds(int rounds, const byte* data, int sz) +{ + wc_Sha sha; + int i; + + wc_InitSha(&sha); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) + wc_ShaUpdate(&sha, data, sz); + wc_ShaFree(&sha); /* in case needed to release resources */ +} +#endif + + +#ifndef NO_SHA256 + +static WC_INLINE void Sha256Rounds(int rounds, const byte* data, int sz) +{ + wc_Sha256 sha256; + int i; + + wc_InitSha256(&sha256); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha256Update(&sha256, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha256Free(&sha256); /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_SHA384 + +static WC_INLINE void Sha384Rounds(int rounds, const byte* data, int sz) +{ + wc_Sha384 sha384; + int i; + + wc_InitSha384(&sha384); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha384Update(&sha384, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha384Free(&sha384); /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_SHA512 +static WC_INLINE void Sha512Rounds(int rounds, const byte* data, int sz) +{ + wc_Sha512 sha512; + int i; + + wc_InitSha512(&sha512); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha512Update(&sha512, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha512Free(&sha512); /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_RIPEMD + +static WC_INLINE void RmdRounds(int rounds, const byte* data, int sz) +{ + RipeMd ripemd; + int i; + + wc_InitRipeMd(&ripemd); + + for (i = 0; i < rounds; i++) + wc_RipeMdUpdate(&ripemd, data, sz); +} + +#endif + + +/* Do dummy rounds */ +static WC_INLINE void DoRounds(int type, int rounds, const byte* data, int sz) +{ + (void)rounds; + (void)data; + (void)sz; + + switch (type) { + case no_mac : + break; + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + case md5_mac : + Md5Rounds(rounds, data, sz); + break; +#endif + +#ifndef NO_SHA + case sha_mac : + ShaRounds(rounds, data, sz); + break; +#endif +#endif + +#ifndef NO_SHA256 + case sha256_mac : + Sha256Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_SHA384 + case sha384_mac : + Sha384Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_SHA512 + case sha512_mac : + Sha512Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_RIPEMD + case rmd_mac : + RmdRounds(rounds, data, sz); + break; +#endif + + default: + WOLFSSL_MSG("Bad round type"); + break; + } +} + + +/* do number of compression rounds on dummy data */ +static WC_INLINE void CompressRounds(WOLFSSL* ssl, int rounds, + const byte* dummy) +{ + if (rounds) + DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER); +} + + +/* check all length bytes for the pad value, return 0 on success */ +static int PadCheck(const byte* a, byte pad, int length) +{ + int i; + int compareSum = 0; + + for (i = 0; i < length; i++) { + compareSum |= a[i] ^ pad; + } + + return compareSum; +} + + +/* get compression extra rounds */ +static WC_INLINE int GetRounds(int pLen, int padLen, int t) +{ + int roundL1 = 1; /* round up flags */ + int roundL2 = 1; + + int L1 = COMPRESS_CONSTANT + pLen - t; + int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t; + + L1 -= COMPRESS_UPPER; + L2 -= COMPRESS_UPPER; + + if ( (L1 % COMPRESS_LOWER) == 0) + roundL1 = 0; + if ( (L2 % COMPRESS_LOWER) == 0) + roundL2 = 0; + + L1 /= COMPRESS_LOWER; + L2 /= COMPRESS_LOWER; + + L1 += roundL1; + L2 += roundL2; + + return L1 - L2; +} + + +/* timing resistant pad/verify check, return 0 on success */ + int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, + int pLen, int content) +{ + byte verify[WC_MAX_DIGEST_SIZE]; + byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0}; + byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy; + int ret = 0; + + (void)dmy; + + if ( (t + padLen + 1) > pLen) { + WOLFSSL_MSG("Plain Len not long enough for pad/mac"); + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE); + /* still compare */ + ssl->hmac(ssl, verify, input, pLen - t, -1, content, 1, PEER_ORDER); + ConstantCompare(verify, input + pLen - t, t); + WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); + return VERIFY_MAC_ERROR; + } + + if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) { + WOLFSSL_MSG("PadCheck failed"); + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + /* still compare */ + ssl->hmac(ssl, verify, input, pLen - t, -1, content, 1, PEER_ORDER); + ConstantCompare(verify, input + pLen - t, t); + WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); + return VERIFY_MAC_ERROR; + } + + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, -1, content, + 1, PEER_ORDER); + + CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy); + + if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) { + WOLFSSL_MSG("Verify MAC compare failed"); + WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); + return VERIFY_MAC_ERROR; + } + + /* treat any failure as verify MAC error */ + if (ret != 0) { + ret = VERIFY_MAC_ERROR; + WOLFSSL_ERROR_VERBOSE(ret); + } + + return ret; +} +#else + +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + +#ifndef WOLFSSL_LEANPSK_STATIC +/* check all length bytes for the pad value, return 0 on success */ +static int PadCheck(const byte* a, byte pad, int length) +{ + int i; + int compareSum = 0; + + for (i = 0; i < length; i++) { + compareSum |= a[i] ^ pad; + } + + return compareSum; +} +#endif /* WOLFSSL_LEANPSK_STATIC */ + + +/* Mask the padding bytes with the expected values. + * Constant time implementation - does maximum pad size possible. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC. + * returns 0 on success, otherwise failure. + */ +static byte MaskPadding(const byte* data, int sz, int macSz) +{ + int i; + int checkSz = sz - 1; + byte paddingSz = data[sz - 1]; + byte good = ctMaskGT(paddingSz, sz - 1 - macSz); + + if (checkSz > TLS_MAX_PAD_SZ) + checkSz = TLS_MAX_PAD_SZ; + + for (i = 0; i < checkSz; i++) { + byte mask = ctMaskLTE(i, paddingSz); + good |= mask & (data[sz - 1 - i] ^ paddingSz); + } + + return good; +} + +/* Mask the MAC in the message with the MAC calculated. + * Constant time implementation - starts looking for MAC where maximum padding + * size has it. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC data. + * expMac Expected MAC value. + * returns 0 on success, otherwise failure. + */ +static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac) +{ + int i, j; + unsigned char mac[WC_MAX_DIGEST_SIZE]; + int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz; + int macEnd = sz - 1 - data[sz - 1]; + int macStart = macEnd - macSz; + int r = 0; + unsigned char started, notEnded; + unsigned char good = 0; + + scanStart &= ctMaskIntGTE(scanStart, 0); + macStart &= ctMaskIntGTE(macStart, 0); + + /* Div on Intel has different speeds depending on value. + * Use a bitwise AND or mod a specific value (converted to mul). */ + if ((macSz & (macSz - 1)) == 0) + r = (macSz - (scanStart - macStart)) & (macSz - 1); +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE; +#endif + + XMEMSET(mac, 0, macSz); + for (i = scanStart; i < sz; i += macSz) { + for (j = 0; j < macSz && j + i < sz; j++) { + started = ctMaskGTE(i + j, macStart); + notEnded = ctMaskLT(i + j, macEnd); + mac[j] |= started & notEnded & data[i + j]; + } + } + + if ((macSz & (macSz - 1)) == 0) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) & (macSz - 1)]; + } +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE]; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE]; + } +#endif + + return good; +} + +/* timing resistant pad/verify check, return 0 on success */ +int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz, + int pLen, int content) +{ + byte verify[WC_MAX_DIGEST_SIZE]; + byte good; + int ret = 0; + + good = MaskPadding(input, pLen, macSz); + /* 4th argument has potential to underflow, ssl->hmac function should + * either increment the size by (macSz + padLen + 1) before use or check on + * the size to make sure is valid. */ + ret = TLS_hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen, + content, 1, PEER_ORDER); + good |= MaskMac(input, pLen, WC_SHA256_DIGEST_SIZE, verify); + + /* Non-zero on failure. */ + good = (byte)~(word32)good; + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + /* Make ret negative on masking failure. */ + ret -= 1 - good; + + /* Treat any failure as verify MAC error. */ + if (ret != 0) { + ret = VERIFY_MAC_ERROR; + WOLFSSL_ERROR_VERBOSE(ret); + } + + return ret; +} +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ +#endif /* WOLSSL_OLD_TIMINGPADVERIFY */ +#endif /* WOLFSSL_AEAD_ONLY */ + +int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) +{ + word32 msgSz = WOLFSSL_IS_QUIC(ssl)? ssl->curSize : ssl->keys->encryptSz; + word32 idx = *inOutIdx; + int dataSz; + int ivExtra = 0; + byte* rawData = input + idx; /* keep current for hmac */ +#ifdef HAVE_LIBZ + byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; +#endif + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) { + int process = 0; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + if ((ssl->earlyData != no_early_data) && + (ssl->options.clientState == CLIENT_HELLO_COMPLETE)) { + process = 1; + } + if (!process) { + WOLFSSL_MSG("Ignoring EarlyData!"); + *inOutIdx += ssl->curSize; + if (*inOutIdx > ssl->buffers.inputBuffer.length) + return BUFFER_E; + + return 0; + } + } + if (!process) { + WOLFSSL_MSG("Received App data before a handshake completed"); + if (sniff == NO_SNIFF) { + SendAlert(ssl, alert_fatal, unexpected_message); + } + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + } + else +#endif + if (ssl->options.handShakeDone == 0u) { + WOLFSSL_MSG("Received App data before a handshake completed"); + if (sniff == NO_SNIFF) { + SendAlert(ssl, alert_fatal, unexpected_message); + } + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; + } + + +#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS) + /* Check if we want to invalidate old epochs. If + * ssl->dtls13InvalidateBefore is set then we want to mark all old + * epochs as encrypt only. This is done when we detect too many failed + * decryptions. We do this here to confirm that the peer has updated its + * keys and we can stop using the old keys-> */ + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { + if (!w64IsZero(ssl->dtls13InvalidateBefore) && + w64Equal(ssl->keys->curEpoch64, ssl->dtls13InvalidateBefore)) { + Dtls13SetOlderEpochSide(ssl, ssl->dtls13InvalidateBefore, + ENCRYPT_SIDE_ONLY); + w64Zero(&ssl->dtls13InvalidateBefore); + } + } +#endif + +#ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == (byte)block) { + if (ssl->options.tls1_1) + ivExtra = ssl->specs.block_size; + } + else +#endif + if (ssl->specs.cipher_type == (byte)aead) { + if (CipherHasExpIV(ssl)) + ivExtra = AESGCM_EXP_IV_SZ; + } + + dataSz = msgSz - ivExtra - ssl->keys->padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + dataSz -= MacSize(ssl); +#endif + if (dataSz < 0) { + WOLFSSL_MSG("App data buffer error, malicious input?"); + if (sniff == NO_SNIFF) { + SendAlert(ssl, alert_fatal, unexpected_message); + } + WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR); + return BUFFER_ERROR; + } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData > early_data_ext) { + if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) { + if (sniff == NO_SNIFF) { + SendAlert(ssl, alert_fatal, unexpected_message); + } + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyDataSz += dataSz; + } +#endif + + /* read data */ + if (dataSz) { + int rawSz = dataSz; /* keep raw size for idx adjustment */ + +#ifdef HAVE_LIBZ + if (ssl->options.usingCompression) { + dataSz = myDeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp)); + if (dataSz < 0) return dataSz; + } +#endif + idx += rawSz; + + ssl->buffers.clearOutputBuffer.buffer = rawData; + ssl->buffers.clearOutputBuffer.length = (unsigned int)dataSz; + } + + idx += ssl->keys->padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + idx += MacSize(ssl); +#endif + +#ifdef HAVE_LIBZ + /* decompress could be bigger, overwrite after verify */ + if (ssl->options.usingCompression) + XMEMMOVE(rawData, decomp, dataSz); +#endif + + *inOutIdx = idx; +#ifdef WOLFSSL_DTLS13 + if (ssl->options.connectState == WAIT_FINISHED_ACK) { + /* DTLS 1.3 is waiting for an ACK but we can still return app data. */ + return APP_DATA_READY; + } +#endif + return 0; +} + +#ifndef NO_ALERT_STRINGS +const char* AlertTypeToString(int type) +{ + switch (type) { + case close_notify: + { + static const char close_notify_str[] = + "close_notify"; + return close_notify_str; + } + + case unexpected_message: + { + static const char unexpected_message_str[] = + "unexpected_message"; + return unexpected_message_str; + } + + case bad_record_mac: + { + static const char bad_record_mac_str[] = + "bad_record_mac"; + return bad_record_mac_str; + } + + case record_overflow: + { + static const char record_overflow_str[] = + "record_overflow"; + return record_overflow_str; + } + + case decompression_failure: + { + static const char decompression_failure_str[] = + "decompression_failure"; + return decompression_failure_str; + } + + case handshake_failure: + { + static const char handshake_failure_str[] = + "handshake_failure"; + return handshake_failure_str; + } + + case no_certificate: + { + static const char no_certificate_str[] = + "no_certificate"; + return no_certificate_str; + } + + case bad_certificate: + { + static const char bad_certificate_str[] = + "bad_certificate"; + return bad_certificate_str; + } + + case unsupported_certificate: + { + static const char unsupported_certificate_str[] = + "unsupported_certificate"; + return unsupported_certificate_str; + } + + case certificate_revoked: + { + static const char certificate_revoked_str[] = + "certificate_revoked"; + return certificate_revoked_str; + } + + case certificate_expired: + { + static const char certificate_expired_str[] = + "certificate_expired"; + return certificate_expired_str; + } + + case certificate_unknown: + { + static const char certificate_unknown_str[] = + "certificate_unknown"; + return certificate_unknown_str; + } + + case illegal_parameter: + { + static const char illegal_parameter_str[] = + "illegal_parameter"; + return illegal_parameter_str; + } + + case unknown_ca: + { + static const char unknown_ca_str[] = + "unknown_ca"; + return unknown_ca_str; + } + + case access_denied: + { + static const char access_denied_str[] = + "access_denied"; + return access_denied_str; + } + + case decode_error: + { + static const char decode_error_str[] = + "decode_error"; + return decode_error_str; + } + + case decrypt_error: + { + static const char decrypt_error_str[] = + "decrypt_error"; + return decrypt_error_str; + } + + case wolfssl_alert_protocol_version: + { + static const char protocol_version_str[] = + "protocol_version"; + return protocol_version_str; + } + case insufficient_security: + { + static const char insufficient_security_str[] = + "insufficient_security"; + return insufficient_security_str; + } + + case internal_error: + { + static const char internal_error_str[] = + "internal_error"; + return internal_error_str; + } + + case user_canceled: + { + static const char user_canceled_str[] = + "user_canceled"; + return user_canceled_str; + } + + case no_renegotiation: + { + static const char no_renegotiation_str[] = + "no_renegotiation"; + return no_renegotiation_str; + } + + case unrecognized_name: + { + static const char unrecognized_name_str[] = + "unrecognized_name"; + return unrecognized_name_str; + } + + case bad_certificate_status_response: + { + static const char bad_certificate_status_response_str[] = + "bad_certificate_status_response"; + return bad_certificate_status_response_str; + } + + case no_application_protocol: + { + static const char no_application_protocol_str[] = + "no_application_protocol"; + return no_application_protocol_str; + } + default: + WOLFSSL_MSG("Unknown Alert"); + return NULL; + } +} +#endif /* !NO_ALERT_STRINGS */ + +#ifndef WOLFSSL_LEANPSK +static void LogAlert(int type) +{ +#ifdef DEBUG_WOLFSSL + const char* typeStr; + + typeStr = AlertTypeToString(type); + if (typeStr != NULL) { + char buff[60]; + XSNPRINTF(buff, sizeof(buff), "Alert type: %s", typeStr); + WOLFSSL_MSG(buff); + } +#else + (void)type; +#endif /* DEBUG_WOLFSSL */ +} +#endif + +/* process alert, return level */ +static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type) +{ + byte level; + byte code; + word32 dataSz = (word32)ssl->curSize; + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "Alert"); + if (ssl->toInfoOn) { + /* add record header back on to info + alert bytes level/code */ + int ret = AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx, + ALERT_SIZE, READ_PROTO, RECORD_HEADER_SZ, ssl->heap); + if (ret != 0) + return ret; + #ifdef WOLFSSL_CALLBACKS + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif + } + #endif + + if (IsEncryptionOn(ssl, 0)) { + int ivExtra = 0; +#ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == (byte)block) { + if (ssl->options.tls1_1) + ivExtra = ssl->specs.block_size; + } + else +#endif + if (ssl->specs.cipher_type == (byte)aead) { + if (CipherHasExpIV(ssl)) + ivExtra = AESGCM_EXP_IV_SZ; + } + dataSz -= ivExtra; + dataSz -= ssl->keys->padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + dataSz -= MacSize(ssl); + #endif + } + + /* make sure can read the message */ + if (dataSz != (word32)ALERT_SIZE) { +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + return BUFFER_E; + } + + level = input[(*inOutIdx)++]; + code = input[(*inOutIdx)++]; + ssl->alert_history.last_rx.code = code; + ssl->alert_history.last_rx.level = level; + *type = code; + if (level == (byte)alert_fatal) { + ssl->options.isClosed = 1; /* Don't send close_notify */ + } + + if (++ssl->options.alertCount >= (byte)WOLFSSL_ALERT_COUNT_MAX) { + WOLFSSL_MSG("Alert count exceeded"); +#ifdef WOLFSSL_EXTRA_ALERTS + if (level != alert_warning || code != close_notify) + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + WOLFSSL_ERROR_VERBOSE(ALERT_COUNT_E); + return ALERT_COUNT_E; + } + +#ifndef WOLFSSL_LEANPSK + LogAlert(*type); +#endif + if (*type == close_notify) { + ssl->options.closeNotify = 1; + } + else { + /* + * A close_notify alert doesn't mean there's been an error, so we only + * add other types of alerts to the error queue + */ + WOLFSSL_ERROR(*type); + } + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys->padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif + } + + return level; +} + +static int GetInputData(WOLFSSL *ssl, word32 size) +{ + int inSz; + int maxLength; + int usedLength; + int dtlsExtra = 0; + + + /* check max input length */ + usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; + maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength; + inSz = (int)(size - usedLength); /* from last partial read */ + + /* check that no lengths or size values are negative */ + if (usedLength < 0 || maxLength < 0 || inSz <= 0) { + return BUFFER_ERROR; + } + + if (inSz > maxLength) { + if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0) + return MEMORY_E; + } + + /* Put buffer data at start if not there */ + if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0u) + XMEMMOVE((void*)&ssl->buffers.inputBuffer.buffer[0], + (void*)(ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx), + usedLength); + + /* remove processed data */ + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = (word32)usedLength; + + /* read data from network */ + do { + int in = wolfSSLReceive(ssl, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.length, + (word32)inSz); + if (in == WANT_READ) + return WANT_READ; + + if (in < 0) { + WOLFSSL_ERROR_VERBOSE(SOCKET_ERROR_E); + return SOCKET_ERROR_E; + } + + if (in > inSz) { + WOLFSSL_ERROR_VERBOSE(RECV_OVERFLOW_E); + return RECV_OVERFLOW_E; + } + + ssl->buffers.inputBuffer.length += in; + inSz -= in; + + } while (ssl->buffers.inputBuffer.length < size); + + return 0; +} + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz, + int content) +{ + int ret; +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + byte verify[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_MSG("Verify MAC of Encrypted Data"); + + if (msgSz < digestSz) { + WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); + return VERIFY_MAC_ERROR; + } + + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, + PEER_ORDER); + ret |= ConstantCompare(verify, input + msgSz - digestSz, (int)digestSz); + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); + return VERIFY_MAC_ERROR; + } + + return 0; +} +#endif + +static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, + int content, word32* padSz) +{ +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + int ret; + word32 pad = 0; + word32 padByte = 0; +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = WC_SHA256_DIGEST_SIZE; +#endif + byte verify[WC_MAX_DIGEST_SIZE]; + + + if (ssl->specs.cipher_type == (byte)block) { + int ivExtra = 0; + if (ssl->options.tls1_1) + ivExtra = ssl->specs.block_size; + pad = *(input + msgSz - ivExtra - 1); + padByte = 1; + + if (ssl->options.tls) { + ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra, + content); + if (ret != 0) + return ret; + } + } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ + + if (ssl->specs.cipher_type == (byte)aead) { + *padSz = ssl->specs.aead_mac_size; + } + else +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + { + *padSz = digestSz + pad + padByte; + } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ + + (void)input; + (void)msgSz; + (void)content; + + return 0; +} + + +int ProcessReply(WOLFSSL* ssl) +{ + int allowSocketErr = 0; + int ret = 0, type = internal_error, readSz; + int atomicUser = 0; + + if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE + #if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13) + && ssl->error != APP_DATA_READY + #endif + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + && ssl->error != OCSP_WANT_READ + #endif + && (allowSocketErr != 1 || ssl->error != SOCKET_ERROR_E) + ) { + WOLFSSL_MSG("ProcessReply retry in error state, not allowed"); + return ssl->error; + } + + /* If checking alert on error (allowSocketErr == 1) do not try and + * process alerts for async or ocsp non blocking */ +#if defined(WOLFSSL_CHECK_ALERT_ON_ERR) && \ + (defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)) + if (allowSocketErr == 1 && \ + (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + return ssl->error; + } +#endif + + ret = RetrySendAlert(ssl); + if (ret != 0) { + WOLFSSL_MSG_EX("RetrySendAlert failed, giving up. err = %d", ret); + return ret; + } + + for (;;) { + switch (ssl->options.processReply) { + + /* in the WOLFSSL_SERVER case, get the first byte for detecting + * old client hello */ + case doProcessInit: + + readSz = RECORD_HEADER_SZ; + + /* get header or return error */ + if ((ret = GetInputData(ssl, (word32)readSz)) < 0) + return ret; + + FALL_THROUGH; + + /* get the record layer header */ + case getRecordLayerHeader: + + /* DTLSv1.3 record numbers in the header are encrypted, and AAD + * uses the unencrypted form. Because of this we need to modify the + * header, decrypting the numbers inside + * DtlsParseUnifiedRecordLayer(). This violates the const attribute + * of the buffer parameter of GetRecordHeader() used here. */ + ret = GetRecordHeader(ssl, &ssl->buffers.inputBuffer.idx, + &ssl->curRL, &ssl->curSize); + + if (ret != 0) { + switch (ret) { + case VERSION_ERROR: + /* send alert per RFC5246 Appendix E. Backward + * Compatibility */ + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) + SendAlert(ssl, alert_fatal, + wolfssl_alert_protocol_version); + break; +#ifdef HAVE_MAX_FRAGMENT + case LENGTH_ERROR: + SendAlert(ssl, alert_fatal, record_overflow); + break; +#endif /* HAVE_MAX_FRAGMENT */ +default: + break; + } + return ret; + } + + ssl->options.processReply = getData; + FALL_THROUGH; + + /* retrieve record layer data */ + case getData: + + /* get sz bytes or return error */ +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) { +#endif + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) { +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret != WANT_READ) + SendAlert(ssl, alert_fatal, bad_record_mac); +#endif + return ret; + } + +#ifndef WOLFSSL_LEANPSK + if (IsEncryptionOn(ssl, 0)) { +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + int tooLong = 0; +#endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + tooLong = ssl->curSize > MAX_TLS13_ENC_SZ; + tooLong |= ssl->curSize - ssl->specs.aead_mac_size > + MAX_TLS13_PLAIN_SZ; + } +#endif +#ifdef WOLFSSL_EXTRA_ALERTS + if (!IsAtLeastTLSv1_3(ssl->version)) + tooLong = ssl->curSize > MAX_TLS_CIPHER_SZ; +#endif +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + if (tooLong) { + WOLFSSL_MSG("Encrypted data too long"); + SendAlert(ssl, alert_fatal, record_overflow); + return BUFFER_ERROR; + } +#endif + } +#endif + ssl->keys->padSz = 0; + + ssl->options.processReply = verifyEncryptedMessage; + /* in case > 1 msg per record */ + ssl->curStartIdx = ssl->buffers.inputBuffer.idx; + FALL_THROUGH; + + /* verify digest of encrypted message */ + case verifyEncryptedMessage: +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0 && + !atomicUser && ssl->options.startedETMRead) { + ret = VerifyMacEnc(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMacEnc failed"); + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + return HandleDTLSDecryptFailed(ssl); + } + #endif /* WOLFSSL_DTLS */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR); + return DECRYPT_ERROR; + } + ssl->keys->encryptSz = ssl->curSize; + } +#endif + ssl->options.processReply = decryptMessage; + FALL_THROUGH; + + /* decrypt message */ + case decryptMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0u && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != (byte)change_cipher_spec)) + { + bufferStatic* in = &ssl->buffers.inputBuffer; + + ret = SanityCheckCipherText(ssl, ssl->curSize); + if (ret < 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return ret; + } + + if (atomicUser) { + } + else { + if (!ssl->options.tls1_3) { + #ifndef WOLFSSL_NO_TLS12 + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + ret = DecryptTls(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize - (word16)digestSz); + if (ret == 0) { + byte invalid = 0; + byte padding = (byte)-1; + word32 i; + word32 off = in->idx + ssl->curSize - digestSz - 1; + + /* Last of padding bytes - indicates length. */ + ssl->keys->padSz = in->buffer[off]; + /* Constant time checking of padding - don't leak + * the length of the data. + */ + /* Compare max pad bytes or at most data + pad. */ + for (i = 1; i < MAX_PAD_SIZE && off >= i; i++) { + /* Mask on indicates this is expected to be a + * padding byte. + */ + padding &= ctMaskLTE(i, ssl->keys->padSz); + /* When this is a padding byte and not equal + * to length then mask is set. + */ + invalid |= padding & + ctMaskNotEq(in->buffer[off - i], + ssl->keys->padSz); + } + /* If mask is set then there was an error. */ + if (invalid) { + ret = DECRYPT_ERROR; + } + ssl->keys->padSz += 1; + ssl->keys->decryptedCur = 1; + } + } + else + #endif + { + Aes *aes; + byte *key; + byte *iv; + + aes = (Aes*)XMALLOC(sizeof(Aes), ssl->heap, + DYNAMIC_TYPE_CIPHER); + if (aes == NULL) { + return MEMORY_E; + } + + if (wc_AesInit(aes, ssl->heap, INVALID_DEVID) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + + /*If server side this should be keys->client_write_key*/ + key = ssl->keys->keys + WC_MAX_DIGEST_SIZE + + WC_MAX_DIGEST_SIZE + MAX_SYM_KEY_SIZE; + iv = key + MAX_SYM_KEY_SIZE + MAX_WRITE_IV_SZ; + + ret = wc_AesSetKey(aes, key, AES_128_KEY_SIZE, iv, + AES_DECRYPTION); + if (ret != 0) { + XFREE(aes, ssl->heap, DYNAMIC_TYPE_CIPHER); + return ret; + } + + ret = wc_AesCbcDecrypt(aes, + in->buffer + in->idx, in->buffer + in->idx, + ssl->curSize); + XMEMCPY(iv, aes->reg, AES_BLOCK_SIZE); + wc_AesFree(aes); + XFREE(aes, ssl->heap, DYNAMIC_TYPE_CIPHER); + } + #else + ret = DECRYPT_ERROR; + #endif + } + else + { + #ifdef WOLFSSL_TLS13 + byte *aad = (byte*)&ssl->curRL; + word16 aad_size = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + /* aad now points to the record header */ + aad = ssl->dtls13CurRL; + aad_size = ssl->dtls13CurRlLength; + } + #endif /* WOLFSSL_DTLS13 */ + /* Don't send an alert for DTLS. We will just drop it + * silently later. */ + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, + aad, aad_size); + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + (void)in; + } + + if (ret >= 0) { + #ifndef WOLFSSL_NO_TLS12 + /* handle success */ + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->options.tls1_1 && + ssl->specs.cipher_type == (byte)block) + ssl->buffers.inputBuffer.idx += ssl->specs.block_size; + #endif + /* go past TLSv1.1 IV */ + if (CipherHasExpIV(ssl)) + ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + #endif + } + else { + WOLFSSL_MSG("Decrypt failed"); + SendAlert(ssl, alert_fatal, bad_record_mac); + /* Push error once we know that we will error out here */ + WOLFSSL_ERROR(ret); + return ret; + } + } + + ssl->options.processReply = verifyMessage; + FALL_THROUGH; + + /* verify digest of message */ + case verifyMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0u && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != (byte)change_cipher_spec)) + { + if (!atomicUser +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + && !ssl->options.startedETMRead +#endif + ) { + ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type, + &ssl->keys->padSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + #if defined(WOLFSSL_EXTRA_ALERTS) && \ + !defined(WOLFSSL_NO_ETM_ALERT) + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR); + return DECRYPT_ERROR; + } + } + + ssl->keys->encryptSz = ssl->curSize; + ssl->keys->decryptedCur = 1; + } + + ssl->options.processReply = runProcessingOneRecord; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneRecord: + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + case runProcessingOneMessage: + /* can't process a message if we have no data. */ + if (ssl->buffers.inputBuffer.idx + >= ssl->buffers.inputBuffer.length) { + return BUFFER_ERROR; + } + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) { + /* For TLS v1.1 the block size and explicit IV are added to idx, + * so it needs to be included in this limit check */ + if ((ssl->curSize - ssl->keys->padSz - + (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) - + MacSize(ssl) > MAX_PLAINTEXT_SZ) +#ifdef WOLFSSL_ASYNC_CRYPT + && ssl->buffers.inputBuffer.length != + ssl->buffers.inputBuffer.idx +#endif + ) { + WOLFSSL_MSG("Plaintext too long - Encrypt-Then-MAC"); + #if defined(WOLFSSL_EXTRA_ALERTS) && !defined(WOLFSSL_NO_ETM_ALERT) + SendAlert(ssl, alert_fatal, record_overflow); + #endif + WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR); + return BUFFER_ERROR; + } + } + else + #endif + /* TLS13 plaintext limit is checked earlier before decryption */ + /* For TLS v1.1 the block size and explicit IV are added to idx, + * so it needs to be included in this limit check */ + if (!IsAtLeastTLSv1_3(ssl->version) + && ssl->curSize - ssl->keys->padSz - + (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) + > MAX_PLAINTEXT_SZ +#ifdef WOLFSSL_ASYNC_CRYPT + && ssl->buffers.inputBuffer.length != + ssl->buffers.inputBuffer.idx +#endif + ) { + WOLFSSL_MSG("Plaintext too long"); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); +#endif + WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR); + return BUFFER_ERROR; + } + + WOLFSSL_MSG("received record layer msg"); + + switch (ssl->curRL.type) { + case handshake : + WOLFSSL_MSG("got HANDSHAKE"); + if (!IsAtLeastTLSv1_3(ssl->version) +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12) + || !TLSv1_3_Capable(ssl) +#endif + ) { +#ifndef WOLFSSL_NO_TLS12 + ret = DoHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); + if (ret != 0) { + if (SendFatalAlertOnly(ssl, ret) == SOCKET_ERROR_E) + ret = SOCKET_ERROR_E; + } +#else + ret = BUFFER_ERROR; +#endif + } + else { +#ifdef WOLFSSL_TLS13 + ssl->msgsReceived.got_change_cipher = 0; + ret = DoTls13HandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); + #ifdef WOLFSSL_EARLY_DATA + if (ret != 0) + return ret; + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData > early_data_ext && + ssl->options.handShakeState == HANDSHAKE_DONE) { + ssl->earlyData = no_early_data; + ssl->options.processReply = doProcessInit; + return ZERO_RETURN; + } + #endif +#else + ret = BUFFER_ERROR; +#endif + } + if (ret != 0 +#ifdef WOLFSSL_DTLS + /* DoDtlsHandShakeMsg can return a WANT_WRITE when + * calling DtlsMsgPoolSend. This msg is done + * processing so let's move on. */ + && (!ssl->options.dtls + || ret != WANT_WRITE) +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + /* In async case, on pending, move onto next message. + * Current message should have been DtlsMsgStore'ed and + * should be processed with DtlsMsgDrain */ + && (!ssl->options.dtls + || ret != WC_PENDING_E) +#endif + ) { + WOLFSSL_ERROR(ret); + return ret; + } + break; + + case change_cipher_spec: + WOLFSSL_MSG("got CHANGE CIPHER SPEC"); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ChangeCipher"); + /* add record header back on info */ + if (ssl->toInfoOn) { + ret = AddPacketInfo(ssl, "ChangeCipher", + change_cipher_spec, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + 1, READ_PROTO, RECORD_HEADER_SZ, ssl->heap); + if (ret != 0) + return ret; + #ifdef WOLFSSL_CALLBACKS + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif + } + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + word32 i = ssl->buffers.inputBuffer.idx; + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + if (ssl->curSize != 1 || + ssl->buffers.inputBuffer.buffer[i] != 1) { + SendAlert(ssl, alert_fatal, illegal_parameter); + WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + ssl->buffers.inputBuffer.idx++; + if (!ssl->msgsReceived.got_change_cipher) { + ssl->msgsReceived.got_change_cipher = 1; + } + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + break; + } +#endif + +#ifndef WOLFSSL_NO_TLS12 + if (ssl->buffers.inputBuffer.idx >= + ssl->buffers.inputBuffer.length || + ssl->curSize < 1u) { + WOLFSSL_MSG("ChangeCipher msg too short"); + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } + if (ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx] != 1u) { + WOLFSSL_MSG("ChangeCipher msg wrong value"); + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } + + if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) { +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != + wolfssl_chacha) + ssl->curSize -= AESGCM_EXP_IV_SZ; + ssl->buffers.inputBuffer.idx += + ssl->specs.aead_mac_size; + ssl->curSize -= ssl->specs.aead_mac_size; + } + else +#endif + { + ssl->buffers.inputBuffer.idx += ssl->keys->padSz; + ssl->curSize -= (word16)ssl->keys->padSz; + #ifdef HAVE_CHACHA + ssl->curSize -= CHACHA20_IV_SIZE; + #else + ssl->curSize -= AES_IV_SIZE; + #endif + } + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + ssl->buffers.inputBuffer.idx += digestSz; + ssl->curSize -= (word16)digestSz; + } + #endif + } + + if (ssl->curSize != 1u) { + WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg"); + WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR); + return LENGTH_ERROR; + } + + ssl->buffers.inputBuffer.idx++; + + #ifndef WOLFSSL_NO_SANITY_CHECK_HANDSHAKE + ret = SanityCheckMsgReceived(ssl, change_cipher_hs); + if (ret != 0) { + return ret; + } + #endif + + ssl->keys->encryptionOn = 1; + + ssl->decryptSetup = 1; + ssl->keys->peer_sequence_number_hi = 0; + ssl->keys->peer_sequence_number_lo = 0; + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + ssl->options.startedETMRead = ssl->options.encThenMac; + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys->peerSeq; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + peerSeq += ssl->keys->curPeerId; + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } +#endif + peerSeq->nextEpoch++; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, + DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + } + #endif + + #ifdef HAVE_LIBZ + if (ssl->options.usingCompression) + if ( (ret = InitStreams(ssl)) != 0) + return ret; + #endif + ret = BuildTlsFinished(ssl, &ssl->hsHashes->verifyHashes, + ssl->options.side == (byte)WOLFSSL_CLIENT_END ? + 1 : 0); + if (ret != 0) + return ret; +#endif /* !WOLFSSL_NO_TLS12 */ + break; + + case application_data: + WOLFSSL_MSG("got app DATA"); + if ((ret = DoApplicationData(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + NO_SNIFF)) != 0) { + WOLFSSL_ERROR(ret); + #if defined(WOLFSSL_DTLS13) || \ + defined(HAVE_SECURE_RENEGOTIATION) + /* Not really an error. We will return after cleaning + * up the processReply state. */ + if (ret != APP_DATA_READY) + #endif + return ret; + } + break; + + case alert: + WOLFSSL_MSG("got ALERT!"); + ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, &type); + if (ret == alert_fatal) + return FATAL_ERROR; + else if (ret < 0) + return ret; + + /* catch warnings that are handled as errors */ + if (type == close_notify) { + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + ssl->options.processReply = doProcessInit; + return ssl->error = ZERO_RETURN; + } + + if (type == decrypt_error) + return FATAL_ERROR; + + /* Reset error if we got an alert level in ret */ + if (ret > 0) + ret = 0; + break; + + default: + WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + + ssl->options.processReply = doProcessInit; + + /* input exhausted */ + if (ssl->buffers.inputBuffer.idx >= + ssl->buffers.inputBuffer.length) { + /* Shrink input buffer when we successfully finish record + * processing */ + if ((ret == 0) && ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + return ret; + } + /* more messages per record */ + else if ((ssl->buffers.inputBuffer.idx - ssl->curStartIdx) + < ssl->curSize) { + WOLFSSL_MSG("More messages in record"); + + ssl->options.processReply = runProcessingOneMessage; + + if (IsEncryptionOn(ssl, 0)) { + WOLFSSL_MSG( + "Bundled encrypted messages, remove middle pad"); + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (ssl->buffers.inputBuffer.idx >= + ssl->keys->padSz + digestSz) { + ssl->buffers.inputBuffer.idx -= + ssl->keys->padSz + digestSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + WOLFSSL_ERROR_VERBOSE(FATAL_ERROR); + return FATAL_ERROR; + } + } + else + #endif + { + if (ssl->buffers.inputBuffer.idx >= ssl->keys->padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys->padSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + WOLFSSL_ERROR_VERBOSE(FATAL_ERROR); + return FATAL_ERROR; + } + } + } + } + /* more records */ + else { + WOLFSSL_MSG("More records in input"); + } +#ifdef WOLFSSL_ASYNC_CRYPT + /* We are setup to read next message/record but we had an error + * (probably WC_PENDING_E) so return that so it can be handled + * by higher layers. */ + if (ret != 0) + return ret; +#endif +#if defined(WOLFSSL_DTLS13) || defined(HAVE_SECURE_RENEGOTIATION) + /* Signal to user that we have application data ready to read */ + if (ret == APP_DATA_READY) + return ret; +#endif + /* It is safe to shrink the input buffer here now. local vars will + * be reset to the new starting value. */ + if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + continue; + default: + WOLFSSL_MSG("Bad process input state, programming error"); + WOLFSSL_ERROR_VERBOSE(INPUT_CASE_ERROR); + return INPUT_CASE_ERROR; + } + } +} + +#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \ + (defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)) +int SendChangeCipher(WOLFSSL* ssl) +{ + byte *output; + int sendSz = RECORD_HEADER_SZ + ENUM_LEN; + int idx = RECORD_HEADER_SZ; + int ret; + + /* are we in scr */ + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + sendSz += MAX_MSG_EXTRA; + } + /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state + * is not advanced yet */ + ssl->options.buildingMsg = 1; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = GetOutputBuffer(ssl); + + AddRecordHeader(output, 1, change_cipher_spec, ssl, CUR_ORDER); + + output[idx] = 1; /* turn it on */ + + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + byte input[ENUM_LEN]; + int inputSz = ENUM_LEN; + + input[0] = 1; /* turn it on */ + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + change_cipher_spec, 0, 0, 0, CUR_ORDER); + if (sendSz < 0) { + return sendSz; + } + } + ssl->buffers.outputBuffer.length += sendSz; + +#ifdef WOLFSSL_TLS13 + if (!ssl->options.tls1_3) +#endif + { + /* setup encrypt keys, hard set here since known */ + ssl->encryptSetup = 1; + ssl->keys->sequence_number_hi = 0; + ssl->keys->sequence_number_lo = 0; + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + ssl->options.startedETMWrite = ssl->options.encThenMac; + #endif + } + + ssl->options.buildingMsg = 0; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} +#endif + +/* Build SSL Message, encrypted */ +int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay, + int epochOrder) +{ +#ifndef WOLFSSL_NO_TLS12 + int ret; + BuildMsgArgs* args; + BuildMsgArgs lcl_args; +#endif + ALIGN16 byte staticIvBuffer[MAX_IV_SZ]; + + WOLFSSL_ENTER("BuildMessage"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + return BAD_FUNC_ARG; + } + if (sizeOnly && (output || input) ) { + return BAD_FUNC_ARG; + } + + (void)epochOrder; + +#ifndef NO_TLS +#if defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13) + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly, asyncOkay); +#else + { + args = &lcl_args; + } + + /* Reset state */ + { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + ssl->options.buildMsgState = BUILD_MSG_SIZE; + } + FALL_THROUGH; + case BUILD_MSG_SIZE: + { + args->digestSz = WC_SHA256_DIGEST_SIZE; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) + args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz); + #endif + args->sz += args->digestSz; + + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == (byte)block) { + word32 blockSz = ssl->specs.block_size; + + if (blockSz == 0u) { + WOLFSSL_MSG("Invalid block size with block cipher type"); + ERROR_OUT(BAD_STATE_E, exit_buildmsg); + } + + if (ssl->options.tls1_1) { + args->ivSz = blockSz; + args->sz += args->ivSz; + + if (args->ivSz > (byte)MAX_IV_SZ) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + args->pad = (args->sz - args->headerSz - + args->digestSz) % blockSz; + } + else + #endif + { + args->pad = (args->sz - args->headerSz) % blockSz; + } + if (args->pad != 0u) + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + #endif /* WOLFSSL_AEAD_ONLY */ + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + args->ivSz = AESGCM_EXP_IV_SZ; + + args->sz += (args->ivSz + ssl->specs.aead_mac_size - + args->digestSz); + } + #endif + + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + + if (args->ivSz > 0u) { + args->iv = &staticIvBuffer[0]; + } + + if (ssl->options.handShakeState != (byte)HANDSHAKE_DONE) { + /* use stored IV for reducing peak heap usage */ + args->iv = ssl->arrays->csRandom + RAN_LEN + RAN_LEN; + } + else { + if (ssl->rng == NULL) { + ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), + ssl->heap, DYNAMIC_TYPE_RNG); + if (ssl->rng == NULL) { + WOLFSSL_MSG("RNG Memory error"); + goto exit_buildmsg; + } + XMEMSET(ssl->rng, 0, sizeof(WC_RNG)); + ssl->options.weOwnRng = 1; + + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, + INVALID_DEVID)) != 0) { + WOLFSSL_MSG("RNG Init error"); + goto exit_buildmsg; + } + } + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \ + defined(HAVE_AEAD)) + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys->aead_exp_IV, AESGCM_EXP_IV_SZ); + } +#endif + /* move plan text data out of record headers way */ + if (ssl->buffers.outputBuffer.dynamicFlag == + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + XMEMMOVE(output + args->headerSz + args->ivSz, input, inSz); + } + + /* include mac and digest */ + args->size = (word16)(args->sz - args->headerSz); + AddRecordHeader(output, args->size, (byte)type, ssl, epochOrder); + + /* write to output */ + if (args->ivSz > 0u) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, MAX_IV_SZ)); + args->idx += min(args->ivSz, MAX_IV_SZ); + } + if (ssl->buffers.outputBuffer.dynamicFlag != + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + XMEMCPY(output + args->idx, input, inSz); + } + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + case BUILD_MSG_HASH: + { + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (type == handshake && hashOutput) { + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, + output + RECORD_HEADER_SZ + args->ivSz, + args->headerSz + inSz - RECORD_HEADER_SZ); + if (ret != 0) + goto exit_buildmsg; + } + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == (byte)block) { + word32 tmpIdx; + word32 i; + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) + tmpIdx = args->idx; + else + #endif + tmpIdx = args->idx + args->digestSz; + + for (i = 0; i <= args->pad; i++) + /* pad byte gets pad value */ + output[tmpIdx++] = (byte)args->pad; + } + #endif + + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + /* User Record Layer Callback handling */ + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type != (byte)aead + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + && !ssl->options.startedETMWrite + #endif + ) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && + ssl->specs.hash_size > args->digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac; + #else + byte hmac[WC_MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (hmac == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + #endif + + ret = ssl->hmac(ssl, hmac, + output + args->headerSz + args->ivSz, + (word32)inSz, -1, type, 0, epochOrder); + XMEMCPY(output + args->idx, hmac, args->digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else + #endif + { + ret = TLS_hmac(ssl, output + args->idx, output + + args->headerSz + args->ivSz, + (word32)inSz, -1, type, 0, epochOrder); + } + } + #endif /* WOLFSSL_AEAD_ONLY */ + if (ret != 0) + goto exit_buildmsg; + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + ret = Encrypt(ssl, output + args->headerSz, + output + args->headerSz, + (word16)(args->size - args->digestSz), + asyncOkay); + } + else + #endif + { + Aes *aes; + byte *key; + byte *iv; + + aes = (Aes*)XMALLOC(sizeof(Aes), ssl->heap, + DYNAMIC_TYPE_CIPHER); + if (aes == NULL) { + return MEMORY_E; + } + + if (wc_AesInit(aes, ssl->heap, INVALID_DEVID) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + + /* If server side this should be keys->server_write_key */ + key = ssl->keys->keys + WC_MAX_DIGEST_SIZE + + WC_MAX_DIGEST_SIZE; + iv = key + MAX_SYM_KEY_SIZE + MAX_SYM_KEY_SIZE; + + ret = wc_AesSetKey(aes, key, 16, iv, + AES_ENCRYPTION); + if (ret != 0) { + XFREE(aes, NULL, DYNAMIC_TYPE_CIPHER); + return ret; + } + + ret = wc_AesCbcEncrypt(aes, output + args->headerSz, + output + args->headerSz, args->size); + XMEMCPY(iv, aes->reg, AES_BLOCK_SIZE); + wc_AesFree(aes); + XFREE(aes, ssl->heap, DYNAMIC_TYPE_CIPHER); + } + } + + if (ret != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* Zeroize plaintext. */ + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + ForceZero(output + args->headerSz, + (word16)(args->size - args->digestSz)); + } + else + #endif + { +#ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(output + args->headerSz, (word16)args->size); +#endif + } + } + goto exit_buildmsg; + } + ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_ENCRYPTED_VERIFY_MAC: + { + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + WOLFSSL_MSG("Calculate MAC of Encrypted Data"); + + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && + ssl->specs.hash_size > args->digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac = NULL; + #else + byte hmac[WC_MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (hmac == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + #endif + + ret = ssl->hmac(ssl, hmac, output + args->headerSz, + args->ivSz + inSz + args->pad + 1, -1, type, + 0, epochOrder); + XMEMCPY(output + args->idx + args->pad + 1, hmac, + args->digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else + #endif + { + ret = ssl->hmac(ssl, output + args->idx + args->pad + 1, + output + args->headerSz, + args->ivSz + inSz + args->pad + 1, -1, type, + 0, epochOrder); + } + } + #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + } + FALL_THROUGH; + default: + break; + } + +exit_buildmsg: + + WOLFSSL_LEAVE("BuildMessage", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + #ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls && !sizeOnly) + DtlsSEQIncrement(ssl, epochOrder); + #endif + + /* return sz on success */ + if (ret == 0) { + ret = (int)args->sz; + } + else { + WOLFSSL_ERROR_VERBOSE(ret); + } + + return ret; +#endif /* !WOLFSSL_NO_TLS12 */ +#else + (void)outSz; + (void)inSz; + (void)type; + (void)hashOutput; + (void)asyncOkay; + return NOT_COMPILED_IN; +#endif /* NO_TLS */ + +} + +#ifndef WOLFSSL_NO_TLS12 + +int SendFinished(WOLFSSL* ssl) +{ + int sendSz, + finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : + FINISHED_SZ; + byte input[FINISHED_SZ + 12]; /* max */ + byte *output; + Hashes* hashes; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + + WOLFSSL_START(WC_FUNC_FINISHED_SEND); + WOLFSSL_ENTER("SendFinished"); + + /* check for available size */ + outputSz = sizeof(input) + MAX_MSG_EXTRA; + + /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state + * is not advanced yet */ + ssl->options.buildingMsg = 1; + + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = GetOutputBuffer(ssl); + AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + hashes = (Hashes*)&input[headerSz]; + ret = BuildTlsFinished(ssl, hashes, + ssl->options.side == (byte)WOLFSSL_CLIENT_END ? 0 : 1); + if (ret != 0) return ret; + +#ifdef WOLFSSL_HAVE_TLS_UNIQUE + if (ssl->options.side == WOLFSSL_CLIENT_END) { + XMEMCPY(ssl->clientFinished, + hashes, TLS_FINISHED_SZ); + ssl->clientFinished_len = TLS_FINISHED_SZ; + } + else { + XMEMCPY(ssl->serverFinished, + hashes, TLS_FINISHED_SZ); + ssl->serverFinished_len = TLS_FINISHED_SZ; + } +#endif + + sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, + handshake, 1, 0, 0, CUR_ORDER); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + if (!ssl->options.resuming) { + #ifndef WOLFSSL_NO_SESSION_RESUMPTION + SetupSession(ssl); + #endif + if (ssl->options.side == (byte)WOLFSSL_SERVER_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + ssl->options.buildingMsg = 0; + + WOLFSSL_LEAVE("SendFinished", ret); + WOLFSSL_END(WC_FUNC_FINISHED_SEND); + + return ret; +} +#endif /* WOLFSSL_NO_TLS12 */ + +int cipherExtraData(WOLFSSL* ssl) +{ + int cipherExtra; + /* Cipher data that may be added by BuildMessage */ + /* There is always an IV (expect for chacha). For AEAD ciphers, + * there is the authentication tag (aead_mac_size). For block + * ciphers we have the hash_size MAC on the message, and one + * block size for possible padding. */ + if (ssl->specs.cipher_type == (byte)aead) { + cipherExtra = ssl->specs.aead_mac_size; + /* CHACHA does not have an explicit IV. */ + if (ssl->specs.bulk_cipher_algorithm != (byte)wolfssl_chacha) { + cipherExtra += AESGCM_EXP_IV_SZ; + } + } + else { + cipherExtra = AES_IV_SIZE + ssl->specs.block_size + + WC_SHA256_DIGEST_SIZE; + } + /* Sanity check so we don't ever return negative. */ + return cipherExtra > 0 ? cipherExtra : 0; +} + +/** + * ssl_in_handshake(): + * Invoked in wolfSSL_read/wolfSSL_write to check if wolfSSL_negotiate() is + * needed in the handshake. + * + * In TLSv1.2 negotiate until the end of the handshake, unless: + * 1 in SCR and sending data or + * 2 in SCR and we have plain data ready + * Early data logic may bypass this logic in TLSv1.3 when appropriate. + */ +static int ssl_in_handshake(WOLFSSL *ssl, int send) +{ + if (ssl->options.handShakeState != (byte)HANDSHAKE_DONE) + return 1; + + if (ssl->options.side == (byte)WOLFSSL_CLIENT_END) { + if (IsAtLeastTLSv1_3(ssl->version)) + return ssl->options.connectState < (byte)FINISHED_DONE; + if (IsAtLeastTLSv1_2(ssl)) + return ssl->options.connectState < (byte)SECOND_REPLY_DONE; + return 0; + } + + return 0; +} + +int SendData(WOLFSSL* ssl, const void* data, int sz) +{ + int sent = 0, /* plainText size */ + sendSz, + ret; +#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) + int groupMsgs = 0; +#endif + + if (ssl->error == WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + || ssl->error == WC_PENDING_E + #endif + ) { + ssl->error = 0; + } + + /* don't allow write after decrypt or mac error */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) { + /* For DTLS allow these possible errors and allow the session + to continue despite them */ + { + WOLFSSL_MSG("Not allowing write after decrypt or mac error"); + return WOLFSSL_FATAL_ERROR; + } + } + + if (ssl_in_handshake(ssl, 1)) { + return BAD_FUNC_ARG; + } + + /* last time system socket output buffer was full, try again to send */ + if (ssl->buffers.outputBuffer.length > 0u + #if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) + && !groupMsgs + #endif + ) { + WOLFSSL_MSG("output buffer was full, trying to send again"); + if ( (ssl->error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + return ssl->error; + } + else { + /* advance sent to previous sent + plain size just sent */ + sent = ssl->buffers.prevSent + ssl->buffers.plainSz; + WOLFSSL_MSG("sent write buffered data"); + + if (sent > sz) { + WOLFSSL_MSG("error: write() after WANT_WRITE with short size"); + return ssl->error = BAD_FUNC_ARG; + } + } + } + + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + + for (;;) { + byte* out; + byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ + int buffSz; /* may switch on comp */ + int outputSz; + + { + buffSz = wolfSSL_GetMaxFragSize(ssl, sz - sent); + + } + + if (sent == sz) break; + + outputSz = buffSz + COMP_EXTRA + DTLS_RECORD_HEADER_SZ; + if (IsEncryptionOn(ssl, 1) || ssl->options.tls1_3) + outputSz += cipherExtraData(ssl); + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ssl->error = ret; + + /* get output buffer */ + out = GetOutputBuffer(ssl); + + if (!ssl->options.tls1_3) { + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1, CUR_ORDER); + } + else { +#ifdef WOLFSSL_TLS13 + sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); +#else + sendSz = BUFFER_ERROR; +#endif + } + if (sendSz < 0) { + return BUILD_MSG_ERROR; + } + + ssl->buffers.outputBuffer.length += sendSz; + + if ( (ssl->error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + /* store for next call if WANT_WRITE or user embedSend() that + doesn't present like WANT_WRITE */ + ssl->buffers.plainSz = buffSz; + ssl->buffers.prevSent = sent; + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + return ssl->error; + } + + sent += buffSz; + + /* only one message per attempt */ + if (ssl->options.partialWrite == 1u) { + WOLFSSL_MSG("Partial Write on, only sending one record"); + break; + } + } + + return sent; +} + +/* process input data */ +int ReceiveData(WOLFSSL* ssl, byte** output, int sz, int peek) +{ + int size; + + WOLFSSL_ENTER("ReceiveData"); + + /* reset error state */ + if (ssl->error == WANT_READ || ssl->error == WOLFSSL_ERROR_WANT_READ) { + ssl->error = 0; + } + + if (ssl->error != 0 && ssl->error != WANT_WRITE) { + WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); + return ssl->error; + } + + { + if (ssl_in_handshake(ssl, 0)) { + return BAD_FUNC_ARG; + } + } + + while (ssl->buffers.clearOutputBuffer.length == 0u) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + if (ssl->error == ZERO_RETURN) { + WOLFSSL_MSG("Zero return, no more data coming"); + return 0; /* no more data coming */ + } + if (ssl->error == SOCKET_ERROR_E) { + if (ssl->options.connReset || ssl->options.isClosed) { + WOLFSSL_MSG("Peer reset or closed, connection done"); + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + } + WOLFSSL_ERROR(ssl->error); + return ssl->error; + } + } + + size = min(sz, (int)ssl->buffers.clearOutputBuffer.length); + + if (ssl->buffers.inputBuffer.dynamicFlag == + (byte)WOLFSSL_EXTERNAL_IO_BUFFER) { + *output = ssl->buffers.clearOutputBuffer.buffer; + } + else { + XMEMCPY(*output, ssl->buffers.clearOutputBuffer.buffer, size); + } + + if (peek == 0) { + ssl->buffers.clearOutputBuffer.length -= size; + ssl->buffers.clearOutputBuffer.buffer += size; + } + + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + + WOLFSSL_LEAVE("ReceiveData()", size); + return size; +} + +static int SendAlert_ex(WOLFSSL* ssl, int severity, int type) +{ + byte input[ALERT_SIZE]; + byte *output; + int sendSz; + int ret; + int outputSz; + int dtlsExtra = 0; + + WOLFSSL_ENTER("SendAlert"); + + ssl->pendingAlert.code = type; + ssl->pendingAlert.level = severity; + + /* check for available size */ + outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra; + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) { + return ret; + } + + /* Check output buffer */ + if (ssl->buffers.outputBuffer.buffer == NULL) + return BUFFER_E; + + /* get output buffer */ + output = GetOutputBuffer(ssl); + input[0] = (byte)severity; + input[1] = (byte)type; + ssl->alert_history.last_tx.code = type; + ssl->alert_history.last_tx.level = severity; + if (severity == alert_fatal) { + ssl->options.isClosed = 1; /* Don't send close_notify */ + } + + /* send encrypted alert if encryption is on - can be a rehandshake over + * an existing encrypted channel. + * TLS 1.3 encrypts handshake packets after the ServerHello + */ + if (IsEncryptionOn(ssl, 1)) { + sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert, + 0, 0, 0, CUR_ORDER); + } + else { + { + AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER); + } + + output += RECORD_HEADER_SZ; + XMEMCPY(output, input, ALERT_SIZE); + + sendSz = RECORD_HEADER_SZ + ALERT_SIZE; + } + if (sendSz < 0) + return BUILD_MSG_ERROR; + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + ssl->pendingAlert.code = 0; + ssl->pendingAlert.level = alert_none; + + WOLFSSL_LEAVE("SendAlert", ret); + + return ret; +} + +int RetrySendAlert(WOLFSSL* ssl) +{ + int type; + int severity; + WOLFSSL_ENTER("RetrySendAlert"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + type = ssl->pendingAlert.code; + severity = ssl->pendingAlert.level; + + if (severity == alert_none) + return 0; + + ssl->pendingAlert.code = 0; + ssl->pendingAlert.level = alert_none; + + return SendAlert_ex(ssl, severity, type); +} + +/* send alert message */ +int SendAlert(WOLFSSL* ssl, int severity, int type) +{ + WOLFSSL_ENTER("SendAlert"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->pendingAlert.level != alert_none) { + int ret = RetrySendAlert(ssl); + if (ret != 0) { + if (ssl->pendingAlert.level == alert_none || + (ssl->pendingAlert.level != alert_fatal && + severity == alert_fatal)) { + /* Store current alert if pendingAlert is empty or if current + * is fatal and previous was not */ + ssl->pendingAlert.code = type; + ssl->pendingAlert.level = severity; + } + return ret; + } + } + + return SendAlert_ex(ssl, severity, type); +} + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + +#ifndef WOLFSSL_NO_TLS12 + + /* handle generation of client_hello (1) */ + int SendClientHello(WOLFSSL* ssl) + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int idSz; + int ret; + word32 extSz = 0; +#ifndef WOLFSSL_LEANPSK_STATIC + const Suites* suites; +#endif + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_NO_SESSION_RESUMPTION + idSz = 0; +#else + idSz = ssl->options.resuming ? ssl->session->sessionIDSz : 0; +#endif + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); + WOLFSSL_ENTER("SendClientHello"); + +#ifndef WOLFSSL_LEANPSK_STATIC + suites = WOLFSSL_SUITES(ssl); + + if (suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendClientHello"); + return SUITES_ERROR; + } +#endif + + length = VERSION_SZ + RAN_LEN + + (word32)idSz + ENUM_LEN + + SUITE_LEN + + COMP_LEN + ENUM_LEN; + length += 2; /* suiteSz only one cipher suite */ + +#ifdef HAVE_TLS_EXTENSIONS + /* auto populate extensions supported unless user defined */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; + extSz = 0; + ret = TLSX_GetRequestSize(ssl, client_hello, &extSz); + if (ret != 0) + return ret; + length += extSz; +#else +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) + extSz += HELLO_EXT_SZ; +#endif + if (extSz != 0u) + length += extSz + HELLO_EXT_SZ_SZ; +#endif + sendSz = (int)length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + if (ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* Set this in case CheckAvailableSize returns a WANT_WRITE so that + * state is not advanced yet */ + ssl->options.buildingMsg = 1; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = GetOutputBuffer(ssl); + + AddHeaders(output, length, client_hello, ssl); + + /* client hello, first version */ + output[idx++] = ssl->version.major; + output[idx++] = ssl->version.minor; + ssl->chVersion = ssl->version; /* store in case changed */ + + /* then random */ + if (ssl->options.connectState == (byte)CONNECT_BEGIN) { + XMEMCPY(output + idx, ssl->arrays->csRandom, RAN_LEN); + } + idx += RAN_LEN; + + /* then session id */ + output[idx++] = (byte)idSz; + +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (idSz) { + XMEMCPY(output + idx, ssl->session->sessionID, + ssl->session->sessionIDSz); + idx += ssl->session->sessionIDSz; + } +#endif + + { + /* then cipher suites */ + c16toa(2, output + idx); + idx += OPAQUE16_LEN; + output[idx] = ssl->options.cipherSuite0; idx++; + output[idx] = ssl->options.cipherSuite; idx++; + } + + /* last, compression */ + output[idx++] = COMP_LEN; + if (ssl->options.usingCompression) + output[idx++] = ZLIB_COMPRESSION; + else + output[idx++] = NO_COMPRESSION; + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = (int)idx; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + inputSz -= recordHeaderSz; + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + recordHeaderSz, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0, CUR_ORDER); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, + output + RECORD_HEADER_SZ, sendSz - RECORD_HEADER_SZ); + if (ret != 0) + return ret; + } + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + ssl->options.buildingMsg = 0; + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); + + return ret; + } + + /* Check the version in the received message is valid and set protocol + * version to use. + * + * ssl The SSL/TLS object. + * pv The protocol version from the packet. + * returns 0 on success, otherwise failure. + */ + int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) + { + byte lowerVersion, higherVersion; + + { + if (pv.major != (byte)SSLv3_MAJOR) { + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + lowerVersion = pv.minor < ssl->version.minor; + higherVersion = pv.minor > ssl->version.minor; + } + + if (higherVersion) { + WOLFSSL_MSG("Server using higher version, fatal error"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + if (lowerVersion) { + WOLFSSL_MSG("server using lower version"); +#ifndef WOLFSSL_NO_DOWNGRADE + /* Check for downgrade attack. */ + if (!ssl->options.downgrade) { + WOLFSSL_MSG("\tno downgrade allowed, fatal error"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + + if ((!ssl->options.dtls && pv.minor < ssl->options.minDowngrade) || + (ssl->options.dtls && pv.minor > ssl->options.minDowngrade)) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + + + /* Checks made - OK to downgrade. */ + ssl->version.minor = pv.minor; + switch(pv.minor) { + case TLSv1_2_MINOR: + WOLFSSL_MSG("\tdowngrading to TLSv1.2"); + break; + default: + WOLFSSL_MSG("\tbad minor version"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } +#else + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; +#endif + } + + /* check if option is set to not allow the current version + * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ +#ifndef WOLFSSL_NO_DOWNGRADE + if ( +#ifdef WOLFSSL_DTLS + !ssl->options.dtls && +#endif + ssl->options.downgrade && + ssl->options.mask > 0) { + + if (ssl->version.minor == (byte)TLSv1_2_MINOR && + (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == + WOLFSSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading"); + ssl->version.minor = TLSv1_1_MINOR; + } + + + if (ssl->version.minor == (byte)TLSv1_MINOR && + (ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == + WOLFSSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + + if (ssl->version.minor == (byte)SSLv3_MINOR && + (ssl->options.mask & WOLFSSL_OP_NO_SSLv3) == + WOLFSSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tError, option set to not allow SSLv3"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + + if (ssl->version.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); + return VERSION_ERROR; + } + } +#endif + return 0; + } + + /* handle processing of server_hello (2) */ + int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte cs0; /* cipher suite bytes 0, 1 */ + byte cs1; + ProtocolVersion pv; + byte compression; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); + WOLFSSL_ENTER("DoServerHello"); + + /* protocol version, random and session id length check */ + if ((word32)(OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN) > helloSz) + return BUFFER_ERROR; + + /* protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + + ret = CheckVersion(ssl, pv); + if (ret != 0) { + SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); + return ret; + } + + /* random */ + XMEMCPY(ssl->arrays->csRandom + RAN_LEN, input + i, RAN_LEN); + i += RAN_LEN; + + /* session id */ +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + ssl->arrays->sessionIDSz = input[i++]; + + if (ssl->arrays->sessionIDSz > ID_LEN) { + WOLFSSL_MSG("Invalid session ID size"); + ssl->arrays->sessionIDSz = 0; + return BUFFER_ERROR; + } + else if (ssl->arrays->sessionIDSz) { + if ((i - begin) + ssl->arrays->sessionIDSz > helloSz) + return BUFFER_ERROR; + + XMEMCPY(ssl->arrays->sessionID, input + i, + ssl->arrays->sessionIDSz); + i += ssl->arrays->sessionIDSz; + ssl->options.haveSessionId = 1; + } +#else + { + byte idSz = input[i]; + i += 1 + idSz; + } +#endif + + /* suite and compression */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + cs0 = input[i++]; + cs1 = input[i++]; + + ssl->options.cipherSuite0 = cs0; + ssl->options.cipherSuite = cs1; + + compression = input[i++]; + + if (compression != (byte)NO_COMPRESSION && + !ssl->options.usingCompression) { + WOLFSSL_MSG("Server forcing compression w/o support"); + WOLFSSL_ERROR_VERBOSE(COMPRESSION_ERROR); + return COMPRESSION_ERROR; + } + + if (compression != (byte)ZLIB_COMPRESSION && + ssl->options.usingCompression) { + WOLFSSL_MSG("Server refused compression, turning off"); + ssl->options.usingCompression = 0; /* turn off if server refused */ + } + + *inOutIdx = i; + +#ifdef HAVE_TLS_EXTENSIONS + if ( (i - begin) < helloSz) { + if (TLSX_SupportExtensions(ssl)) { + word16 totalExtSz; + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + server_hello, NULL))) + return ret; + + i += totalExtSz; + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + else + ssl->options.haveEMS = 0; /* If no extensions, no EMS */ +#else + { + byte pendingEMS = 0; + + if ( (i - begin) < helloSz) { + int allowExt = 0; + + if (ssl->version.major == (byte)SSLv3_MAJOR && + ssl->version.minor >= (byte)TLSv1_MINOR) { + + allowExt = 1; + } + + if (allowExt) { + word16 totalExtSz; + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + while (totalExtSz) { + word16 extId, extSz; + + if ((word32)(OPAQUE16_LEN + OPAQUE16_LEN) > totalExtSz) + return BUFFER_ERROR; + + ato16(&input[i], &extId); + i += OPAQUE16_LEN; + ato16(&input[i], &extSz); + i += OPAQUE16_LEN; + + if ((word16)OPAQUE16_LEN + (word16)OPAQUE16_LEN + extSz + > totalExtSz) + return BUFFER_ERROR; + + if (extId == (word16)HELLO_EXT_EXTMS) + pendingEMS = 1; + else + i += extSz; + + totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz; + } + + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + + if (!pendingEMS && ssl->options.haveEMS) + ssl->options.haveEMS = 0; + } +#endif + +#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) + if (ssl->secure_renegotiation == NULL || + !ssl->secure_renegotiation->enabled) { + /* If the server does not acknowledge the extension, the client + * MUST generate a fatal handshake_failure alert prior to + * terminating the connection. */ + WOLFSSL_MSG("ServerHello did not contain SCR extension"); + return SECURE_RENEGOTIATION_E; + } +#endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys->padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite && + ssl->specs.cipher_type == block) { + *inOutIdx += MacSize(ssl); + } + #endif + } + ret = CompleteServerHello(ssl); + + WOLFSSL_LEAVE("DoServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); + + return ret; + } + + int CompleteServerHello(WOLFSSL* ssl) + { + int ret; + { +#ifndef WOLFSSL_NO_SESSION_RESUMPTION + if (DSH_CheckSessionId(ssl)) { + if (SetCipherSpecs(ssl) == 0) { + XMEMCPY(ssl->arrays->masterSecret, + ssl->session->masterSecret, SECRET_LEN); + ret = DeriveTlsKeys(ssl); + /* SERVER: peer auth based on session secret. */ + ssl->options.peerAuthGood = (ret == 0); + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + + return ret; + } + else { + WOLFSSL_MSG("Unsupported cipher suite, DoServerHello"); + WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_SUITE); + return UNSUPPORTED_SUITE; + } + } + else +#endif + { + WOLFSSL_MSG("Server denied resumption attempt"); + ssl->options.resuming = 0; /* server denied resumption try */ + } + } + return SetCipherSpecs(ssl); + } + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef WOLFSSL_NO_TLS12 + +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ + word32 idx; + word32 begin; + word16 sigSz; +} DskeArgs; + +/* handle processing of server_key_exchange (12) */ +static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret = 0; + DskeArgs args[1]; + + (void)input; + (void)size; + + WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + WOLFSSL_ENTER("DoServerKeyExchange"); + + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DskeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + ssl->options.peerSigAlgo = ssl->specs.sig_algo; + ssl->options.peerHashAlgo = sha_mac; + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = (int)min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; + break; + } + #endif /* !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + +#ifdef WOLFSSL_LEANPSK + ssl->options.asyncState = TLS_ASYNC_FINALIZE; +#else + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; +#endif + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys->padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + args->idx += MacSize(ssl); + #endif + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* return index */ + *inOutIdx = args->idx; + + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dske: + + WOLFSSL_LEAVE("DoServerKeyExchange", ret); + WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + + /* Final cleanup */ + FreeKeyExchange(ssl); + + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(ret); + } + return ret; +} + +typedef struct SckeArgs { + byte* output; /* not allocated */ + byte* encSecret; + byte* input; + word32 encSz; + word32 length; + int sendSz; + int inputSz; +} SckeArgs; + + +/* handle generation client_key_exchange (16) */ +int SendClientKeyExchange(WOLFSSL* ssl) +{ + int ret = 0; + SckeArgs args[1]; + byte encSecret[MAX_PSK_ID_LEN + NULL_TERM_LEN]; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + WOLFSSL_ENTER("SendClientKeyExchange"); + + + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + /* Set this in case CheckAvailableSize returns a WANT_WRITE so that + * state is not advanced yet */ + ssl->options.buildingMsg = 1; + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + switch (ssl->specs.kea) { + #ifndef NO_PSK + case psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + args->encSz = MAX_ENCRYPT_SZ; + if (ssl->arrays->preMasterSecret == NULL) { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + ERROR_OUT(-1005, exit_scke); + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); + } + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + int psk_keySz = 0; + + byte* pms = ssl->arrays->preMasterSecret; + psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, (char*)&encSecret[0], + MAX_PSK_ID_LEN, pms + OPAQUE16_LEN + MAX_PSK_KEY_LEN + + OPAQUE16_LEN, MAX_PSK_KEY_LEN); + if (psk_keySz == 0 || + (psk_keySz > (int)MAX_PSK_KEY_LEN && + (int)psk_keySz != USE_HW_PSK)) { + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + + /* Ensure the buffer is null-terminated. */ + encSecret[MAX_PSK_ID_LEN] = '\0'; + args->encSz = (word32)XSTRLEN((char*)encSecret); + if (args->encSz > (word32)MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); + } + ssl->options.peerAuthGood = 1; + if (psk_keySz > 0) { + /* CLIENT: Pre-shared Key for peer authentication. */ + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16)psk_keySz, pms); + pms += OPAQUE16_LEN; + XMEMSET(pms, 0, psk_keySz); + pms += psk_keySz; + c16toa((word16)psk_keySz, pms); + pms += OPAQUE16_LEN; + if (psk_keySz < (int)MAX_PSK_KEY_LEN) { + XMEMMOVE((void*)pms, + (void*)(pms + (MAX_PSK_KEY_LEN - psk_keySz)), + psk_keySz); + } + ssl->arrays->preMasterSz = (psk_keySz * 2) + + (2 * OPAQUE16_LEN); + } + psk_keySz = 0; /* No further need */ + break; + } + #endif /* !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ +#ifdef WOLFSSL_LEANPSK + ssl->options.asyncState = TLS_ASYNC_FINALIZE; +#else + ssl->options.asyncState = TLS_ASYNC_DO; +#endif + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + case TLS_ASYNC_FINALIZE: + { + word32 tlsSz = 0; + word32 idx = 0; + + if (ssl->options.tls || + ssl->specs.kea == (byte)diffie_hellman_kea) { + tlsSz = 2; + } + + if (ssl->specs.kea == (byte)ecc_diffie_hellman_kea || + ssl->specs.kea == (byte)dhe_psk_kea || + ssl->specs.kea == (byte)ecdhe_psk_kea) { /* always off */ + tlsSz = 0; + } + + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = (int)(args->encSz + tlsSz + idx); + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) + goto exit_scke; + + /* get output buffer */ + args->output = GetOutputBuffer(ssl); + + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, + ssl); + + if (tlsSz) { + c16toa((word16)args->encSz, &args->output[idx]); + idx += OPAQUE16_LEN; + } + XMEMCPY(args->output + idx, encSecret, args->encSz); + idx += args->encSz; + + if (IsEncryptionOn(ssl, 1)) { + int recordHeaderSz = RECORD_HEADER_SZ; + + args->inputSz = idx - recordHeaderSz; /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(-1006, exit_scke); + } + + XMEMCPY(args->input, args->output + recordHeaderSz, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 0, CUR_ORDER); + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; /* make sure its not double free'd */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + else { + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ); + } + + if (ret != 0) { + goto exit_scke; + } + + ssl->buffers.outputBuffer.length += (word32)args->sendSz; + + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + if (ret == 0 || ret == WANT_WRITE) { + byte keyLabel[KEY_LABEL_SZ + 1] = "key expansion"; + int tmpRet = LeanPSKMakeMasterSecret(ssl, keyLabel); + if (tmpRet != 0) { + ret = tmpRet; /* save WANT_WRITE unless more serious */ + } + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + ssl->options.buildingMsg = 0; + } + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scke: + + WOLFSSL_LEAVE("SendClientKeyExchange", ret); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + +#ifndef WOLFSSL_NO_FORCE_ZERO + /* No further need for PMS */ + if (ssl->arrays->preMasterSecret != NULL) { + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } +#endif + ssl->arrays->preMasterSz = 0; + + /* Final cleanup */ + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + } + FreeKeyExchange(ssl); + + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(ret); + } + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ +#endif /* NO_WOLFSSL_CLIENT */ + + +/** + * Return the max fragment size. This is essentially the maximum + * fragment_length available. + * @param ssl WOLFSSL object containing ciphersuite information. + * @param maxFragment The amount of space we want to check is available. This + * is only the fragment length WITHOUT the (D)TLS headers. + * @return Max fragment size + */ +int wolfSSL_GetMaxFragSize(WOLFSSL* ssl, int maxFragment) +{ + (void) ssl; /* Avoid compiler warnings */ + + if (maxFragment > MAX_RECORD_SIZE) { + maxFragment = MAX_RECORD_SIZE; + } + + return maxFragment; +} + +#undef ERROR_OUT + +/* prevent multiple mutex initializations */ +static volatile WOLFSSL_GLOBAL int initRefCount = 0; +/* init ref count mutex */ +static WOLFSSL_GLOBAL wolfSSL_Mutex inits_count_mutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(inits_count_mutex); +#ifndef WOLFSSL_MUTEX_INITIALIZER +static WOLFSSL_GLOBAL int inits_count_mutex_valid = 0; +#endif + +#ifdef HAVE_ENCRYPT_THEN_MAC +/** + * Sets whether Encrypt-Then-MAC extension can be negotiated against context. + * The default value comes from context. + * + * ctx SSL/TLS context. + * set Whether to allow or not: 1 is allow and 0 is disallow. + * returns WOLFSSL_SUCCESS + */ +int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set) +{ + ssl->options.disallowEncThenMac = !set; + return WOLFSSL_SUCCESS; +} +#endif + + +/* ran array is pregenerated random data, useful to reduce peak heap usage */ +WOLFSSL* wolfSSL_new_leanpsk(WOLFSSL_METHOD* method, + byte ciphersuite0, byte ciphersuite1, unsigned char* ran, int ranSz) +{ + WOLFSSL* ssl = NULL; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_new_leanpsk"); + + ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), NULL, DYNAMIC_TYPE_SSL); + if (ssl == NULL) { + WOLFSSL_MSG_EX("ssl xmalloc failed to allocate %d bytes", + (int)sizeof(WOLFSSL)); + } + else { + ret = InitSSL_leanpsk(ssl, method, ciphersuite0, ciphersuite1, NULL); + if (ret < 0) { + WOLFSSL_MSG_EX("wolfSSL_new failed during InitSSL. err = %d", ret); + FreeSSL(ssl, ssl->heap); + ssl = NULL; + } + else if (ret == 0) { + WOLFSSL_MSG("wolfSSL_new InitSSL success"); + } + else { + /* Only success (0) or negative values should ever be seen. */ + WOLFSSL_MSG_EX("WARNING: wolfSSL_new unexpected InitSSL return" + " value = %d", ret); + } /* InitSSL check */ + } /* ssl XMALLOC success */ + + if (ssl && ssl->arrays) { + /* copy over client random */ + XMEMCPY(ssl->arrays->csRandom, ran, RAN_LEN); + XMEMCPY(ssl->arrays->csRandom + RAN_LEN + RAN_LEN, + ran + RAN_LEN, 16); /* copy over first IV */ + } + + WOLFSSL_LEAVE("wolfSSL_new InitSSL =", ret); + (void)ret; + + return ssl; +} + + +WOLFSSL_ABI +void wolfSSL_free(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_free"); + + if (ssl) { + WOLFSSL_MSG_EX("Free SSL: %p", (wc_ptr_t)ssl); +#ifndef WOLFSSL_LEANPSK_STATIC + FreeSSL(ssl, ssl->ctx->heap); +#else + FreeSSL(ssl, ssl->heap); +#endif + } + else { + WOLFSSL_MSG("Free SSL: wolfSSL_free already null"); + } + WOLFSSL_LEAVE("wolfSSL_free", 0); +} + + +static int wolfSSL_read_internal(WOLFSSL* ssl, void** data, int sz, int peek) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_read_internal"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + + if (ssl->buffers.inputBuffer.dynamicFlag != (byte)WOLFSSL_EXTERNAL_IO_BUFFER + && *data == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_QUIC + if (WOLFSSL_IS_QUIC(ssl)) { + WOLFSSL_MSG("SSL_read() on QUIC not allowed"); + return BAD_FUNC_ARG; + } +#endif +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA) + /* This additional logic is meant to simulate following openSSL behavior: + * After bidirectional SSL_shutdown complete, SSL_read returns 0 and + * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN. + * This behavior is used to know the disconnect of the underlying + * transport layer. + * + * In this logic, CBIORecv is called with a read size of 0 to check the + * transport layer status. It also returns WOLFSSL_FAILURE so that + * SSL_read does not return a positive number on failure. + */ + + /* make sure bidirectional TLS shutdown completes */ + if (ssl->error == WOLFSSL_ERROR_SYSCALL || ssl->options.shutdownDone) { + /* ask the underlying transport the connection is closed */ + if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx) == + WOLFSSL_CBIO_ERR_CONN_CLOSE) { + ssl->options.isClosed = 1; + ssl->error = WOLFSSL_ERROR_ZERO_RETURN; + } + return WOLFSSL_FAILURE; + } +#endif + +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { + WOLFSSL_MSG("Write dup side cannot read"); + return WRITE_DUP_READ_E; + } +#endif + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + + ret = ReceiveData(ssl, (byte**)data, sz, peek); + + WOLFSSL_LEAVE("wolfSSL_read_internal", ret); + + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + +WOLFSSL_ABI +int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) +{ + WOLFSSL_ENTER("wolfSSL_read"); + + return wolfSSL_read_internal(ssl, &data, sz, FALSE); +} + + +WOLFSSL_ABI +int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_write"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + + ret = SendData(ssl, data, sz); + + WOLFSSL_LEAVE("wolfSSL_write", ret); + + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + +/* does encryption and creation of TLS packet inline on buffer 'data' + * can only handle one fragment at a time */ +int wolfSSL_write_inline(WOLFSSL* ssl, const void* data, int dataSz, int maxSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_write_inline"); + + if (ssl == NULL || data == NULL || dataSz < 0) + return BAD_FUNC_ARG; + + /* only support a single TLS fragment */ + if (wolfSSL_GetMaxFragSize(ssl, dataSz) > dataSz) + return BAD_FUNC_ARG; + + if (SetOutputBuffer(ssl, (byte*)data, maxSz) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + ret = SendData(ssl, data, dataSz); + + WOLFSSL_LEAVE("wolfSSL_write_inline", ret); + + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + + +/* 'buf' is the full buffer available when reading data from the peer + * 'data' pointer gets pointed to the location of 'buf' where the data has been + * decrypted on success + * + * returns the amount of clear text data available on success and negative + * values on failure + */ +int wolfSSL_read_inline(WOLFSSL* ssl, void* buf, int bufSz, void** data, + int dataSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_read_inline"); + + #ifdef OPENSSL_EXTRA + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_READ, WOLFSSL_SUCCESS); + ssl->cbmode = SSL_CB_READ; + } + #endif + + /* ShrinkInputBuffer will reset the internal buffer back to the static + * buffer and does not zero out or free 'buf' */ + if (SetInputBuffer(ssl, (byte*)buf, bufSz) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + ret = ReceiveData(ssl, (byte**)data, dataSz, FALSE); + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + +/* WOLFSSL_SUCCESS on ok */ +WOLFSSL_ABI +int wolfSSL_shutdown(WOLFSSL* ssl) +{ + int ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_shutdown"); + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (ssl->options.quietShutdown) { + WOLFSSL_MSG("quiet shutdown, no close notify sent"); + ret = WOLFSSL_SUCCESS; + } + else { + /* try to send close notify, not an error if can't */ + if (!ssl->options.isClosed && !ssl->options.connReset && + !ssl->options.sentNotify) { + ssl->error = SendAlert(ssl, alert_warning, close_notify); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) { + ret = WOLFSSL_SUCCESS; + ssl->options.shutdownDone = 1; + } + else { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + WOLFSSL_LEAVE("wolfSSL_shutdown", ret); + return ret; + } + } + +#ifdef WOLFSSL_SHUTDOWNONCE + if (ssl->options.isClosed || ssl->options.connReset) { + /* Shutdown has already occurred. + * Caller is free to ignore this error. */ + return SSL_SHUTDOWN_ALREADY_DONE_E; + } +#endif + + /* call wolfSSL_shutdown again for bidirectional shutdown */ + if (ssl->options.sentNotify && !ssl->options.closeNotify) { + ret = ProcessReply(ssl); + if ((ret == ZERO_RETURN) || (ret == SOCKET_ERROR_E)) { + /* simulate OpenSSL behavior */ + ssl->options.shutdownDone = 1; + /* Clear error */ + ssl->error = WOLFSSL_ERROR_NONE; + ret = WOLFSSL_SUCCESS; + } else if (ret == MEMORY_E) { + ret = WOLFSSL_FATAL_ERROR; + } else if (ssl->error == WOLFSSL_ERROR_NONE) { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + } else { + WOLFSSL_ERROR(ssl->error); + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + WOLFSSL_LEAVE("wolfSSL_shutdown", ret); + + return ret; +} + + +WOLFSSL_ABI +int wolfSSL_get_error(WOLFSSL* ssl, int ret) +{ + WOLFSSL_ENTER("wolfSSL_get_error"); + + if (ret > 0) + return WOLFSSL_ERROR_NONE; + if (ssl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_LEAVE("wolfSSL_get_error", ssl->error); + + /* make sure converted types are handled in SetErrorString() too */ + if (ssl->error == WANT_READ) + return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */ + else if (ssl->error == WANT_WRITE) + return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */ + else if (ssl->error == ZERO_RETURN || ssl->options.shutdownDone) + return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ + return ssl->error; +} + +WOLFSSL_ABI +int wolfSSL_Init(void) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_Init"); + + if ((ret == WOLFSSL_SUCCESS) && (initRefCount == 0)) { + /* Initialize crypto for use with TLS connection */ + + if (wolfCrypt_Init() != 0) { + WOLFSSL_MSG("Bad wolfCrypt Init"); + ret = WC_INIT_E; + } + } + + if (ret == WOLFSSL_SUCCESS) { + initRefCount++; + } + else { + initRefCount = 1; /* Force cleanup */ + } + + if (ret != WOLFSSL_SUCCESS) { + (void)wolfSSL_Cleanup(); /* Ignore any error from cleanup */ + } + + return ret; +} + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + + /* please see note at top of README if you get an error from connect */ + WOLFSSL_ABI + int wolfSSL_connect(WOLFSSL* ssl) + { + #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \ + defined(WOLFSSL_TLS13)) + int neededState; + byte advanceState; + #endif + int ret = 0; + + (void)ret; + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl == NULL) + return BAD_FUNC_ARG; + + #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \ + defined(WOLFSSL_TLS13) + return wolfSSL_connect_TLSv13(ssl); + #else + + WOLFSSL_MSG("TLS 1.2 or lower"); + WOLFSSL_ENTER("wolfSSL_connect"); + + /* make sure this wolfSSL object has arrays and rng setup. Protects + * case where the WOLFSSL object is reused via wolfSSL_clear() */ + if ((ret = ReinitSSL_leanpsk(ssl)) != 0) { + return ret; + } + + if (ssl->options.side != (byte)WOLFSSL_CLIENT_END) { + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + advanceState = ssl->fragOffset == 0u && + (ssl->options.connectState == (byte)CONNECT_BEGIN || + ssl->options.connectState == (byte)HELLO_AGAIN || + (ssl->options.connectState >= (byte)FIRST_REPLY_DONE && + ssl->options.connectState <= (byte)FIRST_REPLY_FOURTH)); + + if (ssl->buffers.outputBuffer.length > 0u) { + ret = SendBuffered(ssl); + if (ret == 0) { + if (ssl->fragOffset == 0u && !ssl->options.buildingMsg) { + if (advanceState) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: Advanced from last " + "buffered fragment send"); + #ifdef WOLFSSL_ASYNC_IO + /* Cleanup async */ + FreeAsyncCtx(ssl, 0); + #endif + } + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN : + /* always send client hello first */ + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; + + case CLIENT_HELLO_SENT : + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + /* get response */ + WOLFSSL_MSG("Server state up to needed state."); + while (ssl->options.serverState < (byte)neededState) { + WOLFSSL_MSG("Progressing server state..."); + WOLFSSL_MSG("ProcessReply..."); + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) { + neededState = SERVER_HELLODONE_COMPLETE; + } + } + WOLFSSL_MSG("ProcessReply done."); + + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN : + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY : + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE : + if (ssl->options.certOnly) + return WOLFSSL_SUCCESS; + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST : + if (!ssl->options.resuming) { + if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: client key exchange"); + } + + ssl->options.connectState = FIRST_REPLY_SECOND; + FALL_THROUGH; + + #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) + case FIRST_REPLY_SECOND : + /* CLIENT: Fail-safe for Server Authentication. */ + if (!ssl->options.peerAuthGood) { + WOLFSSL_MSG("Server authentication did not happen"); + ssl->error = NO_PEER_VERIFY; + return WOLFSSL_FATAL_ERROR; + } + + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; + + case FIRST_REPLY_THIRD : + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: change cipher spec"); + ssl->options.connectState = FIRST_REPLY_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; + + case FIRST_REPLY_FOURTH : + if ( (ssl->error = SendFinished(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE : + /* get response */ + while (ssl->options.serverState < (byte)SERVER_FINISHED_COMPLETE) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.connectState = SECOND_REPLY_DONE; + WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; + + case SECOND_REPLY_DONE: + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + + ssl->error = 0; /* clear the error */ + + WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */ + } + +#endif /* NO_WOLFSSL_CLIENT */ + +WOLFSSL_ABI +int wolfSSL_Cleanup(void) +{ + int ret = WOLFSSL_SUCCESS; /* Only the first error will be returned */ + int release = 0; + + WOLFSSL_ENTER("wolfSSL_Cleanup"); + + if (initRefCount > 0) { + --initRefCount; + if (initRefCount == 0) + release = 1; + } + + if (!release) + return ret; + + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + if (ret == WOLFSSL_SUCCESS) + ret = WC_CLEANUP_E; + } + +#ifdef HAVE_GLOBAL_RNG +#ifndef WOLFSSL_MUTEX_INITIALIZER + if ((globalRNGMutex_valid == 1) && (wc_FreeMutex(&globalRNGMutex) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + globalRNGMutex_valid = 0; +#endif /* !WOLFSSL_MUTEX_INITIALIZER */ + + #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG) + wolfSSL_FIPS_drbg_free(gDrbgDefCtx); + gDrbgDefCtx = NULL; + #endif +#endif + +#if defined(HAVE_EX_DATA) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \ + defined(WOLFSSL_WPAS_SMALL) + crypto_ex_cb_free(crypto_ex_cb_ctx_session); + crypto_ex_cb_ctx_session = NULL; +#endif + +#ifdef WOLFSSL_MEM_FAIL_COUNT + wc_MemFailCount_Free(); +#endif + + return ret; +} + +#ifndef NO_PSK + void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) + { + WOLFSSL_ENTER("wolfSSL_set_psk_client_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_cb = cb; + } + + const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint"); + + if (ssl == NULL || ssl->arrays == NULL) + return NULL; + + return ssl->arrays->server_hint; + } + + int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) + { + WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint"); + + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FAILURE; + + if (hint == 0) + ssl->arrays->server_hint[0] = 0; + else { + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)-1); + ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0'; + } + return WOLFSSL_SUCCESS; + } + + void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl) + { + return ssl ? ssl->options.psk_ctx : NULL; + } + + int wolfSSL_set_psk_callback_ctx(WOLFSSL* ssl, void* psk_ctx) + { + if (ssl == NULL) + return WOLFSSL_FAILURE; + ssl->options.psk_ctx = psk_ctx; + return WOLFSSL_SUCCESS; + } +#endif /* NO_PSK */ + +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + int isShutdown = 0; + + WOLFSSL_ENTER("wolfSSL_get_shutdown"); + + if (ssl) { + { + /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ + if (ssl->options.sentNotify) + isShutdown |= WOLFSSL_SENT_SHUTDOWN; + if (ssl->options.closeNotify||ssl->options.connReset) + isShutdown |= WOLFSSL_RECEIVED_SHUTDOWN; + } + + } + + WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); + return isShutdown; +} + +#ifndef WOLFSSL_LEANPSK_STATIC_IO +void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) +{ + if (ssl) + ssl->IOCB_ReadCtx = rctx; +} + +void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) +{ + if (ssl) + ssl->IOCB_WriteCtx = wctx; +} +#endif + +/* sets the IO callback to use for receives at WOLFSSL level */ +void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv) +{ + if (ssl) { + ssl->CBIORecv = CBIORecv; + } +} + + +/* sets the IO callback to use for sends at WOLFSSL level */ +void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend) +{ + if (ssl) { + ssl->CBIOSend = CBIOSend; + } +} + +#endif /* !WOLFCRYPT_ONLY */ + diff --git a/mplabx/small-psk-build/psk-tls.c b/mplabx/small-psk-build/psk-tls.c new file mode 100644 index 0000000000..aab5bd2433 --- /dev/null +++ b/mplabx/small-psk-build/psk-tls.c @@ -0,0 +1,980 @@ +/* psk-tls.c + * + * Copyright (C) 2006-2024 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 + */ + + +/* combining all TLS 1.2 components needed for a bare static psk connection */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#include +#include +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + #include +#endif + +#include + +#ifndef NO_TLS + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef WOLFSSL_SHA384 + #define HSHASH_SZ WC_SHA384_DIGEST_SIZE +#else + #define HSHASH_SZ FINISHED_SZ +#endif + +int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) +{ + int ret = 0; + word32 hashSz = FINISHED_SZ; + + if (ssl == NULL || hash == NULL || hashLen == NULL || + *hashLen < (word32)HSHASH_SZ) + return BAD_FUNC_ARG; + + /* for constant timing perform these even if error */ +#ifndef NO_OLD_TLS + ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); + ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); +#endif + if (IsAtLeastTLSv1_2(ssl)) { +#ifndef NO_SHA256 + if (ssl->specs.mac_algorithm <= (byte)sha256_mac || + ssl->specs.mac_algorithm == (byte)blake2b_mac) { +#ifdef WOLFSSL_NO_HASH_COPY + ret |= wc_Sha256Final(&ssl->hsHashes->hashSha256, hash); +#else + ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); +#endif + hashSz = WC_SHA256_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + if (ssl->specs.mac_algorithm == sha384_mac) { + ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + hashSz = WC_SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SM3 + if (ssl->specs.mac_algorithm == sm3_mac) { + ret |= wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash); + hashSz = WC_SM3_DIGEST_SIZE; + } +#endif + } + + *hashLen = hashSz; +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("TLS handshake hash", hash, hashSz); +#endif + + if (ret != 0) { + ret = BUILD_MSG_ERROR; + WOLFSSL_ERROR_VERBOSE(ret); + } + + return ret; +} + + +int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, byte srvr) +{ + const byte kTlsClientFinStr[FINISHED_LABEL_SZ + 1] = "client finished"; + const byte kTlsServerFinStr[FINISHED_LABEL_SZ + 1] = "server finished"; + int ret; + const byte* side = NULL; + word32 hashSz = HSHASH_SZ; +#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH) + byte handshake_hash[HSHASH_SZ]; +#else + WC_DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); + WC_ALLOC_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); + if (handshake_hash == NULL) + return MEMORY_E; +#endif + + XMEMSET(handshake_hash, 0, HSHASH_SZ); + + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); + if (ret == 0) { + if (srvr == 0u) { + side = kTlsClientFinStr; + } + else if (srvr == 1u) { + side = kTlsServerFinStr; + } + else { + ret = BAD_FUNC_ARG; + WOLFSSL_MSG("Unexpected sender value"); + } + } + + if (ret == 0) { +#ifdef WOLFSSL_HAVE_PRF + { + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, + ssl->arrays->masterSecret, SECRET_LEN, side, + FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, + INVALID_DEVID); + PRIVATE_KEY_LOCK(); + } +#ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(handshake_hash, hashSz); +#endif +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_ERROR_VERBOSE(ret); + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)side; + (void)hashes; +#endif + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + WC_FREE_VAR(handshake_hash, ssl->heap); +#elif defined(WOLFSSL_CHECK_MEM_ZERO) + wc_MemZero_Check(handshake_hash, HSHASH_SZ); +#endif + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef WOLFSSL_NO_TLS12 + +ProtocolVersion MakeTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_2_MINOR; + + return pv; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 +/* The TLS v1.3 protocol version. + * + * returns the protocol version data for TLS v1.3. + */ +ProtocolVersion MakeTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + + return pv; +} +#endif + + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_EXTENDED_MASTER +static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = + "extended master secret"; +#endif + +#ifdef HAVE_EXTENDED_MASTER + +static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* sHash, word32 sHashLen, + int tls1_2, int hash_type, + void* heap, int devId) +{ + int ret; + +#ifdef WOLFSSL_HAVE_PRF + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, + EXT_MASTER_LABEL_SZ, sHash, sHashLen, tls1_2, hash_type, heap, devId); + PRIVATE_KEY_LOCK(); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)sHash; + (void)sHashLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + return ret; +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* sHash, word32 sHashLen, + int tls1_2, int hash_type) +{ + return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen, + tls1_2, hash_type, NULL, INVALID_DEVID); +} + +#endif /* HAVE_EXTENDED_MASTER */ + + +int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, + int verify) +{ + if (ssl == NULL || inner == NULL) + return BAD_FUNC_ARG; + + XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ); + + WriteSEQ(ssl, verify, inner); + inner[SEQ_SZ] = (byte)content; + inner[SEQ_SZ + ENUM_LEN] = ssl->version.major; + inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor; + c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ); + + return 0; +} + + +#ifndef WOLFSSL_AEAD_ONLY +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + + +#ifdef NO_HASH_WRAPPER +/* SHA256 only small code build without HASH wrappers. + * Finalize the HMAC by performing outer hash. + * + * hmac HMAC object. + * mac MAC result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) +{ + int ret = BAD_FUNC_ARG; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha256 *hash = NULL; +#else + wc_Sha256 hash[1]; +#endif + enum wc_HashType hashType = (enum wc_HashType)hmac->macType; + word32 digestSz = WC_SHA256_DIGEST_SIZE; + word32 blockSz = WC_SHA256_BLOCK_SIZE; + + if (hashType != WC_HASH_TYPE_SHA256) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, DYNAMIC_TYPE_HASH_TMP); + if (hash == NULL) { + return MEMORY_E; + } +#endif + + if ((digestSz >= 0u) && (blockSz >= 0u)) { + ret = wc_InitSha256(hash); + } + if (ret == 0) { + ret = wc_Sha256Update(hash, (byte*)hmac->opad, + blockSz); + if (ret == 0) + ret = wc_Sha256Update(hash, (byte*)hmac->innerHash, + digestSz); + if (ret == 0) + ret = wc_Sha256Final(hash, mac); + wc_Sha256Free(hash); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASH_TMP); +#endif + return ret; +} +#else +/* Finalize the HMAC by performing outer hash. + * + * hmac HMAC object. + * mac MAC result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) +{ + int ret = BAD_FUNC_ARG; +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg *hash = NULL; +#else + wc_HashAlg hash[1]; +#endif + enum wc_HashType hashType = (enum wc_HashType)hmac->macType; + int digestSz = wc_HashGetDigestSize(hashType); + int blockSz = wc_HashGetBlockSize(hashType); + +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, + DYNAMIC_TYPE_HASH_TMP); + if (hash == NULL) { + return MEMORY_E; + } +#endif + + if ((digestSz >= 0) && (blockSz >= 0)) { + ret = wc_HashInit(hash, hashType); + } + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad, + (word32)blockSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash, + (word32)digestSz); + if (ret == 0) + ret = wc_HashFinal(hash, hashType, mac); + wc_HashFree(hash, hashType); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASH_TMP); +#endif + return ret; +} +#endif + +/* Calculate the HMAC of the header + message data. + * Constant time implementation using wc_Sha*FinalRaw(). + * + * hmac HMAC object. + * digest MAC result. + * in Message data. + * sz Size of the message data. + * header Constructed record header with length of handshake data. + * returns 0 on success, otherwise failure. + */ +static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, + word32 sz, int macLen, byte* header) +{ + byte lenBytes[8]; + int i, j; + unsigned int k; + int blockBits, blockMask; + int lastBlockLen, extraLen, eocIndex; + int blocks, safeBlocks, lenBlock, eocBlock; + unsigned int maxLen; + int blockSz, padSz; + int ret; + word32 realLen; + byte extraBlock; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + blockSz = WC_SHA_BLOCK_SIZE; + blockBits = 6; + padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1; + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + blockSz = WC_SHA256_BLOCK_SIZE; + blockBits = 6; + padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + blockSz = WC_SHA384_BLOCK_SIZE; + blockBits = 7; + padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + blockSz = WC_SHA512_BLOCK_SIZE; + blockBits = 7; + padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef WOLFSSL_SM3 + case WC_SM3: + blockSz = WC_SM3_BLOCK_SIZE; + blockBits = 6; + padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SM3 */ + + default: + return BAD_FUNC_ARG; + } + blockMask = blockSz - 1; + + /* Size of data to HMAC if padding length byte is zero. */ + maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - (unsigned int)macLen; + /* Complete data (including padding) has block for EOC and/or length. */ + extraBlock = (byte)ctSetLTE((maxLen + (unsigned int)padSz) & blockMask, + padSz); + /* Total number of blocks for data including padding. */ + blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock; + /* Up to last 6 blocks can be hashed safely. */ + safeBlocks = blocks - 6; + + if (sz < 1U) + return BAD_FUNC_ARG; + + /* Length of message data. */ + realLen = maxLen - in[sz - 1]; + /* Number of message bytes in last block. */ + lastBlockLen = realLen & blockMask; + /* Number of padding bytes in last block. */ + extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1; + /* Number of blocks to create for hash. */ + lenBlock = (realLen + extraLen) >> blockBits; + /* Block containing EOC byte. */ + eocBlock = realLen >> blockBits; + /* Index of EOC byte in block. */ + eocIndex = realLen & blockMask; + + /* Add length of hmac's ipad to total length. */ + realLen += blockSz; + /* Length as bits - 8 bytes bigendian. */ + c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes); + c32toa(realLen << 3, lenBytes + sizeof(word32)); + + ret = wc_Sha256Update(&hmac->hash.sha256, (unsigned char*)hmac->ipad, + (word32)blockSz); + if (ret != 0) + return ret; + + XMEMSET(hmac->innerHash, 0, macLen); + + if (safeBlocks > 0) { + ret = wc_Sha256Update(&hmac->hash.sha256, header, + WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + ret = wc_Sha256Update(&hmac->hash.sha256, in, safeBlocks * blockSz - + WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + } + else + safeBlocks = 0; + + XMEMSET(digest, 0, macLen); + k = (unsigned int)(safeBlocks * blockSz); + for (i = safeBlocks; i < blocks; i++) { +#ifdef WOLFSSL_SMALL_STACK + unsigned char* hashBlock; +#else + unsigned char hashBlock[WC_MAX_BLOCK_SIZE]; +#endif + unsigned char isEocBlock = ctMaskEq(i, eocBlock); + unsigned char isOutBlock = ctMaskEq(i, lenBlock); + +#ifdef WOLFSSL_SMALL_STACK + hashBlock = (unsigned char*)XMALLOC(WC_MAX_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_HMAC); + if (hashBlock == NULL) + return MEMORY_E; +#endif + + for (j = 0; j < blockSz; j++) { + unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock; + unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock; + unsigned char b = 0; + + if (k < (unsigned int)WOLFSSL_TLS_HMAC_INNER_SZ) + b = header[k]; + else if (k < maxLen) + b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ]; + k++; + + b = ctMaskSel(atEoc, 0x80, b); + b &= (unsigned char)~(word32)pastEoc; + b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock; + + if (j >= blockSz - 8) { + b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b); + } + + hashBlock[j] = b; + } + + ret = wc_Sha256Update(&hmac->hash.sha256, hashBlock, (word32)blockSz); + if (ret != 0) + return ret; + ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hashBlock); + if (ret != 0) + return ret; + for (j = 0; j < macLen; j++) + ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock; +#ifdef WOLFSSL_SMALL_STACK + XFREE(hashBlock, NULL, DYNAMIC_TYPE_HMAC); +#endif + } + + ret = Hmac_OuterHash(hmac, digest); + + return ret; +} + +#endif + +int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, + int content, int verify, int epochOrder) +{ +#ifdef WOLFSSL_SMALL_STACK + Hmac* hmac = NULL; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; +#else + Hmac hmac[1]; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; +#endif + int ret = 0; + const byte* macSecret = NULL; +#ifdef WOLFSSL_LEANPSK_STATIC + byte hashSz = 0; +#else + word32 hashSz = 0; +#endif + + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC); + if (hmac == NULL) + return MEMORY_E; +#endif + +#ifdef HAVE_TRUNCATED_HMAC + hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + hashSz = ssl->specs.hash_size; +#endif + + wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); + ret = wc_HmacInit(hmac, ssl->heap,INVALID_DEVID); + if (ret != 0) + return ret; + + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + macSecret = wolfSSL_GetDtlsMacSecret(ssl, verify, epochOrder); + else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#elif defined(WOLFSSL_LEANPSK) && defined(NO_WOLFSSL_SERVER) + if (verify) { + macSecret = (const byte*)(ssl->keys->keys + WC_MAX_DIGEST_SIZE); + } + else + { + macSecret = (const byte*)ssl->keys->keys; + } +#else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#endif + ret = wc_HmacSetKey(hmac, WC_SHA256, macSecret, ssl->specs.hash_size); + + if (ret == 0) { + /* Constant time verification required. */ + if (verify && padSz >= 0) { +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + { + ret = Hmac_UpdateFinal_CT(hmac, digest, in, + sz + hashSz + padSz + 1, hashSz, myInner); + } +#else + ret = Hmac_UpdateFinal(hmac, digest, in, sz + hashSz + padSz + 1, + myInner); +#endif + } + else { + ret = wc_HmacUpdate (hmac, myInner, WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret == 0) + ret = wc_HmacUpdate(hmac, in, sz); /* content */ + if (ret == 0) + ret = wc_HmacFinal(hmac, digest); + } + } + + wc_HmacFree(hmac); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC); +#endif + return ret; +} +#endif /* WOLFSSL_AEAD_ONLY */ + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef NO_WOLFSSL_CLIENT + +#ifndef WOLFSSL_NO_TLS12 + WOLFSSL_ABI + WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) + { + return wolfTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_2()); + return method; + } +#endif /* WOLFSSL_NO_TLS12 */ + +#endif /* NO_WOLFSSL_CLIENT */ + +#endif /* NO_TLS */ + +#endif /* WOLFCRYPT_ONLY */ + + +int SetCipherSpecs(WOLFSSL* ssl) +{ + int ret = GetCipherSpec(ssl->options.side, ssl->options.cipherSuite0, + ssl->options.cipherSuite, &ssl->specs, + &ssl->options); + if (ret == 0) { + /* set TLS if it hasn't been turned off */ + if (ssl->version.major == (byte)SSLv3_MAJOR && + ssl->version.minor >= (byte)TLSv1_MINOR) { + #ifndef NO_TLS + ssl->options.tls = 1; + if (ssl->version.minor >= (byte)TLSv1_1_MINOR) { + ssl->options.tls1_1 = 1; + if (ssl->version.minor >= (byte)TLSv1_3_MINOR) + ssl->options.tls1_3 = 1; + } + #endif + } + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block) + ssl->options.encThenMac = 0; + #endif + + } + return ret; +} + +/** + * Populate specs with the specification of the chosen ciphersuite. If opts is + * not NULL then the appropriate options will also be set. + * + * @param side [in] WOLFSSL_SERVER_END or WOLFSSL_CLIENT_END + * @param cipherSuite0 [in] + * @param cipherSuite [in] + * @param specs [out] CipherSpecs + * @param opts [in/out] Options can be NULL + * @return + */ +int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, + CipherSpecs* specs, Options* opts) +{ + word16 havePSK = 0; + (void)havePSK; + (void)side; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (opts != NULL) + havePSK = opts->havePSK; +#endif + if (cipherSuite != TLS_PSK_WITH_AES_128_CBC_SHA256) + return UNSUPPORTED_SUITE; + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->block_size = AES_BLOCK_SIZE; + + if (opts != NULL) + opts->usingPSK_cipher = 1; +#endif + + if (specs->sig_algo == anonymous_sa_algo && opts != NULL) { + /* CLIENT/SERVER: No peer authentication to be performed. */ + opts->peerAuthGood = 1; + } + + return 0; +} + + +enum KeyStuff { + MASTER_ROUNDS = 3, + PREFIX = 3, /* up to three letters for master prefix */ + KEY_PREFIX = 9 /* up to 9 prefix letters for key rounds */ + + +}; + + +/* Master wrapper, doesn't use SSL stack space in TLS mode */ +int LeanPSKMakeMasterSecret(WOLFSSL* ssl, byte* keyLabel) +{ + /* append secret to premaster : premaster | SerSi | CliSi */ + int ret = 0; + { + byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF_TLS(ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + master_label, MASTER_LABEL_SZ, ssl->arrays->csRandom, SEED_LEN, + 1, ssl->specs.mac_algorithm, ssl->heap, INVALID_DEVID); + PRIVATE_KEY_LOCK(); + } + + if (ret == 0) { + int key_dig_len = 2 * ssl->specs.hash_size + + 2 * AES_128_KEY_SIZE + + 2 * AES_IV_SIZE; + byte seed[SEED_LEN]; + + XMEMCPY(seed, ssl->arrays->csRandom + RAN_LEN, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->csRandom, RAN_LEN); + + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF_TLS(ssl->keys->keys, key_dig_len, + ssl->arrays->masterSecret, SECRET_LEN, keyLabel, + KEY_LABEL_SZ, (const byte*)seed, SEED_LEN, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, + INVALID_DEVID); + PRIVATE_KEY_LOCK(); + } + + return ret; +} + + +#ifndef NO_KDF + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include +#ifdef WC_SRTP_KDF +#include +#endif + +#if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) + +/* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */ +/* In TLS 1.2 case call straight thru to wc_PRF */ +int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, + const byte* label, word32 labLen, const byte* seed, word32 seedLen, + int useAtLeastSha256, int hash_type, void* heap, int devId) +{ + int ret = 0; + byte times; + byte lastLen; + byte lastTime; + +#ifdef WOLFSSL_SMALL_STACK + byte* current; + byte previous[WC_SHA256_DIGEST_SIZE]; /* max size */ + Hmac* hmac; +#else + byte previous[WC_SHA256_DIGEST_SIZE]; /* max size */ + byte current[WC_SHA256_DIGEST_SIZE]; /* max size */ + Hmac hmac[1]; +#endif + + if (useAtLeastSha256) { + #ifdef WOLFSSL_SMALL_STACK + byte* labelSeed; + #else + byte labelSeed[MAX_PRF_LABSEED]; + #endif + + if (labLen + seedLen > (word32)MAX_PRF_LABSEED) { + return BUFFER_E; + } + + #ifdef WOLFSSL_SMALL_STACK + labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, DYNAMIC_TYPE_DIGEST); + if (labelSeed == NULL) { + return MEMORY_E; + } + #endif + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + /* If a cipher suite wants an algorithm better than sha256, it + * should use better. */ + if (hash_type < sha256_mac || hash_type == blake2b_mac) { + hash_type = sha256_mac; + } + + times = digLen / WC_SHA256_DIGEST_SIZE; + lastLen = digLen % WC_SHA256_DIGEST_SIZE; + + if (lastLen) + times += 1; + + + /* times == 0 if resLen == 0, but times == 0 abides clang static + analyzer while resLen == 0 doesn't */ + if (times == 0U) + return BAD_FUNC_ARG; + + lastTime = times - 1U; + + #ifdef WOLFSSL_SMALL_STACK + current = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, heap, + DYNAMIC_TYPE_DIGEST); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); + if (hmac == NULL || current == NULL) { + if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); + return MEMORY_E; + } + #endif + #ifdef WOLFSSL_CHECK_MEM_ZERO + XMEMSET(previous, 0xff, P_HASH_MAX_SIZE); + wc_MemZero_Add("wc_PRF previous", previous, P_HASH_MAX_SIZE); + wc_MemZero_Add("wc_PRF current", current, P_HASH_MAX_SIZE); + wc_MemZero_Add("wc_PRF hmac", hmac, sizeof(Hmac)); + #endif + + ret = wc_HmacInit(hmac, heap, devId); + if (ret == 0) { + ret = wc_HmacSetKey(hmac, WC_SHA256, secret, secLen); + if (ret == 0) { + /* A0 = seed */ + ret = wc_HmacUpdate(hmac, labelSeed, labLen + seedLen); + } + if (ret == 0) { + ret = wc_HmacFinal(hmac, previous); /* A1 */ + } + if (ret == 0) { + byte i; + word32 idx = 0; + + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, WC_SHA256_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, labelSeed, labLen + seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&digest[idx], current, + min(lastLen, WC_SHA256_DIGEST_SIZE)); + else { + XMEMCPY(&digest[idx], current, WC_SHA256_DIGEST_SIZE); + idx += WC_SHA256_DIGEST_SIZE; + ret = wc_HmacUpdate(hmac, previous, + WC_SHA256_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, previous); + if (ret != 0) + break; + } + } + } + wc_HmacFree(hmac); + } + + + #ifndef WOLFSSL_NO_FORCE_ZERO + ForceZero(previous, WC_SHA256_DIGEST_SIZE); + ForceZero(current, WC_SHA256_DIGEST_SIZE); + ForceZero(hmac, sizeof(Hmac)); + #endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); + #endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(labelSeed, NULL, DYNAMIC_TYPE_DIGEST); + #endif +#define WOLFSSL_SMALL_STACK + } + else { + ret = BAD_FUNC_ARG; + } + + return ret; +} +#endif /* WOLFSSL_HAVE_PRF && !NO_HMAC */ + +#endif /* NO_KDF */ + diff --git a/mplabx/small-psk-build/setup.sh b/mplabx/small-psk-build/setup.sh new file mode 100644 index 0000000000..97f1ed4e76 --- /dev/null +++ b/mplabx/small-psk-build/setup.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +cp -r ../../wolfssl ../../../tls/ +cp psk-tls.c ../../../tls/ +cp psk-ssl.c ../../../tls/ +cp user_settings.h ../../../tls/ +cp ../../wolfcrypt/src/random.c ../../../tls/ +cp ../../wolfcrypt/src/aes.c ../../../tls/ +cp ../../wolfcrypt/src/hmac.c ../../../tls/ +cp ../../wolfcrypt/src/sha256.c ../../../tls/ +cp ../../wolfcrypt/src/misc.c ../../../tls/ + diff --git a/mplabx/small-psk-build/user_settings.h b/mplabx/small-psk-build/user_settings.h new file mode 100644 index 0000000000..3816b5814a --- /dev/null +++ b/mplabx/small-psk-build/user_settings.h @@ -0,0 +1,357 @@ +/* Example custom user settings for wolfSSL */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------------- */ +/* Platform */ +/* ------------------------------------------------------------------------- */ +#undef WOLFSSL_GENERAL_ALIGNMENT +#define WOLFSSL_GENERAL_ALIGNMENT 4 + +#undef SINGLE_THREADED +#define SINGLE_THREADED + +#undef NO_BIG_INT +#define NO_BIG_INT + +/* remove code around sockets and use IO callbacks instead */ +#undef WOLFSSL_NO_SOCK +#define WOLFSSL_NO_SOCK + +#undef WOLFSSL_USER_IO +#define WOLFSSL_USER_IO + +/* Build settings specific for use with MCC18 */ +#ifdef __18CXX + + /* 8 bit Micro, reusing some of the setting from 16 bit Micro */ + #undef WC_16BIT_CPU + #define WC_16BIT_CPU + + #define SIZEOF_LONG_LONG 4 + #define SIZEOF_LONG 4 + + /* pushing some large buffers to 'rom' */ + #undef WOLFSSL_USE_FLASHMEM + #define WOLFSSL_USE_FLASHMEM +#endif + +#define NO_WOLFSSL_DIR + +/* ------------------------------------------------------------------------- */ +/* Crypto */ +/* ------------------------------------------------------------------------- */ + +/* AES Configuration */ +#undef NO_AES +#if 1 + #undef WOLFSSL_AES_SMALL_TABLES + #define WOLFSSL_AES_SMALL_TABLES + + #undef AES_MAX_KEY_SIZE + #define AES_MAX_KEY_SIZE 128 + + #undef NO_AES_192 + #define NO_AES_192 + + #undef NO_AES_256 + #define NO_AES_256 + + #undef HAVE_AES_DECRYPT + #define HAVE_AES_DECRYPT + + #undef HAVE_AESGCM + #undef HAVE_AESCCM + #undef WOLFSSL_AES_COUNTER + #undef WOLFSSL_AES_DIRECT +#else + #define NO_AES +#endif + +/* No public/private key support, just static PSK */ +#undef WOLFSSL_STATIC_PSK +#define WOLFSSL_STATIC_PSK + +#undef NO_DES3 +#define NO_DES3 + +#undef HAVE_CURVE25519 +#undef HAVE_ED25519 +#undef HAVE_ECC + +#undef NO_RSA +#define NO_RSA + +#undef NO_DSA +#define NO_DSA + +#undef NO_DH +#define NO_DH + +/* ------------------------------------------------------------------------- */ +/* Hashing */ +/* ------------------------------------------------------------------------- */ + +/* use Sha256, disable all other hashing */ +#undef NO_SHA256 + +/* Uses about 10 bytes less "DATA" memory */ +#undef USE_SLOW_SHA256 +#define USE_SLOW_SHA256 + +#undef NO_SHA +#define NO_SHA + +#undef WOLFSSL_SHA512 + +#undef NO_RC4 +#define NO_RC4 + +#undef NO_MD5 +#define NO_MD5 + +#undef NO_MD4 +#define NO_MD4 + +#undef NO_HASH_WRAPPER +#define NO_HASH_WRAPPER + +#undef WOLFSSL_NOSHA512_256 +#define WOLFSSL_NOSHA512_256 + +#undef WOLFSSL_NOSHA512_224 +#define WOLFSSL_NOSHA512_224 + +/* ------------------------------------------------------------------------- */ +/* Debugging */ +/* ------------------------------------------------------------------------- */ +#undef DEBUG_WOLFSSL +//#define DEBUG_WOLFSSL + +#ifdef DEBUG_WOLFSSL + /* Use this to measure / print heap usage */ + #if 0 + #undef USE_WOLFSSL_MEMORY + #define USE_WOLFSSL_MEMORY + #undef WOLFSSL_TRACK_MEMORY + #define WOLFSSL_TRACK_MEMORY + #endif +#else + #undef NO_WOLFSSL_MEMORY + //#define NO_WOLFSSL_MEMORY + + #undef NO_ERROR_STRINGS + #define NO_ERROR_STRINGS +#endif + +#undef WOLFSSL_DEBUG_ERRORS_ONLY +#define WOLFSSL_DEBUG_ERRORS_ONLY + +/* removes ability to get human readable alert strings */ +#undef NO_ALERT_STRINGS +#define NO_ALERT_STRINGS + +/* ------------------------------------------------------------------------- */ +/* Disable Features */ +/* ------------------------------------------------------------------------- */ +#undef KEEP_PEER_CERT +#undef HAVE_COMP_KEY +#undef HAVE_TLS_EXTENSIONS +#undef HAVE_SUPPORTED_CURVES +#undef WOLFSSL_BASE64_ENCODE +#undef NO_WOLFSSL_CLIENT +#undef NO_CRYPT_TEST +#undef NO_CRYPT_BENCHMARK + +#undef NO_SESSION_CACHE +#define NO_SESSION_CACHE + +#undef NO_WOLFSSL_SERVER +#define NO_WOLFSSL_SERVER + +#undef WOLFSSL_NO_CLIENT_AUTH +#define WOLFSSL_NO_CLIENT_AUTH + +#undef NO_ASN_TIME +#define NO_ASN_TIME + +/* In-lining of misc.c functions */ +/* If defined, must include wolfcrypt/src/misc.c in build */ +/* Slower, but about 1k smaller */ + +#undef NO_INLINE +#define NO_INLINE + +#undef NO_FILESYSTEM +#define NO_FILESYSTEM + +#undef NO_WRITEV +#define NO_WRITEV + +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#undef NO_OLD_TLS +#define NO_OLD_TLS + +#undef NO_PWDBASED +#define NO_PWDBASED + +#undef NO_CODING +#define NO_CODING + +#undef NO_SESSION_CACHE +#define NO_SESSION_CACHE + +#undef NO_CERTS +#define NO_CERTS + +#undef NO_ASN +#define NO_ASN + +#undef NO_CLIENT_CACHE +#define NO_CLIENT_CACHE + +#undef NO_WOLFSSL_CM_VERIFY +#define NO_WOLFSSL_CM_VERIFY + +/* ------------------------------------------------------------------------- */ +/* Fine Tuned Size Reduction */ +/* ------------------------------------------------------------------------- */ + +#undef WC_NO_CACHE_RESISTANT +#define WC_NO_CACHE_RESISTANT + +/* pre calculated sizes */ +#ifdef __18CXX + #define MAX_PSK_ID_LEN 10 +#else + /* large enough for example "Client_identity" */ + #define MAX_PSK_ID_LEN 17 +#endif +#define MAX_PSK_KEY_LEN 16u + +#undef WOLFSSL_MAX_SUITE_SZ +#define WOLFSSL_MAX_SUITE_SZ 1 + +#undef WOLFSSL_MAX_SIGALGO +#define WOLFSSL_MAX_SIGALGO 1 + +#undef MAX_PRF_DIG +#define MAX_PRF_DIG 128 + +#undef MAX_PRF_LABSEED +#define MAX_PRF_LABSEED 77 + +/* remove code with cipher suites, have a hard set PSK suite */ +#undef NO_CIPHER_SUITE_ALIASES +#define NO_CIPHER_SUITE_ALIASES + +#undef NO_FORCE_SCR_SAME_SUITE +#define NO_FORCE_SCR_SAME_SUITE + +/* remove extra check that server hello did use matching cihper suite */ +#undef WOLFSSL_NO_STRICT_CIPHER_SUITE +#define WOLFSSL_NO_STRICT_CIPHER_SUITE + +/* Remove additional sanity checks to make sure no duplicates, no fast forward + ... ~1k of code size */ +#undef WOLFSSL_NO_SANITY_CHECK_HANDSHAKE +//#define WOLFSSL_NO_SANITY_CHECK_HANDSHAKE + +/* remove async support */ +#undef WOLFSSL_NO_ASYNC_IO +#define WOLFSSL_NO_ASYNC_IO + +/* trim down misc.c file */ +#define WOLFSSL_NO_FORCE_ZERO +#define WOLFSSL_NO_STRING_CONV + +/* lean PSK to compile additional code */ +#define WOLFSSL_LEANPSK +#define WOLFSSL_LEANPSK_STATIC +#ifdef __18CXX + #define WOLFSSL_LEANPSK_STATIC_IO +#endif + +/* disables some early sanity checks on the handshake */ +#undef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS +#define WOLFSSL_DISABLE_EARLY_SANITY_CHECKS + +/* removing session resumption support, each connection + * does a full handshake */ +#undef WOLFSSL_NO_SESSION_RESUMPTION +#define WOLFSSL_NO_SESSION_RESUMPTION + +/* cutting out TLS downgrade handling code */ +#undef WOLFSSL_NO_DOWNGRADE +#define WOLFSSL_NO_DOWNGRADE + +#undef NO_HANDSHAKE_DONE_CB +#define NO_HANDSHAKE_DONE_CB + +/* ------------------------------------------------------------------------- */ +/* Memory config */ +/* ------------------------------------------------------------------------- */ + +#undef WOLFSSL_SMALL_STACK +#define WOLFSSL_SMALL_STACK + +#undef WOLFSSL_NO_REALLOC +#define WOLFSSL_NO_REALLOC + +//#define WOLFSSL_STATIC_MEMORY +#ifndef WOLFSSL_STATIC_MEMORY + #ifdef __18CXX + /* use custom malloc on target */ + #define XMALLOC_USER + #else + #define NO_WOLFSSL_MEMORY + #endif +#else + #define WOLFSSL_STATIC_MEMORY_LEAN + #define USE_WOLFSSL_MEMORY + #define WOLFSSL_NO_MALLOC + + /* AES_CBC tunning */ + #if !defined(HAVE_AESGCM) && !defined(HAVE_CHACHA) + #define WOLFMEM_MAX_BUCKETS 12 + #define WOLFMEM_DEF_BUCKETS 12 + #define WOLFMEM_BUCKETS 4,32,36,80,107,139,154,166,172,195,205,256 + #define WOLFMEM_DIST 3,2,2,1,2,1,1,1,1,1,1,1 + #endif + + #define WOLFSSL_STATIC_ALIGN 1 + + /* Send debugging messages about memory allocation */ + //#define WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK +#endif + +/* ------------------------------------------------------------------------- */ +/* RNG config */ +/* ------------------------------------------------------------------------- */ +#ifndef WOLFSSL_GENSEED_FORTEST + #if 0 + /* Gains about 30 bytes of heap and ~6k of code space but is not a + * secure RNG. RNG is used with client random in ClientHello and with + * AES-CBC IV's when usng static PSK cipher suite. + */ + #define CUSTOM_RAND_GENERATE_BLOCK myRng + + #undef NO_DEV_RANDOM + #define NO_DEV_RANDOM + #else + #define CUSTOM_RAND_GENERATE_SEED myGenSeed + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/src/dtls.c b/src/dtls.c index 1bdb7ce464..9236724e67 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -82,10 +82,10 @@ void DtlsResetState(WOLFSSL* ssl) sizeof(ssl->dtls13Epochs[0].window)); Dtls13FreeFsmResources(ssl); #endif - ssl->keys.dtls_expected_peer_handshake_number = 0; - ssl->keys.dtls_handshake_number = 0; - ssl->keys.dtls_sequence_number_hi = 0; - ssl->keys.dtls_sequence_number_lo = 0; + ssl->keys->dtls_expected_peer_handshake_number = 0; + ssl->keys->dtls_handshake_number = 0; + ssl->keys->dtls_sequence_number_hi = 0; + ssl->keys->dtls_sequence_number_lo = 0; /* Reset states */ ssl->options.serverState = NULL_STATE; @@ -95,9 +95,9 @@ void DtlsResetState(WOLFSSL* ssl) ssl->options.handShakeState = NULL_STATE; ssl->options.seenUnifiedHdr = 0; ssl->msgsReceived.got_client_hello = 0; - ssl->keys.dtls_handshake_number = 0; - ssl->keys.dtls_expected_peer_handshake_number = 0; - XMEMSET(ssl->keys.peerSeq, 0, sizeof(ssl->keys.peerSeq)); + ssl->keys->dtls_handshake_number = 0; + ssl->keys->dtls_expected_peer_handshake_number = 0; + XMEMSET(ssl->keys->peerSeq, 0, sizeof(ssl->keys->peerSeq)); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->options.tls1_3 = 0; @@ -127,18 +127,18 @@ void DtlsSetSeqNumForReply(WOLFSSL* ssl) * protocols. */ /* We should continue with the same sequence number as the * Client Hello. */ - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + ssl->keys->dtls_sequence_number_hi = ssl->keys->curSeq_hi; + ssl->keys->dtls_sequence_number_lo = ssl->keys->curSeq_lo; #ifdef WOLFSSL_DTLS13 if (ssl->dtls13EncryptEpoch != NULL) { ssl->dtls13EncryptEpoch->nextSeqNumber = - w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo); + w64From32(ssl->keys->curSeq_hi, ssl->keys->curSeq_lo); } #endif /* We should continue with the same handshake number as the * Client Hello. */ - ssl->keys.dtls_handshake_number = - ssl->keys.dtls_peer_handshake_number; + ssl->keys->dtls_handshake_number = + ssl->keys->dtls_peer_handshake_number; } #if !defined(NO_WOLFSSL_SERVER) @@ -1019,7 +1019,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz, /* Set record numbers before current record number as read */ Dtls13Epoch* e; ret = Dtls13UpdateWindowRecordRecvd(ssl); - e = Dtls13GetEpoch(ssl, ssl->keys.curEpoch64); + e = Dtls13GetEpoch(ssl, ssl->keys->curEpoch64); if (e != NULL) XMEMSET(e->window, 0xFF, sizeof(e->window)); } @@ -1027,8 +1027,8 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz, #endif DtlsUpdateWindow(ssl); /* Set record numbers before current record number as read */ - XMEMSET(ssl->keys.peerSeq->window, 0xFF, - sizeof(ssl->keys.peerSeq->window)); + XMEMSET(ssl->keys->peerSeq->window, 0xFF, + sizeof(ssl->keys->peerSeq->window)); } } diff --git a/src/dtls13.c b/src/dtls13.c index c661dc94cc..db9beea7e5 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -203,7 +203,7 @@ static int Dtls13HandshakeAddHeaderFrag(WOLFSSL* ssl, byte* output, hdr->msg_type = msg_type; c32to24((word32)msg_length, hdr->length); - c16toa(ssl->keys.dtls_handshake_number, hdr->messageSeq); + c16toa(ssl->keys->dtls_handshake_number, hdr->messageSeq); c32to24(frag_offset, hdr->fragmentOffset); c32to24(frag_length, hdr->fragmentLength); @@ -339,7 +339,7 @@ static byte Dtls13RtxMsgNeedsAck(WOLFSSL* ssl, enum HandShakeType hs) static void Dtls13MsgWasProcessed(WOLFSSL* ssl, enum HandShakeType hs) { if (ssl->options.dtlsStateful) - ssl->keys.dtls_expected_peer_handshake_number++; + ssl->keys->dtls_expected_peer_handshake_number++; /* we need to send ACKs on the last message of a flight that needs explicit acknowledgment */ @@ -359,7 +359,7 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) idx = 0; /* message not in order */ - if (ssl->keys.dtls_expected_peer_handshake_number != msg->seq) + if (ssl->keys->dtls_expected_peer_handshake_number != msg->seq) break; /* message not complete */ @@ -407,7 +407,7 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) /* DoHandShakeMsgType normally handles the hs number but if * DoTls13HandShakeMsgType processed 1.2 msgs then this wasn't * incremented. */ - ssl->keys.dtls_expected_peer_handshake_number++; + ssl->keys->dtls_expected_peer_handshake_number++; ssl->dtls_rx_msg_list = msg->next; DtlsMsgDelete(msg, ssl->heap); @@ -429,7 +429,7 @@ static int Dtls13NextMessageComplete(WOLFSSL* ssl) return ssl->dtls_rx_msg_list != NULL && ssl->dtls_rx_msg_list->ready && ssl->dtls_rx_msg_list->seq == - ssl->keys.dtls_expected_peer_handshake_number; + ssl->keys->dtls_expected_peer_handshake_number; } static WC_INLINE int FragIsInOutputBuffer(WOLFSSL* ssl, const byte* frag) @@ -745,13 +745,13 @@ static int Dtls13DetectDisruption(WOLFSSL* ssl, word32 fragOffset) { /* retransmission. The other peer may have lost our flight or our ACKs. We don't account this as a disruption */ - if (ssl->keys.dtls_peer_handshake_number < - ssl->keys.dtls_expected_peer_handshake_number) + if (ssl->keys->dtls_peer_handshake_number < + ssl->keys->dtls_expected_peer_handshake_number) return 0; /* out of order message */ - if (ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number) { + if (ssl->keys->dtls_peer_handshake_number > + ssl->keys->dtls_expected_peer_handshake_number) { return 1; } @@ -788,8 +788,8 @@ static void Dtls13RtxRemoveCurAck(WOLFSSL* ssl) rn = ssl->dtls13Rtx.seenRecords; while (rn != NULL) { - if (w64Equal(rn->epoch, ssl->keys.curEpoch64) && - w64Equal(rn->seq, ssl->keys.curSeq)) { + if (w64Equal(rn->epoch, ssl->keys->curEpoch64) && + w64Equal(rn->seq, ssl->keys->curSeq)) { *prevNext = rn->next; XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); return; @@ -833,8 +833,8 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs, WOLFSSL_ENTER("Dtls13RtxMsgRecvd"); if (!ssl->options.handShakeDone && - ssl->keys.dtls_peer_handshake_number >= - ssl->keys.dtls_expected_peer_handshake_number) { + ssl->keys->dtls_peer_handshake_number >= + ssl->keys->dtls_expected_peer_handshake_number) { if (hs == server_hello) Dtls13MaybeSaveClientHello(ssl); @@ -852,8 +852,8 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs, DtlsMsgPoolReset(ssl); } - if (ssl->keys.dtls_peer_handshake_number < - ssl->keys.dtls_expected_peer_handshake_number) { + if (ssl->keys->dtls_peer_handshake_number < + ssl->keys->dtls_expected_peer_handshake_number) { /* retransmission detected. */ ssl->dtls13Rtx.retransmit = 1; @@ -864,8 +864,8 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs, ssl->dtls13Rtx.sendAcks = (byte)ssl->options.dtls13SendMoreAcks; } - if (ssl->keys.dtls_peer_handshake_number == - ssl->keys.dtls_expected_peer_handshake_number && + if (ssl->keys->dtls_peer_handshake_number == + ssl->keys->dtls_expected_peer_handshake_number && ssl->options.handShakeDone && hs == certificate_request) { /* the current record, containing a post-handshake certificate request, @@ -1202,7 +1202,7 @@ int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output, hdr->msg_type = msg_type; c32to24((word32)length, hdr->length); - c16toa(ssl->keys.dtls_handshake_number, hdr->messageSeq); + c16toa(ssl->keys->dtls_handshake_number, hdr->messageSeq); /* send unfragmented first */ c32to24(0, hdr->fragmentOffset); @@ -1506,7 +1506,7 @@ int Dtls13RecordRecvd(WOLFSSL* ssl) if (!ssl->options.dtls13SendMoreAcks) ssl->dtls13FastTimeout = 1; - ret = Dtls13RtxAddAck(ssl, ssl->keys.curEpoch64, ssl->keys.curSeq); + ret = Dtls13RtxAddAck(ssl, ssl->keys->curEpoch64, ssl->keys->curSeq); if (ret != 0) WOLFSSL_MSG("can't save ack fragment"); @@ -1666,10 +1666,10 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, /* To be able to operate in stateless mode, we assume the ClientHello * is in order and we use its Handshake Message number and Sequence * Number for our Tx. */ - ssl->keys.dtls_expected_peer_handshake_number = - ssl->keys.dtls_handshake_number = - ssl->keys.dtls_peer_handshake_number; - ssl->dtls13Epochs[0].nextSeqNumber = ssl->keys.curSeq; + ssl->keys->dtls_expected_peer_handshake_number = + ssl->keys->dtls_handshake_number = + ssl->keys->dtls_peer_handshake_number; + ssl->dtls13Epochs[0].nextSeqNumber = ssl->keys->curSeq; } if (idx + fragLength > size) { @@ -1684,8 +1684,8 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, if (ret != 0) return ret; - if (ssl->keys.dtls_peer_handshake_number < - ssl->keys.dtls_expected_peer_handshake_number) { + if (ssl->keys->dtls_peer_handshake_number < + ssl->keys->dtls_expected_peer_handshake_number) { #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG( @@ -1693,7 +1693,7 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, #endif /* WOLFSSL_DEBUG_TLS */ /* ignore the message */ - *processedSize = idx + fragLength + ssl->keys.padSz; + *processedSize = idx + fragLength + ssl->keys->padSz; return 0; } @@ -1727,7 +1727,7 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, WOLFSSL_MSG("DTLS1.3 not accepting fragmented plaintext message"); #endif /* WOLFSSL_DEBUG_TLS */ /* ignore the message */ - *processedSize = idx + fragLength + ssl->keys.padSz; + *processedSize = idx + fragLength + ssl->keys->padSz; return 0; } } @@ -1740,12 +1740,12 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, * if the message is stored in the buffer. */ if (!isComplete || - ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number || + ssl->keys->dtls_peer_handshake_number > + ssl->keys->dtls_expected_peer_handshake_number || usingAsyncCrypto) { if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { - DtlsMsgStore(ssl, (word16)w64GetLow32(ssl->keys.curEpoch64), - ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, (word16)w64GetLow32(ssl->keys->curEpoch64), + ssl->keys->dtls_peer_handshake_number, input + DTLS_HANDSHAKE_HEADER_SZ, messageLength, handshakeType, fragOff, fragLength, ssl->heap); } @@ -1755,7 +1755,7 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, return DTLS_TOO_MANY_FRAGMENTS_E; } - *processedSize = idx + fragLength + ssl->keys.padSz; + *processedSize = idx + fragLength + ssl->keys->padSz; if (Dtls13NextMessageComplete(ssl)) return Dtls13ProcessBufferedMessages(ssl); @@ -1804,7 +1804,7 @@ int Dtls13FragmentsContinue(WOLFSSL* ssl) ret = Dtls13SendFragmentedInternal(ssl); if (ret == 0) - ssl->keys.dtls_handshake_number++; + ssl->keys->dtls_handshake_number++; return ret; } @@ -1894,13 +1894,13 @@ int Dtls13HandshakeSend(WOLFSSL* ssl, byte* message, word16 outputSize, ret = Dtls13SendOneFragmentRtx(ssl, handshakeType, outputSize, message, length, hashOutput); if (ret == 0 || ret == WC_NO_ERR_TRACE(WANT_WRITE)) - ssl->keys.dtls_handshake_number++; + ssl->keys->dtls_handshake_number++; } else { ret = Dtls13SendFragmented(ssl, message, length, handshakeType, hashOutput); if (ret == 0) - ssl->keys.dtls_handshake_number++; + ssl->keys->dtls_handshake_number++; } return ret; @@ -1927,7 +1927,7 @@ int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision) if (ret != 0) goto end; - XMEMCPY(ssl->keys.client_sn_key, key_dig, ssl->specs.key_size); + XMEMCPY(ssl->keys->client_sn_key, key_dig, ssl->specs.key_size); } if (provision & PROVISION_SERVER) { @@ -1938,7 +1938,7 @@ int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision) if (ret != 0) goto end; - XMEMCPY(ssl->keys.server_sn_key, key_dig, ssl->specs.key_size); + XMEMCPY(ssl->keys->server_sn_key, key_dig, ssl->specs.key_size); } end: @@ -2081,7 +2081,7 @@ int Dtls13GetSeq(WOLFSSL* ssl, int order, word32* seq, byte increment) w64wrapper* nativeSeq; if (order == PEER_ORDER) { - nativeSeq = &ssl->keys.curSeq; + nativeSeq = &ssl->keys->curSeq; /* never increment seq number for current record. In DTLS seq number are explicit */ increment = 0; @@ -2166,7 +2166,7 @@ int Dtls13NewEpoch(WOLFSSL* ssl, w64wrapper epochNumber, int side) return BAD_STATE_E; } - Dtls13EpochCopyKeys(ssl, e, &ssl->keys, side); + Dtls13EpochCopyKeys(ssl, e, ssl->keys, side); if (!e->isValid) { /* fresh epoch, initialize fields */ @@ -2243,33 +2243,33 @@ int Dtls13SetEpochKeys(WOLFSSL* ssl, w64wrapper epochNumber, return 0; if (clientWrite) { - XMEMCPY(ssl->keys.client_write_key, e->client_write_key, - sizeof(ssl->keys.client_write_key)); + XMEMCPY(ssl->keys->client_write_key, e->client_write_key, + sizeof(ssl->keys->client_write_key)); - XMEMCPY(ssl->keys.client_write_IV, e->client_write_IV, - sizeof(ssl->keys.client_write_IV)); + XMEMCPY(ssl->keys->client_write_IV, e->client_write_IV, + sizeof(ssl->keys->client_write_IV)); - XMEMCPY(ssl->keys.client_sn_key, e->client_sn_key, - sizeof(ssl->keys.client_sn_key)); + XMEMCPY(ssl->keys->client_sn_key, e->client_sn_key, + sizeof(ssl->keys->client_sn_key)); } if (serverWrite) { - XMEMCPY(ssl->keys.server_write_key, e->server_write_key, - sizeof(ssl->keys.server_write_key)); + XMEMCPY(ssl->keys->server_write_key, e->server_write_key, + sizeof(ssl->keys->server_write_key)); - XMEMCPY(ssl->keys.server_write_IV, e->server_write_IV, - sizeof(ssl->keys.server_write_IV)); + XMEMCPY(ssl->keys->server_write_IV, e->server_write_IV, + sizeof(ssl->keys->server_write_IV)); - XMEMCPY(ssl->keys.server_sn_key, e->server_sn_key, - sizeof(ssl->keys.server_sn_key)); + XMEMCPY(ssl->keys->server_sn_key, e->server_sn_key, + sizeof(ssl->keys->server_sn_key)); } if (enc) - XMEMCPY(ssl->keys.aead_enc_imp_IV, e->aead_enc_imp_IV, - sizeof(ssl->keys.aead_enc_imp_IV)); + XMEMCPY(ssl->keys->aead_enc_imp_IV, e->aead_enc_imp_IV, + sizeof(ssl->keys->aead_enc_imp_IV)); if (dec) - XMEMCPY(ssl->keys.aead_dec_imp_IV, e->aead_dec_imp_IV, - sizeof(ssl->keys.aead_dec_imp_IV)); + XMEMCPY(ssl->keys->aead_dec_imp_IV, e->aead_dec_imp_IV, + sizeof(ssl->keys->aead_dec_imp_IV)); return SetKeysSide(ssl, side); } @@ -2300,16 +2300,16 @@ int Dtls13SetRecordNumberKeys(WOLFSSL* ssl, enum encrypt_side side) if (enc) { if (ssl->options.side == WOLFSSL_CLIENT_END) - encKey = ssl->keys.client_sn_key; + encKey = ssl->keys->client_sn_key; else - encKey = ssl->keys.server_sn_key; + encKey = ssl->keys->server_sn_key; } if (dec) { if (ssl->options.side == WOLFSSL_CLIENT_END) - decKey = ssl->keys.server_sn_key; + decKey = ssl->keys->server_sn_key; else - decKey = ssl->keys.client_sn_key; + decKey = ssl->keys->client_sn_key; } /* DTLSv1.3 supports only AEAD algorithm. */ @@ -2863,7 +2863,7 @@ int Dtls13CheckAEADFailLimit(WOLFSSL* ssl) else if (w64GT(ssl->dtls13DecryptEpoch->dropCount, keyUpdateLimit)) { WOLFSSL_MSG("Connection exceeded key update limit. Issuing key update"); /* If not waiting for a response then request a key update. */ - if (!ssl->keys.updateResponseReq) { + if (!ssl->keys->updateResponseReq) { ssl->dtls13DoKeyUpdate = 1; ssl->dtls13InvalidateBefore = ssl->dtls13PeerEpoch; w64Increment(&ssl->dtls13InvalidateBefore); diff --git a/src/internal.c b/src/internal.c index 2fc63753f6..3479b63237 100644 --- a/src/internal.c +++ b/src/internal.c @@ -245,7 +245,8 @@ enum processReply { #ifndef WOLFSSL_NO_TLS12 -#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#if !defined(NO_WOLFSSL_SERVER) || \ + (!defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_TLS13)) /* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ static const byte tls13Downgrade[7] = { @@ -594,7 +595,7 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) return 0; } -int IsAtLeastTLSv1_3(const ProtocolVersion pv) +int IsAtLeastTLSv1_3(ProtocolVersion pv) { int ret; ret = (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); @@ -612,11 +613,11 @@ int IsEncryptionOn(const WOLFSSL* ssl, int isSend) #ifdef WOLFSSL_DTLS /* For DTLS, epoch 0 is always not encrypted. */ if (ssl->options.dtls && !isSend) { - if (!IsAtLeastTLSv1_3(ssl->version) && ssl->keys.curEpoch == 0) + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->keys->curEpoch == 0) return 0; #ifdef WOLFSSL_DTLS13 else if (IsAtLeastTLSv1_3(ssl->version) - && w64IsZero(ssl->keys.curEpoch64)) + && w64IsZero(ssl->keys->curEpoch64)) return 0; #endif /* WOLFSSL_DTLS13 */ @@ -627,7 +628,7 @@ int IsEncryptionOn(const WOLFSSL* ssl, int isSend) return 0; } #endif - return ssl->keys.encryptionOn && + return ssl->keys->encryptionOn && (isSend ? ssl->encrypt.setup : ssl->decrypt.setup); } @@ -826,7 +827,7 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, return BAD_FUNC_ARG; } - keys = &(ssl->keys); + keys = ssl->keys; if (DTLS_EXPORT_MIN_KEY_SZ > len) { WOLFSSL_MSG("Buffer not large enough for minimum key struct size"); @@ -1028,20 +1029,20 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, } /* temporarily save the sequence numbers */ - tmp_seq_peer_lo = ssl->keys.peer_sequence_number_lo; - tmp_seq_peer_hi = ssl->keys.peer_sequence_number_hi; - tmp_seq_lo = ssl->keys.sequence_number_lo; - tmp_seq_hi = ssl->keys.sequence_number_hi; + tmp_seq_peer_lo = ssl->keys->peer_sequence_number_lo; + tmp_seq_peer_hi = ssl->keys->peer_sequence_number_hi; + tmp_seq_lo = ssl->keys->sequence_number_lo; + tmp_seq_hi = ssl->keys->sequence_number_hi; if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) < 0) { return ret; } /* reset sequence numbers after setting keys */ - ssl->keys.peer_sequence_number_lo = tmp_seq_peer_lo; - ssl->keys.peer_sequence_number_hi = tmp_seq_peer_hi; - ssl->keys.sequence_number_lo = tmp_seq_lo; - ssl->keys.sequence_number_hi = tmp_seq_hi; + ssl->keys->peer_sequence_number_lo = tmp_seq_peer_lo; + ssl->keys->peer_sequence_number_hi = tmp_seq_peer_hi; + ssl->keys->sequence_number_lo = tmp_seq_lo; + ssl->keys->sequence_number_hi = tmp_seq_hi; if (type == WOLFSSL_EXPORT_TLS && ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { @@ -1084,7 +1085,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, return BAD_FUNC_ARG; } - keys = &(ssl->keys); + keys = ssl->keys; /* check minimum length -- includes byte used for size indicators */ if (len < DTLS_EXPORT_MIN_KEY_SZ) { @@ -2331,7 +2332,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifdef HAVE_DILITHIUM ctx->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ; #endif /* HAVE_DILITHIUM */ +#ifndef NO_CERTS ctx->verifyDepth = MAX_CHAIN_DEPTH; +#endif #ifdef OPENSSL_EXTRA ctx->cbioFlag = WOLFSSL_CBIO_NONE; #endif @@ -2779,7 +2782,9 @@ static void SSL_CtxResourceFreeStaticMem(void* heap) ) { WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; WOLFSSL_HEAP* mem = hint->memory; + #ifndef SINGLE_THREADED wc_FreeMutex(&mem->memory_mutex); + #endif } #else (void)heap; @@ -2901,7 +2906,8 @@ void FreeCiphers(WOLFSSL* ssl) XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #if defined(BUILD_AES) || defined(BUILD_AESGCM) || defined(HAVE_ARIA) - /* See: InitKeys() in keys.c on addition of BUILD_AESGCM check (enc->aes, dec->aes) */ + /* See: InitKeys() in keys->c on addition of BUILD_AESGCM check + (enc->aes, dec->aes) */ wc_AesFree(ssl->encrypt.aes); wc_AesFree(ssl->decrypt.aes); XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -6433,17 +6439,21 @@ static void InitSuites_EitherSide(Suites* suites, ProtocolVersion pv, int keySz, word16 haveFalconSig, word16 haveDilithiumSig, word16 haveAnon, int side) { +#ifndef NO_WOLFSSL_SERVER /* make sure server has DH params, and add PSK if there */ if (side == WOLFSSL_SERVER_END) { InitSuites(suites, pv, keySz, haveRSA, havePSK, haveDH, haveECDSAsig, haveECC, TRUE, haveStaticECC, haveFalconSig, haveDilithiumSig, haveAnon, TRUE, side); } - else { + else +#endif + { InitSuites(suites, pv, keySz, haveRSA, havePSK, TRUE, haveECDSAsig, haveECC, TRUE, haveStaticECC, haveFalconSig, haveDilithiumSig, haveAnon, TRUE, side); } + (void)haveDH; /* not used when no server support is compiled in */ } void InitSSL_CTX_Suites(WOLFSSL_CTX* ctx) @@ -6708,7 +6718,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->CBIS = ctx->CBIS; #endif ssl->timeout = ctx->timeout; +#ifndef NO_CERTS ssl->verifyCallback = ctx->verifyCallback; +#endif /* If we are setting the ctx on an already initialized SSL object * then we possibly already have a side defined. Don't overwrite unless * the context has a well defined role. */ @@ -6942,8 +6954,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) if (ssl->CBIOSend != SslBioSend) #endif ssl->CBIOSend = ctx->CBIOSend; +#ifndef NO_CERTS ssl->verifyDepth = ctx->verifyDepth; - +#endif return ret; } @@ -7055,6 +7068,7 @@ void FreeHandshakeHashes(WOLFSSL* ssl) } } +#ifdef WOLFSSL_TLS13 /* copy the hashes from source to a newly made destination return status */ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source, HS_Hashes** destination) @@ -7129,6 +7143,7 @@ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source, return ret; } +#endif /* called if user attempts to reuse WOLFSSL object for a new session. * For example wolfSSL_clear() is called then wolfSSL_connect or accept */ @@ -7181,7 +7196,7 @@ int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) /* FIPS RNG API does not accept a heap hint */ #ifndef HAVE_FIPS - if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap,ssl->devId)) != 0) { WOLFSSL_MSG("RNG Init error"); return ret; } @@ -7215,7 +7230,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) XMEMSET(ssl, 0, sizeof(WOLFSSL)); #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("SSL Keys", &ssl->keys, sizeof(ssl->keys)); #ifdef WOLFSSL_TLS13 wc_MemZero_Add("SSL client secret", &ssl->clientSecret, sizeof(ssl->clientSecret)); @@ -7301,6 +7315,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS)); } + /* check if using fixed IO buffers */ if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) { #ifndef SINGLE_THREADED @@ -7329,7 +7344,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif return MEMORY_E; } - #ifndef SINGLE_THREADED + #ifndef SINGLE_THREADED wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); #endif } @@ -7345,6 +7360,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->heap = ctx->heap; /* carry over user heap without static memory */ #endif /* WOLFSSL_STATIC_MEMORY */ + if (ssl->keys == NULL) { + ssl->keys = (Keys*)XMALLOC(sizeof(Keys), ssl->heap, DYNAMIC_TYPE_KEY); + if (ssl->keys == NULL) + return MEMORY_E; + XMEMSET(ssl->keys, 0, sizeof(Keys)); + } + ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; @@ -7411,12 +7433,15 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->IOCB_ReadCtx = ssl->gnrcCtx; ssl->IOCB_WriteCtx = ssl->gnrcCtx; #else +#ifndef WOLFSSL_LEANPSK_STATIC ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ #endif #endif +#endif +#ifndef WOLFSSL_LEANPSK_STATIC #ifndef WOLFSSL_AEAD_ONLY #ifndef NO_OLD_TLS ssl->hmac = SSL_hmac; /* default to SSLv3 */ @@ -7429,6 +7454,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif #endif #endif +#endif #if defined(WOLFSSL_OPENVPN) && defined(HAVE_KEYING_MATERIAL) /* Save arrays by default for OpenVPN */ @@ -7577,7 +7603,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) WOLFSSL_MSG_EX("SetSSL_CTX failed. err = %d", ret); return ret; } +#ifdef WOLFSSL_DTLS ssl->options.dtls = ssl->version.major == DTLS_MAJOR; +#endif #ifdef HAVE_WRITE_DUP if (writeDup) { @@ -7657,7 +7685,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.handShakeDone = 1; for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) - ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID; + ssl->keys->peerSeq[i].peerId = INVALID_PEER_ID; } #endif @@ -7731,18 +7759,23 @@ void FreeArrays(WOLFSSL* ssl, int keep) ssl->session->sessionIDSz = ssl->arrays->sessionIDSz; } if (ssl->arrays->preMasterSecret) { + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN); + #endif XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); ssl->arrays->preMasterSecret = NULL; } XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays->pendingMsg = NULL; + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ + #endif } XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays = NULL; } + void FreeKey(WOLFSSL* ssl, int type, void** pKey) { if (ssl && pKey && *pKey) { @@ -7810,6 +7843,10 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) } } +#if defined(HAVE_ECC) || !defined(NO_RSA) || defined(HAVE_ED25519) || \ + defined(HAVE_CURVE25519) || defined(HAVE_ED448) || defined(HAVE_CURVE448) \ + || defined(HAVE_PQC) || !defined(NO_DH) + int AllocKey(WOLFSSL* ssl, int type, void** pKey) { int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); @@ -7977,6 +8014,7 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) return ret; } +#endif /* have public key */ #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ defined(HAVE_CURVE25519) || defined(HAVE_ED448) || \ @@ -8095,7 +8133,9 @@ void FreeKeyExchange(WOLFSSL* ssl) } /* Free handshake key */ +#ifndef WOLFSSL_LEANPSK_STATIC FreeKey(ssl, (int)ssl->hsType, &ssl->hsKey); +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS FreeKey(ssl, ssl->hsAltType, &ssl->hsAltKey); #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -8160,8 +8200,14 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); - /* clear keys struct after session */ - ForceZero(&ssl->keys, sizeof(Keys)); + if (ssl->keys != NULL) { + #ifndef WOLFSSL_NO_FORCE_ZERO + /* clear keys struct after session */ + ForceZero(ssl->keys, sizeof(Keys)); + #endif + XFREE(ssl->keys, ssl->heap, DYNAMIC_TYPE_KEY); + ssl->keys = NULL; + } #ifdef WOLFSSL_TLS13 ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret)); @@ -8757,19 +8803,19 @@ void FreeSSL(WOLFSSL* ssl, void* heap) static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) { if (verify) { - seq[0] = ssl->keys.peer_sequence_number_hi; - seq[1] = ssl->keys.peer_sequence_number_lo++; - if (seq[1] > ssl->keys.peer_sequence_number_lo) { + seq[0] = ssl->keys->peer_sequence_number_hi; + seq[1] = ssl->keys->peer_sequence_number_lo++; + if (seq[1] > ssl->keys->peer_sequence_number_lo) { /* handle rollover */ - ssl->keys.peer_sequence_number_hi++; + ssl->keys->peer_sequence_number_hi++; } } else { - seq[0] = ssl->keys.sequence_number_hi; - seq[1] = ssl->keys.sequence_number_lo++; - if (seq[1] > ssl->keys.sequence_number_lo) { + seq[0] = ssl->keys->sequence_number_hi; + seq[1] = ssl->keys->sequence_number_lo++; + if (seq[1] > ssl->keys->sequence_number_lo) { /* handle rollover */ - ssl->keys.sequence_number_hi++; + ssl->keys->sequence_number_hi++; } } } @@ -8786,41 +8832,41 @@ static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) /* Previous epoch case */ if (ssl->options.haveMcast) { #ifdef WOLFSSL_MULTICAST - seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) | + seq[0] = (((word32)ssl->keys->dtls_epoch - 1) << 16) | (ssl->options.mcastID << 8) | - (ssl->keys.dtls_prev_sequence_number_hi & 0xFF); + (ssl->keys->dtls_prev_sequence_number_hi & 0xFF); #endif } else - seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) | - (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); - seq[1] = ssl->keys.dtls_prev_sequence_number_lo; + seq[0] = (((word32)ssl->keys->dtls_epoch - 1) << 16) | + (ssl->keys->dtls_prev_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys->dtls_prev_sequence_number_lo; } else if (order == PEER_ORDER) { if (ssl->options.haveMcast) { #ifdef WOLFSSL_MULTICAST - seq[0] = ((word32)ssl->keys.curEpoch << 16) | - (ssl->keys.curPeerId << 8) | - (ssl->keys.curSeq_hi & 0xFF); + seq[0] = ((word32)ssl->keys->curEpoch << 16) | + (ssl->keys->curPeerId << 8) | + (ssl->keys->curSeq_hi & 0xFF); #endif } else - seq[0] = ((word32)ssl->keys.curEpoch << 16) | - (ssl->keys.curSeq_hi & 0xFFFF); - seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ + seq[0] = ((word32)ssl->keys->curEpoch << 16) | + (ssl->keys->curSeq_hi & 0xFFFF); + seq[1] = ssl->keys->curSeq_lo; /* explicit from peer */ } else { if (ssl->options.haveMcast) { #ifdef WOLFSSL_MULTICAST - seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | + seq[0] = ((word32)ssl->keys->dtls_epoch << 16) | (ssl->options.mcastID << 8) | - (ssl->keys.dtls_sequence_number_hi & 0xFF); + (ssl->keys->dtls_sequence_number_hi & 0xFF); #endif } else - seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | - (ssl->keys.dtls_sequence_number_hi & 0xFFFF); - seq[1] = ssl->keys.dtls_sequence_number_lo; + seq[0] = ((word32)ssl->keys->dtls_epoch << 16) | + (ssl->keys->dtls_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys->dtls_sequence_number_lo; } } @@ -8832,24 +8878,24 @@ static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order) #endif if (order == PREV_ORDER) { - seq = ssl->keys.dtls_prev_sequence_number_lo++; - if (seq > ssl->keys.dtls_prev_sequence_number_lo) { + seq = ssl->keys->dtls_prev_sequence_number_lo++; + if (seq > ssl->keys->dtls_prev_sequence_number_lo) { /* handle rollover */ - ssl->keys.dtls_prev_sequence_number_hi++; + ssl->keys->dtls_prev_sequence_number_hi++; } } else if (order == PEER_ORDER) { - seq = ssl->keys.peer_sequence_number_lo++; - if (seq > ssl->keys.peer_sequence_number_lo) { + seq = ssl->keys->peer_sequence_number_lo++; + if (seq > ssl->keys->peer_sequence_number_lo) { /* handle rollover */ - ssl->keys.peer_sequence_number_hi++; + ssl->keys->peer_sequence_number_hi++; } } else { - seq = ssl->keys.dtls_sequence_number_lo++; - if (seq > ssl->keys.dtls_sequence_number_lo) { + seq = ssl->keys->dtls_sequence_number_lo++; + if (seq > ssl->keys->dtls_sequence_number_lo) { /* handle rollover */ - ssl->keys.dtls_sequence_number_hi++; + ssl->keys->dtls_sequence_number_hi++; } } } @@ -8860,14 +8906,17 @@ void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) { word32 seq[2] = {0, 0}; - if (!ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) +#endif + { GetSEQIncrement(ssl, verifyOrder, seq); } - else { #ifdef WOLFSSL_DTLS + else { DtlsGetSEQ(ssl, verifyOrder, seq); -#endif } +#endif c32toa(seq[0], out); c32toa(seq[1], out + OPAQUE32_LEN); @@ -9305,7 +9354,15 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data, */ DtlsMsg* head = ssl->dtls_rx_msg_list; - byte encrypted = ssl->keys.decryptedCur == 1; + byte encrypted; + + if (ssl->keys == NULL) { + encrypted = 0; + } + else { + encrypted = ssl->keys->decryptedCur == 1; + } + WOLFSSL_ENTER("DtlsMsgStore"); if (head != NULL) { @@ -9382,7 +9439,7 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) /** * DtlsMsgPoolSave() adds the message to the end of the stored transmit * list. Must be called BEFORE BuildMessage or DtlsSEQIncrement or - * anything else that increments ssl->keys.dtls_handshake_number. + * anything else that increments ssl->keys->dtls_handshake_number. */ int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz, enum HandShakeType type) @@ -9403,8 +9460,8 @@ int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz, DtlsMsg* cur = ssl->dtls_tx_msg_list; XMEMCPY(item->raw, data, dataSz); - item->epoch = ssl->keys.dtls_epoch; - item->seq = ssl->keys.dtls_handshake_number; + item->epoch = ssl->keys->dtls_epoch; + item->seq = ssl->keys->dtls_handshake_number; item->type = type; if (cur == NULL) @@ -9487,7 +9544,7 @@ int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) int VerifyForTxDtlsMsgDelete(WOLFSSL* ssl, DtlsMsg* item) { WOLFSSL_ENTER("VerifyForTxDtlsMsgDelete"); - if (item->epoch < ssl->keys.dtls_epoch - 1) + if (item->epoch < ssl->keys->dtls_epoch - 1) /* Messages not from current or previous epoch can be deleted */ return 1; switch (ssl->options.side) { @@ -9556,7 +9613,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) * If the stored record's epoch is 0 and the currently set * epoch is not 0, the stored record is considered a "previous * order" sequence number. */ - epochOrder = (ssl->keys.dtls_epoch == 0) ? + epochOrder = (ssl->keys->dtls_epoch == 0) ? CUR_ORDER : PREV_ORDER; WriteSEQ(ssl, epochOrder, dtls->sequence_number); @@ -10193,19 +10250,22 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl } #endif - if (!ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) +#endif + { c16toa((word16)length, rl->length); } - else { #ifdef WOLFSSL_DTLS + else { DtlsRecordLayerHeader* dtls; /* dtls record layer header extensions */ dtls = (DtlsRecordLayerHeader*)output; WriteSEQ(ssl, epochOrder, dtls->sequence_number); c16toa((word16)length, dtls->length); -#endif } + #endif } @@ -10234,7 +10294,7 @@ static void AddHandShakeHeader(byte* output, word32 length, /* dtls handshake header extensions */ dtls = (DtlsHandShakeHeader*)output; - c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq); + c16toa(ssl->keys->dtls_handshake_number++, dtls->message_seq); c32to24(fragOffset, dtls->fragment_offset); c32to24(fragLength, dtls->fragment_length); } @@ -10344,7 +10404,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, /* Decrement msg number so that we continue to use the * same msg number for this msg */ if (ssl->options.dtls) - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; #endif } while (ssl->fragOffset < inputSz) { @@ -10378,7 +10438,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, dataSz += DTLS_HANDSHAKE_HEADER_SZ; AddHandShakeHeader(data, inputSz, ssl->fragOffset, fragSz, type, ssl); - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; } if (IsDtlsNotSctpMode(ssl) && (ret = DtlsMsgPoolSave(ssl, data, @@ -10406,7 +10466,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, XMEMCPY(output + headerSz, data, fragSz); #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; DtlsSEQIncrement(ssl, CUR_ORDER); } if (IsDtlsNotSctpMode(ssl)) { @@ -10438,7 +10498,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, #ifdef WOLFSSL_DTLS /* Increment msg number once we sent all fragments */ if (ssl->options.dtls) - ssl->keys.dtls_handshake_number++; + ssl->keys->dtls_handshake_number++; #endif ssl->fragOffset = 0; ssl->options.buildingMsg = 0; @@ -10497,7 +10557,7 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) return WC_NO_ERR_TRACE(WANT_READ); case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_RST): - #ifdef USE_WINDOWS_API + #if defined(USE_WINDOWS_API) && defined(WOLFSSL_DTLS) if (ssl->options.dtls) { goto retry; } @@ -10599,8 +10659,10 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) usedLength); } +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(ssl->buffers.inputBuffer.buffer, ssl->buffers.inputBuffer.length); +#endif XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; @@ -10719,8 +10781,12 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) { byte* tmp; #if WOLFSSL_GENERAL_ALIGNMENT > 0 +#ifdef WOLFSSL_DTLS byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : RECORD_HEADER_SZ; +#else + byte hdrSz = RECORD_HEADER_SZ; +#endif byte align = WOLFSSL_GENERAL_ALIGNMENT; #else const byte align = WOLFSSL_GENERAL_ALIGNMENT; @@ -10794,7 +10860,11 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) { byte* tmp; #if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 +#ifdef WOLFSSL_DTLS byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; +#else + byte align = 0; +#endif byte hdrSz = DTLS_RECORD_HEADER_SZ; #else const byte align = WOLFSSL_GENERAL_ALIGNMENT; @@ -10844,10 +10914,12 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) ssl->buffers.inputBuffer.idx, usedLength); if (ssl->buffers.inputBuffer.dynamicFlag) { + #ifndef WOLFSSL_NO_FORCE_ZERO if (IsEncryptionOn(ssl, 1)) { ForceZero(ssl->buffers.inputBuffer.buffer, ssl->buffers.inputBuffer.length); } + #endif XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); } @@ -11029,7 +11101,7 @@ static WC_INLINE int isLastMsg(const WOLFSSL* ssl, word32 msgSz) { word32 extra = 0; if (IsEncryptionOn(ssl, 0)) { - extra = ssl->keys.padSz; + extra = ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) extra += MacSize(ssl); @@ -11180,7 +11252,7 @@ int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz) WOLFSSL_ENTER("EarlySanityCheckMsgReceived"); if (version_negotiated) - ret = MsgCheckEncryption(ssl, type, ssl->keys.decryptedCur == 1); + ret = MsgCheckEncryption(ssl, type, ssl->keys->decryptedCur == 1); if (ret == 0) ret = MsgCheckBoundary(ssl, type, version_negotiated, msgSz); @@ -11288,15 +11360,15 @@ static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx, rh->pvMajor = ssl->version.major; rh->pvMinor = DTLSv1_2_MINOR; - ssl->keys.curEpoch64 = epochNumber; + ssl->keys->curEpoch64 = epochNumber; - ret = Dtls13ReconstructSeqNumber(ssl, &hdrInfo, &ssl->keys.curSeq); + ret = Dtls13ReconstructSeqNumber(ssl, &hdrInfo, &ssl->keys->curSeq); if (ret != 0) return ret; #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG_EX("reconstructed seq number: %ld", - ssl->keys.curSeq); + ssl->keys->curSeq); #endif /* WOLFSSL_DEBUG_TLS */ XMEMCPY(ssl->dtls13CurRL, ssl->buffers.inputBuffer.buffer + *inOutIdx, @@ -11363,37 +11435,38 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx, XMEMCPY(rh, ssl->buffers.inputBuffer.buffer + *inOutIdx, ENUM_LEN + VERSION_SZ); *inOutIdx += ENUM_LEN + VERSION_SZ; - ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys.curEpoch); + ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys->curEpoch); #ifdef WOLFSSL_DTLS13 /* only non protected message can use the DTLSPlaintext record header */ if (IsAtLeastTLSv1_3(ssl->version)) { - if (ssl->keys.curEpoch != 0) + if (ssl->keys->curEpoch != 0) return SEQUENCE_ERROR; - w64Zero(&ssl->keys.curEpoch64); + w64Zero(&ssl->keys->curEpoch64); if (!w64IsZero(ssl->dtls13DecryptEpoch->epochNumber)) - Dtls13SetEpochKeys(ssl, ssl->keys.curEpoch64, DECRYPT_SIDE_ONLY); + Dtls13SetEpochKeys(ssl, ssl->keys->curEpoch64, DECRYPT_SIDE_ONLY); } #endif /* WOLFSSL_DTLS13 */ *inOutIdx += OPAQUE16_LEN; if (ssl->options.haveMcast) { #ifdef WOLFSSL_MULTICAST - ssl->keys.curPeerId = ssl->buffers.inputBuffer.buffer[*inOutIdx]; - ssl->keys.curSeq_hi = ssl->buffers.inputBuffer.buffer[*inOutIdx+1]; + ssl->keys->curPeerId = ssl->buffers.inputBuffer.buffer[*inOutIdx]; + ssl->keys->curSeq_hi = ssl->buffers.inputBuffer.buffer[*inOutIdx+1]; #endif } else - ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys.curSeq_hi); + ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, + &ssl->keys->curSeq_hi); *inOutIdx += OPAQUE16_LEN; - ato32(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys.curSeq_lo); + ato32(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys->curSeq_lo); *inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */ #ifdef WOLFSSL_DTLS13 /* DTLSv1.3 PlainText records use DTLSv1.2 sequence number encoding. Update the DTLv1.3 word64 version as well */ - ssl->keys.curSeq = w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo); + ssl->keys->curSeq = w64From32(ssl->keys->curSeq_hi, ssl->keys->curSeq_lo); #endif /* WOLFSSL_DTLS13 */ ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, size); @@ -11414,8 +11487,10 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, #endif (void)tls12minor; - - if (!ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + if (!ssl->options.dtls) +#endif + { #ifdef HAVE_FUZZER if (ssl->fuzzerCb) ssl->fuzzerCb(ssl, ssl->buffers.inputBuffer.buffer + *inOutIdx, @@ -11431,22 +11506,22 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, *inOutIdx += RECORD_HEADER_SZ; ato16(rh->length, size); } - else { #ifdef WOLFSSL_DTLS + else { int ret = GetDtlsRecordHeader(ssl, inOutIdx, rh, size); if (ret != 0) return ret; -#endif } - +#endif #ifdef WOLFSSL_DTLS /* DTLSv1.3 MUST check window after deprotecting to avoid timing channel (RFC9147 Section 4.5.1) */ if (IsDtlsNotSctpMode(ssl) && !IsAtLeastTLSv1_3(ssl->version)) { if (!_DtlsCheckWindow(ssl) || - (rh->type == application_data && ssl->keys.curEpoch == 0) || + (rh->type == application_data && ssl->keys->curEpoch == 0) || (rh->type == alert && ssl->options.handShakeDone && - ssl->keys.curEpoch == 0 && ssl->keys.dtls_epoch != 0)) { + ssl->keys->curEpoch == 0 && + ssl->keys->dtls_epoch != 0)) { WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR); return SEQUENCE_ERROR; } @@ -11478,9 +11553,11 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, ssl->options.downgrade && ssl->options.connectState < FIRST_REPLY_DONE) WOLFSSL_MSG("Server attempting to accept with different version"); +#ifdef WOLFSSL_DTLS else if (ssl->options.dtls && rh->type == handshake) /* Check the DTLS handshake message RH version later. */ WOLFSSL_MSG("DTLS handshake, skip RH version number check"); +#endif #ifdef WOLFSSL_DTLS13 else if (ssl->options.dtls && !ssl->options.handShakeDone) { /* we may have lost the ServerHello and this is a unified record @@ -11563,7 +11640,7 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, } /* haven't decrypted this record yet */ - ssl->keys.decryptedCur = 0; + ssl->keys->decryptedCur = 0; return 0; } @@ -11604,7 +11681,7 @@ int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, c24to32(input + idx, size); idx += OPAQUE24_LEN; - ato16(input + idx, &ssl->keys.dtls_peer_handshake_number); + ato16(input + idx, &ssl->keys->dtls_peer_handshake_number); idx += DTLS_HANDSHAKE_SEQ_SZ; c24to32(input + idx, fragOffset); @@ -11782,6 +11859,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#ifndef WOLFSSL_LEANPSK /* Does this cipher suite (first, second) have the requirement an ephemeral key exchange will still require the key for signing the key exchange so ECDHE_RSA requires an rsa key thus rsa_kea */ @@ -12086,7 +12164,7 @@ int CipherRequires(byte first, byte second, int requirement) break; #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ - #ifndef NO_PSK + #if !defined(NO_PSK) && defined(HAVE_AESCCM) case TLS_PSK_WITH_AES_128_CCM: case TLS_PSK_WITH_AES_256_CCM: case TLS_PSK_WITH_AES_128_CCM_8: @@ -12277,6 +12355,7 @@ int CipherRequires(byte first, byte second, int requirement) #endif /* !NO_RSA */ #ifndef NO_PSK + #ifdef HAVE_AESGCM case TLS_PSK_WITH_AES_128_GCM_SHA256 : if (requirement == REQUIRES_PSK) return 1; @@ -12290,18 +12369,21 @@ int CipherRequires(byte first, byte second, int requirement) if (requirement == REQUIRES_AEAD) return 1; break; + #endif case TLS_PSK_WITH_AES_128_CBC_SHA256 : case TLS_PSK_WITH_AES_256_CBC_SHA384 : + #ifndef NO_SHA case TLS_PSK_WITH_AES_128_CBC_SHA : case TLS_PSK_WITH_AES_256_CBC_SHA : + #endif case TLS_PSK_WITH_NULL_SHA384 : case TLS_PSK_WITH_NULL_SHA256 : case TLS_PSK_WITH_NULL_SHA : if (requirement == REQUIRES_PSK) return 1; break; - + #ifdef HAVE_AESGCM case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : if (requirement == REQUIRES_DHE) @@ -12311,7 +12393,8 @@ int CipherRequires(byte first, byte second, int requirement) if (requirement == REQUIRES_AEAD) return 1; break; - + #endif + #ifndef NO_DH case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : case TLS_DHE_PSK_WITH_NULL_SHA384 : @@ -12321,6 +12404,7 @@ int CipherRequires(byte first, byte second, int requirement) if (requirement == REQUIRES_PSK) return 1; break; + #endif #endif /* NO_PSK */ #ifndef NO_RSA @@ -12428,7 +12512,7 @@ int CipherRequires(byte first, byte second, int requirement) return 0; } - +#endif /* WOLFSSL_LEANPSK */ #endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ @@ -13814,7 +13898,8 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int cert_err, } #endif /* if verify callback has been set */ - if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL) + if ((use_cb && (ssl != NULL) + && ((ssl->verifyCallback != NULL) #ifdef OPENSSL_ALL || (ssl->ctx->verifyCertCb != NULL) #endif @@ -16179,7 +16264,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } if (IsEncryptionOn(ssl, 0)) { - args->idx += ssl->keys.padSz; + args->idx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) args->idx += MacSize(ssl); @@ -16447,16 +16532,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); - if (*inOutIdx + ssl->keys.padSz + digestSz > size) + if (*inOutIdx + ssl->keys->padSz + digestSz > size) return BUFFER_E; - *inOutIdx += ssl->keys.padSz + digestSz; + *inOutIdx += ssl->keys->padSz + digestSz; } else #endif { - if (*inOutIdx + ssl->keys.padSz > size) + if (*inOutIdx + ssl->keys->padSz > size) return BUFFER_E; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; } } @@ -16492,19 +16577,19 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); if (size != totalSz && - *inOutIdx + ssl->keys.padSz + digestSz > totalSz) + *inOutIdx + ssl->keys->padSz + digestSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz + digestSz; + *inOutIdx += ssl->keys->padSz + digestSz; } else #endif { /* access beyond input + size should be checked against totalSz */ if (size != totalSz && - *inOutIdx + ssl->keys.padSz > totalSz) + *inOutIdx + ssl->keys->padSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; } } @@ -16544,13 +16629,13 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, if (size != totalSz) { #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) { - if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz) + if (*inOutIdx + size + ssl->keys->padSz + MacSize(ssl) > totalSz) return BUFFER_E; } else #endif { - if (*inOutIdx + size + ssl->keys.padSz > totalSz) + if (*inOutIdx + size + ssl->keys->padSz > totalSz) return BUFFER_E; } } @@ -16594,7 +16679,7 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, #endif /* force input exhaustion at ProcessReply consuming padSz */ - *inOutIdx += size + ssl->keys.padSz; + *inOutIdx += size + ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) *inOutIdx += MacSize(ssl); @@ -16643,8 +16728,8 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, if ((!ssl->options.resuming && ssl->options.side == WOLFSSL_CLIENT_END) || (ssl->options.resuming && ssl->options.side == WOLFSSL_SERVER_END)){ DtlsMsgPoolReset(ssl); - ssl->keys.dtls_handshake_number = 0; - ssl->keys.dtls_expected_peer_handshake_number = 0; + ssl->keys->dtls_handshake_number = 0; + ssl->keys->dtls_expected_peer_handshake_number = 0; } } #endif @@ -17020,7 +17105,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - if (ssl->keys.curEpoch == 0) { + if (ssl->keys->curEpoch == 0) { WOLFSSL_MSG("Finished received with epoch 0"); WOLFSSL_ERROR_VERBOSE(SEQUENCE_ERROR); return SEQUENCE_ERROR; @@ -17120,7 +17205,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) return 0; } - int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, byte type, word32 size, word32 totalSz) { @@ -17144,9 +17228,9 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } expectedIdx = *inOutIdx + size + - (ssl->keys.encryptionOn ? ssl->keys.padSz : 0); + (ssl->keys->encryptionOn ? ssl->keys->padSz : 0); #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.startedETMRead && ssl->keys.encryptionOn) + if (ssl->options.startedETMRead && ssl->keys->encryptionOn) expectedIdx += MacSize(ssl); #endif @@ -17200,7 +17284,10 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, return OUT_OF_ORDER_E; } - if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 && + if (ssl->options.side == WOLFSSL_CLIENT_END && + #ifdef WOLFSSL_DTLS + ssl->options.dtls == 0 && + #endif ssl->options.serverState == NULL_STATE && type != server_hello && type != hello_request) { WOLFSSL_MSG("First server message not server hello or " @@ -17210,7 +17297,10 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, return OUT_OF_ORDER_E; } - if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls && + if (ssl->options.side == WOLFSSL_CLIENT_END && + #ifdef WOLFSSL_DTLS + ssl->options.dtls && + #endif type == server_hello_done && ssl->options.serverState < SERVER_HELLO_COMPLETE) { WOLFSSL_MSG("Server hello done received before server hello in DTLS"); @@ -17295,6 +17385,7 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; #ifndef NO_WOLFSSL_CLIENT +#ifdef WOLFSSL_DTLS case hello_verify_request: WOLFSSL_MSG("processing hello verify request"); ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size); @@ -17302,22 +17393,23 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); - if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + if (*inOutIdx + ssl->keys->padSz + digestSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz + digestSz; + *inOutIdx += ssl->keys->padSz + digestSz; } else #endif { /* access beyond input + size should be checked against totalSz */ - if (*inOutIdx + ssl->keys.padSz > totalSz) + if (*inOutIdx + ssl->keys->padSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; } } break; +#endif case server_hello: WOLFSSL_MSG("processing server hello"); @@ -17389,7 +17481,7 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) *inOutIdx += MacSize(ssl); @@ -17433,9 +17525,9 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); if (size != totalSz && - *inOutIdx + ssl->keys.padSz + digestSz > totalSz) + *inOutIdx + ssl->keys->padSz + digestSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz + digestSz; + *inOutIdx += ssl->keys->padSz + digestSz; } else #endif @@ -17443,9 +17535,9 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* access beyond input + size should be checked against totalSz */ if (size != totalSz && - *inOutIdx + ssl->keys.padSz > totalSz) + *inOutIdx + ssl->keys->padSz > totalSz) return BUFFER_E; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; } } break; @@ -17472,7 +17564,9 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } if (ret == 0 && expectedIdx != *inOutIdx) { WOLFSSL_MSG("Extra data in handshake message"); + #ifdef WOLFSSL_DTLS if (!ssl->options.dtls) + #endif SendAlert(ssl, alert_fatal, decode_error); ret = DECODE_E; WOLFSSL_ERROR_VERBOSE(ret); @@ -17502,11 +17596,11 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (type == client_hello) { /* Advance expected number only if cookie exchange complete */ if (ssl->msgsReceived.got_client_hello) - ssl->keys.dtls_expected_peer_handshake_number = - ssl->keys.dtls_peer_handshake_number + 1; + ssl->keys->dtls_expected_peer_handshake_number = + ssl->keys->dtls_peer_handshake_number + 1; } else if (type != finished) { - ssl->keys.dtls_expected_peer_handshake_number++; + ssl->keys->dtls_expected_peer_handshake_number++; } } #endif @@ -17730,17 +17824,17 @@ static int _DtlsCheckWindow(WOLFSSL* ssl) WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL; if (!ssl->options.haveMcast) - peerSeq = ssl->keys.peerSeq; + peerSeq = ssl->keys->peerSeq; else { #ifdef WOLFSSL_MULTICAST WOLFSSL_DTLS_PEERSEQ* p; int i; - for (i = 0, p = ssl->keys.peerSeq; + for (i = 0, p = ssl->keys->peerSeq; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++, p++) { - if (p->peerId == ssl->keys.curPeerId) { + if (p->peerId == ssl->keys->curPeerId) { peerSeq = p; break; } @@ -17753,12 +17847,12 @@ static int _DtlsCheckWindow(WOLFSSL* ssl) return 0; } - if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + if (ssl->keys->curEpoch == peerSeq->nextEpoch) { next_hi = peerSeq->nextSeq_hi; next_lo = peerSeq->nextSeq_lo; window = peerSeq->window; } - else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) { + else if (ssl->keys->curEpoch == peerSeq->nextEpoch - 1) { next_hi = peerSeq->prevSeq_hi; next_lo = peerSeq->prevSeq_lo; window = peerSeq->prevWindow; @@ -17767,8 +17861,8 @@ static int _DtlsCheckWindow(WOLFSSL* ssl) return 0; } - cur_hi = ssl->keys.curSeq_hi; - cur_lo = ssl->keys.curSeq_lo; + cur_hi = ssl->keys->curSeq_hi; + cur_lo = ssl->keys->curSeq_lo; /* If the difference between next and cur is > 2^32, way outside window. */ if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) { @@ -17846,7 +17940,7 @@ static WC_INLINE int Dtls13CheckWindow(WOLFSSL* ssl) nextSeq = ssl->dtls13DecryptEpoch->nextPeerSeqNumber; window = ssl->dtls13DecryptEpoch->window; - seq = ssl->keys.curSeq; + seq = ssl->keys->curSeq; if (w64GTE(seq, nextSeq)) return 1; @@ -18008,24 +18102,24 @@ int wolfSSL_DtlsUpdateWindow(word16 cur_hi, word32 cur_lo, int DtlsUpdateWindow(WOLFSSL* ssl) { - WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys->peerSeq; word16 *next_hi; word32 *next_lo; word32* window; #ifdef WOLFSSL_MULTICAST - word32 cur_lo = ssl->keys.curSeq_lo; + word32 cur_lo = ssl->keys->curSeq_lo; if (ssl->options.haveMcast) { WOLFSSL_DTLS_PEERSEQ* p; int i; peerSeq = NULL; - for (i = 0, p = ssl->keys.peerSeq; + for (i = 0, p = ssl->keys->peerSeq; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++, p++) { - if (p->peerId == ssl->keys.curPeerId) { + if (p->peerId == ssl->keys->curPeerId) { peerSeq = p; break; } @@ -18056,7 +18150,7 @@ int DtlsUpdateWindow(WOLFSSL* ssl) } #endif - if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + if (ssl->keys->curEpoch == peerSeq->nextEpoch) { next_hi = &peerSeq->nextSeq_hi; next_lo = &peerSeq->nextSeq_lo; window = peerSeq->window; @@ -18067,7 +18161,7 @@ int DtlsUpdateWindow(WOLFSSL* ssl) window = peerSeq->prevWindow; } - return wolfSSL_DtlsUpdateWindow(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo, + return wolfSSL_DtlsUpdateWindow(ssl->keys->curSeq_hi, ssl->keys->curSeq_lo, next_hi, next_lo, window); } @@ -18095,9 +18189,10 @@ static int Dtls13UpdateWindow(WOLFSSL* ssl) return BAD_STATE_E; } - if (!w64Equal(ssl->keys.curEpoch64, ssl->dtls13DecryptEpoch->epochNumber)) { + if (!w64Equal(ssl->keys->curEpoch64, + ssl->dtls13DecryptEpoch->epochNumber)) { /* ssl->dtls13DecryptEpoch has been updated since we received the msg */ - e = Dtls13GetEpoch(ssl, ssl->keys.curEpoch64); + e = Dtls13GetEpoch(ssl, ssl->keys->curEpoch64); if (e == NULL) { WOLFSSL_MSG("Can't find decrypting Epoch"); return BAD_STATE_E; @@ -18106,7 +18201,7 @@ static int Dtls13UpdateWindow(WOLFSSL* ssl) nextSeq = e->nextPeerSeqNumber; window = e->window; - seq = ssl->keys.curSeq; + seq = ssl->keys->curSeq; /* seq < nextSeq */ if (w64LT(seq, nextSeq)) { @@ -18162,7 +18257,7 @@ int DtlsMsgDrain(WOLFSSL* ssl) * message, and it is complete, and there hasn't been an error in the * last message... */ while (item != NULL && - ssl->keys.dtls_expected_peer_handshake_number == item->seq && + ssl->keys->dtls_expected_peer_handshake_number == item->seq && item->ready && ret == 0) { word32 idx = 0; @@ -18249,9 +18344,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return LENGTH_ERROR; } - if (type == finished && ssl->keys.dtls_peer_handshake_number >= - ssl->keys.dtls_expected_peer_handshake_number && - ssl->keys.curEpoch == ssl->keys.dtls_epoch) { + if (type == finished && ssl->keys->dtls_peer_handshake_number >= + ssl->keys->dtls_expected_peer_handshake_number && + ssl->keys->curEpoch == ssl->keys->dtls_epoch) { /* finished msg should be ignore from the current epoch * if it comes from a previous handshake */ if (ssl->options.side == WOLFSSL_CLIENT_END) { @@ -18281,8 +18376,8 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, * order, if so, process it. (Repeat until list exhausted.) If the * head is out of order, return for more processing. */ - if (ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number && + if (ssl->keys->dtls_peer_handshake_number > + ssl->keys->dtls_expected_peer_handshake_number && /* Only client_hello shouldn't be ignored if the handshake * num is greater */ (type == client_hello || @@ -18304,15 +18399,15 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return DTLS_TOO_MANY_FRAGMENTS_E; } - DtlsMsgStore(ssl, ssl->keys.curEpoch, - ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, ssl->keys->curEpoch, + ssl->keys->dtls_peer_handshake_number, input + *inOutIdx, size, type, fragOffset, fragSz, ssl->heap); *inOutIdx += fragSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + if (ssl->options.startedETMRead && ssl->keys->curEpoch != 0) { word32 digestSz = MacSize(ssl); - if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) { + if (*inOutIdx + ssl->keys->padSz + digestSz > totalSz) { WOLFSSL_ERROR(BUFFER_E); return BUFFER_E; } @@ -18321,12 +18416,12 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, else #endif { - if (*inOutIdx + ssl->keys.padSz > totalSz) { + if (*inOutIdx + ssl->keys->padSz > totalSz) { WOLFSSL_ERROR(BUFFER_E); return BUFFER_E; } } - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; ret = 0; #ifndef WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT /* If we receive an out of order last flight msg then retransmit */ @@ -18354,21 +18449,21 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } } } - else if (ssl->keys.dtls_peer_handshake_number < - ssl->keys.dtls_expected_peer_handshake_number || + else if (ssl->keys->dtls_peer_handshake_number < + ssl->keys->dtls_expected_peer_handshake_number || /* ignore all handshake messages if we are done with the * handshake */ - (ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number && + (ssl->keys->dtls_peer_handshake_number > + ssl->keys->dtls_expected_peer_handshake_number && ssl->options.handShakeState == HANDSHAKE_DONE) || ignoreFinished) { /* Already saw this message and processed it. It can be ignored. */ WOLFSSL_MSG("Already saw this message and processed it"); *inOutIdx += fragSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + if (ssl->options.startedETMRead && ssl->keys->curEpoch != 0) { word32 digestSz = MacSize(ssl); - if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) { + if (*inOutIdx + ssl->keys->padSz + digestSz > totalSz) { WOLFSSL_ERROR(BUFFER_E); return BUFFER_E; } @@ -18377,7 +18472,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, else #endif { - if (*inOutIdx + ssl->keys.padSz > totalSz) { + if (*inOutIdx + ssl->keys->padSz > totalSz) { WOLFSSL_ERROR(BUFFER_E); return BUFFER_E; } @@ -18389,7 +18484,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DtlsMsgPoolSend(ssl, 0); } #endif - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; } else if (fragSz < size) { /* Since this branch is in order, but fragmented, dtls_rx_msg_list will @@ -18408,14 +18503,14 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ERROR(DTLS_TOO_MANY_FRAGMENTS_E); return DTLS_TOO_MANY_FRAGMENTS_E; } - DtlsMsgStore(ssl, ssl->keys.curEpoch, - ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, ssl->keys->curEpoch, + ssl->keys->dtls_peer_handshake_number, input + *inOutIdx, size, type, fragOffset, fragSz, ssl->heap); *inOutIdx += fragSz; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + if (ssl->options.startedETMRead && ssl->keys->curEpoch != 0) { word32 digestSz = MacSize(ssl); if (*inOutIdx + digestSz > totalSz) { WOLFSSL_ERROR(BUFFER_E); @@ -18440,11 +18535,11 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ERROR(BUFFER_ERROR); return BUFFER_ERROR; } - if (idx + fragSz + ssl->keys.padSz > totalSz) + if (idx + fragSz + ssl->keys->padSz > totalSz) return BUFFER_E; - *inOutIdx = idx + fragSz + ssl->keys.padSz; + *inOutIdx = idx + fragSz + ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + if (ssl->options.startedETMRead && ssl->keys->curEpoch != 0) { word32 digestSz = MacSize(ssl); if (*inOutIdx + digestSz > totalSz) return BUFFER_E; @@ -18458,8 +18553,8 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Reached rx msg limit error"); return DTLS_TOO_MANY_FRAGMENTS_E; } - DtlsMsgStore(ssl, ssl->keys.curEpoch, - ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, ssl->keys->curEpoch, + ssl->keys->dtls_peer_handshake_number, input + idx, size, type, fragOffset, fragSz, ssl->heap); ret = DtlsMsgDrain(ssl); @@ -18499,7 +18594,7 @@ static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) { int i; for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) { - if (++ssl->keys.aead_exp_IV[i]) return; + if (++ssl->keys->aead_exp_IV[i]) return; } } #endif @@ -18586,7 +18681,7 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, #ifdef CHACHA_AEAD_TEST int i; #endif - Keys* keys = &ssl->keys; + Keys* keys = ssl->keys; XMEMSET(tag, 0, sizeof(tag)); XMEMSET(nonce, 0, sizeof(nonce)); @@ -18603,7 +18698,7 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, */ /* opaque SEQ number stored for AD */ if (ssl->options.dtls && DtlsSCRKeysSet(ssl)) { - if (ssl->keys.dtls_epoch == + if (ssl->keys->dtls_epoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) { keys = &ssl->secure_renegotiation->tmp_keys; WriteSEQ(ssl, CUR_ORDER, add); @@ -18795,7 +18890,7 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ int ret = 0; int msgLen = (sz - ssl->specs.aead_mac_size); - Keys* keys = &ssl->keys; + Keys* keys = ssl->keys; #ifdef CHACHA_AEAD_TEST int i; @@ -18820,7 +18915,7 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, * has the latest epoch cipher material */ if (ssl->options.dtls && DtlsSCRKeysSet(ssl) && - ssl->keys.curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) + ssl->keys->curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) keys = &ssl->secure_renegotiation->tmp_keys; #endif @@ -19008,7 +19103,6 @@ typedef int (*Sm4AuthDecryptFunc)(wc_Sm4* sm4, byte* out, const byte* in, #endif - static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, int asyncOkay) { @@ -19120,9 +19214,9 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) XMEMCPY(ssl->encrypt.nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + ssl->keys->aead_enc_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ssl->keys->aead_exp_IV, AESGCM_EXP_IV_SZ); #endif #ifdef HAVE_PK_CALLBACKS ret = NOT_COMPILED_IN; @@ -19188,9 +19282,9 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, ssl->encrypt.additional + AEAD_LEN_OFFSET); XMEMCPY(ssl->encrypt.nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + ssl->keys->aead_enc_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ssl->keys->aead_exp_IV, AESGCM_EXP_IV_SZ); outBuf = (byte*)XMALLOC(sz - AESGCM_EXP_IV_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (outBuf == NULL) { @@ -19291,9 +19385,9 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, c16toa(sz - GCM_EXP_IV_SZ - ssl->specs.aead_mac_size, ssl->encrypt.additional + AEAD_LEN_OFFSET); XMEMCPY(ssl->encrypt.nonce, - ssl->keys.aead_enc_imp_IV, GCM_IMP_IV_SZ); + ssl->keys->aead_enc_imp_IV, GCM_IMP_IV_SZ); XMEMCPY(ssl->encrypt.nonce + GCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, GCM_EXP_IV_SZ); + ssl->keys->aead_exp_IV, GCM_EXP_IV_SZ); ret = sm4_auth_fn(ssl->encrypt.sm4, out + GCM_EXP_IV_SZ, input + GCM_EXP_IV_SZ, sz - GCM_EXP_IV_SZ - ssl->specs.aead_mac_size, @@ -19473,8 +19567,10 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) AeadIncrementExpIV(ssl); #endif + #ifndef WOLFSSL_NO_FORCE_ZERO if (ssl->encrypt.nonce) ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); + #endif } #endif /* BUILD_AESGCM || HAVE_AESCCM || HAVE_ARIA */ #if defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM) @@ -19603,7 +19699,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, AESGCM_IMP_IV_SZ); else #endif - XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + XMEMCPY(ssl->decrypt.nonce, ssl->keys->aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -19666,7 +19762,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, AESGCM_IMP_IV_SZ); else #endif - XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + XMEMCPY(ssl->decrypt.nonce, ssl->keys->aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -19767,7 +19863,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, GCM_IMP_IV_SZ); else #endif - XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + XMEMCPY(ssl->decrypt.nonce, ssl->keys->aead_dec_imp_IV, GCM_IMP_IV_SZ); XMEMCPY(ssl->decrypt.nonce + GCM_IMP_IV_SZ, input, GCM_EXP_IV_SZ); if ((ret = sm4_auth_fn(ssl->decrypt.sm4, @@ -19907,9 +20003,9 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) #if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) if (ssl->options.dtls && DtlsSCRKeysSet(ssl)) { /* For epochs >1 the current cipher parameters are located in - * ssl->secure_renegotiation->tmp_keys. Previous cipher + * ssl->secure_renegotiation->tmp_keys Previous cipher * parameters and for epoch 1 use ssl->keys */ - if (ssl->keys.curEpoch == + if (ssl->keys->curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) { if (ssl->decrypt.src != SCR) { ssl->secure_renegotiation->cache_status = @@ -19948,8 +20044,11 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) /* make sure AES GCM/CCM nonce is cleared */ if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + + #ifndef WOLFSSL_NO_FORCE_ZERO if (ssl->decrypt.nonce) ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ); + #endif if (ret < 0) { ret = VERIFY_MAC_ERROR; @@ -20000,6 +20099,7 @@ static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl) (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha); } + /* check cipher text size for sanity */ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) { @@ -20053,7 +20153,6 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) return 0; } - #ifndef WOLFSSL_AEAD_ONLY #ifdef WOLSSL_OLD_TIMINGPADVERIFY #define COMPRESS_LOWER 64 @@ -20322,6 +20421,8 @@ static WC_INLINE int GetRounds(int pLen, int padLen, int t) #else #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + +#ifndef NO_OLD_TLS /* check all length bytes for the pad value, return 0 on success */ static int PadCheck(const byte* a, byte pad, int length) { @@ -20334,6 +20435,7 @@ static int PadCheck(const byte* a, byte pad, int length) return compareSum; } +#endif /* Mask the padding bytes with the expected values. @@ -20466,7 +20568,7 @@ int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz, int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) { - word32 msgSz = WOLFSSL_IS_QUIC(ssl)? ssl->curSize : ssl->keys.encryptSz; + word32 msgSz = WOLFSSL_IS_QUIC(ssl)? ssl->curSize : ssl->keys->encryptSz; word32 idx = *inOutIdx; int dataSz; int ivExtra = 0; @@ -20522,7 +20624,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) * keys and we can stop using the old keys. */ if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { if (!w64IsZero(ssl->dtls13InvalidateBefore) && - w64Equal(ssl->keys.curEpoch64, ssl->dtls13InvalidateBefore)) { + w64Equal(ssl->keys->curEpoch64, ssl->dtls13InvalidateBefore)) { Dtls13SetOlderEpochSide(ssl, ssl->dtls13InvalidateBefore, ENCRYPT_SIDE_ONLY); w64Zero(&ssl->dtls13InvalidateBefore); @@ -20542,7 +20644,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) ivExtra = AESGCM_EXP_IV_SZ; } - dataSz = (int)(msgSz - (word32)ivExtra - ssl->keys.padSz); + dataSz = (int)(msgSz - (word32)ivExtra - ssl->keys->padSz); #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) dataSz -= MacSize(ssl); @@ -20584,7 +20686,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) ssl->buffers.clearOutputBuffer.length = (unsigned int)dataSz; } - idx += ssl->keys.padSz; + idx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) idx += MacSize(ssl); @@ -20613,6 +20715,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) return 0; } +#ifndef NO_ALERT_STRINGS const char* AlertTypeToString(int type) { switch (type) { @@ -20789,13 +20892,14 @@ const char* AlertTypeToString(int type) "no_application_protocol"; return no_application_protocol_str; } - default: WOLFSSL_MSG("Unknown Alert"); return NULL; } } +#endif /* !NO_ALERT_STRINGS */ +#ifndef WOLFSSL_LEANPSK static void LogAlert(int type) { #ifdef DEBUG_WOLFSSL @@ -20815,6 +20919,7 @@ static void LogAlert(int type) (void)type; #endif /* DEBUG_WOLFSSL */ } +#endif /* process alert, return level */ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type) @@ -20852,7 +20957,7 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type) ivExtra = AESGCM_EXP_IV_SZ; } dataSz -= ivExtra; - dataSz -= ssl->keys.padSz; + dataSz -= ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) dataSz -= MacSize(ssl); @@ -20886,7 +20991,9 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type) return ALERT_COUNT_E; } +#ifndef WOLFSSL_LEANPSK LogAlert(*type); +#endif if (*type == close_notify) { ssl->options.closeNotify = 1; } @@ -20899,7 +21006,7 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type) } if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) *inOutIdx += MacSize(ssl); @@ -21037,7 +21144,6 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, #endif byte verify[WC_MAX_DIGEST_SIZE]; - if (ssl->specs.cipher_type == block) { int ivExtra = 0; if (ssl->options.tls1_1) @@ -21066,6 +21172,7 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, if (ret != 0) return ret; } +#ifndef NO_OLD_TLS else { /* sslv3, some implementations have bad padding, but don't * allow bad read */ int badPadLen = 0; @@ -21091,6 +21198,7 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, return VERIFY_MAC_ERROR; } } +#endif } else if (ssl->specs.cipher_type == stream) { ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, @@ -21109,8 +21217,9 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, if (ssl->specs.cipher_type == aead) { *padSz = ssl->specs.aead_mac_size; } + else #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) - else { + { *padSz = digestSz + pad + padByte; } #endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ @@ -21159,7 +21268,7 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode) #ifdef WOLFSSL_DTLS13 if (IsAtLeastTLSv1_3(ssl->version) && !w64IsZero(ssl->dtls13Epoch) - && w64IsZero(ssl->keys.curEpoch64) && ssl->curRL.type != ack) { + && w64IsZero(ssl->keys->curEpoch64) && ssl->curRL.type != ack) { WOLFSSL_MSG("Silently dropping plaintext DTLS message " "during encrypted handshake."); return 1; @@ -21180,6 +21289,7 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode) } #endif /* WOLFSSL_DTLS */ + int ProcessReply(WOLFSSL* ssl) { return ProcessReplyEx(ssl, 0); @@ -21285,11 +21395,14 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif /* get header or return error */ + #ifdef WOLFSSL_DTLS if (!ssl->options.dtls) { + #endif if ((ret = GetInputData(ssl, (word32)readSz)) < 0) return ret; - } else { #ifdef WOLFSSL_DTLS + } + else { /* read ahead may already have header */ used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; @@ -21297,8 +21410,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) if ((ret = GetInputData(ssl, (word32)readSz)) < 0) return ret; } - #endif } + #endif #ifdef OLD_HELLO_ALLOWED @@ -21443,7 +21556,9 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) case getData: /* get sz bytes or return error */ +#ifdef WOLFSSL_DTLS if (!ssl->options.dtls) { +#endif if ((ret = GetInputData(ssl, ssl->curSize)) < 0) { #ifdef WOLFSSL_EXTRA_ALERTS if (ret != WC_NO_ERR_TRACE(WANT_READ)) @@ -21451,17 +21566,17 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif return ret; } +#ifdef WOLFSSL_DTLS } else { -#ifdef WOLFSSL_DTLS /* read ahead may already have */ used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; if (used < ssl->curSize) if ((ret = GetInputData(ssl, ssl->curSize)) < 0) return ret; -#endif } +#endif if (IsEncryptionOn(ssl, 0)) { #if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) @@ -21471,8 +21586,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version)) { tooLong = ssl->curSize > MAX_TLS13_ENC_SZ; - tooLong |= ssl->curSize - ssl->specs.aead_mac_size > - MAX_TLS13_PLAIN_SZ; + tooLong |= (int)(ssl->curSize - ssl->specs.aead_mac_size) > + (int)MAX_TLS13_PLAIN_SZ; } #endif #ifdef WOLFSSL_EXTRA_ALERTS @@ -21487,7 +21602,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } #endif } - ssl->keys.padSz = 0; + ssl->keys->padSz = 0; ssl->options.processReply = verifyEncryptedMessage; /* in case > 1 msg per record */ @@ -21497,7 +21612,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* verify digest of encrypted message */ case verifyEncryptedMessage: #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0 && !atomicUser && ssl->options.startedETMRead) { ret = VerifyMacEnc(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, @@ -21525,7 +21640,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR); return DECRYPT_ERROR; } - ssl->keys.encryptSz = ssl->curSize; + ssl->keys->encryptSz = ssl->curSize; } #endif ssl->options.processReply = decryptMessage; @@ -21534,7 +21649,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* decrypt message */ case decryptMessage: - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0 && (!IsAtLeastTLSv1_3(ssl->version) || ssl->curRL.type != change_cipher_spec)) { @@ -21555,7 +21670,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ret = ssl->ctx->VerifyDecryptCb(ssl, in->buffer + in->idx, in->buffer + in->idx, ssl->curSize - MacSize(ssl), - ssl->curRL.type, 1, &ssl->keys.padSz, + ssl->curRL.type, 1, &ssl->keys->padSz, ssl->DecryptVerifyCtx); } else @@ -21565,7 +21680,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) in->buffer + in->idx, in->buffer + in->idx, ssl->curSize, ssl->curRL.type, 1, - &ssl->keys.padSz, ssl->DecryptVerifyCtx); + &ssl->keys->padSz, ssl->DecryptVerifyCtx); } #endif /* ATOMIC_USER */ } @@ -21586,7 +21701,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) word32 off = in->idx + ssl->curSize - digestSz - 1; /* Last of padding bytes - indicates length. */ - ssl->keys.padSz = in->buffer[off]; + ssl->keys->padSz = in->buffer[off]; /* Constant time checking of padding - don't leak * the length of the data. */ @@ -21596,20 +21711,20 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) * padding byte. */ padding &= ctMaskLTE((int)i, - (int)ssl->keys.padSz); + (int)ssl->keys->padSz); /* When this is a padding byte and not equal * to length then mask is set. */ invalid |= padding & ctMaskNotEq(in->buffer[off - i], - (int)ssl->keys.padSz); + (int)ssl->keys->padSz); } /* If mask is set then there was an error. */ if (invalid) { ret = DECRYPT_ERROR; } - ssl->keys.padSz += 1; - ssl->keys.decryptedCur = 1; + ssl->keys->padSz += 1; + ssl->keys->decryptedCur = 1; } } else @@ -21689,8 +21804,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) { WOLFSSL_MSG("Ignoring EarlyData!"); - if (ssl->keys.peer_sequence_number_lo-- == 0) - ssl->keys.peer_sequence_number_hi--; + if (ssl->keys->peer_sequence_number_lo-- == 0) + ssl->keys->peer_sequence_number_hi--; ssl->options.processReply = doProcessInit; ssl->buffers.inputBuffer.idx += ssl->curSize; if (ssl->buffers.inputBuffer.idx > @@ -21721,7 +21836,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* verify digest of message */ case verifyMessage: - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + if (IsEncryptionOn(ssl, 0) && ssl->keys->decryptedCur == 0 && (!IsAtLeastTLSv1_3(ssl->version) || ssl->curRL.type != change_cipher_spec)) { @@ -21733,7 +21848,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, ssl->curSize, ssl->curRL.type, - &ssl->keys.padSz); + &ssl->keys->padSz); #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; @@ -21759,8 +21874,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } } - ssl->keys.encryptSz = ssl->curSize; - ssl->keys.decryptedCur = 1; + ssl->keys->encryptSz = ssl->curSize; + ssl->keys->decryptedCur = 1; #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { word32 i = (ssl->buffers.inputBuffer.idx + @@ -21781,7 +21896,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* Get the real content type from the end of the data. */ ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i]; /* consider both contentType byte and MAC as padding */ - ssl->keys.padSz = ssl->buffers.inputBuffer.idx + ssl->keys->padSz = ssl->buffers.inputBuffer.idx + ssl->curSize - i; } #endif @@ -21835,7 +21950,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) { /* For TLS v1.1 the block size and explicit IV are added to idx, * so it needs to be included in this limit check */ - if ((ssl->curSize - ssl->keys.padSz - + if ((ssl->curSize - ssl->keys->padSz - (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) - MacSize(ssl) > MAX_PLAINTEXT_SZ) #ifdef WOLFSSL_ASYNC_CRYPT @@ -21857,7 +21972,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* For TLS v1.1 the block size and explicit IV are added to idx, * so it needs to be included in this limit check */ if (!IsAtLeastTLSv1_3(ssl->version) - && ssl->curSize - ssl->keys.padSz - + && ssl->curSize - ssl->keys->padSz - (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) > MAX_PLAINTEXT_SZ #ifdef WOLFSSL_ASYNC_CRYPT @@ -21878,9 +21993,9 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) switch (ssl->curRL.type) { case handshake : WOLFSSL_MSG("got HANDSHAKE"); +#ifdef WOLFSSL_DTLS /* debugging in DoHandShakeMsg */ if (ssl->options.dtls) { -#ifdef WOLFSSL_DTLS if (!IsAtLeastTLSv1_3(ssl->version)) { ret = DoDtlsHandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, @@ -21899,7 +22014,6 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } } } -#endif #ifdef WOLFSSL_DTLS13 if (IsAtLeastTLSv1_3(ssl->version)) { ret = Dtls13HandshakeRecv(ssl, @@ -21924,7 +22038,9 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } #endif /* WOLFSSL_DTLS13 */ } - else if (!IsAtLeastTLSv1_3(ssl->version) + else +#endif /* WOLFSSL_DTLS */ + if (!IsAtLeastTLSv1_3(ssl->version) #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12) || !TLSv1_3_Capable(ssl) #endif @@ -22057,8 +22173,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) else #endif { - ssl->buffers.inputBuffer.idx += ssl->keys.padSz; - ssl->curSize -= (word16)ssl->keys.padSz; + ssl->buffers.inputBuffer.idx += ssl->keys->padSz; + ssl->curSize -= (word16)ssl->keys->padSz; ssl->curSize -= ssl->specs.iv_size; } @@ -22099,7 +22215,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } } - ssl->keys.encryptionOn = 1; + ssl->keys->encryptionOn = 1; /* setup decrypt keys for following messages */ /* XXX This might not be what we want to do when @@ -22114,10 +22230,10 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys->peerSeq; #ifdef WOLFSSL_MULTICAST if (ssl->options.haveMcast) { - peerSeq += ssl->keys.curPeerId; + peerSeq += ssl->keys->curPeerId; peerSeq->highwaterMark = UpdateHighwaterMark(0, ssl->ctx->mcastFirstSeq, ssl->ctx->mcastSecondSeq, @@ -22170,7 +22286,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } #endif #ifdef WOLFSSL_TLS13 - if (ssl->keys.keyUpdateRespond) { + if (ssl->keys->keyUpdateRespond) { WOLFSSL_MSG("No KeyUpdate from peer seen"); WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E); return SANITY_MSG_E; @@ -22225,9 +22341,9 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx - - ssl->keys.padSz, &processedSize); + ssl->keys->padSz, &processedSize); ssl->buffers.inputBuffer.idx += processedSize; - ssl->buffers.inputBuffer.idx += ssl->keys.padSz; + ssl->buffers.inputBuffer.idx += ssl->keys->padSz; if (ret != 0) return ret; break; @@ -22272,14 +22388,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ssl->options.processReply = runProcessingOneMessage; if (IsEncryptionOn(ssl, 0)) { - WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); + WOLFSSL_MSG( + "Bundled encrypted messages, remove middle pad"); #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); if (ssl->buffers.inputBuffer.idx >= - ssl->keys.padSz + digestSz) { + ssl->keys->padSz + digestSz) { ssl->buffers.inputBuffer.idx -= - ssl->keys.padSz + digestSz; + ssl->keys->padSz + digestSz; } else { WOLFSSL_MSG("\tmiddle padding error"); @@ -22290,8 +22407,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) else #endif { - if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) { - ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + if (ssl->buffers.inputBuffer.idx >= ssl->keys->padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys->padSz; } else { WOLFSSL_MSG("\tmiddle padding error"); @@ -22843,7 +22960,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) if (ssl->options.dtls && DtlsSCRKeysSet(ssl)) { /* For epochs >1 the current cipher parameters are located in - * ssl->secure_renegotiation->tmp_keys. Previous cipher + * ssl->secure_renegotiation->tmp_keys Previous cipher * parameters and for epoch 1 use ssl->keys */ switch (epochOrder) { case PREV_ORDER: @@ -22855,7 +22972,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } break; case CUR_ORDER: - if (ssl->keys.dtls_epoch == + if (ssl->keys->dtls_epoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) { if (ssl->encrypt.src != SCR) { ssl->secure_renegotiation->cache_status = @@ -22913,7 +23030,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } if (ssl->options.tls1_1) { - args->ivSz = blockSz; + args->ivSz = (byte)blockSz; args->sz += args->ivSz; if (args->ivSz > MAX_IV_SZ) @@ -22976,7 +23093,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, defined(HAVE_AEAD)) if (ssl->specs.cipher_type == aead) { if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + XMEMCPY(args->iv, ssl->keys->aead_exp_IV, AESGCM_EXP_IV_SZ); } #endif @@ -23122,14 +23239,14 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int swap_seq = ssl->options.dtls && epochOrder == PREV_ORDER && DtlsUseSCRKeys(ssl); if (swap_seq) { - dtls_epoch = ssl->keys.dtls_epoch; - dtls_sequence_number_hi = ssl->keys.dtls_sequence_number_hi; - dtls_sequence_number_lo = ssl->keys.dtls_sequence_number_lo; - ssl->keys.dtls_epoch--; - ssl->keys.dtls_sequence_number_hi = - ssl->keys.dtls_prev_sequence_number_hi; - ssl->keys.dtls_sequence_number_lo = - ssl->keys.dtls_prev_sequence_number_lo; + dtls_epoch = ssl->keys->dtls_epoch; + dtls_sequence_number_hi = ssl->keys->dtls_sequence_number_hi; + dtls_sequence_number_lo = ssl->keys->dtls_sequence_number_lo; + ssl->keys->dtls_epoch--; + ssl->keys->dtls_sequence_number_hi = + ssl->keys->dtls_prev_sequence_number_hi; + ssl->keys->dtls_sequence_number_lo = + ssl->keys->dtls_prev_sequence_number_lo; } #endif #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) @@ -23148,9 +23265,9 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #if defined(HAVE_SECURE_RENEGOTIATION) && defined(WOLFSSL_DTLS) /* Restore sequence numbers */ if (swap_seq) { - ssl->keys.dtls_epoch = dtls_epoch; - ssl->keys.dtls_sequence_number_hi = dtls_sequence_number_hi; - ssl->keys.dtls_sequence_number_lo = dtls_sequence_number_lo; + ssl->keys->dtls_epoch = dtls_epoch; + ssl->keys->dtls_sequence_number_hi = dtls_sequence_number_hi; + ssl->keys->dtls_sequence_number_lo = dtls_sequence_number_lo; } #endif } @@ -23169,7 +23286,9 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, else #endif { + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(output + args->headerSz, (word16)args->size); + #endif } } goto exit_buildmsg; @@ -23302,13 +23421,13 @@ int SendFinished(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { headerSz += DTLS_HANDSHAKE_EXTRA; - ssl->keys.dtls_epoch++; - ssl->keys.dtls_prev_sequence_number_hi = - ssl->keys.dtls_sequence_number_hi; - ssl->keys.dtls_prev_sequence_number_lo = - ssl->keys.dtls_sequence_number_lo; - ssl->keys.dtls_sequence_number_hi = 0; - ssl->keys.dtls_sequence_number_lo = 0; + ssl->keys->dtls_epoch++; + ssl->keys->dtls_prev_sequence_number_hi = + ssl->keys->dtls_sequence_number_hi; + ssl->keys->dtls_prev_sequence_number_lo = + ssl->keys->dtls_sequence_number_lo; + ssl->keys->dtls_sequence_number_hi = 0; + ssl->keys->dtls_sequence_number_lo = 0; } #endif @@ -23416,8 +23535,8 @@ int SendFinished(WOLFSSL* ssl) ssl->options.side == WOLFSSL_SERVER_END) || (ssl->options.resuming && ssl->options.side == WOLFSSL_CLIENT_END)) { - ssl->keys.dtls_handshake_number = 0; - ssl->keys.dtls_expected_peer_handshake_number = 0; + ssl->keys->dtls_handshake_number = 0; + ssl->keys->dtls_expected_peer_handshake_number = 0; } #endif @@ -23754,9 +23873,9 @@ int SendCertificate(WOLFSSL* ssl) HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); /* Adding the headers increments these, decrement them for * actual message header. */ - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; #endif /* WOLFSSL_DTLS */ } @@ -23797,7 +23916,7 @@ int SendCertificate(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz, payloadSz, certificate, ssl); - ssl->keys.dtls_handshake_number--; + ssl->keys->dtls_handshake_number--; #endif /* WOLFSSL_DTLS */ } } @@ -23901,7 +24020,7 @@ int SendCertificate(WOLFSSL* ssl) ssl->fragOffset = 0; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) - ssl->keys.dtls_handshake_number++; + ssl->keys->dtls_handshake_number++; #endif if (ssl->options.side == WOLFSSL_SERVER_END){ ssl->options.serverState = SERVER_CERT_COMPLETE; @@ -24161,7 +24280,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, #endif sendSz = (int)(idx + length); - if (ssl->keys.encryptionOn) + if (ssl->keys->encryptionOn) sendSz += MAX_MSG_EXTRA; output =(byte*)XMALLOC(sendSz, ssl->heap, DYNAMIC_TYPE_OCSP); @@ -24419,7 +24538,7 @@ int DtlsSCRKeysSet(WOLFSSL* ssl) int IsDtlsMsgSCRKeys(WOLFSSL* ssl) { return DtlsSCRKeysSet(ssl) && - ssl->keys.curEpoch == + ssl->keys->curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch; } @@ -24433,17 +24552,18 @@ int DtlsUseSCRKeys(WOLFSSL* ssl) { return DtlsSCRKeysSet(ssl) && ssl->secure_renegotiation->tmp_keys.dtls_epoch == - ssl->keys.dtls_epoch; + ssl->keys->dtls_epoch; } /** - * If ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch + * If ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys->dtls_epoch * then PREV_ORDER refers to the current epoch. * */ int DtlsCheckOrder(WOLFSSL* ssl, int order) { if (order == PREV_ORDER && ssl->secure_renegotiation && - ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch) { + ssl->secure_renegotiation->tmp_keys.dtls_epoch > + ssl->keys->dtls_epoch) { return CUR_ORDER; } else { @@ -24452,6 +24572,7 @@ int DtlsCheckOrder(WOLFSSL* ssl, int order) } #endif /* HAVE_SECURE_RENEGOTIATION && WOLFSSL_DTLS */ + /* If secure renegotiation is disabled, this will always return false. * Otherwise it checks to see if we are currently renegotiating. */ int IsSCR(WOLFSSL* ssl) @@ -24552,8 +24673,8 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl) else #endif { - seq = w64From32(ssl->keys.sequence_number_hi, - ssl->keys.sequence_number_lo); + seq = w64From32(ssl->keys->sequence_number_hi, + ssl->keys->sequence_number_lo); } if (w64GTE(seq, limit)) { /* cppcheck-suppress uninitvar @@ -24593,6 +24714,7 @@ static int ssl_in_handshake(WOLFSSL *ssl, int send) if (ssl->options.handShakeState != HANDSHAKE_DONE) return 1; +#ifndef NO_WOLFSSL_SERVER if (ssl->options.side == WOLFSSL_SERVER_END) { if (IsAtLeastTLSv1_3(ssl->version)) return ssl->options.acceptState < TLS13_TICKET_SENT; @@ -24600,6 +24722,7 @@ static int ssl_in_handshake(WOLFSSL *ssl, int send) return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE; return 0; } +#endif if (ssl->options.side == WOLFSSL_CLIENT_END) { if (IsAtLeastTLSv1_3(ssl->version)) @@ -24634,10 +24757,13 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) ssl->error == WC_NO_ERR_TRACE(DECRYPT_ERROR)) { /* For DTLS allow these possible errors and allow the session to continue despite them */ +#ifdef WOLFSSL_DTLS if (ssl->options.dtls) { ssl->error = 0; } - else { + else +#endif + { WOLFSSL_MSG("Not allowing write after decrypt or mac error"); return WOLFSSL_FATAL_ERROR; } @@ -24927,6 +25053,9 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) #endif { if (ssl_in_handshake(ssl, 0)) { +#ifdef WOLFSSL_LEANPSK + return BAD_FUNC_ARG; +#else int err; WOLFSSL_MSG("Handshake not complete, trying to finish"); if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { @@ -24938,6 +25067,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) #endif return err; } +#endif } } @@ -25055,8 +25185,9 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type) WOLFSSL_ENTER("SendAlert"); +#ifndef NO_ALERT_STRINGS WOLFSSL_MSG_EX("SendAlert: %d %s", type, AlertTypeToString(type)); - +#endif #ifdef WOLFSSL_QUIC if (WOLFSSL_IS_QUIC(ssl)) { ret = !ssl->quic.method->send_alert(ssl, ssl->quic.enc_level_write, (uint8_t)type); @@ -25922,6 +26053,7 @@ void SetErrorString(int error, char* str) str[WOLFSSL_MAX_ERROR_SZ-1] = 0; } + #ifdef NO_CIPHER_SUITE_ALIASES #ifndef NO_ERROR_STRINGS #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) @@ -26462,7 +26594,7 @@ int GetCipherNamesSize(void) } -const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite) +const char* GetCipherNameInternal(byte cipherSuite0, byte cipherSuite) { int i; const char* nameInternal = "None"; @@ -26775,7 +26907,8 @@ int SetCipherBits(const char* enc) { } #endif /* WOLFSSL_QT || OPENSSL_ALL */ -const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite) +#ifndef WOLFSSL_LEANPSK +const char* GetCipherNameIana(byte cipherSuite0, byte cipherSuite) { #ifndef NO_ERROR_STRINGS int i; @@ -26799,6 +26932,7 @@ const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite) return NULL; #endif } +#endif const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl) { @@ -26809,6 +26943,7 @@ const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl) return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite); } +#ifndef WOLFSSL_LEANPSK const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl) { if (ssl == NULL) { @@ -27355,6 +27490,7 @@ int SetCipherList(const WOLFSSL_CTX* ctx, Suites* suites, { return SetCipherList_ex(ctx, NULL, suites, list); } +#endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES) int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list, @@ -28193,7 +28329,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz, #endif /* WOLFSSL_CALLBACKS */ #ifdef OPENSSL_EXTRA if ((ssl->protoMsgCb != NULL) && (sz > 0) && - (ssl->keys.encryptionOn != 1)) { + (ssl->keys->encryptionOn != 1)) { /* version from hex to dec 16 is 16^1, 256 from 16^2 and 4096 from 16^3 */ int version = (ssl->version.minor & 0x0F) + @@ -29736,8 +29872,10 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, int inputSz = (int)idx; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) recordHeaderSz += DTLS_RECORD_EXTRA; + #endif inputSz -= recordHeaderSz; input = (byte*)XMALLOC((size_t)inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); @@ -29802,7 +29940,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, return ret; } - +#ifdef WOLFSSL_DTLS /* handle processing of DTLS hello_verify_request (3) */ int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) @@ -29816,7 +29954,6 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo); #endif -#ifdef WOLFSSL_DTLS if (ssl->options.dtls) { DtlsMsgPoolReset(ssl); #ifdef WOLFSSL_DTLS_CID @@ -29824,7 +29961,6 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, DtlsCIDOnExtensionsParsed(ssl); #endif /* WOLFSSL_DTLS_CID */ } -#endif if (OPAQUE16_LEN + OPAQUE8_LEN > size) return BUFFER_ERROR; @@ -29842,12 +29978,10 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if ((*inOutIdx - begin) + cookieSz > size) return BUFFER_ERROR; -#ifdef WOLFSSL_DTLS if (cookieSz <= MAX_COOKIE_LEN) { XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz); ssl->arrays->cookieSz = cookieSz; } -#endif *inOutIdx += cookieSz; } @@ -29870,7 +30004,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, return 0; } - +#endif static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl) { @@ -29922,6 +30056,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } #endif +#ifdef WOLFSSL_DTLS if (ssl->options.dtls) { if (pv.major != DTLS_MAJOR || pv.minor == DTLS_BOGUS_MINOR) { WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); @@ -29930,7 +30065,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, lowerVersion = pv.minor > ssl->version.minor; higherVersion = pv.minor < ssl->version.minor; } - else { + else +#endif + { if (pv.major != SSLv3_MAJOR) { WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); return VERSION_ERROR; @@ -29973,6 +30110,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, /* Checks made - OK to downgrade. */ ssl->version.minor = pv.minor; switch(pv.minor) { +#ifndef NO_OLD_TLS case SSLv3_MINOR: /* turn off tls */ WOLFSSL_MSG("\tdowngrading to SSLv3"); @@ -29987,15 +30125,18 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, case TLSv1_1_MINOR: WOLFSSL_MSG("\tdowngrading to TLSv1.1"); break; - case DTLS_MINOR: - WOLFSSL_MSG("\tdowngrading to DTLSv1.1"); - break; +#endif case TLSv1_2_MINOR: WOLFSSL_MSG("\tdowngrading to TLSv1.2"); break; +#ifdef WOLFSSL_DTLS + case DTLS_MINOR: + WOLFSSL_MSG("\tdowngrading to DTLSv1.1"); + break; case DTLSv1_2_MINOR: WOLFSSL_MSG("\tdowngrading to DTLSv1.2"); break; +#endif default: WOLFSSL_MSG("\tbad minor version"); WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); @@ -30005,7 +30146,11 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, /* check if option is set to not allow the current version * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ - if (!ssl->options.dtls && ssl->options.downgrade && + if ( +#ifdef WOLFSSL_DTLS + !ssl->options.dtls && +#endif + ssl->options.downgrade && ssl->options.mask > 0) { if (ssl->version.minor == TLSv1_2_MINOR && @@ -30278,7 +30423,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, ssl->options.serverState = SERVER_HELLO_COMPLETE; if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMWrite && ssl->specs.cipher_type == block) { @@ -30314,12 +30459,12 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, int CompleteServerHello(WOLFSSL* ssl) { int ret; - + #ifdef WOLFSSL_TLS13 if (!ssl->options.resuming) { byte* down = ssl->arrays->serverRandom + RAN_LEN - TLS13_DOWNGRADE_SZ - 1; byte vers = ssl->arrays->serverRandom[RAN_LEN - 1]; - #ifdef WOLFSSL_TLS13 + if (TLSv1_3_Capable(ssl)) { /* TLS v1.3 capable client not allowed to downgrade when * connecting to TLS v1.3 capable server unless cipher suite @@ -30333,10 +30478,13 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } } else - #endif if (ssl->ctx->method->version.major == SSLv3_MAJOR && - ssl->ctx->method->version.minor == TLSv1_2_MINOR && - (wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_2) == 0) { + ssl->ctx->method->version.minor == TLSv1_2_MINOR + #ifndef WOLFSSL_LEANPSK + && + (wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_2) == 0 + #endif + ) { /* TLS v1.2 capable client not allowed to downgrade when * connecting to TLS v1.2 capable server. */ @@ -30348,7 +30496,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } } } - else { + else + #endif /* WOLFSSL_TLS13 */ + { if (DSH_CheckSessionId(ssl)) { if (SetCipherSpecs(ssl) == 0) { if (!HaveUniqueSessionObj(ssl)) { @@ -30618,7 +30768,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) *inOutIdx += MacSize(ssl); @@ -32012,7 +32162,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - args->idx += ssl->keys.padSz; + args->idx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) args->idx += MacSize(ssl); @@ -32549,7 +32699,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz); ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) + (2 * OPAQUE16_LEN); + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + #endif } ssl->arrays->psk_keySz = 0; /* No further need */ break; @@ -33188,9 +33340,12 @@ int SendClientKeyExchange(WOLFSSL* ssl) if (IsEncryptionOn(ssl, 1)) { int recordHeaderSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) recordHeaderSz += DTLS_RECORD_EXTRA; - args->inputSz = (int)idx - recordHeaderSz; /* buildmsg adds rechdr */ + #endif + /* buildmsg adds rechdr */ + args->inputSz = (int)idx - recordHeaderSz; args->input = (byte*)XMALLOC((size_t)args->inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (args->input == NULL) { @@ -33299,10 +33454,12 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif +#ifndef WOLFSSL_NO_FORCE_ZERO /* No further need for PMS */ if (ssl->arrays->preMasterSecret != NULL) { ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); } +#endif ssl->arrays->preMasterSz = 0; /* Final cleanup */ @@ -33981,7 +34138,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) *inOutIdx += MacSize(ssl); @@ -34281,7 +34438,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; -#ifdef WOLFSSL_TLS13 +#if defined(WOLFSSL_TLS13) if (TLSv1_3_Capable(ssl)) { /* TLS v1.3 capable server downgraded. */ XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), @@ -37793,7 +37950,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - args->idx += ssl->keys.padSz; + args->idx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) args->idx += MacSize(ssl); @@ -38842,8 +38999,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int inputSz = (int)idx; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) recordHeaderSz += DTLS_RECORD_EXTRA; + #endif inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) @@ -39631,8 +39790,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (!IsSCR(ssl)) #endif { - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + ssl->keys->dtls_sequence_number_hi = ssl->keys->curSeq_hi; + ssl->keys->dtls_sequence_number_lo = ssl->keys->curSeq_lo; } AddHeaders(output, (word32)length, hello_verify_request, ssl); @@ -40878,7 +41037,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - args->idx += ssl->keys.padSz; + args->idx += ssl->keys->padSz; #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) args->idx += MacSize(ssl); diff --git a/src/keys.c b/src/keys.c index 3123a610e0..0d2fdd039b 100644 --- a/src/keys.c +++ b/src/keys.c @@ -3479,7 +3479,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) int ret, copy = 0; Ciphers* wc_encrypt = NULL; Ciphers* wc_decrypt = NULL; - Keys* keys = &ssl->keys; + Keys* keys = ssl->keys; (void)copy; @@ -3583,9 +3583,9 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef WOLFSSL_DTLS if (ret == 0 && ssl->options.dtls && !ssl->options.tls1_3) { if (wc_encrypt) - wc_encrypt->src = keys == &ssl->keys ? KEYS : SCR; + wc_encrypt->src = keys == ssl->keys ? KEYS : SCR; if (wc_decrypt) - wc_decrypt->src = keys == &ssl->keys ? KEYS : SCR; + wc_decrypt->src = keys == ssl->keys ? KEYS : SCR; } #endif @@ -3595,7 +3595,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) /* Sanity check that keys == ssl->secure_renegotiation->tmp_keys. * Otherwise the memcpy calls would copy overlapping memory * and cause UB. Fail early. */ - if (keys == &ssl->keys) + if (keys == ssl->keys) return BAD_FUNC_ARG; if (ssl->options.side == WOLFSSL_CLIENT_END && wc_encrypt) @@ -3605,54 +3605,54 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) if (clientCopy) { #ifndef WOLFSSL_AEAD_ONLY - XMEMCPY(ssl->keys.client_write_MAC_secret, + XMEMCPY(ssl->keys->client_write_MAC_secret, keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE); #endif - XMEMCPY(ssl->keys.client_write_key, + XMEMCPY(ssl->keys->client_write_key, keys->client_write_key, AES_256_KEY_SIZE); - XMEMCPY(ssl->keys.client_write_IV, + XMEMCPY(ssl->keys->client_write_IV, keys->client_write_IV, MAX_WRITE_IV_SZ); } else { #ifndef WOLFSSL_AEAD_ONLY - XMEMCPY(ssl->keys.server_write_MAC_secret, + XMEMCPY(ssl->keys->server_write_MAC_secret, keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE); #endif - XMEMCPY(ssl->keys.server_write_key, + XMEMCPY(ssl->keys->server_write_key, keys->server_write_key, AES_256_KEY_SIZE); - XMEMCPY(ssl->keys.server_write_IV, + XMEMCPY(ssl->keys->server_write_IV, keys->server_write_IV, MAX_WRITE_IV_SZ); } if (wc_encrypt) { - ssl->keys.sequence_number_hi = keys->sequence_number_hi; - ssl->keys.sequence_number_lo = keys->sequence_number_lo; + ssl->keys->sequence_number_hi = keys->sequence_number_hi; + ssl->keys->sequence_number_lo = keys->sequence_number_lo; #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ - XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV, + XMEMCPY(ssl->keys->aead_exp_IV, keys->aead_exp_IV, AEAD_MAX_EXP_SZ); /* Initialize encrypt implicit IV by encrypt side */ if (ssl->options.side == WOLFSSL_CLIENT_END) { - XMEMCPY(ssl->keys.aead_enc_imp_IV, + XMEMCPY(ssl->keys->aead_enc_imp_IV, keys->client_write_IV, AEAD_MAX_IMP_SZ); } else { - XMEMCPY(ssl->keys.aead_enc_imp_IV, + XMEMCPY(ssl->keys->aead_enc_imp_IV, keys->server_write_IV, AEAD_MAX_IMP_SZ); } } #endif } if (wc_decrypt) { - ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi; - ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo; + ssl->keys->peer_sequence_number_hi = keys->peer_sequence_number_hi; + ssl->keys->peer_sequence_number_lo = keys->peer_sequence_number_lo; #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize decrypt implicit IV by decrypt side */ if (ssl->options.side == WOLFSSL_SERVER_END) { - XMEMCPY(ssl->keys.aead_dec_imp_IV, + XMEMCPY(ssl->keys->aead_dec_imp_IV, keys->client_write_IV, AEAD_MAX_IMP_SZ); } else { - XMEMCPY(ssl->keys.aead_dec_imp_IV, + XMEMCPY(ssl->keys->aead_dec_imp_IV, keys->server_write_IV, AEAD_MAX_IMP_SZ); } } @@ -3671,7 +3671,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { size_t sz; int i = 0; - Keys* keys = &ssl->keys; + Keys* keys = ssl->keys; #ifdef WOLFSSL_DTLS /* In case of DTLS, ssl->keys is updated here */ int scr_copy = 0; @@ -3684,9 +3684,10 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { /* epoch is incremented after StoreKeys is called */ - ssl->secure_renegotiation->tmp_keys.dtls_epoch = ssl->keys.dtls_epoch + 1; + ssl->secure_renegotiation->tmp_keys.dtls_epoch = + ssl->keys->dtls_epoch + 1; /* we only need to copy keys on second and future renegotiations */ - if (ssl->keys.dtls_epoch > 1) + if (ssl->keys->dtls_epoch > 1) scr_copy = 1; ssl->encrypt.src = KEYS_NOT_SET; ssl->decrypt.src = KEYS_NOT_SET; @@ -3705,9 +3706,9 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #ifdef WOLFSSL_DTLS if (scr_copy) { - XMEMCPY(ssl->keys.client_write_MAC_secret, + XMEMCPY(ssl->keys->client_write_MAC_secret, keys->client_write_MAC_secret, sz); - XMEMCPY(ssl->keys.server_write_MAC_secret, + XMEMCPY(ssl->keys->server_write_MAC_secret, keys->server_write_MAC_secret, sz); } #endif @@ -3719,9 +3720,9 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) sz = ssl->specs.key_size; #ifdef WOLFSSL_DTLS if (scr_copy) { - XMEMCPY(ssl->keys.client_write_key, + XMEMCPY(ssl->keys->client_write_key, keys->client_write_key, sz); - XMEMCPY(ssl->keys.server_write_key, + XMEMCPY(ssl->keys->server_write_key, keys->server_write_key, sz); } #endif @@ -3732,9 +3733,9 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) sz = ssl->specs.iv_size; #ifdef WOLFSSL_DTLS if (scr_copy) { - XMEMCPY(ssl->keys.client_write_IV, + XMEMCPY(ssl->keys->client_write_IV, keys->client_write_IV, sz); - XMEMCPY(ssl->keys.server_write_IV, + XMEMCPY(ssl->keys->server_write_IV, keys->server_write_IV, sz); } #endif @@ -3746,7 +3747,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) /* Initialize the AES-GCM/CCM explicit IV to a zero. */ #ifdef WOLFSSL_DTLS if (scr_copy) { - XMEMCPY(ssl->keys.aead_exp_IV, + XMEMCPY(ssl->keys->aead_exp_IV, keys->aead_exp_IV, AEAD_MAX_EXP_SZ); } #endif @@ -3764,7 +3765,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #ifndef WOLFSSL_AEAD_ONLY #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.client_write_MAC_secret, + XMEMCPY(ssl->keys->client_write_MAC_secret, keys->client_write_MAC_secret, sz); #endif XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); @@ -3775,7 +3776,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #ifndef WOLFSSL_AEAD_ONLY #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.server_write_MAC_secret, + XMEMCPY(ssl->keys->server_write_MAC_secret, keys->server_write_MAC_secret, sz); #endif XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); @@ -3787,7 +3788,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) if (side & PROVISION_CLIENT) { #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.client_write_key, + XMEMCPY(ssl->keys->client_write_key, keys->client_write_key, sz); #endif XMEMCPY(keys->client_write_key, &keyData[i], sz); @@ -3796,7 +3797,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) if (side & PROVISION_SERVER) { #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.server_write_key, + XMEMCPY(ssl->keys->server_write_key, keys->server_write_key, sz); #endif XMEMCPY(keys->server_write_key, &keyData[i], sz); @@ -3807,7 +3808,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) if (side & PROVISION_CLIENT) { #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.client_write_IV, + XMEMCPY(ssl->keys->client_write_IV, keys->client_write_IV, sz); #endif XMEMCPY(keys->client_write_IV, &keyData[i], sz); @@ -3816,7 +3817,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) if (side & PROVISION_SERVER) { #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMCPY(ssl->keys.server_write_IV, + XMEMCPY(ssl->keys->server_write_IV, keys->server_write_IV, sz); #endif XMEMCPY(keys->server_write_IV, &keyData[i], sz); @@ -3827,7 +3828,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) /* Initialize the AES-GCM/CCM explicit IV to a zero. */ #ifdef WOLFSSL_DTLS if (scr_copy) - XMEMMOVE(ssl->keys.aead_exp_IV, + XMEMMOVE(ssl->keys->aead_exp_IV, keys->aead_exp_IV, AEAD_MAX_EXP_SZ); #endif XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); diff --git a/src/ocsp.c b/src/ocsp.c index 41c038fd12..6eed0b8a07 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -967,7 +967,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, /* check calculated length */ fcur = flen - fcur; - if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) + if ((unsigned long)fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) return NULL; data = (byte*)XMALLOC((size_t)fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/src/sniffer.c b/src/sniffer.c index 7be98cdef0..50fbe0a3fa 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1668,7 +1668,7 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, return WOLFSSL_FATAL_ERROR; } fileSz = XFTELL(file); - if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) { + if ((unsigned long)fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) { XFCLOSE(file); return WOLFSSL_FATAL_ERROR; } @@ -4812,8 +4812,10 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); - XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce, ssl->keys->aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, + AESGCM_EXP_IV_SZ); if ((ret = aes_auth_fn(ssl->decrypt.aes, plain, @@ -5006,7 +5008,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, return NULL; } - ssl->keys.encryptSz = sz; + ssl->keys->encryptSz = sz; if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) { output += ssl->specs.block_size; /* go past TLSv1.1 IV */ ivExtra = ssl->specs.block_size; @@ -5015,10 +5017,10 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, if (ssl->specs.cipher_type == aead) { *advance = ssl->specs.aead_mac_size; - ssl->keys.padSz = ssl->specs.aead_mac_size; + ssl->keys->padSz = ssl->specs.aead_mac_size; } else - ssl->keys.padSz = ssl->specs.hash_size; + ssl->keys->padSz = ssl->specs.hash_size; if (ssl->specs.cipher_type == block) { /* last pad bytes indicates length */ @@ -5027,12 +5029,12 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, /* get value of last pad byte */ pad = *(output + sz - ivExtra - 1) + 1; } - ssl->keys.padSz += pad; + ssl->keys->padSz += pad; } #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version)) { - word16 i = (word16)(sz - ssl->keys.padSz); + word16 i = (word16)(sz - ssl->keys->padSz); /* Remove padding from end of plain text. */ for (--i; i > 0; i--) { if (output[i] != 0) @@ -5040,7 +5042,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, } /* Get the real content type from the end of the data. */ rh->type = output[i]; - ssl->keys.padSz = sz - i; + ssl->keys->padSz = sz - i; } #endif (void)rh; @@ -6382,7 +6384,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, used = startIdx - sslBytes; sslFrame += used; if (decrypted) - sslFrame += ssl->keys.padSz; + sslFrame += ssl->keys->padSz; } break; case change_cipher_spec: diff --git a/src/ssl.c b/src/ssl.c index 264f2c04ec..aa5fa708a3 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1726,10 +1726,15 @@ int wolfSSL_get_fd(const WOLFSSL* ssl) int wolfSSL_dtls(WOLFSSL* ssl) { +#ifdef WOLFSSL_DTLS int dtlsOpt = 0; if (ssl) dtlsOpt = ssl->options.dtls; return dtlsOpt; +#else + (void)ssl; + return 0; +#endif } #if !defined(NO_CERTS) @@ -2253,7 +2258,7 @@ int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, ret = MakeTlsMasterSecret(ssl); if (ret == 0) { - ssl->keys.encryptionOn = 1; + ssl->keys->encryptionOn = 1; ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); } @@ -2263,8 +2268,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, WOLFSSL_DTLS_PEERSEQ* peerSeq; int i; - ssl->keys.dtls_epoch = epoch; - for (i = 0, peerSeq = ssl->keys.peerSeq; + ssl->keys->dtls_epoch = epoch; + for (i = 0, peerSeq = ssl->keys->peerSeq; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++, peerSeq++) { @@ -2313,9 +2318,9 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub) /* Make sure it isn't already present, while keeping the first * open spot. */ for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { - if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID) - p = &ssl->keys.peerSeq[i]; - if (ssl->keys.peerSeq[i].peerId == peerId) { + if (ssl->keys->peerSeq[i].peerId == INVALID_PEER_ID) + p = &ssl->keys->peerSeq[i]; + if (ssl->keys->peerSeq[i].peerId == peerId) { WOLFSSL_MSG("Peer ID already in multicast peer list."); p = NULL; } @@ -2336,8 +2341,8 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub) } else { for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { - if (ssl->keys.peerSeq[i].peerId == peerId) - p = &ssl->keys.peerSeq[i]; + if (ssl->keys->peerSeq[i].peerId == peerId) + p = &ssl->keys->peerSeq[i]; } if (p != NULL) { @@ -2367,9 +2372,9 @@ int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId) } for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { - if (ssl->keys.peerSeq[i].peerId == peerId) { - if (ssl->keys.peerSeq[i].nextSeq_hi || - ssl->keys.peerSeq[i].nextSeq_lo) { + if (ssl->keys->peerSeq[i].peerId == peerId) { + if (ssl->keys->peerSeq[i].nextSeq_hi || + ssl->keys->peerSeq[i].nextSeq_lo) { known = 1; } @@ -2993,7 +2998,7 @@ int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz) ret = wolfSSL_read_internal(ssl, data, sz, FALSE); if (ssl->options.dtls && ssl->options.haveMcast && id != NULL) - *id = ssl->keys.curPeerId; + *id = ssl->keys->curPeerId; return ret; } @@ -3612,7 +3617,7 @@ static int _Rehandshake(WOLFSSL* ssl) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls && ssl->keys.dtls_epoch == 0xFFFF) { + if (ssl->options.dtls && ssl->keys->dtls_epoch == 0xFFFF) { WOLFSSL_MSG("Secure Renegotiation not allowed. Epoch would wrap"); return SECURE_RENEGOTIATION_E; } @@ -4316,23 +4321,23 @@ const byte* wolfSSL_GetDtlsMacSecret(WOLFSSL* ssl, int verify, int epochOrder) if (IsDtlsMsgSCRKeys(ssl)) keys = &ssl->secure_renegotiation->tmp_keys; else - keys = &ssl->keys; + keys = ssl->keys; break; case PREV_ORDER: - keys = &ssl->keys; + keys = ssl->keys; break; case CUR_ORDER: if (DtlsUseSCRKeys(ssl)) keys = &ssl->secure_renegotiation->tmp_keys; else - keys = &ssl->keys; + keys = ssl->keys; break; default: WOLFSSL_MSG("Unknown epoch order"); return NULL; } #else - keys = &ssl->keys; + keys = ssl->keys; #endif if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || @@ -4358,9 +4363,9 @@ const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || (ssl->options.side == WOLFSSL_SERVER_END && verify) ) - return ssl->keys.client_write_MAC_secret; + return ssl->keys->client_write_MAC_secret; else - return ssl->keys.server_write_MAC_secret; + return ssl->keys->server_write_MAC_secret; #else (void)ssl; (void)verify; @@ -4508,7 +4513,7 @@ void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl) const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl) { if (ssl) - return ssl->keys.client_write_key; + return ssl->keys->client_write_key; return NULL; } @@ -4517,7 +4522,7 @@ const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl) const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl) { if (ssl) - return ssl->keys.client_write_IV; + return ssl->keys->client_write_IV; return NULL; } @@ -4526,7 +4531,7 @@ const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl) const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl) { if (ssl) - return ssl->keys.server_write_key; + return ssl->keys->server_write_key; return NULL; } @@ -4535,7 +4540,7 @@ const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl) const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl) { if (ssl) - return ssl->keys.server_write_IV; + return ssl->keys->server_write_IV; return NULL; } @@ -4631,8 +4636,8 @@ int wolfSSL_GetPeerSequenceNumber(WOLFSSL* ssl, word64 *seq) if ((ssl == NULL) || (seq == NULL)) return BAD_FUNC_ARG; - *seq = ((word64)ssl->keys.peer_sequence_number_hi << 32) | - ssl->keys.peer_sequence_number_lo; + *seq = ((word64)ssl->keys->peer_sequence_number_hi << 32) | + ssl->keys->peer_sequence_number_lo; return !(*seq); } @@ -4641,8 +4646,8 @@ int wolfSSL_GetSequenceNumber(WOLFSSL* ssl, word64 *seq) if ((ssl == NULL) || (seq == NULL)) return BAD_FUNC_ARG; - *seq = ((word64)ssl->keys.sequence_number_hi << 32) | - ssl->keys.sequence_number_lo; + *seq = ((word64)ssl->keys->sequence_number_hi << 32) | + ssl->keys->sequence_number_lo; return !(*seq); } #endif @@ -8842,12 +8847,13 @@ int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) return WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock"); - if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { useNb = ssl->options.dtlsUseNonblock; -#endif } - else { + else +#endif + { WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is " "DEPRECATED for non-DTLS use."); } @@ -8866,12 +8872,13 @@ void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) if (ssl == NULL) return; - if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { ssl->options.dtlsUseNonblock = (nonblock != 0); -#endif } - else { + else +#endif + { WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is " "DEPRECATED for non-DTLS use."); } @@ -13164,7 +13171,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, ssl->extensions = NULL; #endif - if (ssl->keys.encryptionOn) { + if (ssl->keys->encryptionOn) { ForceZero(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, ssl->buffers.inputBuffer.bufferSize); @@ -13174,7 +13181,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, ssl->buffers.inputBuffer.bufferSize); #endif } - ssl->keys.encryptionOn = 0; + ssl->keys->encryptionOn = 0; XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); if (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS) @@ -17155,7 +17162,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) return WOLFSSL_BAD_FILE; } - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if ((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { WOLFSSL_MSG("cmp_peer_cert_to_file size error"); XFCLOSE(file); return WOLFSSL_BAD_FILE; diff --git a/src/ssl_misc.c b/src/ssl_misc.c index 9a5f4b042a..a6cc4ac48f 100644 --- a/src/ssl_misc.c +++ b/src/ssl_misc.c @@ -256,7 +256,8 @@ static int wolfssl_file_len(XFILE fp, long* fileSz) ret = WOLFSSL_BAD_FILE; } /* Validate size. */ - if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) { + if ((ret == 0) && (((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE) || + (sz <= 0L))) { ret = WOLFSSL_BAD_FILE; } if (ret == 0) { diff --git a/src/tls13.c b/src/tls13.c index df4ab791bd..7e51f64d6f 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1075,9 +1075,9 @@ int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) #endif /* Length of the finished label. */ -#define FINISHED_LABEL_SZ 8 +#define TLS13_FINISHED_LABEL_SZ 8 /* Finished label for generating finished key. */ -static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished"; +static const byte finishedLabel[TLS13_FINISHED_LABEL_SZ+1] = "finished"; /* Derive the finished secret. * * ssl The SSL/TLS object. @@ -1091,7 +1091,7 @@ static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret, { WOLFSSL_MSG("Derive Finished Secret"); return Tls13DeriveKey(ssl, secret, -1, key, finishedLabel, - FINISHED_LABEL_SZ, ssl->specs.mac_algorithm, 0, + TLS13_FINISHED_LABEL_SZ, ssl->specs.mac_algorithm, 0, side); } @@ -2400,18 +2400,18 @@ static WC_INLINE void WriteSEQTls13(WOLFSSL* ssl, int verifyOrder, byte* out) #endif /* WOLFSSL_DTLS13 */ } else if (verifyOrder == PEER_ORDER) { - seq[0] = ssl->keys.peer_sequence_number_hi; - seq[1] = ssl->keys.peer_sequence_number_lo++; + seq[0] = ssl->keys->peer_sequence_number_hi; + seq[1] = ssl->keys->peer_sequence_number_lo++; /* handle rollover */ - if (seq[1] > ssl->keys.peer_sequence_number_lo) - ssl->keys.peer_sequence_number_hi++; + if (seq[1] > ssl->keys->peer_sequence_number_lo) + ssl->keys->peer_sequence_number_hi++; } else { - seq[0] = ssl->keys.sequence_number_hi; - seq[1] = ssl->keys.sequence_number_lo++; + seq[0] = ssl->keys->sequence_number_hi; + seq[1] = ssl->keys->sequence_number_lo++; /* handle rollover */ - if (seq[1] > ssl->keys.sequence_number_lo) - ssl->keys.sequence_number_hi++; + if (seq[1] > ssl->keys->sequence_number_lo) + ssl->keys->sequence_number_hi++; } c32toa(seq[0], out); @@ -2620,7 +2620,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, if (ssl->encrypt.nonce == NULL) return MEMORY_E; - BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV, + BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys->aead_enc_imp_IV, CUR_ORDER); #endif @@ -3022,7 +3022,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, if (ssl->decrypt.nonce == NULL) return MEMORY_E; - BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys->aead_dec_imp_IV, PEER_ORDER); #endif @@ -4069,13 +4069,13 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) /* Derive the Finished message secret. */ ret = DeriveFinishedSecret(ssl, binderKey, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, 0 /* neither end */); if (ret != 0) break; /* Build the HMAC of the handshake message data = binder. */ - ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, + ret = BuildTls13HandshakeHmac(ssl, ssl->keys->client_write_MAC_secret, current->binder, ¤t->binderLen); if (ret != 0) break; @@ -4756,9 +4756,9 @@ static int Dtls13ClientDoDowngrade(WOLFSSL* ssl) XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); ssl->dtls13ClientHello = NULL; ssl->dtls13ClientHelloSz = 0; - ssl->keys.dtls_sequence_number_hi = + ssl->keys->dtls_sequence_number_hi = (word16)w64GetHigh32(ssl->dtls13EncryptEpoch->nextSeqNumber); - ssl->keys.dtls_sequence_number_lo = + ssl->keys->dtls_sequence_number_lo = w64GetLow32(ssl->dtls13EncryptEpoch->nextSeqNumber); return ret; } @@ -5562,7 +5562,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return EXT_MISSING; } - ssl->keys.encryptionOn = 1; + ssl->keys->encryptionOn = 1; ssl->options.serverState = SERVER_HELLO_COMPLETE; } @@ -5637,7 +5637,7 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, *inOutIdx = i + totalExtSz; /* Always encrypted. */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; #ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData != no_early_data) { @@ -5775,7 +5775,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, } /* This message is always encrypted so add encryption padding. */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; WOLFSSL_LEAVE("DoTls13CertificateRequest", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); @@ -6120,14 +6120,14 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, /* Derive the Finished message secret. */ ret = DeriveFinishedSecret(ssl, binderKey, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, 0 /* neither end */); if (ret != 0) return ret; /* Derive the binder and compare with the one in the extension. */ ret = BuildTls13HandshakeHmac(ssl, - ssl->keys.client_write_MAC_secret, binder, &binderLen); + ssl->keys->client_write_MAC_secret, binder, &binderLen); if (ret != 0) return ret; if (binderLen != current->binderLen || @@ -6288,7 +6288,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; - ssl->keys.encryptionOn = 1; + ssl->keys->encryptionOn = 1; #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { @@ -7503,7 +7503,7 @@ static int SendTls13EncryptedExtensions(WOLFSSL* ssl) WOLFSSL_ENTER("SendTls13EncryptedExtensions"); ssl->options.buildingMsg = 1; - ssl->keys.encryptionOn = 1; + ssl->keys->encryptionOn = 1; #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { @@ -10599,7 +10599,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, *inOutIdx = args->idx; /* Encryption is always on: add padding */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; @@ -10725,33 +10725,33 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.handShakeDone) { ret = DeriveFinishedSecret(ssl, ssl->clientSecret, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, WOLFSSL_CLIENT_END); if (ret != 0) return ret; - secret = ssl->keys.client_write_MAC_secret; + secret = ssl->keys->client_write_MAC_secret; } else if (ssl->options.side == WOLFSSL_CLIENT_END) { /* All the handshake messages have been received to calculate * client and server finished keys. */ ret = DeriveFinishedSecret(ssl, ssl->clientSecret, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, WOLFSSL_CLIENT_END); if (ret != 0) return ret; ret = DeriveFinishedSecret(ssl, ssl->serverSecret, - ssl->keys.server_write_MAC_secret, + ssl->keys->server_write_MAC_secret, WOLFSSL_SERVER_END); if (ret != 0) return ret; - secret = ssl->keys.server_write_MAC_secret; + secret = ssl->keys->server_write_MAC_secret; } else { - secret = ssl->keys.client_write_MAC_secret; + secret = ssl->keys->client_write_MAC_secret; } if (sniff == NO_SNIFF) { @@ -10789,7 +10789,7 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Force input exhaustion at ProcessReply by consuming padSz. */ - *inOutIdx += size + ssl->keys.padSz; + *inOutIdx += size + ssl->keys->padSz; if (ssl->options.side == WOLFSSL_SERVER_END && !ssl->options.handShakeDone) { @@ -10899,32 +10899,32 @@ static int SendTls13Finished(WOLFSSL* ssl) /* make finished hashes */ if (ssl->options.handShakeDone) { ret = DeriveFinishedSecret(ssl, ssl->clientSecret, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, WOLFSSL_CLIENT_END); if (ret != 0) return ret; - secret = ssl->keys.client_write_MAC_secret; + secret = ssl->keys->client_write_MAC_secret; } else if (ssl->options.side == WOLFSSL_CLIENT_END) - secret = ssl->keys.client_write_MAC_secret; + secret = ssl->keys->client_write_MAC_secret; else { /* All the handshake messages have been done to calculate client and * server finished keys. */ ret = DeriveFinishedSecret(ssl, ssl->clientSecret, - ssl->keys.client_write_MAC_secret, + ssl->keys->client_write_MAC_secret, WOLFSSL_SERVER_END); if (ret != 0) return ret; ret = DeriveFinishedSecret(ssl, ssl->serverSecret, - ssl->keys.server_write_MAC_secret, + ssl->keys->server_write_MAC_secret, WOLFSSL_CLIENT_END); if (ret != 0) return ret; - secret = ssl->keys.server_write_MAC_secret; + secret = ssl->keys->server_write_MAC_secret; } ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL); if (ret != 0) @@ -11147,10 +11147,10 @@ static int SendTls13KeyUpdate(WOLFSSL* ssl) * 2. This isn't responding to peer KeyUpdate requiring a response then, * I want a response. */ - ssl->keys.updateResponseReq = output[i++] = - !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond; + ssl->keys->updateResponseReq = output[i++] = + !ssl->keys->updateResponseReq && !ssl->keys->keyUpdateRespond; /* Sent response, no longer need to respond. */ - ssl->keys.keyUpdateRespond = 0; + ssl->keys->keyUpdateRespond = 0; #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { @@ -11232,12 +11232,12 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (input[i]) { case update_not_requested: /* This message in response to any outstanding request. */ - ssl->keys.keyUpdateRespond = 0; - ssl->keys.updateResponseReq = 0; + ssl->keys->keyUpdateRespond = 0; + ssl->keys->updateResponseReq = 0; break; case update_requested: /* New key update requiring a response. */ - ssl->keys.keyUpdateRespond = 1; + ssl->keys->keyUpdateRespond = 1; break; default: WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER); @@ -11247,7 +11247,7 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Move index to byte after message. */ *inOutIdx += totalSz; /* Always encrypted. */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; /* Future traffic uses new decryption keys. */ if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1)) @@ -11271,7 +11271,7 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS13 */ - if (ssl->keys.keyUpdateRespond) { + if (ssl->keys->keyUpdateRespond) { #ifdef WOLFSSL_DTLS13 /* we already sent a keyUpdate (either in response to a previous @@ -11281,7 +11281,7 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, don't do that as it looks redundant, it will make the code more complex and I don't see a good use case for that. */ if (ssl->options.dtls && ssl->dtls13WaitKeyUpdateAck) { - ssl->keys.keyUpdateRespond = 0; + ssl->keys->keyUpdateRespond = 0; return 0; } #endif /* WOLFSSL_DTLS13 */ @@ -11386,7 +11386,7 @@ static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input, ssl->earlyData = done_early_data; /* Always encrypted. */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY); @@ -11551,7 +11551,7 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, #endif /* Always encrypted. */ - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys->padSz; ssl->expect_session_ticket = 0; #else @@ -11560,7 +11560,7 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, WOLFSSL_ENTER("DoTls13NewSessionTicket"); - *inOutIdx += size + ssl->keys.padSz; + *inOutIdx += size + ssl->keys->padSz; #endif /* HAVE_SESSION_TICKET */ WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0); @@ -11624,7 +11624,7 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) } /* Generate the Client's Finished message and hash it. */ - ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac, + ret = BuildTls13HandshakeHmac(ssl, ssl->keys->client_write_MAC_secret, mac, &finishedSz); if (ret != 0) return ret; @@ -12800,7 +12800,8 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, totalSz); } - inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz; + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - + ssl->keys->padSz; /* If there is a pending fragmented handshake message, * pending message size will be non-zero. */ @@ -12841,7 +12842,7 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, input + *inOutIdx - HANDSHAKE_HEADER_SZ, inputLength); ssl->arrays->pendingMsgOffset = inputLength; - *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ; + *inOutIdx += inputLength + ssl->keys->padSz - HANDSHAKE_HEADER_SZ; return 0; } @@ -12865,7 +12866,7 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, input + *inOutIdx, inputLength); ssl->arrays->pendingMsgOffset += inputLength; - *inOutIdx += inputLength + ssl->keys.padSz; + *inOutIdx += inputLength + ssl->keys->padSz; if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) { @@ -12879,7 +12880,7 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* setup to process fragment again */ ssl->arrays->pendingMsgOffset -= inputLength; - *inOutIdx -= inputLength + ssl->keys.padSz; + *inOutIdx -= inputLength + ssl->keys->padSz; } else #endif @@ -13676,7 +13677,7 @@ int wolfSSL_key_update_response(WOLFSSL* ssl, int* required) if (required == NULL || ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) return BAD_FUNC_ARG; - *required = ssl->keys.updateResponseReq; + *required = ssl->keys->updateResponseReq; return 0; } diff --git a/src/x509.c b/src/x509.c index 759e1fc6f1..705fc5990c 100644 --- a/src/x509.c +++ b/src/x509.c @@ -5079,7 +5079,7 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) if (XFSEEK(file, 0, XSEEK_SET) != 0) return NULL; - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if ((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { WOLFSSL_MSG("X509_d2i file size error"); return NULL; } @@ -5141,7 +5141,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) return NULL; } - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if ((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { WOLFSSL_MSG("X509_load_certificate_file size error"); XFCLOSE(file); return NULL; @@ -7803,7 +7803,7 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, return WS_RETURN_CODE(WOLFSSL_BAD_FILE,WOLFSSL_FAILURE); } - if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + if ((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { WOLFSSL_MSG("X509_LOOKUP_load_file size error"); goto end; } @@ -8499,7 +8499,7 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) return NULL; } - if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + if ((unsigned long)sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { WOLFSSL_MSG("d2i_X509_fp_ex file size error"); return NULL; } @@ -12384,7 +12384,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) pemSz = (int)(l - i); /* check calculated length */ - if (pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz <= 0) { + if ((unsigned long)pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz <= 0) { WOLFSSL_MSG("PEM_read_X509_ex file size error"); return NULL; } diff --git a/tests/api.c b/tests/api.c index 0e8ae3a811..1f71cd591e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -86746,13 +86746,13 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl) sslCopy.error = 0; sslCopy.curSize = 0; sslCopy.curStartIdx = 0; - sslCopy.keys.curSeq_lo = 0; + sslCopy.keys->curSeq_lo = 0; XMEMSET(&sslCopy.curRL, 0, sizeof(sslCopy.curRL)); #ifdef WOLFSSL_DTLS13 - XMEMSET(&sslCopy.keys.curSeq, 0, sizeof(sslCopy.keys.curSeq)); + XMEMSET(&sslCopy.keys->curSeq, 0, sizeof(sslCopy.keys->curSeq)); sslCopy.dtls13FastTimeout = 0; #endif - sslCopy.keys.dtls_peer_handshake_number = 0; + sslCopy.keys->dtls_peer_handshake_number = 0; XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); sslCopy.hsHashes = NULL; #ifdef WOLFSSL_ASYNC_IO diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 4c9a8d1811..01620f2b5d 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -1596,7 +1596,7 @@ static const FLASH_QUALIFIER byte Td4[256] = #define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) #ifdef WOLFSSL_AES_SMALL_TABLES -static const byte Tsbox[256] = { +static const FLASH_QUALIFIER byte Tsbox[256] = { 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, @@ -1952,7 +1952,7 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, #ifdef WC_C_DYNAMIC_FALLBACK rk = aes->key_C_fallback; #else - rk = aes->key; + rk = (const word32*)aes->key; #endif /* @@ -2127,7 +2127,7 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, r *= 2; /* Two rounds at a time */ - for (rk += 4; r > 1; r--, rk += 4) { + for (rk += 4u; r > 1u; r--, rk += 4u) { t0 = ((word32)GetTable8(Tsbox, GETBYTE(s0, 3)) << 24) ^ ((word32)GetTable8(Tsbox, GETBYTE(s1, 2)) << 16) ^ @@ -2823,7 +2823,7 @@ static WARN_UNUSED_RESULT int wc_AesEncrypt( r = aes->rounds >> 1; - if (r > 7 || r == 0) { + if (r > 7U || r == 0U) { WOLFSSL_ERROR_VERBOSE(KEYUSAGE_E); return KEYUSAGE_E; } @@ -2994,7 +2994,7 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, #ifdef WC_C_DYNAMIC_FALLBACK rk = aes->key_C_fallback; #else - rk = aes->key; + rk = (const word32*)aes->key; #endif /* @@ -3120,7 +3120,7 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, #endif r *= 2; - for (rk += 4; r > 1; r--, rk += 4) { + for (rk += 4u; r > 1u; r--, rk += 4u) { t0 = ((word32)GetTable8(Td4, GETBYTE(s0, 3)) << 24) ^ ((word32)GetTable8(Td4, GETBYTE(s3, 2)) << 16) ^ @@ -3600,7 +3600,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( r = aes->rounds >> 1; - if (r > 7 || r == 0) { + if (r > 7U || r == 0U) { WOLFSSL_ERROR_VERBOSE(KEYUSAGE_E); return KEYUSAGE_E; } @@ -4222,7 +4222,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; - if (++i == 10) + if (++i == 10U) break; rk += 4; } @@ -4315,7 +4315,9 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) break; #endif /* 256 */ } /* switch */ +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(&temp, sizeof(temp)); +#endif #if defined(HAVE_AES_DECRYPT) && !defined(MAX3266X_AES) if (dir == AES_DECRYPTION) { @@ -4334,7 +4336,9 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(&temp, sizeof(temp)); +#endif #if !defined(WOLFSSL_AES_SMALL_TABLES) /* apply the inverse MixColumn transform to all round keys but the first and the last: */ @@ -4508,13 +4512,13 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) #endif if (checkKeyLen) { - if (keylen != 16 && keylen != 24 && keylen != 32) { + if (keylen != 16U && keylen != 24U && keylen != 32U) { return BAD_FUNC_ARG; } #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE < 256 /* Check key length only when AES_MAX_KEY_SIZE doesn't allow * all key sizes. Otherwise this condition is never true. */ - if (keylen > (AES_MAX_KEY_SIZE / 8)) { + if (keylen > (word32)(AES_MAX_KEY_SIZE / 8)) { return BAD_FUNC_ARG; } #endif @@ -5647,7 +5651,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return BAD_FUNC_ARG; } - if (sz == 0) { + if (sz == 0U) { return 0; } @@ -5769,10 +5773,11 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) else #endif { - ret = 0; + ret = 0; /* in case blocks is 0 */ while (blocks--) { xorbuf((byte*)aes->reg, in, AES_BLOCK_SIZE); - ret = wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg); + ret = wc_AesEncrypt(aes, (const byte*)aes->reg, + (byte*)aes->reg); if (ret != 0) break; XMEMCPY(out, aes->reg, AES_BLOCK_SIZE); @@ -5800,7 +5805,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return BAD_FUNC_ARG; } - if (sz == 0) { + if (sz == 0U) { return 0; } @@ -5972,13 +5977,25 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } #else while (blocks--) { + #ifdef WOLFSSL_LEANPSK + byte tmp[16]; + + /* throw the 16 bytes tmp buffer on the stack breifly rather + * than hanging on to them for the life of the AES struct */ + XMEMCPY(tmp, in, AES_BLOCK_SIZE); + #else XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); + #endif ret = wc_AesDecrypt(aes, in, out); if (ret != 0) return ret; - xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE); + xorbuf((void*)out, (const void*)aes->reg, AES_BLOCK_SIZE); /* store iv for next call */ + #ifdef WOLFSSL_LEANPSK + XMEMCPY(aes->reg, tmp, AES_BLOCK_SIZE); + #else XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + #endif out += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; @@ -10532,7 +10549,9 @@ int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, authTag, authTagSz, authIn, authInSz); wc_AesFree(aes); } +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(aes, sizeof *aes); +#endif #ifdef WOLFSSL_SMALL_STACK XFREE(aes, NULL, DYNAMIC_TYPE_AES); #endif @@ -10573,7 +10592,9 @@ int wc_GmacVerify(const byte* key, word32 keySz, authTag, authTagSz, authIn, authInSz); wc_AesFree(aes); } +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(aes, sizeof *aes); +#endif #ifdef WOLFSSL_SMALL_STACK XFREE(aes, NULL, DYNAMIC_TYPE_AES); #endif @@ -11492,6 +11513,7 @@ void wc_AesFree(Aes* aes) #endif } +#ifndef WOLFSSL_LEANPSK int wc_AesGetKeySize(Aes* aes, word32* keySize) { int ret = 0; @@ -11530,6 +11552,7 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize) return ret; } +#endif #endif /* !WOLFSSL_TI_CRYPT */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bea4c89d0e..a5f7eab557 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -6886,7 +6886,7 @@ static const ASNItem pkcs8KeyASN[] = { { 1, ASN_CONTEXT_SPECIFIC | 0, 1, 0, 1 }, /* [[2: publicKey [1] PublicKey OPTIONAL ]] */ }; -enum { +enum pkcsEnum { PKCS8KEYASN_IDX_SEQ = 0, PKCS8KEYASN_IDX_VER, PKCS8KEYASN_IDX_PKEY_ALGO_SEQ, @@ -21840,7 +21840,7 @@ static const ASNItem x509CertASN[] = { /* signature BIT STRING */ /* SIGNATURE */ { 1, ASN_BIT_STRING, 0, 0, 0 }, }; -enum { +enum x509Enum { X509CERTASN_IDX_SEQ = 0, X509CERTASN_IDX_TBS_SEQ, X509CERTASN_IDX_TBS_VER, diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 47f8f13824..acfd765049 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -71,6 +71,7 @@ } #endif +#ifndef WOLFSSL_LEANPSK int wc_HmacSizeByType(int type) { int ret; @@ -153,6 +154,7 @@ int wc_HmacSizeByType(int type) return ret; } +#endif int _InitHmac(Hmac* hmac, int type, void* heap) { @@ -254,7 +256,7 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, int ret = 0; void* heap = NULL; - if (hmac == NULL || (key == NULL && length != 0) || + if (hmac == NULL || (key == NULL && length != 0U) || !(type == WC_MD5 || type == WC_SHA || #ifdef WOLFSSL_SM3 type == WC_SM3 || @@ -272,7 +274,7 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, provided the user calls wc_HmacInit() first. That function is not available in FIPS builds. In current FIPS builds, the hashes are not allocating resources. */ - if (hmac->macType != WC_HASH_TYPE_NONE) { + if (hmac->macType != (byte)WC_HASH_TYPE_NONE) { wc_HmacFree(hmac); } #endif @@ -313,7 +315,7 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, * (no security strength) */ if (!allowFlag) { - if (length < HMAC_FIPS_MIN_KEY) { + if (length < (word32)HMAC_FIPS_MIN_KEY) { WOLFSSL_ERROR_VERBOSE(HMAC_MIN_KEYLEN_E); return HMAC_MIN_KEYLEN_E; } @@ -397,7 +399,7 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, #ifndef NO_SHA256 case WC_SHA256: hmac_block_size = WC_SHA256_BLOCK_SIZE; - if (length <= WC_SHA256_BLOCK_SIZE) { + if (length <= (word32)WC_SHA256_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } @@ -704,7 +706,7 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { int ret = 0; - if (hmac == NULL || (msg == NULL && length > 0)) { + if (hmac == NULL || (msg == NULL && length > 0U)) { return BAD_FUNC_ARG; } @@ -1064,7 +1066,7 @@ int wc_HmacInit(Hmac* hmac, void* heap, int devId) if (hmac == NULL) return BAD_FUNC_ARG; - XMEMSET(hmac, 0, sizeof(Hmac)); + XMEMSET((void*)hmac, 0, sizeof(Hmac)); hmac->macType = WC_HASH_TYPE_NONE; hmac->heap = heap; #ifdef WOLF_CRYPTO_CB @@ -1219,7 +1221,9 @@ void wc_HmacFree(Hmac* hmac) break; } +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(hmac, sizeof(*hmac)); +#endif } #endif /* WOLFSSL_KCAPI_HMAC */ diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index 7a9bcb02c9..77617c1bbd 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -297,7 +297,7 @@ WC_MISC_STATIC WC_INLINE void xorbufout(void* out, const void* buf, /* Alignment checks out. Possible to XOR words. */ /* Move alignment so that it lines up with a * WOLFSSL_WORD_SIZE boundary */ - while (((wc_ptr_t)b) % WOLFSSL_WORD_SIZE != 0 && count > 0) { + while (((wc_ptr_t)b) % WOLFSSL_WORD_SIZE != 0U && count > 0U) { *(o++) = (byte)(*(b++) ^ *(m++)); count--; } @@ -352,7 +352,7 @@ WC_MISC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) /* Alignment checks out. Possible to XOR words. */ /* Move alignment so that it lines up with a * WOLFSSL_WORD_SIZE boundary */ - while (((wc_ptr_t)buf) % WOLFSSL_WORD_SIZE != 0 && count > 0) { + while (((wc_ptr_t)buf) % WOLFSSL_WORD_SIZE != 0U && count > 0U) { *(b++) ^= *(m++); count--; } @@ -492,7 +492,8 @@ WC_MISC_STATIC WC_INLINE void ato24(const byte* c, word32* wc_u24) /* convert opaque to 16 bit integer */ WC_MISC_STATIC WC_INLINE void ato16(const byte* c, word16* wc_u16) { - *wc_u16 = (word16) ((c[0] << 8) | (c[1])); + *wc_u16 = c[0]; + *wc_u16 = (word16) (((*wc_u16 << 8) & 0xFF00) | (c[1])); } /* convert opaque to 32 bit integer */ @@ -526,6 +527,7 @@ WC_MISC_STATIC WC_INLINE word32 btoi(byte b) } #endif +#ifndef WOLFSSL_NO_STRING_CONV WC_MISC_STATIC WC_INLINE signed char HexCharToByte(char ch) { signed char ret = (signed char)ch; @@ -568,6 +570,7 @@ WC_MISC_STATIC WC_INLINE int CharIsWhiteSpace(char ch) return 0; } } +#endif #ifndef WOLFSSL_NO_CT_OPS /* Constant time - mask set when a > b. */ @@ -673,7 +676,7 @@ WC_MISC_STATIC WC_INLINE byte ctSetLTE(int a, int b) WC_MISC_STATIC WC_INLINE void ctMaskCopy(byte mask, byte* dst, byte* src, word16 size) { - int i; + word16 i; for (i = 0; i < size; ++i) { dst[i] ^= (dst[i] ^ src[i]) & mask; } diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index d6c32f6923..5bbf6ca3bc 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -316,20 +316,20 @@ int wc_SetSeed_Cb(wc_RngSeed_Cb cb) #define DRBG_FAILED 2 #define DRBG_CONT_FAILED 3 -#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) +/* SHA256 digest size times 4 */ +#define RNG_HEALTH_TEST_CHECK_SIZE 128 /* Verify max gen block len */ #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length #endif -enum { - drbgInitC = 0, - drbgReseed = 1, - drbgGenerateW = 2, - drbgGenerateH = 3, - drbgInitV = 4 -}; + +#define drbgInitC 0U +#define drbgReseed 1U +#define drbgGenerateW 2U +#define drbgGenerateH 3U +#define drbgInitV 4U typedef struct DRBG_internal DRBG_internal; @@ -348,6 +348,8 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, word32 bits = (outSz * 8); /* reverse byte order */ #ifdef WOLFSSL_SMALL_STACK_CACHE wc_Sha256* sha = &drbg->sha256; +#elif defined(WOLFSSL_SMALL_STACK) + wc_Sha256* sha; #else wc_Sha256 sha[1]; #endif @@ -362,6 +364,12 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, } #ifdef WOLFSSL_SMALL_STACK +#ifndef WOLFSSL_SMALL_STACK_CACHE + sha = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), drbg->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return DRBG_FAILURE; +#endif digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, DYNAMIC_TYPE_DIGEST); if (digest == NULL) @@ -399,7 +407,7 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, if (ret == 0) ret = wc_Sha256Update(sha, inA, inASz); if (ret == 0) { - if (inB != NULL && inBSz > 0) + if (inB != NULL && inBSz > 0U) ret = wc_Sha256Update(sha, inB, inBSz); } if (ret == 0) @@ -409,7 +417,7 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, wc_Sha256Free(sha); #endif if (ret == 0) { - if (outSz > OUTPUT_BLOCK_LEN) { + if (outSz > (word32)OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; @@ -419,10 +427,13 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, } } } - +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(digest, WC_SHA256_DIGEST_SIZE); - +#endif #ifdef WOLFSSL_SMALL_STACK +#ifndef WOLFSSL_SMALL_STACK_CACHE + XFREE(sha, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); #endif @@ -455,8 +466,9 @@ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz drbg->V, sizeof(drbg->V), seed, seedSz); if (ret == DRBG_SUCCESS) { XMEMCPY(drbg->V, newV, sizeof(drbg->V)); + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(newV, DRBG_SEED_LEN); - + #endif ret = Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, sizeof(drbg->V), NULL, 0); } @@ -495,7 +507,7 @@ static WC_INLINE void array_add_one(byte* data, word32 dataSz) int i; for (i = (int)dataSz - 1; i >= 0; i--) { data[i]++; - if (data[i] != 0) break; + if (data[i] != 0U) break; } } @@ -514,6 +526,11 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) word32 len; #ifdef WOLFSSL_SMALL_STACK_CACHE wc_Sha256* sha = &drbg->sha256; +#elif defined(WOLFSSL_SMALL_STACK) + wc_Sha256* sha = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; #else wc_Sha256 sha[1]; #endif @@ -536,7 +553,7 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ - if (outSz == 0) { + if (outSz == 0U) { outSz = 1; } @@ -560,8 +577,8 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) #endif if (ret == 0) { - if (out != NULL && outSz != 0) { - if (outSz >= OUTPUT_BLOCK_LEN) { + if (out != NULL && outSz != 0U) { + if (outSz >= (word32)OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; @@ -578,9 +595,15 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) break; } } + +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(data, DRBG_SEED_LEN); +#endif #ifdef WOLFSSL_SMALL_STACK +#ifndef WOLFSSL_SMALL_STACK_CACHE + XFREE(sha, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -590,7 +613,7 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) { - if (dLen > 0 && sLen > 0 && dLen >= sLen) { + if (dLen > 0U && sLen > 0U && dLen >= sLen) { int sIdx, dIdx; word16 carry = 0; @@ -616,6 +639,8 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) int ret; #ifdef WOLFSSL_SMALL_STACK_CACHE wc_Sha256* sha = &drbg->sha256; +#elif defined(WOLFSSL_SMALL_STACK) + wc_Sha256* sha; #else wc_Sha256 sha[1]; #endif @@ -626,7 +651,7 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) return DRBG_FAILURE; } - if (drbg->reseedCtr == RESEED_INTERVAL) { + if (drbg->reseedCtr == (word32)RESEED_INTERVAL) { #if FIPS_VERSION3_GE(6,0,0) printf("Reseed triggered\n"); #endif @@ -636,7 +661,16 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) #ifndef WOLFSSL_SMALL_STACK byte digest[WC_SHA256_DIGEST_SIZE]; #else - byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, + byte* digest; + + #ifndef WOLFSSL_SMALL_STACK_CACHE + sha = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), drbg->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return DRBG_FAILURE; + #endif + + digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, DYNAMIC_TYPE_DIGEST); if (digest == NULL) return DRBG_FAILURE; @@ -677,8 +711,13 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) } drbg->reseedCtr++; } + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(digest, WC_SHA256_DIGEST_SIZE); + #endif #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SMALL_STACK_CACHE + XFREE(sha, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); #endif } @@ -733,9 +772,11 @@ static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg) #ifdef WOLFSSL_SMALL_STACK_CACHE wc_Sha256Free(&drbg->sha256); #endif - +#ifdef WOLFSSL_NO_FORCE_ZERO + memset(drbg, 0, sizeof(DRBG_internal)); +#else ForceZero(drbg, sizeof(DRBG_internal)); - +#endif for (i = 0; i < sizeof(DRBG_internal); i++) { compareSum |= compareDrbg[i] ^ 0; } @@ -1595,7 +1636,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, if (rng == NULL) return BAD_FUNC_ARG; - if (nonce == NULL && nonceSz != 0) + if (nonce == NULL && nonceSz != 0U) return BAD_FUNC_ARG; #ifdef WOLFSSL_HEAP_TEST @@ -1663,7 +1704,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, /* not CUSTOM_RAND_GENERATE_BLOCK follows */ #ifdef HAVE_HASHDRBG - if (nonceSz == 0) { + if (nonceSz == 0U) { seedSz = MAX_SEED_SZ; } @@ -1741,8 +1782,9 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, rng->drbg = NULL; } } /* ret == 0 */ - + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(seed, seedSz); + #endif #ifdef WOLFSSL_SMALL_STACK XFREE(seed, rng->heap, DYNAMIC_TYPE_SEED); #endif @@ -1778,6 +1820,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, } +#ifndef WOLFSSL_LEANPSK WOLFSSL_ABI WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap) { @@ -1823,11 +1866,14 @@ void wc_rng_free(WC_RNG* rng) void* heap = rng->heap; wc_FreeRng(rng); +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(rng, sizeof(WC_RNG)); +#endif XFREE(rng, heap, DYNAMIC_TYPE_RNG); (void)heap; } } +#endif WOLFSSL_ABI int wc_InitRng(WC_RNG* rng) @@ -1842,6 +1888,7 @@ int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) } +#ifndef WOLFSSL_LEANPSK int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz) { return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID); @@ -1853,6 +1900,7 @@ int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, { return _InitRng(rng, nonce, nonceSz, heap, devId); } +#endif /* place a generated block in output */ @@ -1864,7 +1912,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) if (rng == NULL || output == NULL) return BAD_FUNC_ARG; - if (sz == 0) + if (sz == 0U) return 0; #ifdef WOLF_CRYPTO_CB @@ -1907,10 +1955,10 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) #else #ifdef HAVE_HASHDRBG - if (sz > RNG_MAX_BLOCK_LEN) + if (sz > (word32)RNG_MAX_BLOCK_LEN) return BAD_FUNC_ARG; - if (rng->status != DRBG_OK) + if (rng->status != (byte)DRBG_OK) return RNG_FAILURE_E; ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); @@ -1956,9 +2004,11 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_NO_FORCE_ZERO if (newSeed != NULL) { ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ); } + #endif XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED); #else ForceZero(newSeed, sizeof(newSeed)); @@ -2066,7 +2116,7 @@ int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz, return BAD_FUNC_ARG; } - if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) { + if (outputSz != (word32)RNG_HEALTH_TEST_CHECK_SIZE) { return ret; } diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index c9c3b100bb..468299ee1e 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1229,7 +1229,9 @@ static int InitSha256(wc_Sha256* sha256) } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + #ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(W, sizeof(word32) * WC_SHA256_BLOCK_SIZE); + #endif XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return 0; @@ -1334,7 +1336,7 @@ static int InitSha256(wc_Sha256* sha256) byte* local; /* check that internal buffLen is valid */ - if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) { + if (sha256->buffLen >= (word32)WC_SHA256_BLOCK_SIZE) { return BUFFER_E; } @@ -1344,7 +1346,7 @@ static int InitSha256(wc_Sha256* sha256) local = (byte*)sha256->buffer; /* process any remainder from previous operation */ - if (sha256->buffLen > 0) { + if (sha256->buffLen > 0U) { blocksLen = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); XMEMCPY(&local[sha256->buffLen], data, blocksLen); @@ -1352,7 +1354,7 @@ static int InitSha256(wc_Sha256* sha256) data += blocksLen; len -= blocksLen; - if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) { + if (sha256->buffLen == (word32)WC_SHA256_BLOCK_SIZE) { #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.mode == ESP32_SHA_INIT) { @@ -1437,7 +1439,7 @@ static int InitSha256(wc_Sha256* sha256) (defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))) { - while (len >= WC_SHA256_BLOCK_SIZE) { + while (len >= (word32)WC_SHA256_BLOCK_SIZE) { word32* local32 = sha256->buffer; /* optimization to avoid memcpy if data pointer is properly aligned */ /* Intel transform function requires use of sha256->buffer */ @@ -1490,7 +1492,7 @@ static int InitSha256(wc_Sha256* sha256) #endif /* save remainder */ - if (ret == 0 && len > 0) { + if (ret == 0 && len > 0U) { XMEMCPY(local, data, len); sha256->buffLen = len; } @@ -1507,7 +1509,7 @@ static int InitSha256(wc_Sha256* sha256) if (sha256 == NULL) { return BAD_FUNC_ARG; } - if (data == NULL && len == 0) { + if (data == NULL && len == 0U) { /* valid, but do nothing */ return 0; } @@ -1545,7 +1547,7 @@ static int InitSha256(wc_Sha256* sha256) /* we'll add a 0x80 byte at the end, ** so make sure we have appropriate buffer length. */ - if (sha256->buffLen > WC_SHA256_BLOCK_SIZE - 1) { + if (sha256->buffLen > (word32)WC_SHA256_BLOCK_SIZE - 1U) { /* exit with error code if there's a bad buffer size in buffLen */ return BAD_STATE_E; } /* buffLen check */ @@ -1554,8 +1556,8 @@ static int InitSha256(wc_Sha256* sha256) local[sha256->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (sha256->buffLen > WC_SHA256_PAD_SIZE) { - if (sha256->buffLen < WC_SHA256_BLOCK_SIZE) { + if (sha256->buffLen > (word32)WC_SHA256_PAD_SIZE) { + if (sha256->buffLen < (word32)WC_SHA256_BLOCK_SIZE) { XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_BLOCK_SIZE - sha256->buffLen); } @@ -2242,7 +2244,9 @@ void wc_Sha256Free(wc_Sha256* sha256) #ifdef WOLFSSL_SMALL_STACK_CACHE if (sha256->W != NULL) { +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(sha256->W, sizeof(word32) * WC_SHA256_BLOCK_SIZE); +#endif XFREE(sha256->W, NULL, DYNAMIC_TYPE_DIGEST); sha256->W = NULL; } @@ -2326,7 +2330,9 @@ void wc_Sha256Free(wc_Sha256* sha256) ESP_LOGV(TAG, "Hardware unlock not needed in wc_Sha256Free."); } #endif +#ifndef WOLFSSL_NO_FORCE_ZERO ForceZero(sha256, sizeof(*sha256)); +#endif } /* wc_Sha256Free */ #endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ @@ -2623,5 +2629,4 @@ int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags) } #endif #endif /* !WOLFSSL_TI_HASH */ - #endif /* NO_SHA256 */ diff --git a/wolfssl/callbacks.h b/wolfssl/callbacks.h index 1010eca9e2..fd9f7ba6b9 100644 --- a/wolfssl/callbacks.h +++ b/wolfssl/callbacks.h @@ -31,7 +31,7 @@ #endif -enum { /* CALLBACK CONSTANTS */ +enum callbackConstants { /* CALLBACK CONSTANTS */ MAX_PACKETNAME_SZ = 24, MAX_CIPHERNAME_SZ = 24, MAX_TIMEOUT_NAME_SZ = 24, diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7ce0436355..89cd156ec3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1546,8 +1546,6 @@ enum Misc { ZLIB_COMPRESSION = 221, /* wolfSSL zlib compression */ HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */ HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ - SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, - /* pre RSA and all master */ #if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_32BIT_MILLI_TIME) TIMESTAMP_LEN = 4, /* timestamp size in ticket */ #else @@ -1559,29 +1557,13 @@ enum Misc { #ifdef WOLFSSL_EARLY_DATA MAXEARLYDATASZ_LEN = 4, /* maxEarlyDataSz size in ticket */ #endif -#endif -#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) - ENCRYPT_LEN = 5120, /* Allow 5k byte buffer for dilithium and - * hybridization with other algs. */ -#else -#ifndef NO_PSK - ENCRYPT_LEN = (ENCRYPT_BASE_BITS / 8) + MAX_PSK_KEY_LEN + 2, -#else - ENCRYPT_LEN = (ENCRYPT_BASE_BITS / 8), -#endif #endif SIZEOF_SENDER = 4, /* clnt or srvr */ FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ - MAX_PLAINTEXT_SZ = (1 << 14), /* Max plaintext sz */ - MAX_TLS_CIPHER_SZ = (1 << 14) + 2048, /* Max TLS encrypted data sz */ #ifdef WOLFSSL_TLS13 MAX_TLS13_PLAIN_SZ = (1 << 14) + 1, /* Max unencrypted data sz */ MAX_TLS13_ENC_SZ = (1 << 14) + 256, /* Max encrypted data sz */ #endif - MAX_MSG_EXTRA = 38 + WC_MAX_DIGEST_SIZE, - /* max added to msg, mac + pad from */ - /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max - digest sz + BLOC_SZ (iv) + pad byte (1) */ MAX_COMP_EXTRA = 1024, /* max compression extra */ MAX_MTU = WOLFSSL_MAX_MTU, /* max expected MTU */ MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ @@ -1615,7 +1597,6 @@ enum Misc { MAX_LIFETIME = 604800, /* maximum ticket lifetime */ RAN_LEN = 32, /* random length */ - SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ ID_LEN = 32, /* session id length */ COOKIE_SECRET_SZ = 14, /* dtls cookie secret size */ MAX_COOKIE_LEN = 32, /* max dtls cookie size */ @@ -1859,6 +1840,35 @@ enum Misc { READ_PROTO = 0 /* reading a protocol message */ }; +#define SECRET_LEN WOLFSSL_MAX_MASTER_KEY_LENGTH + /* pre RSA and all master */ +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) + #define ENCRYPT_LEN 5120 /* Allow 5k byte buffer for dilithium and + * hybridization with other algs. */ +#else + #ifndef NO_PSK + #define ENCRYPT_LEN ((ENCRYPT_BASE_BITS / 8) + MAX_PSK_KEY_LEN + 2) + #else + #define ENCRYPT_LEN (ENCRYPT_BASE_BITS / 8) + #endif +#endif +#ifndef MAX_PLAINTEXT_SZ + #define MAX_PLAINTEXT_SZ 16384u /* (1u << 14) Max plaintext sz */ +#endif + +#ifndef MAX_TLS_CIPHER_SZ + #define MAX_TLS_CIPHER_SZ 18432u /* (1u << 14) + 2048 Max TLS encrypted + data sz */ +#endif +#define SEED_LEN (RAN_LEN * 2) /* tls prf seed length */ +#ifndef MAX_PSK_KEY_LEN + #define MAX_PSK_KEY_LEN 64 /* max psk key supported */ +#endif +#define MAX_MSG_EXTRA (38 + WC_MAX_DIGEST_SIZE) + /* max added to msg, mac + pad from */ + /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max + digest sz + BLOC_SZ (iv) + pad byte (1) */ + #define WOLFSSL_NAMED_GROUP_IS_FFHDE(group) \ (MIN_FFHDE_GROUP <= (group) && (group) <= MAX_FFHDE_GROUP) #ifdef WOLFSSL_HAVE_KYBER @@ -2335,9 +2345,10 @@ enum { #ifdef STATIC_BUFFER_LEN /* user supplied option */ #if STATIC_BUFFER_LEN < 5 || STATIC_BUFFER_LEN > (RECORD_HEADER_SZ + \ - RECORD_SIZE + COMP_EXTRA + MTU_EXTRA + MAX_MSG_EXTRA)) + RECORD_SIZE + COMP_EXTRA + MTU_EXTRA + MAX_MSG_EXTRA) #error Invalid static buffer length #endif + #elif defined(LARGE_STATIC_BUFFERS) #define STATIC_BUFFER_LEN (RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \ MTU_EXTRA + MAX_MSG_EXTRA) @@ -2346,13 +2357,15 @@ enum { #define STATIC_BUFFER_LEN RECORD_HEADER_SZ #endif +#define WOLFSSL_DYNMAIC_IO_BUFFER 1 +#define WOLFSSL_EXTERNAL_IO_BUFFER 2 typedef struct { ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN]; byte* buffer; /* place holder for static or dynamic buffer */ word32 length; /* total buffer length used */ word32 idx; /* idx to part of length already consumed */ word32 bufferSize; /* current buffer size */ - byte dynamicFlag; /* dynamic memory currently in use */ + byte dynamicFlag; /* dynamic(1) or external(2) memory currently in use */ byte offset; /* alignment offset attempt */ } bufferStatic; @@ -2368,8 +2381,12 @@ struct Suites { typedef struct CipherSuite { byte cipherSuite0; byte cipherSuite; +#ifdef HAVE_ECC word32 ecdhCurveOID; +#endif +#ifndef WOLFSSL_LEANPSK_STATIC struct KeyShareEntry* clientKSE; +#endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) int doHelloRetry; #endif @@ -2820,6 +2837,12 @@ WOLFSSL_LOCAL socklen_t wolfSSL_BIO_ADDR_size(const WOLFSSL_BIO_ADDR *addr); /* keys and secrets * keep as a constant size (no additional ifdefs) for session export */ typedef struct Keys { +#ifdef WOLFSSL_LEANPSK_STATIC + /* storing all in a single buffer with offsets to avoid + * placing on and off the stack when storing into individual + * arrays */ + byte keys[MAX_PRF_DIG]; +#else #if !defined(WOLFSSL_AEAD_ONLY) || defined(WOLFSSL_TLS13) byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE]; /* max sizes */ byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE]; @@ -2833,6 +2856,7 @@ typedef struct Keys { byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ]; byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ]; #endif +#endif #ifdef WOLFSSL_DTLS13 byte client_sn_key[MAX_SYM_KEY_SIZE]; @@ -3714,6 +3738,7 @@ struct WOLFSSL_CTX { #ifdef WOLFSSL_TLS13 int certChainCnt; #endif +#ifndef WOLFSSL_LEANPSK_STATIC DerBuffer* privateKey; #ifdef WOLFSSL_BLIND_PRIVATE_KEY DerBuffer* privateKeyMask; /* Mask of private key DER. */ @@ -3723,6 +3748,7 @@ struct WOLFSSL_CTX { byte privateKeyLabel:1; int privateKeySz; int privateKeyDevId; +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altPrivateKey; @@ -3746,7 +3772,9 @@ struct WOLFSSL_CTX { #endif Suites* suites; /* make dynamic, user may not need/set */ void* heap; /* for user memory overrides */ +#ifndef NO_CERTS byte verifyDepth; +#endif byte verifyPeer:1; byte verifyNone:1; byte failNoCert:1; @@ -3884,8 +3912,10 @@ struct WOLFSSL_CTX { CallbackGetPeer CBGetPeer; CallbackSetPeer CBSetPeer; #endif +#ifndef NO_CERTS VerifyCallback verifyCallback; /* cert verification callback */ void* verifyCbCtx; /* cert verify callback user ctx*/ +#endif #ifdef OPENSSL_ALL CertVerifyCallback verifyCertCb; void* verifyCertCbArg; @@ -4159,10 +4189,17 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* All cipher suite related info * Keep as a constant size (no ifdefs) for session export */ typedef struct CipherSpecs { +#ifdef WOLFSSL_LEANPSK_STATIC + byte key_size; + byte iv_size; + byte block_size; + byte aead_mac_size; +#else word16 key_size; word16 iv_size; word16 block_size; word16 aead_mac_size; +#endif byte bulk_cipher_algorithm; byte cipher_type; /* block, stream, or aead */ byte mac_algorithm; @@ -4685,26 +4722,28 @@ enum AcceptStateTls13 { typedef struct Buffers { bufferStatic inputBuffer; bufferStatic outputBuffer; - buffer domainName; /* for client check */ - buffer clearOutputBuffer; - buffer sig; /* signature data */ - buffer digest; /* digest data */ + WOLFSSL_BUFFER_INFO domainName; /* for client check */ + WOLFSSL_BUFFER_INFO clearOutputBuffer; + WOLFSSL_BUFFER_INFO sig; /* signature data */ + WOLFSSL_BUFFER_INFO digest; /* digest data */ int prevSent; /* previous plain text bytes sent when got WANT_WRITE */ int plainSz; /* plain text bytes in buffer to send when got WANT_WRITE */ - byte weOwnCert; /* SSL own cert flag */ - byte weOwnCertChain; /* SSL own cert chain flag */ - byte weOwnKey; /* SSL own key flag */ +#ifndef NO_CERTS + byte weOwnCert:1; /* SSL own cert flag */ + byte weOwnCertChain:1; /* SSL own cert chain flag */ + byte weOwnKey:1; /* SSL own key flag */ +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS byte weOwnAltKey; /* SSL own alt key flag */ #endif - byte weOwnDH; /* SSL own dh (p,g) flag */ + byte weOwnDH:1; /* SSL own dh (p,g) flag */ #ifndef NO_DH - buffer serverDH_P; /* WOLFSSL_CTX owns, unless we own */ - buffer serverDH_G; /* WOLFSSL_CTX owns, unless we own */ - buffer serverDH_Pub; - buffer serverDH_Priv; + WOLFSSL_BUFFER_INFO serverDH_P; /* WOLFSSL_CTX owns, unless we own */ + WOLFSSL_BUFFER_INFO serverDH_G; /* WOLFSSL_CTX owns, unless we own */ + WOLFSSL_BUFFER_INFO serverDH_Pub; + WOLFSSL_BUFFER_INFO serverDH_Priv; DhKey* serverDH_Key; #endif #ifndef NO_CERTS @@ -4729,34 +4768,36 @@ typedef struct Buffers { int altKeySz; /* Size of alt key */ int altKeyDevId; /* Device Id for alt key */ #endif +#ifndef NO_CERTS DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ /* chain after self, in DER, with leading size for each cert */ +#endif #ifdef WOLFSSL_TLS13 int certChainCnt; DerBuffer* certExts; #endif #endif #ifdef WOLFSSL_SEND_HRR_COOKIE - buffer tls13CookieSecret; /* HRR cookie secret */ + WOLFSSL_BUFFER_INFO tls13CookieSecret; /* HRR cookie secret */ #endif #ifdef WOLFSSL_DTLS - WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ + WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ #ifndef NO_WOLFSSL_SERVER - buffer dtlsCookieSecret; /* DTLS cookie secret */ + WOLFSSL_BUFFER_INFO dtlsCookieSecret; /* DTLS cookie secret */ #endif /* NO_WOLFSSL_SERVER */ #endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC - buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */ + WOLFSSL_BUFFER_INFO peerEccDsaKey; /* we own for Ecc Verify Callbacks */ #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - buffer peerEd25519Key; /* for Ed25519 Verify Callbacks */ + WOLFSSL_BUFFER_INFO peerEd25519Key;/* for Ed25519 Verify Callbacks */ #endif /* HAVE_ED25519 */ #ifdef HAVE_ED448 - buffer peerEd448Key; /* for Ed448 Verify Callbacks */ + WOLFSSL_BUFFER_INFO peerEd448Key; /* for Ed448 Verify Callbacks */ #endif /* HAVE_ED448 */ #ifndef NO_RSA - buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ + WOLFSSL_BUFFER_INFO peerRsaKey; /* we own for Rsa Verify Callbacks */ #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ } Buffers; @@ -4791,7 +4832,9 @@ enum cipherState { struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; +#ifndef NO_WOLFSSL_SERVER wc_psk_server_callback server_psk_cb; +#endif #ifdef OPENSSL_EXTRA wc_psk_use_session_cb_func session_psk_cb; #endif @@ -4802,7 +4845,9 @@ struct Options { #endif void* psk_ctx; #endif /* NO_PSK */ +#ifndef WOLFSSL_NO_DOWNGRADE unsigned long mask; /* store SSL_OP_ flags */ +#endif #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) word16 minProto:1; /* sets min to min available */ word16 maxProto:1; /* sets max to max available */ @@ -4828,7 +4873,9 @@ struct Options { word16 verifyNone:1; word16 failNoCert:1; word16 failNoCertxPSK:1; /* fail for no cert except with PSK */ +#ifndef WOLFSSL_NO_DOWNGRADE word16 downgrade:1; /* allow downgrade of versions */ +#endif word16 resuming:1; #ifdef HAVE_SECURE_RENEGOTIATION word16 resumed:1; /* resuming may be reset on SCR */ @@ -4839,8 +4886,8 @@ struct Options { word16 tls1_1:1; /* using TLSv1.1+ ? */ word16 tls1_3:1; /* using TLSv1.3+ ? */ word16 seenUnifiedHdr:1; /* received msg with unified header */ +#ifndef WOLFSSL_LEANPSK_STATIC word16 dtls:1; /* using datagrams ? */ -#ifdef WOLFSSL_DTLS word16 dtlsStateful:1; /* allow stateful processing ? */ #endif word16 connReset:1; /* has the peer reset */ @@ -4849,6 +4896,7 @@ struct Options { word16 sentNotify:1; /* we've sent a close notify */ word16 shutdownDone:1; /* we've completed a shutdown */ word16 usingCompression:1; /* are we using compression */ +#ifndef WOLFSSL_LEANPSK_STATIC word16 haveRSA:1; /* RSA available */ word16 haveECC:1; /* ECC available */ word16 haveDH:1; /* server DH params set by user */ @@ -4858,6 +4906,7 @@ struct Options { word16 haveDilithiumSig:1; /* server Dilithium signed cert */ word16 havePeerCert:1; /* do we have peer's cert */ word16 havePeerVerify:1; /* and peer's cert verify */ +#endif word16 usingPSK_cipher:1; /* are using psk as cipher */ word16 usingAnon_cipher:1; /* are we using an anon cipher */ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) @@ -5034,22 +5083,38 @@ struct Options { typedef struct Arrays { byte* pendingMsg; /* defrag buffer */ byte* preMasterSecret; +#ifdef WOLFSSL_LEANPSK_STATIC + byte preMasterSz; /* differs for DH, actual size */ + byte pendingMsgSz; /* defrag buffer size */ + byte pendingMsgOffset; /* current offset into defrag buffer */ +#else word32 preMasterSz; /* differs for DH, actual size */ word32 pendingMsgSz; /* defrag buffer size */ word32 pendingMsgOffset; /* current offset into defrag buffer */ +#endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef WOLFSSL_LEANPSK_STATIC + /* In special PSK static build these are on stack rather than in struct */ word32 psk_keySz; /* actual size */ char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN]; - char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; byte psk_key[MAX_PSK_KEY_LEN]; #endif + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; +#endif +#ifdef WOLFSSL_LEANPSK_STATIC + /* client + server random + first IV*/ + byte csRandom[(RAN_LEN * 2) + AES_IV_SIZE]; +#else byte clientRandom[RAN_LEN]; + byte serverRandom[RAN_LEN]; +#endif #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) byte clientRandomInner[RAN_LEN]; #endif - byte serverRandom[RAN_LEN]; +#ifndef WOLFSSL_NO_SESSION_RESUMPTION byte sessionID[ID_LEN]; byte sessionIDSz; +#endif #ifdef WOLFSSL_TLS13 byte secret[SECRET_LEN]; #endif @@ -5090,7 +5155,7 @@ typedef struct Arrays { #define MAX_DATE_SZ 32 #endif -typedef enum { +typedef enum WOLF_STACK_TYPE { STACK_TYPE_X509 = 0, STACK_TYPE_GEN_NAME = 1, STACK_TYPE_BIO = 2, @@ -5176,6 +5241,7 @@ struct WOLFSSL_X509_NAME { typedef struct DNS_entry DNS_entry; #endif +#ifndef NO_CERTS struct WOLFSSL_X509 { int version; int serialSz; @@ -5321,6 +5387,7 @@ struct WOLFSSL_X509 { int altSigValLen; #endif /* WOLFSSL_DUAL_ALG_CERTS */ }; +#endif /* !NO_CERTS */ #if defined(WOLFSSL_ACERT) struct WOLFSSL_X509_ACERT { @@ -5355,6 +5422,7 @@ typedef struct RecordLayerHeader { } RecordLayerHeader; +#ifdef WOLFSSL_DTLS /* record layer header for DTLS PlainText, Compressed, and CipherText */ typedef struct DtlsRecordLayerHeader { byte type; @@ -5400,7 +5468,7 @@ typedef struct DtlsMsg { byte ready:1; byte encrypted:1; } DtlsMsg; - +#endif #ifdef HAVE_NETX @@ -5440,7 +5508,9 @@ typedef struct MsgsReceived { /* Handshake hashes */ typedef struct HS_Hashes { Hashes verifyHashes; +#ifndef NO_CERTS Hashes certHashes; /* for cert verify */ +#endif #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ defined(WOLFSSL_ALLOW_TLS_SHA1)) wc_Sha hashSha; /* sha hash of handshake msgs */ @@ -5473,15 +5543,17 @@ typedef struct HS_Hashes { #ifndef WOLFSSL_NO_TLS12 /* Persistable BuildMessage arguments */ typedef struct BuildMsgArgs { - word32 digestSz; + byte digestSz; word32 sz; word32 pad; word32 idx; word32 headerSz; word16 size; - word32 ivSz; /* TLSv1.1 IV */ + byte ivSz; /* TLSv1.1 IV */ byte* iv; +#ifndef WOLFSSL_LEANPSK_STATIC ALIGN16 byte staticIvBuffer[MAX_IV_SZ]; +#endif } BuildMsgArgs; #endif @@ -5631,21 +5703,29 @@ typedef struct CIDInfo CIDInfo; /* The idea is to reuse the context suites object whenever possible to save * space. */ +#ifdef WOLFSSL_LEANPSK_STATIC +#define WOLFSSL_SUITES(ssl) (const Suites*)(ssl)->suites +#else #define WOLFSSL_SUITES(ssl) \ ((const Suites*) ((ssl)->suites != NULL ? \ (ssl)->suites : \ (ssl)->ctx->suites)) +#endif /* wolfSSL ssl type */ struct WOLFSSL { +#ifndef WOLFSSL_LEANPSK_STATIC WOLFSSL_CTX* ctx; +#endif #if defined(WOLFSSL_HAPROXY) WOLFSSL_CTX* initial_ctx; /* preserve session key materials */ #endif +#ifndef WOLFSSL_LEANPSK_STATIC Suites* suites; /* Only need during handshake. Can be NULL when * re-using the context's object. When WOLFSSL * object needs separate instance of suites use * AllocateSuites(). */ +#endif #ifdef OPENSSL_EXTRA const Suites* clSuites; #endif @@ -5662,11 +5742,15 @@ struct WOLFSSL { #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) HS_Hashes* hsHashesEch; #endif +#ifndef WOLFSSL_LEANPSK_STATIC_IO void* IOCB_ReadCtx; void* IOCB_WriteCtx; +#endif WC_RNG* rng; +#ifndef NO_CERTS void* verifyCbCtx; /* cert verify callback user ctx*/ VerifyCallback verifyCallback; /* cert verification callback */ +#endif void* heap; /* for user overrides */ #ifdef HAVE_WRITE_DUP WriteDup* dupWrite; /* valid pointer indicates ON */ @@ -5705,43 +5789,63 @@ struct WOLFSSL { * to encounter encryption blocking or fragment the message. */ struct WOLFSSL_ASYNC* async; #endif +#ifndef WOLFSSL_LEANPSK_STATIC void* hsKey; /* Handshake key (RsaKey or ecc_key) * allocated from heap */ word32 hsType; /* Type of Handshake key (hsKey) */ WOLFSSL_CIPHER cipher; +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS void* hsAltKey; /* Handshake key (dilithium, falcon) * allocated from heap */ word32 hsAltType; /* Type of Handshake key (hsAltKey) */ #endif +#ifndef WOLFSSL_LEANPSK_STATIC #ifndef WOLFSSL_AEAD_ONLY hmacfp hmac; #endif Ciphers encrypt; Ciphers decrypt; +#else + byte encryptSetup:1; + byte decryptSetup:1; +#endif Buffers buffers; +#ifndef WOLFSSL_NO_SESSION_RESUMPTION WOLFSSL_SESSION* session; +#endif #ifndef NO_CLIENT_CACHE ClientSession* clientSession; #endif WOLFSSL_ALERT_HISTORY alert_history; WOLFSSL_ALERT pendingAlert; int error; +#ifndef WOLFSSL_LEANPSK_STATIC_IO int rfd; /* read file descriptor */ int wfd; /* write file descriptor */ int rflags; /* user read flags */ int wflags; /* user write flags */ +#endif +#ifndef NO_ASN_TIME word32 timeout; /* session timeout */ +#endif +#ifdef WOLFSSL_LEANPSK_STATIC + word16 fragOffset; /* fragment offset */ + word16 curStartIdx; +#else word32 fragOffset; /* fragment offset */ - word16 curSize; word32 curStartIdx; +#endif + word16 curSize; +#ifndef NO_CERTS byte verifyDepth; +#endif RecordLayerHeader curRL; MsgsReceived msgsReceived; /* peer messages received */ ProtocolVersion version; /* negotiated version */ ProtocolVersion chVersion; /* client hello version */ CipherSpecs specs; - Keys keys; + Keys* keys; Options options; #ifdef WOLFSSL_SESSION_ID_CTX byte sessionCtx[ID_LEN]; /* app session context ID */ @@ -5933,7 +6037,9 @@ struct WOLFSSL { points to ctx if not owned (owned flag found in buffers.weOwnCert) */ #endif +#ifndef NO_CERTS byte keepCert; /* keep certificate after handshake */ +#endif #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data, for Fortress */ #endif @@ -6301,11 +6407,15 @@ enum { REQUIRES_AEAD }; -static const byte kTlsClientStr[SIZEOF_SENDER+1] = { 0x43, 0x4C, 0x4E, 0x54, 0x00 }; /* CLNT */ -static const byte kTlsServerStr[SIZEOF_SENDER+1] = { 0x53, 0x52, 0x56, 0x52, 0x00 }; /* SRVR */ +static const FLASH_QUALIFIER byte kTlsClientStr[SIZEOF_SENDER+1] = + { 0x43, 0x4C, 0x4E, 0x54, 0x00 }; /* CLNT */ +static const FLASH_QUALIFIER byte kTlsServerStr[SIZEOF_SENDER+1] = + { 0x53, 0x52, 0x56, 0x52, 0x00 }; /* SRVR */ +#ifndef WOLFSSL_LEANPSK_STATIC static const byte kTlsClientFinStr[FINISHED_LABEL_SZ + 1] = "client finished"; static const byte kTlsServerFinStr[FINISHED_LABEL_SZ + 1] = "server finished"; +#endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) typedef struct { @@ -6357,7 +6467,11 @@ WOLFSSL_LOCAL int SendHelloRequest(WOLFSSL* ssl); WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL* ssl); WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL* ssl); WOLFSSL_LOCAL int SendBuffered(WOLFSSL* ssl); +#ifdef WOLFSSL_LEANPSK_STATIC +WOLFSSL_LOCAL int ReceiveData(WOLFSSL* ssl, byte** output, int sz, int peek); +#else WOLFSSL_LOCAL int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek); +#endif WOLFSSL_LOCAL int SendFinished(WOLFSSL* ssl); WOLFSSL_LOCAL int RetrySendAlert(WOLFSSL* ssl); WOLFSSL_LOCAL int SendAlert(WOLFSSL* ssl, int severity, int type); @@ -6386,6 +6500,10 @@ WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL byte* GetOutputBuffer(WOLFSSL* ssl); +#ifdef WOLFSSL_LEANPSK_STATIC +WOLFSSL_LOCAL int SetOutputBuffer(WOLFSSL* ssl, byte* buf, int bufSz); +WOLFSSL_LOCAL int SetInputBuffer(WOLFSSL* ssl, byte* buf, int bufSz); +#endif WOLFSSL_LOCAL int CipherRequires(byte first, byte second, int requirement); WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0, @@ -6408,6 +6526,7 @@ WOLFSSL_LOCAL int SetECKeyExternal(WOLFSSL_EC_KEY* eckey); WOLFSSL_LOCAL int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id); #else +#ifndef WOLFSSL_LEANPSK_STATIC static WC_INLINE int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) { @@ -6416,6 +6535,7 @@ static WC_INLINE int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, return 0; } #endif +#endif WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng); @@ -6505,8 +6625,12 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, #endif /* !NO_CERTS */ WOLFSSL_LOCAL int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen); -WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, +#ifdef WOLFSSL_LEANPSK_STATIC +WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, byte srvr); +#else +WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender); +#endif WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep); WOLFSSL_LOCAL int CheckAvailableSize(WOLFSSL *ssl, int size); WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index fbfea201a1..43b1425873 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -1230,10 +1230,10 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, #endif -#define EVP_R_BAD_DECRYPT (-MIN_CODE_E + 100 + 1) -#define EVP_R_BN_DECODE_ERROR (-MIN_CODE_E + 100 + 2) -#define EVP_R_DECODE_ERROR (-MIN_CODE_E + 100 + 3) -#define EVP_R_PRIVATE_KEY_DECODE_ERROR (-MIN_CODE_E + 100 + 4) +#define EVP_R_BAD_DECRYPT (-(MIN_CODE_E) + 100 + 1) +#define EVP_R_BN_DECODE_ERROR (-(MIN_CODE_E) + 100 + 2) +#define EVP_R_DECODE_ERROR (-(MIN_CODE_E) + 100 + 3) +#define EVP_R_PRIVATE_KEY_DECODE_ERROR (-(MIN_CODE_E) + 100 + 4) #define EVP_PKEY_NONE NID_undef #define EVP_PKEY_DH 28 diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index ef65f60ea9..2ed4ec0b66 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1556,11 +1556,11 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define PEM_F_PEM_DEF_CALLBACK 100 /* Avoid wolfSSL error code range */ -#define PEM_R_NO_START_LINE (-MIN_CODE_E + 1) -#define PEM_R_PROBLEMS_GETTING_PASSWORD (-MIN_CODE_E + 2) -#define PEM_R_BAD_PASSWORD_READ (-MIN_CODE_E + 3) -#define PEM_R_BAD_DECRYPT (-MIN_CODE_E + 4) -#define ASN1_R_HEADER_TOO_LONG (-MIN_CODE_E + 5) +#define PEM_R_NO_START_LINE (-(MIN_CODE_E) + 1) +#define PEM_R_PROBLEMS_GETTING_PASSWORD (-(MIN_CODE_E) + 2) +#define PEM_R_BAD_PASSWORD_READ (-(MIN_CODE_E) + 3) +#define PEM_R_BAD_DECRYPT (-(MIN_CODE_E) + 4) +#define ASN1_R_HEADER_TOO_LONG (-(MIN_CODE_E) + 5) #define ERR_LIB_SYS 2 #define ERR_LIB_RSA 4 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 90f711589e..c19cbdcd79 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1145,6 +1145,9 @@ WOLFSSL_API int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list); #endif WOLFSSL_ABI WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx); WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(const WOLFSSL* ssl); +#ifdef WOLFSSL_LEANPSK_STATIC +WOLFSSL_API WOLFSSL* wolfSSL_new_leanpsk(WOLFSSL_METHOD* method, byte ciphersuite0, byte ciphersuite1, unsigned char* ran, int ranSz); +#endif WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx); WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm); @@ -1176,6 +1179,12 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_connect(WOLFSSL* ssl); WOLFSSL_ABI WOLFSSL_API int wolfSSL_write( WOLFSSL* ssl, const void* data, int sz); WOLFSSL_ABI WOLFSSL_API int wolfSSL_read(WOLFSSL* ssl, void* data, int sz); +#ifdef WOLFSSL_LEANPSK_STATIC +WOLFSSL_API int wolfSSL_write_inline( WOLFSSL* ssl, const void* data, + int dataSz, int maxSz); +WOLFSSL_API int wolfSSL_read_inline(WOLFSSL* ssl, void* buf, int bufSz, + void** data, int dataSz); +#endif WOLFSSL_API int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz); WOLFSSL_ABI WOLFSSL_API int wolfSSL_accept(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req); @@ -2350,7 +2359,7 @@ WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); #define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ /* These are bit-masks */ -enum { +enum ocspCrlCheck { WOLFSSL_OCSP_URL_OVERRIDE = 1, WOLFSSL_OCSP_NO_NONCE = 2, WOLFSSL_OCSP_CHECKALL = 4, @@ -2360,7 +2369,7 @@ enum { }; /* Separated out from other enums because of size */ -enum { +enum sslOptionsCode { WOLFSSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001, WOLFSSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002, WOLFSSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000004, @@ -2603,18 +2612,17 @@ WOLFSSL_API void wolfSSL_ERR_print_errors(WOLFSSL_BIO *bio); #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE #endif -enum { /* ssl Constants */ - WOLFSSL_ERROR_NONE = 0, /* for most functions */ - WOLFSSL_FAILURE = 0, /* for some functions */ - - #if defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES) && \ - (defined(BUILDING_WOLFSSL) || \ - defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_ALWAYS)) - #define WOLFSSL_FAILURE WC_ERR_TRACE(WOLFSSL_FAILURE) - #define CONST_NUM_ERR_WOLFSSL_FAILURE 0 - #endif +#define WOLFSSL_ERROR_NONE 0 /* for most functions */ +#define WOLFSSL_FAILURE 0 /* for some functions */ +#define WOLFSSL_SUCCESS 1 - WOLFSSL_SUCCESS = 1, +#if defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES) && \ + (defined(BUILDING_WOLFSSL) || \ + defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_ALWAYS)) + #undef WOLFSSL_FAILURE + #define WOLFSSL_FAILURE WC_ERR_TRACE(WOLFSSL_FAILURE) + #define CONST_NUM_ERR_WOLFSSL_FAILURE 0 +#endif /* WOLFSSL_SHUTDOWN_NOT_DONE is returned by wolfSSL_shutdown and * wolfSSL_SendUserCanceled when the other end @@ -2626,55 +2634,53 @@ enum { /* ssl Constants */ */ #ifdef WOLFSSL_ERROR_CODE_OPENSSL /* SSL_shutdown returns 0 when not done, per OpenSSL documentation. */ - WOLFSSL_SHUTDOWN_NOT_DONE = 0, +#define WOLFSSL_SHUTDOWN_NOT_DONE 0 #else - WOLFSSL_SHUTDOWN_NOT_DONE = 2, -#endif - - WOLFSSL_FILETYPE_ASN1 = CTC_FILETYPE_ASN1, - WOLFSSL_FILETYPE_PEM = CTC_FILETYPE_PEM, - WOLFSSL_FILETYPE_DEFAULT = CTC_FILETYPE_ASN1, /* ASN1 */ - - WOLFSSL_VERIFY_NONE = 0, - WOLFSSL_VERIFY_PEER = 1 << 0, - WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 1 << 1, - WOLFSSL_VERIFY_CLIENT_ONCE = 1 << 2, - WOLFSSL_VERIFY_POST_HANDSHAKE = 1 << 3, - WOLFSSL_VERIFY_FAIL_EXCEPT_PSK = 1 << 4, - WOLFSSL_VERIFY_DEFAULT = 1 << 9, - - WOLFSSL_SESS_CACHE_OFF = 0x0000, - WOLFSSL_SESS_CACHE_CLIENT = 0x0001, - WOLFSSL_SESS_CACHE_SERVER = 0x0002, - WOLFSSL_SESS_CACHE_BOTH = 0x0003, - WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, - WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, - WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, - WOLFSSL_SESS_CACHE_NO_INTERNAL = - (WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE | - WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP), - - /* These values match OpenSSL values for corresponding names. */ - WOLFSSL_ERROR_SSL = 1, - WOLFSSL_ERROR_WANT_READ = 2, - WOLFSSL_ERROR_WANT_WRITE = 3, - WOLFSSL_ERROR_WANT_X509_LOOKUP = 4, - WOLFSSL_ERROR_SYSCALL = 5, - WOLFSSL_ERROR_ZERO_RETURN = 6, - WOLFSSL_ERROR_WANT_CONNECT = 7, - WOLFSSL_ERROR_WANT_ACCEPT = 8, - - WOLFSSL_SENT_SHUTDOWN = 1, - WOLFSSL_RECEIVED_SHUTDOWN = 2, - WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, - - WOLFSSL_R_SSL_HANDSHAKE_FAILURE = 101, - WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, - WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, - WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, - - WOLF_PEM_BUFSIZE = 1024 -}; +#define WOLFSSL_SHUTDOWN_NOT_DONE 2 +#endif + +#define WOLFSSL_FILETYPE_ASN1 CTC_FILETYPE_ASN1 +#define WOLFSSL_FILETYPE_PEM CTC_FILETYPE_PEM +#define WOLFSSL_FILETYPE_DEFAULT CTC_FILETYPE_ASN1 /* ASN1 */ + +#define WOLFSSL_VERIFY_NONE 0 +#define WOLFSSL_VERIFY_PEER 1 << 0 +#define WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT 1 << 1 +#define WOLFSSL_VERIFY_CLIENT_ONCE 1 << 2 +#define WOLFSSL_VERIFY_POST_HANDSHAKE 1 << 3 +#define WOLFSSL_VERIFY_FAIL_EXCEPT_PSK 1 << 4 +#define WOLFSSL_VERIFY_DEFAULT 1 << 9 + +#define WOLFSSL_SESS_CACHE_OFF 0x0000 +#define WOLFSSL_SESS_CACHE_CLIENT 0x0001 +#define WOLFSSL_SESS_CACHE_SERVER 0x0002 +#define WOLFSSL_SESS_CACHE_BOTH 0x0003 +#define WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR 0x0008 +#define WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 +#define WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 +#define WOLFSSL_SESS_CACHE_NO_INTERNAL \ + (WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE | WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) + +/* These values match OpenSSL values for corresponding names. */ +#define WOLFSSL_ERROR_SSL 1 +#define WOLFSSL_ERROR_WANT_READ 2 +#define WOLFSSL_ERROR_WANT_WRITE 3 +#define WOLFSSL_ERROR_WANT_X509_LOOKUP 4 +#define WOLFSSL_ERROR_SYSCALL 5 +#define WOLFSSL_ERROR_ZERO_RETURN 6 +#define WOLFSSL_ERROR_WANT_CONNECT 7 +#define WOLFSSL_ERROR_WANT_ACCEPT 8 + +#define WOLFSSL_SENT_SHUTDOWN 1 +#define WOLFSSL_RECEIVED_SHUTDOWN 2 +#define WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 4 + +#define WOLFSSL_R_SSL_HANDSHAKE_FAILURE 101 +#define WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA 102 +#define WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 103 +#define WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE 104 + +#define WOLF_PEM_BUFSIZE 1024 #ifndef NO_PSK typedef unsigned int (*wc_psk_client_callback)(WOLFSSL* ssl, const char*, char*, @@ -3392,6 +3398,7 @@ enum { WOLFSSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */ }; + /* for GetBulkCipher and internal use * using explicit values to assist with serialization of a TLS session */ enum BulkCipherAlgorithm { @@ -4061,7 +4068,7 @@ WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, #endif /* Named Groups */ -enum { +enum eccNameGroup { WOLFSSL_NAMED_GROUP_INVALID = 0, #if 0 /* Not Supported */ WOLFSSL_ECC_SECT163K1 = 1, @@ -4156,7 +4163,7 @@ enum { #endif /* HAVE_PQC */ }; -enum { +enum eccCompresion { WOLFSSL_EC_PF_UNCOMPRESSED = 0, #if 0 /* Not Supported */ WOLFSSL_EC_PF_X962_COMP_PRIME = 1, diff --git a/wolfssl/test.h b/wolfssl/test.h index 60327d53a6..4183af3d98 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1473,15 +1473,18 @@ static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, { SOCKADDR_IN_T addr; build_addr(&addr, ip, port, udp, sctp); +#ifdef WOLFSSL_DTLS if (udp) { wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); } +#endif tcp_socket(sockfd, udp, sctp); if (!udp) { if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) err_sys_with_errno("tcp connect failed"); } + (void)ssl; /* not used when compiled without DTLS support */ } #endif /* WOLFSSL_WOLFSENTRY_HOOKS */ @@ -1851,7 +1854,9 @@ static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ XSTRNCPY(identity, kIdentityStr, id_max_len); +#ifdef WOLFSSL_TLS13 if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { +#endif /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using * unsigned binary */ key[0] = 0x1a; @@ -1860,6 +1865,7 @@ static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, key[3] = 0x4d; ret = 4; /* length of key in octets or 0 for error */ +#ifdef WOLFSSL_TLS13 } else { int i; @@ -1873,6 +1879,7 @@ static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, ret = 32; /* length of key in octets or 0 for error */ } +#endif #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PSK) WOLFSSL_PKMSG("PSK Client using HW (Len %d, Hint %s)\n", ret, hint); diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index cf08ec3a5c..8f497d43c7 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -163,7 +163,7 @@ WOLFSSL_LOCAL void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c, #ifndef WOLFSSL_AES_KEY_SIZE_ENUM #define WOLFSSL_AES_KEY_SIZE_ENUM /* these are required for FIPS and non-FIPS */ -enum { +enum aesSizes { AES_128_KEY_SIZE = 16, /* for 128 bit */ AES_192_KEY_SIZE = 24, /* for 192 bit */ AES_256_KEY_SIZE = 32, /* for 256 bit */ @@ -180,7 +180,7 @@ enum { #include #endif -enum { +enum aesTypes { AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */ AES_ENCRYPTION = 0, AES_DECRYPTION = 1, @@ -255,7 +255,12 @@ enum { #endif struct Aes { +#if defined(NO_AES_192) && defined(NO_AES_256) + /* only need to store an expanded 128 bit key */ + ALIGN16 word32 key[44]; +#else ALIGN16 word32 key[60]; +#endif #ifdef WC_AES_BITSLICED /* Extra key schedule space required for bit-slicing technique. */ ALIGN16 bs_word bs_key[15 * AES_BLOCK_SIZE * BS_WORD_SIZE]; @@ -267,8 +272,9 @@ struct Aes { int keylen; ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ +#ifndef WOLFSSL_LEANPSK ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ - +#endif #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) word32 invokeCtr[2]; word32 nonceSz; diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 98270ee7ba..0e1b05c286 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -65,50 +65,48 @@ #define WC_HMAC_INNER_HASH_KEYED_SW 1 #define WC_HMAC_INNER_HASH_KEYED_DEV 2 -enum { - HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum */ - IPAD = 0x36, - OPAD = 0x5C, +#define HMAC_FIPS_MIN_KEY 14 /* 112 bit key length minimum */ + +#define IPAD 0x36 +#define OPAD 0x5C /* If any hash is not enabled, add the ID here. */ #ifdef NO_MD5 - WC_MD5 = WC_HASH_TYPE_MD5, + #define WC_MD5 WC_HASH_TYPE_MD5 #endif #ifdef NO_SHA - WC_SHA = WC_HASH_TYPE_SHA, + #define WC_SHA WC_HASH_TYPE_SHA #endif #ifdef NO_SHA256 - WC_SHA256 = WC_HASH_TYPE_SHA256, + #define WC_SHA256 WC_HASH_TYPE_SHA256 #endif #ifndef WOLFSSL_SHA512 - WC_SHA512 = WC_HASH_TYPE_SHA512, + #define WC_SHA512 WC_HASH_TYPE_SHA512 #ifndef WOLFSSL_NOSHA512_224 - WC_SHA512_224 = WC_HASH_TYPE_SHA512_224, + #define WC_SHA512_224 WC_HASH_TYPE_SHA512_224 #endif #ifndef WOLFSSL_NOSHA512_256 - WC_SHA512_256 = WC_HASH_TYPE_SHA512_256, + #define WC_SHA512_256 WC_HASH_TYPE_SHA512_256 #endif #endif #ifndef WOLFSSL_SHA384 - WC_SHA384 = WC_HASH_TYPE_SHA384, + #define WC_SHA384 WC_HASH_TYPE_SHA384 #endif #ifndef WOLFSSL_SHA224 - WC_SHA224 = WC_HASH_TYPE_SHA224, + #define WC_SHA224 WC_HASH_TYPE_SHA224 #endif #ifndef WOLFSSL_SHA3 - WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, - WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, - WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, - WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, + #define WC_SHA3_224 WC_HASH_TYPE_SHA3_224 + #define WC_SHA3_256 WC_HASH_TYPE_SHA3_256 + #define WC_SHA3_384 WC_HASH_TYPE_SHA3_384 + #define WC_SHA3_512 WC_HASH_TYPE_SHA3_512 #endif #ifdef WOLF_PRIVATE_KEY_ID - HMAC_MAX_ID_LEN = 32, - HMAC_MAX_LABEL_LEN = 32, +#define HMAC_MAX_ID_LEN 32 +#define HMAC_MAX_LABEL_LEN 32 #endif - WOLF_ENUM_DUMMY_LAST_ELEMENT(HMAC) -}; /* Select the largest available hash for the buffer size. */ #define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE diff --git a/wolfssl/wolfcrypt/kdf.h b/wolfssl/wolfcrypt/kdf.h index 1e731ebc63..440b47ca67 100644 --- a/wolfssl/wolfcrypt/kdf.h +++ b/wolfssl/wolfcrypt/kdf.h @@ -44,17 +44,21 @@ WOLFSSL_LOCAL int wolfCrypt_FIPS_KDF_sanity(void); #endif -enum max_prf { #ifdef HAVE_FFDHE_8192 - MAX_PRF_HALF = 516, /* Maximum half secret len */ + #define MAX_PRF_HALF 516 /* Maximum half secret len */ #elif defined(HAVE_FFDHE_6144) - MAX_PRF_HALF = 388, /* Maximum half secret len */ + #define MAX_PRF_HALF 388 /* Maximum half secret len */ #else - MAX_PRF_HALF = 260, /* Maximum half secret len */ + #define MAX_PRF_HALF 260 /* Maximum half secret len */ +#endif + +#ifndef MAX_PRF_LABSEED + #define MAX_PRF_LABSEED 128 /* Maximum label + seed len */ +#endif + +#ifndef MAX_PRF_DIG + #define MAX_PRF_DIG 224 /* Maximum digest len */ #endif - MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ - MAX_PRF_DIG = 224 /* Maximum digest len */ -}; #ifdef WOLFSSL_HAVE_PRF diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 03cd5e5501..80d9ab540a 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1619,12 +1619,17 @@ extern void uITRON4_free(void *p) ; /* To support storing some of the large constant tables in flash memory rather than SRAM. Useful for processors that have limited SRAM, such as the AVR family of microtrollers. */ #ifdef WOLFSSL_USE_FLASHMEM +#ifdef __18CXX + #define FLASH_QUALIFIER rom + #define XMEMCPY_P memcpypgm2ram +#else /* This is supported on the avr-gcc compiler, for more information see: https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html */ #define FLASH_QUALIFIER __flash /* Copy data out of flash memory and into SRAM */ #define XMEMCPY_P(pdest, psrc, size) memcpy_P((pdest), (psrc), (size)) +#endif #else #ifndef FLASH_QUALIFIER #define FLASH_QUALIFIER diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index c435cf061c..681ea2042f 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -120,12 +120,12 @@ #endif /* in bytes */ -enum { - WC_SHA256 = WC_HASH_TYPE_SHA256, - WC_SHA256_BLOCK_SIZE = 64, - WC_SHA256_DIGEST_SIZE = 32, - WC_SHA256_PAD_SIZE = 56 -}; + +#define WC_SHA256 WC_HASH_TYPE_SHA256 +#define WC_SHA256_BLOCK_SIZE 64 +#define WC_SHA256_DIGEST_SIZE 32 +#define WC_SHA256_PAD_SIZE 56 + #ifdef WOLFSSL_TI_HASH diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 6aacec3604..04322f0542 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -554,7 +554,7 @@ typedef struct w64wrapper { #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ - && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4) + && !defined(WOLFSSL_uITRON4) /* default C runtime, can install different routines at runtime via cbs */ #ifndef WOLFSSL_MEMORY_H #include @@ -726,8 +726,13 @@ typedef struct w64wrapper { #include #endif + #ifdef __18CXX + #define XMEMCPY(d,s,l) memcpy((void*)(d),(void*)(s),(size_t)(l)) + #define XMEMSET(b,c,l) memset((void*)(b),(c),(size_t)(l)) + #else #define XMEMCPY(d,s,l) memcpy((d),(s),(l)) #define XMEMSET(b,c,l) memset((b),(c),(l)) + #endif #define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n)) #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) @@ -995,7 +1000,7 @@ typedef struct w64wrapper { /* memory allocation types for user hints */ - enum { + enum dynamicTypes { DYNAMIC_TYPE_CA = 1, DYNAMIC_TYPE_CERT = 2, DYNAMIC_TYPE_KEY = 3, diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index cb8d0f732d..d4a532b584 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -537,9 +537,16 @@ WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb); WOLFSSL_API mutex_cb* wc_GetMutexCb(void); #endif +#ifdef WOLFSSL_LEANPSK_STATIC + /* static PSK build (WOLFSSL_STATIC_PSK) that is single threaded + * and has no initializations */ + #define wolfCrypt_Init() 0 + #define wolfCrypt_Cleanup() 0 +#else /* main crypto initialization function */ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Init(void); WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); +#endif #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE WOLFSSL_API long wolfCrypt_heap_peakAllocs_checkpoint(void);