summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/src/internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/src/internal.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/src/internal.c28486
1 files changed, 21755 insertions, 6731 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/internal.c b/FreeRTOS-Plus/Source/WolfSSL/src/internal.c
index 75d85b130..fbdbb13a0 100644
--- a/FreeRTOS-Plus/Source/WolfSSL/src/internal.c
+++ b/FreeRTOS-Plus/Source/WolfSSL/src/internal.c
@@ -1,8 +1,8 @@
/* internal.c
*
- * Copyright (C) 2006-2015 wolfSSL Inc.
+ * Copyright (C) 2006-2020 wolfSSL Inc.
*
- * This file is part of wolfSSL. (formerly known as CyaSSL)
+ * 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
@@ -16,16 +16,37 @@
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
+/*
+ * 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.
+ */
+
+
+#ifdef EXTERNAL_OPTS_OPENVPN
+#error EXTERNAL_OPTS_OPENVPN should not be defined\
+ when building wolfSSL
+#endif
+
+#ifndef WOLFCRYPT_ONLY
+
#include <wolfssl/internal.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
@@ -33,21 +54,24 @@
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
+ #define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA)
+ #include <wolfssl/wolfcrypt/srp.h>
+#endif
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
#ifdef HAVE_NTRU
- #include "ntru_crypto.h"
+ #include "libntruencrypt/ntru_crypto.h"
#endif
-#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
- #ifdef FREESCALE_MQX
- #include <fio.h>
- #else
+#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \
+ defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
+ #ifndef NO_STDIO_FILESYSTEM
#include <stdio.h>
#endif
#endif
@@ -56,12 +80,8 @@
#include <sys/filio.h>
#endif
-#ifndef TRUE
- #define TRUE 1
-#endif
-#ifndef FALSE
- #define FALSE 0
-#endif
+
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
#ifdef _MSC_VER
/* disable for while(0) cases at the .c level for now */
@@ -77,13 +97,11 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#error Cannot use both secure-renegotiation and renegotiation-indication
#endif
-static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
- const byte* input, int inSz, int type);
+#ifndef WOLFSSL_NO_TLS12
#ifndef NO_WOLFSSL_CLIENT
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
word32);
- static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
word32);
#ifndef NO_CERTS
@@ -98,54 +116,66 @@ static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
#ifndef NO_WOLFSSL_SERVER
- static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
- #if !defined(NO_RSA) || defined(HAVE_ECC)
+ #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
#endif
+ #ifdef WOLFSSL_DTLS
+ static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
+ #endif /* WOLFSSL_DTLS */
#endif
+#endif /* !WOLFSSL_NO_TLS12 */
#ifdef WOLFSSL_DTLS
- static INLINE int DtlsCheckWindow(DtlsState* state);
- static INLINE int DtlsUpdateWindow(DtlsState* state);
+ static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl);
+ static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
#endif
-typedef enum {
+enum processReply {
doProcessInit = 0,
#ifndef NO_WOLFSSL_SERVER
runProcessOldClientHello,
#endif
getRecordLayerHeader,
getData,
+ verifyEncryptedMessage,
+ decryptMessage,
+ verifyMessage,
runProcessingOneMessage
-} processReply;
+};
-#ifndef NO_OLD_TLS
-static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
- int content, int verify);
-#endif
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-#ifndef NO_CERTS
-static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
-#endif
+/* 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)
-static void PickHashSigAlgo(WOLFSSL* ssl,
- const byte* hashSigAlgo, word32 hashSigAlgoSz);
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
-#ifndef WOLFSSL_HAVE_MIN
-#define WOLFSSL_HAVE_MIN
+#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY)
+static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
+ int padSz, int content, int verify);
- static INLINE word32 min(word32 a, word32 b)
- {
- return a > b ? b : a;
- }
+#endif
-#endif /* WOLFSSL_HAVE_MIN */
+#endif /* !WOLFSSL_NO_TLS12 */
+#ifdef HAVE_QSH
+ int QSH_Init(WOLFSSL* ssl);
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+ int tsip_useable(const WOLFSSL *ssl);
+ int tsip_generatePremasterSecret();
+ int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz);
+#endif
int IsTLS(const WOLFSSL* ssl)
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
@@ -159,108 +189,172 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
return 1;
+#ifdef WOLFSSL_DTLS
if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
return 1;
+#endif
return 0;
}
-
-#ifdef HAVE_NTRU
-
-static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
+int IsAtLeastTLSv1_3(const ProtocolVersion pv)
{
- /* TODO: add locking? */
- static RNG rng;
+ return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR);
+}
- if (cmd == INIT)
- return (wc_InitRng(&rng) == 0) ? 1 : 0;
+static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
+{
+ (void)isSend;
- if (out == NULL)
+ #ifdef WOLFSSL_DTLS
+ /* For DTLS, epoch 0 is always not encrypted. */
+ if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
return 0;
+ #endif /* WOLFSSL_DTLS */
- if (cmd == GET_BYTE_OF_ENTROPY)
- return (wc_RNG_GenerateBlock(&rng, out, 1) == 0) ? 1 : 0;
-
- if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
- *out = 1;
- return 1;
- }
-
- return 0;
+#ifdef WOLFSSL_TLS13
+ if (isSend)
+ return ssl->encrypt.setup;
+ else
+ return ssl->decrypt.setup;
+#else
+ return ssl->keys.encryptionOn;
+#endif
}
-#endif /* HAVE_NTRU */
-/* used by ssl.c too */
-void c32to24(word32 in, word24 out)
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+/* If SCTP is not enabled returns the state of the dtls option.
+ * If SCTP is enabled returns dtls && !sctp. */
+static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
{
- out[0] = (in >> 16) & 0xff;
- out[1] = (in >> 8) & 0xff;
- out[2] = in & 0xff;
-}
+ int result = ssl->options.dtls;
+ if (result) {
+#ifdef WOLFSSL_SCTP
+ result = !ssl->options.dtlsSctp;
+#endif
+ }
-#ifdef WOLFSSL_DTLS
+ return result;
+}
+#endif /* DTLS || !WOLFSSL_NO_TLS12 */
-static INLINE void c32to48(word32 in, byte out[6])
+
+#ifdef HAVE_QSH
+/* free all structs that where used with QSH */
+static int QSH_FreeAll(WOLFSSL* ssl)
{
- out[0] = 0;
- out[1] = 0;
- out[2] = (in >> 24) & 0xff;
- out[3] = (in >> 16) & 0xff;
- out[4] = (in >> 8) & 0xff;
- out[5] = in & 0xff;
-}
+ QSHKey* key = ssl->QSH_Key;
+ QSHKey* preKey = NULL;
+ QSHSecret* secret = ssl->QSH_secret;
+ QSHScheme* list = NULL;
+ QSHScheme* preList = NULL;
+
+ /* free elements in struct */
+ while (key) {
+ preKey = key;
+ if (key->pri.buffer) {
+ ForceZero(key->pri.buffer, key->pri.length);
+ XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+ }
+ if (key->pub.buffer)
+ XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ key = (QSHKey*)key->next;
-#endif /* WOLFSSL_DTLS */
+ /* free struct */
+ XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+ }
-/* convert 16 bit integer to opaque */
-static INLINE void c16toa(word16 u16, byte* c)
-{
- c[0] = (u16 >> 8) & 0xff;
- c[1] = u16 & 0xff;
-}
+ /* free all of peers QSH keys */
+ key = ssl->peerQSHKey;
+ while (key) {
+ preKey = key;
+ if (key->pri.buffer) {
+ ForceZero(key->pri.buffer, key->pri.length);
+ XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+ }
+ if (key->pub.buffer)
+ XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ key = (QSHKey*)key->next;
+
+ /* free struct */
+ XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+ }
+ key = NULL;
+
+ /* free secret information */
+ if (secret) {
+ /* free up the QSHScheme list in QSHSecret */
+ if (secret->list)
+ list = secret->list;
+ while (list) {
+ preList = list;
+ if (list->PK)
+ XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET);
+ list = (QSHScheme*)list->next;
+ XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH);
+ }
+ /* free secret buffers */
+ if (secret->SerSi) {
+ if (secret->SerSi->buffer) {
+ /* clear extra secret material that supplemented Master Secret*/
+ ForceZero(secret->SerSi->buffer, secret->SerSi->length);
+ XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+ }
+ XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+ }
+ if (secret->CliSi) {
+ if (secret->CliSi->buffer) {
+ /* clear extra secret material that supplemented Master Secret*/
+ ForceZero(secret->CliSi->buffer, secret->CliSi->length);
+ XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+ }
+ XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+ }
+ }
+ XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH);
+ secret = NULL;
-#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
- || defined(HAVE_AESGCM)
-/* convert 32 bit integer to opaque */
-static INLINE void c32toa(word32 u32, byte* c)
-{
- c[0] = (u32 >> 24) & 0xff;
- c[1] = (u32 >> 16) & 0xff;
- c[2] = (u32 >> 8) & 0xff;
- c[3] = u32 & 0xff;
+ return 0;
}
#endif
-/* convert a 24 bit integer into a 32 bit one */
-static INLINE void c24to32(const word24 u24, word32* u32)
-{
- *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
-}
-
+#ifdef HAVE_NTRU
+static WOLFSSL_GLOBAL WC_RNG* rng;
+static WOLFSSL_GLOBAL wolfSSL_Mutex* rngMutex;
-/* convert opaque to 16 bit integer */
-static INLINE void ato16(const byte* c, word16* u16)
+static word32 GetEntropy(unsigned char* out, word32 num_bytes)
{
- *u16 = (word16) ((c[0] << 8) | (c[1]));
-}
+ int ret = 0;
+ if (rng == NULL) {
+ if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0,
+ DYNAMIC_TYPE_RNG)) == NULL)
+ return DRBG_OUT_OF_MEMORY;
+ wc_InitRng(rng);
+ }
-#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET)
+ if (rngMutex == NULL) {
+ if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0,
+ DYNAMIC_TYPE_MUTEX)) == NULL)
+ return DRBG_OUT_OF_MEMORY;
+ wc_InitMutex(rngMutex);
+ }
-/* convert opaque to 32 bit integer */
-static INLINE void ato32(const byte* c, word32* u32)
-{
- *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
-}
+ ret |= wc_LockMutex(rngMutex);
+ ret |= wc_RNG_GenerateBlock(rng, out, num_bytes);
+ ret |= wc_UnLockMutex(rngMutex);
-#endif /* WOLFSSL_DTLS */
+ if (ret != 0)
+ return DRBG_ENTROPY_FAIL;
+ return DRBG_OK;
+}
+#endif /* HAVE_NTRU */
#ifdef HAVE_LIBZ
@@ -328,7 +422,7 @@ static INLINE void ato32(const byte* c, word32* u32)
}
- /* decompress in to out, returnn out size or error */
+ /* decompress in to out, return out size or error */
static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
{
int err;
@@ -348,6 +442,1140 @@ static INLINE void ato32(const byte* c, word32* u32)
#endif /* HAVE_LIBZ */
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+/* serializes the cipher specs struct for exporting */
+static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ word32 idx = 0;
+ CipherSpecs* specs;
+
+ WOLFSSL_ENTER("ExportCipherSpecState");
+
+ if (exp == NULL || ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ specs= &(ssl->specs);
+
+ if (DTLS_EXPORT_SPC_SZ > len) {
+ return BUFFER_E;
+ }
+
+ XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ);
+
+ c16toa(specs->key_size, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(specs->iv_size, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(specs->block_size, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN;
+ exp[idx++] = specs->bulk_cipher_algorithm;
+ exp[idx++] = specs->cipher_type;
+ exp[idx++] = specs->mac_algorithm;
+ exp[idx++] = specs->kea;
+ exp[idx++] = specs->sig_algo;
+ exp[idx++] = specs->hash_size;
+ exp[idx++] = specs->pad_size;
+ exp[idx++] = specs->static_ecdh;
+
+ if (idx != DTLS_EXPORT_SPC_SZ) {
+ WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version");
+ return DTLS_EXPORT_VER_E;
+ }
+
+ WOLFSSL_LEAVE("ExportCipherSpecState", idx);
+ (void)ver;
+ return idx;
+}
+
+
+/* serializes the key struct for exporting */
+static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver,
+ byte small)
+{
+ word32 idx = 0;
+ byte sz;
+ Keys* keys;
+
+ WOLFSSL_ENTER("ExportKeyState");
+
+ if (exp == NULL || ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ keys = &(ssl->keys);
+
+ if (DTLS_EXPORT_MIN_KEY_SZ > len) {
+ WOLFSSL_MSG("Buffer not large enough for minimum key struct size");
+ return BUFFER_E;
+ }
+
+ XMEMSET(exp, 0, DTLS_EXPORT_MIN_KEY_SZ);
+
+ c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
+ c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+ c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
+ c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+
+ c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+ c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+ c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+
+ c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(keys->dtls_expected_peer_handshake_number, exp + idx);
+ idx += OPAQUE16_LEN;
+
+ c16toa(keys->dtls_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->dtls_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+ c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+ c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN;
+ c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN;
+ c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN;
+ exp[idx++] = keys->encryptionOn;
+ exp[idx++] = keys->decryptedCur;
+
+ /* from here on the buffer needs checked because is variable length that
+ * can be larger than DTLS_EXPORT_MIN_KEY_SZ */
+ {
+ word32 i;
+ if ((OPAQUE16_LEN * 2) + idx +
+ (2 * (WOLFSSL_DTLS_WINDOW_WORDS * OPAQUE32_LEN)) > len) {
+ WOLFSSL_MSG("Buffer not large enough for WOLFSSL_DTLS_WINDOW_WORDS");
+ return BUFFER_E;
+ }
+
+ c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+ for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+ c32toa(keys->peerSeq[0].window[i], exp + idx);
+ idx += OPAQUE32_LEN;
+ }
+ c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+ for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+ c32toa(keys->peerSeq[0].prevWindow[i], exp + idx);
+ idx += OPAQUE32_LEN;
+ }
+ }
+
+ if (idx >= len) {
+ WOLFSSL_MSG("Buffer not large enough for truncated hmac flag");
+ return BUFFER_E;
+ }
+
+#ifdef HAVE_TRUNCATED_HMAC
+ sz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size;
+ exp[idx++] = ssl->truncated_hmac;
+#else
+ sz = ssl->specs.hash_size;
+ exp[idx++] = 0; /* no truncated hmac */
+#endif
+
+ sz = (small)? 0: sz;
+ if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+ WOLFSSL_MSG("Buffer not large enough for MAC secret");
+ return BUFFER_E;
+ }
+
+ exp[idx++] = sz;
+ if (sz > 0) {
+ #ifndef WOLFSSL_AEAD_ONLY
+ XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz;
+ XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz;
+ #else
+ XMEMSET(exp + idx, 0, sz); idx += sz;
+ XMEMSET(exp + idx, 0, sz); idx += sz;
+ #endif
+ }
+
+ sz = (small)? 0: ssl->specs.key_size;
+ if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+ WOLFSSL_MSG("Buffer not large enough for write key");
+ return BUFFER_E;
+ }
+
+ exp[idx++] = sz;
+ if (sz > 0) {
+ XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz;
+ XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz;
+ }
+
+ sz = (small)? 0: ssl->specs.iv_size;
+ if (idx + (sz * 2) + OPAQUE8_LEN + AEAD_MAX_EXP_SZ > len) {
+ WOLFSSL_MSG("Buffer not large enough for IVs");
+ return BUFFER_E;
+ }
+
+ exp[idx++] = sz;
+ if (sz > 0) {
+ XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz;
+ XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz;
+ }
+ XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
+ idx += AEAD_MAX_EXP_SZ;
+
+ sz = (small)? 0: AEAD_MAX_IMP_SZ;
+ if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+ WOLFSSL_MSG("Buffer not large enough for imp IVs");
+ return BUFFER_E;
+ }
+ exp[idx++] = sz;
+ if (sz > 0) {
+ XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz;
+ XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz;
+ }
+
+ /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */
+ if (idx > DTLS_EXPORT_KEY_SZ) {
+ WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version");
+ return DTLS_EXPORT_VER_E;
+ }
+
+ WOLFSSL_LEAVE("ExportKeyState", idx);
+ (void)ver;
+ return idx;
+}
+
+static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ word32 idx = 0;
+ CipherSpecs* specs;
+
+ WOLFSSL_ENTER("ImportCipherSpecState");
+
+ if (exp == NULL || ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ specs= &(ssl->specs);
+
+ if (DTLS_EXPORT_SPC_SZ > len) {
+ WOLFSSL_MSG("Buffer not large enough for max spec struct size");
+ return BUFFER_E;
+ }
+
+ ato16(exp + idx, &specs->key_size); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &specs->iv_size); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &specs->block_size); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN;
+ specs->bulk_cipher_algorithm = exp[idx++];
+ specs->cipher_type = exp[idx++];
+ specs->mac_algorithm = exp[idx++];
+ specs->kea = exp[idx++];
+ specs->sig_algo = exp[idx++];
+ specs->hash_size = exp[idx++];
+ specs->pad_size = exp[idx++];
+ specs->static_ecdh = exp[idx++];
+
+ WOLFSSL_LEAVE("ImportCipherSpecState", idx);
+ (void)ver;
+ return idx;
+}
+
+
+static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ word32 idx = 0;
+ byte sz;
+ Keys* keys;
+
+ WOLFSSL_ENTER("ImportKeyState");
+
+ if (exp == NULL || ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ keys = &(ssl->keys);
+
+ /* check minimum length -- includes byte used for size indicators */
+ if (len < DTLS_EXPORT_MIN_KEY_SZ) {
+ WOLFSSL_MSG("Buffer not large enough for minimum expected size");
+ return BUFFER_E;
+ }
+ ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN;
+ ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN;
+ ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN;
+ ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN;
+
+ ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN;
+ ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN;
+ ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN;
+
+ ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
+ idx += OPAQUE16_LEN;
+
+ ato16(exp + idx, &keys->dtls_sequence_number_hi); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->dtls_sequence_number_lo); idx += OPAQUE32_LEN;
+ ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN;
+ ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN;
+ ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN;
+ ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN;
+ keys->encryptionOn = exp[idx++];
+ keys->decryptedCur = exp[idx++];
+
+ {
+ word16 i, wordCount, wordAdj = 0;
+
+ /* do window */
+ ato16(exp + idx, &wordCount);
+ idx += OPAQUE16_LEN;
+
+ if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+ wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+ wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+ }
+
+ XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
+ for (i = 0; i < wordCount; i++) {
+ ato32(exp + idx, &keys->peerSeq[0].window[i]);
+ idx += OPAQUE32_LEN;
+ }
+ idx += wordAdj;
+
+ /* do prevWindow */
+ ato16(exp + idx, &wordCount);
+ idx += OPAQUE16_LEN;
+
+ if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+ wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+ wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+ }
+
+ XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
+ for (i = 0; i < wordCount; i++) {
+ ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]);
+ idx += OPAQUE32_LEN;
+ }
+ idx += wordAdj;
+
+ }
+
+#ifdef HAVE_TRUNCATED_HMAC
+ ssl->truncated_hmac = exp[idx++];
+#else
+ idx++; /* no truncated hmac */
+#endif
+ sz = exp[idx++];
+#ifndef WOLFSSL_AEAD_ONLY
+ if (sz > sizeof(keys->client_write_MAC_secret) || (sz * 2) + idx > len) {
+ WOLFSSL_MSG("Buffer not large enough for MAC import");
+ return BUFFER_E;
+ }
+ if (sz > 0) {
+ XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz;
+ XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz;
+ }
+#else
+ if (sz + idx > len) {
+ return BUFFER_E;
+ }
+ idx += sz; idx += sz;
+#endif
+
+ sz = exp[idx++];
+ if (sz > sizeof(keys->client_write_key) || (sz * 2) + idx > len) {
+ WOLFSSL_MSG("Buffer not large enough for key import");
+ return BUFFER_E;
+ }
+ if (sz > 0) {
+ XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz;
+ XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz;
+ }
+
+ sz = exp[idx++];
+ if (sz > sizeof(keys->client_write_IV) || (sz * 2) + idx > len) {
+ WOLFSSL_MSG("Buffer not large enough for write IV import");
+ return BUFFER_E;
+ }
+ if (sz > 0) {
+ XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz;
+ XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz;
+ }
+ XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ);
+ idx += AEAD_MAX_EXP_SZ;
+
+ sz = exp[idx++];
+ if (sz > sizeof(keys->aead_enc_imp_IV) || (sz * 2) + idx > len) {
+ WOLFSSL_MSG("Buffer not large enough for imp IV import");
+ return BUFFER_E;
+ }
+ if (sz > 0) {
+ XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz;
+ XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz;
+ }
+
+ WOLFSSL_LEAVE("ImportKeyState", idx);
+ (void)ver;
+ return idx;
+}
+
+
+/* copy over necessary information from Options struct to buffer
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ int idx = 0;
+ word16 zero = 0;
+ Options* options = &ssl->options;
+
+ WOLFSSL_ENTER("dtls_export_new");
+
+ if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
+ return BAD_FUNC_ARG;
+ }
+
+ XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ);
+
+ /* these options are kept and sent to indicate verify status and strength
+ * of handshake */
+ exp[idx++] = options->sendVerify;
+ exp[idx++] = options->verifyPeer;
+ exp[idx++] = options->verifyNone;
+ exp[idx++] = options->downgrade;
+#ifndef NO_DH
+ c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(options->dhKeySz, exp + idx); idx += OPAQUE16_LEN;
+#else
+ c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+ c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+ c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+ c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+ c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+ c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+
+ /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+ exp[idx++] = options->havePSK;
+#else
+ exp[idx++] = 0;
+#endif
+ exp[idx++] = options->sessionCacheOff;
+ exp[idx++] = options->sessionCacheFlushOff;
+ exp[idx++] = options->side;
+ exp[idx++] = options->resuming;
+ exp[idx++] = options->haveSessionId;
+ exp[idx++] = options->tls;
+ exp[idx++] = options->tls1_1;
+ exp[idx++] = options->dtls;
+ exp[idx++] = options->connReset;
+ exp[idx++] = options->isClosed;
+ exp[idx++] = options->closeNotify;
+ exp[idx++] = options->sentNotify;
+ exp[idx++] = options->usingCompression;
+ exp[idx++] = options->haveRSA;
+ exp[idx++] = options->haveECC;
+ exp[idx++] = options->haveDH;
+ exp[idx++] = options->haveNTRU;
+ exp[idx++] = options->haveQSH;
+ exp[idx++] = options->haveECDSAsig;
+ exp[idx++] = options->haveStaticECC;
+ exp[idx++] = options->havePeerVerify;
+ exp[idx++] = options->usingPSK_cipher;
+ exp[idx++] = options->usingAnon_cipher;
+ exp[idx++] = options->sendAlertState;
+ exp[idx++] = options->partialWrite;
+ exp[idx++] = options->quietShutdown;
+ exp[idx++] = options->groupMessages;
+#ifdef HAVE_POLY1305
+ exp[idx++] = options->oldPoly;
+#else
+ exp[idx++] = 0;
+#endif
+#ifdef HAVE_ANON
+ exp[idx++] = options->haveAnon;
+#else
+ exp[idx++] = 0;
+#endif
+#ifdef HAVE_SESSION_TICKET
+ exp[idx++] = options->createTicket;
+ exp[idx++] = options->useTicket;
+#ifdef WOLFSSL_TLS13
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ exp[idx++] = options->noTicketTls13;
+ }
+#else
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ exp[idx++] = 0;
+ }
+#endif
+#else
+ exp[idx++] = 0;
+ exp[idx++] = 0;
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ exp[idx++] = 0;
+ }
+#endif
+ exp[idx++] = options->processReply;
+ exp[idx++] = options->cipherSuite0;
+ exp[idx++] = options->cipherSuite;
+ exp[idx++] = options->serverState;
+ exp[idx++] = options->clientState;
+ exp[idx++] = options->handShakeState;
+ exp[idx++] = options->handShakeDone;
+ exp[idx++] = options->minDowngrade;
+ exp[idx++] = options->connectState;
+ exp[idx++] = options->acceptState;
+ exp[idx++] = options->asyncState;
+
+ /* version of connection */
+ exp[idx++] = ssl->version.major;
+ exp[idx++] = ssl->version.minor;
+
+ (void)zero;
+
+ /* check if changes were made and notify of need to update export version */
+ switch (ver) {
+ case DTLS_EXPORT_VERSION_3:
+ if (idx != DTLS_EXPORT_OPT_SZ_3) {
+ WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+ return DTLS_EXPORT_VER_E;
+ }
+ break;
+
+ case DTLS_EXPORT_VERSION:
+ if (idx != DTLS_EXPORT_OPT_SZ) {
+ WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+ return DTLS_EXPORT_VER_E;
+ }
+ break;
+
+ default:
+ WOLFSSL_MSG("New version case needs added to wolfSSL export");
+ return DTLS_EXPORT_VER_E;
+ }
+
+ WOLFSSL_LEAVE("dtls_export_new", idx);
+
+ return idx;
+}
+
+
+/* copy items from Export struct to Options struct
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ int idx = 0;
+ Options* options = &ssl->options;
+
+ switch (ver) {
+ case DTLS_EXPORT_VERSION:
+ if (len < DTLS_EXPORT_OPT_SZ) {
+ WOLFSSL_MSG("Sanity check on buffer size failed");
+ return BAD_FUNC_ARG;
+ }
+ break;
+
+ case DTLS_EXPORT_VERSION_3:
+ if (len < DTLS_EXPORT_OPT_SZ_3) {
+ WOLFSSL_MSG("Sanity check on buffer size failed");
+ return BAD_FUNC_ARG;
+ }
+ break;
+
+ default:
+ WOLFSSL_MSG("Export version not supported");
+ return BAD_FUNC_ARG;
+ }
+
+ if (exp == NULL || options == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+
+ /* these options are kept and sent to indicate verify status and strength
+ * of handshake */
+ options->sendVerify = exp[idx++];
+ options->verifyPeer = exp[idx++];
+ options->verifyNone = exp[idx++];
+ options->downgrade = exp[idx++];
+#ifndef NO_DH
+ ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN;
+ ato16(exp + idx, &(options->dhKeySz)); idx += OPAQUE16_LEN;
+#else
+ idx += OPAQUE16_LEN;
+ idx += OPAQUE16_LEN;
+ idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+ ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN;
+#else
+ idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+ ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN;
+#else
+ idx += OPAQUE16_LEN;
+#endif
+
+ /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+ options->havePSK = exp[idx++];
+#else
+ idx++;
+#endif
+ options->sessionCacheOff = exp[idx++];
+ options->sessionCacheFlushOff = exp[idx++];
+ options->side = exp[idx++];
+ options->resuming = exp[idx++];
+ options->haveSessionId = exp[idx++];
+ options->tls = exp[idx++];
+ options->tls1_1 = exp[idx++];
+ options->dtls = exp[idx++];
+ options->connReset = exp[idx++];
+ options->isClosed = exp[idx++];
+ options->closeNotify = exp[idx++];
+ options->sentNotify = exp[idx++];
+ options->usingCompression = exp[idx++];
+ options->haveRSA = exp[idx++];
+ options->haveECC = exp[idx++];
+ options->haveDH = exp[idx++];
+ options->haveNTRU = exp[idx++];
+ options->haveQSH = exp[idx++];
+ options->haveECDSAsig = exp[idx++];
+ options->haveStaticECC = exp[idx++];
+ options->havePeerVerify = exp[idx++];
+ options->usingPSK_cipher = exp[idx++];
+ options->usingAnon_cipher = exp[idx++];
+ options->sendAlertState = exp[idx++];
+ options->partialWrite = exp[idx++];
+ options->quietShutdown = exp[idx++];
+ options->groupMessages = exp[idx++];
+#ifdef HAVE_POLY1305
+ options->oldPoly = exp[idx++]; /* set when to use old rfc way of poly*/
+#else
+ idx++;
+#endif
+#ifdef HAVE_ANON
+ options->haveAnon = exp[idx++]; /* User wants to allow Anon suites */
+#else
+ idx++;
+#endif
+#ifdef HAVE_SESSION_TICKET
+ options->createTicket = exp[idx++]; /* Server to create new Ticket */
+ options->useTicket = exp[idx++]; /* Use Ticket not session cache */
+#ifdef WOLFSSL_TLS13
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */
+ }
+#else
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ exp[idx++] = 0;
+ }
+#endif
+#else
+ idx++;
+ idx++;
+ if (ver > DTLS_EXPORT_VERSION_3) {
+ idx++;
+ }
+#endif
+ options->processReply = exp[idx++];
+ options->cipherSuite0 = exp[idx++];
+ options->cipherSuite = exp[idx++];
+ options->serverState = exp[idx++];
+ options->clientState = exp[idx++];
+ options->handShakeState = exp[idx++];
+ options->handShakeDone = exp[idx++];
+ options->minDowngrade = exp[idx++];
+ options->connectState = exp[idx++];
+ options->acceptState = exp[idx++];
+ options->asyncState = exp[idx++];
+
+ /* version of connection */
+ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) {
+ WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2");
+ return VERSION_ERROR;
+ }
+
+ return idx;
+}
+
+#ifndef WOLFSSL_SESSION_EXPORT_NOPEER
+static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+ int idx = 0;
+ int ipSz = DTLS_EXPORT_IP; /* start as max size */
+ int fam = 0;
+ word16 port = 0;
+ char ip[DTLS_EXPORT_IP];
+
+ if (ver != DTLS_EXPORT_VERSION) {
+ WOLFSSL_MSG("Export version not supported");
+ return BAD_FUNC_ARG;
+ }
+
+ if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ssl->ctx->CBGetPeer == NULL) {
+ WOLFSSL_MSG("No get peer call back set");
+ return BAD_FUNC_ARG;
+ }
+ if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Get peer callback error");
+ return SOCKET_ERROR_E;
+ }
+
+ /* check that ipSz/fam is not negative or too large since user can set cb */
+ if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) {
+ WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback");
+ return SOCKET_ERROR_E;
+ }
+
+ c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN;
+ c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
+ XMEMCPY(exp + idx, ip, ipSz); idx += ipSz;
+ c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN;
+
+ return idx;
+}
+#endif /* !WOLFSSL_SESSION_EXPORT_NOPEER */
+
+
+static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
+{
+ word16 idx = 0;
+ word16 ipSz;
+ word16 fam;
+ word16 port;
+ char ip[DTLS_EXPORT_IP];
+
+ if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) {
+ WOLFSSL_MSG("Export version not supported");
+ return BAD_FUNC_ARG;
+ }
+
+ if (len == 0) {
+ WOLFSSL_MSG("No peer info sent");
+ return 0;
+ }
+
+ if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* import sin family */
+ ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN;
+
+ /* import ip address idx, and ipSz are unsigned but cast for enum */
+ ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN;
+ if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) {
+ return BUFFER_E;
+ }
+ XMEMSET(ip, 0, sizeof(ip));
+ XMEMCPY(ip, buf + idx, ipSz); idx += ipSz;
+ ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */
+ ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN;
+
+ /* sanity check for a function to call, then use it to import peer info */
+ if (ssl->ctx->CBSetPeer == NULL) {
+ WOLFSSL_MSG("No set peer function");
+ return BAD_FUNC_ARG;
+ }
+ if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error setting peer info");
+ return SOCKET_ERROR_E;
+ }
+
+ return idx;
+}
+
+
+/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session state only
+ * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
+ * passed in.
+ * On success returns the size of serialized session state.*/
+int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+ int ret;
+ word32 idx = 0;
+ word32 totalLen = 0;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_export_state_internal");
+
+ if (buf == NULL || ssl == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BAD_FUNC_ARG);
+ return BAD_FUNC_ARG;
+ }
+
+ totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
+ /* each of the following have a 2 byte length before data */
+ totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_MIN_KEY_SZ;
+ if (totalLen > sz) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E);
+ return BUFFER_E;
+ }
+
+ buf[idx++] = (byte)DTLS_EXPORT_STATE_PRO;
+ buf[idx++] = ((byte)DTLS_EXPORT_STATE_PRO & 0xF0) |
+ ((byte)DTLS_EXPORT_VERSION & 0X0F);
+ idx += DTLS_EXPORT_LEN; /* leave room for total length */
+
+ /* export keys struct and dtls state -- variable length stored in ret */
+ idx += DTLS_EXPORT_LEN; /* leave room for length */
+ if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
+ DTLS_EXPORT_VERSION, 1)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret);
+ return ret;
+ }
+ c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
+
+ /* place total length of exported buffer minus 2 bytes protocol/version */
+ c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
+
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+ /* if compiled with debug options then print the version, protocol, size */
+ {
+ char debug[256];
+ XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session state\n"
+ "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+ , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
+ WOLFSSL_MSG(debug);
+ }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", idx);
+ return idx;
+}
+
+
+/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
+ * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
+ * passed in.
+ * On success returns the size of serialized session.*/
+int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+ int ret;
+ word32 idx = 0;
+ word32 totalLen = 0;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
+
+ if (buf == NULL || ssl == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG);
+ return BAD_FUNC_ARG;
+ }
+
+ totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
+ /* each of the following have a 2 byte length before data */
+ totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ;
+ totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ;
+ totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ;
+ totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
+
+ if (totalLen > sz) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
+ return BUFFER_E;
+ }
+
+ buf[idx++] = (byte)DTLS_EXPORT_PRO;
+ buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
+ ((byte)DTLS_EXPORT_VERSION & 0X0F);
+
+ idx += DTLS_EXPORT_LEN; /* leave spot for length */
+
+ c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+ if ((ret = dtls_export_new(ssl, buf + idx, sz - idx,
+ DTLS_EXPORT_VERSION)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+ return ret;
+ }
+ idx += ret;
+
+ /* export keys struct and dtls state -- variable length stored in ret */
+ idx += DTLS_EXPORT_LEN; /* leave room for length */
+ if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
+ DTLS_EXPORT_VERSION, 0)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+ return ret;
+ }
+ c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
+
+ /* export of cipher specs struct */
+ c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+ if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx,
+ DTLS_EXPORT_VERSION)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+ return ret;
+ }
+ idx += ret;
+
+ /* export of dtls peer information */
+ idx += DTLS_EXPORT_LEN;
+#ifdef WOLFSSL_SESSION_EXPORT_NOPEER
+ ret = 0; /* not saving peer port/ip information */
+#else
+ if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx,
+ DTLS_EXPORT_VERSION)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+ return ret;
+ }
+#endif
+ c16toa(ret, buf + idx - DTLS_EXPORT_LEN);
+ idx += ret;
+
+ /* place total length of exported buffer minus 2 bytes protocol/version */
+ c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
+
+ /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+ {
+ char debug[256];
+ XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n"
+ "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+ , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
+ WOLFSSL_MSG(debug);
+ }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+ WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
+ return idx;
+}
+
+
+/* On success return amount of buffer consumed */
+int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+ word32 idx = 0;
+ word16 length = 0;
+ int version;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal");
+ /* check at least enough room for protocol and length */
+ if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG);
+ return BAD_FUNC_ARG;
+ }
+
+ if (buf[idx++] != (byte)DTLS_EXPORT_STATE_PRO ||
+ (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
+ WOLFSSL_MSG("Incorrect protocol");
+ return BAD_FUNC_ARG;
+ }
+ version = buf[idx++] & 0x0F;
+
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
+ WOLFSSL_MSG("Buffer size sanity check failed");
+ return BUFFER_E;
+ }
+
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+ /* if compiled with debug options then print the version, protocol, size */
+ {
+ char debug[256];
+ XSNPRINTF(debug, sizeof(debug), "Importing DTLS session state\n"
+ "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+ , (int)version, buf[0], (buf[1] >> 4), length);
+ WOLFSSL_MSG(debug);
+ }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+ /* perform sanity checks and extract Options information used */
+ switch (version) {
+ case DTLS_EXPORT_VERSION:
+ break;
+
+ default:
+ WOLFSSL_MSG("Bad export state version");
+ return BAD_FUNC_ARG;
+
+ }
+
+ /* perform sanity checks and extract Keys struct */
+ if (DTLS_EXPORT_LEN + idx > sz) {
+ WOLFSSL_MSG("Import Key struct error");
+ return BUFFER_E;
+ }
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
+ WOLFSSL_MSG("Import Key struct error");
+ return BUFFER_E;
+ }
+ if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
+ WOLFSSL_MSG("Import Key struct error");
+ WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
+ return ret;
+ }
+ idx += ret;
+
+ WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
+ return ret;
+}
+
+
+/* On success return amount of buffer consumed */
+int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+ word32 idx = 0;
+ word16 length = 0;
+ int version;
+ int ret;
+ int optSz;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
+ /* check at least enough room for protocol and length */
+ if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* sanity check on protocol ID and size of buffer */
+ if (buf[idx++] != (byte)DTLS_EXPORT_PRO ||
+ (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
+ /* don't increment on second idx to next get version */
+
+ /* check if importing state only */
+ return wolfSSL_dtls_import_state_internal(ssl, buf, sz);
+ }
+ version = buf[idx++] & 0x0F;
+
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
+ return BUFFER_E;
+ }
+
+ /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+ {
+ char debug[256];
+ XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n"
+ "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+ , (int)version, buf[0], (buf[1] >> 4), length);
+ WOLFSSL_MSG(debug);
+ }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+ /* perform sanity checks and extract Options information used */
+ switch (version) {
+ case DTLS_EXPORT_VERSION:
+ optSz = DTLS_EXPORT_OPT_SZ;
+ break;
+
+ case DTLS_EXPORT_VERSION_3:
+ WOLFSSL_MSG("Importing older version 3");
+ optSz = DTLS_EXPORT_OPT_SZ_3;
+ break;
+
+ default:
+ WOLFSSL_MSG("Bad export version");
+ return BAD_FUNC_ARG;
+
+ }
+
+ if (DTLS_EXPORT_LEN + optSz + idx > sz) {
+ WOLFSSL_MSG("Import Options struct error");
+ return BUFFER_E;
+ }
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (length != optSz) {
+ WOLFSSL_MSG("Import Options struct error");
+ return BUFFER_E;
+ }
+ if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) {
+ WOLFSSL_MSG("Import Options struct error");
+ return ret;
+ }
+ idx += length;
+
+ /* perform sanity checks and extract Keys struct */
+ if (DTLS_EXPORT_LEN + idx > sz) {
+ WOLFSSL_MSG("Import Key struct error");
+ return BUFFER_E;
+ }
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
+ WOLFSSL_MSG("Import Key struct error");
+ return BUFFER_E;
+ }
+ if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
+ WOLFSSL_MSG("Import Key struct error");
+ return ret;
+ }
+ idx += ret;
+
+ /* perform sanity checks and extract CipherSpecs struct */
+ if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) {
+ WOLFSSL_MSG("Import CipherSpecs struct error");
+ return BUFFER_E;
+ }
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if ( length != DTLS_EXPORT_SPC_SZ) {
+ WOLFSSL_MSG("Import CipherSpecs struct error");
+ return BUFFER_E;
+ }
+ if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) {
+ WOLFSSL_MSG("Import CipherSpecs struct error");
+ return ret;
+ }
+ idx += ret;
+
+ /* perform sanity checks and extract DTLS peer info */
+ if (DTLS_EXPORT_LEN + idx > sz) {
+ WOLFSSL_MSG("Import DTLS peer info error");
+ return BUFFER_E;
+ }
+ ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+ if (idx + length > sz) {
+ WOLFSSL_MSG("Import DTLS peer info error");
+ return BUFFER_E;
+ }
+ if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) {
+ WOLFSSL_MSG("Import Peer Addr error");
+ return ret;
+ }
+ idx += ret;
+
+ SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+
+ /* set hmac function to use when verifying */
+ if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 ||
+ ssl->options.dtls == 1) {
+ ssl->hmac = TLS_hmac;
+ }
+
+ /* make sure is a valid suite used */
+ if (wolfSSL_get_cipher(ssl) == NULL) {
+ WOLFSSL_MSG("Can not match cipher suite imported");
+ return MATCH_SUITE_ERROR;
+ }
+
+ /* do not allow stream ciphers with DTLS, except for NULL cipher */
+ if (ssl->specs.cipher_type == stream &&
+ ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) {
+ WOLFSSL_MSG("Can not import stream ciphers for DTLS");
+ return SANITY_CIPHER_E;
+ }
+
+ return idx;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+
void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
{
method->version = pv;
@@ -355,121 +1583,373 @@ void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
method->downgrade = 0;
}
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+int InitSSL_Side(WOLFSSL* ssl, word16 side)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ /* set side */
+ ssl->options.side = side;
+
+ /* reset options that are side specific */
+#ifdef HAVE_NTRU
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ ssl->options.haveNTRU = 1; /* always on client side */
+ /* server can turn on by loading key */
+ }
+#endif
+#ifdef HAVE_ECC
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ ssl->options.haveECDSAsig = 1; /* always on client side */
+ ssl->options.haveECC = 1; /* server turns on with ECC key cert */
+ ssl->options.haveStaticECC = 1; /* server can turn on by loading key */
+ }
+#elif defined(HAVE_ED25519) || defined(HAVE_ED448)
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ ssl->options.haveECDSAsig = 1; /* always on client side */
+ ssl->options.haveECC = 1; /* server turns on with ECC key cert */
+ }
+#endif
-/* Initialze SSL context, return 0 on success */
-int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
+#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if ((ssl->ctx->method->version.major == SSLv3_MAJOR) &&
+ (ssl->ctx->method->version.minor >= TLSv1_MINOR)) {
+ ssl->options.haveEMS = 1;
+ }
+ #ifdef WOLFSSL_DTLS
+ if (ssl->ctx->method->version.major == DTLS_MAJOR)
+ ssl->options.haveEMS = 1;
+ #endif /* WOLFSSL_DTLS */
+ }
+#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+ if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
+ int ret;
+ ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
+ if (ret != 0) {
+ WOLFSSL_MSG("DTLS Cookie Secret error");
+ return ret;
+ }
+ }
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+ return InitSSL_Suites(ssl);
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+/* Initialize SSL context, return 0 on success */
+int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
{
+ int ret = 0;
+
XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
ctx->method = method;
ctx->refCount = 1; /* so either CTX_free or SSL_free can release */
ctx->heap = ctx; /* defaults to self */
ctx->timeout = WOLFSSL_SESSION_TIMEOUT;
- ctx->minDowngrade = TLSv1_MINOR; /* current default */
+ ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */
- if (InitMutex(&ctx->countMutex) < 0) {
+ if (wc_InitMutex(&ctx->countMutex) < 0) {
WOLFSSL_MSG("Mutex error on CTX init");
+ ctx->err = CTX_INIT_MUTEX_E;
return BAD_MUTEX_E;
}
#ifndef NO_DH
- ctx->minDhKeySz = MIN_DHKEY_SZ;
+ ctx->minDhKeySz = MIN_DHKEY_SZ;
+ ctx->maxDhKeySz = MAX_DHKEY_SZ;
+#endif
+#ifndef NO_RSA
+ ctx->minRsaKeySz = MIN_RSAKEY_SZ;
#endif
-
#ifdef HAVE_ECC
+ ctx->minEccKeySz = MIN_ECCKEY_SZ;
ctx->eccTempKeySz = ECDHE_SIZE;
#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ctx->verifyDepth = MAX_CHAIN_DEPTH;
+#endif
+#ifdef OPENSSL_EXTRA
+ ctx->cbioFlag = WOLFSSL_CBIO_NONE;
+#endif
#ifndef WOLFSSL_USER_IO
- ctx->CBIORecv = EmbedReceive;
- ctx->CBIOSend = EmbedSend;
- #ifdef WOLFSSL_DTLS
+ #ifdef MICRIUM
+ ctx->CBIORecv = MicriumReceive;
+ ctx->CBIOSend = MicriumSend;
+ #ifdef WOLFSSL_DTLS
+ if (method->version.major == DTLS_MAJOR) {
+ ctx->CBIORecv = MicriumReceiveFrom;
+ ctx->CBIOSend = MicriumSendTo;
+ }
+ #ifdef WOLFSSL_SESSION_EXPORT
+ #error Micrium port does not support DTLS session export yet
+ #endif
+ #endif
+ #elif defined WOLFSSL_UIP
+ ctx->CBIORecv = uIPReceive;
+ ctx->CBIOSend = uIPSend;
+ #ifdef WOLFSSL_DTLS
if (method->version.major == DTLS_MAJOR) {
- ctx->CBIORecv = EmbedReceiveFrom;
- ctx->CBIOSend = EmbedSendTo;
- ctx->CBIOCookie = EmbedGenerateCookie;
+ ctx->CBIOSendTo = uIPSendTo;
+ ctx->CBIORecvFrom = uIPRecvFrom;
}
- #endif
+ #endif
+ #else
+ ctx->CBIORecv = EmbedReceive;
+ ctx->CBIOSend = EmbedSend;
+ #ifdef WOLFSSL_DTLS
+ if (method->version.major == DTLS_MAJOR) {
+ ctx->CBIORecv = EmbedReceiveFrom;
+ ctx->CBIOSend = EmbedSendTo;
+ }
+ #ifdef WOLFSSL_SESSION_EXPORT
+ ctx->CBGetPeer = EmbedGetPeer;
+ ctx->CBSetPeer = EmbedSetPeer;
+ #endif
+ #endif
+ #endif /* MICRIUM */
#endif /* WOLFSSL_USER_IO */
#ifdef HAVE_NETX
ctx->CBIORecv = NetX_Receive;
ctx->CBIOSend = NetX_Send;
+#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+ ctx->CBIORecv = Mynewt_Receive;
+ ctx->CBIOSend = Mynewt_Send;
+#elif defined(WOLFSSL_GNRC)
+ ctx->CBIORecv = GNRC_ReceiveFrom;
+ ctx->CBIOSend = GNRC_SendTo;
#endif
#ifdef HAVE_NTRU
if (method->side == WOLFSSL_CLIENT_END)
- ctx->haveNTRU = 1; /* always on cliet side */
+ ctx->haveNTRU = 1; /* always on client side */
/* server can turn on by loading key */
#endif
#ifdef HAVE_ECC
if (method->side == WOLFSSL_CLIENT_END) {
- ctx->haveECDSAsig = 1; /* always on cliet side */
+ ctx->haveECDSAsig = 1; /* always on client side */
+ ctx->haveECC = 1; /* server turns on with ECC key cert */
ctx->haveStaticECC = 1; /* server can turn on by loading key */
}
+#elif defined(HAVE_ED25519) || defined(HAVE_ED448)
+ if (method->side == WOLFSSL_CLIENT_END) {
+ ctx->haveECDSAsig = 1; /* always on client side */
+ ctx->haveECC = 1; /* server turns on with ECC key cert */
+ }
#endif
-#ifdef HAVE_CAVIUM
- ctx->devId = NO_CAVIUM_DEVICE;
+ ctx->devId = INVALID_DEVID;
+
+#if defined(WOLFSSL_DTLS)
+ #ifdef WOLFSSL_SCTP
+ ctx->dtlsMtuSz = MAX_RECORD_SIZE;
+ #elif defined(WOLFSSL_DTLS_MTU)
+ ctx->dtlsMtuSz = MAX_MTU;
+ #endif
#endif
#ifndef NO_CERTS
- ctx->cm = wolfSSL_CertManagerNew();
+ ctx->cm = wolfSSL_CertManagerNew_ex(heap);
if (ctx->cm == NULL) {
WOLFSSL_MSG("Bad Cert Manager New");
return BAD_CERT_MANAGER_ERROR;
}
+ #ifdef OPENSSL_EXTRA
+ /* setup WOLFSSL_X509_STORE */
+ ctx->x509_store.cm = ctx->cm;
+ #endif
#endif
+#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
+ if (method->side == WOLFSSL_CLIENT_END) {
+ if ((method->version.major == SSLv3_MAJOR) &&
+ (method->version.minor >= TLSv1_MINOR)) {
+
+ ctx->haveEMS = 1;
+ }
+#ifdef WOLFSSL_DTLS
+ if (method->version.major == DTLS_MAJOR)
+ ctx->haveEMS = 1;
+#endif /* WOLFSSL_DTLS */
+ }
+#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
+
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
#endif
- return 0;
+#ifdef HAVE_WOLF_EVENT
+ ret = wolfEventQueue_Init(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+#ifdef WOLFSSL_EARLY_DATA
+ ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ;
+#endif
+
+ ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */
+ ctx->verifyDepth = MAX_CHAIN_DEPTH;
+
+ return ret;
}
/* In case contexts are held in array and don't want to free actual ctx */
void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
{
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && \
+ defined(HAVE_TLS_EXTENSIONS) && !defined(NO_WOLFSSL_SERVER)
+ int i;
+#endif
+
+#ifdef HAVE_WOLF_EVENT
+ wolfEventQueue_Free(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+ if (ctx->onHeap == 1) {
+ XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+ }
+ else {
+ XFREE(ctx->method, NULL, DYNAMIC_TYPE_METHOD);
+ }
+#else
XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
- if (ctx->suites)
+#endif
+ ctx->method = NULL;
+ if (ctx->suites) {
XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
+ ctx->suites = NULL;
+ }
#ifndef NO_DH
- XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
-#endif
+ XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ctx->serverDH_G.buffer = NULL;
+ XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ctx->serverDH_P.buffer = NULL;
+#endif /* !NO_DH */
+
+#ifdef SINGLE_THREADED
+ if (ctx->rng) {
+ wc_FreeRng(ctx->rng);
+ XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG);
+ ctx->rng = NULL;
+ }
+#endif /* SINGLE_THREADED */
+
#ifndef NO_CERTS
- XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
- XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
- XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
+ FreeDer(&ctx->privateKey);
+ FreeDer(&ctx->certificate);
+ #ifdef KEEP_OUR_CERT
+ if (ctx->ourCert && ctx->ownOurCert) {
+ FreeX509(ctx->ourCert);
+ XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+ ctx->ourCert = NULL;
+ }
+ #endif /* KEEP_OUR_CERT */
+ FreeDer(&ctx->certChain);
wolfSSL_CertManagerFree(ctx->cm);
-#endif
+ ctx->cm = NULL;
+ #ifdef OPENSSL_EXTRA
+ /* ctx->cm was free'd so cm of x509 store should now be NULL */
+ if (ctx->x509_store_pt != NULL) {
+ ctx->x509_store_pt->cm = NULL;
+ }
+ wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+ while (ctx->ca_names != NULL) {
+ WOLFSSL_STACK *next = ctx->ca_names->next;
+ wolfSSL_X509_NAME_free(ctx->ca_names->data.name);
+ XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL);
+ ctx->ca_names = next;
+ }
+ #endif
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ while (ctx->x509Chain != NULL) {
+ WOLFSSL_STACK *next = ctx->x509Chain->next;
+ wolfSSL_X509_free(ctx->x509Chain->data.x509);
+ XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL);
+ ctx->x509Chain = next;
+ }
+ #endif
+#endif /* !NO_CERTS */
+
#ifdef HAVE_TLS_EXTENSIONS
- TLSX_FreeAll(ctx->extensions);
+ TLSX_FreeAll(ctx->extensions, ctx->heap);
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ctx->certOcspRequest) {
+ FreeOcspRequest(ctx->certOcspRequest);
+ XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ }
#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
+ if (ctx->chainOcspRequest[i]) {
+ FreeOcspRequest(ctx->chainOcspRequest[i]);
+ XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ ctx->chainOcspRequest[i] = NULL;
+ }
+ }
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+#endif /* !NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef OPENSSL_EXTRA
+ if(ctx->alpn_cli_protos) {
+ XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL);
+ ctx->alpn_cli_protos = NULL;
+ }
+#endif
+#ifdef WOLFSSL_STATIC_MEMORY
+ if (ctx->heap != NULL) {
+#ifdef WOLFSSL_HEAP_TEST
+ /* avoid dereferencing a test value */
+ if (ctx->heap != (void*)WOLFSSL_HEAP_TEST)
+#endif
+ {
+ WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap);
+ wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex);
+ }
+ }
+#endif /* WOLFSSL_STATIC_MEMORY */
}
void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
{
- int doFree = 0;
-
- if (LockMutex(&ctx->countMutex) != 0) {
- WOLFSSL_MSG("Couldn't lock count mutex");
+ int refCount;
+
+ /* decrement CTX reference count */
+ if ((refCount = SSL_CTX_RefCount(ctx, -1)) < 0) {
+ /* check error state, if mutex error code then mutex init failed but
+ * CTX was still malloc'd */
+ if (ctx->err == CTX_INIT_MUTEX_E) {
+ SSL_CtxResourceFree(ctx);
+ XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+ }
return;
}
- ctx->refCount--;
- if (ctx->refCount == 0)
- doFree = 1;
- UnLockMutex(&ctx->countMutex);
- if (doFree) {
+ if (refCount == 0) {
+ void* heap = ctx->heap;
WOLFSSL_MSG("CTX ref count down to 0, doing full free");
SSL_CtxResourceFree(ctx);
- FreeMutex(&ctx->countMutex);
- XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+ wc_FreeMutex(&ctx->countMutex);
+#ifdef WOLFSSL_STATIC_MEMORY
+ if (ctx->onHeap == 0) {
+ heap = NULL;
+ }
+#endif
+ XFREE(ctx, heap, DYNAMIC_TYPE_CTX);
+ (void)heap; /* not used in some builds */
}
else {
(void)ctx;
@@ -509,7 +1989,7 @@ void InitCiphers(WOLFSSL* ssl)
ssl->encrypt.chacha = NULL;
ssl->decrypt.chacha = NULL;
#endif
-#ifdef HAVE_POLY1305
+#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
ssl->auth.poly1305 = NULL;
#endif
ssl->encrypt.setup = 0;
@@ -517,6 +1997,10 @@ void InitCiphers(WOLFSSL* ssl)
#ifdef HAVE_ONE_TIME_AUTH
ssl->auth.setup = 0;
#endif
+#ifdef HAVE_IDEA
+ ssl->encrypt.idea = NULL;
+ ssl->decrypt.idea = NULL;
+#endif
}
@@ -525,35 +2009,34 @@ void FreeCiphers(WOLFSSL* ssl)
{
(void)ssl;
#ifdef BUILD_ARC4
- #ifdef HAVE_CAVIUM
- if (ssl->devId != NO_CAVIUM_DEVICE) {
- wc_Arc4FreeCavium(ssl->encrypt.arc4);
- wc_Arc4FreeCavium(ssl->decrypt.arc4);
- }
- #endif
+ wc_Arc4Free(ssl->encrypt.arc4);
+ wc_Arc4Free(ssl->decrypt.arc4);
XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_DES3
- #ifdef HAVE_CAVIUM
- if (ssl->devId != NO_CAVIUM_DEVICE) {
- wc_Des3_FreeCavium(ssl->encrypt.des3);
- wc_Des3_FreeCavium(ssl->decrypt.des3);
- }
- #endif
+ wc_Des3Free(ssl->encrypt.des3);
+ wc_Des3Free(ssl->decrypt.des3);
XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
-#ifdef BUILD_AES
- #ifdef HAVE_CAVIUM
- if (ssl->devId != NO_CAVIUM_DEVICE) {
- wc_AesFreeCavium(ssl->encrypt.aes);
- wc_AesFreeCavium(ssl->decrypt.aes);
- }
+#if defined(BUILD_AES) || defined(BUILD_AESGCM) /* 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);
+ #if (defined(BUILD_AESGCM) || defined(HAVE_AESCCM)) && \
+ !defined(WOLFSSL_NO_TLS12)
+ XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
#endif
XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
+#ifdef CIPHER_NONCE
+ XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+#endif
#ifdef HAVE_CAMELLIA
XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
@@ -570,95 +2053,212 @@ void FreeCiphers(WOLFSSL* ssl)
XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
-#ifdef HAVE_POLY1305
+#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
+#ifdef HAVE_IDEA
+ XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+ wc_HmacFree(ssl->encrypt.hmac);
+ wc_HmacFree(ssl->decrypt.hmac);
+ XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
}
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(USE_ECDSA_KEYSZ_HASH_ALGO) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_ECC))
+static int GetMacDigestSize(byte macAlgo)
+{
+ switch (macAlgo) {
+ #ifndef NO_SHA
+ case sha_mac:
+ return WC_SHA_DIGEST_SIZE;
+ #endif
+ #ifndef NO_SHA256
+ case sha256_mac:
+ return WC_SHA256_DIGEST_SIZE;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ return WC_SHA384_DIGEST_SIZE;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ return WC_SHA512_DIGEST_SIZE;
+ #endif
+ default:
+ break;
+ }
+ return NOT_COMPILED_IN;
+}
+#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */
- cs->hash_size = 0;
- cs->static_ecdh = 0;
- cs->key_size = 0;
- cs->iv_size = 0;
- cs->block_size = 0;
+static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, byte sigAlgo,
+ int keySz, word16* inOutIdx)
+{
+ int addSigAlgo = 1;
+
+#ifdef USE_ECDSA_KEYSZ_HASH_ALGO
+ if (sigAlgo == ecc_dsa_sa_algo) {
+ int digestSz = GetMacDigestSize(macAlgo);
+ /* do not add sig/algos with digest size larger than key size */
+ if (digestSz <= 0 || (keySz > 0 && digestSz > keySz)) {
+ addSigAlgo = 0;
+ }
+ }
+#else
+ (void)keySz;
+#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */
+
+ if (addSigAlgo) {
+#ifdef WC_RSA_PSS
+ if (sigAlgo == rsa_pss_sa_algo) {
+ /* RSA PSS is sig then mac */
+ suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+ *inOutIdx += 1;
+ suites->hashSigAlgo[*inOutIdx] = macAlgo;
+ *inOutIdx += 1;
+ #ifdef WOLFSSL_TLS13
+ /* Add the certificate algorithm as well */
+ suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+ *inOutIdx += 1;
+ suites->hashSigAlgo[*inOutIdx] = PSS_RSAE_TO_PSS_PSS(macAlgo);
+ *inOutIdx += 1;
+ #endif
+ }
+ else
+#endif
+ {
+ suites->hashSigAlgo[*inOutIdx] = macAlgo;
+ *inOutIdx += 1;
+ suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+ *inOutIdx += 1;
+ }
+ }
}
-static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
- int haveRSAsig, int haveAnon)
+void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig,
+ int haveAnon, int tls1_2, int keySz)
{
- int idx = 0;
+ word16 idx = 0;
+ (void)tls1_2;
+ (void)keySz;
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
if (haveECDSAsig) {
- #ifdef WOLFSSL_SHA512
- suites->hashSigAlgo[idx++] = sha512_mac;
- suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
- #endif
- #ifdef WOLFSSL_SHA384
- suites->hashSigAlgo[idx++] = sha384_mac;
- suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
- #endif
- #ifndef NO_SHA256
- suites->hashSigAlgo[idx++] = sha256_mac;
- suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
- #endif
- #ifndef NO_SHA
- suites->hashSigAlgo[idx++] = sha_mac;
- suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
- #endif
+#ifdef HAVE_ECC
+ #ifdef WOLFSSL_SHA512
+ AddSuiteHashSigAlgo(suites, sha512_mac, ecc_dsa_sa_algo, keySz, &idx);
+ #endif
+ #ifdef WOLFSSL_SHA384
+ AddSuiteHashSigAlgo(suites, sha384_mac, ecc_dsa_sa_algo, keySz, &idx);
+ #endif
+ #ifndef NO_SHA256
+ AddSuiteHashSigAlgo(suites, sha256_mac, ecc_dsa_sa_algo, keySz, &idx);
+ #endif
+ #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_TLS_SHA1))
+ AddSuiteHashSigAlgo(suites, sha_mac, ecc_dsa_sa_algo, keySz, &idx);
+ #endif
+#endif
+ #ifdef HAVE_ED25519
+ AddSuiteHashSigAlgo(suites, ED25519_SA_MAJOR, ED25519_SA_MINOR, keySz,
+ &idx);
+ #endif
+ #ifdef HAVE_ED448
+ AddSuiteHashSigAlgo(suites, ED448_SA_MAJOR, ED448_SA_MINOR, keySz,
+ &idx);
+ #endif
}
+#endif /* HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448 */
if (haveRSAsig) {
+ #ifdef WC_RSA_PSS
+ if (tls1_2) {
#ifdef WOLFSSL_SHA512
- suites->hashSigAlgo[idx++] = sha512_mac;
- suites->hashSigAlgo[idx++] = rsa_sa_algo;
+ AddSuiteHashSigAlgo(suites, sha512_mac, rsa_pss_sa_algo, keySz,
+ &idx);
#endif
#ifdef WOLFSSL_SHA384
- suites->hashSigAlgo[idx++] = sha384_mac;
- suites->hashSigAlgo[idx++] = rsa_sa_algo;
+ AddSuiteHashSigAlgo(suites, sha384_mac, rsa_pss_sa_algo, keySz,
+ &idx);
#endif
#ifndef NO_SHA256
- suites->hashSigAlgo[idx++] = sha256_mac;
- suites->hashSigAlgo[idx++] = rsa_sa_algo;
- #endif
- #ifndef NO_SHA
- suites->hashSigAlgo[idx++] = sha_mac;
- suites->hashSigAlgo[idx++] = rsa_sa_algo;
+ AddSuiteHashSigAlgo(suites, sha256_mac, rsa_pss_sa_algo, keySz,
+ &idx);
#endif
+ }
+ #endif
+ #ifdef WOLFSSL_SHA512
+ AddSuiteHashSigAlgo(suites, sha512_mac, rsa_sa_algo, keySz, &idx);
+ #endif
+ #ifdef WOLFSSL_SHA384
+ AddSuiteHashSigAlgo(suites, sha384_mac, rsa_sa_algo, keySz, &idx);
+ #endif
+ #ifndef NO_SHA256
+ AddSuiteHashSigAlgo(suites, sha256_mac, rsa_sa_algo, keySz, &idx);
+ #endif
+ #ifdef WOLFSSL_SHA224
+ AddSuiteHashSigAlgo(suites, sha224_mac, rsa_sa_algo, keySz, &idx);
+ #endif
+ #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_TLS_SHA1))
+ AddSuiteHashSigAlgo(suites, sha_mac, rsa_sa_algo, keySz, &idx);
+ #endif
}
+#ifdef HAVE_ANON
if (haveAnon) {
- #ifdef HAVE_ANON
- suites->hashSigAlgo[idx++] = sha_mac;
- suites->hashSigAlgo[idx++] = anonymous_sa_algo;
- #endif
+ AddSuiteHashSigAlgo(suites, sha_mac, anonymous_sa_algo, keySz, &idx);
}
+#endif
- suites->hashSigAlgoSz = (word16)idx;
+ (void)haveAnon;
+ (void)haveECDSAsig;
+ suites->hashSigAlgoSz = idx;
}
-void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
+void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
word16 havePSK, word16 haveDH, word16 haveNTRU,
- word16 haveECDSAsig, word16 haveStaticECC, int side)
+ word16 haveECDSAsig, word16 haveECC,
+ word16 haveStaticECC, int side)
{
word16 idx = 0;
int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
+#ifdef WOLFSSL_TLS13
+ int tls1_3 = IsAtLeastTLSv1_3(pv);
+#endif
+ int dtls = 0;
int haveRSAsig = 1;
(void)tls; /* shut up compiler */
(void)tls1_2;
+ (void)dtls;
(void)haveDH;
(void)havePSK;
(void)haveNTRU;
(void)haveStaticECC;
+ (void)haveECC;
+ (void)side;
+ (void)haveRSA; /* some builds won't read */
+ (void)haveRSAsig; /* non ecc builds won't read */
if (suites == NULL) {
WOLFSSL_MSG("InitSuites pointer error");
@@ -668,67 +2268,133 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
if (suites->setSuites)
return; /* trust user settings, don't override */
+#ifdef WOLFSSL_TLS13
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+ if (tls1_3) {
+ suites->suites[idx++] = TLS13_BYTE;
+ suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+ if (tls1_3) {
+ suites->suites[idx++] = TLS13_BYTE;
+ suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
+ }
+#endif
+
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+ if (tls1_3) {
+ suites->suites[idx++] = TLS13_BYTE;
+ suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+ if (tls1_3) {
+ suites->suites[idx++] = TLS13_BYTE;
+ suites->suites[idx++] = TLS_AES_128_CCM_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+ if (tls1_3) {
+ suites->suites[idx++] = TLS13_BYTE;
+ suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256;
+ }
+#endif
+
+#ifdef HAVE_NULL_CIPHER
+ #ifdef BUILD_TLS_SHA256_SHA256
+ if (tls1_3) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_SHA256_SHA256;
+ }
+ #endif
+
+ #ifdef BUILD_TLS_SHA384_SHA384
+ if (tls1_3) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_SHA384_SHA384;
+ }
+ #endif
+#endif
+#endif /* WOLFSSL_TLS13 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_RSA)
if (side == WOLFSSL_SERVER_END && haveStaticECC) {
haveRSA = 0; /* can't do RSA with ECDSA key */
- (void)haveRSA; /* some builds won't read */
}
if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */
- (void)haveRSAsig; /* non ecc builds won't read */
}
+#endif /* !NO_WOLFSSL_SERVER */
#ifdef WOLFSSL_DTLS
if (pv.major == DTLS_MAJOR) {
+ dtls = 1;
tls = 1;
+ /* May be dead assignments dependent upon configuration */
+ (void) dtls;
+ (void) tls;
tls1_2 = pv.minor <= DTLSv1_2_MINOR;
}
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION
if (side == WOLFSSL_CLIENT_END) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
}
#endif
+#ifdef BUILD_TLS_QSH
+ if (tls) {
+ suites->suites[idx++] = QSH_BYTE;
+ suites->suites[idx++] = TLS_QSH;
+ }
+#endif
+
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
+ if (tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
- }
+ }
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
+ if (!dtls && tls && haveNTRU && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
@@ -750,41 +2416,41 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- if (tls1_2 && haveECDSAsig && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveECDSAsig && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
}
@@ -806,62 +2472,86 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
}
#endif
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+ if (tls1_2 && haveDH) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+ if (tls1_2 && haveDH) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+ }
+#endif
+
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
if (tls1_2 && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
if (tls1_2 && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- if (tls && haveRSA) {
+ if (tls1_2 && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- if (tls && haveRSA) {
+ if (tls1_2 && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
+/* Place as higher priority for MYSQL */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE)
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveDH && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+#endif
+
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveRSAsig) {
+ if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
}
@@ -875,21 +2565,21 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveECDSAsig && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- if (tls1_2 && haveRSAsig) {
+ if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
}
@@ -903,63 +2593,63 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- if (tls1_2 && haveECDSAsig && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- if (tls && haveECDSAsig) {
+ if (tls && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- if (tls && haveECDSAsig && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- if (tls && haveECDSAsig) {
+ if (tls && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- if (tls && haveECDSAsig && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- if (tls && haveECDSAsig) {
+ if (!dtls && tls && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- if (tls && haveECDSAsig && haveStaticECC) {
+ if (!dtls && tls && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveECDSAsig) {
+ if (tls && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveECDSAsig && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
@@ -994,14 +2684,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- if (tls && haveRSA) {
+ if (!dtls && tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
- if (tls && haveRSAsig && haveStaticECC) {
+ if (!dtls && tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
}
@@ -1021,15 +2711,22 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
}
#endif
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+ if (tls1_2 && haveECC) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
+ }
+#endif
+
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
- if (tls1_2 && haveECDSAsig) {
+ if (tls1_2 && haveECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
}
@@ -1050,113 +2747,204 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && haveRSA)
+#else
+ if (tls && haveDH && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && haveRSA)
+#else
+ if (tls && haveDH && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
+/* Place as higher priority for MYSQL testing */
+#if !defined(WOLFSSL_MYSQL_COMPATIBLE)
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
+#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ if (tls && haveDH && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveRSA)
+#else
+ if (tls && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveRSA)
+#else
+ if (tls && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
}
#endif
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ if (tls1_2 && haveECC) {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] =
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ if (tls1_2 && haveRSA) {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ if (tls1_2 && haveRSA) {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ if (tls && haveECC) {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_MD5
+ if (tls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = TLS_RSA_WITH_NULL_MD5;
+ }
+#endif
+
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveRSA)
+#else
+ if (tls && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
if (tls && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
- if (tls && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && havePSK)
+#else
+ if (tls && haveDH && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
- if (tls && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && havePSK)
+#else
+ if (tls && haveDH && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls1 && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
if (tls && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
}
#endif
@@ -1175,6 +2963,54 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
}
#endif
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CHACHA_BYTE;
+ suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+ }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+ }
+#endif
+
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
if (tls && havePSK) {
suites->suites[idx++] = ECC_BYTE;
@@ -1204,167 +3040,298 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
- if (tls && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && havePSK)
+#else
+ if (tls && haveDH && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
}
#endif
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = ECC_BYTE;
+ suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256;
+ }
+#endif
+
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
- if (tls && haveDH && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && havePSK)
+#else
+ if (tls && haveDH && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && havePSK)
+#else
+ if (tls && havePSK)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
if (tls && havePSK) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- if (haveRSA ) {
- suites->suites[idx++] = 0;
+ if (!dtls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- if (haveRSA ) {
- suites->suites[idx++] = 0;
+ if (!dtls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
if (haveRSA ) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ if (!dtls && tls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ if (!dtls && tls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
}
#endif
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
- }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256;
- }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
- }
-#endif
-
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ if (!dtls && tls && haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
-#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveRSA)
+#else
+ if (tls && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && haveRSA)
+#else
+ if (tls && haveDH && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveRSA)
+#else
+ if (tls && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+ if (tls1_2 && haveDH && haveRSA)
+#else
+ if (tls && haveDH && haveRSA)
+#endif
+ {
+ suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
#endif
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+ if (haveRSA) {
+ suites->suites[idx++] = CIPHER_BYTE;
+ suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
+ }
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
suites->suiteSz = idx;
- InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0);
+ InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, haveRSAsig | haveRSA,
+ 0, tls1_2, keySz);
}
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \
+ (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC)))
-#ifndef NO_CERTS
+/* Decode the signature algorithm.
+ *
+ * input The encoded signature algorithm.
+ * hashalgo The hash algorithm.
+ * hsType The signature type.
+ */
+static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
+{
+ switch (input[0]) {
+ case NEW_SA_MAJOR:
+ #ifdef HAVE_ED25519
+ /* ED25519: 0x0807 */
+ if (input[1] == ED25519_SA_MINOR) {
+ *hsType = ed25519_sa_algo;
+ /* Hash performed as part of sign/verify operation. */
+ *hashAlgo = sha512_mac;
+ }
+ else
+ #endif
+ #ifdef HAVE_ED448
+ /* ED448: 0x0808 */
+ if (input[1] == ED448_SA_MINOR) {
+ *hsType = ed448_sa_algo;
+ /* Hash performed as part of sign/verify operation. */
+ *hashAlgo = sha512_mac;
+ }
+ else
+ #endif
+ #ifdef WC_RSA_PSS
+ /* PSS PSS signatures: 0x080[9-b] */
+ if (input[1] >= pss_sha256 && input[1] <= pss_sha512) {
+ *hsType = rsa_pss_pss_algo;
+ *hashAlgo = PSS_PSS_HASH_TO_MAC(input[1]);
+ }
+ else
+ #endif
+ {
+ *hsType = input[0];
+ *hashAlgo = input[1];
+ }
+ break;
+ default:
+ *hashAlgo = input[0];
+ *hsType = input[1];
+ break;
+ }
+}
+#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448) || (!defined(NO_RSA) && defined(WC_RSA_PSS))
+static enum wc_HashType HashAlgoToType(int hashAlgo)
+{
+ switch (hashAlgo) {
+ #ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ return WC_HASH_TYPE_SHA512;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ return WC_HASH_TYPE_SHA384;
+ #endif
+ #ifndef NO_SHA256
+ case sha256_mac:
+ return WC_HASH_TYPE_SHA256;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case sha224_mac:
+ return WC_HASH_TYPE_SHA224;
+ #endif
+ #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_TLS_SHA1))
+ case sha_mac:
+ return WC_HASH_TYPE_SHA;
+ #endif
+ default:
+ WOLFSSL_MSG("Bad hash sig algo");
+ break;
+ }
+
+ return WC_HASH_TYPE_NONE;
+}
+#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_CERTS
void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
{
@@ -1373,65 +3340,65 @@ void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
if (name != NULL) {
name->name = name->staticName;
name->dynamicName = 0;
-#ifdef OPENSSL_EXTRA
+ name->sz = 0;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
XMEMSET(&name->fullName, 0, sizeof(DecodedName));
+ XMEMSET(&name->cnEntry, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+ XMEMSET(&name->extra, 0, sizeof(name->extra));
+ name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/
+ name->cnEntry.nid = ASN_COMMON_NAME;
+ name->x509 = NULL;
#endif /* OPENSSL_EXTRA */
}
}
-void FreeX509Name(WOLFSSL_X509_NAME* name)
+void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap)
{
if (name != NULL) {
- if (name->dynamicName)
- XFREE(name->name, NULL, DYNAMIC_TYPE_SUBJECT_CN);
-#ifdef OPENSSL_EXTRA
- if (name->fullName.fullName != NULL)
- XFREE(name->fullName.fullName, NULL, DYNAMIC_TYPE_X509);
-#endif /* OPENSSL_EXTRA */
+ if (name->dynamicName) {
+ XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+ name->name = NULL;
+ }
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ {
+ int i;
+ if (name->fullName.fullName != NULL) {
+ XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509);
+ name->fullName.fullName = NULL;
+ }
+ for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+ /* free ASN1 string data */
+ if (name->extra[i].set && name->extra[i].data.data != NULL) {
+ XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL);
+ }
+ }
+ wolfSSL_ASN1_OBJECT_free(&name->cnEntry.object);
+ }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
}
+ (void)heap;
}
/* Initialize wolfSSL X509 type */
-void InitX509(WOLFSSL_X509* x509, int dynamicFlag)
+void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
{
+ if (x509 == NULL) {
+ WOLFSSL_MSG("Null parameter passed in!");
+ return;
+ }
+
+ XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
+
+ x509->heap = heap;
InitX509Name(&x509->issuer, 0);
InitX509Name(&x509->subject, 0);
- x509->version = 0;
- x509->pubKey.buffer = NULL;
- x509->sig.buffer = NULL;
- x509->derCert.buffer = NULL;
- x509->altNames = NULL;
- x509->altNamesNext = NULL;
x509->dynamicMemory = (byte)dynamicFlag;
- x509->isCa = 0;
-#ifdef HAVE_ECC
- x509->pkCurveOID = 0;
-#endif /* HAVE_ECC */
-#ifdef OPENSSL_EXTRA
- x509->pathLength = 0;
- x509->basicConstSet = 0;
- x509->basicConstCrit = 0;
- x509->basicConstPlSet = 0;
- x509->subjAltNameSet = 0;
- x509->subjAltNameCrit = 0;
- x509->authKeyIdSet = 0;
- x509->authKeyIdCrit = 0;
- x509->authKeyId = NULL;
- x509->authKeyIdSz = 0;
- x509->subjKeyIdSet = 0;
- x509->subjKeyIdCrit = 0;
- x509->subjKeyId = NULL;
- x509->subjKeyIdSz = 0;
- x509->keyUsageSet = 0;
- x509->keyUsageCrit = 0;
- x509->keyUsage = 0;
- #ifdef WOLFSSL_SEP
- x509->certPolicySet = 0;
- x509->certPolicyCrit = 0;
- #endif /* WOLFSSL_SEP */
-#endif /* OPENSSL_EXTRA */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ x509->refCount = 1;
+ (void)wc_InitMutex(&x509->refMutex);
+ #endif
}
@@ -1441,287 +3408,2506 @@ void FreeX509(WOLFSSL_X509* x509)
if (x509 == NULL)
return;
- FreeX509Name(&x509->issuer);
- FreeX509Name(&x509->subject);
- if (x509->pubKey.buffer)
- XFREE(x509->pubKey.buffer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(x509->derCert.buffer, NULL, DYNAMIC_TYPE_SUBJECT_CN);
- XFREE(x509->sig.buffer, NULL, DYNAMIC_TYPE_SIGNATURE);
+ FreeX509Name(&x509->issuer, x509->heap);
+ FreeX509Name(&x509->subject, x509->heap);
+ if (x509->pubKey.buffer) {
+ XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ x509->pubKey.buffer = NULL;
+ }
+ FreeDer(&x509->derCert);
+ XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+ x509->sig.buffer = NULL;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->authKeyId = NULL;
+ XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->subjKeyId = NULL;
+ if (x509->authInfo != NULL) {
+ XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->authInfo = NULL;
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ if (x509->authInfoCaIssuer != NULL) {
+ XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ }
+ if (x509->ext_sk != NULL) {
+ wolfSSL_sk_X509_EXTENSION_free(x509->ext_sk);
+ }
+ #endif /* OPENSSL_ALL || WOLFSSL_QT */
+ #ifdef OPENSSL_EXTRA
+ /* Free serialNumber that was set by wolfSSL_X509_get_serialNumber */
+ if (x509->serialNumber != NULL) {
+ wolfSSL_ASN1_INTEGER_free(x509->serialNumber);
+ }
+ #endif
+ if (x509->extKeyUsageSrc != NULL) {
+ XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->extKeyUsageSrc= NULL;
+ }
+ #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+ #if defined(OPENSSL_ALL)
+ if (x509->algor.algorithm) {
+ wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm);
+ x509->algor.algorithm = NULL;
+ }
+ if (x509->key.algor) {
+ wolfSSL_X509_ALGOR_free(x509->key.algor);
+ x509->key.algor = NULL;
+ }
+ if (x509->key.pkey) {
+ wolfSSL_EVP_PKEY_free(x509->key.pkey);
+ x509->key.pkey = NULL;
+ }
+ #endif /* OPENSSL_ALL */
+ if (x509->altNames) {
+ FreeAltNames(x509->altNames, x509->heap);
+ x509->altNames = NULL;
+ }
+
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ wc_FreeMutex(&x509->refMutex);
+ #endif
+}
+
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(WOLFSSL_NO_TLS12)
+/* Encode the signature algorithm into buffer.
+ *
+ * hashalgo The hash algorithm.
+ * hsType The signature type.
+ * output The buffer to encode into.
+ */
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+{
+ switch (hsType) {
+#ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ output[0] = hashAlgo;
+ output[1] = ecc_dsa_sa_algo;
+ break;
+#endif
+#ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ output[0] = ED25519_SA_MAJOR;
+ output[1] = ED25519_SA_MINOR;
+ (void)hashAlgo;
+ break;
+#endif
+#ifdef HAVE_ED448
+ case ed448_sa_algo:
+ output[0] = ED448_SA_MAJOR;
+ output[1] = ED448_SA_MINOR;
+ (void)hashAlgo;
+ break;
+#endif
+#ifndef NO_RSA
+ case rsa_sa_algo:
+ output[0] = hashAlgo;
+ output[1] = rsa_sa_algo;
+ break;
+ #ifdef WC_RSA_PSS
+ /* PSS signatures: 0x080[4-6] */
+ case rsa_pss_sa_algo:
+ output[0] = rsa_pss_sa_algo;
+ output[1] = hashAlgo;
+ break;
+ #endif
+#endif
+ }
+ (void)hashAlgo;
+ (void)output;
+}
+#endif
+
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+static void SetDigest(WOLFSSL* ssl, int hashAlgo)
+{
+ switch (hashAlgo) {
+ #ifndef NO_SHA
+ case sha_mac:
+ ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha;
+ ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE;
+ break;
+ #endif /* !NO_SHA */
+ #ifndef NO_SHA256
+ case sha256_mac:
+ ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256;
+ ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE;
+ break;
+ #endif /* !NO_SHA256 */
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384;
+ ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE;
+ break;
+ #endif /* WOLFSSL_SHA384 */
+ #ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512;
+ ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE;
+ break;
+ #endif /* WOLFSSL_SHA512 */
+ } /* switch */
+}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !NO_CERTS */
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+static word32 MacSize(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 */
+
+#ifndef NO_RSA
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || (!defined(NO_WOLFSSL_CLIENT) && \
+ !defined(WOLFSSL_NO_CLIENT_AUTH))
+static int TypeHash(int hashAlgo)
+{
+ switch (hashAlgo) {
+ #ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ return SHA512h;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ return SHA384h;
+ #endif
+ #ifndef NO_SHA256
+ case sha256_mac:
+ return SHA256h;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case sha224_mac:
+ return SHA224h;
+ #endif
+ #ifndef NO_SHA
+ case sha_mac:
+ return SHAh;
+ #endif
+ }
+
+ return 0;
+}
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(WC_RSA_PSS)
+int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
+{
+ switch (hashAlgo) {
+ #ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ *hashType = WC_HASH_TYPE_SHA512;
+ if (mgf != NULL)
+ *mgf = WC_MGF1SHA512;
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ *hashType = WC_HASH_TYPE_SHA384;
+ if (mgf != NULL)
+ *mgf = WC_MGF1SHA384;
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case sha256_mac:
+ *hashType = WC_HASH_TYPE_SHA256;
+ if (mgf != NULL)
+ *mgf = WC_MGF1SHA256;
+ break;
+ #endif
+ default:
+ return BAD_FUNC_ARG;
+ }
+
+ return 0;
+}
+#endif
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+ word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
+ DerBuffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+ (void)sigAlgo;
+ (void)hashAlgo;
+
+ WOLFSSL_ENTER("RsaSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ if (key) {
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+ }
+#endif
+
+#if defined(WC_RSA_PSS)
+ if (sigAlgo == rsa_pss_sa_algo) {
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+ int mgf = 0;
+
+ ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+ if (ret != 0)
+ return ret;
+
+ #if defined(HAVE_PK_CALLBACKS)
+ if (ssl->ctx->RsaPssSignCb) {
+ void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+ ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz,
+ TypeHash(hashAlgo), mgf,
+ keyBuf, keySz, ctx);
+ }
+ else
+ #endif
+ {
+ ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key,
+ ssl->rng);
+ }
+ }
+ else
+#endif
+#if defined(HAVE_PK_CALLBACKS)
+ if (ssl->ctx->RsaSignCb) {
+ void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+ ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+ ctx);
+ }
+ else
+#endif /*HAVE_PK_CALLBACKS */
+ ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng);
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (key && ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ /* For positive response return in outSz */
+ if (ret > 0) {
+ *outSz = ret;
+ ret = 0;
+ }
+
+ WOLFSSL_LEAVE("RsaSign", ret);
+
+ return ret;
+}
+#endif
+
+int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
+ int hashAlgo, RsaKey* key, buffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+ (void)sigAlgo;
+ (void)hashAlgo;
+
+ WOLFSSL_ENTER("RsaVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#if defined(WC_RSA_PSS)
+ if (sigAlgo == rsa_pss_sa_algo) {
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+ int mgf = 0;
+
+ ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+ if (ret != 0)
+ return ret;
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaPssVerifyCb) {
+ void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl);
+ ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out,
+ TypeHash(hashAlgo), mgf,
+ keyBuf, keySz, ctx);
+ }
+ else
+#endif /*HAVE_PK_CALLBACKS */
+ ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key);
+ }
+ else
+#endif
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaVerifyCb) {
+ void* ctx = wolfSSL_GetRsaVerifyCtx(ssl);
+ ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+ }
+ else
+#endif /*HAVE_PK_CALLBACKS */
+ {
+ ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("RsaVerify", ret);
+
+ return ret;
+}
+
+/* Verify RSA signature, 0 on success */
+/* This function is used to check the sign result */
+int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
+ const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key,
+ DerBuffer* keyBufInfo)
+{
+ byte* out = NULL; /* inline result */
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+ (void)sigAlgo;
+ (void)hashAlgo;
+
+ WOLFSSL_ENTER("VerifyRsaSign");
+
+ if (verifySig == NULL || plain == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (sigSz > ENCRYPT_LEN) {
+ WOLFSSL_MSG("Signature buffer too big");
+ return BUFFER_E;
+ }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ if (key) {
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+ }
+#endif
+
+#if defined(WC_RSA_PSS)
+ if (sigAlgo == rsa_pss_sa_algo) {
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+ int mgf = 0;
+
+ ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+ if (ret != 0)
+ return ret;
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaPssSignCheckCb) {
+ /* The key buffer includes private/public portion,
+ but only public is used */
+ /* If HSM hardware is checking the signature result you can
+ optionally skip the sign check and return 0 */
+ /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+ void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+ ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out,
+ TypeHash(hashAlgo), mgf,
+ keyBuf, keySz, ctx);
+ if (ret > 0) {
+ ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
+ hashType);
+ if (ret != 0)
+ ret = VERIFY_CERT_ERROR;
+ }
+ }
+ else
+ #endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
+ key);
+ if (ret > 0) {
+ #ifdef HAVE_SELFTEST
+ ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
+ hashType);
+ #else
+ ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, ret,
+ hashType, -1,
+ mp_count_bits(&key->n));
+ #endif
+ if (ret != 0)
+ ret = VERIFY_CERT_ERROR;
+ }
+ }
+
+ }
+ else
+#endif /* WC_RSA_PSS */
+ {
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaSignCheckCb) {
+ /* The key buffer includes private/public portion,
+ but only public is used */
+ /* If HSM hardware is checking the signature result you can
+ optionally skip the sign check and return 0 */
+ /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+ void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+ ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out,
+ keyBuf, keySz, ctx);
+ }
+ else
+ #endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key);
+ }
+
+ if (ret > 0) {
+ if (ret != (int)plainSz || !out ||
+ XMEMCMP(plain, out, plainSz) != 0) {
+ WOLFSSL_MSG("RSA Signature verification failed");
+ ret = RSA_SIGN_FAULT;
+ } else {
+ ret = 0; /* RSA reset */
+ }
+ }
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (key && ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("VerifyRsaSign", ret);
+
+ return ret;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
+ RsaKey* key, DerBuffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("RsaDec");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaDecCb) {
+ void* ctx = wolfSSL_GetRsaDecCtx(ssl);
+ ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ #ifdef WC_RSA_BLINDING
+ ret = wc_RsaSetRNG(key, ssl->rng);
+ if (ret != 0)
+ return ret;
+ #endif
+ ret = wc_RsaPrivateDecryptInline(in, inSz, out, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ /* For positive response return in outSz */
+ if (ret > 0) {
+ *outSz = ret;
+ ret = 0;
+ }
+
+ WOLFSSL_LEAVE("RsaDec", ret);
+
+ return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER) || !WOLFSSL_NO_CLIENT_AUTH */
+
+int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
+ RsaKey* key, buffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("RsaEnc");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->RsaEncCb) {
+ void* ctx = wolfSSL_GetRsaEncCtx(ssl);
+ ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ /* For positive response return in outSz */
+ if (ret > 0) {
+ *outSz = ret;
+ ret = 0;
+ }
+
+ WOLFSSL_LEAVE("RsaEnc", ret);
+
+ return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* NO_RSA */
+
+#ifdef HAVE_ECC
+
+int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+ word32* outSz, ecc_key* key, DerBuffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("EccSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ if (key) {
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+ }
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+ if (ssl->ctx->EccSignCb) {
+ void* ctx = wolfSSL_GetEccSignCtx(ssl);
+ ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf,
+ keySz, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (key && ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("EccSign", ret);
+
+ return ret;
+}
+
+int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
+ word32 outSz, ecc_key* key, buffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("EccVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->EccVerifyCb) {
+ void* ctx = wolfSSL_GetEccVerifyCtx(ssl);
+ ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+ &ssl->eccVerifyRes, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+ else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+ {
+ ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+ }
+
+ WOLFSSL_LEAVE("EccVerify", ret);
+
+ return ret;
+}
+
+#ifdef HAVE_PK_CALLBACKS
+ /* Gets ECC key for shared secret callback testing
+ * Client side: returns peer key
+ * Server side: returns private key
+ */
+ static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey)
+ {
+ int ret = NO_PEER_KEY;
+ ecc_key* tmpKey = NULL;
+
+ if (ssl == NULL || otherKey == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if (ssl->specs.static_ecdh) {
+ if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
+ !ssl->peerEccDsaKey->dp) {
+ return NO_PEER_KEY;
+ }
+ tmpKey = (struct ecc_key*)ssl->peerEccDsaKey;
+ }
+ else {
+ if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+ !ssl->peerEccKey->dp) {
+ return NO_PEER_KEY;
+ }
+ tmpKey = (struct ecc_key*)ssl->peerEccKey;
+ }
+ }
+ else if (ssl->options.side == WOLFSSL_SERVER_END) {
+ if (ssl->specs.static_ecdh) {
+ if (ssl->hsKey == NULL) {
+ return NO_PRIVATE_KEY;
+ }
+ tmpKey = (struct ecc_key*)ssl->hsKey;
+ }
+ else {
+ if (!ssl->eccTempKeyPresent) {
+ return NO_PRIVATE_KEY;
+ }
+ tmpKey = (struct ecc_key*)ssl->eccTempKey;
+ }
+ }
+
+ if (tmpKey) {
+ *otherKey = tmpKey;
+ ret = 0;
+ }
+
+ return ret;
+ }
+#endif /* HAVE_PK_CALLBACKS */
+
+int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
+ byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
+ int side)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ ecc_key* otherKey = NULL;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+ WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev;
+#endif
+
+ (void)ssl;
+ (void)pubKeyDer;
+ (void)pubKeySz;
+ (void)side;
+
+ WOLFSSL_ENTER("EccSharedSecret");
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->EccSharedSecretCb) {
+ ret = EccGetKey(ssl, &otherKey);
+ if (ret != 0)
+ return ret;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ asyncDev = &otherKey->asyncDev;
+ #endif
+ }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->EccSharedSecretCb) {
+ void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl);
+ ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
+ pubKeySz, out, outlen, side, ctx);
+ }
+ else
+#endif
+ {
+ ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("EccSharedSecret", ret);
+
+ return ret;
+}
+
+int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
+{
+ int ret = 0;
+ int keySz = 0;
+ int ecc_curve = ECC_CURVE_DEF;
+
+ WOLFSSL_ENTER("EccMakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+ if (ret != 0)
+ return ret;
+#endif
+
+ /* get key size */
+ if (peer == NULL) {
+ keySz = ssl->eccTempKeySz;
+ }
+ else {
+ keySz = peer->dp->size;
+ }
+
+ /* get curve type */
+ if (ssl->ecdhCurveOID > 0) {
+ ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
+ }
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->EccKeyGenCb) {
+ void* ctx = wolfSSL_GetEccKeyGenCtx(ssl);
+ ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx);
+ }
+ else
+#endif
+ {
+ ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
+ }
+
+ /* make sure the curve is set for TLS */
+ if (ret == 0 && key->dp) {
+ ssl->ecdhCurveOID = key->dp->oidSum;
+ #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
+ #endif
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("EccMakeKey", ret);
+
+ return ret;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+/* Check whether the key contains a public key.
+ * If not then pull it out of the leaf certificate.
+ *
+ * ssl SSL/TLS object.
+ * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
+ * 0 on success.
+ */
+int Ed25519CheckPubKey(WOLFSSL* ssl)
+{
+ ed25519_key* key = (ed25519_key*)ssl->hsKey;
+ int ret = 0;
+
+ /* Public key required for signing. */
+ if (!key->pubKeySet) {
+ DerBuffer* leaf = ssl->buffers.certificate;
+ DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert),
+ ssl->heap, DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ ret = MEMORY_E;
+
+ if (ret == 0) {
+ InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
+ ret = DecodeToKey(cert, 0);
+ }
+ if (ret == 0) {
+ ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize,
+ key);
+ }
+ if (cert != NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ }
+ }
+
+ return ret;
+}
+
+/* Sign the data using EdDSA and key using Ed25519.
+ *
+ * ssl SSL object.
+ * in Data or message to sign.
+ * inSz Length of the data.
+ * out Buffer to hold signature.
+ * outSz On entry, size of the buffer. On exit, the size of the signature.
+ * key The private Ed25519 key data.
+ * keySz The length of the private key data in bytes.
+ * ctx The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+ word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("Ed25519Sign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+ if (ssl->ctx->Ed25519SignCb) {
+ void* ctx = wolfSSL_GetEd25519SignCtx(ssl);
+ ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf,
+ keySz, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("Ed25519Sign", ret);
+
+ return ret;
+}
+
+/* Verify the data using EdDSA and key using Ed25519.
+ *
+ * ssl SSL object.
+ * in Signature data.
+ * inSz Length of the signature data in bytes.
+ * msg Message to verify.
+ * outSz Length of message in bytes.
+ * key The public Ed25519 key data.
+ * keySz The length of the private key data in bytes.
+ * ctx The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
+ word32 msgSz, ed25519_key* key, buffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("Ed25519Verify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->Ed25519VerifyCb) {
+ void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl);
+ ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf,
+ keySz, &ssl->eccVerifyRes, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz,
+ &ssl->eccVerifyRes, key);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+ else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+ {
+ ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+ }
+
+ WOLFSSL_LEAVE("Ed25519Verify", ret);
+
+ return ret;
+}
+#endif /* HAVE_ED25519 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CURVE25519
+#ifdef HAVE_PK_CALLBACKS
+ /* Gets X25519 key for shared secret callback testing
+ * Client side: returns peer key
+ * Server side: returns private key
+ */
+ static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey)
+ {
+ int ret = NO_PEER_KEY;
+ struct curve25519_key* tmpKey = NULL;
+
+ if (ssl == NULL || otherKey == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent ||
+ !ssl->peerX25519Key->dp) {
+ return NO_PEER_KEY;
+ }
+ tmpKey = (struct curve25519_key*)ssl->peerX25519Key;
+ }
+ else if (ssl->options.side == WOLFSSL_SERVER_END) {
+ if (!ssl->eccTempKeyPresent) {
+ return NO_PRIVATE_KEY;
+ }
+ tmpKey = (struct curve25519_key*)ssl->eccTempKey;
+ }
+
+ if (tmpKey) {
+ *otherKey = (curve25519_key *)tmpKey;
+ ret = 0;
+ }
+
+ return ret;
+ }
+#endif /* HAVE_PK_CALLBACKS */
+
+static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
+ curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz,
+ byte* out, word32* outlen, int side)
+{
+ int ret;
+
+ (void)ssl;
+ (void)pubKeyDer;
+ (void)pubKeySz;
+ (void)side;
+
+ WOLFSSL_ENTER("X25519SharedSecret");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->X25519SharedSecretCb) {
+ curve25519_key* otherKey = NULL;
+
+ ret = X25519GetKey(ssl, &otherKey);
+ if (ret == 0) {
+ void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl);
+ ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer,
+ pubKeySz, out, outlen, side, ctx);
+ }
+ }
+ else
+#endif
+ {
+ ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
+ EC25519_LITTLE_ENDIAN);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("X25519SharedSecret", ret);
+
+ return ret;
+}
+
+static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
+ curve25519_key* peer)
+{
+ int ret = 0;
+
+ (void)peer;
+
+ WOLFSSL_ENTER("X25519MakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->X25519KeyGenCb) {
+ void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl);
+ ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx);
+ }
+ else
+#endif
+ {
+ ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+ }
+
+ if (ret == 0) {
+ ssl->ecdhCurveOID = ECC_X25519_OID;
+ #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
+ #endif
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("X25519MakeKey", ret);
+
+ return ret;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifdef HAVE_ED448
+/* Check whether the key contains a public key.
+ * If not then pull it out of the leaf certificate.
+ *
+ * ssl SSL/TLS object.
+ * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
+ * 0 on success.
+ */
+int Ed448CheckPubKey(WOLFSSL* ssl)
+{
+ ed448_key* key = (ed448_key*)ssl->hsKey;
+ int ret = 0;
+
+ /* Public key required for signing. */
+ if (!key->pubKeySet) {
+ DerBuffer* leaf = ssl->buffers.certificate;
+ DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert), ssl->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ ret = MEMORY_E;
+
+ if (ret == 0) {
+ InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
+ ret = DecodeToKey(cert, 0);
+ }
+ if (ret == 0) {
+ ret = wc_ed448_import_public(cert->publicKey, cert->pubKeySize,
+ key);
+ }
+ if (cert != NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ }
+ }
+
+ return ret;
+}
+
+/* Sign the data using EdDSA and key using Ed448.
+ *
+ * ssl SSL object.
+ * in Data or message to sign.
+ * inSz Length of the data.
+ * out Buffer to hold signature.
+ * outSz On entry, size of the buffer. On exit, the size of the signature.
+ * key The private Ed448 key data.
+ * keySz The length of the private key data in bytes.
+ * ctx The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+ word32* outSz, ed448_key* key, DerBuffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("Ed448Sign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+ if (ssl->ctx->Ed448SignCb) {
+ void* ctx = wolfSSL_GetEd448SignCtx(ssl);
+ ret = ssl->ctx->Ed448SignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+ ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ed448_sign_msg(in, inSz, out, outSz, key, NULL, 0);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("Ed448Sign", ret);
+
+ return ret;
+}
+
+/* Verify the data using EdDSA and key using Ed448.
+ *
+ * ssl SSL object.
+ * in Signature data.
+ * inSz Length of the signature data in bytes.
+ * msg Message to verify.
+ * outSz Length of message in bytes.
+ * key The public Ed448 key data.
+ * keySz The length of the private key data in bytes.
+ * ctx The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
+ word32 msgSz, ed448_key* key, buffer* keyBufInfo)
+{
+ int ret;
+#ifdef HAVE_PK_CALLBACKS
+ const byte* keyBuf = NULL;
+ word32 keySz = 0;
+
+ if (keyBufInfo) {
+ keyBuf = keyBufInfo->buffer;
+ keySz = keyBufInfo->length;
+ }
+#endif
+
+ (void)ssl;
+ (void)keyBufInfo;
+
+ WOLFSSL_ENTER("Ed448Verify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->Ed448VerifyCb) {
+ void* ctx = wolfSSL_GetEd448VerifyCtx(ssl);
+ ret = ssl->ctx->Ed448VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, keySz,
+ &ssl->eccVerifyRes, ctx);
+ }
+ else
+#endif /* HAVE_PK_CALLBACKS */
+ {
+ ret = wc_ed448_verify_msg(in, inSz, msg, msgSz, &ssl->eccVerifyRes, key,
+ NULL, 0);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+ else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+ {
+ ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+ }
+
+ WOLFSSL_LEAVE("Ed448Verify", ret);
+
+ return ret;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+#ifdef HAVE_PK_CALLBACKS
+ /* Gets X448 key for shared secret callback testing
+ * Client side: returns peer key
+ * Server side: returns private key
+ */
+ static int X448GetKey(WOLFSSL* ssl, curve448_key** otherKey)
+ {
+ int ret = NO_PEER_KEY;
+ struct curve448_key* tmpKey = NULL;
+
+ if (ssl == NULL || otherKey == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if (!ssl->peerX448Key || !ssl->peerX448KeyPresent) {
+ return NO_PEER_KEY;
+ }
+ tmpKey = (struct curve448_key*)ssl->peerX448Key;
+ }
+ else if (ssl->options.side == WOLFSSL_SERVER_END) {
+ if (!ssl->eccTempKeyPresent) {
+ return NO_PRIVATE_KEY;
+ }
+ tmpKey = (struct curve448_key*)ssl->eccTempKey;
+ }
+
+ if (tmpKey) {
+ *otherKey = (curve448_key *)tmpKey;
+ ret = 0;
+ }
+
+ return ret;
+ }
+#endif /* HAVE_PK_CALLBACKS */
+
+static int X448SharedSecret(WOLFSSL* ssl, curve448_key* priv_key,
+ curve448_key* pub_key, byte* pubKeyDer,
+ word32* pubKeySz, byte* out, word32* outlen,
+ int side)
+{
+ int ret;
+
+ (void)ssl;
+ (void)pubKeyDer;
+ (void)pubKeySz;
+ (void)side;
+
+ WOLFSSL_ENTER("X448SharedSecret");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->X448SharedSecretCb) {
+ curve448_key* otherKey = NULL;
+
+ ret = X448GetKey(ssl, &otherKey);
+ if (ret == 0) {
+ void* ctx = wolfSSL_GetX448SharedSecretCtx(ssl);
+ ret = ssl->ctx->X448SharedSecretCb(ssl, otherKey, pubKeyDer,
+ pubKeySz, out, outlen, side, ctx);
+ }
+ }
+ else
+#endif
+ {
+ ret = wc_curve448_shared_secret_ex(priv_key, pub_key, out, outlen,
+ EC448_LITTLE_ENDIAN);
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("X448SharedSecret", ret);
+
+ return ret;
+}
+
+static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer)
+{
+ int ret = 0;
+
+ (void)peer;
+
+ WOLFSSL_ENTER("X448MakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->X448KeyGenCb) {
+ void* ctx = wolfSSL_GetX448KeyGenCtx(ssl);
+ ret = ssl->ctx->X448KeyGenCb(ssl, key, CURVE448_KEY_SIZE, ctx);
+ }
+ else
+#endif
+ {
+ ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
+ }
+
+ if (ret == 0) {
+ ssl->ecdhCurveOID = ECC_X448_OID;
+ #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
+ #endif
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("X448MakeKey", ret);
+
+ return ret;
+}
+#endif /* HAVE_CURVE448 */
+
+#if !defined(NO_CERTS) || !defined(NO_PSK)
+#if !defined(NO_DH)
+
+int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
+ byte* priv, word32* privSz,
+ byte* pub, word32* pubSz)
+{
+ int ret;
+
+ WOLFSSL_ENTER("DhGenKeyPair");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+ if (ret != 0)
+ return ret;
+#endif
+
+ ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz);
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("DhGenKeyPair", ret);
+
+ return ret;
+}
+
+int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
+ const byte* priv, word32 privSz,
+ const byte* otherPub, word32 otherPubSz,
+ byte* agree, word32* agreeSz)
+{
+ int ret;
+
+ (void)ssl;
+
+ WOLFSSL_ENTER("DhAgree");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+ if (ret != 0)
+ return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->DhAgreeCb) {
+ void* ctx = wolfSSL_GetDhAgreeCtx(ssl);
+
+ WOLFSSL_MSG("Calling DhAgree Callback Function");
+ ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz,
+ otherPub, otherPubSz, agree, agreeSz, ctx);
+ }
+ else
+#endif
+ {
+#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+ ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length, otherPub, otherPubSz);
+ if (ret != 0) {
#ifdef OPENSSL_EXTRA
- XFREE(x509->authKeyId, NULL, 0);
- XFREE(x509->subjKeyId, NULL, 0);
- #endif /* OPENSSL_EXTRA */
- if (x509->altNames)
- FreeAltNames(x509->altNames, NULL);
- if (x509->dynamicMemory)
- XFREE(x509, NULL, DYNAMIC_TYPE_X509);
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ }
+ else
+#endif
+ {
+ ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub,
+ otherPubSz);
+ }
+ }
+
+ /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ WOLFSSL_LEAVE("DhAgree", ret);
+
+ return ret;
}
+#endif /* !NO_DH */
+#endif /* !NO_CERTS || !NO_PSK */
-#endif /* NO_CERTS */
+#endif /* !WOLFSSL_NO_TLS12 */
-/* init everything to 0, NULL, default values before calling anything that may
- fail so that desctructor has a "good" state to cleanup */
-int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
+#ifdef HAVE_PK_CALLBACKS
+int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl)
{
- int ret;
- byte haveRSA = 0;
+ int pkcbset = 0;
+ (void)ssl;
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ !defined(NO_RSA)
+ if (0
+ #ifdef HAVE_ECC
+ || (ssl->ctx->EccSignCb != NULL &&
+ ssl->buffers.keyType == ecc_dsa_sa_algo)
+ #endif
+ #ifdef HAVE_ED25519
+ || (ssl->ctx->Ed25519SignCb != NULL &&
+ ssl->buffers.keyType == ed25519_sa_algo)
+ #endif
+ #ifdef HAVE_ED448
+ || (ssl->ctx->Ed448SignCb != NULL &&
+ ssl->buffers.keyType == ed448_sa_algo)
+ #endif
+ #ifndef NO_RSA
+ || (ssl->ctx->RsaSignCb != NULL && ssl->buffers.keyType == rsa_sa_algo)
+ || (ssl->ctx->RsaDecCb != NULL && ssl->buffers.keyType == rsa_kea)
+ #ifdef WC_RSA_PSS
+ || (ssl->ctx->RsaPssSignCb != NULL &&
+ ssl->buffers.keyType == rsa_pss_sa_algo)
+ #endif
+ #endif
+ ) {
+ pkcbset = 1;
+ }
+#endif
+ return pkcbset;
+}
+
+int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
+{
+ int pkcbset = 0;
+ (void)ctx;
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ !defined(NO_RSA)
+ if (0
+ #ifdef HAVE_ECC
+ || ctx->EccSignCb != NULL
+ #endif
+ #ifdef HAVE_ED25519
+ || ctx->Ed25519SignCb != NULL
+ #endif
+ #ifdef HAVE_ED448
+ || ctx->Ed448SignCb != NULL
+ #endif
+ #ifndef NO_RSA
+ || ctx->RsaSignCb != NULL
+ || ctx->RsaDecCb != NULL
+ #ifdef WC_RSA_PSS
+ || ctx->RsaPssSignCb != NULL
+ #endif
+ #endif
+ ) {
+ pkcbset = 1;
+ }
+#endif
+ return pkcbset;
+}
+#endif /* HAVE_PK_CALLBACKS */
+
+
+int InitSSL_Suites(WOLFSSL* ssl)
+{
+ int keySz = 0;
byte havePSK = 0;
byte haveAnon = 0;
+ byte haveRSA = 0;
+ byte haveMcast = 0;
- (void) haveAnon;
-
- XMEMSET(ssl, 0, sizeof(WOLFSSL));
+ (void)haveAnon; /* Squash unused var warnings */
+ (void)haveMcast;
- ssl->ctx = ctx; /* only for passing to calls, options could change */
- ssl->version = ctx->method->version;
+ if (!ssl)
+ return BAD_FUNC_ARG;
#ifndef NO_RSA
haveRSA = 1;
#endif
+#ifndef NO_PSK
+ havePSK = (byte)ssl->options.havePSK;
+#endif /* NO_PSK */
+#ifdef HAVE_ANON
+ haveAnon = (byte)ssl->options.haveAnon;
+#endif /* HAVE_ANON*/
+#ifdef WOLFSSL_MULTICAST
+ haveMcast = (byte)ssl->options.haveMcast;
+#endif /* WOLFSSL_MULTICAST */
- ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
- ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ ssl->options.maxEarlyDataSz = ssl->ctx->maxEarlyDataSz;
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+ ssl->buffers.keyType == ed25519_sa_algo ||
+ ssl->buffers.keyType == ed448_sa_algo;
+#endif
- ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
- ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+#ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+#endif
-#ifdef KEEP_PEER_CERT
- InitX509(&ssl->peerCert, 0);
+ /* make sure server has DH parms, and add PSK if there, add NTRU too */
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
+ else {
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ TRUE, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
+
+#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
+ /* make sure server has cert and key unless using PSK, Anon, or
+ * Multicast. This should be true even if just switching ssl ctx */
+ if (ssl->options.side == WOLFSSL_SERVER_END &&
+ !havePSK && !haveAnon && !haveMcast) {
+
+ /* server certificate must be loaded */
+ if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) {
+ WOLFSSL_MSG("Server missing certificate");
+ return NO_PRIVATE_KEY;
+ }
+
+ /* allow no private key if using PK callbacks and CB is set */
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+ WOLFSSL_MSG("Using PK for server private key");
+ }
+ else
+ #endif
+ if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+ WOLFSSL_MSG("Server missing private key");
+ return NO_PRIVATE_KEY;
+ }
+ }
#endif
-#ifdef HAVE_ECC
- ssl->eccTempKeySz = ctx->eccTempKeySz;
- ssl->pkCurveOID = ctx->pkCurveOID;
+ return WOLFSSL_SUCCESS;
+}
+
+/* returns new reference count. Arg incr positive=up or negative=down */
+int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr)
+{
+ int refCount;
+
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (wc_LockMutex(&ctx->countMutex) != 0) {
+ WOLFSSL_MSG("Couldn't lock CTX count mutex");
+ return BAD_MUTEX_E;
+ }
+
+ ctx->refCount += incr;
+ /* make sure refCount is never negative */
+ if (ctx->refCount < 0) {
+ ctx->refCount = 0;
+ }
+ refCount = ctx->refCount;
+
+ wc_UnLockMutex(&ctx->countMutex);
+
+ return refCount;
+}
+
+/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
+ It is used during initialization and to switch an ssl's CTX with
+ wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK
+ unless writeDup is on.
+
+ ssl object to initialize
+ ctx parent factory
+ writeDup flag indicating this is a write dup only
+
+ WOLFSSL_SUCCESS return value on success */
+int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+ int ret;
+ byte newSSL;
+
+ if (!ssl || !ctx)
+ return BAD_FUNC_ARG;
+
+#ifndef SINGLE_THREADED
+ if (ssl->suites == NULL && !writeDup)
+ return BAD_FUNC_ARG;
#endif
- ssl->timeout = ctx->timeout;
- ssl->rfd = -1; /* set to invalid descriptor */
- ssl->wfd = -1;
+ newSSL = ssl->ctx == NULL; /* Assign after null check */
- ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */
- ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
+#ifndef NO_PSK
+ if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
+ return BAD_FUNC_ARG; /* needed for copy below */
+ }
+#endif
-#ifdef HAVE_NETX
- ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */
- ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */
+ /* decrement previous CTX reference count if exists.
+ * This should only happen if switching ctxs!*/
+ if (!newSSL) {
+ WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx.");
+ wolfSSL_CTX_free(ssl->ctx);
+ }
+
+ /* increment CTX reference count */
+ if ((ret = SSL_CTX_RefCount(ctx, 1)) < 0) {
+ return ret;
+ }
+ ret = WOLFSSL_SUCCESS; /* set default ret */
+
+ ssl->ctx = ctx; /* only for passing to calls, options could change */
+ ssl->version = ctx->method->version;
+
+#ifdef HAVE_ECC
+ ssl->eccTempKeySz = ctx->eccTempKeySz;
+ ssl->ecdhCurveOID = ctx->ecdhCurveOID;
#endif
-#ifdef WOLFSSL_DTLS
- ssl->dtls_expected_rx = MAX_MTU;
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+ ssl->pkCurveOID = ctx->pkCurveOID;
#endif
+#ifdef OPENSSL_EXTRA
+ ssl->options.mask = ctx->mask;
+ ssl->CBIS = ctx->CBIS;
+#endif
+ ssl->timeout = ctx->timeout;
ssl->verifyCallback = ctx->verifyCallback;
ssl->options.side = ctx->method->side;
ssl->options.downgrade = ctx->method->downgrade;
ssl->options.minDowngrade = ctx->minDowngrade;
- if (ssl->options.side == WOLFSSL_SERVER_END)
- ssl->options.haveDH = ctx->haveDH;
-
+ ssl->options.haveDH = ctx->haveDH;
ssl->options.haveNTRU = ctx->haveNTRU;
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
+ ssl->options.haveECC = ctx->haveECC;
ssl->options.haveStaticECC = ctx->haveStaticECC;
#ifndef NO_PSK
- havePSK = ctx->havePSK;
ssl->options.havePSK = ctx->havePSK;
ssl->options.client_psk_cb = ctx->client_psk_cb;
ssl->options.server_psk_cb = ctx->server_psk_cb;
+#ifdef WOLFSSL_TLS13
+ ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb;
+ ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb;
+#endif
#endif /* NO_PSK */
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz;
+#endif
#ifdef HAVE_ANON
- haveAnon = ctx->haveAnon;
ssl->options.haveAnon = ctx->haveAnon;
#endif
-
- 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;
-
#ifndef NO_DH
ssl->options.minDhKeySz = ctx->minDhKeySz;
+ ssl->options.maxDhKeySz = ctx->maxDhKeySz;
#endif
-
-#ifdef WOLFSSL_DTLS
- ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT;
- ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX;
- ssl->dtls_timeout = ssl->dtls_timeout_init;
+#ifndef NO_RSA
+ ssl->options.minRsaKeySz = ctx->minRsaKeySz;
+#endif
+#ifdef HAVE_ECC
+ ssl->options.minEccKeySz = ctx->minEccKeySz;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->options.verifyDepth = ctx->verifyDepth;
#endif
ssl->options.sessionCacheOff = ctx->sessionCacheOff;
ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
+#ifdef HAVE_EXT_CACHE
+ ssl->options.internalCacheOff = ctx->internalCacheOff;
+#endif
- ssl->options.verifyPeer = ctx->verifyPeer;
- ssl->options.verifyNone = ctx->verifyNone;
- ssl->options.failNoCert = ctx->failNoCert;
- ssl->options.sendVerify = ctx->sendVerify;
-
- #ifndef NO_OLD_TLS
- ssl->hmac = SSL_hmac; /* default to SSLv3 */
- #else
- ssl->hmac = TLS_hmac;
- #endif
-
- ssl->heap = ctx->heap; /* defaults to self */
+ ssl->options.verifyPeer = ctx->verifyPeer;
+ ssl->options.verifyNone = ctx->verifyNone;
+ ssl->options.failNoCert = ctx->failNoCert;
+ ssl->options.failNoCertxPSK = ctx->failNoCertxPSK;
+ ssl->options.sendVerify = ctx->sendVerify;
- ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
ssl->options.partialWrite = ctx->partialWrite;
ssl->options.quietShutdown = ctx->quietShutdown;
ssl->options.groupMessages = ctx->groupMessages;
#ifndef NO_DH
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- ssl->buffers.serverDH_P = ctx->serverDH_P;
- ssl->buffers.serverDH_G = ctx->serverDH_G;
- }
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ ssl->options.dhKeyTested = ctx->dhKeyTested;
+ #endif
+ ssl->buffers.serverDH_P = ctx->serverDH_P;
+ ssl->buffers.serverDH_G = ctx->serverDH_G;
#endif
+
#ifndef NO_CERTS
/* ctx still owns certificate, certChain, key, dh, and cm */
ssl->buffers.certificate = ctx->certificate;
ssl->buffers.certChain = ctx->certChain;
- ssl->buffers.key = ctx->privateKey;
+#ifdef WOLFSSL_TLS13
+ ssl->buffers.certChainCnt = ctx->certChainCnt;
#endif
-
-#ifdef WOLFSSL_DTLS
- ssl->buffers.dtlsCtx.fd = -1;
+ ssl->buffers.key = ctx->privateKey;
+ ssl->buffers.keyType = ctx->privateKeyType;
+ ssl->buffers.keyId = ctx->privateKeyId;
+ ssl->buffers.keySz = ctx->privateKeySz;
+ ssl->buffers.keyDevId = ctx->privateKeyDevId;
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+ ssl->buffers.keyType == ed25519_sa_algo ||
+ ssl->buffers.keyType == ed448_sa_algo;
#endif
- ssl->cipher.ssl = ssl;
-#ifdef HAVE_CAVIUM
+#ifdef WOLFSSL_ASYNC_CRYPT
ssl->devId = ctx->devId;
#endif
-#ifdef HAVE_TLS_EXTENSIONS
-#ifdef HAVE_MAX_FRAGMENT
- ssl->max_fragment = MAX_RECORD_SIZE;
+ if (writeDup == 0) {
+#ifndef NO_PSK
+ if (ctx->server_hint[0]) { /* set in CTX */
+ XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,
+ sizeof(ssl->arrays->server_hint));
+ ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+ }
+#endif /* NO_PSK */
+
+ if (ctx->suites) {
+#ifndef SINGLE_THREADED
+ *ssl->suites = *ctx->suites;
+#else
+ ssl->suites = ctx->suites;
#endif
+ }
+ else {
+ XMEMSET(ssl->suites, 0, sizeof(Suites));
+ }
+
+ if (ssl->options.side != WOLFSSL_NEITHER_END) {
+ /* Defer initializing suites until accept or connect */
+ ret = InitSSL_Suites(ssl);
+ }
+ } /* writeDup check */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+ #ifdef WOLFSSL_DTLS
+ ssl->dtls_export = ctx->dtls_export; /* export function for session */
+ #endif
#endif
- /* 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->CBIORecv = ctx->CBIORecv;
+ ssl->CBIOSend = ctx->CBIOSend;
+#ifdef OPENSSL_EXTRA
+ ssl->readAhead = ctx->readAhead;
+#endif
+ ssl->verifyDepth = ctx->verifyDepth;
- InitCiphers(ssl);
- InitCipherSpecs(&ssl->specs);
+ return ret;
+}
- /* all done with init, now can return errors, call other stuff */
+int InitHandshakeHashes(WOLFSSL* ssl)
+{
+ int ret;
- /* hsHashes */
+ /* 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_OLD_TLS
#ifndef NO_MD5
- wc_InitMd5(&ssl->hsHashes->hashMd5);
+ ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId);
+ if (ret != 0)
+ return ret;
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY);
+ #endif
#endif
#ifndef NO_SHA
- ret = wc_InitSha(&ssl->hsHashes->hashSha);
- if (ret != 0) {
+ ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId);
+ if (ret != 0)
return ret;
- }
-#endif
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY);
+ #endif
#endif
+#endif /* !NO_OLD_TLS */
#ifndef NO_SHA256
- ret = wc_InitSha256(&ssl->hsHashes->hashSha256);
- if (ret != 0) {
+ ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId);
+ if (ret != 0)
return ret;
- }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY);
+ #endif
#endif
#ifdef WOLFSSL_SHA384
- ret = wc_InitSha384(&ssl->hsHashes->hashSha384);
- if (ret != 0) {
+ ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId);
+ if (ret != 0)
return ret;
- }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY);
+ #endif
#endif
#ifdef WOLFSSL_SHA512
- ret = wc_InitSha512(&ssl->hsHashes->hashSha512);
- if (ret != 0) {
+ ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId);
+ if (ret != 0)
return ret;
- }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY);
+ #endif
#endif
- /* increment CTX reference count */
- if (LockMutex(&ctx->countMutex) != 0) {
- WOLFSSL_MSG("Couldn't lock CTX count mutex");
- return BAD_MUTEX_E;
+ return ret;
+}
+
+void FreeHandshakeHashes(WOLFSSL* ssl)
+{
+ if (ssl->hsHashes) {
+#ifndef NO_OLD_TLS
+ #ifndef NO_MD5
+ wc_Md5Free(&ssl->hsHashes->hashMd5);
+ #endif
+ #ifndef NO_SHA
+ wc_ShaFree(&ssl->hsHashes->hashSha);
+ #endif
+#endif /* !NO_OLD_TLS */
+ #ifndef NO_SHA256
+ wc_Sha256Free(&ssl->hsHashes->hashSha256);
+ #endif
+ #ifdef WOLFSSL_SHA384
+ wc_Sha384Free(&ssl->hsHashes->hashSha384);
+ #endif
+ #ifdef WOLFSSL_SHA512
+ wc_Sha512Free(&ssl->hsHashes->hashSha512);
+ #endif
+ #if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+ !defined(WOLFSSL_NO_CLIENT_AUTH)
+ if (ssl->hsHashes->messages != NULL) {
+ 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;
}
- ctx->refCount++;
- UnLockMutex(&ctx->countMutex);
+}
- /* arrays */
- ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
- DYNAMIC_TYPE_ARRAYS);
- if (ssl->arrays == NULL) {
- WOLFSSL_MSG("Arrays Memory error");
+
+/* 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(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+ int ret;
+
+ XMEMSET(ssl, 0, sizeof(WOLFSSL));
+
+#if defined(WOLFSSL_STATIC_MEMORY)
+ if (ctx->heap != NULL) {
+ WOLFSSL_HEAP_HINT* ssl_hint;
+ WOLFSSL_HEAP_HINT* ctx_hint;
+
+ /* avoid dereferencing a test value */
+ #ifdef WOLFSSL_HEAP_TEST
+ if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) {
+ ssl->heap = ctx->heap;
+ }
+ else {
+ #endif
+ ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT),
+ ctx->heap, DYNAMIC_TYPE_SSL);
+ if (ssl->heap == NULL) {
+ return MEMORY_E;
+ }
+ XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT));
+ ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+ ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap));
+
+ /* lock and check IO count / handshake count */
+ if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+ WOLFSSL_MSG("Bad memory_mutex lock");
+ XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+ ssl->heap = NULL; /* free and set to NULL for IO counter */
+ return BAD_MUTEX_E;
+ }
+ if (ctx_hint->memory->maxHa > 0 &&
+ ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) {
+ WOLFSSL_MSG("At max number of handshakes for static memory");
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+ ssl->heap = NULL; /* free and set to NULL for IO counter */
+ return MEMORY_E;
+ }
+
+ if (ctx_hint->memory->maxIO > 0 &&
+ ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) {
+ WOLFSSL_MSG("At max number of IO allowed for static memory");
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+ ssl->heap = NULL; /* free and set to NULL for IO counter */
+ return MEMORY_E;
+ }
+ ctx_hint->memory->curIO++;
+ ctx_hint->memory->curHa++;
+ ssl_hint->memory = ctx_hint->memory;
+ ssl_hint->haFlag = 1;
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+
+ /* check if tracking stats */
+ if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) {
+ ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC(
+ sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL);
+ if (ssl_hint->stats == NULL) {
+ return MEMORY_E;
+ }
+ 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) {
+ if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+ WOLFSSL_MSG("Bad memory_mutex lock");
+ return BAD_MUTEX_E;
+ }
+ if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) {
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ return MEMORY_E;
+ }
+ if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) {
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ return MEMORY_E;
+ }
+ if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) {
+ WOLFSSL_MSG("Not enough memory to create fixed IO buffers");
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ return MEMORY_E;
+ }
+ wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ }
+ #ifdef WOLFSSL_HEAP_TEST
+ }
+ #endif
+ }
+ else {
+ ssl->heap = ctx->heap;
+ }
+#else
+ ssl->heap = ctx->heap; /* carry over user heap without static memory */
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+ 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;
+
+#ifdef KEEP_PEER_CERT
+ InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+
+ ssl->rfd = -1; /* set to invalid descriptor */
+ ssl->wfd = -1;
+ ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */
+
+ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */
+ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
+
+#ifdef HAVE_NETX
+ ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */
+ ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */
+#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+ ssl->mnCtx = mynewt_ctx_new();
+ if(!ssl->mnCtx) {
return MEMORY_E;
}
- XMEMSET(ssl->arrays, 0, sizeof(Arrays));
+ ssl->IOCB_ReadCtx = ssl->mnCtx; /* default Mynewt IO ctx, same for read */
+ ssl->IOCB_WriteCtx = ssl->mnCtx; /* and write */
+#elif defined (WOLFSSL_GNRC)
+ ssl->IOCB_ReadCtx = ssl->gnrcCtx;
+ ssl->IOCB_WriteCtx = ssl->gnrcCtx;
+#endif
+ /* 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;
+ ssl->encrypt.state = CIPHER_STATE_BEGIN;
+ ssl->decrypt.state = CIPHER_STATE_BEGIN;
+#ifndef NO_DH
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ ssl->options.dhDoKeyTest = 1;
+ #endif
+#endif
-#ifndef NO_PSK
- if (ctx->server_hint[0]) { /* set in CTX */
- XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
- ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
+#ifdef WOLFSSL_DTLS
+ #ifdef WOLFSSL_SCTP
+ ssl->options.dtlsSctp = ctx->dtlsSctp;
+ #endif
+ #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
+ ssl->dtlsMtuSz = ctx->dtlsMtuSz;
+ ssl->dtls_expected_rx = ssl->dtlsMtuSz;
+ #else
+ ssl->dtls_expected_rx = MAX_MTU;
+ #endif
+ ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT;
+ ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX;
+ ssl->dtls_timeout = ssl->dtls_timeout_init;
+ ssl->buffers.dtlsCtx.rfd = -1;
+ ssl->buffers.dtlsCtx.wfd = -1;
+#endif
+
+#ifndef WOLFSSL_AEAD_ONLY
+ #ifndef NO_OLD_TLS
+ ssl->hmac = SSL_hmac; /* default to SSLv3 */
+ #elif !defined(WOLFSSL_NO_TLS12)
+ ssl->hmac = TLS_hmac;
+ #endif
+#endif
+
+
+ ssl->cipher.ssl = ssl;
+
+#ifdef HAVE_EXTENDED_MASTER
+ ssl->options.haveEMS = ctx->haveEMS;
+#endif
+ ssl->options.useClientOrder = ctx->useClientOrder;
+ ssl->options.mutualAuth = ctx->mutualAuth;
+
+#ifdef WOLFSSL_TLS13
+ #ifdef HAVE_SESSION_TICKET
+ ssl->options.noTicketTls13 = ctx->noTicketTls13;
+ #endif
+ ssl->options.noPskDheKe = ctx->noPskDheKe;
+ #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
+ #endif
+
+ if (ctx->numGroups > 0) {
+ XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups);
+ ssl->numGroups = ctx->numGroups;
}
-#endif /* NO_PSK */
+#endif
- /* RNG */
- ssl->rng = (RNG*)XMALLOC(sizeof(RNG), ssl->heap, DYNAMIC_TYPE_RNG);
- if (ssl->rng == NULL) {
- WOLFSSL_MSG("RNG Memory error");
+#ifdef HAVE_TLS_EXTENSIONS
+#ifdef HAVE_MAX_FRAGMENT
+ ssl->max_fragment = MAX_RECORD_SIZE;
+#endif
+#ifdef HAVE_ALPN
+ ssl->alpn_client_list = NULL;
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ ssl->alpnSelect = ctx->alpnSelect;
+ ssl->alpnSelectArg = ctx->alpnSelectArg;
+ #endif
+#endif
+#ifdef HAVE_SUPPORTED_CURVES
+ ssl->options.userCurves = ctx->userCurves;
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
+#endif
+
+ /* 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;
+
+#ifdef OPENSSL_EXTRA
+ /* copy over application session context ID */
+ ssl->sessionCtxSz = ctx->sessionCtxSz;
+ XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
+ ssl->cbioFlag = ctx->cbioFlag;
+
+#endif
+
+ InitCiphers(ssl);
+ InitCipherSpecs(&ssl->specs);
+
+ /* all done with init, now can return errors, call other stuff */
+
+ if (!writeDup) {
+ /* arrays */
+ ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
+ DYNAMIC_TYPE_ARRAYS);
+ if (ssl->arrays == NULL) {
+ WOLFSSL_MSG("Arrays Memory error");
+ return MEMORY_E;
+ }
+ XMEMSET(ssl->arrays, 0, sizeof(Arrays));
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER)
+ ssl->arrays->preMasterSz = ENCRYPT_LEN;
+ ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
+ DYNAMIC_TYPE_SECRET);
+ if (ssl->arrays->preMasterSecret == NULL) {
+ return MEMORY_E;
+ }
+ XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+#endif
+
+#ifdef OPENSSL_EXTRA
+ if ((ssl->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+ sizeof(WOLFSSL_X509_VERIFY_PARAM),
+ ssl->heap, DYNAMIC_TYPE_OPENSSL)) == NULL) {
+ WOLFSSL_MSG("ssl->param memory error");
return MEMORY_E;
}
+ XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+#endif
- if ( (ret = wc_InitRng(ssl->rng)) != 0) {
- WOLFSSL_MSG("RNG Init error");
+#ifdef SINGLE_THREADED
+ if (ctx->suites == NULL)
+#endif
+ {
+ /* suites */
+ ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+ DYNAMIC_TYPE_SUITES);
+ if (ssl->suites == NULL) {
+ WOLFSSL_MSG("Suites Memory error");
+ return MEMORY_E;
+ }
+ #ifdef OPENSSL_ALL
+ ssl->suites->stack = NULL;
+ #endif
+#ifdef SINGLE_THREADED
+ ssl->options.ownSuites = 1;
+#endif
+ }
+#ifdef SINGLE_THREADED
+ else {
+ ssl->options.ownSuites = 0;
+ }
+#endif
+ }
+
+ /* Initialize SSL with the appropriate fields from it's ctx */
+ /* requires valid arrays and suites unless writeDup ing */
+ if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS)
return ret;
+
+ ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
+
+#ifdef SINGLE_THREADED
+ ssl->rng = ctx->rng; /* CTX may have one, if so use it */
+#endif
+
+ if (ssl->rng == NULL) {
+ /* RNG */
+ ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
+ if (ssl->rng == NULL) {
+ WOLFSSL_MSG("RNG Memory error");
+ return MEMORY_E;
+ }
+ XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
+ ssl->options.weOwnRng = 1;
+
+ /* FIPS RNG API does not accept a heap hint */
+#ifndef HAVE_FIPS
+ if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) {
+ WOLFSSL_MSG("RNG Init error");
+ return ret;
+ }
+#else
+ if ( (ret = wc_InitRng(ssl->rng)) != 0) {
+ WOLFSSL_MSG("RNG Init error");
+ return ret;
+ }
+#endif
}
- /* suites */
- ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
- DYNAMIC_TYPE_SUITES);
- if (ssl->suites == NULL) {
- WOLFSSL_MSG("Suites Memory error");
- return MEMORY_E;
+#ifdef HAVE_WRITE_DUP
+ if (writeDup) {
+ /* all done */
+ return 0;
}
- if (ctx->suites)
- *ssl->suites = *ctx->suites;
- else
- XMEMSET(ssl->suites, 0, sizeof(Suites));
+#endif
+ /* hsHashes */
+ ret = InitHandshakeHashes(ssl);
+ if (ret != 0)
+ return ret;
-#ifndef NO_CERTS
- /* make sure server has cert and key unless using PSK or Anon */
- if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
- if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer) {
- WOLFSSL_MSG("Server missing certificate and/or private key");
- return NO_PRIVATE_KEY;
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+ if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
+ ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
+ if (ret != 0) {
+ WOLFSSL_MSG("DTLS Cookie Secret error");
+ return ret;
}
-#endif
+ }
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
#ifdef HAVE_SECRET_CALLBACK
ssl->sessionSecretCb = NULL;
ssl->sessionSecretCtx = NULL;
+#ifdef WOLFSSL_TLS13
+ ssl->tls13SecretCb = NULL;
+ ssl->tls13SecretCtx = NULL;
+#endif
#endif
- /* make sure server has DH parms, and add PSK if there, add NTRU too */
- if (ssl->options.side == WOLFSSL_SERVER_END)
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
- ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
- else
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
- ssl->options.haveNTRU, ssl->options.haveECDSAsig,
- ssl->options.haveStaticECC, ssl->options.side);
+#ifdef HAVE_SESSION_TICKET
+ ssl->session.ticket = ssl->session.staticTicket;
+#endif
+
+#ifdef WOLFSSL_MULTICAST
+ if (ctx->haveMcast) {
+ int i;
+
+ ssl->options.haveMcast = 1;
+ ssl->options.mcastID = ctx->mcastID;
+
+ /* Force the state to look like handshake has completed. */
+ /* Keying material is supplied externally. */
+ ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+ ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+ ssl->options.connectState = SECOND_REPLY_DONE;
+ ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ ssl->options.handShakeDone = 1;
+
+ for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++)
+ ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID;
+ }
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ int useSecureReneg = ssl->ctx->useSecureReneg;
+ /* use secure renegotiation by default (not recommend) */
+ #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
+ useSecureReneg = 1;
+ #endif
+ if (useSecureReneg) {
+ ret = wolfSSL_UseSecureRenegotiation(ssl);
+ if (ret != WOLFSSL_SUCCESS)
+ return ret;
+ }
+ }
+#endif /* HAVE_SECURE_RENEGOTIATION */
return 0;
}
@@ -1730,15 +5916,300 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
/* free use of temporary arrays */
void FreeArrays(WOLFSSL* ssl, int keep)
{
- if (ssl->arrays && keep) {
- /* keeps session id for user retrieval */
- XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
- ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
+ if (ssl->arrays) {
+ if (keep) {
+ /* keeps session id for user retrieval */
+ XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
+ ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
+ }
+ if (ssl->arrays->preMasterSecret) {
+ 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;
+ ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */
}
XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays = NULL;
}
+void FreeKey(WOLFSSL* ssl, int type, void** pKey)
+{
+ if (ssl && pKey && *pKey) {
+ switch (type) {
+ #ifndef NO_RSA
+ case DYNAMIC_TYPE_RSA:
+ wc_FreeRsaKey((RsaKey*)*pKey);
+ break;
+ #endif /* ! NO_RSA */
+ #ifdef HAVE_ECC
+ case DYNAMIC_TYPE_ECC:
+ wc_ecc_free((ecc_key*)*pKey);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case DYNAMIC_TYPE_ED25519:
+ wc_ed25519_free((ed25519_key*)*pKey);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_CURVE25519
+ case DYNAMIC_TYPE_CURVE25519:
+ wc_curve25519_free((curve25519_key*)*pKey);
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_ED448
+ case DYNAMIC_TYPE_ED448:
+ wc_ed448_free((ed448_key*)*pKey);
+ break;
+ #endif /* HAVE_ED448 */
+ #ifdef HAVE_CURVE448
+ case DYNAMIC_TYPE_CURVE448:
+ wc_curve448_free((curve448_key*)*pKey);
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifndef NO_DH
+ case DYNAMIC_TYPE_DH:
+ wc_FreeDhKey((DhKey*)*pKey);
+ break;
+ #endif /* !NO_DH */
+ default:
+ break;
+ }
+ XFREE(*pKey, ssl->heap, type);
+
+ /* Reset pointer */
+ *pKey = NULL;
+ }
+}
+
+int AllocKey(WOLFSSL* ssl, int type, void** pKey)
+{
+ int ret = BAD_FUNC_ARG;
+ int sz = 0;
+
+ if (ssl == NULL || pKey == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* Sanity check key destination */
+ if (*pKey != NULL) {
+ WOLFSSL_MSG("Key already present!");
+ return BAD_STATE_E;
+ }
+
+ /* Determine size */
+ switch (type) {
+ #ifndef NO_RSA
+ case DYNAMIC_TYPE_RSA:
+ sz = sizeof(RsaKey);
+ break;
+ #endif /* ! NO_RSA */
+ #ifdef HAVE_ECC
+ case DYNAMIC_TYPE_ECC:
+ sz = sizeof(ecc_key);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case DYNAMIC_TYPE_ED25519:
+ sz = sizeof(ed25519_key);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_CURVE25519
+ case DYNAMIC_TYPE_CURVE25519:
+ sz = sizeof(curve25519_key);
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_ED448
+ case DYNAMIC_TYPE_ED448:
+ sz = sizeof(ed448_key);
+ break;
+ #endif /* HAVE_ED448 */
+ #ifdef HAVE_CURVE448
+ case DYNAMIC_TYPE_CURVE448:
+ sz = sizeof(curve448_key);
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifndef NO_DH
+ case DYNAMIC_TYPE_DH:
+ sz = sizeof(DhKey);
+ break;
+ #endif /* !NO_DH */
+ default:
+ return BAD_FUNC_ARG;
+ }
+
+ if (sz == 0) {
+ return NOT_COMPILED_IN;
+ }
+
+ /* Allocate memory for key */
+ *pKey = XMALLOC(sz, ssl->heap, type);
+ if (*pKey == NULL) {
+ return MEMORY_E;
+ }
+
+ /* Initialize key */
+ switch (type) {
+ #ifndef NO_RSA
+ case DYNAMIC_TYPE_RSA:
+ ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* ! NO_RSA */
+ #ifdef HAVE_ECC
+ case DYNAMIC_TYPE_ECC:
+ ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case DYNAMIC_TYPE_ED25519:
+ wc_ed25519_init((ed25519_key*)*pKey);
+ ret = 0;
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_CURVE25519
+ case DYNAMIC_TYPE_CURVE25519:
+ wc_curve25519_init((curve25519_key*)*pKey);
+ ret = 0;
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_ED448
+ case DYNAMIC_TYPE_ED448:
+ wc_ed448_init((ed448_key*)*pKey);
+ ret = 0;
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifdef HAVE_CURVE448
+ case DYNAMIC_TYPE_CURVE448:
+ wc_curve448_init((curve448_key*)*pKey);
+ ret = 0;
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifndef NO_DH
+ case DYNAMIC_TYPE_DH:
+ ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* !NO_DH */
+ default:
+ return BAD_FUNC_ARG;
+ }
+
+ /* On error free handshake key */
+ if (ret != 0) {
+ FreeKey(ssl, type, pKey);
+ }
+
+ return ret;
+}
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_CURVE25519) || defined(HHAVE_ED448) || defined(HAVE_CURVE448)
+static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
+{
+ int ret = 0;
+
+ (void)ssl;
+
+ switch (type) {
+ #ifndef NO_RSA
+ case DYNAMIC_TYPE_RSA:
+ wc_FreeRsaKey((RsaKey*)pKey);
+ ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* ! NO_RSA */
+ #ifdef HAVE_ECC
+ case DYNAMIC_TYPE_ECC:
+ wc_ecc_free((ecc_key*)pKey);
+ ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case DYNAMIC_TYPE_ED25519:
+ wc_ed25519_free((ed25519_key*)pKey);
+ ret = wc_ed25519_init((ed25519_key*)pKey);
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_CURVE25519
+ case DYNAMIC_TYPE_CURVE25519:
+ wc_curve25519_free((curve25519_key*)pKey);
+ ret = wc_curve25519_init((curve25519_key*)pKey);
+ break;
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_ED448
+ case DYNAMIC_TYPE_ED448:
+ wc_ed448_free((ed448_key*)pKey);
+ ret = wc_ed448_init((ed448_key*)pKey);
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifdef HAVE_CURVE448
+ case DYNAMIC_TYPE_CURVE448:
+ wc_curve448_free((curve448_key*)pKey);
+ ret = wc_curve448_init((curve448_key*)pKey);
+ break;
+ #endif /* HAVE_CURVE448 */
+ #ifndef NO_DH
+ case DYNAMIC_TYPE_DH:
+ wc_FreeDhKey((DhKey*)pKey);
+ ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId);
+ break;
+ #endif /* !NO_DH */
+ default:
+ return BAD_FUNC_ARG;
+ }
+
+ return ret;
+}
+#endif
+
+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) {
+ XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST);
+ ssl->buffers.digest.buffer = NULL;
+ ssl->buffers.digest.length = 0;
+ }
+
+ /* Free handshake key */
+ FreeKey(ssl, ssl->hsType, &ssl->hsKey);
+
+#ifndef NO_DH
+ /* Free temp DH key */
+ FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key);
+#endif
+
+ /* Cleanup async */
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ssl->async.freeArgs) {
+ ssl->async.freeArgs(ssl, ssl->async.args);
+ ssl->async.freeArgs = NULL;
+ }
+#endif
+}
+
+
+/* Free up all memory used by Suites structure from WOLFSSL */
+void FreeSuites(WOLFSSL* ssl)
+{
+#ifdef SINGLE_THREADED
+ if (ssl->options.ownSuites)
+#endif
+ {
+ #ifdef OPENSSL_ALL
+ wolfSSL_sk_SSL_CIPHER_free(ssl->suites->stack);
+ #endif
+ XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
+ }
+ ssl->suites = NULL;
+}
+
/* In case holding SSL object in array and don't want to free actual ssl */
void SSL_ResourceFree(WOLFSSL* ssl)
@@ -1751,78 +6222,146 @@ void SSL_ResourceFree(WOLFSSL* ssl)
FreeCiphers(ssl);
FreeArrays(ssl, 0);
- wc_FreeRng(ssl->rng);
- XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
- XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
- XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
+ FreeKeyExchange(ssl);
+ if (ssl->options.weOwnRng) {
+ wc_FreeRng(ssl->rng);
+ XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+ }
+ FreeSuites(ssl);
+ FreeHandshakeHashes(ssl);
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+ /* clear keys struct after session */
+ ForceZero(&ssl->keys, sizeof(Keys));
+
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret));
+ ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
+ }
+#endif
+
#ifndef NO_DH
- XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_Priv.buffer) {
+ ForceZero(ssl->buffers.serverDH_Priv.buffer,
+ ssl->buffers.serverDH_Priv.length);
+ }
+ XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+ XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
/* parameters (p,g) may be owned by ctx */
- if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ if (ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
-#endif
+#endif /* !NO_DH */
#ifndef NO_CERTS
- if (ssl->buffers.weOwnCert)
- XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
- if (ssl->buffers.weOwnCertChain)
- XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
- if (ssl->buffers.weOwnKey)
- XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
+ ssl->keepCert = 0; /* make sure certificate is free'd */
+ wolfSSL_UnloadCertsKeys(ssl);
#endif
#ifndef NO_RSA
- if (ssl->peerRsaKey) {
- wc_FreeRsaKey(ssl->peerRsaKey);
- XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
- }
+ FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+ ssl->peerRsaKeyPresent = 0;
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+ XFREE(ssl->peerTsipEncRsaKeyIndex, ssl->heap, DYNAMIC_TYPE_RSA);
#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)
+ XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
+ DYNAMIC_TYPE_COOKIE_PWD);
+#endif
#ifdef WOLFSSL_DTLS
- if (ssl->dtls_pool != NULL) {
- DtlsPoolReset(ssl);
- XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE);
- }
- if (ssl->dtls_msg_list != NULL) {
- DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap);
- ssl->dtls_msg_list = NULL;
+ DtlsMsgPoolReset(ssl);
+ if (ssl->dtls_rx_msg_list != NULL) {
+ DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+ ssl->dtls_rx_msg_list = NULL;
+ ssl->dtls_rx_msg_list_sz = 0;
}
XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
+#ifndef NO_WOLFSSL_SERVER
+ XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
+ DYNAMIC_TYPE_COOKIE_PWD);
#endif
-#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
- FreeX509(&ssl->peerCert);
-#endif
-#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
- wolfSSL_BIO_free(ssl->biord);
- if (ssl->biord != ssl->biowr) /* in case same as write */
+#endif /* WOLFSSL_DTLS */
+#ifdef OPENSSL_EXTRA
+ if (ssl->biord != ssl->biowr) /* only free write if different */
wolfSSL_BIO_free(ssl->biowr);
+ wolfSSL_BIO_free(ssl->biord); /* always free read bio */
+ ssl->biowr = NULL;
+ ssl->biord = NULL;
#endif
#ifdef HAVE_LIBZ
FreeStreams(ssl);
#endif
#ifdef HAVE_ECC
- if (ssl->peerEccKey) {
- if (ssl->peerEccKeyPresent)
- wc_ecc_free(ssl->peerEccKey);
- XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
- }
- if (ssl->peerEccDsaKey) {
- if (ssl->peerEccDsaKeyPresent)
- wc_ecc_free(ssl->peerEccDsaKey);
- XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
- }
- if (ssl->eccTempKey) {
- if (ssl->eccTempKeyPresent)
- wc_ecc_free(ssl->eccTempKey);
- XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
- }
+ FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+ ssl->peerEccDsaKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) ||defined(HAVE_CURVE448)
+ {
+ int dtype = 0;
+ #ifdef HAVE_ECC
+ dtype = DYNAMIC_TYPE_ECC;
+ #endif
+ #ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent
+ #ifdef HAVE_ECC
+ || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519
+ #endif /* HAVE_ECC */
+ )
+ {
+ dtype = DYNAMIC_TYPE_CURVE25519;
+ }
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent
+ #ifdef HAVE_ECC
+ || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448
+ #endif /* HAVE_ECC */
+ )
+ {
+ dtype = DYNAMIC_TYPE_CURVE448;
+ }
+ #endif /* HAVE_CURVE448 */
+ FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+ ssl->eccTempKeyPresent = 0;
+ }
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#ifdef HAVE_CURVE25519
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+#endif
+#ifdef HAVE_ED25519
+ FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
+ ssl->peerEd25519KeyPresent = 0;
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->buffers.peerEd25519Key.buffer != NULL) {
+ XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+ DYNAMIC_TYPE_ED25519);
+ ssl->buffers.peerEd25519Key.buffer = NULL;
+ }
+ #endif
+#endif
+#ifdef HAVE_CURVE448
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+#endif
+#ifdef HAVE_ED448
+ FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key);
+ ssl->peerEd448KeyPresent = 0;
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->buffers.peerEd448Key.buffer != NULL) {
+ XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap,
+ DYNAMIC_TYPE_ED448);
+ ssl->buffers.peerEd448Key.buffer = NULL;
+ }
+ #endif
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
@@ -1833,38 +6372,105 @@ void SSL_ResourceFree(WOLFSSL* ssl)
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
#ifdef HAVE_TLS_EXTENSIONS
- TLSX_FreeAll(ssl->extensions);
+ TLSX_FreeAll(ssl->extensions, ssl->heap);
+
+#ifdef HAVE_ALPN
+ if (ssl->alpn_client_list != NULL) {
+ XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
+ ssl->alpn_client_list = NULL;
+ }
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+ if (ssl->mnCtx) {
+ mynewt_ctx_clear(ssl->mnCtx);
+ ssl->mnCtx = NULL;
+ }
#endif
#ifdef HAVE_NETX
if (ssl->nxCtx.nxPacket)
nx_packet_release(ssl->nxCtx.nxPacket);
#endif
-}
+#ifdef KEEP_PEER_CERT
+ FreeX509(&ssl->peerCert);
+#endif
-#ifdef WOLFSSL_TI_HASH
-static void HashFinal(WOLFSSL * ssl) {
- byte dummyHash[32] ;
-#ifndef NO_MD5
- wc_Md5Final(&(ssl->hsHashes->hashMd5), dummyHash) ;
+#ifdef HAVE_SESSION_TICKET
+ if (ssl->session.isDynamic) {
+ XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ ssl->session.ticket = ssl->session.staticTicket;
+ ssl->session.isDynamic = 0;
+ ssl->session.ticketLen = 0;
+ }
#endif
-#ifndef NO_SHA
- wc_ShaFinal(&(ssl->hsHashes->hashSha), dummyHash) ;
+#ifdef HAVE_EXT_CACHE
+ wolfSSL_SESSION_free(ssl->extSession);
#endif
-#ifndef NO_SHA256
- wc_Sha256Final(&(ssl->hsHashes->hashSha256), dummyHash) ;
+#ifdef HAVE_WRITE_DUP
+ if (ssl->dupWrite) {
+ FreeWriteDup(ssl);
+ }
+#endif
+#ifdef OPENSSL_EXTRA
+ if (ssl->param) {
+ XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
+ }
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ while (ssl->certReqCtx != NULL) {
+ CertReqCtx* curr = ssl->certReqCtx;
+ ssl->certReqCtx = curr->next;
+ XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#endif
-}
-#else
- #define HashFinal(ssl)
+#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
+ WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
+ WOLFSSL_HEAP* ctx_heap;
+ void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
+ ctx_heap = ssl_hint->memory;
+ if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+ WOLFSSL_MSG("Bad memory_mutex lock");
+ }
+ 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");
+ }
+ if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/
+ ctx_heap->curHa--;
+ }
+ wc_UnLockMutex(&(ctx_heap->memory_mutex));
+
+ /* check if tracking stats */
+ if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
+ XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
+ }
+ XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
+ #ifdef WOLFSSL_HEAP_TEST
+ }
+ #endif
+ }
+#endif /* WOLFSSL_STATIC_MEMORY */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ wolfSSL_sk_CIPHER_free(ssl->supportedCiphers);
+ wolfSSL_sk_X509_free(ssl->peerCertChain);
#endif
+}
/* Free any handshake resources no longer needed */
void FreeHandshakeResources(WOLFSSL* ssl)
{
- HashFinal(ssl) ;
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
@@ -1876,100 +6482,147 @@ void FreeHandshakeResources(WOLFSSL* ssl)
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, NO_FORCED_FREE);
- /* suites */
- XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
- ssl->suites = NULL;
-
- /* hsHashes */
- XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
- ssl->hsHashes = NULL;
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ if (!ssl->options.tls1_3)
+#endif
+ {
+ #ifndef OPENSSL_ALL
+ /* free suites unless using compatibility layer */
+ FreeSuites(ssl);
+ #endif
+ /* hsHashes */
+ FreeHandshakeHashes(ssl);
+ }
/* RNG */
- if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) {
- wc_FreeRng(ssl->rng);
- XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
- ssl->rng = NULL;
+ if (ssl->options.tls1_1 == 0
+#ifndef WOLFSSL_AEAD_ONLY
+ || ssl->specs.cipher_type == stream
+#endif
+#if defined(WOLFSSL_TLS13)
+ #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ || ssl->options.tls1_3
+ #elif !defined(HAVE_SESSION_TICKET)
+ || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_SERVER_END)
+ #endif
+#endif
+ ) {
+ if (ssl->options.weOwnRng) {
+ wc_FreeRng(ssl->rng);
+ XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+ ssl->rng = NULL;
+ ssl->options.weOwnRng = 0;
+ }
}
#ifdef WOLFSSL_DTLS
/* DTLS_POOL */
- if (ssl->options.dtls && ssl->dtls_pool != NULL) {
- DtlsPoolReset(ssl);
- XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
- ssl->dtls_pool = NULL;
+ if (ssl->options.dtls) {
+ DtlsMsgPoolReset(ssl);
+ DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+ ssl->dtls_rx_msg_list = NULL;
+ ssl->dtls_rx_msg_list_sz = 0;
}
#endif
- /* arrays */
- if (ssl->options.saveArrays == 0)
- FreeArrays(ssl, 1);
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \
+ defined(HAVE_SESSION_TICKET)
+ if (!ssl->options.tls1_3)
+#endif
+ /* arrays */
+ if (ssl->options.saveArrays == 0)
+ FreeArrays(ssl, 1);
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END)
+#endif
+ {
#ifndef NO_RSA
- /* peerRsaKey */
- if (ssl->peerRsaKey) {
- wc_FreeRsaKey(ssl->peerRsaKey);
- XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
- ssl->peerRsaKey = NULL;
- }
+ /* peerRsaKey */
+ FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+ ssl->peerRsaKeyPresent = 0;
#endif
-
#ifdef HAVE_ECC
- if (ssl->peerEccKey)
- {
- if (ssl->peerEccKeyPresent) {
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- }
- XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->peerEccKey = NULL;
- }
- if (ssl->peerEccDsaKey)
- {
- if (ssl->peerEccDsaKeyPresent) {
- wc_ecc_free(ssl->peerEccDsaKey);
- ssl->peerEccDsaKeyPresent = 0;
- }
- XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->peerEccDsaKey = NULL;
+ FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+ ssl->peerEccDsaKeyPresent = 0;
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
+ ssl->peerEd25519KeyPresent = 0;
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key);
+ ssl->peerEd448KeyPresent = 0;
+#endif /* HAVE_ED448 */
}
- if (ssl->eccTempKey)
+
+#ifdef HAVE_ECC
+ FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
{
- if (ssl->eccTempKeyPresent) {
- wc_ecc_free(ssl->eccTempKey);
- ssl->eccTempKeyPresent = 0;
- }
- XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->eccTempKey = NULL;
+ int dtype;
+ #ifdef HAVE_ECC
+ dtype = DYNAMIC_TYPE_ECC;
+ #endif
+ #ifdef HAVE_CURVE25519
+ #ifdef HAVE_ECC
+ if (ssl->peerX25519KeyPresent ||
+ ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+ #endif /* HAVE_ECC */
+ {
+ dtype = DYNAMIC_TYPE_CURVE25519;
+ }
+ #endif /* HAVE_CURVE25519 */
+ #ifdef HAVE_CURVE448
+ #ifdef HAVE_ECC
+ if (ssl->peerX448KeyPresent ||
+ ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448)
+ #endif /* HAVE_ECC */
+ {
+ dtype = DYNAMIC_TYPE_CURVE448;
+ }
+ #endif /* HAVE_CURVE448 */
+ FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+ ssl->eccTempKeyPresent = 0;
}
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#ifdef HAVE_CURVE25519
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+#endif
+#ifdef HAVE_CURVE448
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
#endif
+
#ifndef NO_DH
- XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_Priv.buffer) {
+ ForceZero(ssl->buffers.serverDH_Priv.buffer,
+ ssl->buffers.serverDH_Priv.length);
+ }
+ XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
ssl->buffers.serverDH_Priv.buffer = NULL;
- XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ssl->buffers.serverDH_Pub.buffer = NULL;
/* parameters (p,g) may be owned by ctx */
- if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ if (ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ssl->buffers.serverDH_G.buffer = NULL;
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ssl->buffers.serverDH_P.buffer = NULL;
}
-#endif
+#endif /* !NO_DH */
+
#ifndef NO_CERTS
- if (ssl->buffers.weOwnCert) {
- XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
- ssl->buffers.certificate.buffer = NULL;
- }
- if (ssl->buffers.weOwnCertChain) {
- XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
- ssl->buffers.certChain.buffer = NULL;
- }
- if (ssl->buffers.weOwnKey) {
- XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
- ssl->buffers.key.buffer = NULL;
- }
+ wolfSSL_UnloadCertsKeys(ssl);
#endif
#ifdef HAVE_PK_CALLBACKS
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END)
+#endif
+ {
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->buffers.peerEccDsaKey.buffer = NULL;
@@ -1978,134 +6631,196 @@ void FreeHandshakeResources(WOLFSSL* ssl)
XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
ssl->buffers.peerRsaKey.buffer = NULL;
#endif /* NO_RSA */
+ #ifdef HAVE_ED25519
+ XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+ DYNAMIC_TYPE_ED25519);
+ ssl->buffers.peerEd25519Key.buffer = NULL;
+ #endif
+ #ifdef HAVE_ED448
+ XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap, DYNAMIC_TYPE_ED448);
+ ssl->buffers.peerEd448Key.buffer = NULL;
+ #endif
+ }
#endif /* HAVE_PK_CALLBACKS */
-}
-
-void FreeSSL(WOLFSSL* ssl)
-{
- FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
- SSL_ResourceFree(ssl);
- XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
-}
+#ifdef HAVE_QSH
+ QSH_FreeAll(ssl);
+#endif
+#ifdef HAVE_SESSION_TICKET
+ if (ssl->session.isDynamic) {
+ XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ ssl->session.ticket = ssl->session.staticTicket;
+ ssl->session.isDynamic = 0;
+ ssl->session.ticketLen = 0;
+ }
+#endif
-#ifdef WOLFSSL_DTLS
+#if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \
+ !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ /* Some extensions need to be kept for post-handshake querying. */
+ TLSX_FreeAll(ssl->extensions, ssl->heap);
+ ssl->extensions = NULL;
+#endif
-int DtlsPoolInit(WOLFSSL* ssl)
-{
- if (ssl->dtls_pool == NULL) {
- DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool),
- ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
- if (pool == NULL) {
- WOLFSSL_MSG("DTLS Buffer Pool Memory error");
- return MEMORY_E;
- }
- else {
- int i;
+#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;
- for (i = 0; i < DTLS_POOL_SZ; i++) {
- pool->buf[i].length = 0;
- pool->buf[i].buffer = NULL;
- }
- pool->used = 0;
- ssl->dtls_pool = pool;
+ ctx_heap = ssl_hint->memory;
+ if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+ WOLFSSL_MSG("Bad memory_mutex lock");
}
+ ctx_heap->curHa--;
+ ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */
+ wc_UnLockMutex(&(ctx_heap->memory_mutex));
+ #ifdef WOLFSSL_HEAP_TEST
}
- return 0;
+ #endif
+ }
+#endif /* WOLFSSL_STATIC_MEMORY */
}
-int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz)
+/* heap argument is the heap hint used when creating SSL */
+void FreeSSL(WOLFSSL* ssl, void* heap)
{
- DtlsPool *pool = ssl->dtls_pool;
- if (pool != NULL && pool->used < DTLS_POOL_SZ) {
- buffer *pBuf = &pool->buf[pool->used];
- pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
- if (pBuf->buffer == NULL) {
- WOLFSSL_MSG("DTLS Buffer Memory error");
- return MEMORY_ERROR;
- }
- XMEMCPY(pBuf->buffer, src, sz);
- pBuf->length = (word32)sz;
- pool->used++;
+ if (ssl->ctx) {
+ FreeSSL_Ctx(ssl->ctx); /* will decrement and free underlying CTX if 0 */
}
- return 0;
+ SSL_ResourceFree(ssl);
+ XFREE(ssl, heap, DYNAMIC_TYPE_SSL);
+ (void)heap;
}
+#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \
+ ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \
+ && defined(HAVE_AEAD))
-void DtlsPoolReset(WOLFSSL* ssl)
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
{
- DtlsPool *pool = ssl->dtls_pool;
- if (pool != NULL) {
- buffer *pBuf;
- int i, used;
-
- used = pool->used;
- for (i = 0, pBuf = &pool->buf[0]; i < used; i++, pBuf++) {
- XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
- pBuf->buffer = NULL;
- pBuf->length = 0;
+ 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++;
}
- pool->used = 0;
}
- ssl->dtls_timeout = ssl->dtls_timeout_init;
}
+#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */
-int DtlsPoolTimeout(WOLFSSL* ssl)
+#ifdef WOLFSSL_DTLS
+static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
{
- int result = -1;
- if (ssl->dtls_timeout < ssl->dtls_timeout_max) {
- ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
- result = 0;
+ if (order == PREV_ORDER) {
+ /* Previous epoch case */
+ if (ssl->options.haveMcast) {
+ #ifdef WOLFSSL_MULTICAST
+ seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) |
+ (ssl->options.mcastID << 8) |
+ (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;
+ }
+ 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);
+ #endif
+ }
+ else
+ 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) |
+ (ssl->options.mcastID << 8) |
+ (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;
}
- return result;
}
-
-int DtlsPoolSend(WOLFSSL* ssl)
+static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
{
- int ret;
- DtlsPool *pool = ssl->dtls_pool;
-
- if (pool != NULL && pool->used > 0) {
- int i;
- for (i = 0; i < pool->used; i++) {
- int sendResult;
- buffer* buf = &pool->buf[i];
-
- DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)buf->buffer;
+ word32 seq;
- word16 message_epoch;
- ato16(dtls->epoch, &message_epoch);
- if (message_epoch == ssl->keys.dtls_epoch) {
- /* Increment record sequence number on retransmitted handshake
- * messages */
- c32to48(ssl->keys.dtls_sequence_number, dtls->sequence_number);
- ssl->keys.dtls_sequence_number++;
- }
- else {
- /* The Finished message is sent with the next epoch, keep its
- * sequence number */
- }
-
- if ((ret = CheckAvailableSize(ssl, buf->length)) != 0)
- return ret;
+ if (order == PREV_ORDER) {
+ 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++;
+ }
+ }
+ else if (order == PEER_ORDER) {
+ seq = ssl->keys.peer_sequence_number_lo++;
+ if (seq > ssl->keys.peer_sequence_number_lo) {
+ /* handle rollover */
+ ssl->keys.peer_sequence_number_hi++;
+ }
+ }
+ else {
+ seq = ssl->keys.dtls_sequence_number_lo++;
+ if (seq > ssl->keys.dtls_sequence_number_lo) {
+ /* handle rollover */
+ ssl->keys.dtls_sequence_number_hi++;
+ }
+ }
+}
+#endif /* WOLFSSL_DTLS */
- XMEMCPY(ssl->buffers.outputBuffer.buffer, buf->buffer, buf->length);
- ssl->buffers.outputBuffer.idx = 0;
- ssl->buffers.outputBuffer.length = buf->length;
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+ word32 seq[2] = {0, 0};
- sendResult = SendBuffered(ssl);
- if (sendResult < 0) {
- return sendResult;
- }
- }
+ if (!ssl->options.dtls) {
+ GetSEQIncrement(ssl, verifyOrder, seq);
}
- return 0;
+ else {
+#ifdef WOLFSSL_DTLS
+ 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 ||
+ * ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM) && HAVE_AEAD) */
+#ifdef WOLFSSL_DTLS
/* functions for managing DTLS datagram reordering */
@@ -2116,18 +6831,18 @@ int DtlsPoolSend(WOLFSSL* ssl)
* extra space for the headers. */
DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
{
- DtlsMsg* msg = NULL;
+ DtlsMsg* msg;
+ (void)heap;
msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
if (msg != NULL) {
+ XMEMSET(msg, 0, sizeof(DtlsMsg));
msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
- heap, DYNAMIC_TYPE_NONE);
+ heap, DYNAMIC_TYPE_DTLS_BUFFER);
if (msg->buf != NULL) {
- msg->next = NULL;
- msg->seq = 0;
msg->sz = sz;
- msg->fragSz = 0;
+ msg->type = no_shake;
msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
}
else {
@@ -2144,8 +6859,14 @@ void DtlsMsgDelete(DtlsMsg* item, void* heap)
(void)heap;
if (item != NULL) {
+ DtlsFrag* cur = item->fragList;
+ while (cur != NULL) {
+ DtlsFrag* next = cur->next;
+ XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
+ cur = next;
+ }
if (item->buf != NULL)
- XFREE(item->buf, heap, DYNAMIC_TYPE_NONE);
+ XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
}
}
@@ -2162,32 +6883,128 @@ void DtlsMsgListDelete(DtlsMsg* head, void* heap)
}
-void DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
- word32 fragOffset, word32 fragSz)
+/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
+static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
+ byte* buf, word32* bytesLeft, void* heap)
+{
+ DtlsFrag* newFrag;
+ word32 added = end - *begin + 1;
+
+ (void)heap;
+ newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
+ DYNAMIC_TYPE_DTLS_FRAG);
+ if (newFrag != NULL) {
+ newFrag->next = NULL;
+ newFrag->begin = *begin;
+ newFrag->end = end;
+
+ XMEMCPY(buf + *begin, data, added);
+ *bytesLeft -= added;
+ *begin = newFrag->end + 1;
+ }
+
+ return newFrag;
+}
+
+
+int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
+ word32 fragOffset, word32 fragSz, void* heap)
{
if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
- fragOffset <= msg->sz && (fragOffset + fragSz) <= msg->sz) {
+ (fragOffset + fragSz) <= msg->sz) {
+ DtlsFrag* cur = msg->fragList;
+ DtlsFrag* prev = cur;
+ DtlsFrag* newFrag;
+ word32 bytesLeft = fragSz; /* could be overlapping fragment */
+ word32 startOffset = fragOffset;
+ word32 added;
msg->seq = seq;
msg->type = type;
- msg->fragSz += fragSz;
- /* If fragOffset is zero, this is either a full message that is out
- * of order, or the first fragment of a fragmented message. Copy the
- * handshake message header with the message data. Zero length messages
- * like Server Hello Done should be saved as well. */
- if (fragOffset == 0)
+
+ if (fragOffset == 0) {
XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
- fragSz + DTLS_HANDSHAKE_HEADER_SZ);
- else {
- /* If fragOffet is non-zero, this is an additional fragment that
- * needs to be copied to its location in the message buffer. Also
- * copy the total size of the message over the fragment size. The
- * hash routines look at a defragmented message if it had actually
- * come across as a single handshake message. */
- XMEMCPY(msg->msg + fragOffset, data, fragSz);
+ DTLS_HANDSHAKE_HEADER_SZ);
+ c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
+ }
+
+ /* if no message data, just return */
+ if (fragSz == 0)
+ return 0;
+
+ /* if list is empty add full fragment to front */
+ if (cur == NULL) {
+ newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
+ msg->msg, &bytesLeft, heap);
+ if (newFrag == NULL)
+ return MEMORY_E;
+
+ msg->fragSz = fragSz;
+ msg->fragList = newFrag;
+
+ return 0;
+ }
+
+ /* add to front if before current front, up to next->begin */
+ if (fragOffset < cur->begin) {
+ word32 end = fragOffset + fragSz - 1;
+
+ if (end >= cur->begin)
+ end = cur->begin - 1;
+
+ added = end - fragOffset + 1;
+ newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
+ &bytesLeft, heap);
+ if (newFrag == NULL)
+ return MEMORY_E;
+
+ msg->fragSz += added;
+
+ newFrag->next = cur;
+ msg->fragList = newFrag;
+ }
+
+ /* while we have bytes left, try to find a gap to fill */
+ while (bytesLeft > 0) {
+ /* get previous packet in list */
+ while (cur && (fragOffset >= cur->begin)) {
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* don't add duplicate data */
+ if (prev->end >= fragOffset) {
+ if ( (fragOffset + bytesLeft - 1) <= prev->end)
+ return 0;
+ fragOffset = prev->end + 1;
+ bytesLeft = startOffset + fragSz - fragOffset;
+ }
+
+ if (cur == NULL)
+ /* we're at the end */
+ added = bytesLeft;
+ else
+ /* we're in between two frames */
+ added = min(bytesLeft, cur->begin - fragOffset);
+
+ /* data already there */
+ if (added == 0)
+ continue;
+
+ newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
+ data + fragOffset - startOffset,
+ msg->msg, &bytesLeft, heap);
+ if (newFrag == NULL)
+ return MEMORY_E;
+
+ msg->fragSz += added;
+
+ newFrag->next = prev->next;
+ prev->next = newFrag;
}
- c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
}
+
+ return 0;
}
@@ -2200,44 +7017,60 @@ DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
}
-DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data,
+void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data,
word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap)
{
-
/* See if seq exists in the list. If it isn't in the list, make
* a new item of size dataSz, copy fragSz bytes from data to msg->msg
* starting at offset fragOffset, and add fragSz to msg->fragSz. If
* the seq is in the list and it isn't full, copy fragSz bytes from
* data to msg->msg starting at offset fragOffset, and add fragSz to
- * msg->fragSz. The new item should be inserted into the list in its
+ * msg->fragSz. Insertions take into account data already in the list
+ * in case there are overlaps in the handshake message due to retransmit
+ * messages. The new item should be inserted into the list in its
* proper position.
*
* 1. Find seq in list, or where seq should go in list. If seq not in
* list, create new item and insert into list. Either case, keep
* pointer to item.
- * 2. If msg->fragSz + fragSz < sz, copy data to msg->msg at offset
- * fragOffset. Add fragSz to msg->fragSz.
+ * 2. Copy the data from the message to the stored message where it
+ * belongs without overlaps.
*/
+ DtlsMsg* head = ssl->dtls_rx_msg_list;
+
if (head != NULL) {
DtlsMsg* cur = DtlsMsgFind(head, seq);
if (cur == NULL) {
cur = DtlsMsgNew(dataSz, heap);
if (cur != NULL) {
- DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz);
- head = DtlsMsgInsert(head, cur);
+ if (DtlsMsgSet(cur, seq, data, type,
+ fragOffset, fragSz, heap) < 0) {
+ DtlsMsgDelete(cur, heap);
+ }
+ else {
+ ssl->dtls_rx_msg_list_sz++;
+ head = DtlsMsgInsert(head, cur);
+ }
}
}
else {
- DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz);
+ /* If this fails, the data is just dropped. */
+ DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap);
}
}
else {
head = DtlsMsgNew(dataSz, heap);
- DtlsMsgSet(head, seq, data, type, fragOffset, fragSz);
+ if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) {
+ DtlsMsgDelete(head, heap);
+ head = NULL;
+ }
+ else {
+ ssl->dtls_rx_msg_list_sz++;
+ }
}
- return head;
+ ssl->dtls_rx_msg_list = head;
}
@@ -2271,9 +7104,202 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
return head;
}
+
+/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */
+int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz)
+{
+ DtlsMsg* item;
+ int ret = 0;
+
+ WOLFSSL_ENTER("DtlsMsgPoolSave()");
+
+ if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ) {
+ WOLFSSL_ERROR(DTLS_POOL_SZ_E);
+ return DTLS_POOL_SZ_E;
+ }
+
+ item = DtlsMsgNew(dataSz, ssl->heap);
+
+ if (item != NULL) {
+ DtlsMsg* cur = ssl->dtls_tx_msg_list;
+
+ XMEMCPY(item->buf, data, dataSz);
+ item->sz = dataSz;
+ item->seq = ssl->keys.dtls_epoch;
+
+ if (cur == NULL)
+ ssl->dtls_tx_msg_list = item;
+ else {
+ while (cur->next)
+ cur = cur->next;
+ cur->next = item;
+ }
+ ssl->dtls_tx_msg_list_sz++;
+ }
+ else
+ ret = MEMORY_E;
+
+ WOLFSSL_LEAVE("DtlsMsgPoolSave()", ret);
+ return ret;
+}
+
+
+/* DtlsMsgPoolTimeout() updates the timeout time. */
+int DtlsMsgPoolTimeout(WOLFSSL* ssl)
+{
+ int result = -1;
+ if (ssl->dtls_timeout < ssl->dtls_timeout_max) {
+ ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
+ result = 0;
+ }
+ WOLFSSL_LEAVE("DtlsMsgPoolTimeout()", result);
+ return result;
+}
+
+
+/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout
+ * value. */
+void DtlsMsgPoolReset(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("DtlsMsgPoolReset()");
+ if (ssl->dtls_tx_msg_list) {
+ DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap);
+ ssl->dtls_tx_msg_list = NULL;
+ ssl->dtls_tx_msg = NULL;
+ ssl->dtls_tx_msg_list_sz = 0;
+ ssl->dtls_timeout = ssl->dtls_timeout_init;
+ }
+}
+
+
+int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset)
+{
+ /**
+ * only the first message from previous flight should be valid
+ * to be used for triggering retransmission of whole DtlsMsgPool.
+ * change cipher suite type is not verified here
+ */
+ return ((fragOffset == 0) &&
+ (((ssl->options.side == WOLFSSL_SERVER_END) &&
+ ((type == client_hello) ||
+ ((ssl->options.verifyPeer) && (type == certificate)) ||
+ ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) ||
+ ((ssl->options.side == WOLFSSL_CLIENT_END) &&
+ (type == server_hello))));
+}
+
+
+/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is
+ * updated with new sequence numbers, and will be re-encrypted if needed. */
+int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
+{
+ int ret = 0;
+ DtlsMsg* pool;
+
+ WOLFSSL_ENTER("DtlsMsgPoolSend()");
+
+ pool = ssl->dtls_tx_msg == NULL ? ssl->dtls_tx_msg_list : ssl->dtls_tx_msg;
+
+ if (pool != NULL) {
+ if ((ssl->options.side == WOLFSSL_SERVER_END &&
+ !(ssl->options.acceptState == SERVER_HELLO_DONE ||
+ ssl->options.acceptState == ACCEPT_FINISHED_DONE ||
+ ssl->options.acceptState == ACCEPT_THIRD_REPLY_DONE)) ||
+ (ssl->options.side == WOLFSSL_CLIENT_END &&
+ !(ssl->options.connectState == CLIENT_HELLO_SENT ||
+ ssl->options.connectState == HELLO_AGAIN_REPLY ||
+ ssl->options.connectState == FINISHED_DONE ||
+ ssl->options.connectState == SECOND_REPLY_DONE))) {
+
+ WOLFSSL_ERROR(DTLS_RETX_OVER_TX);
+ ssl->error = DTLS_RETX_OVER_TX;
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ while (pool != NULL) {
+ if (pool->seq == 0) {
+ DtlsRecordLayerHeader* dtls;
+ int epochOrder;
+
+ dtls = (DtlsRecordLayerHeader*)pool->buf;
+ /* If the stored record's epoch is 0, and the currently set
+ * epoch is 0, use the "current order" sequence number.
+ * 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) ?
+ CUR_ORDER : PREV_ORDER;
+
+ WriteSEQ(ssl, epochOrder, dtls->sequence_number);
+ DtlsSEQIncrement(ssl, epochOrder);
+ if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) {
+ WOLFSSL_ERROR(ret);
+ return ret;
+ }
+
+ XMEMCPY(ssl->buffers.outputBuffer.buffer,
+ pool->buf, pool->sz);
+ ssl->buffers.outputBuffer.idx = 0;
+ ssl->buffers.outputBuffer.length = pool->sz;
+ }
+ else if (pool->seq == ssl->keys.dtls_epoch) {
+ byte* input;
+ byte* output;
+ int inputSz, sendSz;
+
+ input = pool->buf;
+ inputSz = pool->sz;
+ sendSz = inputSz + MAX_MSG_EXTRA;
+
+ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
+ WOLFSSL_ERROR(ret);
+ return ret;
+ }
+
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 0, 0, 0);
+ if (sendSz < 0) {
+ WOLFSSL_ERROR(BUILD_MSG_ERROR);
+ return BUILD_MSG_ERROR;
+ }
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ }
+
+ ret = SendBuffered(ssl);
+ if (ret < 0) {
+ WOLFSSL_ERROR(ret);
+ return ret;
+ }
+
+ /**
+ * on server side, retransmission is being triggered only by sending
+ * first message of given flight, in order to trigger client
+ * to retransmit its whole flight. Sending the whole previous flight
+ * could lead to retransmission of previous client flight for each
+ * server message from previous flight. Therefore one message should
+ * be enough to do the trick.
+ */
+ if (sendOnlyFirstPacket &&
+ ssl->options.side == WOLFSSL_SERVER_END) {
+
+ pool = NULL;
+ }
+ else
+ pool = pool->next;
+ ssl->dtls_tx_msg = pool;
+ }
+ }
+
+ WOLFSSL_LEAVE("DtlsMsgPoolSend()", ret);
+ return ret;
+}
+
#endif /* WOLFSSL_DTLS */
-#ifndef NO_OLD_TLS
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
ProtocolVersion MakeSSLv3(void)
{
@@ -2284,7 +7310,7 @@ ProtocolVersion MakeSSLv3(void)
return pv;
}
-#endif /* NO_OLD_TLS */
+#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
#ifdef WOLFSSL_DTLS
@@ -2298,6 +7324,8 @@ ProtocolVersion MakeDTLSv1(void)
return pv;
}
+#ifndef WOLFSSL_NO_TLS12
+
ProtocolVersion MakeDTLSv1_2(void)
{
ProtocolVersion pv;
@@ -2307,12 +7335,38 @@ ProtocolVersion MakeDTLSv1_2(void)
return pv;
}
+#endif /* !WOLFSSL_NO_TLS12 */
+
#endif /* WOLFSSL_DTLS */
+#ifndef NO_ASN_TIME
+#if defined(USER_TICKS)
+#if 0
+ word32 LowResTimer(void)
+ {
+ /*
+ write your own clock tick function if don't want time(0)
+ needs second accuracy but doesn't have to correlated to EPOCH
+ */
+ }
+#endif
+#elif defined(TIME_OVERRIDES)
+
+ /* use same asn time overrides unless user wants tick override above */
-#ifdef USE_WINDOWS_API
+ #ifndef HAVE_TIME_T_TYPE
+ typedef long time_t;
+ #endif
+ extern time_t XTIME(time_t * timer);
+
+ word32 LowResTimer(void)
+ {
+ return (word32) XTIME(0);
+ }
+
+#elif defined(USE_WINDOWS_API)
word32 LowResTimer(void)
{
@@ -2339,17 +7393,26 @@ ProtocolVersion MakeDTLSv1_2(void)
return (word32)rtp_get_system_sec();
}
+#elif defined(WOLFSSL_DEOS)
+
+ word32 LowResTimer(void)
+ {
+ const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
+ uint32_t *systemTickPtr = systemTickPointer();
+
+ return (word32) *systemTickPtr/systemTickTimeInHz;
+ }
#elif defined(MICRIUM)
word32 LowResTimer(void)
{
- NET_SECURE_OS_TICK clk;
+ OS_TICK ticks = 0;
+ OS_ERR err;
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- clk = NetSecure_OS_TimeGet();
- #endif
- return (word32)clk;
+ ticks = OSTimeGet(&err);
+
+ return (word32) (ticks / OSCfg_TickRate_Hz);
}
@@ -2357,7 +7420,7 @@ ProtocolVersion MakeDTLSv1_2(void)
word32 LowResTimer(void)
{
- return (word32) TickGet();
+ return (word32) (TickGet() / TICKS_PER_SECOND);
}
@@ -2369,19 +7432,20 @@ ProtocolVersion MakeDTLSv1_2(void)
word32 LowResTimer(void)
{
- return (word32) SYS_TMR_TickCountGet();
+ return (word32) (SYS_TMR_TickCountGet() /
+ SYS_TMR_TickCounterFrequencyGet());
}
#else
word32 LowResTimer(void)
{
- return (word32) SYS_TICK_Get();
+ return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet());
}
#endif
-#elif defined(FREESCALE_MQX)
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
word32 LowResTimer(void)
{
@@ -2391,6 +7455,31 @@ ProtocolVersion MakeDTLSv1_2(void)
return (word32) mqxTime.SECONDS;
}
+#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+
+ #include "include/task.h"
+
+ unsigned int LowResTimer(void)
+ {
+ return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
+ }
+
+#elif defined(FREERTOS)
+
+ #include "task.h"
+
+ unsigned int LowResTimer(void)
+ {
+ return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
+ }
+
+#elif defined(FREESCALE_KSDK_BM)
+
+ #include "lwip/sys.h" /* lwIP */
+ word32 LowResTimer(void)
+ {
+ return sys_now()/1000;
+ }
#elif defined(WOLFSSL_TIRTOS)
@@ -2398,49 +7487,172 @@ ProtocolVersion MakeDTLSv1_2(void)
{
return (word32) Seconds_get();
}
+#elif defined(WOLFSSL_XILINX)
+ #include "xrtcpsu.h"
-#elif defined(USER_TICKS)
-#if 0
word32 LowResTimer(void)
{
- /*
- write your own clock tick function if don't want time(0)
- needs second accuracy but doesn't have to correlated to EPOCH
- */
+ XRtcPsu_Config* con;
+ XRtcPsu rtc;
+
+ con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
+ if (con != NULL) {
+ if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr)
+ == XST_SUCCESS) {
+ return (word32)XRtcPsu_GetCurrentTime(&rtc);
+ }
+ else {
+ WOLFSSL_MSG("Unable to initialize RTC");
+ }
+ }
+
+ return 0;
}
-#endif
-#elif defined(TIME_OVERRIDES)
+#elif defined(WOLFSSL_UTASKER)
- /* use same asn time overrides unless user wants tick override above */
+ word32 LowResTimer(void)
+ {
+ return (word32)(uTaskerSystemTick / TICK_RESOLUTION);
+ }
- #ifndef HAVE_TIME_T_TYPE
- typedef long time_t;
- #endif
- extern time_t XTIME(time_t * timer);
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+
+ #define NU_TICKS_PER_SECOND 100
word32 LowResTimer(void)
{
- return (word32) XTIME(0);
+ /* returns number of 10ms ticks, so 100 ticks/sec */
+ return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND;
+ }
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+
+ #include "os/os_time.h"
+ word32 LowResTimer(void)
+ {
+ word32 now;
+ struct os_timeval tv;
+ os_gettimeofday(&tv, NULL);
+ now = (word32)tv.tv_sec;
+ return now;
}
-#else /* !USE_WINDOWS_API && !HAVE_RTP_SYS && !MICRIUM && !USER_TICKS */
+#elif defined(WOLFSSL_ZEPHYR)
+ word32 LowResTimer(void)
+ {
+ return k_uptime_get() / 1000;
+ }
+
+#else
+ /* Posix style time */
+ #if !defined(USER_TIME) && !defined(USE_WOLF_TM)
#include <time.h>
+ #endif
word32 LowResTimer(void)
{
- return (word32)time(0);
+ return (word32)XTIME(0);
+ }
+#endif
+#endif /* !NO_ASN_TIME */
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+/* Store the message for use with CertificateVerify using EdDSA.
+ *
+ * ssl SSL/TLS object.
+ * data Message to store.
+ * sz Size of message to store.
+ * returns MEMORY_E if not able to reallocate, otherwise 0.
+ */
+static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz)
+{
+ int ret = 0;
+ byte* msgs;
+
+ if (ssl->options.cacheMessages) {
+ msgs = (byte*)XREALLOC(ssl->hsHashes->messages,
+ ssl->hsHashes->length + sz,
+ ssl->heap, DYNAMIC_TYPE_HASHES);
+ if (msgs == NULL)
+ ret = MEMORY_E;
+ if (ret == 0) {
+ ssl->hsHashes->messages = msgs;
+ XMEMCPY(msgs + ssl->hsHashes->length, data, sz);
+ ssl->hsHashes->prevLen = ssl->hsHashes->length;
+ ssl->hsHashes->length += sz;
+ }
}
+ return ret;
+}
+#endif /* (HAVE_ED25519 || HAVE_ED448) && !WOLFSSL_NO_CLIENT_AUTH */
+
+#ifndef NO_CERTS
+int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
+{
+ int ret = 0;
+
+ (void)output;
+ (void)sz;
-#endif /* USE_WINDOWS_API */
+ if (ssl->hsHashes == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef HAVE_FUZZER
+ if (ssl->fuzzerCb)
+ ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
+#endif
+#ifndef NO_OLD_TLS
+ #ifndef NO_SHA
+ wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
+ #endif
+ #ifndef NO_MD5
+ wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
+ #endif
+#endif /* NO_OLD_TLS */
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ #ifndef NO_SHA256
+ ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
+ if (ret != 0)
+ return ret;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
+ if (ret != 0)
+ return ret;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
+ if (ret != 0)
+ return ret;
+ #endif
+ #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ ret = EdDSA_Update(ssl, output, sz);
+ if (ret != 0)
+ return ret;
+ #endif
+ }
+
+ return ret;
+}
+#endif /* NO_CERTS */
/* add output to md5 and sha handshake hashes, exclude record header */
-static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
+int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
{
- const byte* adj = output + RECORD_HEADER_SZ + ivSz;
+ int ret = 0;
+ const byte* adj;
+
+ if (ssl->hsHashes == NULL)
+ return BAD_FUNC_ARG;
+
+ adj = output + RECORD_HEADER_SZ + ivSz;
sz -= RECORD_HEADER_SZ;
#ifdef HAVE_FUZZER
@@ -2454,44 +7666,54 @@ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
}
#endif
#ifndef NO_OLD_TLS
-#ifndef NO_SHA
- wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
-#endif
-#ifndef NO_MD5
- wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
-#endif
+ #ifndef NO_SHA
+ wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+ #endif
+ #ifndef NO_MD5
+ wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+ #endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
- int ret;
-
-#ifndef NO_SHA256
+ #ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
-#endif
-#ifdef WOLFSSL_SHA384
+ #endif
+ #ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
-#endif
-#ifdef WOLFSSL_SHA512
+ #endif
+ #ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
-#endif
+ #endif
+ #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ ret = EdDSA_Update(ssl, adj, sz);
+ if (ret != 0)
+ return ret;
+ #endif
}
- return 0;
+ return ret;
}
/* add input to md5 and sha handshake hashes, include handshake header */
-static int HashInput(WOLFSSL* ssl, const byte* input, int sz)
+int HashInput(WOLFSSL* ssl, const byte* input, int sz)
{
- const byte* adj = input - HANDSHAKE_HEADER_SZ;
+ int ret = 0;
+ const byte* adj;
+
+ adj = input - HANDSHAKE_HEADER_SZ;
sz += HANDSHAKE_HEADER_SZ;
+ (void)adj;
+
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
adj -= DTLS_HANDSHAKE_EXTRA;
@@ -2499,36 +7721,45 @@ static int HashInput(WOLFSSL* ssl, const byte* input, int sz)
}
#endif
+ if (ssl->hsHashes == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
#ifndef NO_OLD_TLS
-#ifndef NO_SHA
- wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
-#endif
-#ifndef NO_MD5
- wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
-#endif
+ #ifndef NO_SHA
+ wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+ #endif
+ #ifndef NO_MD5
+ wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+ #endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
- int ret;
-
-#ifndef NO_SHA256
+ #ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
-#endif
-#ifdef WOLFSSL_SHA384
+ #endif
+ #ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
-#endif
-#ifdef WOLFSSL_SHA512
+ #endif
+ #ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
-#endif
+ #endif
+ #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ ret = EdDSA_Update(ssl, adj, sz);
+ if (ret != 0)
+ return ret;
+ #endif
}
- return 0;
+ return ret;
}
@@ -2539,35 +7770,65 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl
/* 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_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+#ifdef WOLFSSL_TLS13_DRAFT_18
+ rl->pvMinor = TLSv1_MINOR;
+#else
+ rl->pvMinor = TLSv1_2_MINOR;
+#endif
+ }
+ else
+#endif
+ 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
- if (!ssl->options.dtls)
+ if (!ssl->options.dtls) {
c16toa((word16)length, rl->length);
+ }
else {
#ifdef WOLFSSL_DTLS
DtlsRecordLayerHeader* dtls;
/* dtls record layer header extensions */
dtls = (DtlsRecordLayerHeader*)output;
- c16toa(ssl->keys.dtls_epoch, dtls->epoch);
- c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
+ WriteSEQ(ssl, 0, dtls->sequence_number);
c16toa((word16)length, dtls->length);
#endif
}
}
+#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, byte type,
- WOLFSSL* ssl)
+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
@@ -2577,44 +7838,79 @@ static void AddHandShakeHeader(byte* output, word32 length, byte type,
/* dtls handshake header extensions */
dtls = (DtlsHandShakeHeader*)output;
c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
- c32to24(0, dtls->fragment_offset);
- c32to24(length, dtls->fragment_length);
+ 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)
{
- if (!ssl->options.dtls) {
- AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
- AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, 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);
+ AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
+}
+#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */
+
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_SERVER) || \
+ !defined(WOLFSSL_NO_CLIENT_AUTH))
+static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
+ word32 length, byte type, WOLFSSL* ssl)
+{
+ word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+ word32 outputAdj = RECORD_HEADER_SZ;
+ (void)fragSz;
+
#ifdef WOLFSSL_DTLS
- else {
- AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
- AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
+ if (ssl->options.dtls) {
+ lengthAdj += DTLS_HANDSHAKE_EXTRA;
+ outputAdj += DTLS_RECORD_EXTRA;
}
#endif
+
+ AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl);
+ AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
}
+#endif /* NO_CERTS */
+#endif /* !WOLFSSL_NO_TLS12 */
/* return bytes received, -1 on error */
-static int Receive(WOLFSSL* ssl, byte* buf, word32 sz)
+static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
{
int recvd;
- if (ssl->ctx->CBIORecv == NULL) {
+ if (ssl->CBIORecv == NULL) {
WOLFSSL_MSG("Your IO Recv callback is null, please set");
return -1;
}
retry:
- recvd = ssl->ctx->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
- if (recvd < 0)
+ recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+ if (recvd < 0) {
switch (recvd) {
case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)
+ 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
return -1;
case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */
@@ -2639,6 +7935,9 @@ retry:
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;
}
@@ -2651,16 +7950,23 @@ retry:
return -1;
case WOLFSSL_CBIO_ERR_TIMEOUT:
-#ifdef WOLFSSL_DTLS
- if (DtlsPoolTimeout(ssl) == 0 && DtlsPoolSend(ssl) == 0)
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl) &&
+ !ssl->options.handShakeDone &&
+ DtlsMsgPoolTimeout(ssl) == 0 &&
+ DtlsMsgPoolSend(ssl, 0) == 0) {
+
+ /* retry read for DTLS during handshake only */
goto retry;
- else
-#endif
- return -1;
+ }
+ #endif
+ return -1;
default:
+ WOLFSSL_MSG("Unexpected recv return code");
return recvd;
}
+ }
return recvd;
}
@@ -2690,7 +7996,7 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
WOLFSSL_MSG("Shrinking input buffer\n");
- if (!forcedFree && usedLength)
+ if (!forcedFree && usedLength > 0)
XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
usedLength);
@@ -2707,13 +8013,21 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
int SendBuffered(WOLFSSL* ssl)
{
- if (ssl->ctx->CBIOSend == NULL) {
+ if (ssl->CBIOSend == NULL) {
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
+
while (ssl->buffers.outputBuffer.length > 0) {
- int sent = ssl->ctx->CBIOSend(ssl,
+ int sent = ssl->CBIOSend(ssl,
(char*)ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.idx,
(int)ssl->buffers.outputBuffer.length,
@@ -2738,6 +8052,9 @@ int SendBuffered(WOLFSSL* ssl)
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;
}
@@ -2775,12 +8092,18 @@ int SendBuffered(WOLFSSL* ssl)
/* Grow the output buffer */
-static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
+static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
{
byte* tmp;
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
RECORD_HEADER_SZ;
- byte align = WOLFSSL_GENERAL_ALIGNMENT;
+ byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#else
+ const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#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 */
@@ -2789,14 +8112,29 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
while (align < hdrSz)
align *= 2;
}
+#endif
- tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align,
- ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align,
+ ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
WOLFSSL_MSG("growing output buffer\n");
- if (!tmp) return MEMORY_E;
+ 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 =
+ size + ssl->buffers.outputBuffer.length;
+ return 0;
+ }
+#endif
if (ssl->buffers.outputBuffer.length)
XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
@@ -2807,10 +8145,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
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 = size +
ssl->buffers.outputBuffer.length;
@@ -2822,8 +8164,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
{
byte* tmp;
- byte hdrSz = DTLS_RECORD_HEADER_SZ;
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
+ 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
@@ -2833,13 +8181,34 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
while (align < hdrSz)
align *= 2;
}
- tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap,
- DYNAMIC_TYPE_IN_BUFFER);
+#endif
+
+ if (usedLength < 0 || size < 0) {
+ WOLFSSL_MSG("GrowInputBuffer() called with negative number");
+ return BAD_FUNC_ARG;
+ }
+
+ tmp = (byte*)XMALLOC(size + usedLength + align,
+ ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
WOLFSSL_MSG("growing input buffer\n");
- if (!tmp) return MEMORY_E;
+ 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 +
@@ -2850,10 +8219,13 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
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;
@@ -2866,7 +8238,6 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
/* check available size into output buffer, make room if needed */
int CheckAvailableSize(WOLFSSL *ssl, int size)
{
-
if (size < 0) {
WOLFSSL_MSG("CheckAvailableSize() called with negative number");
return BAD_FUNC_ARG;
@@ -2898,46 +8269,78 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
else {
#ifdef WOLFSSL_DTLS
+#ifdef HAVE_FUZZER
+ if (ssl->fuzzerCb)
+ ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
+ FUZZ_HEAD, ssl->fuzzerCtx);
+#endif
/* type and version in same sport */
XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
*inOutIdx += ENUM_LEN + VERSION_SZ;
- ato16(input + *inOutIdx, &ssl->keys.dtls_state.curEpoch);
- *inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */
- ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq);
- *inOutIdx += 4; /* advance past rest of seq */
+ ato16(input + *inOutIdx, &ssl->keys.curEpoch);
+ *inOutIdx += OPAQUE16_LEN;
+ if (ssl->options.haveMcast) {
+ #ifdef WOLFSSL_MULTICAST
+ ssl->keys.curPeerId = input[*inOutIdx];
+ ssl->keys.curSeq_hi = input[*inOutIdx+1];
+ #endif
+ }
+ else
+ ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
+ *inOutIdx += OPAQUE16_LEN;
+ ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
+ *inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
-#ifdef HAVE_FUZZER
- if (ssl->fuzzerCb)
- ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN -
- VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ,
- FUZZ_HEAD, ssl->fuzzerCtx);
-#endif
#endif
}
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl) && !DtlsCheckWindow(ssl)) {
+ WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR);
+ return SEQUENCE_ERROR;
+ }
+#endif
+
/* catch version mismatch */
- if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){
+#ifndef WOLFSSL_TLS13
+ if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor)
+#else
+ if (rh->pvMajor != ssl->version.major ||
+ (rh->pvMinor != ssl->version.minor &&
+#ifdef WOLFSSL_TLS13_DRAFT_18
+ (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR)
+#else
+ (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR)
+#endif
+ ))
+#endif
+ {
if (ssl->options.side == WOLFSSL_SERVER_END &&
- ssl->options.acceptState == ACCEPT_BEGIN)
+ 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 if (ssl->options.dtls && rh->type == handshake)
+ /* Check the DTLS handshake message RH version later. */
+ WOLFSSL_MSG("DTLS handshake, skip RH version number check");
else {
WOLFSSL_MSG("SSL version error");
+ /* send alert per RFC5246 Appendix E. Backward Compatibility */
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+#ifdef WOLFSSL_MYSQL_COMPATIBLE
+ SendAlert(ssl, alert_fatal, wc_protocol_version);
+#else
+ SendAlert(ssl, alert_fatal, protocol_version);
+#endif
+ }
return VERSION_ERROR; /* only use requested version */
}
}
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if (DtlsCheckWindow(&ssl->keys.dtls_state) != 1)
- return SEQUENCE_ERROR;
- }
-#endif
-
/* record layer length check */
#ifdef HAVE_MAX_FRAGMENT
if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
@@ -2968,7 +8371,7 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return 0;
}
-
+#ifndef WOLFSSL_NO_TLS12
static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
byte *type, word32 *size, word32 totalSz)
{
@@ -2984,7 +8387,7 @@ static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return 0;
}
-
+#endif
#ifdef WOLFSSL_DTLS
static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
@@ -2995,12 +8398,14 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
word32 idx = *inOutIdx;
*inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
- if (*inOutIdx > totalSz)
+ if (*inOutIdx > totalSz) {
+ WOLFSSL_ERROR(BUFFER_E);
return BUFFER_E;
+ }
*type = input[idx++];
c24to32(input + idx, size);
- idx += BYTE3_LEN;
+ idx += OPAQUE24_LEN;
ato16(input + idx, &ssl->keys.dtls_peer_handshake_number);
idx += DTLS_HANDSHAKE_SEQ_SZ;
@@ -3009,12 +8414,24 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
idx += DTLS_HANDSHAKE_FRAG_SZ;
c24to32(input + idx, fragSz);
+ if (ssl->curRL.pvMajor != ssl->version.major ||
+ ssl->curRL.pvMinor != ssl->version.minor) {
+
+ if (*type != client_hello && *type != hello_verify_request) {
+ WOLFSSL_ERROR(VERSION_ERROR);
+ return VERSION_ERROR;
+ }
+ else {
+ WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version");
+ }
+ }
return 0;
}
#endif
-#ifndef NO_OLD_TLS
+#if !defined(NO_OLD_TLS) || \
+ (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1))
/* fill with MD5 pad size since biggest required */
static const byte PAD1[PAD_MD5] =
{ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
@@ -3032,116 +8449,116 @@ static const byte PAD2[PAD_MD5] =
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
};
+#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */
+
+#ifndef NO_OLD_TLS
/* calculate MD5 hash for finished */
#ifdef WOLFSSL_TI_HASH
#include <wolfssl/wolfcrypt/hash.h>
#endif
-static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
{
-
- byte md5_result[MD5_DIGEST_SIZE];
-
+ int ret;
+ byte md5_result[WC_MD5_DIGEST_SIZE];
#ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+ if (md5 == NULL)
+ return MEMORY_E;
#else
- Md5 md5[1];
- Md5 md5_2[1];
+ wc_Md5 md5[1];
#endif
/* make md5 inner */
- md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */
-
- wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER);
- wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN);
- wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5);
- wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result);
- wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */
+ ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, sender, SIZEOF_SENDER);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+ if (ret == 0)
+ ret = wc_Md5Final(md5, md5_result);
/* make md5 outer */
- wc_InitMd5(md5_2) ;
- wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN);
- wc_Md5Update(md5_2, PAD2, PAD_MD5);
- wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE);
- wc_Md5Final(md5_2, hashes->md5);
+ if (ret == 0) {
+ ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+ if (ret == 0) {
+ ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+ if (ret == 0)
+ ret = wc_Md5Final(md5, hashes->md5);
+ wc_Md5Free(md5);
+ }
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
#endif
+ return ret;
}
/* calculate SHA hash for finished */
-static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
{
- byte sha_result[SHA_DIGEST_SIZE];
-
+ int ret;
+ byte sha_result[WC_SHA_DIGEST_SIZE];
#ifdef WOLFSSL_SMALL_STACK
- Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+ if (sha == NULL)
+ return MEMORY_E;
#else
- Sha sha[1];
- Sha sha2[1] ;
+ wc_Sha sha[1];
#endif
/* make sha inner */
- sha[0] = ssl->hsHashes->hashSha ; /* Save current position */
-
- wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER);
- wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN);
- wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA);
- wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result);
- wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */
+ ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+ if (ret == 0)
+ ret = wc_ShaFinal(sha, sha_result);
/* make sha outer */
- wc_InitSha(sha2) ;
- wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN);
- wc_ShaUpdate(sha2, PAD2, PAD_SHA);
- wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE);
- wc_ShaFinal(sha2, hashes->sha);
+ if (ret == 0) {
+ ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+ if (ret == 0) {
+ ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+ if (ret == 0)
+ ret = wc_ShaFinal(sha, hashes->sha);
+ wc_ShaFree(sha);
+ }
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
#endif
+ return ret;
}
#endif
+#ifndef WOLFSSL_NO_TLS12
+
/* Finished doesn't support SHA512, not SHA512 cipher suites yet */
static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
{
int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- #ifdef WOLFSSL_SHA384
- Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
-#else
- #ifdef WOLFSSL_SHA384
- Sha384 sha384[1];
- #endif
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ssl == NULL
- #ifdef WOLFSSL_SHA384
- || sha384 == NULL
- #endif
- ) {
- #ifdef WOLFSSL_SHA384
- XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return MEMORY_E;
- }
-#endif
- /* store current states, building requires get_digest which resets state */
-#ifdef WOLFSSL_SHA384
- sha384[0] = ssl->hsHashes->hashSha384;
-#endif
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
#ifndef NO_TLS
if (ssl->options.tls) {
@@ -3150,37 +8567,29 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
#endif
#ifndef NO_OLD_TLS
if (!ssl->options.tls) {
- BuildMD5(ssl, hashes, sender);
- BuildSHA(ssl, hashes, sender);
- }
-#endif
-
- /* restore */
- if (IsAtLeastTLSv1_2(ssl)) {
- #ifdef WOLFSSL_SHA384
- ssl->hsHashes->hashSha384 = sha384[0];
- #endif
+ ret = BuildMD5(ssl, hashes, sender);
+ if (ret == 0) {
+ ret = BuildSHA(ssl, hashes, sender);
+ }
}
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SHA384
- XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
#endif
return ret;
}
+#endif /* WOLFSSL_NO_TLS12 */
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
/* cipher requirements */
enum {
REQUIRES_RSA,
REQUIRES_DHE,
- REQUIRES_ECC_DSA,
+ REQUIRES_ECC,
REQUIRES_ECC_STATIC,
REQUIRES_PSK,
REQUIRES_NTRU,
- REQUIRES_RSA_SIG
+ REQUIRES_RSA_SIG,
+ REQUIRES_AEAD
};
@@ -3191,17 +8600,21 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
static int CipherRequires(byte first, byte second, int requirement)
{
+ (void)requirement;
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CHACHA
if (first == CHACHA_BYTE) {
switch (second) {
-
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
@@ -3211,15 +8624,55 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_DHE)
return 1;
break;
+
+ case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+ if (requirement == REQUIRES_RSA)
+ return 1;
+ break;
+
+ case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+ if (requirement == REQUIRES_ECC)
+ return 1;
+ break;
+
+ case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+ if (requirement == REQUIRES_RSA)
+ return 1;
+ if (requirement == REQUIRES_DHE)
+ return 1;
+ break;
+
+
+ case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ break;
+
+ case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ break;
+
+ case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ if (requirement == REQUIRES_DHE)
+ return 1;
+ break;
}
+
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+
}
+#endif /* HAVE_CHACHA */
/* ECC extensions */
if (first == ECC_BYTE) {
switch (second) {
-
-#ifndef NO_RSA
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ #ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
@@ -3232,7 +8685,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
break;
-#ifndef NO_DES3
+ #ifndef NO_DES3
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
@@ -3244,9 +8697,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
-#endif
+ #endif /* !NO_DES3 */
-#ifndef NO_RC4
+ #ifndef NO_RC4
case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_RSA)
return 1;
@@ -3258,12 +8711,12 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
-#endif
-#endif /* NO_RSA */
+ #endif /* !NO_RC4 */
+ #endif /* NO_RSA */
-#ifndef NO_DES3
+ #ifndef NO_DES3
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
@@ -3271,10 +8724,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
-#endif
-#ifndef NO_RC4
+ #endif /* !NO_DES3 */
+ #ifndef NO_RC4
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
@@ -3282,8 +8735,8 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
-#endif
-#ifndef NO_RSA
+ #endif /* !NO_RC4 */
+ #ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
@@ -3295,10 +8748,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
-#endif
+ #endif /* !NO_RSA */
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
@@ -3308,7 +8761,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
@@ -3318,34 +8771,48 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
break;
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
#ifndef NO_RSA
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
@@ -3353,6 +8820,8 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
@@ -3360,22 +8829,27 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
-
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #ifdef HAVE_AESCCM
case TLS_RSA_WITH_AES_128_CCM_8 :
case TLS_RSA_WITH_AES_256_CCM_8 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
+ #endif /* HAVE_AESCCM */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
- if (requirement == REQUIRES_RSA_SIG)
- return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
@@ -3385,34 +8859,43 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
-#endif
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#endif /* !NO_RSA */
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
- if (requirement == REQUIRES_ECC_DSA)
+ if (requirement == REQUIRES_ECC)
return 1;
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#ifndef NO_PSK
case TLS_PSK_WITH_AES_128_CCM:
case TLS_PSK_WITH_AES_256_CCM:
case TLS_PSK_WITH_AES_128_CCM_8:
case TLS_PSK_WITH_AES_256_CCM_8:
if (requirement == REQUIRES_PSK)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_DHE_PSK_WITH_AES_128_CCM:
@@ -3421,41 +8904,92 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+ break;
+#endif /* !NO_PSK */
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
+ if (requirement == REQUIRES_ECC)
+ return 1;
+ break;
+
+ case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
break;
+ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+ case TLS_SHA256_SHA256:
+ break;
+ case TLS_SHA384_SHA384:
+ break;
+#endif
+
default:
WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
return 0;
} /* switch */
} /* if */
- if (first != ECC_BYTE) { /* normal suites */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+ /* Distinct TLS v1.3 cipher suites with cipher and digest only. */
+ if (first == TLS13_BYTE) {
+
+ switch (second) {
+#ifdef WOLFSSL_TLS13
+ case TLS_AES_128_GCM_SHA256:
+ case TLS_AES_256_GCM_SHA384:
+ case TLS_CHACHA20_POLY1305_SHA256:
+ case TLS_AES_128_CCM_SHA256:
+ case TLS_AES_128_CCM_8_SHA256:
+ break;
+#endif
+
+ default:
+ WOLFSSL_MSG("Unsupported cipher suite, CipherRequires "
+ "TLS v1.3");
+ return 0;
+ }
+ }
+
+#ifndef WOLFSSL_NO_TLS12
+
+ if (first != ECC_BYTE && first != CHACHA_BYTE &&
+ first != TLS13_BYTE) { /* normal suites */
switch (second) {
#ifndef NO_RSA
+ #ifndef NO_RC4
case SSL_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
- case TLS_NTRU_RSA_WITH_RC4_128_SHA :
- if (requirement == REQUIRES_NTRU)
- return 1;
- break;
-
case SSL_RSA_WITH_RC4_128_MD5 :
if (requirement == REQUIRES_RSA)
return 1;
break;
+ #endif /* NO_RC4 */
case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
- case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+ #ifdef HAVE_NTRU
+ case TLS_NTRU_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
+ #endif /* HAVE_NTRU */
case TLS_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_RSA)
@@ -3467,35 +9001,67 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
break;
- case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ #ifdef HAVE_NTRU
+ case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
+ #endif /* HAVE_NTRU */
case TLS_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
+ #ifdef HAVE_NTRU
+ case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ if (requirement == REQUIRES_NTRU)
+ return 1;
+ break;
+ #endif /* HAVE_NTRU */
+
case TLS_RSA_WITH_AES_256_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
+ case TLS_RSA_WITH_NULL_MD5 :
case TLS_RSA_WITH_NULL_SHA :
case TLS_RSA_WITH_NULL_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
+ #ifdef HAVE_NTRU
case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
-#endif
+ #endif /* HAVE_NTRU */
+
+ #ifdef HAVE_IDEA
+ case SSL_RSA_WITH_IDEA_CBC_SHA :
+ if (requirement == REQUIRES_RSA)
+ return 1;
+ break;
+ #endif /* HAVE_IDEA */
+#endif /* !NO_RSA */
+#ifndef NO_PSK
case TLS_PSK_WITH_AES_128_GCM_SHA256 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+ break;
+
case TLS_PSK_WITH_AES_256_GCM_SHA384 :
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+ break;
+
case TLS_PSK_WITH_AES_128_CBC_SHA256 :
case TLS_PSK_WITH_AES_256_CBC_SHA384 :
case TLS_PSK_WITH_AES_128_CBC_SHA :
@@ -3509,6 +9075,14 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
+ if (requirement == REQUIRES_DHE)
+ return 1;
+ if (requirement == REQUIRES_PSK)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+ break;
+
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 :
@@ -3518,6 +9092,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_PSK)
return 1;
break;
+#endif /* NO_PSK */
#ifndef NO_RSA
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
@@ -3548,6 +9123,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
break;
+#ifndef NO_HC128
case TLS_RSA_WITH_HC_128_MD5 :
if (requirement == REQUIRES_RSA)
return 1;
@@ -3557,27 +9133,21 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_RSA)
return 1;
break;
+#endif /* NO_HC128 */
- case TLS_RSA_WITH_HC_128_B2B256:
- if (requirement == REQUIRES_RSA)
- return 1;
- break;
-
- case TLS_RSA_WITH_AES_128_CBC_B2B256:
- case TLS_RSA_WITH_AES_256_CBC_B2B256:
- if (requirement == REQUIRES_RSA)
- return 1;
- break;
-
+#ifndef NO_RABBIT
case TLS_RSA_WITH_RABBIT_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
+#endif /* !NO_RABBIT */
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
case TLS_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
@@ -3586,8 +9156,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
break;
+#ifdef HAVE_CAMELLIA
case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
@@ -3607,12 +9180,32 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_DHE)
return 1;
break;
+#endif /* HAVE_CAMELLIA */
+
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ if (requirement == REQUIRES_RSA)
+ return 1;
+ if (requirement == REQUIRES_RSA_SIG)
+ return 1;
+ if (requirement == REQUIRES_DHE)
+ return 1;
+ break;
#endif
#ifdef HAVE_ANON
case TLS_DH_anon_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_DHE)
return 1;
break;
+ case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+ if (requirement == REQUIRES_DHE)
+ return 1;
+ if (requirement == REQUIRES_AEAD)
+ return 1;
+ break;
+#endif
+#ifdef WOLFSSL_MULTICAST
+ case WDM_WITH_NULL_SHA256 :
+ break;
#endif
default:
@@ -3621,20 +9214,25 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
} /* switch */
} /* if ECC / Normal suites else */
+#endif /* !WOLFSSL_NO_TLS12 */
+
return 0;
}
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+
#ifndef NO_CERTS
/* Match names with wildcards, each wildcard can represent a single name
- component or fragment but not mulitple names, i.e.,
+ component or fragment but not multiple names, i.e.,
*.z.com matches y.z.com but not x.y.z.com
return 1 on success */
-static int MatchDomainName(const char* pattern, int len, const char* str)
+int MatchDomainName(const char* pattern, int len, const char* str)
{
+ int ret = 0;
char p, s;
if (pattern == NULL || str == NULL || len <= 0)
@@ -3643,13 +9241,13 @@ static int MatchDomainName(const char* pattern, int len, const char* str)
while (len > 0) {
p = (char)XTOLOWER((unsigned char)*pattern++);
- if (p == 0)
+ if (p == '\0')
break;
if (p == '*') {
while (--len > 0 &&
- (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*')
- ;
+ (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') {
+ }
if (len == 0)
p = '\0';
@@ -3667,19 +9265,23 @@ static int MatchDomainName(const char* pattern, int len, const char* str)
return 0;
}
- if (*str != '\0')
- str++;
- if (len > 0)
+ if (len > 0) {
+ str++;
len--;
+ }
}
- return *str == '\0';
+ if (*str == '\0' && len == 0) {
+ ret = 1; /* success */
+ }
+
+ return ret;
}
/* try to find an altName match to domain, return 1 on success */
-static int CheckAltNames(DecodedCert* dCert, char* domain)
+int CheckAltNames(DecodedCert* dCert, char* domain)
{
int match = 0;
DNS_entry* altName = NULL;
@@ -3690,9 +9292,9 @@ static int CheckAltNames(DecodedCert* dCert, char* domain)
altName = dCert->altNames;
while (altName) {
- WOLFSSL_MSG(" individual AltName check");
+ WOLFSSL_MSG("\tindividual AltName check");
- if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){
+ if (MatchDomainName(altName->name, altName->len, domain)){
match = 1;
break;
}
@@ -3703,15 +9305,113 @@ static int CheckAltNames(DecodedCert* dCert, char* domain)
return match;
}
+#ifdef OPENSSL_EXTRA
+/* Check that alternative names, if they exists, match the domain.
+ * Fail if there are wild patterns and they didn't match.
+ * Check the common name if no alternative names matched.
+ *
+ * dCert Decoded cert to get the alternative names from.
+ * domain Domain name to compare against.
+ * checkCN Whether to check the common name.
+ * returns whether there was a problem in matching.
+ */
+static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN)
+{
+ int match;
+ DNS_entry* altName = NULL;
+
+ WOLFSSL_MSG("Checking AltNames");
+
+ if (dCert)
+ altName = dCert->altNames;
+
+ *checkCN = altName == NULL;
+ match = 0;
+ while (altName) {
+ WOLFSSL_MSG("\tindividual AltName check");
+
+ if (MatchDomainName(altName->name, altName->len, domain)) {
+ match = 1;
+ *checkCN = 0;
+ break;
+ }
+ /* No matches and wild pattern match failed. */
+ else if (altName->name && altName->len >=1 &&
+ altName->name[0] == '*' && match == 0) {
+ match = -1;
+ }
+
+ altName = altName->next;
+ }
+
+ return match != -1;
+}
+
+/* Check the domain name matches the subject alternative name or the subject
+ * name.
+ *
+ * dcert Decoded certificate.
+ * domainName The domain name.
+ * domainNameLen The length of the domain name.
+ * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success.
+ */
+int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen)
+{
+ int checkCN;
+
+ /* Assume name is NUL terminated. */
+ (void)domainNameLen;
+
+ if (CheckForAltNames(dCert, domainName, &checkCN) == 0) {
+ WOLFSSL_MSG("DomainName match on alt names failed too");
+ return DOMAIN_NAME_MISMATCH;
+ }
+ if (checkCN == 1) {
+ if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
+ domainName) == 0) {
+ WOLFSSL_MSG("DomainName match on common name failed");
+ return DOMAIN_NAME_MISMATCH;
+ }
+ }
+
+ return 0;
+}
+
+int CheckIPAddr(DecodedCert* dCert, char* ipasc)
+{
+ WOLFSSL_MSG("Checking IPAddr");
-#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
+ return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc));
+}
+#endif
+#ifdef SESSION_CERTS
+static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
+ byte* certBuf, word32 certSz)
+{
+ if (chain->count < MAX_CHAIN_DEPTH &&
+ certSz < MAX_X509_SIZE) {
+ chain->certs[chain->count].length = certSz;
+ XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz);
+ chain->count++;
+ }
+ else {
+ WOLFSSL_MSG("Couldn't store chain cert for session");
+ }
+}
+#endif
+
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
/* Copy parts X509 needs from Decoded cert, 0 on success */
+/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the
+ * altNames pointers could be free'd by second x509 still active by first */
int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
{
int ret = 0;
- if (x509 == NULL || dCert == NULL)
+ if (x509 == NULL || dCert == NULL ||
+ dCert->subjectCNLen < 0)
return BAD_FUNC_ARG;
x509->version = dCert->version + 1;
@@ -3719,36 +9419,47 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX);
x509->issuer.name[ASN_NAME_MAX - 1] = '\0';
x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1;
-#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (dCert->issuerName.fullName != NULL) {
XMEMCPY(&x509->issuer.fullName,
&dCert->issuerName, sizeof(DecodedName));
x509->issuer.fullName.fullName = (char*)XMALLOC(
- dCert->issuerName.fullNameLen, NULL, DYNAMIC_TYPE_X509);
+ dCert->issuerName.fullNameLen, x509->heap,
+ DYNAMIC_TYPE_X509);
if (x509->issuer.fullName.fullName != NULL)
XMEMCPY(x509->issuer.fullName.fullName,
dCert->issuerName.fullName, dCert->issuerName.fullNameLen);
}
-#endif /* OPENSSL_EXTRA */
+ x509->issuer.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX);
x509->subject.name[ASN_NAME_MAX - 1] = '\0';
x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1;
-#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (dCert->subjectName.fullName != NULL) {
XMEMCPY(&x509->subject.fullName,
&dCert->subjectName, sizeof(DecodedName));
x509->subject.fullName.fullName = (char*)XMALLOC(
- dCert->subjectName.fullNameLen, NULL, DYNAMIC_TYPE_X509);
+ dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509);
if (x509->subject.fullName.fullName != NULL)
XMEMCPY(x509->subject.fullName.fullName,
dCert->subjectName.fullName, dCert->subjectName.fullNameLen);
}
-#endif /* OPENSSL_EXTRA */
+ x509->subject.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw));
+ XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen);
+#ifdef WOLFSSL_CERT_EXT
+ x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw));
+ XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen);
+#endif
+#endif
XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE);
x509->serialSz = dCert->serialSz;
- if (dCert->subjectCNLen < ASN_NAME_MAX) {
+ if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) {
XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen);
x509->subjectCN[dCert->subjectCNLen] = '\0';
}
@@ -3765,14 +9476,14 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
else
x509->deviceTypeSz = 0;
minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
- if (minSz != 0) {
+ if (minSz > 0) {
x509->hwTypeSz = minSz;
XMEMCPY(x509->hwType, dCert->hwType, minSz);
}
else
x509->hwTypeSz = 0;
minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
- if (minSz != 0) {
+ if (minSz > 0) {
x509->hwSerialNumSz = minSz;
XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
}
@@ -3781,25 +9492,28 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
#endif /* WOLFSSL_SEP */
{
- int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ);
- if (minSz != 0) {
- x509->notBeforeSz = minSz;
- XMEMCPY(x509->notBefore, dCert->beforeDate, minSz);
+ int minSz;
+ if (dCert->beforeDateLen > 0) {
+ minSz = min(dCert->beforeDate[1], MAX_DATE_SZ);
+ x509->notBefore.type = dCert->beforeDate[0];
+ x509->notBefore.length = minSz;
+ XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz);
}
else
- x509->notBeforeSz = 0;
- minSz = min(dCert->afterDateLen, MAX_DATE_SZ);
- if (minSz != 0) {
- x509->notAfterSz = minSz;
- XMEMCPY(x509->notAfter, dCert->afterDate, minSz);
+ x509->notBefore.length = 0;
+ if (dCert->afterDateLen > 0) {
+ minSz = min(dCert->afterDate[1], MAX_DATE_SZ);
+ x509->notAfter.type = dCert->afterDate[0];
+ x509->notAfter.length = minSz;
+ XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz);
}
else
- x509->notAfterSz = 0;
+ x509->notAfter.length = 0;
}
if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
x509->pubKey.buffer = (byte*)XMALLOC(
- dCert->pubKeySize, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (x509->pubKey.buffer != NULL) {
x509->pubKeyOID = dCert->keyOID;
x509->pubKey.length = dCert->pubKeySize;
@@ -3807,11 +9521,34 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
else
ret = MEMORY_E;
+#if defined(OPENSSL_ALL)
+ if (ret == 0) {
+ x509->key.pubKeyOID = dCert->keyOID;
+
+ if (!x509->key.algor) {
+ x509->key.algor = wolfSSL_X509_ALGOR_new();
+ } else {
+ wolfSSL_ASN1_OBJECT_free(x509->key.algor->algorithm);
+ }
+ if (!(x509->key.algor->algorithm =
+ wolfSSL_OBJ_nid2obj(dCert->keyOID))) {
+ ret = PUBLIC_KEY_E;
+ }
+
+ wolfSSL_EVP_PKEY_free(x509->key.pkey);
+ if (!(x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
+ &dCert->publicKey,
+ dCert->pubKeySize))) {
+ ret = PUBLIC_KEY_E;
+ }
+ }
+#endif
}
- if (dCert->signature != NULL && dCert->sigLength != 0) {
+ if (dCert->signature != NULL && dCert->sigLength != 0 &&
+ dCert->sigLength <= MAX_ENCODED_SIG_SZ) {
x509->sig.buffer = (byte*)XMALLOC(
- dCert->sigLength, NULL, DYNAMIC_TYPE_SIGNATURE);
+ dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE);
if (x509->sig.buffer == NULL) {
ret = MEMORY_E;
}
@@ -3820,37 +9557,110 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->sig.length = dCert->sigLength;
x509->sigOID = dCert->signatureOID;
}
+#if defined(OPENSSL_ALL)
+ wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm);
+ if (!(x509->algor.algorithm =
+ wolfSSL_OBJ_nid2obj(dCert->signatureOID))) {
+ ret = PUBLIC_KEY_E;
+ }
+#endif
}
/* store cert for potential retrieval */
- x509->derCert.buffer = (byte*)XMALLOC(dCert->maxIdx, NULL,
- DYNAMIC_TYPE_CERT);
- if (x509->derCert.buffer == NULL) {
- ret = MEMORY_E;
+ if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) {
+ XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx);
}
else {
- XMEMCPY(x509->derCert.buffer, dCert->source, dCert->maxIdx);
- x509->derCert.length = dCert->maxIdx;
+ ret = MEMORY_E;
}
x509->altNames = dCert->altNames;
dCert->weOwnAltNames = 0;
x509->altNamesNext = x509->altNames; /* index hint */
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ !defined(IGNORE_NAME_CONSTRAINTS)
+ /* add copies of alternate emails from dCert to X509 */
+ if (dCert->altEmailNames != NULL) {
+ DNS_entry* cur = dCert->altEmailNames;
+
+ while (cur != NULL) {
+ if (cur->type == ASN_RFC822_TYPE) {
+ DNS_entry* dnsEntry;
+ int strLen = cur->len;
+
+ dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (dnsEntry == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ dnsEntry->type = ASN_RFC822_TYPE;
+ dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (dnsEntry->name == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME);
+ return MEMORY_E;
+ }
+ dnsEntry->len = strLen;
+ XMEMCPY(dnsEntry->name, cur->name, strLen);
+ dnsEntry->name[strLen] = '\0';
+
+ dnsEntry->next = x509->altNames;
+ x509->altNames = dnsEntry;
+ }
+ cur = cur->next;
+ }
+ }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
x509->isCa = dCert->isCA;
-#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
x509->pathLength = dCert->pathLength;
x509->keyUsage = dCert->extKeyUsage;
+ x509->CRLdistSet = dCert->extCRLdistSet;
+ x509->CRLdistCrit = dCert->extCRLdistCrit;
+ x509->CRLInfo = dCert->extCrlInfo;
+ x509->CRLInfoSz = dCert->extCrlInfoSz;
+ x509->authInfoSet = dCert->extAuthInfoSet;
+ x509->authInfoCrit = dCert->extAuthInfoCrit;
+ if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) {
+ x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap,
+ DYNAMIC_TYPE_X509_EXT);
+ if (x509->authInfo != NULL) {
+ XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz);
+ x509->authInfoSz = dCert->extAuthInfoSz;
+ }
+ else {
+ ret = MEMORY_E;
+ }
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ if (dCert->extAuthInfoCaIssuer != NULL && dCert->extAuthInfoCaIssuerSz > 0) {
+ x509->authInfoCaIssuer = (byte*)XMALLOC(dCert->extAuthInfoCaIssuerSz, x509->heap,
+ DYNAMIC_TYPE_X509_EXT);
+ if (x509->authInfoCaIssuer != NULL) {
+ XMEMCPY(x509->authInfoCaIssuer, dCert->extAuthInfoCaIssuer, dCert->extAuthInfoCaIssuerSz);
+ x509->authInfoCaIssuerSz = dCert->extAuthInfoCaIssuerSz;
+ }
+ else {
+ ret = MEMORY_E;
+ }
+ }
+ #endif
x509->basicConstSet = dCert->extBasicConstSet;
x509->basicConstCrit = dCert->extBasicConstCrit;
- x509->basicConstPlSet = dCert->extBasicConstPlSet;
+ x509->basicConstPlSet = dCert->pathLengthSet;
x509->subjAltNameSet = dCert->extSubjAltNameSet;
x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
x509->authKeyIdSet = dCert->extAuthKeyIdSet;
x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) {
- x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, NULL, 0);
+ x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (x509->authKeyId != NULL) {
XMEMCPY(x509->authKeyId,
dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz);
@@ -3862,7 +9672,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) {
- x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, NULL, 0);
+ x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (x509->subjKeyId != NULL) {
XMEMCPY(x509->subjKeyId,
dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz);
@@ -3873,595 +9684,2142 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
x509->keyUsageSet = dCert->extKeyUsageSet;
x509->keyUsageCrit = dCert->extKeyUsageCrit;
- #ifdef WOLFSSL_SEP
+ if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) {
+ x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz,
+ x509->heap, DYNAMIC_TYPE_X509_EXT);
+ if (x509->extKeyUsageSrc != NULL) {
+ XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc,
+ dCert->extExtKeyUsageSz);
+ x509->extKeyUsageSz = dCert->extExtKeyUsageSz;
+ x509->extKeyUsageCrit = dCert->extExtKeyUsageCrit;
+ x509->extKeyUsageCount = dCert->extExtKeyUsageCount;
+ }
+ else {
+ ret = MEMORY_E;
+ }
+ }
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
x509->certPolicySet = dCert->extCertPolicySet;
x509->certPolicyCrit = dCert->extCertPolicyCrit;
- #endif /* WOLFSSL_SEP */
-#endif /* OPENSSL_EXTRA */
-#ifdef HAVE_ECC
+ #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+ #ifdef WOLFSSL_CERT_EXT
+ {
+ int i;
+ for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++)
+ XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i],
+ MAX_CERTPOL_SZ);
+ x509->certPoliciesNb = dCert->extCertPoliciesNb;
+ }
+ #endif /* WOLFSSL_CERT_EXT */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
x509->pkCurveOID = dCert->pkCurveOID;
-#endif /* HAVE_ECC */
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
return ret;
}
#endif /* KEEP_PEER_CERT || SESSION_CERTS */
-
-static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
- word32 size)
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
+static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 status_length)
{
- word32 listSz;
- word32 begin = *inOutIdx;
- int ret = 0;
- int anyError = 0;
- int totalCerts = 0; /* number of certs in certs buffer */
- int count;
- buffer certs[MAX_CHAIN_DEPTH];
-
-#ifdef WOLFSSL_SMALL_STACK
- char* domain = NULL;
- DecodedCert* dCert = NULL;
- WOLFSSL_X509_STORE_CTX* store = NULL;
-#else
- char domain[ASN_NAME_MAX];
- DecodedCert dCert[1];
- WOLFSSL_X509_STORE_CTX store[1];
-#endif
+ int ret = 0;
+ OcspRequest* request;
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
+ #ifdef WOLFSSL_SMALL_STACK
+ CertStatus* status;
+ OcspResponse* response;
+ #else
+ CertStatus status[1];
+ OcspResponse response[1];
#endif
- if ((*inOutIdx - begin) + OPAQUE24_LEN > size)
+ do {
+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+ if (ssl->status_request) {
+ request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
+ ssl->status_request = 0;
+ break;
+ }
+ #endif
+
+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ if (ssl->status_request_v2) {
+ request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
+ WOLFSSL_CSR2_OCSP, 0);
+ ssl->status_request_v2 = 0;
+ break;
+ }
+ #endif
+
return BUFFER_ERROR;
+ } while(0);
- c24to32(input + *inOutIdx, &listSz);
- *inOutIdx += OPAQUE24_LEN;
+ if (request == NULL)
+ return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
-#ifdef HAVE_MAX_FRAGMENT
- if (listSz > ssl->max_fragment) {
- SendAlert(ssl, alert_fatal, record_overflow);
- return BUFFER_E;
- }
-#else
- if (listSz > MAX_RECORD_SIZE)
- return BUFFER_E;
-#endif
+ #ifdef WOLFSSL_SMALL_STACK
+ status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+ DYNAMIC_TYPE_OCSP_STATUS);
+ response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
- if ((*inOutIdx - begin) + listSz != size)
- return BUFFER_ERROR;
+ if (status == NULL || response == NULL) {
+ if (status)
+ XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+ if (response)
+ XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
- WOLFSSL_MSG("Loading peer's cert chain");
- /* first put cert chain into buffer so can verify top down
- we're sent bottom up */
- while (listSz) {
- word32 certSz;
+ return MEMORY_ERROR;
+ }
+ #endif
- if (totalCerts >= MAX_CHAIN_DEPTH)
- return MAX_CHAIN_ERROR;
+ InitOcspResponse(response, status, input +*inOutIdx, status_length);
- if ((*inOutIdx - begin) + OPAQUE24_LEN > size)
- return BUFFER_ERROR;
+ if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (CompareOcspReqResp(request, response) != 0)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (response->responseStatus != OCSP_SUCCESSFUL)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (response->status->status == CERT_REVOKED)
+ ret = OCSP_CERT_REVOKED;
+ else if (response->status->status != CERT_GOOD)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
- c24to32(input + *inOutIdx, &certSz);
- *inOutIdx += OPAQUE24_LEN;
+ *inOutIdx += status_length;
- if ((*inOutIdx - begin) + certSz > size)
- return BUFFER_ERROR;
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+ XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ #endif
- certs[totalCerts].length = certSz;
- certs[totalCerts].buffer = input + *inOutIdx;
+ return ret;
+}
+#endif
-#ifdef SESSION_CERTS
- if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
- certSz < MAX_X509_SIZE) {
- ssl->session.chain.certs[ssl->session.chain.count].length = certSz;
- XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
- input + *inOutIdx, certSz);
- ssl->session.chain.count++;
- } else {
- WOLFSSL_MSG("Couldn't store chain cert for session");
+
+
+#ifdef HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+ static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz,
+ const unsigned char* hash, unsigned int hashSz,
+ const unsigned char* keyDer, unsigned int keySz,
+ int* result, void* ctx)
+ {
+ int ret = NOT_COMPILED_IN;
+ WOLFSSL* ssl = (WOLFSSL*)ctx;
+
+ if (ssl && ssl->ctx->EccVerifyCb) {
+ ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz,
+ keyDer, keySz, result, ssl->EccVerifyCtx);
}
+ return ret;
+ }
#endif
+#ifndef NO_RSA
+ static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz,
+ unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
+ void* ctx)
+ {
+ int ret = NOT_COMPILED_IN;
+ WOLFSSL* ssl = (WOLFSSL*)ctx;
- *inOutIdx += certSz;
- listSz -= certSz + CERT_HEADER_SZ;
-
- totalCerts++;
- WOLFSSL_MSG(" Put another cert into chain");
+ if (ssl && ssl->ctx->RsaVerifyCb) {
+ ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz,
+ ssl->RsaVerifyCtx);
+ }
+ return ret;
}
+#endif
- count = totalCerts;
+int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
+{
+ if (ssl == NULL || sigCtx == NULL)
+ return BAD_FUNC_ARG;
-#ifdef WOLFSSL_SMALL_STACK
- dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (dCert == NULL)
- return MEMORY_E;
+ /* only setup the verify callback if a PK is set */
+#ifdef HAVE_ECC
+ if (ssl->ctx->EccVerifyCb) {
+ sigCtx->pkCbEcc = SigPkCbEccVerify;
+ sigCtx->pkCtxEcc = ssl;
+ }
#endif
+#ifndef NO_RSA
+ /* only setup the verify callback if a PK is set */
+ if (ssl->ctx->RsaVerifyCb) {
+ sigCtx->pkCbRsa = SigPkCbRsaVerify;
+ sigCtx->pkCtxRsa = ssl;
+ }
+#endif
+
+ return 0;
+}
- /* verify up to peer's first */
- while (count > 1) {
- buffer myCert = certs[count - 1];
- byte* subjectHash;
+#endif /* HAVE_PK_CALLBACKS */
- InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap);
- ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone,
- ssl->ctx->cm);
- #ifndef NO_SKID
- subjectHash = dCert->extSubjKeyId;
- #else
- subjectHash = dCert->subjectHash;
- #endif
- if (ret == 0 && dCert->isCA == 0) {
- WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+static void DoCertFatalAlert(WOLFSSL* ssl, int ret)
+{
+ int alertWhy;
+ if (ssl == NULL || ret == 0) {
+ return;
+ }
+
+ /* Determine alert reason */
+ alertWhy = bad_certificate;
+ if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
+ alertWhy = certificate_expired;
+ }
+#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD))
+ else if (ret == CRL_CERT_REVOKED) {
+ alertWhy = certificate_revoked;
+ }
+#endif
+ else if (ret == NO_PEER_CERT) {
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ alertWhy = certificate_required;
}
- else if (ret == 0 && ssl->options.verifyNone) {
- WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
+ else
+#endif
+ {
+ alertWhy = handshake_failure;
}
- else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
- buffer add;
- add.length = myCert.length;
- add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap,
- DYNAMIC_TYPE_CA);
- WOLFSSL_MSG("Adding CA from chain");
+ }
- if (add.buffer == NULL)
- return MEMORY_E;
- XMEMCPY(add.buffer, myCert.buffer, myCert.length);
+ /* send fatal alert and mark connection closed */
+ SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
+ ssl->options.isClosed = 1;
+}
+
+/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */
+/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */
+
+/* Callback is issued for certificate presented in TLS Certificate (11) packet.
+ * The intermediates are done first then peer leaf cert last. Use the
+ * store->error_depth member to determine index (0=peer, >1 intermediates)
+ */
- ret = AddCA(ssl->ctx->cm, add, WOLFSSL_CHAIN_CA,
- ssl->ctx->verifyPeer);
- if (ret == 1) ret = 0; /* SSL_SUCCESS for external */
+int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
+ ProcPeerCertArgs* args)
+{
+ int verify_ok = 0, use_cb = 0;
+ void *heap = (ssl != NULL) ? ssl->heap : cm->heap;
+
+ /* Determine if verify was okay */
+ if (ret == 0) {
+ verify_ok = 1;
+ }
+
+ /* Determine if verify callback should be used */
+ if (ret != 0) {
+ if ((ssl != NULL) && (!ssl->options.verifyNone)) {
+ use_cb = 1; /* always report errors */
}
- else if (ret != 0) {
- WOLFSSL_MSG("Failed to verify CA from chain");
+ }
+#ifdef WOLFSSL_ALWAYS_VERIFY_CB
+ /* always use verify callback on peer leaf cert */
+ if (args->certIdx == 0) {
+ use_cb = 1;
+ }
+#endif
+#ifdef WOLFSSL_VERIFY_CB_ALL_CERTS
+ /* perform verify callback on other intermediate certs (not just peer) */
+ if (args->certIdx > 0) {
+ use_cb = 1;
+ }
+#endif
+#if defined(OPENSSL_EXTRA)
+ /* perform domain name check on the peer certificate */
+ if (args->dCertInit && args->dCert && (ssl != NULL) &&
+ ssl->param && ssl->param->hostName[0]) {
+ /* If altNames names is present, then subject common name is ignored */
+ if (args->dCert->altNames != NULL) {
+ if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) {
+ if (ret == 0) {
+ ret = DOMAIN_NAME_MISMATCH;
+ }
+ }
}
else {
- WOLFSSL_MSG("Verified CA from chain and already had it");
+ if (args->dCert->subjectCN) {
+ if (MatchDomainName(args->dCert->subjectCN,
+ args->dCert->subjectCNLen,
+ ssl->param->hostName) == 0) {
+ if (ret == 0) {
+ ret = DOMAIN_NAME_MISMATCH;
+ }
+ }
+ }
}
+ }
-#if defined(HAVE_OCSP) || defined(HAVE_CRL)
- if (ret == 0) {
- int doCrlLookup = 1;
- (void)doCrlLookup;
-#ifdef HAVE_OCSP
- if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) {
- WOLFSSL_MSG("Doing Non Leaf OCSP check");
- ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert);
- doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
- if (ret != 0) {
- doCrlLookup = 0;
- WOLFSSL_MSG("\tOCSP Lookup not ok");
- }
+ /* perform IP address check on the peer certificate */
+ if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
+ (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
+ if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
+ if (ret == 0) {
+ ret = IPADDR_MISMATCH;
}
-#endif /* HAVE_OCSP */
+ }
+ }
+#endif
+ /* if verify callback has been set */
+ if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL)
+ #ifdef OPENSSL_ALL
+ || (ssl->ctx->verifyCertCb != NULL)
+ #endif
+ ))
+ #ifndef NO_WOLFSSL_CM_VERIFY
+ || (cm->verifyCallback != NULL)
+ #endif
+ ) {
+ int verifyFail = 0;
+ #ifdef WOLFSSL_SMALL_STACK
+ WOLFSSL_X509_STORE_CTX* store;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ WOLFSSL_X509* x509;
+ #endif
+ char* domain = NULL;
+ #else
+ WOLFSSL_X509_STORE_CTX store[1];
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ WOLFSSL_X509 x509[1];
+ #endif
+ char domain[ASN_NAME_MAX];
+ #endif
-#ifdef HAVE_CRL
- if (doCrlLookup && ssl->ctx->cm->crlEnabled
- && ssl->ctx->cm->crlCheckAll) {
- WOLFSSL_MSG("Doing Non Leaf CRL check");
- ret = CheckCertCRL(ssl->ctx->cm->crl, dCert);
+ #ifdef WOLFSSL_SMALL_STACK
+ store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+ sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE);
+ if (store == NULL) {
+ return MEMORY_E;
+ }
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+ DYNAMIC_TYPE_X509);
+ if (x509 == NULL) {
+ XFREE(store, heap, DYNAMIC_TYPE_X509);
+ return MEMORY_E;
+ }
+ #endif
+ domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING);
+ if (domain == NULL) {
+ XFREE(store, heap, DYNAMIC_TYPE_X509);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ XFREE(x509, heap, DYNAMIC_TYPE_X509);
+ #endif
+ return MEMORY_E;
+ }
+ #endif /* WOLFSSL_SMALL_STACK */
- if (ret != 0) {
- WOLFSSL_MSG("\tCRL check not ok");
- }
+ XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
+ #endif
+ domain[0] = '\0';
+
+ /* build subject CN as string to return in store */
+ if (args->dCertInit && args->dCert && args->dCert->subjectCN) {
+ int subjectCNLen = args->dCert->subjectCNLen;
+ if (subjectCNLen > ASN_NAME_MAX-1)
+ subjectCNLen = ASN_NAME_MAX-1;
+ if (subjectCNLen > 0) {
+ XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen);
+ domain[subjectCNLen] = '\0';
}
-#endif /* HAVE_CRL */
}
-#endif /* HAVE_OCSP || HAVE_CRL */
- if (ret != 0 && anyError == 0)
- anyError = ret; /* save error from last time */
+ store->error = ret;
+ store->error_depth = args->certIdx;
+ store->discardSessionCerts = 0;
+ store->domain = domain;
+ store->userCtx = (ssl != NULL) ? ssl->verifyCbCtx : cm;
+ store->certs = args->certs;
+ store->totalCerts = args->totalCerts;
+ #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl)
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX");
+ }
+ #endif
- FreeDecodedCert(dCert);
- count--;
- }
+ if (ssl != NULL) {
+ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ if (ssl->ctx->x509_store_pt != NULL) {
+ store->store = ssl->ctx->x509_store_pt;
+ }
+ else {
+ store->store = &ssl->ctx->x509_store;
+ }
+ #if defined(OPENSSL_EXTRA)
+ store->depth = args->count;
+ store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+ sizeof(WOLFSSL_X509_VERIFY_PARAM),
+ heap, DYNAMIC_TYPE_OPENSSL);
+ if (store->param == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(domain, heap, DYNAMIC_TYPE_STRING);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ XFREE(x509, heap, DYNAMIC_TYPE_X509);
+ #endif
+ XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
+ #endif
+ return MEMORY_E;
+ }
+ XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+ /* Overwrite with non-default param values in SSL */
+ if (ssl->param) {
+ if (ssl->param->check_time)
+ store->param->check_time = ssl->param->check_time;
- /* peer's, may not have one if blank client cert sent by TLSv1.2 */
- if (count) {
- buffer myCert = certs[0];
- int fatal = 0;
+ if (ssl->param->flags)
+ store->param->flags = ssl->param->flags;
- WOLFSSL_MSG("Verifying Peer's cert");
+ if (ssl->param->hostName[0])
+ XMEMCPY(store->param->hostName, ssl->param->hostName,
+ WOLFSSL_HOST_NAME_MAX);
- InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap);
- ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone,
- ssl->ctx->cm);
- if (ret == 0) {
- WOLFSSL_MSG("Verified Peer's cert");
- fatal = 0;
- }
- else if (ret == ASN_PARSE_E) {
- WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal");
- fatal = 1;
+ }
+ #endif /* defined(OPENSSL_EXTRA) */
+ #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ #ifdef KEEP_PEER_CERT
+ if (args->certIdx == 0) {
+ store->current_cert = &ssl->peerCert; /* use existing X509 */
+ }
+ else
+ #endif
+ {
+ InitX509(x509, 0, heap);
+ if (CopyDecodedToX509(x509, args->dCert) == 0) {
+ store->current_cert = x509;
+ }
+ else {
+ FreeX509(x509);
+ }
+ }
+ #endif
+ #ifdef SESSION_CERTS
+ store->sesChain = &ssl->session.chain;
+ #endif
}
- else {
- WOLFSSL_MSG("Failed to verify Peer's cert");
- if (ssl->verifyCallback) {
- WOLFSSL_MSG("\tCallback override available, will continue");
- fatal = 0;
+ #ifndef NO_WOLFSSL_CM_VERIFY
+ /* non-zero return code indicates failure override */
+ if ((cm != NULL) && (cm->verifyCallback != NULL)) {
+ store->userCtx = cm;
+ if (cm->verifyCallback(verify_ok, store)) {
+ if (ret != 0) {
+ WOLFSSL_MSG("Verify CM callback overriding error!");
+ ret = 0;
+ }
}
else {
- WOLFSSL_MSG("\tNo callback override available, fatal");
- fatal = 1;
+ verifyFail = 1;
}
}
+ #endif
-#ifdef HAVE_SECURE_RENEGOTIATION
- if (fatal == 0 && ssl->secure_renegotiation
- && ssl->secure_renegotiation->enabled) {
+ if (ssl != NULL) {
+ #ifdef OPENSSL_ALL
+ /* non-zero return code indicates failure override */
+ if (ssl->ctx->verifyCertCb) {
+ if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) {
+ if (ret != 0) {
+ WOLFSSL_MSG("Verify Cert callback overriding error!");
+ ret = 0;
+ }
+ }
+ else {
+ verifyFail = 1;
+ }
+ }
+ #endif
- if (ssl->keys.encryptionOn) {
- /* compare against previous time */
- if (XMEMCMP(dCert->subjectHash,
- ssl->secure_renegotiation->subject_hash,
- SHA_DIGEST_SIZE) != 0) {
- WOLFSSL_MSG("Peer sent different cert during scr, fatal");
- fatal = 1;
- ret = SCR_DIFFERENT_CERT_E;
+ /* non-zero return code indicates failure override */
+ if (ssl->verifyCallback) {
+ if (ssl->verifyCallback(verify_ok, store)) {
+ if (ret != 0) {
+ WOLFSSL_MSG("Verify callback overriding error!");
+ ret = 0;
+ }
+ }
+ else {
+ verifyFail = 1;
}
}
+ }
- /* cache peer's hash */
- if (fatal == 0) {
- XMEMCPY(ssl->secure_renegotiation->subject_hash,
- dCert->subjectHash, SHA_DIGEST_SIZE);
+ if (verifyFail) {
+ /* induce error if one not present */
+ if (ret == 0) {
+ ret = VERIFY_CERT_ERROR;
}
+
+ /* mark as verify error */
+ args->verifyErr = 1;
+ }
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ if (args->certIdx > 0)
+ FreeX509(x509);
+ #endif
+ #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+ wolfSSL_sk_X509_free(store->chain);
+ store->chain = NULL;
+ #endif
+ #ifdef SESSION_CERTS
+ if ((ssl != NULL) && (store->discardSessionCerts)) {
+ WOLFSSL_MSG("Verify callback requested discard sess certs");
+ ssl->session.chain.count = 0;
+ #ifdef WOLFSSL_ALT_CERT_CHAINS
+ ssl->session.altChain.count = 0;
+ #endif
+ }
+ #endif /* SESSION_CERTS */
+#ifdef OPENSSL_EXTRA
+ if ((ssl != NULL) && (store->param)) {
+ XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL);
}
#endif
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(domain, heap, DYNAMIC_TYPE_STRING);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ XFREE(x509, heap, DYNAMIC_TYPE_X509);
+ #endif
+ XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
+ #endif
+ }
-#if defined(HAVE_OCSP) || defined(HAVE_CRL)
- if (fatal == 0) {
- int doCrlLookup = 1;
- (void)doCrlLookup;
-#ifdef HAVE_OCSP
- if (ssl->ctx->cm->ocspEnabled) {
- ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert);
- doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
- if (ret != 0) {
- WOLFSSL_MSG("\tOCSP Lookup not ok");
- fatal = 0;
- }
- }
-#endif /* HAVE_OCSP */
+ (void)heap;
-#ifdef HAVE_CRL
- if (doCrlLookup && ssl->ctx->cm->crlEnabled) {
- WOLFSSL_MSG("Doing Leaf CRL check");
- ret = CheckCertCRL(ssl->ctx->cm->crl, dCert);
- if (ret != 0) {
- WOLFSSL_MSG("\tCRL check not ok");
- fatal = 0;
- }
+ return ret;
+}
+
+static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
+{
+ ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs;
+
+ (void)ssl;
+
+ if (args->certs) {
+ XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
+ args->certs = NULL;
+ }
+#ifdef WOLFSSL_TLS13
+ if (args->exts) {
+ XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+ args->exts = NULL;
+ }
+#endif
+ if (args->dCert) {
+ if (args->dCertInit) {
+ FreeDecodedCert(args->dCert);
+ args->dCertInit = 0;
+ }
+ XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ args->dCert = NULL;
+ }
+}
+
+static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
+ int certType, int verify, byte** pSubjectHash, int* pAlreadySigner)
+{
+ int ret = 0;
+ buffer* cert;
+ byte* subjectHash = NULL;
+ int alreadySigner = 0;
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+ int sigRet = 0;
+#endif
+
+ if (ssl == NULL || args == NULL)
+ return BAD_FUNC_ARG;
+
+ /* check to make sure certificate index is valid */
+ if (args->certIdx > args->count)
+ return BUFFER_E;
+
+ /* check if returning from non-blocking OCSP */
+ /* skip this section because cert is already initialized and parsed */
+#ifdef WOLFSSL_NONBLOCK_OCSP
+ if (args->lastErr == OCSP_WANT_READ) {
+ args->lastErr = 0; /* clear error */
+ return 0;
+ }
+#endif
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+ /* we have trusted peer */
+ if (args->haveTrustPeer) {
+ return 0;
+ }
+#endif
+
+ /* get certificate buffer */
+ cert = &args->certs[args->certIdx];
+
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+ if (verify == VERIFY) {
+ /* for small cert verify, release decoded cert during signature check to
+ reduce peak memory usage */
+ if (args->dCert != NULL) {
+ if (args->dCertInit) {
+ FreeDecodedCert(args->dCert);
+ args->dCertInit = 0;
}
-#endif /* HAVE_CRL */
+ XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ args->dCert = NULL;
}
-#endif /* HAVE_OCSP || HAVE_CRL */
-#ifdef KEEP_PEER_CERT
- {
- /* set X509 format for peer cert even if fatal */
- int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert);
- if (copyRet == MEMORY_E)
- fatal = 1;
+ /* perform cert parsing and signature check */
+ sigRet = CheckCertSignature(cert->buffer, cert->length,
+ ssl->heap, ssl->ctx->cm);
+ /* fail on errors here after the ParseCertRelative call, so dCert is populated */
+
+ /* verify name only in ParseCertRelative below, signature check done */
+ verify = VERIFY_NAME;
+ }
+#endif /* WOLFSSL_SMALL_CERT_VERIFY */
+
+ /* make sure the decoded cert structure is allocated and initialized */
+ if (!args->dCertInit
+ #ifdef WOLFSSL_SMALL_CERT_VERIFY
+ || args->dCert == NULL
+ #endif
+ ) {
+ #ifdef WOLFSSL_SMALL_CERT_VERIFY
+ if (args->dCert == NULL) {
+ args->dCert = (DecodedCert*)XMALLOC(
+ sizeof(DecodedCert), ssl->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (args->dCert == NULL) {
+ return MEMORY_E;
+ }
}
+ #endif
+
+ InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap);
+
+ args->dCertInit = 1;
+ args->dCert->sigCtx.devId = ssl->devId;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ args->dCert->sigCtx.asyncCtx = ssl;
+ #endif
+
+ #ifdef HAVE_PK_CALLBACKS
+ /* setup the PK callback context */
+ ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+ if (ret != 0)
+ return ret;
+ #endif
+ }
+
+ /* Parse Certificate */
+ ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm);
+ /* perform below checks for date failure cases */
+ if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) {
+ /* get subject and determine if already loaded */
+ #ifndef NO_SKID
+ if (args->dCert->extAuthKeyIdSet)
+ subjectHash = args->dCert->extSubjKeyId;
+ else
+ #endif
+ subjectHash = args->dCert->subjectHash;
+ alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash);
+ }
+
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+ /* get signature check failures from above */
+ if (ret == 0)
+ ret = sigRet;
+#endif
+
+ if (pSubjectHash)
+ *pSubjectHash = subjectHash;
+ if (pAlreadySigner)
+ *pAlreadySigner = alreadySigner;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl,
+ args->dCert->sigCtx.asyncDev);
+ }
#endif
-#ifndef IGNORE_KEY_EXTENSIONS
- if (dCert->extKeyUsageSet) {
- if ((ssl->specs.kea == rsa_kea) &&
- (dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
- ret = KEYUSE_ENCIPHER_E;
+ return ret;
+}
+
+/* Check key sizes for certs. Is redundant check since
+ ProcessBuffer also performs this check. */
+static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
+{
+ int ret = 0;
+
+ if (ssl->options.verifyNone) {
+ return ret;
+ }
+
+ switch (args->dCert->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ if (ssl->options.minRsaKeySz < 0 ||
+ args->dCert->pubKeySize <
+ (word16)ssl->options.minRsaKeySz) {
+ WOLFSSL_MSG(
+ "RSA key size in cert chain error");
+ ret = RSA_KEY_SIZE_E;
+ }
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ if (ssl->options.minEccKeySz < 0 ||
+ args->dCert->pubKeySize <
+ (word16)ssl->options.minEccKeySz) {
+ WOLFSSL_MSG(
+ "ECC key size in cert chain error");
+ ret = ECC_KEY_SIZE_E;
}
- if ((ssl->specs.sig_algo == rsa_sa_algo ||
- (ssl->specs.sig_algo == ecc_dsa_sa_algo &&
- !ssl->specs.static_ecdh)) &&
- (dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
- WOLFSSL_MSG("KeyUse Digital Sig not set");
- ret = KEYUSE_SIGNATURE_E;
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ if (ssl->options.minEccKeySz < 0 ||
+ ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
+ WOLFSSL_MSG(
+ "ECC key size in cert chain error");
+ ret = ECC_KEY_SIZE_E;
+ }
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ if (ssl->options.minEccKeySz < 0 ||
+ ED448_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
+ WOLFSSL_MSG(
+ "ECC key size in cert chain error");
+ ret = ECC_KEY_SIZE_E;
}
+ break;
+ #endif /* HAVE_ED448 */
+ default:
+ WOLFSSL_MSG("Key size not checked");
+ /* key not being checked for size if not in
+ switch */
+ break;
+ }
+
+ return ret;
+}
+
+int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 totalSz)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+ ProcPeerCertArgs* args = ssl->nonblockarg;
+#elif defined(WOLFSSL_SMALL_STACK)
+ ProcPeerCertArgs* args = NULL;
+#else
+ ProcPeerCertArgs args[1];
+#endif
+ byte* subjectHash = NULL;
+ int alreadySigner = 0;
+
+ WOLFSSL_ENTER("ProcessPeerCerts");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_ppc;
+ }
+ else
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+ if (args == NULL) {
+ args = (ProcPeerCertArgs*)XMALLOC(
+ sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (args == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
}
+ }
+ if (ssl->nonblockarg == NULL) /* new args */
+#elif defined(WOLFSSL_SMALL_STACK)
+ args = (ProcPeerCertArgs*)XMALLOC(
+ sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (args == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
+ }
+#endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
+ args->idx = *inOutIdx;
+ args->begin = *inOutIdx;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeProcPeerCertArgs;
+ #elif defined(WOLFSSL_NONBLOCK_OCSP)
+ ssl->nonblockarg = args;
+ #endif
+ }
- if (dCert->extExtKeyUsageSet) {
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- if ((dCert->extExtKeyUsage &
- (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
- WOLFSSL_MSG("ExtKeyUse Server Auth not set");
- ret = EXTKEYUSE_AUTH_E;
+ switch (ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ word32 listSz;
+
+ #ifdef WOLFSSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "Certificate");
+ if (ssl->toInfoOn)
+ AddLateName("Certificate", &ssl->timeoutInfo);
+ #endif
+
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ byte ctxSz;
+
+ /* Certificate Request Context */
+ if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz)
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ ctxSz = *(input + args->idx);
+ args->idx++;
+ if ((args->idx - args->begin) + ctxSz > totalSz)
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ #ifndef NO_WOLFSSL_CLIENT
+ /* Must be empty when received from server. */
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if (ctxSz != 0) {
+ ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+ }
+ }
+ #endif
+ #ifndef NO_WOLFSSL_SERVER
+ /* Must contain value sent in request. */
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ if (ssl->options.handShakeState != HANDSHAKE_DONE &&
+ ctxSz != 0) {
+ ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+ }
+ else if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+ CertReqCtx* curr = ssl->certReqCtx;
+ CertReqCtx* prev = NULL;
+ while (curr != NULL) {
+ if ((ctxSz == curr->len) &&
+ XMEMCMP(&curr->ctx, input + args->idx, ctxSz)
+ == 0) {
+ if (prev != NULL)
+ prev->next = curr->next;
+ else
+ ssl->certReqCtx = curr->next;
+ XFREE(curr, ssl->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ break;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ if (curr == NULL)
+ #endif
+ ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+ }
+ }
+ #endif
+ args->idx += ctxSz;
+
+ #ifdef OPENSSL_EXTRA
+ /* allocate buffer for cert extensions */
+ args->exts = (buffer*)XMALLOC(sizeof(buffer) *
+ (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+ if (args->exts == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
+ }
+ #else
+ /* allocate buffer for cert extensions */
+ args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+ ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+ if (args->exts == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
}
+ #endif
}
- else {
- if ((dCert->extExtKeyUsage &
- (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
- WOLFSSL_MSG("ExtKeyUse Client Auth not set");
- ret = EXTKEYUSE_AUTH_E;
+ #endif
+
+ /* allocate buffer for certs */
+ #ifdef OPENSSL_EXTRA
+ args->certs = (buffer*)XMALLOC(sizeof(buffer) *
+ (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER);
+ if (args->certs == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
+ }
+ XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1));
+ #else
+ args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+ ssl->heap, DYNAMIC_TYPE_DER);
+ if (args->certs == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
+ }
+ XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
+ #endif /* OPENSSL_EXTRA */
+
+ /* Certificate List */
+ if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+ c24to32(input + args->idx, &listSz);
+ args->idx += OPAQUE24_LEN;
+ if (listSz > MAX_CERTIFICATE_SZ) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+ if ((args->idx - args->begin) + listSz != totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+
+ WOLFSSL_MSG("Loading peer's cert chain");
+ /* first put cert chain into buffer so can verify top down
+ we're sent bottom up */
+ while (listSz) {
+ word32 certSz;
+
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ if (args->totalCerts > ssl->verifyDepth) {
+ ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+ }
+ #else
+ if (args->totalCerts >= ssl->verifyDepth ||
+ args->totalCerts >= MAX_CHAIN_DEPTH) {
+ ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+ }
+ #endif
+
+ if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+
+ c24to32(input + args->idx, &certSz);
+ args->idx += OPAQUE24_LEN;
+
+ if ((args->idx - args->begin) + certSz > totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+
+ args->certs[args->totalCerts].length = certSz;
+ args->certs[args->totalCerts].buffer = input + args->idx;
+
+ #ifdef SESSION_CERTS
+ AddSessionCertToChain(&ssl->session.chain,
+ input + args->idx, certSz);
+ #endif /* SESSION_CERTS */
+
+ args->idx += certSz;
+ listSz -= certSz + CERT_HEADER_SZ;
+
+ #ifdef WOLFSSL_TLS13
+ /* Extensions */
+ if (ssl->options.tls1_3) {
+ word16 extSz;
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+ ato16(input + args->idx, &extSz);
+ args->idx += OPAQUE16_LEN;
+ if ((args->idx - args->begin) + extSz > totalSz) {
+ ERROR_OUT(BUFFER_ERROR, exit_ppc);
+ }
+ /* Store extension data info for later processing. */
+ args->exts[args->totalCerts].length = extSz;
+ args->exts[args->totalCerts].buffer = input + args->idx;
+ args->idx += extSz;
+ listSz -= extSz + OPAQUE16_LEN;
+ ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
+ args->exts[args->totalCerts].length, certificate, NULL);
+ if (ret < 0) {
+ ERROR_OUT(ret, exit_ppc);
+ }
}
+ #endif
+
+ args->totalCerts++;
+ WOLFSSL_MSG("\tPut another cert into chain");
+ } /* while (listSz) */
+
+ args->count = args->totalCerts;
+ args->certIdx = 0; /* select peer cert (first one) */
+
+ if (args->count == 0 && ssl->options.mutualAuth &&
+ ssl->options.side == WOLFSSL_SERVER_END) {
+ ret = NO_PEER_CERT;
+ DoCertFatalAlert(ssl, ret);
}
- }
-#endif /* IGNORE_KEY_EXTENSIONS */
- if (fatal) {
- FreeDecodedCert(dCert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ args->dCertInit = 0;
+ #ifndef WOLFSSL_SMALL_CERT_VERIFY
+ args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (args->dCert == NULL) {
+ ERROR_OUT(MEMORY_E, exit_ppc);
+ }
+ XMEMSET(args->dCert, 0, sizeof(DecodedCert));
#endif
- ssl->error = ret;
- return ret;
- }
- ssl->options.havePeerCert = 1;
-#ifdef WOLFSSL_SMALL_STACK
- domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (domain == NULL) {
- FreeDecodedCert(dCert);
- XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
-#endif
- /* store for callback use */
- if (dCert->subjectCNLen < ASN_NAME_MAX) {
- XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen);
- domain[dCert->subjectCNLen] = '\0';
- }
- else
- domain[0] = '\0';
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* case TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
- if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
- if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
- (char*)ssl->buffers.domainName.buffer) == 0) {
- WOLFSSL_MSG("DomainName match on common name failed");
- if (CheckAltNames(dCert,
- (char*)ssl->buffers.domainName.buffer) == 0 ) {
- WOLFSSL_MSG("DomainName match on alt names failed too");
- ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
+ case TLS_ASYNC_BUILD:
+ {
+ if (args->count > 0) {
+
+ /* check for trusted peer and get untrustedDepth */
+ #if defined(WOLFSSL_TRUST_PEER_CERT) || defined(OPENSSL_EXTRA)
+ if (args->certIdx == 0) {
+ #ifdef WOLFSSL_TRUST_PEER_CERT
+ TrustedPeerCert* tp;
+ int matchType = WC_MATCH_NAME;
+ #endif
+
+ ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY,
+ &subjectHash, &alreadySigner);
+ if (ret != 0)
+ goto exit_ppc;
+
+ #ifdef OPENSSL_EXTRA
+ /* Determine untrusted depth */
+ if (!alreadySigner && (!args->dCert ||
+ !args->dCertInit || !args->dCert->selfSigned)) {
+ args->untrustedDepth = 1;
+ }
+ #endif
+
+ #ifdef WOLFSSL_TRUST_PEER_CERT
+ #ifndef NO_SKID
+ if (args->dCert->extAuthKeyIdSet)
+ matchType = WC_MATCH_SKID;
+ #endif
+ tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType);
+ WOLFSSL_MSG("Checking for trusted peer cert");
+
+ if (tp && MatchTrustedPeer(tp, args->dCert)) {
+ WOLFSSL_MSG("Found matching trusted peer cert");
+ args->haveTrustPeer = 1;
+ }
+ else if (tp == NULL) {
+ /* no trusted peer cert */
+ WOLFSSL_MSG("No matching trusted peer cert. Checking CAs");
+ }
+ else {
+ WOLFSSL_MSG("Trusted peer cert did not match!");
+ }
+ if (!args->haveTrustPeer)
+ #endif
+ {
+ /* free cert if not trusted peer */
+ FreeDecodedCert(args->dCert);
+ args->dCertInit = 0;
+ }
}
- }
- }
+ #endif /* WOLFSSL_TRUST_PEER_CERT || OPENSSL_EXTRA */
+
+ /* check certificate up to peer's first */
+ /* do not verify chain if trusted peer cert found */
+ while (args->count > 1
+ #ifdef WOLFSSL_TRUST_PEER_CERT
+ && !args->haveTrustPeer
+ #endif /* WOLFSSL_TRUST_PEER_CERT */
+ ) {
+ int skipAddCA = 0;
+
+ /* select last certificate */
+ args->certIdx = args->count - 1;
+
+ ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
+ !ssl->options.verifyNone ? VERIFY : NO_VERIFY,
+ &subjectHash, &alreadySigner);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ goto exit_ppc;
+ #endif
+ if (ret == 0) {
+ ret = ProcessPeerCertCheckKey(ssl, args);
+ }
- /* decode peer key */
- switch (dCert->keyOID) {
- #ifndef NO_RSA
- case RSAk:
- {
- word32 idx = 0;
- int keyRet = 0;
+ if (ret == 0 && args->dCert->isCA == 0) {
+ WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
+ }
+ else if (ret == 0 && ssl->options.verifyNone) {
+ WOLFSSL_MSG("Chain cert not verified by option, "
+ "not adding as CA");
+ }
+ else if (ret == 0) {
+ #ifdef OPENSSL_EXTRA
+ if (args->certIdx > args->untrustedDepth) {
+ args->untrustedDepth = (char)args->certIdx + 1;
+ }
+ #endif
- if (ssl->peerRsaKey == NULL) {
- ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey),
- ssl->heap, DYNAMIC_TYPE_RSA);
- if (ssl->peerRsaKey == NULL) {
- WOLFSSL_MSG("PeerRsaKey Memory error");
- keyRet = MEMORY_E;
- } else {
- keyRet = wc_InitRsaKey(ssl->peerRsaKey,
- ssl->ctx->heap);
+ if (alreadySigner) {
+ WOLFSSL_MSG("Verified CA from chain and already had it");
}
- } else if (ssl->peerRsaKeyPresent) {
- /* don't leak on reuse */
- wc_FreeRsaKey(ssl->peerRsaKey);
- ssl->peerRsaKeyPresent = 0;
- keyRet = wc_InitRsaKey(ssl->peerRsaKey, ssl->heap);
}
+ else {
+ WOLFSSL_MSG("Failed to verify CA from chain");
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
+ #endif
+ }
+
+ #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+ if (ret == 0) {
+ int doCrlLookup = 1;
+ #ifdef HAVE_OCSP
+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ if (ssl->status_request_v2) {
+ ret = TLSX_CSR2_InitRequests(ssl->extensions,
+ args->dCert, 0, ssl->heap);
+ }
+ else /* skips OCSP and force CRL check */
+ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+ if (ssl->ctx->cm->ocspEnabled &&
+ ssl->ctx->cm->ocspCheckAll) {
+ WOLFSSL_MSG("Doing Non Leaf OCSP check");
+ ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+ args->dCert, NULL, ssl);
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ if (ret == OCSP_WANT_READ) {
+ args->lastErr = ret;
+ goto exit_ppc;
+ }
+ #endif
+ doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
+ if (ret != 0) {
+ doCrlLookup = 0;
+ WOLFSSL_MSG("\tOCSP Lookup not ok");
+ }
+ }
+ #endif /* HAVE_OCSP */
+
+ #ifdef HAVE_CRL
+ if (ret == 0 && doCrlLookup &&
+ ssl->ctx->cm->crlEnabled &&
+ ssl->ctx->cm->crlCheckAll) {
+ WOLFSSL_MSG("Doing Non Leaf CRL check");
+ ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ if (ret == OCSP_WANT_READ) {
+ args->lastErr = ret;
+ goto exit_ppc;
+ }
+ #endif
+ if (ret != 0) {
+ WOLFSSL_MSG("\tCRL check not ok");
+ }
+ }
+ #endif /* HAVE_CRL */
+ (void)doCrlLookup;
+ }
+ #endif /* HAVE_OCSP || HAVE_CRL */
+
+ /* Do verify callback */
+ ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
+
+ #ifdef WOLFSSL_ALT_CERT_CHAINS
+ /* For alternate cert chain, its okay for a CA cert to fail
+ with ASN_NO_SIGNER_E here. The "alternate" certificate
+ chain mode only requires that the peer certificate
+ validate to a trusted CA */
+ if (ret != 0 && args->dCert->isCA) {
+ if (ret == ASN_NO_SIGNER_E) {
+ if (!ssl->options.usingAltCertChain) {
+ WOLFSSL_MSG("Trying alternate cert chain");
+ ssl->options.usingAltCertChain = 1;
+ }
- if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey,
- &idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) {
- ret = PEER_KEY_ERROR;
+ ret = 0; /* clear error and continue */
+ }
+
+ /* do not add to certificate manager */
+ skipAddCA = 1;
+ }
+ #endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+ /* If valid CA then add to Certificate Manager */
+ if (ret == 0 && args->dCert->isCA &&
+ !ssl->options.verifyNone && !skipAddCA) {
+ buffer* cert = &args->certs[args->certIdx];
+
+ /* Is valid CA */
+ #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
+ /* if using alternate chain, store the cert used */
+ if (ssl->options.usingAltCertChain) {
+ AddSessionCertToChain(&ssl->session.altChain,
+ cert->buffer, cert->length);
+ }
+ #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+ if (!alreadySigner) {
+ DerBuffer* add = NULL;
+ ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
+ if (ret < 0)
+ goto exit_ppc;
+
+ XMEMCPY(add->buffer, cert->buffer, cert->length);
+
+ /* CA already verified above in ParseCertRelative */
+ WOLFSSL_MSG("Adding CA from chain");
+ ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA,
+ NO_VERIFY);
+ if (ret == WOLFSSL_SUCCESS) {
+ ret = 0;
+ }
+ }
+ }
+
+ /* Handle error codes */
+ if (ret != 0) {
+ if (!ssl->options.verifyNone) {
+ DoCertFatalAlert(ssl, ret);
+ }
+ ssl->error = ret; /* Report SSL error */
+
+ if (args->lastErr == 0) {
+ args->lastErr = ret; /* save error from last time */
+ ret = 0; /* reset error */
+ }
+ }
+
+ FreeDecodedCert(args->dCert);
+ args->dCertInit = 0;
+ args->count--;
+ } /* while (count > 0 && !args->haveTrustPeer) */
+ } /* if (count > 0) */
+
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_ppc;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_DO:
+ {
+ /* peer's, may not have one if blank client cert sent by TLSv1.2 */
+ if (args->count > 0) {
+ WOLFSSL_MSG("Verifying Peer's cert");
+
+ /* select peer cert (first one) */
+ args->certIdx = 0;
+
+ ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
+ !ssl->options.verifyNone ? VERIFY : NO_VERIFY,
+ &subjectHash, &alreadySigner);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ goto exit_ppc;
+ #endif
+ if (ret == 0) {
+ WOLFSSL_MSG("Verified Peer's cert");
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = X509_V_OK;
+ #endif
+ #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
+ /* if using alternate chain, store the cert used */
+ if (ssl->options.usingAltCertChain) {
+ buffer* cert = &args->certs[args->certIdx];
+ AddSessionCertToChain(&ssl->session.altChain,
+ cert->buffer, cert->length);
+ }
+ #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+
+ /* check if fatal error */
+ if (args->verifyErr) {
+ args->fatal = 1;
+ if (ret == 0) {
+ ret = args->lastErr;
+ }
}
else {
- ssl->peerRsaKeyPresent = 1;
- #ifdef HAVE_PK_CALLBACKS
- #ifndef NO_RSA
- ssl->buffers.peerRsaKey.buffer =
- (byte*)XMALLOC(dCert->pubKeySize,
- ssl->heap, DYNAMIC_TYPE_RSA);
- if (ssl->buffers.peerRsaKey.buffer == NULL)
- ret = MEMORY_ERROR;
- else {
- XMEMCPY(ssl->buffers.peerRsaKey.buffer,
- dCert->publicKey, dCert->pubKeySize);
- ssl->buffers.peerRsaKey.length =
- dCert->pubKeySize;
- }
- #endif /* NO_RSA */
- #endif /*HAVE_PK_CALLBACKS */
+ args->fatal = 0;
}
}
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_NTRU
- case NTRUk:
- {
- if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
- ret = PEER_KEY_ERROR;
+ else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
+ WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ SendAlert(ssl, alert_fatal, bad_certificate);
+ ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+ #endif
+ args->fatal = 1;
+ }
+ else {
+ WOLFSSL_MSG("Failed to verify Peer's cert");
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+ #endif
+ if (ssl->verifyCallback) {
+ WOLFSSL_MSG(
+ "\tCallback override available, will continue");
+ /* check if fatal error */
+ args->fatal = (args->verifyErr) ? 1 : 0;
}
else {
- XMEMCPY(ssl->peerNtruKey, dCert->publicKey,
- dCert->pubKeySize);
- ssl->peerNtruKeyLen = (word16)dCert->pubKeySize;
- ssl->peerNtruKeyPresent = 1;
+ WOLFSSL_MSG("\tNo callback override available, fatal");
+ args->fatal = 1;
+ #ifdef OPENSSL_EXTRA
+ SendAlert(ssl, alert_fatal, bad_certificate);
+ #endif
}
}
- break;
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- case ECDSAk:
- {
- if (ssl->peerEccDsaKey == NULL) {
- /* alloc/init on demand */
- ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
- ssl->ctx->heap, DYNAMIC_TYPE_ECC);
- if (ssl->peerEccDsaKey == NULL) {
- WOLFSSL_MSG("PeerEccDsaKey Memory error");
- return MEMORY_E;
+
+ #ifdef HAVE_SECURE_RENEGOTIATION
+ if (args->fatal == 0 && !IsAtLeastTLSv1_3(ssl->version)
+ && ssl->secure_renegotiation
+ && ssl->secure_renegotiation->enabled) {
+
+ if (IsEncryptionOn(ssl, 0)) {
+ /* compare against previous time */
+ if (ssl->secure_renegotiation->subject_hash_set) {
+ if (XMEMCMP(args->dCert->subjectHash,
+ ssl->secure_renegotiation->subject_hash,
+ KEYID_SIZE) != 0) {
+ WOLFSSL_MSG(
+ "Peer sent different cert during scr, fatal");
+ args->fatal = 1;
+ ret = SCR_DIFFERENT_CERT_E;
+ }
}
- wc_ecc_init(ssl->peerEccDsaKey);
- } else if (ssl->peerEccDsaKeyPresent) {
- /* don't leak on reuse */
- wc_ecc_free(ssl->peerEccDsaKey);
- ssl->peerEccDsaKeyPresent = 0;
- wc_ecc_init(ssl->peerEccDsaKey);
}
- if (wc_ecc_import_x963(dCert->publicKey, dCert->pubKeySize,
- ssl->peerEccDsaKey) != 0) {
- ret = PEER_KEY_ERROR;
+
+ /* cache peer's hash */
+ if (args->fatal == 0) {
+ XMEMCPY(ssl->secure_renegotiation->subject_hash,
+ args->dCert->subjectHash, KEYID_SIZE);
+ ssl->secure_renegotiation->subject_hash_set = 1;
+ }
+ }
+ #endif /* HAVE_SECURE_RENEGOTIATION */
+ } /* if (count > 0) */
+
+ /* Check for error */
+ if (args->fatal && ret != 0) {
+ goto exit_ppc;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_VERIFY:
+ {
+ if (args->count > 0) {
+ #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+ if (args->fatal == 0) {
+ int doLookup = 1;
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+ if (ssl->status_request) {
+ args->fatal = TLSX_CSR_InitRequest(ssl->extensions,
+ args->dCert, ssl->heap);
+ doLookup = 0;
+ #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+ if (ssl->options.tls1_3) {
+ TLSX* ext = TLSX_Find(ssl->extensions,
+ TLSX_STATUS_REQUEST);
+ if (ext != NULL) {
+ word32 idx = 0;
+ CertificateStatusRequest* csr =
+ (CertificateStatusRequest*)ext->data;
+ ret = ProcessCSR(ssl, csr->response.buffer,
+ &idx, csr->response.length);
+ if (ret < 0)
+ goto exit_ppc;
+ }
+ }
+ #endif
+ }
+ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ if (ssl->status_request_v2) {
+ args->fatal = TLSX_CSR2_InitRequests(ssl->extensions,
+ args->dCert, 1, ssl->heap);
+ doLookup = 0;
+ }
+ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+ }
+
+ #ifdef HAVE_OCSP
+ if (doLookup && ssl->ctx->cm->ocspEnabled) {
+ WOLFSSL_MSG("Doing Leaf OCSP check");
+ ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+ args->dCert, NULL, ssl);
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ if (ret == OCSP_WANT_READ) {
+ goto exit_ppc;
+ }
+ #endif
+ doLookup = (ret == OCSP_CERT_UNKNOWN);
+ if (ret != 0) {
+ WOLFSSL_MSG("\tOCSP Lookup not ok");
+ args->fatal = 0;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+ #endif
+ }
+ }
+ #endif /* HAVE_OCSP */
+
+ #ifdef HAVE_CRL
+ if (doLookup && ssl->ctx->cm->crlEnabled) {
+ WOLFSSL_MSG("Doing Leaf CRL check");
+ ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ if (ret == OCSP_WANT_READ) {
+ goto exit_ppc;
+ }
+ #endif
+ if (ret != 0) {
+ WOLFSSL_MSG("\tCRL check not ok");
+ args->fatal = 0;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+ #endif
+ }
+ }
+ #endif /* HAVE_CRL */
+ (void)doLookup;
+ }
+ #endif /* HAVE_OCSP || HAVE_CRL */
+
+ #ifdef KEEP_PEER_CERT
+ if (args->fatal == 0) {
+ int copyRet = 0;
+
+ #ifdef HAVE_SECURE_RENEGOTIATION
+ if (ssl->secure_renegotiation &&
+ ssl->secure_renegotiation->enabled) {
+ /* free old peer cert */
+ FreeX509(&ssl->peerCert);
+ }
+ #endif
+
+ /* set X509 format for peer cert */
+ copyRet = CopyDecodedToX509(&ssl->peerCert, args->dCert);
+ if (copyRet == MEMORY_E) {
+ args->fatal = 1;
+ }
+ }
+ #endif /* KEEP_PEER_CERT */
+
+ #ifndef IGNORE_KEY_EXTENSIONS
+ #if defined(OPENSSL_EXTRA)
+ /* when compatibility layer is turned on and no verify is
+ * set then ignore the certificate key extension */
+ if (args->dCert->extKeyUsageSet &&
+ args->dCert->extKeyUsageCrit == 0 &&
+ ssl->options.verifyNone) {
+ WOLFSSL_MSG("Not verifying certificate key usage");
+ }
+ else
+ #endif
+ if (args->dCert->extKeyUsageSet) {
+ if ((ssl->specs.kea == rsa_kea) &&
+ (ssl->options.side == WOLFSSL_CLIENT_END) &&
+ (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
+ ret = KEYUSE_ENCIPHER_E;
+ }
+ if ((ssl->specs.sig_algo == rsa_sa_algo ||
+ (ssl->specs.sig_algo == ecc_dsa_sa_algo &&
+ !ssl->specs.static_ecdh)) &&
+ (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
+ WOLFSSL_MSG("KeyUse Digital Sig not set");
+ ret = KEYUSE_SIGNATURE_E;
+ }
+ }
+
+ #if defined(OPENSSL_EXTRA)
+ /* when compatibility layer is turned on and no verify is
+ * set then ignore the certificate key extension */
+ if (args->dCert->extExtKeyUsageSet &&
+ args->dCert->extExtKeyUsageCrit == 0 &&
+ ssl->options.verifyNone) {
+ WOLFSSL_MSG("Not verifying certificate ext key usage");
+ }
+ else
+ #endif
+ if (args->dCert->extExtKeyUsageSet) {
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if ((args->dCert->extExtKeyUsage &
+ (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
+ WOLFSSL_MSG("ExtKeyUse Server Auth not set");
+ ret = EXTKEYUSE_AUTH_E;
+ }
}
else {
- ssl->peerEccDsaKeyPresent = 1;
- #ifdef HAVE_PK_CALLBACKS
- #ifdef HAVE_ECC
- ssl->buffers.peerEccDsaKey.buffer =
- (byte*)XMALLOC(dCert->pubKeySize,
- ssl->heap, DYNAMIC_TYPE_ECC);
- if (ssl->buffers.peerEccDsaKey.buffer == NULL)
- ret = MEMORY_ERROR;
- else {
- XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
- dCert->publicKey, dCert->pubKeySize);
- ssl->buffers.peerEccDsaKey.length =
- dCert->pubKeySize;
+ if ((args->dCert->extExtKeyUsage &
+ (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
+ WOLFSSL_MSG("ExtKeyUse Client Auth not set");
+ ret = EXTKEYUSE_AUTH_E;
+ }
+ }
+ }
+ #endif /* IGNORE_KEY_EXTENSIONS */
+
+ if (args->fatal) {
+ ssl->error = ret;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ SendAlert(ssl, alert_fatal, bad_certificate);
+ ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+ #endif
+ goto exit_ppc;
+ }
+
+ ssl->options.havePeerCert = 1;
+
+ if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
+ #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
+ /* Per RFC 5280 section 4.2.1.6, "Whenever such identities
+ * are to be bound into a certificate, the subject
+ * alternative name extension MUST be used." */
+ if (args->dCert->altNames) {
+ if (CheckAltNames(args->dCert,
+ (char*)ssl->buffers.domainName.buffer) == 0 ) {
+ WOLFSSL_MSG("DomainName match on alt names failed");
+ /* try to get peer key still */
+ ret = DOMAIN_NAME_MISMATCH;
+ }
+ }
+ else {
+ if (MatchDomainName(
+ args->dCert->subjectCN,
+ args->dCert->subjectCNLen,
+ (char*)ssl->buffers.domainName.buffer) == 0) {
+ WOLFSSL_MSG("DomainName match on common name failed");
+ ret = DOMAIN_NAME_MISMATCH;
+ }
+ }
+ #else /* WOLFSSL_ALL_NO_CN_IN_SAN */
+ /* Old behavior. */
+ if (MatchDomainName(args->dCert->subjectCN,
+ args->dCert->subjectCNLen,
+ (char*)ssl->buffers.domainName.buffer) == 0) {
+ WOLFSSL_MSG("DomainName match on common name failed");
+ if (CheckAltNames(args->dCert,
+ (char*)ssl->buffers.domainName.buffer) == 0 ) {
+ WOLFSSL_MSG(
+ "DomainName match on alt names failed too");
+ /* try to get peer key still */
+ ret = DOMAIN_NAME_MISMATCH;
+ }
+ }
+ #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
+ }
+
+ /* decode peer key */
+ switch (args->dCert->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ word32 keyIdx = 0;
+ int keyRet = 0;
+
+ if (ssl->peerRsaKey == NULL) {
+ keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA,
+ (void**)&ssl->peerRsaKey);
+ } else if (ssl->peerRsaKeyPresent) {
+ keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA,
+ ssl->peerRsaKey);
+ ssl->peerRsaKeyPresent = 0;
+ }
+
+ if (keyRet != 0 || wc_RsaPublicKeyDecode(
+ args->dCert->publicKey, &keyIdx, ssl->peerRsaKey,
+ args->dCert->pubKeySize) != 0) {
+ ret = PEER_KEY_ERROR;
+ }
+ else {
+ ssl->peerRsaKeyPresent = 1;
+ #ifdef WOLFSSL_RENESAS_TSIP_TLS
+ /* copy encrypted tsip key index into ssl object */
+ if (args->dCert->tsip_encRsaKeyIdx) {
+ if (!ssl->peerTsipEncRsaKeyIndex) {
+ ssl->peerTsipEncRsaKeyIndex = (byte*)XMALLOC(
+ TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY,
+ ssl->heap, DYNAMIC_TYPE_RSA);
+ if (!ssl->peerTsipEncRsaKeyIndex) {
+ args->lastErr = MEMORY_E;
+ goto exit_ppc;
}
- #endif /* HAVE_ECC */
- #endif /*HAVE_PK_CALLBACKS */
+ }
+
+ XMEMCPY(ssl->peerTsipEncRsaKeyIndex,
+ args->dCert->tsip_encRsaKeyIdx,
+ TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY);
+ }
+ #endif
+ #ifdef HAVE_PK_CALLBACKS
+ #ifndef NO_RSA
+ #ifdef HAVE_SECURE_RENEGOTIATION
+ if (ssl->buffers.peerRsaKey.buffer) {
+ XFREE(ssl->buffers.peerRsaKey.buffer,
+ ssl->heap, DYNAMIC_TYPE_RSA);
+ ssl->buffers.peerRsaKey.buffer = NULL;
+ }
+ #endif
+
+
+ ssl->buffers.peerRsaKey.buffer =
+ (byte*)XMALLOC(args->dCert->pubKeySize,
+ ssl->heap, DYNAMIC_TYPE_RSA);
+ if (ssl->buffers.peerRsaKey.buffer == NULL) {
+ ret = MEMORY_ERROR;
+ }
+ else {
+ XMEMCPY(ssl->buffers.peerRsaKey.buffer,
+ args->dCert->publicKey,
+ args->dCert->pubKeySize);
+ ssl->buffers.peerRsaKey.length =
+ args->dCert->pubKeySize;
+ }
+ #endif /* NO_RSA */
+ #endif /* HAVE_PK_CALLBACKS */
+ }
+
+ /* check size of peer RSA key */
+ if (ret == 0 && ssl->peerRsaKeyPresent &&
+ !ssl->options.verifyNone &&
+ wc_RsaEncryptSize(ssl->peerRsaKey)
+ < ssl->options.minRsaKeySz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG("Peer RSA key is too small");
+ }
+ break;
+ }
+ #endif /* NO_RSA */
+ #ifdef HAVE_NTRU
+ case NTRUk:
+ {
+ if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
+ ret = PEER_KEY_ERROR;
+ }
+ else {
+ XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey,
+ args->dCert->pubKeySize);
+ ssl->peerNtruKeyLen =
+ (word16)args->dCert->pubKeySize;
+ ssl->peerNtruKeyPresent = 1;
+ }
+ break;
+ }
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ int keyRet = 0;
+ word32 idx = 0;
+
+ if (ssl->peerEccDsaKey == NULL) {
+ /* alloc/init on demand */
+ keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccDsaKey);
+ } else if (ssl->peerEccDsaKeyPresent) {
+ keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+ ssl->peerEccDsaKey);
+ ssl->peerEccDsaKeyPresent = 0;
+ }
+
+ if (keyRet != 0 ||
+ wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
+ ssl->peerEccDsaKey,
+ args->dCert->pubKeySize) != 0) {
+ ret = PEER_KEY_ERROR;
+ }
+ else {
+ ssl->peerEccDsaKeyPresent = 1;
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.peerEccDsaKey.buffer =
+ (byte*)XMALLOC(args->dCert->pubKeySize,
+ ssl->heap, DYNAMIC_TYPE_ECC);
+ if (ssl->buffers.peerEccDsaKey.buffer == NULL) {
+ ERROR_OUT(MEMORY_ERROR, exit_ppc);
+ }
+ else {
+ XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
+ args->dCert->publicKey,
+ args->dCert->pubKeySize);
+ ssl->buffers.peerEccDsaKey.length =
+ args->dCert->pubKeySize;
+ }
+ #endif /* HAVE_PK_CALLBACKS */
+ }
+
+ /* check size of peer ECC key */
+ if (ret == 0 && ssl->peerEccDsaKeyPresent &&
+ !ssl->options.verifyNone &&
+ wc_ecc_size(ssl->peerEccDsaKey)
+ < ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Peer ECC key is too small");
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ int keyRet = 0;
+ if (ssl->peerEd25519Key == NULL) {
+ /* alloc/init on demand */
+ keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519,
+ (void**)&ssl->peerEd25519Key);
+ } else if (ssl->peerEd25519KeyPresent) {
+ keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519,
+ ssl->peerEd25519Key);
+ ssl->peerEd25519KeyPresent = 0;
+ }
+
+ if (keyRet != 0 ||
+ wc_ed25519_import_public(args->dCert->publicKey,
+ args->dCert->pubKeySize,
+ ssl->peerEd25519Key)
+ != 0) {
+ ret = PEER_KEY_ERROR;
+ }
+ else {
+ ssl->peerEd25519KeyPresent = 1;
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.peerEd25519Key.buffer =
+ (byte*)XMALLOC(args->dCert->pubKeySize,
+ ssl->heap, DYNAMIC_TYPE_ED25519);
+ if (ssl->buffers.peerEd25519Key.buffer == NULL) {
+ ERROR_OUT(MEMORY_ERROR, exit_ppc);
+ }
+ else {
+ XMEMCPY(ssl->buffers.peerEd25519Key.buffer,
+ args->dCert->publicKey,
+ args->dCert->pubKeySize);
+ ssl->buffers.peerEd25519Key.length =
+ args->dCert->pubKeySize;
+ }
+ #endif /*HAVE_PK_CALLBACKS */
+ }
+
+ /* check size of peer ECC key */
+ if (ret == 0 && ssl->peerEd25519KeyPresent &&
+ !ssl->options.verifyNone &&
+ ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Peer ECC key is too small");
+ }
+ break;
}
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ int keyRet = 0;
+ if (ssl->peerEd448Key == NULL) {
+ /* alloc/init on demand */
+ keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED448,
+ (void**)&ssl->peerEd448Key);
+ } else if (ssl->peerEd448KeyPresent) {
+ keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED448,
+ ssl->peerEd448Key);
+ ssl->peerEd448KeyPresent = 0;
+ }
+
+ if (keyRet != 0 ||
+ wc_ed448_import_public(args->dCert->publicKey,
+ args->dCert->pubKeySize,
+ ssl->peerEd448Key) != 0) {
+ ret = PEER_KEY_ERROR;
+ }
+ else {
+ ssl->peerEd448KeyPresent = 1;
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.peerEd448Key.buffer =
+ (byte*)XMALLOC(args->dCert->pubKeySize,
+ ssl->heap, DYNAMIC_TYPE_ED448);
+ if (ssl->buffers.peerEd448Key.buffer == NULL) {
+ ERROR_OUT(MEMORY_ERROR, exit_ppc);
+ }
+ else {
+ XMEMCPY(ssl->buffers.peerEd448Key.buffer,
+ args->dCert->publicKey,
+ args->dCert->pubKeySize);
+ ssl->buffers.peerEd448Key.length =
+ args->dCert->pubKeySize;
+ }
+ #endif /*HAVE_PK_CALLBACKS */
+ }
+
+ /* check size of peer ECC key */
+ if (ret == 0 && ssl->peerEd448KeyPresent &&
+ !ssl->options.verifyNone &&
+ ED448_KEY_SIZE < ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Peer ECC key is too small");
+ }
+ break;
+ }
+ #endif /* HAVE_ED448 */
+ default:
+ break;
}
- break;
- #endif /* HAVE_ECC */
- default:
- break;
+
+ /* args->dCert free'd in function cleanup after callback */
+ } /* if (count > 0) */
+
+ /* Check for error */
+ if (args->fatal && ret != 0) {
+ goto exit_ppc;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_FINALIZE:
+ {
+ /* load last error */
+ if (args->lastErr != 0 && ret == 0) {
+ ret = args->lastErr;
+ }
+
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ if (args->untrustedDepth > ssl->options.verifyDepth) {
+ ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ ret = MAX_CHAIN_ERROR;
+ }
+ #endif
+
+ /* Do verify callback */
+ ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
+
+ if (ssl->options.verifyNone &&
+ (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
+ WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
+ ret = ssl->error = 0;
+ }
+
+ if (ret != 0) {
+ if (!ssl->options.verifyNone) {
+ DoCertFatalAlert(ssl, ret);
+ }
+ ssl->error = ret; /* Report SSL error */
+ }
+
+ if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+ }
+
+ 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:
+ {
+ /* Set final index */
+ *inOutIdx = args->idx;
+
+ break;
}
+ default:
+ ret = INPUT_CASE_ERROR;
+ break;
+ } /* switch(ssl->options.asyncState) */
- FreeDecodedCert(dCert);
- }
+exit_ppc:
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_LEAVE("ProcessPeerCerts", ret);
- store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX),
- NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (store == NULL) {
- XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+ if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) {
+ /* Mark message as not received so it can process again */
+ ssl->msgsReceived.got_certificate = 0;
+
+ return ret;
}
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
+
+ FreeProcPeerCertArgs(ssl, args);
+
+#if defined(WOLFSSL_ASYNC_CRYPT)
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+ XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ ssl->nonblockarg = NULL;
+#elif defined(WOLFSSL_SMALL_STACK)
+ XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- if (anyError != 0 && ret == 0)
- ret = anyError;
+ FreeKeyExchange(ssl);
- if (ret != 0) {
- if (!ssl->options.verifyNone) {
- int why = bad_certificate;
+ return ret;
+}
+#endif
- if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
- why = certificate_expired;
- if (ssl->verifyCallback) {
- int ok;
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
- store->error = ret;
- store->error_depth = totalCerts;
- store->discardSessionCerts = 0;
- store->domain = domain;
- store->userCtx = ssl->verifyCbCtx;
-#ifdef KEEP_PEER_CERT
- store->current_cert = &ssl->peerCert;
-#else
- store->current_cert = NULL;
+/* handle processing of certificate (11) */
+static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 size)
+{
+ int ret;
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
+ WOLFSSL_ENTER("DoCertificate");
+
+#ifdef SESSION_CERTS
+ /* Reset the session cert chain count in case the session resume failed. */
+ ssl->session.chain.count = 0;
+ #ifdef WOLFSSL_ALT_CERT_CHAINS
+ ssl->session.altChain.count = 0;
+ #endif
+#endif /* SESSION_CERTS */
+
+ ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
+#ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_ERROR || ret == ASN_PARSE_E)
+ SendAlert(ssl, alert_fatal, decode_error);
#endif
-#ifdef FORTRESS
- store->ex_data = ssl;
+
+#ifdef OPENSSL_EXTRA
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
#endif
- ok = ssl->verifyCallback(0, store);
- if (ok) {
- WOLFSSL_MSG("Verify callback overriding error!");
- ret = 0;
+
+ WOLFSSL_LEAVE("DoCertificate", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
+
+ return ret;
+}
+
+/* handle processing of certificate_status (22) */
+static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 size)
+{
+ int ret = 0;
+ byte status_type;
+ word32 status_length;
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
+ WOLFSSL_ENTER("DoCertificateStatus");
+
+ if (size < ENUM_LEN + OPAQUE24_LEN)
+ return BUFFER_ERROR;
+
+ status_type = input[(*inOutIdx)++];
+
+ c24to32(input + *inOutIdx, &status_length);
+ *inOutIdx += OPAQUE24_LEN;
+
+ if (size != ENUM_LEN + OPAQUE24_LEN + status_length)
+ return BUFFER_ERROR;
+
+ switch (status_type) {
+
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+ /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
+ case WOLFSSL_CSR2_OCSP:
+ ret = ProcessCSR(ssl, input, inOutIdx, status_length);
+ break;
+
+ #endif
+
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+ case WOLFSSL_CSR2_OCSP_MULTI: {
+ OcspRequest* request;
+ word32 list_length = status_length;
+ byte idx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ CertStatus* status;
+ OcspResponse* response;
+ #else
+ CertStatus status[1];
+ OcspResponse response[1];
+ #endif
+
+ do {
+ if (ssl->status_request_v2) {
+ ssl->status_request_v2 = 0;
+ break;
}
- #ifdef SESSION_CERTS
- if (store->discardSessionCerts) {
- WOLFSSL_MSG("Verify callback requested discard sess certs");
- ssl->session.chain.count = 0;
+
+ return BUFFER_ERROR;
+ } while(0);
+
+ #ifdef WOLFSSL_SMALL_STACK
+ status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+ DYNAMIC_TYPE_OCSP_STATUS);
+ response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+
+ if (status == NULL || response == NULL) {
+ if (status)
+ XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+ if (response)
+ XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+
+ return MEMORY_ERROR;
}
- #endif
- }
- if (ret != 0) {
- SendAlert(ssl, alert_fatal, why); /* try to send */
- ssl->options.isClosed = 1;
- }
- }
- ssl->error = ret;
- }
-#ifdef WOLFSSL_ALWAYS_VERIFY_CB
- else {
- if (ssl->verifyCallback) {
- int ok;
-
- store->error = ret;
- store->error_depth = totalCerts;
- store->discardSessionCerts = 0;
- store->domain = domain;
- store->userCtx = ssl->verifyCbCtx;
-#ifdef KEEP_PEER_CERT
- store->current_cert = &ssl->peerCert;
-#endif
- store->ex_data = ssl;
+ #endif
- ok = ssl->verifyCallback(1, store);
- if (!ok) {
- WOLFSSL_MSG("Verify callback overriding valid certificate!");
- ret = -1;
- SendAlert(ssl, alert_fatal, bad_certificate);
- ssl->options.isClosed = 1;
- }
- #ifdef SESSION_CERTS
- if (store->discardSessionCerts) {
- WOLFSSL_MSG("Verify callback requested discard sess certs");
- ssl->session.chain.count = 0;
+ while (list_length && ret == 0) {
+ if (OPAQUE24_LEN > list_length) {
+ ret = BUFFER_ERROR;
+ break;
+ }
+
+ c24to32(input + *inOutIdx, &status_length);
+ *inOutIdx += OPAQUE24_LEN;
+ list_length -= OPAQUE24_LEN;
+
+ if (status_length > list_length) {
+ ret = BUFFER_ERROR;
+ break;
+ }
+
+ if (status_length) {
+ InitOcspResponse(response, status, input +*inOutIdx,
+ status_length);
+
+ if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
+ 0) != 0)
+ || (response->responseStatus != OCSP_SUCCESSFUL)
+ || (response->status->status != CERT_GOOD))
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+ while (ret == 0) {
+ request = (OcspRequest*)TLSX_CSR2_GetRequest(
+ ssl->extensions, status_type, idx++);
+
+ if (request == NULL)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (CompareOcspReqResp(request, response) == 0)
+ break;
+ else if (idx == 1) /* server cert must be OK */
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ }
+
+ *inOutIdx += status_length;
+ list_length -= status_length;
+ }
}
+
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ ssl->status_request_v2 = 0;
+ #endif
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+ XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
#endif
+
}
- }
-#endif
+ break;
- if (ssl->options.verifyNone &&
- (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
- WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
- ret = ssl->error = 0;
+ #endif
+
+ default:
+ ret = BUFFER_ERROR;
}
- if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END)
- ssl->options.serverState = SERVER_CERT_COMPLETE;
+ if (ret != 0)
+ SendAlert(ssl, alert_fatal, bad_certificate_status_response);
- if (ssl->keys.encryptionOn) {
- *inOutIdx += ssl->keys.padSz;
+ if (IsEncryptionOn(ssl, 0)) {
+ #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)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz + digestSz;
+ }
+ else
+ #endif
+ {
+ if (*inOutIdx + ssl->keys.padSz > size)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz;
+ }
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WOLFSSL_LEAVE("DoCertificateStatus", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO);
return ret;
}
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
#endif /* !NO_CERTS */
+#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 (ssl->keys.encryptionOn) {
- /* access beyond input + size should be checked against totalSz */
- if (*inOutIdx + ssl->keys.padSz > totalSz)
- return BUFFER_E;
+ if (IsEncryptionOn(ssl, 0)) {
+ #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)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz + digestSz;
+ }
+ else
+ #endif
+ {
+ /* access beyond input + size should be checked against totalSz */
+ if (*inOutIdx + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
- *inOutIdx += ssl->keys.padSz;
+ *inOutIdx += ssl->keys.padSz;
+ }
}
if (ssl->options.side == WOLFSSL_SERVER_END) {
@@ -4471,6 +11829,8 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#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
@@ -4485,21 +11845,36 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
{
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 (*inOutIdx + size + ssl->keys.padSz > totalSz)
- return BUFFER_E;
+ #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;
+ }
#ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
#endif
if (sniff == NO_SNIFF) {
if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){
WOLFSSL_MSG("Verify finished error on hashes");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, decrypt_error);
+ #endif
return VERIFY_FINISHED_ERROR;
}
}
@@ -4513,42 +11888,57 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
else
XMEMCPY(ssl->secure_renegotiation->client_verify_data,
input + *inOutIdx, TLS_FINISHED_SZ);
+ ssl->secure_renegotiation->verifySet = 1;
}
#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 == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#endif
if (!ssl->options.resuming) {
- ssl->options.handShakeState = HANDSHAKE_DONE;
- ssl->options.handShakeDone = 1;
-
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- /* Other side has received our Finished, go to next epoch */
- ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 1;
+#ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
}
#endif
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ ssl->options.handShakeDone = 1;
}
}
else {
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+ ssl->cbmode = SSL_CB_MODE_READ;
+ ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#endif
if (ssl->options.resuming) {
- ssl->options.handShakeState = HANDSHAKE_DONE;
- ssl->options.handShakeDone = 1;
-
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- /* Other side has received our Finished, go to next epoch */
- ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 1;
+#ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
}
#endif
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ ssl->options.handShakeDone = 1;
}
}
+#ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ DtlsMsgPoolReset(ssl);
+ }
+#endif
+
+ WOLFSSL_LEAVE("DoFinished", 0);
+ WOLFSSL_END(WC_FUNC_FINISHED_DO);
return 0;
}
@@ -4575,6 +11965,9 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
case client_hello:
if (ssl->msgsReceived.got_client_hello) {
WOLFSSL_MSG("Duplicate ClientHello received");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ #endif
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_client_hello = 1;
@@ -4641,6 +12034,26 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
break;
#ifndef NO_WOLFSSL_CLIENT
+ case certificate_status:
+ if (ssl->msgsReceived.got_certificate_status) {
+ WOLFSSL_MSG("Duplicate CertificateSatatus received");
+ return DUPLICATE_MSG_E;
+ }
+ ssl->msgsReceived.got_certificate_status = 1;
+
+ if (ssl->msgsReceived.got_certificate == 0) {
+ WOLFSSL_MSG("No Certificate before CertificateStatus");
+ return OUT_OF_ORDER_E;
+ }
+ if (ssl->msgsReceived.got_server_key_exchange != 0) {
+ WOLFSSL_MSG("CertificateStatus after ServerKeyExchange");
+ 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");
@@ -4648,10 +12061,30 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
ssl->msgsReceived.got_server_key_exchange = 1;
- if ( ssl->msgsReceived.got_server_hello == 0) {
- WOLFSSL_MSG("No ServerHello before Cert");
+ if (ssl->msgsReceived.got_server_hello == 0) {
+ WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_certificate_status == 0) {
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+ if (ssl->status_request) {
+ int ret;
+
+ WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+ if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
+ return ret;
+ }
+#endif
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ if (ssl->status_request_v2) {
+ int ret;
+
+ WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+ if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
+ return ret;
+ }
+#endif
+ }
break;
#endif
@@ -4678,6 +12111,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
if (ssl->msgsReceived.got_certificate == 0) {
if (ssl->specs.kea == psk_kea ||
ssl->specs.kea == dhe_psk_kea ||
+ ssl->specs.kea == ecdhe_psk_kea ||
ssl->options.usingAnon_cipher) {
WOLFSSL_MSG("No Cert required");
} else {
@@ -4686,9 +12120,18 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
}
if (ssl->msgsReceived.got_server_key_exchange == 0) {
+ int pskNoServerHint = 0; /* not required in this case */
+
+ #ifndef NO_PSK
+ if (ssl->specs.kea == psk_kea &&
+ ssl->arrays != NULL &&
+ ssl->arrays->server_hint[0] == 0)
+ pskNoServerHint = 1;
+ #endif
if (ssl->specs.static_ecdh == 1 ||
ssl->specs.kea == rsa_kea ||
- ssl->specs.kea == ntru_kea) {
+ ssl->specs.kea == ntru_kea ||
+ pskNoServerHint) {
WOLFSSL_MSG("No KeyExchange required");
} else {
WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
@@ -4717,6 +12160,9 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
case client_key_exchange:
if (ssl->msgsReceived.got_client_key_exchange) {
WOLFSSL_MSG("Duplicate ClientKeyExchange received");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ #endif
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_client_key_exchange = 1;
@@ -4737,25 +12183,50 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
if (ssl->msgsReceived.got_change_cipher == 0) {
WOLFSSL_MSG("Finished received before ChangeCipher");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ #endif
return NO_CHANGE_CIPHER_E;
}
-
break;
case change_cipher_hs:
if (ssl->msgsReceived.got_change_cipher) {
WOLFSSL_MSG("Duplicate ChangeCipher received");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ #endif
return DUPLICATE_MSG_E;
}
- ssl->msgsReceived.got_change_cipher = 1;
+ /* DTLS is going to ignore the CCS message if the client key
+ * exchange message wasn't received yet. */
+ if (!ssl->options.dtls)
+ ssl->msgsReceived.got_change_cipher = 1;
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END) {
- if (!ssl->options.resuming &&
- ssl->msgsReceived.got_server_hello_done == 0) {
- WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
- return OUT_OF_ORDER_E;
+ if (!ssl->options.resuming) {
+ if (ssl->msgsReceived.got_server_hello_done == 0) {
+ WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
+ return OUT_OF_ORDER_E;
+ }
}
+ else {
+ if (ssl->msgsReceived.got_server_hello == 0) {
+ WOLFSSL_MSG("No ServerHello before ChangeCipher on Resume");
+ 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)
+ return OUT_OF_ORDER_E;
+ #endif
+ return SESSION_TICKET_EXPECT_E;
+ }
+ #endif
}
#endif
#ifndef NO_WOLFSSL_SERVER
@@ -4763,11 +12234,29 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
if (!ssl->options.resuming &&
ssl->msgsReceived.got_client_key_exchange == 0) {
WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ #endif
return OUT_OF_ORDER_E;
}
+ #ifndef NO_CERTS
+ if (ssl->options.verifyPeer &&
+ ssl->options.havePeerCert) {
+
+ if (!ssl->options.havePeerVerify) {
+ WOLFSSL_MSG("client didn't send cert verify");
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ return OUT_OF_ORDER_E;
+ #endif
+ return NO_PEER_VERIFY;
+ }
+ }
+ #endif
}
#endif
-
+ if (ssl->options.dtls)
+ ssl->msgsReceived.got_change_cipher = 1;
break;
default:
@@ -4783,13 +12272,51 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type, word32 size, word32 totalSz)
{
int ret = 0;
- (void)totalSz;
+ 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)
+ if (*inOutIdx + size > totalSz) {
+ WOLFSSL_MSG("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
+
+#if !defined(WOLFSSL_NO_SERVER) && \
+ defined(HAVE_SECURE_RENEGOTIATION) && \
+ defined(HAVE_SERVER_RENEGOTIATION_INFO)
+ if (ssl->options.handShakeDone && type == client_hello &&
+ ssl->secure_renegotiation &&
+ ssl->secure_renegotiation->enabled)
+ {
+ WOLFSSL_MSG("Reset handshake state");
+ XMEMSET(&ssl->msgsReceived, 0, sizeof(MsgsReceived));
+ ssl->options.serverState = NULL_STATE;
+ ssl->options.clientState = NULL_STATE;
+ ssl->options.connectState = CONNECT_BEGIN;
+ ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+ ssl->options.handShakeState = NULL_STATE;
+ ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
+
+ ret = InitHandshakeHashes(ssl);
+ if (ret != 0)
+ return ret;
+ }
+#endif
/* sanity check msg received */
if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) {
@@ -4797,13 +12324,15 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
return ret;
}
-#ifdef WOLFSSL_CALLBACKS
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
/* add name later, add on record and handshake header part back on */
if (ssl->toInfoOn) {
int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
- size + add, ssl->heap);
+ AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
+ size + add, READ_PROTO, ssl->heap);
+ #ifdef WOLFSSL_CALLBACKS
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ #endif
}
#endif
@@ -4837,11 +12366,32 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* above checks handshake state */
/* hello_request not hashed */
- if (type != hello_request) {
+ /* Also, skip hashing the client_hello message here for DTLS. It will be
+ * hashed later if the DTLS cookie is correct. */
+ if (type != hello_request &&
+ !(IsDtlsNotSctpMode(ssl) && type == client_hello)
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ssl->error != WC_PENDING_E
+ #endif
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ && ssl->error != OCSP_WANT_READ
+ #endif
+ ) {
ret = HashInput(ssl, input + *inOutIdx, size);
- if (ret != 0) return ret;
+ if (ret != 0) {
+ WOLFSSL_MSG("Incomplete handshake hashes");
+ return ret;
+ }
}
+#ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL){
+ ssl->cbmode = SSL_CB_MODE_READ;
+ ssl->cbtype = type;
+ ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+ }
+#endif
+
switch (type) {
case hello_request:
@@ -4858,6 +12408,25 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case server_hello:
WOLFSSL_MSG("processing server hello");
ret = DoServerHello(ssl, input, inOutIdx, size);
+ #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((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->messages != NULL) {
+ XFREE(ssl->hsHashes->messages, ssl->heap,
+ DYNAMIC_TYPE_HASHES);
+ ssl->hsHashes->messages = NULL;
+ }
+ }
+ }
+ #endif
break;
#ifndef NO_CERTS
@@ -4880,24 +12449,34 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif /* HAVE_SESSION_TICKET */
#endif
-#ifndef NO_CERTS
+#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
+ !defined(WOLFSSL_NO_CLIENT_AUTH))
case certificate:
WOLFSSL_MSG("processing certificate");
- ret = DoCertificate(ssl, input, inOutIdx, size);
+ ret = DoCertificate(ssl, input, inOutIdx, size);
+ break;
+
+ case certificate_status:
+ WOLFSSL_MSG("processing certificate status");
+ ret = DoCertificateStatus(ssl, input, inOutIdx, size);
break;
#endif
case server_hello_done:
WOLFSSL_MSG("processing server hello done");
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ServerHelloDone", &ssl->timeoutInfo);
- #endif
+ #ifdef WOLFSSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "ServerHelloDone");
+ if (ssl->toInfoOn)
+ AddLateName("ServerHelloDone", &ssl->timeoutInfo);
+ #endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- if (ssl->keys.encryptionOn) {
+ 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
}
if (ssl->options.resuming) {
WOLFSSL_MSG("Not resuming as thought");
@@ -4914,6 +12493,42 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case client_hello:
WOLFSSL_MSG("processing client hello");
ret = DoClientHello(ssl, input, inOutIdx, size);
+ #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+ if (ssl->options.resuming || !ssl->options.verifyPeer || \
+ !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->messages != NULL) {
+ XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
+ ssl->hsHashes->messages = NULL;
+ }
+ }
+ }
+ #endif
+ if (IsEncryptionOn(ssl, 0)) {
+ #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)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz + digestSz;
+ }
+ else
+ #endif
+ {
+ /* access beyond input + size should be checked against totalSz
+ */
+ if (*inOutIdx + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
+
+ *inOutIdx += ssl->keys.padSz;
+ }
+ }
break;
case client_key_exchange:
@@ -4921,12 +12536,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
break;
-#if !defined(NO_RSA) || defined(HAVE_ECC)
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
case certificate_verify:
WOLFSSL_MSG("processing certificate verify");
ret = DoCertificateVerify(ssl, input, inOutIdx, size);
break;
-#endif /* !NO_RSA || HAVE_ECC */
+#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */
#endif /* !NO_WOLFSSL_SERVER */
@@ -4935,6 +12551,38 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = UNKNOWN_HANDSHAKE_TYPE;
break;
}
+ if (ret == 0 && expectedIdx != *inOutIdx) {
+ WOLFSSL_MSG("Extra data in handshake message");
+ if (!ssl->options.dtls)
+ SendAlert(ssl, alert_fatal, decode_error);
+ ret = DECODE_E;
+ }
+
+ if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag
+ #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+ /* do not shrink input for async or non-block */
+ && ssl->error != WC_PENDING_E && ssl->error != OCSP_WANT_READ
+ #endif
+ ) {
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+ }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+ /* if async, offset index so this msg will be processed again */
+ if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
+ *inOutIdx -= HANDSHAKE_HEADER_SZ;
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ *inOutIdx -= DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ }
+
+ /* make sure async error is cleared */
+ if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) {
+ ssl->error = 0;
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
WOLFSSL_LEAVE("DoHandShakeMsgType()", ret);
return ret;
@@ -4944,79 +12592,335 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
{
- byte type;
- word32 size;
int ret = 0;
+ word32 inputLength;
WOLFSSL_ENTER("DoHandShakeMsg()");
- if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size, totalSz) != 0)
- return PARSE_ERROR;
+ if (ssl->arrays == NULL) {
+ byte type;
+ word32 size;
+
+ if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
+ return PARSE_ERROR;
+
+ ssl->options.handShakeState = type;
+
+ 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 == 0) {
+ byte type;
+ word32 size;
+
+ if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
+ return PARSE_ERROR;
+
+ /* 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 > MAX_HANDSHAKE_SZ) {
+ WOLFSSL_MSG("Handshake message too large");
+ return HANDSHAKE_SIZE_ERROR;
+ }
- ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+ /* 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;
+ 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;
+
+ 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_DTLS
-static INLINE int DtlsCheckWindow(DtlsState* state)
+static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
{
- word32 cur;
- word32 next;
- DtlsSeq window;
+ word32* window;
+ word16 cur_hi, next_hi;
+ word32 cur_lo, next_lo, diff;
+ int curLT;
+ WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL;
+
+ if (!ssl->options.haveMcast)
+ peerSeq = ssl->keys.peerSeq;
+ else {
+#ifdef WOLFSSL_MULTICAST
+ WOLFSSL_DTLS_PEERSEQ* p;
+ int i;
+
+ for (i = 0, p = ssl->keys.peerSeq;
+ i < WOLFSSL_DTLS_PEERSEQ_SZ;
+ i++, p++) {
- if (state->curEpoch == state->nextEpoch) {
- next = state->nextSeq;
- window = state->window;
+ if (p->peerId == ssl->keys.curPeerId) {
+ peerSeq = p;
+ break;
+ }
+ }
+#endif
+ }
+
+ if (peerSeq == NULL) {
+ WOLFSSL_MSG("Could not find peer sequence");
+ return 0;
}
- else if (state->curEpoch < state->nextEpoch) {
- next = state->prevSeq;
- window = state->prevWindow;
+
+ 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) {
+ next_hi = peerSeq->prevSeq_hi;
+ next_lo = peerSeq->prevSeq_lo;
+ window = peerSeq->prevWindow;
}
else {
return 0;
}
- cur = state->curSeq;
+ 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)) {
+ WOLFSSL_MSG("Current record from way too far in the future.");
+ return 0;
+ }
+
+ if (cur_hi == next_hi) {
+ curLT = cur_lo < next_lo;
+ diff = curLT ? next_lo - cur_lo : cur_lo - next_lo;
+ }
+ else {
+ curLT = cur_hi < next_hi;
+ diff = curLT ? cur_lo - next_lo : next_lo - cur_lo;
+ }
+
+ /* Check to see that the next value is greater than the number of messages
+ * trackable in the window, and that the difference between the next
+ * expected sequence number and the received sequence number is inside the
+ * window. */
+ if ((next_hi || next_lo > DTLS_SEQ_BITS) &&
+ curLT && (diff > DTLS_SEQ_BITS)) {
- if ((next > DTLS_SEQ_BITS) && (cur < next - DTLS_SEQ_BITS)) {
+ WOLFSSL_MSG("Current record sequence number from the past.");
return 0;
}
- else if ((cur < next) && (window & ((DtlsSeq)1 << (next - cur - 1)))) {
+#ifndef WOLFSSL_DTLS_ALLOW_FUTURE
+ else if (!curLT && (diff > DTLS_SEQ_BITS)) {
+ WOLFSSL_MSG("Rejecting message too far into the future.");
return 0;
}
+#endif
+ else if (curLT) {
+ word32 idx = diff / DTLS_WORD_BITS;
+ word32 newDiff = diff % DTLS_WORD_BITS;
+
+ /* verify idx is valid for window array */
+ if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) {
+ WOLFSSL_MSG("Invalid DTLS windows index");
+ return 0;
+ }
+
+ if (window[idx] & (1 << newDiff)) {
+ WOLFSSL_MSG("Current record sequence number already received.");
+ return 0;
+ }
+ }
return 1;
}
-static INLINE int DtlsUpdateWindow(DtlsState* state)
+#ifdef WOLFSSL_MULTICAST
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+ word32 second, word32 max)
+{
+ word32 newCur = 0;
+
+ if (cur < first)
+ newCur = first;
+ else if (cur < second)
+ newCur = second;
+ else if (cur < max)
+ newCur = max;
+
+ return newCur;
+}
+#endif /* WOLFSSL_MULTICAST */
+
+
+static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
{
- word32 cur;
- word32* next;
- DtlsSeq* window;
+ word32* window;
+ word32* next_lo;
+ word16* next_hi;
+ int curLT;
+ word32 cur_lo, diff;
+ word16 cur_hi;
+ WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
+
+ cur_hi = ssl->keys.curSeq_hi;
+ cur_lo = ssl->keys.curSeq_lo;
+
+#ifdef WOLFSSL_MULTICAST
+ if (ssl->options.haveMcast) {
+ WOLFSSL_DTLS_PEERSEQ* p;
+ int i;
+
+ peerSeq = NULL;
+ for (i = 0, p = ssl->keys.peerSeq;
+ i < WOLFSSL_DTLS_PEERSEQ_SZ;
+ i++, p++) {
+
+ if (p->peerId == ssl->keys.curPeerId) {
+ peerSeq = p;
+ break;
+ }
+ }
+
+ if (peerSeq == NULL) {
+ WOLFSSL_MSG("Couldn't find that peer ID to update window.");
+ return 0;
+ }
+
+ if (p->highwaterMark && cur_lo >= p->highwaterMark) {
+ int cbError = 0;
- if (state->curEpoch == state->nextEpoch) {
- next = &state->nextSeq;
- window = &state->window;
+ if (ssl->ctx->mcastHwCb)
+ cbError = ssl->ctx->mcastHwCb(p->peerId,
+ ssl->ctx->mcastMaxSeq,
+ cur_lo, ssl->mcastHwCbCtx);
+ if (cbError) {
+ WOLFSSL_MSG("Multicast highwater callback returned an error.");
+ return MCAST_HIGHWATER_CB_E;
+ }
+
+ p->highwaterMark = UpdateHighwaterMark(cur_lo,
+ ssl->ctx->mcastFirstSeq,
+ ssl->ctx->mcastSecondSeq,
+ ssl->ctx->mcastMaxSeq);
+ }
+ }
+#endif
+
+ if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
+ next_hi = &peerSeq->nextSeq_hi;
+ next_lo = &peerSeq->nextSeq_lo;
+ window = peerSeq->window;
+ }
+ else {
+ next_hi = &peerSeq->prevSeq_hi;
+ next_lo = &peerSeq->prevSeq_lo;
+ window = peerSeq->prevWindow;
+ }
+
+ if (cur_hi == *next_hi) {
+ curLT = cur_lo < *next_lo;
+ diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo;
}
else {
- next = &state->prevSeq;
- window = &state->prevWindow;
+ curLT = cur_hi < *next_hi;
+ diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo;
}
- cur = state->curSeq;
+ if (curLT) {
+ word32 idx = diff / DTLS_WORD_BITS;
+ word32 newDiff = diff % DTLS_WORD_BITS;
- if (cur < *next) {
- *window |= ((DtlsSeq)1 << (*next - cur - 1));
+ if (idx < WOLFSSL_DTLS_WINDOW_WORDS)
+ window[idx] |= (1 << newDiff);
}
else {
- *window <<= (1 + cur - *next);
- *window |= 1;
- *next = cur + 1;
+ if (diff >= DTLS_SEQ_BITS)
+ XMEMSET(window, 0, DTLS_SEQ_SZ);
+ else {
+ word32 idx, newDiff, temp, i;
+ word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS];
+
+ temp = 0;
+ diff++;
+ idx = diff / DTLS_WORD_BITS;
+ newDiff = diff % DTLS_WORD_BITS;
+
+ XMEMCPY(oldWindow, window, sizeof(oldWindow));
+
+ for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+ if (i < idx)
+ window[i] = 0;
+ else {
+ temp |= (oldWindow[i-idx] << newDiff);
+ window[i] = temp;
+ temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff - 1);
+ }
+ }
+ }
+ window[0] |= 1;
+ *next_lo = cur_lo + 1;
+ if (*next_lo < cur_lo)
+ (*next_hi)++;
}
return 1;
@@ -5025,12 +12929,14 @@ static INLINE int DtlsUpdateWindow(DtlsState* state)
static int DtlsMsgDrain(WOLFSSL* ssl)
{
- DtlsMsg* item = ssl->dtls_msg_list;
+ DtlsMsg* item = ssl->dtls_rx_msg_list;
int ret = 0;
+ WOLFSSL_ENTER("DtlsMsgDrain()");
+
/* While there is an item in the store list, and it is the expected
* message, and it is complete, and there hasn't been an error in the
- * last messge... */
+ * last message... */
while (item != NULL &&
ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
item->fragSz == item->sz &&
@@ -5039,11 +12945,19 @@ static int DtlsMsgDrain(WOLFSSL* ssl)
ssl->keys.dtls_expected_peer_handshake_number++;
ret = DoHandShakeMsgType(ssl, item->msg,
&idx, item->type, item->sz, item->sz);
- ssl->dtls_msg_list = item->next;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ssl->keys.dtls_expected_peer_handshake_number--;
+ break;
+ }
+ #endif
+ ssl->dtls_rx_msg_list = item->next;
DtlsMsgDelete(item, ssl->heap);
- item = ssl->dtls_msg_list;
+ item = ssl->dtls_rx_msg_list;
+ ssl->dtls_rx_msg_list_sz--;
}
+ WOLFSSL_LEAVE("DtlsMsgDrain()", ret);
return ret;
}
@@ -5057,12 +12971,38 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
int ret = 0;
WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
+
+ /* process any pending DTLS messages - this flow can happen with async */
+ if (ssl->dtls_rx_msg_list != NULL) {
+ ret = DtlsMsgDrain(ssl);
+ if (ret != 0)
+ return ret;
+
+ /* if done processing fragment exit with success */
+ if (totalSz == *inOutIdx)
+ return ret;
+ }
+
+ /* parse header */
if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
- &size, &fragOffset, &fragSz, totalSz) != 0)
+ &size, &fragOffset, &fragSz, totalSz) != 0) {
+ WOLFSSL_ERROR(PARSE_ERROR);
return PARSE_ERROR;
+ }
- if (*inOutIdx + fragSz > totalSz)
+ /* 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 > MAX_HANDSHAKE_SZ) {
+ WOLFSSL_MSG("Handshake message too large");
+ return HANDSHAKE_SIZE_ERROR;
+ }
+
+ /* check that we have complete fragment */
+ if (*inOutIdx + fragSz > totalSz) {
+ WOLFSSL_ERROR(INCOMPLETE_DATA);
return INCOMPLETE_DATA;
+ }
/* Check the handshake sequence number first. If out of order,
* add the current message to the list. If the message is in order,
@@ -5076,38 +13016,84 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->keys.dtls_peer_handshake_number >
ssl->keys.dtls_expected_peer_handshake_number) {
/* Current message is out of order. It will get stored in the list.
- * Storing also takes care of defragmentation. */
- ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list,
- ssl->keys.dtls_peer_handshake_number, input + *inOutIdx,
- size, type, fragOffset, fragSz, ssl->heap);
- *inOutIdx += fragSz;
- ret = 0;
+ * Storing also takes care of defragmentation. If the messages is a
+ * client hello, we need to process this out of order; the server
+ * is not supposed to keep state, but the second client hello will
+ * have a different handshake sequence number than is expected, and
+ * the server shouldn't be expecting any particular handshake sequence
+ * number. (If the cookie changes multiple times in quick succession,
+ * the client could be sending multiple new client hello messages
+ * with newer and newer cookies.) */
+ if (type != client_hello) {
+ if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+ DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+ input + *inOutIdx, size, type,
+ fragOffset, fragSz, ssl->heap);
+ }
+ *inOutIdx += fragSz;
+ ret = 0;
+ }
+ else {
+ ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+ if (ret == 0) {
+ ssl->keys.dtls_expected_peer_handshake_number =
+ ssl->keys.dtls_peer_handshake_number + 1;
+ }
+ }
}
else if (ssl->keys.dtls_peer_handshake_number <
ssl->keys.dtls_expected_peer_handshake_number) {
/* Already saw this message and processed it. It can be ignored. */
*inOutIdx += fragSz;
- ret = 0;
+ if(type == finished ) {
+ #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)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz + digestSz;
+ }
+ else
+ #endif
+ {
+ if (*inOutIdx + ssl->keys.padSz > totalSz) {
+ WOLFSSL_ERROR(BUFFER_E);
+ return BUFFER_E;
+ }
+ *inOutIdx += ssl->keys.padSz;
+ }
+ }
+ if (IsDtlsNotSctpMode(ssl) &&
+ VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) {
+
+ ret = DtlsMsgPoolSend(ssl, 0);
+ }
}
else if (fragSz < size) {
- /* Since this branch is in order, but fragmented, dtls_msg_list will be
- * pointing to the message with this fragment in it. Check it to see
+ /* Since this branch is in order, but fragmented, dtls_rx_msg_list will
+ * be pointing to the message with this fragment in it. Check it to see
* if it is completed. */
- ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list,
- ssl->keys.dtls_peer_handshake_number, input + *inOutIdx,
- size, type, fragOffset, fragSz, ssl->heap);
+ if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+ DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+ input + *inOutIdx, size, type,
+ fragOffset, fragSz, ssl->heap);
+ }
*inOutIdx += fragSz;
ret = 0;
- if (ssl->dtls_msg_list != NULL &&
- ssl->dtls_msg_list->fragSz >= ssl->dtls_msg_list->sz)
+ if (ssl->dtls_rx_msg_list != NULL &&
+ ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz)
ret = DtlsMsgDrain(ssl);
}
else {
/* This branch is in order next, and a complete message. */
- ssl->keys.dtls_expected_peer_handshake_number++;
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
- if (ret == 0 && ssl->dtls_msg_list != NULL)
- ret = DtlsMsgDrain(ssl);
+ if (ret == 0) {
+ if (type != client_hello || !IsDtlsNotSctpMode(ssl))
+ ssl->keys.dtls_expected_peer_handshake_number++;
+ if (ssl->dtls_rx_msg_list != NULL) {
+ ret = DtlsMsgDrain(ssl);
+ }
+ }
}
WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
@@ -5115,97 +13101,25 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
-
-#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
- || defined(HAVE_AESGCM)
-static INLINE word32 GetSEQIncrement(WOLFSSL* ssl, int verify)
-{
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if (verify)
- return ssl->keys.dtls_state.curSeq; /* explicit from peer */
- else
- return ssl->keys.dtls_sequence_number - 1; /* already incremented */
- }
-#endif
- if (verify)
- return ssl->keys.peer_sequence_number++;
- else
- return ssl->keys.sequence_number++;
-}
-#endif
-
+#ifndef WOLFSSL_NO_TLS12
#ifdef HAVE_AEAD
-static INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
+
+#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_EXP_IV_SZ-1; i >= 0; i--) {
+ for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) {
if (++ssl->keys.aead_exp_IV[i]) return;
}
}
+#endif
#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
-/*more recent rfc's concatonate input for poly1305 differently*/
-static int Poly1305Tag(WOLFSSL* ssl, byte* additional, const byte* out,
- byte* cipher, word16 sz, byte* tag)
-{
- int ret = 0;
- int paddingSz = 0;
- int msglen = (sz - ssl->specs.aead_mac_size);
- word32 keySz = 32;
- int blockSz = 16;
- byte padding[16];
-
- if (msglen < 0)
- return INPUT_CASE_ERROR;
-
- XMEMSET(padding, 0, sizeof(padding));
-
- if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
- return ret;
-
- /* additional input to poly1305 */
- if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, blockSz)) != 0)
- return ret;
-
- /* cipher input */
- if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
- return ret;
-
- /* handle padding for cipher input to make it 16 bytes long */
- if (msglen % 16 != 0) {
- paddingSz = (16 - (sz - ssl->specs.aead_mac_size) % 16);
- if (paddingSz < 0)
- return INPUT_CASE_ERROR;
-
- if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, paddingSz))
- != 0)
- return ret;
- }
-
- /* add size of AD and size of cipher to poly input */
- XMEMSET(padding, 0, sizeof(padding));
- padding[0] = blockSz;
-
- /* 32 bit size of cipher to 64 bit endian */
- padding[8] = msglen & 0xff;
- padding[9] = (msglen >> 8) & 0xff;
- padding[10] = (msglen >>16) & 0xff;
- padding[11] = (msglen >>24) & 0xff;
- if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
- != 0)
- return ret;
-
- /* generate tag */
- if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
- return ret;
-
- return ret;
-}
-
-
/* Used for the older version of creating AEAD tags with Poly1305 */
static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
byte* cipher, word16 sz, byte* tag)
@@ -5213,7 +13127,7 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
int ret = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
word32 keySz = 32;
- byte padding[8]; /* used to temporarly store lengths */
+ byte padding[8]; /* used to temporarily store lengths */
#ifdef CHACHA_AEAD_TEST
printf("Using old version of poly1305 input.\n");
@@ -5225,9 +13139,6 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
return ret;
- /* add TLS compressed length and additional input to poly1305 */
- additional[AEAD_AUTH_DATA_SZ - 2] = (msglen >> 8) & 0xff;
- additional[AEAD_AUTH_DATA_SZ - 1] = msglen & 0xff;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
AEAD_AUTH_DATA_SZ)) != 0)
return ret;
@@ -5248,8 +13159,8 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
/* 32 bit size of cipher to 64 bit endian */
padding[0] = msglen & 0xff;
padding[1] = (msglen >> 8) & 0xff;
- padding[2] = (msglen >> 16) & 0xff;
- padding[3] = (msglen >> 24) & 0xff;
+ padding[2] = ((word32)msglen >> 16) & 0xff;
+ padding[3] = ((word32)msglen >> 24) & 0xff;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
!= 0)
return ret;
@@ -5262,46 +13173,65 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
}
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implementation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automatically depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparison to the more recent RFC.
+ *
+ * ssl WOLFSSL structure to get cipher and TLS state from
+ * out output buffer to hold encrypted data
+ * input data to encrypt
+ * sz size of input
+ *
+ * Return 0 on success negative values in error case
+ */
static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
word16 sz)
{
const byte* additionalSrc = input - RECORD_HEADER_SZ;
- int ret = 0;
+ int ret = 0;
+ word32 msgLen = (sz - ssl->specs.aead_mac_size);
byte tag[POLY1305_AUTH_SZ];
- byte additional[CHACHA20_BLOCK_SIZE];
- byte nonce[AEAD_NONCE_SZ];
- byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
+ byte add[AEAD_AUTH_DATA_SZ];
+ byte nonce[CHACHA20_NONCE_SZ];
+ byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
#ifdef CHACHA_AEAD_TEST
int i;
#endif
- XMEMSET(tag, 0, sizeof(tag));
- XMEMSET(nonce, 0, AEAD_NONCE_SZ);
- XMEMSET(cipher, 0, sizeof(cipher));
- XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
-
- /* get nonce */
- c32toa(ssl->keys.sequence_number, nonce + AEAD_IMP_IV_SZ
- + AEAD_SEQ_OFFSET);
+ XMEMSET(tag, 0, sizeof(tag));
+ XMEMSET(nonce, 0, sizeof(nonce));
+ XMEMSET(poly, 0, sizeof(poly));
+ XMEMSET(add, 0, sizeof(add));
/* opaque SEQ number stored for AD */
- c32toa(GetSEQIncrement(ssl, 0), additional + AEAD_SEQ_OFFSET);
+ WriteSEQ(ssl, CUR_ORDER, add);
+
+ if (ssl->options.oldPoly != 0) {
+ /* get nonce. SEQ should not be incremented again here */
+ XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+ }
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
- c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
- XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
+ /* add TLS message size to additional data */
+ add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+ add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
+
+ XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
#ifdef CHACHA_AEAD_TEST
printf("Encrypt Additional : ");
- for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
- printf("%02x", additional[i]);
+ for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+ printf("%02x", add[i]);
}
printf("\n\n");
printf("input before encryption :\n");
@@ -5313,36 +13243,73 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
printf("\n");
#endif
+ if (ssl->options.oldPoly == 0) {
+ /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+ * record sequence number XORed with client_write_IV/server_write_IV */
+ XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
+ nonce[4] ^= add[0];
+ nonce[5] ^= add[1];
+ nonce[6] ^= add[2];
+ nonce[7] ^= add[3];
+ nonce[8] ^= add[4];
+ nonce[9] ^= add[5];
+ nonce[10] ^= add[6];
+ nonce[11] ^= add[7];
+ }
+
/* set the nonce for chacha and get poly1305 key */
- if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0)
+ if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
return ret;
+ }
- if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, cipher,
- cipher, sizeof(cipher))) != 0)
+ /* create Poly1305 key using chacha20 keystream */
+ if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly,
+ poly, sizeof(poly))) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
return ret;
+ }
+
+ /* set the counter after getting poly1305 key */
+ if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1)) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
+ return ret;
+ }
+ ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
/* encrypt the plain text */
- if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, input,
- sz - ssl->specs.aead_mac_size)) != 0)
+ if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out,
+ input, msgLen)) != 0) {
+ ForceZero(poly, sizeof(poly));
return ret;
+ }
- /* get the tag : future use of hmac could go here*/
- if (ssl->options.oldPoly == 1) {
- if ((ret = Poly1305TagOld(ssl, additional, (const byte* )out,
- cipher, sz, tag)) != 0)
+ /* get the poly1305 tag using either old padding scheme or more recent */
+ if (ssl->options.oldPoly != 0) {
+ if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
+ poly, sz, tag)) != 0) {
+ ForceZero(poly, sizeof(poly));
return ret;
+ }
}
else {
- if ((ret = Poly1305Tag(ssl, additional, (const byte* )out,
- cipher, sz, tag)) != 0)
+ if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+ sizeof(poly))) != 0) {
+ ForceZero(poly, sizeof(poly));
+ return ret;
+ }
+ if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+ sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
+ ForceZero(poly, sizeof(poly));
return ret;
+ }
}
+ ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
/* append tag to ciphertext */
- XMEMCPY(out + sz - ssl->specs.aead_mac_size, tag, sizeof(tag));
+ XMEMCPY(out + msgLen, tag, sizeof(tag));
AeadIncrementExpIV(ssl);
- ForceZero(nonce, AEAD_NONCE_SZ);
#ifdef CHACHA_AEAD_TEST
printf("mac tag :\n");
@@ -5364,19 +13331,29 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
}
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implementation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automatically depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparison to the more recent RFC.
+ *
+ * ssl WOLFSSL structure to get cipher and TLS state from
+ * plain output buffer to hold decrypted data
+ * input data to decrypt
+ * sz size of input
+ *
+ * Return 0 on success negative values in error case
+ */
static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
word16 sz)
{
- byte additional[CHACHA20_BLOCK_SIZE];
- byte nonce[AEAD_NONCE_SZ];
+ byte add[AEAD_AUTH_DATA_SZ];
+ byte nonce[CHACHA20_NONCE_SZ];
byte tag[POLY1305_AUTH_SZ];
- byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
- int ret = 0;
-
- XMEMSET(tag, 0, sizeof(tag));
- XMEMSET(cipher, 0, sizeof(cipher));
- XMEMSET(nonce, 0, AEAD_NONCE_SZ);
- XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
+ byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
+ int ret = 0;
+ int msgLen = (sz - ssl->specs.aead_mac_size);
#ifdef CHACHA_AEAD_TEST
int i;
@@ -5389,64 +13366,103 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
printf("\n");
#endif
- /* get nonce */
- c32toa(ssl->keys.peer_sequence_number, nonce + AEAD_IMP_IV_SZ
- + AEAD_SEQ_OFFSET);
+ XMEMSET(tag, 0, sizeof(tag));
+ XMEMSET(poly, 0, sizeof(poly));
+ XMEMSET(nonce, 0, sizeof(nonce));
+ XMEMSET(add, 0, sizeof(add));
- /* sequence number field is 64-bits, we only use 32-bits */
- c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
+ /* sequence number field is 64-bits */
+ WriteSEQ(ssl, PEER_ORDER, add);
- /* get AD info */
- additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+ if (ssl->options.oldPoly != 0) {
+ /* get nonce, SEQ should not be incremented again here */
+ XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+ }
+ /* get AD info */
/* Store the type, version. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- c16toa(ssl->keys.dtls_state.curEpoch, additional);
- #endif
+ add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+ add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+ add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+ /* add TLS message size to additional data */
+ add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+ add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
#ifdef CHACHA_AEAD_TEST
printf("Decrypt Additional : ");
- for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
- printf("%02x", additional[i]);
+ for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+ printf("%02x", add[i]);
}
printf("\n\n");
#endif
+ if (ssl->options.oldPoly == 0) {
+ /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+ * record sequence number XORed with client_write_IV/server_write_IV */
+ XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
+ nonce[4] ^= add[0];
+ nonce[5] ^= add[1];
+ nonce[6] ^= add[2];
+ nonce[7] ^= add[3];
+ nonce[8] ^= add[4];
+ nonce[9] ^= add[5];
+ nonce[10] ^= add[6];
+ nonce[11] ^= add[7];
+ }
+
/* set nonce and get poly1305 key */
- if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0)
+ if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
+ return ret;
+ }
+
+ /* use chacha20 keystream to get poly1305 key for tag */
+ if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly,
+ poly, sizeof(poly))) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
return ret;
+ }
- if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, cipher,
- cipher, sizeof(cipher))) != 0)
+ /* set counter after getting poly1305 key */
+ if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1)) != 0) {
+ ForceZero(nonce, CHACHA20_NONCE_SZ);
return ret;
+ }
+ ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
- /* get the tag : future use of hmac could go here*/
- if (ssl->options.oldPoly == 1) {
- if ((ret = Poly1305TagOld(ssl, additional, input, cipher,
- sz, tag)) != 0)
+ /* get the tag using Poly1305 */
+ if (ssl->options.oldPoly != 0) {
+ if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
+ ForceZero(poly, sizeof(poly));
return ret;
+ }
}
else {
- if ((ret = Poly1305Tag(ssl, additional, input, cipher,
- sz, tag)) != 0)
+ if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+ sizeof(poly))) != 0) {
+ ForceZero(poly, sizeof(poly));
return ret;
+ }
+ if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+ sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) {
+ ForceZero(poly, sizeof(poly));
+ return ret;
+ }
}
+ ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
- /* check mac sent along with packet */
- if (ConstantCompare(input + sz - ssl->specs.aead_mac_size, tag,
- ssl->specs.aead_mac_size) != 0) {
- WOLFSSL_MSG("Mac did not match");
- SendAlert(ssl, alert_fatal, bad_record_mac);
- ForceZero(nonce, AEAD_NONCE_SZ);
+ /* check tag sent along with packet */
+ if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) {
+ WOLFSSL_MSG("MAC did not match");
+ if (!ssl->options.dtls)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
return VERIFY_MAC_ERROR;
}
- /* if mac was good decrypt message */
- if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, input,
- sz - ssl->specs.aead_mac_size)) != 0)
+ /* if the tag was good decrypt message */
+ if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
+ input, msgLen)) != 0)
return ret;
#ifdef CHACHA_AEAD_TEST
@@ -5465,175 +13481,313 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
#endif /* HAVE_AEAD */
-static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
+#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
+
+
+static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
+ word16 sz, int asyncOkay)
{
int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ WC_ASYNC_DEV* asyncDev = NULL;
+ word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
+#else
+ (void)asyncOkay;
+#endif
(void)out;
(void)input;
(void)sz;
- if (ssl->encrypt.setup == 0) {
- WOLFSSL_MSG("Encrypt ciphers not setup");
- return ENCRYPT_ERROR;
- }
-
-#ifdef HAVE_FUZZER
- if (ssl->fuzzerCb)
- ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
-#endif
-
switch (ssl->specs.bulk_cipher_algorithm) {
- #ifdef BUILD_ARC4
- case wolfssl_rc4:
- wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
+ #ifdef BUILD_ARC4
+ case wolfssl_rc4:
+ wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case wolfssl_triple_des:
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ asyncDev = &ssl->encrypt.des3->asyncDev;
+ ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+ if (ret != 0)
break;
#endif
- #ifdef BUILD_DES3
- case wolfssl_triple_des:
- ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
+ ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E && asyncOkay) {
+ ret = wolfSSL_AsyncPush(ssl, asyncDev);
+ }
+ #endif
+ break;
+ #endif
+
+ #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
+ case wolfssl_aes:
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ asyncDev = &ssl->encrypt.aes->asyncDev;
+ ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+ if (ret != 0)
break;
#endif
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+ if (tsip_useable(ssl)) {
+ ret = wc_tsip_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+ } else
+ #endif
+ ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E && asyncOkay) {
+ ret = wolfSSL_AsyncPush(ssl, asyncDev);
+ }
+ #endif
+ break;
+ #endif
+
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ case wolfssl_aes_gcm:
+ case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */
+ {
+ AES_AUTH_ENCRYPT_FUNC aes_auth_fn;
+ const byte* additionalSrc;
- #ifdef BUILD_AES
- case wolfssl_aes:
- ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ asyncDev = &ssl->encrypt.aes->asyncDev;
+ ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+ if (ret != 0)
break;
#endif
- #ifdef BUILD_AESGCM
- case wolfssl_aes_gcm:
- {
- byte additional[AEAD_AUTH_DATA_SZ];
- byte nonce[AEAD_NONCE_SZ];
- const byte* additionalSrc = input - 5;
+ #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+ aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+ ? AES_GCM_ENCRYPT : AES_CCM_ENCRYPT;
+ #elif defined(BUILD_AESGCM)
+ aes_auth_fn = AES_GCM_ENCRYPT;
+ #else
+ aes_auth_fn = AES_CCM_ENCRYPT;
+ #endif
+ additionalSrc = input - 5;
- XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
+ XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
- /* sequence number field is 64-bits, we only use 32-bits */
- c32toa(GetSEQIncrement(ssl, 0),
- additional + AEAD_SEQ_OFFSET);
+ /* sequence number field is 64-bits */
+ WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
- /* Store the type, version. Unfortunately, they are in
- * the input buffer ahead of the plaintext. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- c16toa(ssl->keys.dtls_epoch, additional);
- additionalSrc -= DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
-
- /* Store the length of the plain text minus the explicit
- * IV length minus the authentication tag size. */
- c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- additional + AEAD_LEN_OFFSET);
- XMEMCPY(nonce,
- ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ);
- XMEMCPY(nonce + AEAD_IMP_IV_SZ,
- ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
- ret = wc_AesGcmEncrypt(ssl->encrypt.aes,
- out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ,
- sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- nonce, AEAD_NONCE_SZ,
- out + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- additional, AEAD_AUTH_DATA_SZ);
- if (ret == 0)
- AeadIncrementExpIV(ssl);
- ForceZero(nonce, AEAD_NONCE_SZ);
- }
- break;
+ /* Store the type, version. Unfortunately, they are in
+ * the input buffer ahead of the plaintext. */
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+ }
#endif
+ XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
+ additionalSrc, 3);
+
+ /* Store the length of the plain text minus the explicit
+ * IV length minus the authentication tag size. */
+ c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+ ssl->encrypt.additional + AEAD_LEN_OFFSET);
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+ ((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);
+ XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ,
+ ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
+#endif
+ ret = aes_auth_fn(ssl->encrypt.aes,
+ out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
+ sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+ ssl->encrypt.nonce, AESGCM_NONCE_SZ,
+ out + sz - ssl->specs.aead_mac_size,
+ ssl->specs.aead_mac_size,
+ ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E && asyncOkay) {
+ ret = wolfSSL_AsyncPush(ssl, asyncDev);
+ }
+ #endif
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+ ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+ XMEMCPY(out,
+ ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ);
+#endif
+ }
+ break;
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
- #ifdef HAVE_AESCCM
- case wolfssl_aes_ccm:
- {
- byte additional[AEAD_AUTH_DATA_SZ];
- byte nonce[AEAD_NONCE_SZ];
- const byte* additionalSrc = input - 5;
+ #ifdef HAVE_CAMELLIA
+ case wolfssl_camellia:
+ ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
+ break;
+ #endif
- XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
+ #ifdef HAVE_HC128
+ case wolfssl_hc128:
+ ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
+ break;
+ #endif
- /* sequence number field is 64-bits, we only use 32-bits */
- c32toa(GetSEQIncrement(ssl, 0),
- additional + AEAD_SEQ_OFFSET);
+ #ifdef BUILD_RABBIT
+ case wolfssl_rabbit:
+ ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
+ break;
+ #endif
- /* Store the type, version. Unfortunately, they are in
- * the input buffer ahead of the plaintext. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- c16toa(ssl->keys.dtls_epoch, additional);
- additionalSrc -= DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
-
- /* Store the length of the plain text minus the explicit
- * IV length minus the authentication tag size. */
- c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- additional + AEAD_LEN_OFFSET);
- XMEMCPY(nonce,
- ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ);
- XMEMCPY(nonce + AEAD_IMP_IV_SZ,
- ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
- wc_AesCcmEncrypt(ssl->encrypt.aes,
- out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ,
- sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- nonce, AEAD_NONCE_SZ,
- out + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- additional, AEAD_AUTH_DATA_SZ);
- AeadIncrementExpIV(ssl);
- ForceZero(nonce, AEAD_NONCE_SZ);
- }
- break;
- #endif
+ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+ case wolfssl_chacha:
+ ret = ChachaAEADEncrypt(ssl, out, input, sz);
+ break;
+ #endif
- #ifdef HAVE_CAMELLIA
- case wolfssl_camellia:
- wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
- break;
- #endif
+ #ifdef HAVE_NULL_CIPHER
+ case wolfssl_cipher_null:
+ if (input != out) {
+ XMEMMOVE(out, input, sz);
+ }
+ break;
+ #endif
- #ifdef HAVE_HC128
- case wolfssl_hc128:
- ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
- break;
- #endif
+ #ifdef HAVE_IDEA
+ case wolfssl_idea:
+ ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz);
+ break;
+ #endif
- #ifdef BUILD_RABBIT
- case wolfssl_rabbit:
- ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
- break;
- #endif
+ default:
+ WOLFSSL_MSG("wolfSSL Encrypt programming error");
+ ret = ENCRYPT_ERROR;
+ }
- #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
- case wolfssl_chacha:
- ret = ChachaAEADEncrypt(ssl, out, input, sz);
- break;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* if async is not okay, then block */
+ if (ret == WC_PENDING_E && !asyncOkay) {
+ ret = wc_AsyncWait(ret, asyncDev, event_flags);
+ }
+#endif
+
+ return ret;
+}
+
+static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
+ int asyncOkay)
+{
+ int ret = 0;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ssl->error == WC_PENDING_E) {
+ ssl->error = 0; /* clear async */
+ }
+#endif
+
+ switch (ssl->encrypt.state) {
+ case CIPHER_STATE_BEGIN:
+ {
+ if (ssl->encrypt.setup == 0) {
+ WOLFSSL_MSG("Encrypt ciphers not setup");
+ return ENCRYPT_ERROR;
+ }
+
+ #ifdef HAVE_FUZZER
+ if (ssl->fuzzerCb)
+ ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
#endif
- #ifdef HAVE_NULL_CIPHER
- case wolfssl_cipher_null:
- if (input != out) {
- XMEMMOVE(out, input, sz);
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ /* make sure AES GCM/CCM memory is allocated */
+ /* free for these happens in FreeCiphers */
+ if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+ ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+ /* make sure auth iv and auth are allocated */
+ if (ssl->encrypt.additional == NULL)
+ ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+ ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ if (ssl->encrypt.nonce == NULL)
+ ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+ ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ if (ssl->encrypt.additional == NULL ||
+ ssl->encrypt.nonce == NULL) {
+ return MEMORY_E;
}
- break;
+ }
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+ /* Advance state and proceed */
+ ssl->encrypt.state = CIPHER_STATE_DO;
+ }
+ FALL_THROUGH;
+
+ case CIPHER_STATE_DO:
+ {
+ ret = EncryptDo(ssl, out, input, sz, asyncOkay);
+
+ /* Advance state */
+ ssl->encrypt.state = CIPHER_STATE_END;
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* If pending, then leave and return will resume below */
+ if (ret == WC_PENDING_E) {
+ return ret;
+ }
#endif
+ }
+ FALL_THROUGH;
- default:
- WOLFSSL_MSG("wolfSSL Encrypt programming error");
- ret = ENCRYPT_ERROR;
+ case CIPHER_STATE_END:
+ {
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+ ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+ {
+ /* finalize authentication cipher */
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+ ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+ AeadIncrementExpIV(ssl);
+#endif
+ if (ssl->encrypt.nonce)
+ ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ);
+ }
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
+ break;
+ }
}
+ /* Reset state */
+ ssl->encrypt.state = CIPHER_STATE_BEGIN;
+
return ret;
}
-
-static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
word16 sz)
{
int ret = 0;
@@ -5642,162 +13796,300 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
(void)input;
(void)sz;
- if (ssl->decrypt.setup == 0) {
- WOLFSSL_MSG("Decrypt ciphers not setup");
- return DECRYPT_ERROR;
- }
+ switch (ssl->specs.bulk_cipher_algorithm)
+ {
+ #ifdef BUILD_ARC4
+ case wolfssl_rc4:
+ wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
+ break;
+ #endif
- switch (ssl->specs.bulk_cipher_algorithm) {
- #ifdef BUILD_ARC4
- case wolfssl_rc4:
- wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
+ #ifdef BUILD_DES3
+ case wolfssl_triple_des:
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
+ WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
break;
#endif
- #ifdef BUILD_DES3
- case wolfssl_triple_des:
- ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
+ ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
+ }
+ #endif
+ break;
+ #endif
+
+ #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
+ case wolfssl_aes:
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+ WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
break;
#endif
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+ if (tsip_useable(ssl)) {
+ ret = wc_tsip_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+ } else
+ #endif
+ ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+ }
+ #endif
+ break;
+ #endif
+
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ case wolfssl_aes_gcm:
+ case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
+ {
+ wc_AesAuthDecryptFunc aes_auth_fn;
- #ifdef BUILD_AES
- case wolfssl_aes:
- ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* initialize event */
+ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+ WC_ASYNC_FLAG_CALL_AGAIN);
+ if (ret != 0)
break;
#endif
- #ifdef BUILD_AESGCM
- case wolfssl_aes_gcm:
- {
- byte additional[AEAD_AUTH_DATA_SZ];
- byte nonce[AEAD_NONCE_SZ];
+ #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+ aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+ ? wc_AesGcmDecrypt : wc_AesCcmDecrypt;
+ #elif defined(BUILD_AESGCM)
+ aes_auth_fn = wc_AesGcmDecrypt;
+ #else
+ aes_auth_fn = wc_AesCcmDecrypt;
+ #endif
- XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
+ XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
+
+ /* sequence number field is 64-bits */
+ WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
+
+ ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+ ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+ ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+ c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+ ssl->decrypt.additional + AEAD_LEN_OFFSET);
+ 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 + AESGCM_EXP_IV_SZ,
+ input + AESGCM_EXP_IV_SZ,
+ sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+ ssl->decrypt.nonce, AESGCM_NONCE_SZ,
+ input + sz - ssl->specs.aead_mac_size,
+ ssl->specs.aead_mac_size,
+ ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+ }
+ #endif
+ }
+ }
+ break;
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
- /* sequence number field is 64-bits, we only use 32-bits */
- c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
+ #ifdef HAVE_CAMELLIA
+ case wolfssl_camellia:
+ ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
+ break;
+ #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- c16toa(ssl->keys.dtls_state.curEpoch, additional);
- #endif
+ #ifdef HAVE_HC128
+ case wolfssl_hc128:
+ ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
+ break;
+ #endif
- additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
- c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- additional + AEAD_LEN_OFFSET);
- XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ);
- XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ);
- if (wc_AesGcmDecrypt(ssl->decrypt.aes,
- plain + AEAD_EXP_IV_SZ,
- input + AEAD_EXP_IV_SZ,
- sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- nonce, AEAD_NONCE_SZ,
- input + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- additional, AEAD_AUTH_DATA_SZ) < 0) {
- SendAlert(ssl, alert_fatal, bad_record_mac);
- ret = VERIFY_MAC_ERROR;
- }
- ForceZero(nonce, AEAD_NONCE_SZ);
+ #ifdef BUILD_RABBIT
+ case wolfssl_rabbit:
+ ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
+ break;
+ #endif
+
+ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+ case wolfssl_chacha:
+ ret = ChachaAEADDecrypt(ssl, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef HAVE_NULL_CIPHER
+ case wolfssl_cipher_null:
+ if (input != plain) {
+ XMEMMOVE(plain, input, sz);
}
break;
- #endif
+ #endif
- #ifdef HAVE_AESCCM
- case wolfssl_aes_ccm:
- {
- byte additional[AEAD_AUTH_DATA_SZ];
- byte nonce[AEAD_NONCE_SZ];
+ #ifdef HAVE_IDEA
+ case wolfssl_idea:
+ ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz);
+ break;
+ #endif
- XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
+ default:
+ WOLFSSL_MSG("wolfSSL Decrypt programming error");
+ ret = DECRYPT_ERROR;
+ }
- /* sequence number field is 64-bits, we only use 32-bits */
- c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
+ return ret;
+}
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- c16toa(ssl->keys.dtls_state.curEpoch, additional);
- #endif
+static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+ word16 sz)
+{
+ int ret = 0;
- additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
- c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- additional + AEAD_LEN_OFFSET);
- XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ);
- XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ);
- if (wc_AesCcmDecrypt(ssl->decrypt.aes,
- plain + AEAD_EXP_IV_SZ,
- input + AEAD_EXP_IV_SZ,
- sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
- nonce, AEAD_NONCE_SZ,
- input + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- additional, AEAD_AUTH_DATA_SZ) < 0) {
- SendAlert(ssl, alert_fatal, bad_record_mac);
- ret = VERIFY_MAC_ERROR;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
+ if (ret != WC_NOT_PENDING_E) {
+ /* check for still pending */
+ if (ret == WC_PENDING_E)
+ return ret;
+
+ ssl->error = 0; /* clear async */
+
+ /* let failures through so CIPHER_STATE_END logic is run */
+ }
+ else
+#endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->decrypt.state = CIPHER_STATE_BEGIN;
+ }
+
+ switch (ssl->decrypt.state) {
+ case CIPHER_STATE_BEGIN:
+ {
+ if (ssl->decrypt.setup == 0) {
+ WOLFSSL_MSG("Decrypt ciphers not setup");
+ return DECRYPT_ERROR;
+ }
+
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ /* make sure AES GCM/CCM memory is allocated */
+ /* free for these happens in FreeCiphers */
+ if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+ ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+ /* make sure auth iv and auth are allocated */
+ if (ssl->decrypt.additional == NULL)
+ ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+ ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ if (ssl->decrypt.nonce == NULL)
+ ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+ ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+ if (ssl->decrypt.additional == NULL ||
+ ssl->decrypt.nonce == NULL) {
+ return MEMORY_E;
}
- ForceZero(nonce, AEAD_NONCE_SZ);
}
- break;
- #endif
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
- #ifdef HAVE_CAMELLIA
- case wolfssl_camellia:
- wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
- break;
- #endif
+ /* Advance state and proceed */
+ ssl->decrypt.state = CIPHER_STATE_DO;
+ }
+ FALL_THROUGH;
+ case CIPHER_STATE_DO:
+ {
+ ret = DecryptDo(ssl, plain, input, sz);
- #ifdef HAVE_HC128
- case wolfssl_hc128:
- ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
- break;
- #endif
+ /* Advance state */
+ ssl->decrypt.state = CIPHER_STATE_END;
- #ifdef BUILD_RABBIT
- case wolfssl_rabbit:
- ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
- break;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* If pending, leave and return below */
+ if (ret == WC_PENDING_E) {
+ return ret;
+ }
#endif
+ }
+ FALL_THROUGH;
+ case CIPHER_STATE_END:
+ {
+ #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+ /* 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) {
+ if (ssl->decrypt.nonce)
+ ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ);
- #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
- case wolfssl_chacha:
- ret = ChachaAEADDecrypt(ssl, plain, input, sz);
- break;
- #endif
+ if (ret < 0)
+ ret = VERIFY_MAC_ERROR;
+ }
+ #endif /* BUILD_AESGCM || HAVE_AESCCM */
+ break;
+ }
+ }
- #ifdef HAVE_NULL_CIPHER
- case wolfssl_cipher_null:
- if (input != plain) {
- XMEMMOVE(plain, input, sz);
- }
- break;
- #endif
+ /* Reset state */
+ ssl->decrypt.state = CIPHER_STATE_BEGIN;
- default:
- WOLFSSL_MSG("wolfSSL Decrypt programming error");
- ret = DECRYPT_ERROR;
+ /* handle mac error case */
+ if (ret == VERIFY_MAC_ERROR) {
+ if (!ssl->options.dtls)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+
+ #ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->macDropCount++;
+ #endif /* WOLFSSL_DTLS_DROP_STATS */
}
return ret;
}
+#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 == aead) &&
+ (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha);
+}
/* check cipher text size for sanity */
static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
{
#ifdef HAVE_TRUNCATED_HMAC
- word32 minLength = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ
+ 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 == 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");
+ return SANITY_CIPHER_E;
+ }
+ }
+ else
+#endif
if (encryptSz % ssl->specs.block_size) {
WOLFSSL_MSG("Block ciphertext not block size");
return SANITY_CIPHER_E;
@@ -5811,10 +14103,12 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
if (ssl->options.tls1_1)
minLength += ssl->specs.block_size; /* explicit IV */
}
- else if (ssl->specs.cipher_type == aead) {
+ else
+#endif
+ if (ssl->specs.cipher_type == aead) {
minLength = ssl->specs.aead_mac_size; /* authTag size */
- if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- minLength += AEAD_EXP_IV_SZ; /* explicit IV */
+ if (CipherHasExpIV(ssl))
+ minLength += AESGCM_EXP_IV_SZ; /* explicit IV */
}
if (encryptSz < minLength) {
@@ -5826,251 +14120,145 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
}
-#ifndef NO_OLD_TLS
-
-static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
-{
- Md5 md5;
- int i;
-
- wc_InitMd5(&md5);
-
- for (i = 0; i < rounds; i++)
- wc_Md5Update(&md5, data, sz);
-}
-
-
-
-/* do a dummy sha round */
-static INLINE void ShaRounds(int rounds, const byte* data, int sz)
-{
- 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);
-}
-#endif
-
-
-#ifndef NO_SHA256
-
-static INLINE void Sha256Rounds(int rounds, const byte* data, int sz)
+#ifndef WOLFSSL_AEAD_ONLY
+/* check all length bytes for the pad value, return 0 on success */
+static int PadCheck(const byte* a, byte pad, int length)
{
- Sha256 sha256;
int i;
+ int compareSum = 0;
- 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 */
+ for (i = 0; i < length; i++) {
+ compareSum |= a[i] ^ pad;
}
+ return compareSum;
}
-#endif
-
-#ifdef WOLFSSL_SHA384
-
-static INLINE void Sha384Rounds(int rounds, const byte* data, int sz)
+/* 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)
{
- Sha384 sha384;
int i;
+ int checkSz = sz - 1;
+ byte paddingSz = data[sz - 1];
+ byte mask;
+ byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
- wc_InitSha384(&sha384); /* no error check on purpose, dummy round */
+ if (checkSz > TLS_MAX_PAD_SZ)
+ checkSz = TLS_MAX_PAD_SZ;
- for (i = 0; i < rounds; i++) {
- wc_Sha384Update(&sha384, data, sz);
- /* no error check on purpose, dummy round */
+ for (i = 0; i < checkSz; i++) {
+ mask = ctMaskLTE(i, paddingSz);
+ good |= mask & (data[sz - 1 - i] ^ paddingSz);
}
-}
-
-#endif
-
-#ifdef WOLFSSL_SHA512
-
-static INLINE void Sha512Rounds(int rounds, const byte* data, int sz)
-{
- 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 */
- }
+ return good;
}
-#endif
-
-
-#ifdef WOLFSSL_RIPEMD
-
-static 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 INLINE void DoRounds(int type, int rounds, const byte* data, int sz)
+/* 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)
{
- switch (type) {
-
- case no_mac :
- break;
-
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
- case md5_mac :
- Md5Rounds(rounds, data, sz);
- break;
-#endif
-
+ 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
- case sha_mac :
- ShaRounds(rounds, data, sz);
- break;
-#endif
-#endif
-
-#ifndef NO_SHA256
- case sha256_mac :
- Sha256Rounds(rounds, data, sz);
- break;
+ else if (macSz == WC_SHA_DIGEST_SIZE)
+ r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
#endif
-
#ifdef WOLFSSL_SHA384
- case sha384_mac :
- Sha384Rounds(rounds, data, sz);
- break;
+ else if (macSz == WC_SHA384_DIGEST_SIZE)
+ r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
#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;
+ 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];
+ }
}
-}
-
-
-/* do number of compression rounds on dummy data */
-static 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;
+ 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 compareSum;
-}
-
-
-/* get compression extra rounds */
-static 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;
+ return good;
}
-
/* timing resistant pad/verify check, return 0 on success */
-static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
- int pLen, int content)
+int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
+ int pLen, int content)
{
- byte verify[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;
+ byte verify[WC_MAX_DIGEST_SIZE];
+ byte good;
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);
- ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
- ConstantCompare(verify, input + pLen - t, t);
-
- 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);
- ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
- ConstantCompare(verify, input + pLen - t, t);
-
- return VERIFY_MAC_ERROR;
- }
-
- PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
- ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1);
-
- CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy);
-
- if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) {
- WOLFSSL_MSG("Verify MAC compare failed");
- return VERIFY_MAC_ERROR;
- }
-
+ 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 = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
+ content, 1);
+ good |= MaskMac(input, pLen, ssl->specs.hash_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)
- return VERIFY_MAC_ERROR;
- return 0;
+ ret = VERIFY_MAC_ERROR;
+
+ return ret;
}
+#endif
int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
@@ -6084,26 +14272,58 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) {
+ if (ssl->options.side == WOLFSSL_SERVER_END &&
+ ssl->earlyData != no_early_data &&
+ ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
+ ssl->earlyDataSz += ssl->curSize;
+ if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) {
+ WOLFSSL_MSG("Ignoring EarlyData!");
+ *inOutIdx = ssl->buffers.inputBuffer.length;
+ return 0;
+ }
+ WOLFSSL_MSG("Too much EarlyData!");
+ }
+ }
+#endif
if (ssl->options.handShakeDone == 0) {
WOLFSSL_MSG("Received App data before a handshake completed");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
+#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block) {
if (ssl->options.tls1_1)
ivExtra = ssl->specs.block_size;
}
- else if (ssl->specs.cipher_type == aead) {
- if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- ivExtra = AEAD_EXP_IV_SZ;
+ else
+#endif
+ if (ssl->specs.cipher_type == 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?");
+ SendAlert(ssl, alert_fatal, unexpected_message);
return BUFFER_ERROR;
}
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->earlyData > early_data_ext) {
+ if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->earlyDataSz += dataSz;
+ }
+#endif
/* read data */
if (dataSz) {
@@ -6122,6 +14342,10 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
}
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 */
@@ -6140,19 +14364,33 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
{
byte level;
byte code;
+ word32 dataSz = totalSz - *inOutIdx;
- #ifdef WOLFSSL_CALLBACKS
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("Alert", &ssl->handShakeInfo);
+ AddPacketName(ssl, "Alert");
if (ssl->toInfoOn)
- /* add record header back on to info + 2 byte level, data */
- AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
- RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
+ /* add record header back on to info + alert bytes level/code */
+ AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx -
+ RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE,
+ READ_PROTO, ssl->heap);
+ #endif
+
+ if (IsEncryptionOn(ssl, 0)) {
+ 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 (*inOutIdx + ALERT_SIZE > totalSz)
+ if (dataSz != ALERT_SIZE) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, unexpected_message);
+#endif
return BUFFER_E;
+ }
level = input[(*inOutIdx)++];
code = input[(*inOutIdx)++];
@@ -6163,16 +14401,35 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
ssl->options.isClosed = 1; /* Don't send close_notify */
}
+ if (++ssl->options.alertCount >= 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
+ return ALERT_COUNT_E;
+ }
+
WOLFSSL_MSG("Got alert");
if (*type == close_notify) {
- WOLFSSL_MSG(" close notify");
+ WOLFSSL_MSG("\tclose notify");
ssl->options.closeNotify = 1;
}
+#ifdef WOLFSSL_TLS13
+ if (*type == decode_error) {
+ WOLFSSL_MSG("\tdecode error");
+ }
+ if (*type == illegal_parameter) {
+ WOLFSSL_MSG("\tillegal parameter");
+ }
+#endif
WOLFSSL_ERROR(*type);
- if (ssl->keys.encryptionOn) {
- if (*inOutIdx + ssl->keys.padSz > totalSz)
- return BUFFER_E;
+ 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;
@@ -6200,14 +14457,16 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
}
#endif
+ /* 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;
}
- if (inSz <= 0)
- return BUFFER_ERROR;
-
/* Put buffer data at start if not there */
if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
XMEMMOVE(ssl->buffers.inputBuffer.buffer,
@@ -6220,16 +14479,16 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
/* read data from network */
do {
- in = Receive(ssl,
+ in = wolfSSLReceive(ssl,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.length,
inSz);
- if (in == -1)
- return SOCKET_ERROR_E;
-
if (in == WANT_READ)
return WANT_READ;
+ if (in < 0)
+ return SOCKET_ERROR_E;
+
if (in > inSz)
return RECV_OVERFLOW_E;
@@ -6238,24 +14497,62 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
} while (ssl->buffers.inputBuffer.length < size);
+#ifdef WOLFSSL_DEBUG_TLS
+ if (ssl->buffers.inputBuffer.idx == 0) {
+ WOLFSSL_MSG("Data received");
+ WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer,
+ ssl->buffers.inputBuffer.length);
+ }
+#endif
+
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) {
+ return VERIFY_MAC_ERROR;
+ }
-static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
+ ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
+ ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz);
+ if (ret != 0) {
+ 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 ivExtra = 0;
int ret;
word32 pad = 0;
word32 padByte = 0;
#ifdef HAVE_TRUNCATED_HMAC
- word32 digestSz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ
+ word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
: ssl->specs.hash_size;
#else
word32 digestSz = ssl->specs.hash_size;
#endif
- byte verify[MAX_DIGEST_SIZE];
+ byte verify[WC_MAX_DIGEST_SIZE];
+
if (ssl->specs.cipher_type == block) {
if (ssl->options.tls1_1)
@@ -6283,8 +14580,8 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
badPadLen = 1;
}
PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */
- ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
- content, 1);
+ ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
+ content, 1);
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
digestSz) != 0)
return VERIFY_MAC_ERROR;
@@ -6293,20 +14590,27 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
}
}
else if (ssl->specs.cipher_type == stream) {
- ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, content, 1);
+ ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
return VERIFY_MAC_ERROR;
}
if (ret != 0)
return VERIFY_MAC_ERROR;
}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
if (ssl->specs.cipher_type == aead) {
*padSz = ssl->specs.aead_mac_size;
}
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
else {
*padSz = digestSz + pad + padByte;
}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
+
+ (void)input;
+ (void)msgSz;
+ (void)content;
return 0;
}
@@ -6319,7 +14623,7 @@ int ProcessReply(WOLFSSL* ssl)
int ret = 0, type, readSz;
int atomicUser = 0;
word32 startIdx = 0;
-#ifdef WOLFSSL_DTLS
+#if defined(WOLFSSL_DTLS)
int used;
#endif
@@ -6328,7 +14632,14 @@ int ProcessReply(WOLFSSL* ssl)
atomicUser = 1;
#endif
- if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE){
+ if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ssl->error != WC_PENDING_E
+ #endif
+ #ifdef WOLFSSL_NONBLOCK_OCSP
+ && ssl->error != OCSP_WANT_READ
+ #endif
+ ) {
WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
return ssl->error;
}
@@ -6342,10 +14653,10 @@ int ProcessReply(WOLFSSL* ssl)
readSz = RECORD_HEADER_SZ;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- readSz = DTLS_RECORD_HEADER_SZ;
- #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ readSz = DTLS_RECORD_HEADER_SZ;
+ #endif
/* get header or return error */
if (!ssl->options.dtls) {
@@ -6356,9 +14667,10 @@ int ProcessReply(WOLFSSL* ssl)
/* read ahead may already have header */
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
- if (used < readSz)
+ if (used < readSz) {
if ((ret = GetInputData(ssl, readSz)) < 0)
return ret;
+ }
#endif
}
@@ -6375,15 +14687,15 @@ int ProcessReply(WOLFSSL* ssl)
/* sanity checks before getting size at front */
if (ssl->buffers.inputBuffer.buffer[
- ssl->buffers.inputBuffer.idx + 2] != OLD_HELLO_ID) {
+ ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) {
WOLFSSL_MSG("Not a valid old client hello");
return PARSE_ERROR;
}
if (ssl->buffers.inputBuffer.buffer[
- ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR &&
+ ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR &&
ssl->buffers.inputBuffer.buffer[
- ssl->buffers.inputBuffer.idx + 3] != DTLS_MAJOR) {
+ ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) {
WOLFSSL_MSG("Not a valid version in old client hello");
return PARSE_ERROR;
}
@@ -6399,6 +14711,7 @@ int ProcessReply(WOLFSSL* ssl)
ssl->options.processReply = getRecordLayerHeader;
continue;
}
+ FALL_THROUGH;
/* in the WOLFSSL_SERVER case, run the old client hello */
case runProcessOldClientHello:
@@ -6433,6 +14746,7 @@ int ProcessReply(WOLFSSL* ssl)
}
#endif /* OLD_HELLO_ALLOWED */
+ FALL_THROUGH;
/* get the record layer header */
case getRecordLayerHeader:
@@ -6442,25 +14756,52 @@ int ProcessReply(WOLFSSL* ssl)
&ssl->curRL, &ssl->curSize);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls && ret == SEQUENCE_ERROR) {
+ WOLFSSL_MSG("Silently dropping out of order DTLS message");
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.length = 0;
ssl->buffers.inputBuffer.idx = 0;
+#ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->replayDropCount++;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+ if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) {
+ ret = DtlsMsgPoolSend(ssl, 0);
+ if (ret != 0)
+ return ret;
+ }
+
continue;
}
#endif
if (ret != 0)
return ret;
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) &&
+ ssl->curRL.type != application_data &&
+ ssl->curRL.type != change_cipher_spec) {
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ return PARSE_ERROR;
+ }
+#endif
+
ssl->options.processReply = getData;
+ FALL_THROUGH;
/* retrieve record layer data */
case getData:
/* get sz bytes or return error */
if (!ssl->options.dtls) {
- if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ 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;
- } else {
+ }
+ }
+ else {
#ifdef WOLFSSL_DTLS
/* read ahead may already have */
used = ssl->buffers.inputBuffer.length -
@@ -6471,159 +14812,500 @@ int ProcessReply(WOLFSSL* ssl)
#endif
}
- ssl->options.processReply = runProcessingOneMessage;
- startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
+ if (IsEncryptionOn(ssl, 0)) {
+ int tooLong = 0;
- /* the record layer is here */
- case runProcessingOneMessage:
+#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 (tooLong) {
+ WOLFSSL_MSG("Encrypted data too long");
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS)
+ SendAlert(ssl, alert_fatal, record_overflow);
+#endif
+ return BUFFER_ERROR;
+ }
+ }
+ ssl->keys.padSz = 0;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls &&
- ssl->keys.dtls_state.curEpoch < ssl->keys.dtls_state.nextEpoch)
- ssl->keys.decryptedCur = 1;
+ ssl->options.processReply = verifyEncryptedMessage;
+ startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
+ 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");
+ WOLFSSL_ERROR(ret);
+ #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;
+ #ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->macDropCount++;
+ #endif /* WOLFSSL_DTLS_DROP_STATS */
+ }
+ #endif /* WOLFSSL_DTLS */
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (!ssl->options.dtls)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ #endif
+ return DECRYPT_ERROR;
+ }
+ ssl->keys.encryptSz = ssl->curSize;
+ }
+#endif
+ ssl->options.processReply = decryptMessage;
+ FALL_THROUGH;
+
+ /* decrypt message */
+ case decryptMessage:
- if (ssl->keys.encryptionOn && ssl->keys.decryptedCur == 0)
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+ if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+ if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+ (!IsAtLeastTLSv1_3(ssl->version) ||
+ ssl->curRL.type != change_cipher_spec))
+#endif
{
+ bufferStatic* in = &ssl->buffers.inputBuffer;
+
ret = SanityCheckCipherText(ssl, ssl->curSize);
- if (ret < 0)
+ if (ret < 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ #endif
return ret;
+ }
if (atomicUser) {
- #ifdef ATOMIC_USER
- ret = ssl->ctx->DecryptVerifyCb(ssl,
- ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx,
- ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx,
- ssl->curSize, ssl->curRL.type, 1,
- &ssl->keys.padSz, ssl->DecryptVerifyCtx);
- if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
- ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
- /* go past TLSv1.1 IV */
- if (ssl->specs.cipher_type == aead &&
- ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
- #endif /* ATOMIC_USER */
+ #ifdef ATOMIC_USER
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMRead) {
+ 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->DecryptVerifyCtx);
+ }
+ else
+ #endif
+ {
+ ret = ssl->ctx->DecryptVerifyCb(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize, ssl->curRL.type, 1,
+ &ssl->keys.padSz, ssl->DecryptVerifyCtx);
+ }
+ #endif /* ATOMIC_USER */
}
else {
- ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx,
- ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx,
- ssl->curSize);
- if (ret < 0) {
- WOLFSSL_ERROR(ret);
- return DECRYPT_ERROR;
+ 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 = Decrypt(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize - digestSz);
+ ssl->keys.padSz =
+ in->buffer[in->idx + ssl->curSize - digestSz - 1];
+ ssl->keys.padSz += 1;
+ ssl->keys.decryptedCur = 1;
}
+ else
+ #endif
+ {
+ ret = Decrypt(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize);
+ }
+ #else
+ ret = DECRYPT_ERROR;
+ #endif
+ }
+ else
+ {
+ #ifdef WOLFSSL_TLS13
+ #if defined(WOLFSSL_TLS13_DRAFT_18) || \
+ defined(WOLFSSL_TLS13_DRAFT_22) || \
+ defined(WOLFSSL_TLS13_DRAFT_23)
+ ret = DecryptTls13(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize, NULL, 0);
+ #else
+ ret = DecryptTls13(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize,
+ (byte*)&ssl->curRL, RECORD_HEADER_SZ);
+ #endif
+ #else
+ ret = DECRYPT_ERROR;
+ #endif /* WOLFSSL_TLS13 */
+ }
+ }
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ return ret;
+ #endif
+
+ if (ret >= 0) {
+ #ifndef WOLFSSL_NO_TLS12
+ /* handle success */
+ #ifndef WOLFSSL_AEAD_ONLY
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
+ #endif
/* go past TLSv1.1 IV */
- if (ssl->specs.cipher_type == aead &&
- ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
+ if (CipherHasExpIV(ssl))
+ ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
+ #endif
+ }
+ else {
+ WOLFSSL_MSG("Decrypt failed");
+ WOLFSSL_ERROR(ret);
+ #ifdef WOLFSSL_EARLY_DATA
+ if (ssl->options.tls1_3) {
+ if (ssl->options.side == WOLFSSL_SERVER_END &&
+ ssl->earlyData != no_early_data &&
+ ssl->options.clientState <
+ CLIENT_FINISHED_COMPLETE) {
+ ssl->earlyDataSz += ssl->curSize;
+ if (ssl->earlyDataSz <=
+ ssl->options.maxEarlyDataSz) {
+ WOLFSSL_MSG("Ignoring EarlyData!");
+ if (ssl->keys.peer_sequence_number_lo-- == 0)
+ ssl->keys.peer_sequence_number_hi--;
+ ssl->options.processReply = doProcessInit;
+ ssl->buffers.inputBuffer.idx =
+ ssl->buffers.inputBuffer.length;
+ return 0;
+ }
+ WOLFSSL_MSG("Too much EarlyData!");
+ }
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ }
+ #endif
+ #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;
+ #ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->macDropCount++;
+ #endif /* WOLFSSL_DTLS_DROP_STATS */
+ }
+ #endif /* WOLFSSL_DTLS */
+ return DECRYPT_ERROR;
+ }
+ }
+
+ ssl->options.processReply = verifyMessage;
+ FALL_THROUGH;
+
+ /* verify digest of message */
+ case verifyMessage:
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+ if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+ if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+ (!IsAtLeastTLSv1_3(ssl->version) ||
+ ssl->curRL.type != change_cipher_spec))
+#endif
+ {
+ 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) {
+ WOLFSSL_MSG("VerifyMac failed");
+ WOLFSSL_ERROR(ret);
+ #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;
+ #ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->macDropCount++;
+ #endif /* WOLFSSL_DTLS_DROP_STATS */
+ }
+ #endif /* WOLFSSL_DTLS */
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (!ssl->options.dtls)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ #endif
+ return DECRYPT_ERROR;
+ }
}
- if (ret < 0) {
- WOLFSSL_ERROR(ret);
- return DECRYPT_ERROR;
- }
+
ssl->keys.encryptSz = ssl->curSize;
ssl->keys.decryptedCur = 1;
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ word16 i = (word16)(ssl->buffers.inputBuffer.length -
+ ssl->keys.padSz);
+ /* Remove padding from end of plain text. */
+ for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
+ if (ssl->buffers.inputBuffer.buffer[i] != 0)
+ break;
+ }
+ /* Get the real content type from the end of the data. */
+ ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
+ ssl->keys.padSz = ssl->buffers.inputBuffer.length - i;
+ }
+#endif
}
- if (ssl->options.dtls) {
- #ifdef WOLFSSL_DTLS
- DtlsUpdateWindow(&ssl->keys.dtls_state);
- #endif /* WOLFSSL_DTLS */
+ ssl->options.processReply = runProcessingOneMessage;
+ FALL_THROUGH;
+
+ /* the record layer is here */
+ case runProcessingOneMessage:
+
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) {
+ if (ssl->buffers.inputBuffer.length - ssl->keys.padSz -
+ ssl->buffers.inputBuffer.idx -
+ MacSize(ssl) > MAX_PLAINTEXT_SZ) {
+ WOLFSSL_MSG("Plaintext too long - Encrypt-Then-MAC");
+ #if defined(WOLFSSL_EXTRA_ALERTS)
+ SendAlert(ssl, alert_fatal, record_overflow);
+ #endif
+ return BUFFER_ERROR;
+ }
}
+ else
+ #endif
+ if (ssl->buffers.inputBuffer.length - ssl->keys.padSz -
+ ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ) {
+ WOLFSSL_MSG("Plaintext too long");
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS)
+ SendAlert(ssl, alert_fatal, record_overflow);
+#endif
+ return BUFFER_ERROR;
+ }
+
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ DtlsUpdateWindow(ssl);
+ }
+ #endif /* WOLFSSL_DTLS */
WOLFSSL_MSG("received record layer msg");
switch (ssl->curRL.type) {
case handshake :
/* debugging in DoHandShakeMsg */
- if (!ssl->options.dtls) {
+ if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+ ret = DoDtlsHandShakeMsg(ssl,
+ ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ ssl->buffers.inputBuffer.length);
+#endif
+ }
+ else if (!IsAtLeastTLSv1_3(ssl->version)) {
+#ifndef WOLFSSL_NO_TLS12
ret = DoHandShakeMsg(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
+#else
+ ret = BUFFER_ERROR;
+#endif
}
else {
-#ifdef WOLFSSL_DTLS
- ret = DoDtlsHandShakeMsg(ssl,
+#ifdef WOLFSSL_TLS13
+ 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)
+ if (ret != 0) {
+ WOLFSSL_ERROR(ret);
return ret;
+ }
break;
case change_cipher_spec:
WOLFSSL_MSG("got CHANGE CIPHER SPEC");
- #ifdef WOLFSSL_CALLBACKS
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ AddPacketName(ssl, "ChangeCipher");
/* add record header back on info */
if (ssl->toInfoOn) {
- AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
+ AddPacketInfo(ssl, "ChangeCipher",
+ change_cipher_spec,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
- 1 + RECORD_HEADER_SZ, ssl->heap);
+ 1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap);
+ #ifdef WOLFSSL_CALLBACKS
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ #endif
}
#endif
+#ifdef WOLFSSL_TLS13
+ #ifdef WOLFSSL_TLS13_DRAFT_18
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ return UNKNOWN_RECORD_TYPE;
+ }
+ #else
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ word32 i = ssl->buffers.inputBuffer.idx;
+ if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ return UNKNOWN_RECORD_TYPE;
+ }
+ if (ssl->curSize != 1 ||
+ ssl->buffers.inputBuffer.buffer[i] != 1) {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ return UNKNOWN_RECORD_TYPE;
+ }
+ ssl->buffers.inputBuffer.idx++;
+ break;
+ }
+ #endif
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
ret = SanityCheckMsgReceived(ssl, change_cipher_hs);
- if (ret != 0)
- return ret;
+ if (ret != 0) {
+ if (!ssl->options.dtls) {
+ return ret;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ /* Check for duplicate CCS message in DTLS mode.
+ * DTLS allows for duplicate messages, and it should be
+ * skipped. Also skip if out of order. */
+ if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E)
+ return ret;
-#ifdef HAVE_SESSION_TICKET
- if (ssl->options.side == WOLFSSL_CLIENT_END &&
- ssl->expect_session_ticket) {
- WOLFSSL_MSG("Expected session ticket missing");
- return SESSION_TICKET_EXPECT_E;
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = DtlsMsgPoolSend(ssl, 1);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (ssl->curSize != 1) {
+ WOLFSSL_MSG("Malicious or corrupted"
+ " duplicate ChangeCipher msg");
+ return LENGTH_ERROR;
+ }
+ ssl->buffers.inputBuffer.idx++;
+ break;
+ #endif /* WOLFSSL_DTLS */
+ }
}
-#endif
- if (ssl->keys.encryptionOn && ssl->options.handShakeDone) {
+ if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
+ #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 -= digestSz;
+ }
+ #endif
}
if (ssl->curSize != 1) {
WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg");
return LENGTH_ERROR;
}
- #ifndef NO_CERTS
- if (ssl->options.side == WOLFSSL_SERVER_END &&
- ssl->options.verifyPeer &&
- ssl->options.havePeerCert)
- if (!ssl->options.havePeerVerify) {
- WOLFSSL_MSG("client didn't send cert verify");
- return NO_PEER_VERIFY;
- }
- #endif
-
ssl->buffers.inputBuffer.idx++;
ssl->keys.encryptionOn = 1;
/* setup decrypt keys for following messages */
+ /* XXX This might not be what we want to do when
+ * receiving a CCS with multicast. We update the
+ * key when the application updates them. */
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ ssl->options.startedETMRead = ssl->options.encThenMac;
+ #endif
+
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
- DtlsPoolReset(ssl);
- ssl->keys.dtls_state.nextEpoch++;
- ssl->keys.dtls_state.nextSeq = 0;
+ 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
@@ -6637,13 +15319,26 @@ int ProcessReply(WOLFSSL* ssl)
server : client);
if (ret != 0)
return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
break;
case application_data:
WOLFSSL_MSG("got app DATA");
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls && ssl->options.dtlsHsRetain) {
+ FreeHandshakeResources(ssl);
+ ssl->options.dtlsHsRetain = 0;
+ }
+ #endif
+ #ifdef WOLFSSL_TLS13
+ if (ssl->keys.keyUpdateRespond) {
+ WOLFSSL_MSG("No KeyUpdate from peer seen");
+ return SANITY_MSG_E;
+ }
+ #endif
if ((ret = DoApplicationData(ssl,
ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx))
+ &ssl->buffers.inputBuffer.idx))
!= 0) {
WOLFSSL_ERROR(ret);
return ret;
@@ -6676,24 +15371,41 @@ int ProcessReply(WOLFSSL* ssl)
ssl->options.processReply = doProcessInit;
/* input exhausted? */
- if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
+ if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length)
return 0;
/* more messages per record */
else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
WOLFSSL_MSG("More messages in record");
- #ifdef WOLFSSL_DTLS
- /* read-ahead but dtls doesn't bundle messages per record */
- if (ssl->options.dtls) {
- ssl->options.processReply = doProcessInit;
- continue;
- }
- #endif
+
ssl->options.processReply = runProcessingOneMessage;
- if (ssl->keys.encryptionOn) {
+ if (IsEncryptionOn(ssl, 0)) {
WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
- ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
+ #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");
+ 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");
+ return FATAL_ERROR;
+ }
+ }
}
continue;
@@ -6720,6 +15432,21 @@ int SendChangeCipher(WOLFSSL* ssl)
int idx = RECORD_HEADER_SZ;
int ret;
+ #ifdef OPENSSL_EXTRA
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ if (ssl->options.side == WOLFSSL_SERVER_END){
+ ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+ }
+ else{
+ ssl->options.clientState =
+ CLIENT_CHANGECIPHERSPEC_COMPLETE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+ }
+ #endif
+
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA;
@@ -6728,15 +15455,15 @@ int SendChangeCipher(WOLFSSL* ssl)
#endif
/* are we in scr */
- if (ssl->keys.encryptionOn && ssl->options.handShakeDone) {
+ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
sendSz += MAX_MSG_EXTRA;
}
- /* check for avalaible size */
+ /* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
@@ -6744,34 +15471,36 @@ int SendChangeCipher(WOLFSSL* ssl)
output[idx] = 1; /* turn it on */
- if (ssl->keys.encryptionOn && ssl->options.handShakeDone) {
+ 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);
- if (sendSz < 0)
+ change_cipher_spec, 0, 0, 0);
+ if (sendSz < 0) {
return sendSz;
+ }
}
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
+ if (IsDtlsNotSctpMode(ssl)) {
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
#endif
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher");
if (ssl->toInfoOn)
- AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
+ AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output,
+ sendSz, WRITE_PROTO, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
return 0;
- #ifdef WOLFSSL_DTLS
+ #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS)
else if (ssl->options.dtls) {
/* If using DTLS, force the ChangeCipherSpec message to be in the
* same datagram as the finished message. */
@@ -6783,23 +15512,25 @@ int SendChangeCipher(WOLFSSL* ssl)
}
-#ifndef NO_OLD_TLS
+#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY)
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
- int content, int verify)
+ int padLen, int content, int verify)
{
- byte result[MAX_DIGEST_SIZE];
+ byte result[WC_MAX_DIGEST_SIZE];
word32 digestSz = ssl->specs.hash_size; /* actual sizes */
word32 padSz = ssl->specs.pad_size;
int ret = 0;
- Md5 md5;
- Sha sha;
+ wc_Md5 md5;
+ wc_Sha sha;
/* data */
byte seq[SEQ_SZ];
byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
+ (void)padLen;
+
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
@@ -6808,314 +15539,643 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
XMEMSET(seq, 0, SEQ_SZ);
conLen[0] = (byte)content;
c16toa((word16)sz, &conLen[ENUM_LEN]);
- c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
+ WriteSEQ(ssl, verify, seq);
if (ssl->specs.mac_algorithm == md5_mac) {
- wc_InitMd5(&md5);
+ ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId);
+ if (ret != 0)
+ return ret;
+
/* inner */
- wc_Md5Update(&md5, macSecret, digestSz);
- wc_Md5Update(&md5, PAD1, padSz);
- wc_Md5Update(&md5, seq, SEQ_SZ);
- wc_Md5Update(&md5, conLen, sizeof(conLen));
+ ret = wc_Md5Update(&md5, macSecret, digestSz);
+ ret |= wc_Md5Update(&md5, PAD1, padSz);
+ ret |= wc_Md5Update(&md5, seq, SEQ_SZ);
+ ret |= wc_Md5Update(&md5, conLen, sizeof(conLen));
/* in buffer */
- wc_Md5Update(&md5, in, sz);
- wc_Md5Final(&md5, result);
+ ret |= wc_Md5Update(&md5, in, sz);
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+ ret = wc_Md5Final(&md5, result);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* TODO: Make non-blocking */
+ if (ret == WC_PENDING_E) {
+ ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+ }
+ #endif
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+
/* outer */
- wc_Md5Update(&md5, macSecret, digestSz);
- wc_Md5Update(&md5, PAD2, padSz);
- wc_Md5Update(&md5, result, digestSz);
- wc_Md5Final(&md5, digest);
+ ret = wc_Md5Update(&md5, macSecret, digestSz);
+ ret |= wc_Md5Update(&md5, PAD2, padSz);
+ ret |= wc_Md5Update(&md5, result, digestSz);
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+ ret = wc_Md5Final(&md5, digest);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* TODO: Make non-blocking */
+ if (ret == WC_PENDING_E) {
+ ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+ }
+ #endif
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+
+ wc_Md5Free(&md5);
}
else {
- ret = wc_InitSha(&sha);
+ ret = wc_InitSha_ex(&sha, ssl->heap, ssl->devId);
if (ret != 0)
return ret;
+
/* inner */
- wc_ShaUpdate(&sha, macSecret, digestSz);
- wc_ShaUpdate(&sha, PAD1, padSz);
- wc_ShaUpdate(&sha, seq, SEQ_SZ);
- wc_ShaUpdate(&sha, conLen, sizeof(conLen));
+ ret = wc_ShaUpdate(&sha, macSecret, digestSz);
+ ret |= wc_ShaUpdate(&sha, PAD1, padSz);
+ ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ);
+ ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen));
/* in buffer */
- wc_ShaUpdate(&sha, in, sz);
- wc_ShaFinal(&sha, result);
+ ret |= wc_ShaUpdate(&sha, in, sz);
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+ ret = wc_ShaFinal(&sha, result);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* TODO: Make non-blocking */
+ if (ret == WC_PENDING_E) {
+ ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+ }
+ #endif
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+
/* outer */
- wc_ShaUpdate(&sha, macSecret, digestSz);
- wc_ShaUpdate(&sha, PAD2, padSz);
- wc_ShaUpdate(&sha, result, digestSz);
- wc_ShaFinal(&sha, digest);
+ ret = wc_ShaUpdate(&sha, macSecret, digestSz);
+ ret |= wc_ShaUpdate(&sha, PAD2, padSz);
+ ret |= wc_ShaUpdate(&sha, result, digestSz);
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+ ret = wc_ShaFinal(&sha, digest);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* TODO: Make non-blocking */
+ if (ret == WC_PENDING_E) {
+ ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+ }
+ #endif
+ if (ret != 0)
+ return VERIFY_MAC_ERROR;
+
+ wc_ShaFree(&sha);
}
return 0;
}
+#endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */
+
#ifndef NO_CERTS
-static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
-{
- byte md5_result[MD5_DIGEST_SIZE];
+#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
+{
+ int ret;
+ byte md5_result[WC_MD5_DIGEST_SIZE];
#ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
#else
- Md5 md5[1];
- Md5 md5_2[1];
+ wc_Md5 md5[1];
#endif
/* make md5 inner */
- md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */
- wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN);
- wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5);
- wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result);
- wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */
+ ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */
+ if (ret == 0)
+ ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+ if (ret == 0)
+ ret = wc_Md5Final(md5, md5_result);
/* make md5 outer */
- wc_InitMd5(md5_2) ;
- wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN);
- wc_Md5Update(md5_2, PAD2, PAD_MD5);
- wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE);
-
- wc_Md5Final(md5_2, digest);
+ if (ret == 0) {
+ ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+ if (ret == 0) {
+ ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+ if (ret == 0)
+ ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+ if (ret == 0)
+ ret = wc_Md5Final(md5, digest);
+ wc_Md5Free(md5);
+ }
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
#endif
-}
+ return ret;
+}
+#endif /* !NO_MD5 && !NO_OLD_TLS */
-static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
+#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_TLS_SHA1))
+static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
{
- byte sha_result[SHA_DIGEST_SIZE];
-
+ int ret;
+ byte sha_result[WC_SHA_DIGEST_SIZE];
#ifdef WOLFSSL_SMALL_STACK
- Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
#else
- Sha sha[1];
- Sha sha2[1];
+ wc_Sha sha[1];
#endif
/* make sha inner */
- sha[0] = ssl->hsHashes->hashSha ; /* Save current position */
- wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN);
- wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA);
- wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result);
- wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */
+ ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+ if (ret == 0)
+ ret = wc_ShaFinal(sha, sha_result);
/* make sha outer */
- wc_InitSha(sha2) ;
- wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN);
- wc_ShaUpdate(sha2, PAD2, PAD_SHA);
- wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE);
-
- wc_ShaFinal(sha2, digest);
+ if (ret == 0) {
+ ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+ if (ret == 0) {
+ ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+ if (ret == 0)
+ ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+ if (ret == 0)
+ ret = wc_ShaFinal(sha, digest);
+ wc_ShaFree(sha);
+ }
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
#endif
+ return ret;
}
-#endif /* NO_CERTS */
-#endif /* NO_OLD_TLS */
+#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */
+int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
+{
+ int ret = 0;
-#ifndef NO_CERTS
+ (void)hashes;
-static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
-{
- /* store current states, building requires get_digest which resets state */
- #ifdef WOLFSSL_SHA384
- Sha384 sha384 = ssl->hsHashes->hashSha384;
+ if (ssl->options.tls) {
+ #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+ ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
+ if (ret != 0)
+ return ret;
#endif
- #ifdef WOLFSSL_SHA512
- Sha512 sha512 = ssl->hsHashes->hashSha512;
+ #if !defined(NO_SHA)
+ ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
+ if (ret != 0)
+ return ret;
#endif
-
- if (ssl->options.tls) {
-#if ! defined( NO_OLD_TLS )
- wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
- wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
-#endif
if (IsAtLeastTLSv1_2(ssl)) {
- int ret;
-
#ifndef NO_SHA256
- ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,hashes->sha256);
+ ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,
+ hashes->sha256);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
- ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,hashes->sha384);
+ ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384,
+ hashes->sha384);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
- ret = wc_Sha512Final(&ssl->hsHashes->hashSha512,hashes->sha512);
+ ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512,
+ hashes->sha512);
if (ret != 0)
return ret;
#endif
}
}
-#if ! defined( NO_OLD_TLS )
else {
- BuildMD5_CertVerify(ssl, hashes->md5);
- BuildSHA_CertVerify(ssl, hashes->sha);
- }
-
- /* restore */
-#endif
- if (IsAtLeastTLSv1_2(ssl)) {
- #ifdef WOLFSSL_SHA384
- ssl->hsHashes->hashSha384 = sha384;
- #endif
- #ifdef WOLFSSL_SHA512
- ssl->hsHashes->hashSha512 = sha512;
- #endif
+ #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+ ret = BuildMD5_CertVerify(ssl, hashes->md5);
+ if (ret != 0)
+ return ret;
+ #endif
+ #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_TLS_SHA1))
+ ret = BuildSHA_CertVerify(ssl, hashes->sha);
+ if (ret != 0)
+ return ret;
+ #endif
}
- return 0;
+ return ret;
}
-#endif /* WOLFSSL_LEANPSK */
+#endif /* !NO_CERTS */
-/* Build SSL Message, encrypted */
-static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
- const byte* input, int inSz, int type)
-{
-#ifdef HAVE_TRUNCATED_HMAC
- word32 digestSz = min(ssl->specs.hash_size,
- ssl->truncated_hmac ? TRUNCATED_HMAC_SZ : ssl->specs.hash_size);
-#else
- word32 digestSz = ssl->specs.hash_size;
-#endif
- word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
- word32 pad = 0, i;
- word32 idx = RECORD_HEADER_SZ;
- word32 ivSz = 0; /* TLSv1.1 IV */
- word32 headerSz = RECORD_HEADER_SZ;
+#ifndef WOLFSSL_NO_TLS12
+/* Persistable BuildMessage arguments */
+typedef struct BuildMsgArgs {
+ word32 digestSz;
+ word32 sz;
+ word32 pad;
+ word32 idx;
+ word32 headerSz;
word16 size;
- byte iv[AES_BLOCK_SIZE]; /* max size */
- int ret = 0;
- int atomicUser = 0;
+ word32 ivSz; /* TLSv1.1 IV */
+ byte* iv;
+} BuildMsgArgs;
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sz += DTLS_RECORD_EXTRA;
- idx += DTLS_RECORD_EXTRA;
- headerSz += DTLS_RECORD_EXTRA;
+static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs)
+{
+ BuildMsgArgs* args = (BuildMsgArgs*)pArgs;
+
+ (void)ssl;
+ (void)args;
+
+ if (args->iv) {
+ XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT);
+ args->iv = NULL;
}
+}
#endif
-#ifdef ATOMIC_USER
- if (ssl->ctx->MacEncryptCb)
- atomicUser = 1;
+/* 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)
+{
+#ifndef WOLFSSL_NO_TLS12
+ int ret = 0;
+ BuildMsgArgs* args;
+ BuildMsgArgs lcl_args;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ args = (BuildMsgArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+#endif
#endif
- if (ssl->specs.cipher_type == block) {
- word32 blockSz = ssl->specs.block_size;
- if (ssl->options.tls1_1) {
- ivSz = blockSz;
- sz += ivSz;
+ WOLFSSL_ENTER("BuildMessage");
- if (ivSz > (word32)sizeof(iv))
- return BUFFER_E;
-
- ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz);
- if (ret != 0)
- return ret;
-
- }
- sz += 1; /* pad byte */
- pad = (sz - headerSz) % blockSz;
- pad = blockSz - pad;
- sz += pad;
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
}
-#ifdef HAVE_AEAD
- if (ssl->specs.cipher_type == aead) {
- if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- ivSz = AEAD_EXP_IV_SZ;
+#ifdef WOLFSSL_NO_TLS12
+ return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+ hashOutput, sizeOnly, asyncOkay);
+#else
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+ hashOutput, sizeOnly, asyncOkay);
+ }
+#endif
- sz += (ivSz + ssl->specs.aead_mac_size - digestSz);
- XMEMCPY(iv, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
+ ret = WC_NOT_PENDING_E;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (asyncOkay) {
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_buildmsg;
+ }
}
+ else
#endif
- if (sz > (word32)outSz) {
- WOLFSSL_MSG("Oops, want to write past output buffer size");
- return BUFFER_E;
+ {
+ args = &lcl_args;
}
- size = (word16)(sz - headerSz); /* include mac and digest */
- AddRecordHeader(output, size, (byte)type, ssl);
- /* write to output */
- if (ivSz) {
- XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv)));
- idx += ivSz;
+ /* Reset state */
+ if (ret == WC_NOT_PENDING_E) {
+ 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;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeBuildMsgArgs;
+ #endif
}
- XMEMCPY(output + idx, input, inSz);
- idx += inSz;
- if (type == handshake) {
- ret = HashOutput(ssl, output, headerSz + inSz, ivSz);
- if (ret != 0)
- return ret;
- }
+ switch (ssl->options.buildMsgState) {
+ case BUILD_MSG_BEGIN:
+ {
+ /* catch mistaken sizeOnly parameter */
+ if (!sizeOnly && (output == NULL || input == NULL) ) {
+ ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+ }
+ if (sizeOnly && (output || input) ) {
+ WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output");
+ ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+ }
- if (ssl->specs.cipher_type == block) {
- word32 tmpIdx = idx + digestSz;
+ ssl->options.buildMsgState = BUILD_MSG_SIZE;
+ }
+ FALL_THROUGH;
+ case BUILD_MSG_SIZE:
+ {
+ args->digestSz = ssl->specs.hash_size;
+ #ifdef HAVE_TRUNCATED_HMAC
+ if (ssl->truncated_hmac)
+ args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz);
+ #endif
+ args->sz += args->digestSz;
- for (i = 0; i <= pad; i++)
- output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */
- }
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sz += DTLS_RECORD_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA;
+ args->headerSz += DTLS_RECORD_EXTRA;
+ }
+ #endif
- if (atomicUser) { /* User Record Layer Callback handling */
-#ifdef ATOMIC_USER
- if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx,
- output + headerSz + ivSz, inSz, type, 0,
- output + headerSz, output + headerSz, size,
- ssl->MacEncryptCtx)) != 0)
- return ret;
+ #ifndef WOLFSSL_AEAD_ONLY
+ if (ssl->specs.cipher_type == block) {
+ word32 blockSz = ssl->specs.block_size;
+ if (ssl->options.tls1_1) {
+ args->ivSz = blockSz;
+ args->sz += args->ivSz;
+
+ if (args->ivSz > 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;
+ #ifdef OPENSSL_EXTRA
+ if(args->pad != 0)
+ #endif
+ 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 > 0) {
+ args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT);
+ if (args->iv == NULL)
+ ERROR_OUT(MEMORY_E, 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
- }
- else {
- if (ssl->specs.cipher_type != aead) {
-#ifdef HAVE_TRUNCATED_HMAC
- if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) {
- #ifdef WOLFSSL_SMALL_STACK
- byte* hmac = NULL;
- #else
- byte hmac[MAX_DIGEST_SIZE];
+
+ args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */
+ AddRecordHeader(output, args->size, (byte)type, ssl);
+
+ /* write to output */
+ if (args->ivSz > 0) {
+ XMEMCPY(output + args->idx, args->iv,
+ min(args->ivSz, MAX_IV_SZ));
+ args->idx += args->ivSz;
+ }
+ XMEMCPY(output + args->idx, input, inSz);
+ args->idx += inSz;
+
+ ssl->options.buildMsgState = BUILD_MSG_HASH;
+ }
+ FALL_THROUGH;
+ case BUILD_MSG_HASH:
+ {
+ if (type == handshake && hashOutput) {
+ ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
+ if (ret != 0)
+ goto exit_buildmsg;
+ }
+ #ifndef WOLFSSL_AEAD_ONLY
+ if (ssl->specs.cipher_type == 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;
- #ifdef WOLFSSL_SMALL_STACK
- hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (hmac == NULL)
- return MEMORY_E;
+ for (i = 0; i <= args->pad; i++)
+ output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */
+ }
+ #endif
+
+ ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC;
+ }
+ FALL_THROUGH;
+ case BUILD_MSG_VERIFY_MAC:
+ {
+ /* User Record Layer Callback handling */
+ #ifdef ATOMIC_USER
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMWrite) {
+ if (ssl->ctx->EncryptMacCb) {
+ ret = ssl->ctx->EncryptMacCb(ssl, output + args->idx +
+ args->pad + 1, type, 0,
+ output + args->headerSz,
+ output + args->headerSz,
+ args->size - args->digestSz,
+ ssl->MacEncryptCtx);
+ goto exit_buildmsg;
+ }
+ }
+ else
+ #endif
+ {
+ if (ssl->ctx->MacEncryptCb) {
+ ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
+ output + args->headerSz + args->ivSz, inSz,
+ type, 0, output + args->headerSz,
+ output + args->headerSz, args->size,
+ ssl->MacEncryptCtx);
+ goto exit_buildmsg;
+ }
+ }
+ #endif
+
+ #ifndef WOLFSSL_AEAD_ONLY
+ if (ssl->specs.cipher_type != 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
- ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz,
- type, 0);
- XMEMCPY(output + idx, hmac, digestSz);
+ #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
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ret = ssl->hmac(ssl, hmac,
+ output + args->headerSz + args->ivSz, inSz,
+ -1, type, 0);
+ XMEMCPY(output + args->idx, hmac, args->digestSz);
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
+ #endif
+ }
+ else
#endif
- } else
-#endif
- ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz,
- type, 0);
+ {
+ ret = ssl->hmac(ssl, output + args->idx, output +
+ args->headerSz + args->ivSz, inSz, -1, type, 0);
+ }
+ }
+ #endif /* WOLFSSL_AEAD_ONLY */
+ if (ret != 0)
+ goto exit_buildmsg;
+
+ ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
}
- if (ret != 0)
- return ret;
+ FALL_THROUGH;
+ case BUILD_MSG_ENCRYPT:
+ {
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMWrite) {
+ ret = Encrypt(ssl, output + args->headerSz,
+ output + args->headerSz,
+ args->size - args->digestSz, asyncOkay);
+ }
+ else
+ #endif
+ {
+ ret = Encrypt(ssl, output + args->headerSz,
+ output + args->headerSz, args->size, asyncOkay);
+ }
+ if (ret != 0)
+ goto exit_buildmsg;
+ ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC;
+ }
+ FALL_THROUGH;
+ case BUILD_MSG_ENCRYPTED_VERIFY_MAC:
+ {
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMWrite) {
+ WOLFSSL_MSG("Calculate MAC of Encrypted Data");
- if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0)
- return ret;
+ #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);
+ 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);
+ }
+ }
+ #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
+ }
}
- return sz;
+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)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+
+ /* return sz on success */
+ if (ret == 0)
+ ret = args->sz;
+
+ /* Final cleanup */
+ FreeBuildMsgArgs(ssl, args);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = NULL;
+#endif
+
+ return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
}
+#ifndef WOLFSSL_NO_TLS12
int SendFinished(WOLFSSL* ssl)
{
@@ -7129,15 +16189,17 @@ int SendFinished(WOLFSSL* ssl)
int headerSz = HANDSHAKE_HEADER_SZ;
int outputSz;
- #ifdef WOLFSSL_DTLS
- word32 sequence_number = ssl->keys.dtls_sequence_number;
- word16 epoch = ssl->keys.dtls_epoch;
- #endif
+ WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+ WOLFSSL_ENTER("SendFinished");
/* setup encrypt keys */
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
return ret;
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ ssl->options.startedETMWrite = ssl->options.encThenMac;
+ #endif
+
/* check for available size */
outputSz = sizeof(input) + MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
@@ -7145,19 +16207,22 @@ int SendFinished(WOLFSSL* ssl)
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
- /* Send Finished message with the next epoch, but don't commit that
- * change until the other end confirms its reception. */
headerSz += DTLS_HANDSHAKE_EXTRA;
ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
+ 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
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
- AddHandShakeHeader(input, finishedSz, finished, ssl);
+ AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
/* make finished hashes */
hashes = (Hashes*)&input[headerSz];
@@ -7176,211 +16241,525 @@ int SendFinished(WOLFSSL* ssl)
}
#endif
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0)
+ return ret;
+ }
+ #endif
+
sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
- handshake);
+ handshake, 1, 0, 0);
if (sendSz < 0)
return BUILD_MSG_ERROR;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- ssl->keys.dtls_epoch = epoch;
- ssl->keys.dtls_sequence_number = sequence_number;
- }
- #endif
-
if (!ssl->options.resuming) {
#ifndef NO_SESSION_CACHE
AddSession(ssl); /* just try */
#endif
if (ssl->options.side == WOLFSSL_SERVER_END) {
+ #ifdef OPENSSL_EXTRA
+ ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+ #endif
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- /* Other side will soon receive our Finished, go to next
- * epoch. */
- ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 1;
- }
- #endif
}
}
else {
if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ #ifdef OPENSSL_EXTRA
+ ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+ #endif
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- /* Other side will soon receive our Finished, go to next
- * epoch. */
- ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 1;
- }
- #endif
}
}
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- }
- #endif
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
if (ssl->toInfoOn)
- AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
+ AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendFinished", ret);
+ WOLFSSL_END(WC_FUNC_FINISHED_SEND);
+
+ return ret;
+}
+#endif /* WOLFSSL_NO_TLS12 */
+
+#ifndef NO_WOLFSSL_SERVER
+#if (!defined(WOLFSSL_NO_TLS12) && \
+ (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST))
+/* Parses and decodes the certificate then initializes "request". In the case
+ * of !ssl->buffers.weOwnCert, ssl->ctx->certOcspRequest gets set to "request".
+ *
+ * Returns 0 on success
+ */
+static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
+ DecodedCert* cert, byte* certData, word32 length)
+{
+ int ret;
+
+ if (request != NULL)
+ XMEMSET(request, 0, sizeof(OcspRequest));
+
+ InitDecodedCert(cert, certData, length, ssl->heap);
+ /* TODO: Setup async support here */
+ ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm);
+ if (ret != 0) {
+ WOLFSSL_MSG("ParseCert failed");
+ }
+ if (ret == 0)
+ ret = InitOcspRequest(request, cert, 0, ssl->heap);
+ if (ret == 0) {
+ /* make sure ctx OCSP request is updated */
+ if (!ssl->buffers.weOwnCert) {
+ wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock;
+ if (wc_LockMutex(ocspLock) == 0) {
+ if (ssl->ctx->certOcspRequest == NULL)
+ ssl->ctx->certOcspRequest = request;
+ wc_UnLockMutex(ocspLock);
+ }
+ }
+ }
+
+ FreeDecodedCert(cert);
+
+ return ret;
+}
+
+
+/* Creates OCSP response and places it in variable "response". Memory
+ * management for "buffer* response" is up to the caller.
+ *
+ * Also creates an OcspRequest in the case that ocspRequest is null or that
+ * ssl->buffers.weOwnCert is set. In those cases managing ocspRequest free'ing
+ * is up to the caller. NOTE: in OcspCreateRequest ssl->ctx->certOcspRequest can
+ * be set to point to "ocspRequest" and it then should not be free'd since
+ * wolfSSL_CTX_free will take care of it.
+ *
+ * Returns 0 on success
+ */
+int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
+ buffer* response)
+{
+ int ret = 0;
+ OcspRequest* request = NULL;
+ byte createdRequest = 0;
+
+ if (ssl == NULL || ocspRequest == NULL || response == NULL)
+ return BAD_FUNC_ARG;
+
+ XMEMSET(response, 0, sizeof(*response));
+ request = *ocspRequest;
+
+ /* unable to fetch status. skip. */
+ if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
+ return 0;
+
+ if (request == NULL || ssl->buffers.weOwnCert) {
+ DerBuffer* der = ssl->buffers.certificate;
+ #ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert = NULL;
+ #else
+ DecodedCert cert[1];
+ #endif
+
+ /* unable to fetch status. skip. */
+ if (der->buffer == NULL || der->length == 0)
+ return 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return MEMORY_E;
+ #endif
+ request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (request == NULL)
+ ret = MEMORY_E;
+
+ createdRequest = 1;
+ if (ret == 0) {
+ ret = CreateOcspRequest(ssl, request, cert, der->buffer,
+ der->length);
+ }
+
+ if (ret != 0) {
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ request = NULL;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ #endif
+ }
+
+ if (ret == 0) {
+ request->ssl = ssl;
+ ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response);
+
+ /* Suppressing, not critical */
+ if (ret == OCSP_CERT_REVOKED ||
+ ret == OCSP_CERT_UNKNOWN ||
+ ret == OCSP_LOOKUP_FAIL) {
+ ret = 0;
+ }
+ }
+
+ /* free request up if error case found otherwise return it */
+ if (ret != 0 && createdRequest) {
+ FreeOcspRequest(request);
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ }
+
+ if (ret == 0)
+ *ocspRequest = request;
+
+ return ret;
}
+#endif
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifndef WOLFSSL_NO_TLS12
#ifndef NO_CERTS
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+/* handle generation of certificate (11) */
int SendCertificate(WOLFSSL* ssl)
{
- int sendSz, length, ret = 0;
- word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- word32 certSz, listSz;
- byte* output = 0;
+ int ret = 0;
+ word32 certSz, certChainSz, headerSz, listSz, payloadSz;
+ word32 length, maxFragment;
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
+ WOLFSSL_ENTER("SendCertificate");
if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
return 0; /* not needed */
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
- certSz = 0;
- length = CERT_HEADER_SZ;
- listSz = 0;
+ #ifdef OPENSSL_EXTRA
+ if (ssl->version.major == SSLv3_MAJOR
+ && ssl->version.minor == SSLv3_MINOR){
+ SendAlert(ssl, alert_warning, no_certificate);
+ return 0;
+ } else {
+ #endif
+ certSz = 0;
+ certChainSz = 0;
+ headerSz = CERT_HEADER_SZ;
+ length = CERT_HEADER_SZ;
+ listSz = 0;
+ #ifdef OPENSSL_EXTRA
+ }
+ #endif
}
else {
- certSz = ssl->buffers.certificate.length;
+ if (!ssl->buffers.certificate) {
+ WOLFSSL_MSG("Send Cert missing certificate buffer");
+ return BUFFER_ERROR;
+ }
+ certSz = ssl->buffers.certificate->length;
+ headerSz = 2 * CERT_HEADER_SZ;
/* list + cert size */
- length = certSz + 2 * CERT_HEADER_SZ;
+ length = certSz + headerSz;
listSz = certSz + CERT_HEADER_SZ;
/* may need to send rest of chain, already has leading size(s) */
- if (ssl->buffers.certChain.buffer) {
- length += ssl->buffers.certChain.length;
- listSz += ssl->buffers.certChain.length;
+ if (certSz && ssl->buffers.certChain) {
+ certChainSz = ssl->buffers.certChain->length;
+ length += certChainSz;
+ listSz += certChainSz;
}
+ else
+ certChainSz = 0;
}
- sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ payloadSz = length;
+
+ if (ssl->fragOffset != 0)
+ length -= (ssl->fragOffset + headerSz);
+
+ maxFragment = MAX_RECORD_SIZE;
+
+ if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
+ /* The 100 bytes is used to account for the UDP and IP headers.
+ It can also include the record padding and MAC if the
+ SendCertificate is called for a secure renegotiation. */
+ maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ
+ - DTLS_HANDSHAKE_HEADER_SZ - 100;
+ #endif /* WOLFSSL_DTLS */
+ }
- if (ssl->keys.encryptionOn)
- sendSz += MAX_MSG_EXTRA;
+ maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment);
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
- return ret;
+ while (length > 0 && ret == 0) {
+ byte* output = NULL;
+ word32 fragSz = 0;
+ word32 i = RECORD_HEADER_SZ;
+ int sendSz = RECORD_HEADER_SZ;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
+ if (!ssl->options.dtls) {
+ if (ssl->fragOffset == 0) {
+ if (headerSz + certSz + certChainSz <=
+ maxFragment - HANDSHAKE_HEADER_SZ) {
- AddHeaders(output, length, certificate, ssl);
+ fragSz = headerSz + certSz + certChainSz;
+ }
+ else {
+ fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
+ }
+ sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+ i += HANDSHAKE_HEADER_SZ;
+ }
+ else {
+ fragSz = min(length, maxFragment);
+ sendSz += fragSz;
+ }
- /* list total */
- c32to24(listSz, output + i);
- i += CERT_HEADER_SZ;
+ if (IsEncryptionOn(ssl, 1))
+ sendSz += MAX_MSG_EXTRA;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ fragSz = min(length, maxFragment);
+ sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+ + HANDSHAKE_HEADER_SZ;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+ + HANDSHAKE_HEADER_SZ;
+ #endif
+ }
- /* member */
- if (certSz) {
- c32to24(certSz, output + i);
- i += CERT_HEADER_SZ;
- XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz);
- i += certSz;
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+ return ret;
- /* send rest of chain? */
- if (ssl->buffers.certChain.buffer) {
- XMEMCPY(output + i, ssl->buffers.certChain.buffer,
- ssl->buffers.certChain.length);
- i += ssl->buffers.certChain.length;
+ /* get output buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ if (ssl->fragOffset == 0) {
+ if (!ssl->options.dtls) {
+ AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+ if (!IsEncryptionOn(ssl, 1))
+ HashOutputRaw(ssl, output + RECORD_HEADER_SZ,
+ HANDSHAKE_HEADER_SZ);
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ AddHeaders(output, payloadSz, certificate, ssl);
+ if (!IsEncryptionOn(ssl, 1))
+ HashOutputRaw(ssl,
+ output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA,
+ HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
+ /* Adding the headers increments these, decrement them for
+ * actual message header. */
+ ssl->keys.dtls_handshake_number--;
+ AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+ ssl->keys.dtls_handshake_number--;
+ #endif /* WOLFSSL_DTLS */
+ }
+
+ /* list total */
+ c32to24(listSz, output + i);
+ if (!IsEncryptionOn(ssl, 1))
+ HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+ i += CERT_HEADER_SZ;
+ length -= CERT_HEADER_SZ;
+ fragSz -= CERT_HEADER_SZ;
+ if (certSz) {
+ c32to24(certSz, output + i);
+ if (!IsEncryptionOn(ssl, 1))
+ HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+ i += CERT_HEADER_SZ;
+ length -= CERT_HEADER_SZ;
+ fragSz -= CERT_HEADER_SZ;
+
+ if (!IsEncryptionOn(ssl, 1)) {
+ HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz);
+ if (certChainSz)
+ HashOutputRaw(ssl, ssl->buffers.certChain->buffer,
+ certChainSz);
+ }
+ }
+ }
+ else {
+ if (!ssl->options.dtls) {
+ AddRecordHeader(output, fragSz, handshake, ssl);
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz,
+ payloadSz, certificate, ssl);
+ ssl->keys.dtls_handshake_number--;
+ #endif /* WOLFSSL_DTLS */
+ }
}
- }
- if (ssl->keys.encryptionOn) {
- byte* input;
- int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+ /* member */
+ if (certSz && ssl->fragOffset < certSz) {
+ word32 copySz = min(certSz - ssl->fragOffset, fragSz);
+ XMEMCPY(output + i,
+ ssl->buffers.certificate->buffer + ssl->fragOffset, copySz);
+ i += copySz;
+ ssl->fragOffset += copySz;
+ length -= copySz;
+ fragSz -= copySz;
+ }
+ if (certChainSz && fragSz) {
+ word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz);
+ XMEMCPY(output + i,
+ ssl->buffers.certChain->buffer + ssl->fragOffset - certSz,
+ copySz);
+ i += copySz;
+ ssl->fragOffset += copySz;
+ length -= copySz;
+ }
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (input == NULL)
- return MEMORY_E;
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input = NULL;
+ int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
- XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
- sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (inputSz < 0) {
+ WOLFSSL_MSG("Send Cert bad inputSz");
+ return BUFFER_E;
+ }
- if (sendSz < 0)
- return sendSz;
- } else {
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
- }
+ if (inputSz > 0) { /* clang thinks could be zero, let's help */
+ input = (byte*)XMALLOC(inputSz, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ }
+
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+
+ if (inputSz > 0)
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ return sendSz;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ }
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
#endif
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "Certificate");
if (ssl->toInfoOn)
- AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
+ AddPacketInfo(ssl, "Certificate", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
#endif
- if (ssl->options.side == WOLFSSL_SERVER_END)
- ssl->options.serverState = SERVER_CERT_COMPLETE;
+ ssl->buffers.outputBuffer.length += sendSz;
+ if (!ssl->options.groupMessages)
+ ret = SendBuffered(ssl);
+ }
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- return 0;
- else
- return SendBuffered(ssl);
-}
+ if (ret != WANT_WRITE) {
+ /* Clean up the fragment offset. */
+ ssl->fragOffset = 0;
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ ssl->keys.dtls_handshake_number++;
+ #endif
+ if (ssl->options.side == WOLFSSL_SERVER_END){
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+ }
+ }
+
+ WOLFSSL_LEAVE("SendCertificate", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
+ return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
+/* handle generation of certificate_request (13) */
int SendCertificateRequest(WOLFSSL* ssl)
{
byte *output;
int ret;
int sendSz;
word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ word32 dnLen = 0;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
+#endif
int typeTotal = 1; /* only 1 for now */
int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+ WOLFSSL_ENTER("SendCertificateRequest");
+
if (IsAtLeastTLSv1_2(ssl))
reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ /* Certificate Authorities */
+ names = ssl->ctx->ca_names;
+ while (names != NULL) {
+ byte seq[MAX_SEQ_SZ];
+
+ /* 16-bit length | SEQ | Len | DER of name */
+ dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) +
+ names->data.name->rawLen;
+ names = names->next;
+ }
+ reqSz += dnLen;
+#endif
+
if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
return 0; /* not needed */
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+ if (!ssl->options.dtls) {
+ if (IsEncryptionOn(ssl, 1))
+ sendSz += MAX_MSG_EXTRA;
+ }
+ else {
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
#endif
+ }
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
@@ -7389,7 +16768,8 @@ int SendCertificateRequest(WOLFSSL* ssl)
/* write to output */
output[i++] = (byte)typeTotal; /* # of types */
#ifdef HAVE_ECC
- if (ssl->options.cipherSuite0 == ECC_BYTE &&
+ if ((ssl->options.cipherSuite0 == ECC_BYTE ||
+ ssl->options.cipherSuite0 == CHACHA_BYTE) &&
ssl->specs.sig_algo == ecc_dsa_sa_algo) {
output[i++] = ecdsa_sign;
} else
@@ -7401,43 +16781,381 @@ int SendCertificateRequest(WOLFSSL* ssl)
/* supported hash/sig */
if (IsAtLeastTLSv1_2(ssl)) {
c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
- i += LENGTH_SZ;
+ i += OPAQUE16_LEN;
XMEMCPY(&output[i],
ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
i += ssl->suites->hashSigAlgoSz;
}
- c16toa(0, &output[i]); /* auth's */
- /* if add more to output, adjust i
- i += REQ_HEADER_SZ; */
+ /* Certificate Authorities */
+ c16toa((word16)dnLen, &output[i]); /* auth's */
+ i += REQ_HEADER_SZ;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ names = ssl->ctx->ca_names;
+ while (names != NULL) {
+ byte seq[MAX_SEQ_SZ];
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
+ c16toa((word16)names->data.name->rawLen +
+ SetSequence(names->data.name->rawLen, seq), &output[i]);
+ i += OPAQUE16_LEN;
+ i += SetSequence(names->data.name->rawLen, output + i);
+ XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen);
+ i += names->data.name->rawLen;
+ names = names->next;
+ }
+#endif
+ (void)i;
+
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ return sendSz;
+ } else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+ return ret;
+ }
+ #endif
+ ret = HashOutput(ssl, output, sendSz, 0);
+ if (ret != 0)
return ret;
}
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
-
- #ifdef WOLFSSL_CALLBACKS
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ AddPacketName(ssl, "CertificateRequest");
if (ssl->toInfoOn)
- AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
+ AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
- return 0;
+ ret = 0;
else
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendCertificateRequest", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+
+ return ret;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
+ byte count)
+{
+ byte* output = NULL;
+ word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ word32 length = ENUM_LEN;
+ int sendSz = 0;
+ int ret = 0;
+ int i = 0;
+
+ WOLFSSL_ENTER("BuildCertificateStatus");
+
+ switch (type) {
+ case WOLFSSL_CSR2_OCSP_MULTI:
+ length += OPAQUE24_LEN;
+ FALL_THROUGH; /* followed by */
+
+ case WOLFSSL_CSR2_OCSP:
+ for (i = 0; i < count; i++)
+ length += OPAQUE24_LEN + status[i].length;
+ break;
+
+ default:
+ return 0;
+ }
+
+ sendSz = idx + length;
+
+ if (ssl->keys.encryptionOn)
+ sendSz += MAX_MSG_EXTRA;
+
+ if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ AddHeaders(output, length, certificate_status, ssl);
+
+ output[idx++] = type;
+
+ if (type == WOLFSSL_CSR2_OCSP_MULTI) {
+ c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
+ idx += OPAQUE24_LEN;
+ }
+
+ for (i = 0; i < count; i++) {
+ c32to24(status[i].length, output + idx);
+ idx += OPAQUE24_LEN;
+
+ XMEMCPY(output + idx, status[i].buffer, status[i].length);
+ idx += status[i].length;
+ }
+
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int inputSz = idx - RECORD_HEADER_SZ;
+
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ ret = sendSz;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ ret = HashOutput(ssl, output, sendSz, 0);
+ }
+
+ #ifdef WOLFSSL_DTLS
+ if (ret == 0 && IsDtlsNotSctpMode(ssl))
+ ret = DtlsMsgPoolSave(ssl, output, sendSz);
+ #endif
+
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ret == 0 && ssl->hsInfoOn)
+ AddPacketName(ssl, "CertificateStatus");
+ if (ret == 0 && ssl->toInfoOn)
+ AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
+ #endif
+
+ if (ret == 0) {
+ ssl->buffers.outputBuffer.length += sendSz;
+ if (!ssl->options.groupMessages)
+ ret = SendBuffered(ssl);
+ }
+ }
+
+ WOLFSSL_LEAVE("BuildCertificateStatus", ret);
+ return ret;
+}
+#endif
+#endif /* NO_WOLFSSL_SERVER */
+
+/* handle generation of certificate_status (22) */
+int SendCertificateStatus(WOLFSSL* ssl)
+{
+ int ret = 0;
+ byte status_type = 0;
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
+ WOLFSSL_ENTER("SendCertificateStatus");
+
+ (void) ssl;
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+ status_type = ssl->status_request;
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ status_type = status_type ? status_type : ssl->status_request_v2;
+#endif
+
+ switch (status_type) {
+
+ #ifndef NO_WOLFSSL_SERVER
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ /* case WOLFSSL_CSR_OCSP: */
+ case WOLFSSL_CSR2_OCSP:
+ {
+ OcspRequest* request = ssl->ctx->certOcspRequest;
+ buffer response;
+
+ ret = CreateOcspResponse(ssl, &request, &response);
+
+ /* if a request was successfully created and not stored in
+ * ssl->ctx then free it */
+ if (ret == 0 && request != ssl->ctx->certOcspRequest) {
+ FreeOcspRequest(request);
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ request = NULL;
+ }
+
+ if (ret == 0 && response.buffer) {
+ ret = BuildCertificateStatus(ssl, status_type, &response, 1);
+
+ XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ response.buffer = NULL;
+ }
+ break;
+ }
+
+ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+ /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+ #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ case WOLFSSL_CSR2_OCSP_MULTI:
+ {
+ OcspRequest* request = ssl->ctx->certOcspRequest;
+ buffer responses[1 + MAX_CHAIN_DEPTH];
+ int i = 0;
+
+ XMEMSET(responses, 0, sizeof(responses));
+
+ ret = CreateOcspResponse(ssl, &request, &responses[0]);
+
+ /* if a request was successfully created and not stored in
+ * ssl->ctx then free it */
+ if (ret == 0 && request != ssl->ctx->certOcspRequest) {
+ FreeOcspRequest(request);
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ request = NULL;
+ }
+
+ if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
+ || ssl->buffers.weOwnCertChain)) {
+ buffer der;
+ word32 idx = 0;
+ #ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert;
+ #else
+ DecodedCert cert[1];
+ #endif
+
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return MEMORY_E;
+ #endif
+ request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (request == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ #endif
+ return MEMORY_E;
+ }
+
+ while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) {
+ c24to32(ssl->buffers.certChain->buffer + idx, &der.length);
+ idx += OPAQUE24_LEN;
+
+ der.buffer = ssl->buffers.certChain->buffer + idx;
+ idx += der.length;
+
+ if (idx > ssl->buffers.certChain->length)
+ break;
+
+ ret = CreateOcspRequest(ssl, request, cert, der.buffer,
+ der.length);
+ if (ret == 0) {
+ request->ssl = ssl;
+ ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+ request, &responses[i + 1]);
+
+ /* Suppressing, not critical */
+ if (ret == OCSP_CERT_REVOKED ||
+ ret == OCSP_CERT_UNKNOWN ||
+ ret == OCSP_LOOKUP_FAIL) {
+ ret = 0;
+ }
+
+
+ i++;
+ FreeOcspRequest(request);
+ }
+ }
+
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+ #endif
+ }
+ else {
+ while (ret == 0 &&
+ NULL != (request = ssl->ctx->chainOcspRequest[i])) {
+ request->ssl = ssl;
+ ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+ request, &responses[++i]);
+
+ /* Suppressing, not critical */
+ if (ret == OCSP_CERT_REVOKED ||
+ ret == OCSP_CERT_UNKNOWN ||
+ ret == OCSP_LOOKUP_FAIL) {
+ ret = 0;
+ }
+ }
+ }
+
+ if (responses[0].buffer) {
+ if (ret == 0) {
+ ret = BuildCertificateStatus(ssl, status_type, responses,
+ (byte)i + 1);
+ }
+
+ for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) {
+ if (responses[i].buffer) {
+ XFREE(responses[i].buffer, ssl->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ }
+ }
+ }
+
+ break;
+ }
+ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+ #endif /* NO_WOLFSSL_SERVER */
+
+ default:
+ break;
+ }
+
+ WOLFSSL_LEAVE("SendCertificateStatus", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND);
+
+ return ret;
}
+
#endif /* !NO_CERTS */
+#endif /* WOLFSSL_NO_TLS12 */
+
+
+/* If secure renegotiation is disabled, this will always return false.
+ * Otherwise it checks to see if we are currently renegotiating. */
+static WC_INLINE int IsSCR(WOLFSSL* ssl)
+{
+#ifndef HAVE_SECURE_RENEGOTIATION
+ (void)ssl;
+#else /* HAVE_SECURE_RENEGOTIATION */
+ if (ssl->secure_renegotiation &&
+ ssl->secure_renegotiation->enabled &&
+ ssl->options.handShakeState != HANDSHAKE_DONE)
+ return 1;
+#endif /* HAVE_SECURE_RENEGOTIATION */
+ return 0;
+}
+
int SendData(WOLFSSL* ssl, const void* data, int sz)
{
@@ -7445,24 +17163,66 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
sendSz,
ret,
dtlsExtra = 0;
+ int groupMsgs = 0;
- if (ssl->error == WANT_WRITE)
+ if (ssl->error == WANT_WRITE
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ || ssl->error == WC_PENDING_E
+ #endif
+ ) {
ssl->error = 0;
+ }
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ /* 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 */
+ if (ssl->options.dtls) {
+ ssl->error = 0;
+ }
+ else {
+ WOLFSSL_MSG("Not allowing write after decrypt or mac error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->earlyData != no_early_data) {
+ if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+ WOLFSSL_MSG("handshake complete, trying to send early data");
+ return BUILD_MSG_ERROR;
+ }
+ #ifdef WOLFSSL_EARLY_DATA_GROUP
+ groupMsgs = 1;
+ #endif
+ }
+ else
+#endif
+ if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) {
int err;
WOLFSSL_MSG("handshake not complete, trying to finish");
- if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS)
+ if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* if async would block return WANT_WRITE */
+ if (ssl->error == WC_PENDING_E) {
+ return WOLFSSL_CBIO_ERR_WANT_WRITE;
+ }
+ #endif
return err;
+ }
}
/* last time system socket output buffer was full, try again to send */
- if (ssl->buffers.outputBuffer.length > 0) {
+ if (!groupMsgs && ssl->buffers.outputBuffer.length > 0) {
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)
- return 0; /* peer reset */
+ 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 {
@@ -7484,14 +17244,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
#endif
for (;;) {
-#ifdef HAVE_MAX_FRAGMENT
- int len = min(sz - sent, min(ssl->max_fragment, OUTPUT_RECORD_SIZE));
-#else
- int len = min(sz - sent, OUTPUT_RECORD_SIZE);
-#endif
+ int len;
byte* out;
byte* sendBuffer = (byte*)data + sent; /* may switch on comp */
- int buffSz = len; /* may switch on comp */
+ int buffSz; /* may switch on comp */
int outputSz;
#ifdef HAVE_LIBZ
byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
@@ -7499,19 +17255,21 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
if (sent == sz) break;
+ len = wolfSSL_GetMaxRecordSize(ssl, sz - sent);
+
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- len = min(len, MAX_UDP_SIZE);
- buffSz = len;
+ if (IsDtlsNotSctpMode(ssl)) {
+ len = min(len, MAX_UDP_SIZE);
}
#endif
+ buffSz = len;
/* check for available size */
outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
return ssl->error = ret;
- /* get ouput buffer */
+ /* get output buffer */
out = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
@@ -7524,29 +17282,48 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
sendBuffer = comp;
}
#endif
- sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
- application_data);
- if (sendSz < 0)
+ if (!ssl->options.tls1_3) {
+ sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
+ application_data, 0, 0, 1);
+ }
+ else {
+#ifdef WOLFSSL_TLS13
+ sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz,
+ application_data, 0, 0, 1);
+#else
+ sendSz = BUFFER_ERROR;
+#endif
+ }
+ if (sendSz < 0) {
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (sendSz == WC_PENDING_E)
+ ssl->error = sendSz;
+ #endif
return BUILD_MSG_ERROR;
+ }
ssl->buffers.outputBuffer.length += sendSz;
- if ( (ret = SendBuffered(ssl)) < 0) {
- WOLFSSL_ERROR(ret);
+ 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 = len;
ssl->buffers.prevSent = sent;
- if (ret == SOCKET_ERROR_E && ssl->options.connReset)
- return 0; /* peer reset */
- return ssl->error = ret;
+ 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 += len;
/* only one message per attempt */
if (ssl->options.partialWrite == 1) {
- WOLFSSL_MSG("Paritial Write on, only sending one record");
+ WOLFSSL_MSG("Partial Write on, only sending one record");
break;
}
}
@@ -7561,29 +17338,56 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
WOLFSSL_ENTER("ReceiveData()");
- if (ssl->error == WANT_READ)
+ /* reset error state */
+ if (ssl->error == WANT_READ
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ || ssl->error == WC_PENDING_E
+ #endif
+ ) {
ssl->error = 0;
+ }
+
+#ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ /* In DTLS mode, we forgive some errors and allow the session
+ * to continue despite them. */
+ if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
+ ssl->error = 0;
+ }
+#endif /* WOLFSSL_DTLS */
if (ssl->error != 0 && ssl->error != WANT_WRITE) {
WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
return ssl->error;
}
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->earlyData != no_early_data) {
+ }
+ else
+#endif
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
int err;
WOLFSSL_MSG("Handshake not complete, trying to finish");
- if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS)
+ if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* if async would block return WANT_WRITE */
+ if (ssl->error == WC_PENDING_E) {
+ return WOLFSSL_CBIO_ERR_WANT_READ;
+ }
+ #endif
return err;
+ }
}
#ifdef HAVE_SECURE_RENEGOTIATION
startScr:
if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
int err;
- ssl->secure_renegotiation->startScr = 0; /* only start once */
WOLFSSL_MSG("Need to start scr, server requested");
- if ( (err = wolfSSL_Rehandshake(ssl)) != SSL_SUCCESS)
+ if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS)
return err;
+ ssl->secure_renegotiation->startScr = 0; /* only start once */
}
#endif
@@ -7643,7 +17447,29 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
int outputSz;
int dtlsExtra = 0;
- /* if sendalert is called again for nonbloking */
+ WOLFSSL_ENTER("SendAlert");
+
+#ifdef HAVE_WRITE_DUP
+ if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+ int notifyErr = 0;
+
+ WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
+
+ if (type == close_notify) {
+ notifyErr = ZERO_RETURN;
+ } else if (severity == alert_fatal) {
+ notifyErr = FATAL_ERROR;
+ }
+
+ if (notifyErr != 0) {
+ return NotifyWriteSide(ssl, notifyErr);
+ }
+
+ return 0;
+ }
+#endif
+
+ /* if sendalert is called again for nonblocking */
if (ssl->options.sendAlertState != 0) {
ret = SendBuffered(ssl);
if (ret == 0)
@@ -7651,6 +17477,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
return ret;
}
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_ALERT, type);
+ }
+ #endif
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
dtlsExtra = DTLS_RECORD_EXTRA;
@@ -7661,7 +17492,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* Check output buffer */
+ if (ssl->buffers.outputBuffer.buffer == NULL)
+ return BUFFER_E;
+
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
@@ -7675,8 +17510,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
/* only send encrypted alert if handshake actually complete, otherwise
other side may not be able to handle it */
- if (ssl->keys.encryptionOn && ssl->options.handShakeDone)
- sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert);
+ if (IsEncryptionOn(ssl, 1) && (IsAtLeastTLSv1_3(ssl->version) ||
+ ssl->options.handShakeDone)) {
+ sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert,
+ 0, 0, 0);
+ }
else {
AddRecordHeader(output, ALERT_SIZE, alert, ssl);
@@ -7696,17 +17534,22 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
if (sendSz < 0)
return BUILD_MSG_ERROR;
- #ifdef WOLFSSL_CALLBACKS
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("Alert", &ssl->handShakeInfo);
+ AddPacketName(ssl, "Alert");
if (ssl->toInfoOn)
- AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
+ AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO,
+ ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
ssl->options.sendAlertState = 1;
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendAlert", ret);
+
+ return ret;
}
const char* wolfSSL_ERR_reason_error_string(unsigned long e)
@@ -7727,6 +17570,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
switch (error) {
+#ifdef WOLFSSL_WPAS
+ case 0 :
+ return "ok";
+#endif
+
case UNSUPPORTED_SUITE :
return "unsupported cipher suite";
@@ -7773,7 +17621,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
return "error during decryption";
case FATAL_ERROR :
- return "revcd alert fatal error";
+ return "received alert fatal error";
case ENCRYPT_ERROR :
return "error during encryption";
@@ -7796,6 +17644,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case MATCH_SUITE_ERROR :
return "can't match cipher suite";
+ case COMPRESSION_ERROR :
+ return "compression mismatch error";
+
case BUILD_MSG_ERROR :
return "build message failure";
@@ -7805,21 +17656,21 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case DOMAIN_NAME_MISMATCH :
return "peer subject name mismatch";
+ case IPADDR_MISMATCH :
+ return "peer ip address mismatch";
+
case WANT_READ :
- case SSL_ERROR_WANT_READ :
+ case WOLFSSL_ERROR_WANT_READ :
return "non-blocking socket wants data to be read";
case NOT_READY_ERROR :
return "handshake layer not ready yet, complete first";
- case PMS_VERSION_ERROR :
- return "premaster secret version mismatch error";
-
case VERSION_ERROR :
return "record layer version error";
case WANT_WRITE :
- case SSL_ERROR_WANT_WRITE :
+ case WOLFSSL_ERROR_WANT_WRITE :
return "non-blocking socket write buffer full";
case BUFFER_ERROR :
@@ -7852,15 +17703,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case NTRU_DECRYPT_ERROR:
return "NTRU decrypt error";
- case ZLIB_INIT_ERROR:
- return "zlib init error";
-
- case ZLIB_COMPRESS_ERROR:
- return "zlib compress error";
-
- case ZLIB_DECOMPRESS_ERROR:
- return "zlib decompress error";
-
case GETTIME_ERROR:
return "gettimeofday() error";
@@ -7880,7 +17722,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
return "cant decode peer key";
case ZERO_RETURN:
- case SSL_ERROR_ZERO_RETURN:
+ case WOLFSSL_ERROR_ZERO_RETURN:
return "peer sent close notify alert";
case ECC_CURVETYPE_ERROR:
@@ -7904,8 +17746,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case NOT_CA_ERROR:
return "Not a CA by basic constraint error";
- case BAD_PATH_ERROR:
- return "Bad path for opendir error";
+ case HTTP_TIMEOUT:
+ return "HTTP timeout for OCSP or CRL req";
case BAD_CERT_MANAGER_ERROR:
return "Bad Cert Manager error";
@@ -7919,8 +17761,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case CRL_MISSING:
return "CRL missing, not loaded";
- case MONITOR_RUNNING_E:
- return "CRL monitor already running";
+ case MONITOR_SETUP_E:
+ return "CRL monitor setup error";
case THREAD_CREATE_E:
return "Thread creation problem";
@@ -7946,9 +17788,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case SUITES_ERROR:
return "Suites Pointer Error";
- case SSL_NO_PEM_HEADER:
- return "No PEM Header Error";
-
case OUT_OF_ORDER_E:
return "Out of order message, fatal";
@@ -7976,6 +17815,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case UNKNOWN_SNI_HOST_NAME_E:
return "Unrecognized host name Error";
+ case UNKNOWN_MAX_FRAG_LEN_E:
+ return "Unrecognized max frag len Error";
+
case KEYUSE_SIGNATURE_E:
return "Key Use digitalSignature not set Error";
@@ -7997,9 +17839,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case SESSION_TICKET_EXPECT_E:
return "Session Ticket Error";
- case SCR_DIFFERENT_CERT_E:
- return "Peer sent different cert during SCR";
-
case SESSION_SECRET_CB_E:
return "Session Secret Callback Error";
@@ -8030,830 +17869,916 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case DH_KEY_SIZE_E:
return "DH key too small Error";
- default :
- return "unknown error number";
- }
-
-#endif /* NO_ERROR_STRINGS */
-}
-
-void SetErrorString(int error, char* str)
-{
- XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
-}
-
-
-/* be sure to add to cipher_name_idx too !!!! */
-static const char* const cipher_names[] =
-{
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- "RC4-SHA",
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- "RC4-MD5",
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- "DES-CBC3-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- "AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- "AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
- "NULL-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
- "NULL-SHA256",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- "DHE-RSA-AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- "DHE-RSA-AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
- "DHE-PSK-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
- "DHE-PSK-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
- "PSK-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
- "PSK-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
- "DHE-PSK-AES256-CBC-SHA384",
-#endif
+ case SNI_ABSENT_ERROR:
+ return "No Server Name Indication extension Error";
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
- "DHE-PSK-AES128-CBC-SHA256",
-#endif
+ case RSA_SIGN_FAULT:
+ return "RSA Signature Fault Error";
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
- "PSK-AES256-CBC-SHA384",
-#endif
+ case HANDSHAKE_SIZE_ERROR:
+ return "Handshake message too large Error";
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
- "PSK-AES128-CBC-SHA256",
-#endif
+ case UNKNOWN_ALPN_PROTOCOL_NAME_E:
+ return "Unrecognized protocol name Error";
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- "PSK-AES128-CBC-SHA",
-#endif
+ case BAD_CERTIFICATE_STATUS_ERROR:
+ return "Bad Certificate Status Message Error";
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- "PSK-AES256-CBC-SHA",
-#endif
+ case OCSP_INVALID_STATUS:
+ return "Invalid OCSP Status Error";
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
- "DHE-PSK-AES128-CCM",
-#endif
+ case OCSP_WANT_READ:
+ return "OCSP nonblock wants read";
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
- "DHE-PSK-AES256-CCM",
-#endif
+ case RSA_KEY_SIZE_E:
+ return "RSA key too small";
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
- "PSK-AES128-CCM",
-#endif
+ case ECC_KEY_SIZE_E:
+ return "ECC key too small";
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
- "PSK-AES256-CCM",
-#endif
+ case DTLS_EXPORT_VER_E:
+ return "Version needs updated after code change or version mismatch";
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
- "PSK-AES128-CCM-8",
-#endif
+ case INPUT_SIZE_E:
+ return "Input size too large Error";
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
- "PSK-AES256-CCM-8",
-#endif
+ case CTX_INIT_MUTEX_E:
+ return "Initialize ctx mutex error";
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
- "DHE-PSK-NULL-SHA384",
-#endif
+ case EXT_MASTER_SECRET_NEEDED_E:
+ return "Extended Master Secret must be enabled to resume EMS session";
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
- "DHE-PSK-NULL-SHA256",
-#endif
+ case DTLS_POOL_SZ_E:
+ return "Maximum DTLS pool size exceeded";
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
- "PSK-NULL-SHA384",
-#endif
+ case DECODE_E:
+ return "Decode handshake message error";
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
- "PSK-NULL-SHA256",
-#endif
+ case WRITE_DUP_READ_E:
+ return "Write dup write side can't read error";
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
- "PSK-NULL-SHA",
-#endif
+ case WRITE_DUP_WRITE_E:
+ return "Write dup read side can't write error";
-#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
- "HC128-MD5",
-#endif
+ case INVALID_CERT_CTX_E:
+ return "Certificate context does not match request or not empty";
-#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
- "HC128-SHA",
-#endif
+ case BAD_KEY_SHARE_DATA:
+ return "The Key Share data contains group that wasn't in Client Hello";
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
- "HC128-B2B256",
-#endif
+ case MISSING_HANDSHAKE_DATA:
+ return "The handshake message is missing required data";
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
- "AES128-B2B256",
-#endif
+ case BAD_BINDER:
+ return "Binder value does not match value server calculated";
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
- "AES256-B2B256",
-#endif
+ case EXT_NOT_ALLOWED:
+ return "Extension type not allowed in handshake message type";
-#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
- "RABBIT-SHA",
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- "NTRU-RC4-SHA",
-#endif
+ case INVALID_PARAMETER:
+ return "The security parameter is invalid";
-#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
- "NTRU-DES-CBC3-SHA",
-#endif
+ case UNSUPPORTED_EXTENSION:
+ return "TLS Extension not requested by the client";
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
- "NTRU-AES128-SHA",
-#endif
+ case PRF_MISSING:
+ return "Pseudo-random function is not enabled";
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- "NTRU-AES256-SHA",
-#endif
+ case KEY_SHARE_ERROR:
+ return "Key share extension did not contain a valid named group";
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
- "AES128-CCM-8",
-#endif
+ case POST_HAND_AUTH_ERROR:
+ return "Client will not do post handshake authentication";
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
- "AES256-CCM-8",
-#endif
+ case HRR_COOKIE_ERROR:
+ return "Cookie does not match one sent in HelloRetryRequest";
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
- "ECDHE-ECDSA-AES128-CCM-8",
-#endif
+ case MCAST_HIGHWATER_CB_E:
+ return "Multicast highwater callback returned error";
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
- "ECDHE-ECDSA-AES256-CCM-8",
-#endif
+ case ALERT_COUNT_E:
+ return "Alert Count exceeded error";
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- "ECDHE-RSA-AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- "ECDHE-RSA-AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- "ECDHE-ECDSA-AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- "ECDHE-ECDSA-AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- "ECDHE-RSA-RC4-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- "ECDHE-RSA-DES-CBC3-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- "ECDHE-ECDSA-RC4-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- "ECDHE-ECDSA-DES-CBC3-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- "AES128-SHA256",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- "AES256-SHA256",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- "DHE-RSA-AES128-SHA256",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- "DHE-RSA-AES256-SHA256",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- "ECDH-RSA-AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- "ECDH-RSA-AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- "ECDH-ECDSA-AES128-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- "ECDH-ECDSA-AES256-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
- "ECDH-RSA-RC4-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- "ECDH-RSA-DES-CBC3-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- "ECDH-ECDSA-RC4-SHA",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- "ECDH-ECDSA-DES-CBC3-SHA",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
- "AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
- "AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- "DHE-RSA-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- "DHE-RSA-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- "ECDHE-RSA-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- "ECDHE-RSA-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- "ECDHE-ECDSA-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- "ECDHE-ECDSA-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- "ECDH-RSA-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- "ECDH-RSA-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- "ECDH-ECDSA-AES128-GCM-SHA256",
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- "ECDH-ECDSA-AES256-GCM-SHA384",
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- "CAMELLIA128-SHA",
-#endif
+ case EXT_MISSING:
+ return "Required TLS extension missing";
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- "DHE-RSA-CAMELLIA128-SHA",
-#endif
+ case DTLS_RETX_OVER_TX:
+ return "DTLS interrupting flight transmit with retransmit";
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- "CAMELLIA256-SHA",
-#endif
+ case DH_PARAMS_NOT_FFDHE_E:
+ return "Server DH parameters were not from the FFDHE set as required";
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- "DHE-RSA-CAMELLIA256-SHA",
-#endif
+ case TCA_INVALID_ID_TYPE:
+ return "TLS Extension Trusted CA ID type invalid";
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- "CAMELLIA128-SHA256",
-#endif
+ case TCA_ABSENT_ERROR:
+ return "TLS Extension Trusted CA ID response absent";
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- "DHE-RSA-CAMELLIA128-SHA256",
-#endif
+ case TSIP_MAC_DIGSZ_E:
+ return "TSIP MAC size invalid, must be sized for SHA-1 or SHA-256";
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- "CAMELLIA256-SHA256",
-#endif
+ case CLIENT_CERT_CB_ERROR:
+ return "Error importing client cert or key from callback";
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- "DHE-RSA-CAMELLIA256-SHA256",
-#endif
+ case SSL_SHUTDOWN_ALREADY_DONE_E:
+ return "Shutdown has already occurred";
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- "ECDHE-RSA-AES128-SHA256",
-#endif
+ case TLS13_SECRET_CB_E:
+ return "TLS1.3 Secret Callback Error";
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- "ECDHE-ECDSA-AES128-SHA256",
-#endif
+ default :
+ return "unknown error number";
+ }
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- "ECDH-RSA-AES128-SHA256",
-#endif
+#endif /* NO_ERROR_STRINGS */
+}
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- "ECDH-ECDSA-AES128-SHA256",
-#endif
+void SetErrorString(int error, char* str)
+{
+ XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
+ str[WOLFSSL_MAX_ERROR_SZ-1] = 0;
+}
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- "ECDHE-RSA-AES256-SHA384",
+#ifndef NO_ERROR_STRINGS
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w),(v),(u)}
+ #else
+ #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w)}
+ #endif
+#else
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w),(v),(u)}
+ #else
+ #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w)}
+ #endif
#endif
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- "ECDHE-ECDSA-AES256-SHA384",
-#endif
+static const CipherSuiteInfo cipher_names[] =
+{
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- "ECDH-RSA-AES256-SHA384",
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+ SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- "ECDH-ECDSA-AES256-SHA384",
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+ SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384, TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- "ECDHE-RSA-CHACHA20-POLY1305",
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+ SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- "ECDHE-ECDSA-CHACHA20-POLY1305",
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+ SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- "DHE-RSA-CHACHA20-POLY1305",
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+ SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
- "ADH-AES128-SHA",
+#ifdef BUILD_TLS_SHA256_SHA256
+ SUITE_INFO("TLS13-SHA256-SHA256","TLS_SHA256_SHA256",ECC_BYTE,TLS_SHA256_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-#ifdef HAVE_RENEGOTIATION_INDICATION
- "RENEGOTIATION-INFO",
+#ifdef BUILD_TLS_SHA384_SHA384
+ SUITE_INFO("TLS13-SHA384-SHA384","TLS_SHA384_SHA384",ECC_BYTE,TLS_SHA384_SHA384,TLSv1_3_MINOR, SSLv3_MAJOR),
#endif
-};
-
-/* cipher suite number that matches above name table */
-static int cipher_name_idx[] =
-{
+#ifndef WOLFSSL_NO_TLS12
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- SSL_RSA_WITH_RC4_128_SHA,
+ SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- SSL_RSA_WITH_RC4_128_MD5,
+ SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_MD5
+ SUITE_INFO("NULL-MD5","TLS_RSA_WITH_NULL_MD5",CIPHER_BYTE,TLS_RSA_WITH_NULL_MD5,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
- TLS_RSA_WITH_NULL_SHA,
+ SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
- TLS_RSA_WITH_NULL_SHA256,
+ SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
- TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
- TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
- TLS_PSK_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
- TLS_PSK_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
- TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
- TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
- TLS_PSK_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
- TLS_PSK_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- TLS_PSK_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- TLS_PSK_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
- TLS_DHE_PSK_WITH_AES_128_CCM,
+ SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
- TLS_DHE_PSK_WITH_AES_256_CCM,
+ SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
- TLS_PSK_WITH_AES_128_CCM,
+ SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
- TLS_PSK_WITH_AES_256_CCM,
+ SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
- TLS_PSK_WITH_AES_128_CCM_8,
+ SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
- TLS_PSK_WITH_AES_256_CCM_8,
+ SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
- TLS_DHE_PSK_WITH_NULL_SHA384,
+ SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
- TLS_DHE_PSK_WITH_NULL_SHA256,
+ SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
- TLS_PSK_WITH_NULL_SHA384,
+ SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
- TLS_PSK_WITH_NULL_SHA256,
+ SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
- TLS_PSK_WITH_NULL_SHA,
+ SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
- TLS_RSA_WITH_HC_128_MD5,
+ SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
- TLS_RSA_WITH_HC_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
- TLS_RSA_WITH_HC_128_B2B256,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
- TLS_RSA_WITH_AES_128_CBC_B2B256,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
- TLS_RSA_WITH_AES_256_CBC_B2B256,
+ SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
- TLS_RSA_WITH_RABBIT_SHA,
+ SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- TLS_NTRU_RSA_WITH_RC4_128_SHA,
+ SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
- TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
- TLS_RSA_WITH_AES_128_CCM_8,
+ SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
- TLS_RSA_WITH_AES_256_CCM_8,
+ SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+ SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
- TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
- TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA256,
+ SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
- TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+ SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
- TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+ SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_QSH
+ SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH, TLSv1_MINOR, SSLv3_MAJOR),
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION
- TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+ SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+ SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+ SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+ SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+ SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+ SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR)
+#endif
+
+#endif /* WOLFSSL_NO_TLS12 */
};
/* returns the cipher_names array */
-const char* const* GetCipherNames(void)
+const CipherSuiteInfo* GetCipherNames(void)
{
return cipher_names;
}
-/* returns the size of the cipher_names array */
+/* returns the number of elements in the cipher_names array */
int GetCipherNamesSize(void)
{
- return (int)(sizeof(cipher_names) / sizeof(char*));
+ return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo));
+}
+
+
+const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite)
+{
+ int i;
+ const char* nameInternal = "None";
+
+ for (i = 0; i < GetCipherNamesSize(); i++) {
+ if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+ (cipher_names[i].cipherSuite == cipherSuite)) {
+ nameInternal = cipher_names[i].name;
+ break;
+ }
+ }
+ return nameInternal;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]) {
+ const char* keaStr = NULL;
+ const char *n0,*n1,*n2,*n3,*n4;
+ n0 = n[0];
+ n1 = n[1];
+ n2 = n[2];
+ n3 = n[3];
+ n4 = n[4];
+
+ if (XSTRNCMP(n0,"ECDHE",5) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+ keaStr = "ECDHEPSK";
+ else if (XSTRNCMP(n0,"ECDH",4) == 0)
+ keaStr = "ECDH";
+ else if (XSTRNCMP(n0,"DHE",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+ keaStr = "DHEPSK";
+ else if (XSTRNCMP(n0,"DHE",3) == 0)
+ keaStr = "DH";
+ else if (XSTRNCMP(n0,"RSA",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+ keaStr = "RSAPSK";
+ else if (XSTRNCMP(n0,"SRP",3) == 0)
+ keaStr = "SRP";
+ else if (XSTRNCMP(n0,"PSK",3) == 0)
+ keaStr = "PSK";
+ else if (XSTRNCMP(n0,"EDH",3) == 0)
+ keaStr = "EDH";
+ else if ((XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) ||
+ (XSTRNCMP(n3,"SHA",3) == 0) || (XSTRNCMP(n4,"SHA",3) == 0) ||
+ (XSTRNCMP(n2,"RSA",3) == 0) || (XSTRNCMP(n0,"AES128",6) == 0) ||
+ (XSTRNCMP(n0,"AES256",6) == 0) || (XSTRNCMP(n1,"MD5",3) == 0))
+ keaStr = "RSA";
+ else
+ keaStr = "unknown";
+
+ return keaStr;
+}
+
+const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]) {
+
+ const char* authStr = NULL;
+ const char *n0,*n1,*n2;
+ n0 = n[0];
+ n1 = n[1];
+ n2 = n[2];
+
+ if ((XSTRNCMP(n0,"AES128",6) == 0) || (XSTRNCMP(n0,"AES256",6) == 0) ||
+ ((XSTRNCMP(n0,"TLS13",5) == 0) && ((XSTRNCMP(n1,"AES128",6) == 0) ||
+ (XSTRNCMP(n1,"AES256",6) == 0) || (XSTRNCMP(n1,"CHACHA20",8) == 0))) ||
+ (XSTRNCMP(n0,"RSA",3) == 0) || (XSTRNCMP(n1,"RSA",3) == 0) ||
+ (XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) ||
+ (XSTRNCMP(n1,"MD5",3) == 0))
+ authStr = "RSA";
+ else if (XSTRNCMP(n0,"PSK",3) == 0 || XSTRNCMP(n1,"PSK",3) == 0)
+ authStr = "PSK";
+ else if (XSTRNCMP(n0,"SRP",3) == 0 && XSTRNCMP(n1,"AES",3) == 0)
+ authStr = "SRP";
+ else if (XSTRNCMP(n1,"ECDSA",5) == 0)
+ authStr = "ECDSA";
+ else
+ authStr = "unknown";
+
+ return authStr;
+}
+
+const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]) {
+ const char* encStr = NULL;
+ const char *n0,*n1,*n2,*n3;
+ n0 = n[0];
+ n1 = n[1];
+ n2 = n[2];
+ n3 = n[3];
+
+ if ((XSTRNCMP(n0,"AES256",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) ||
+ (XSTRNCMP(n1,"AES256",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) ||
+ (XSTRNCMP(n2,"AES256",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0))
+ encStr = "AESGCM(256)";
+
+ else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) ||
+ (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) ||
+ (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0))
+ encStr = "AESGCM(128)";
+
+ else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"CCM",3) == 0) ||
+ (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"CCM",3) == 0) ||
+ (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"CCM",3) == 0))
+ encStr = "AESCCM(128)";
+
+ else if ((XSTRNCMP(n0,"AES128",6) == 0) ||
+ (XSTRNCMP(n1,"AES128",6) == 0) ||
+ (XSTRNCMP(n2,"AES128",6) == 0) ||
+ (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"128",3) == 0) ||
+ (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"128",3) == 0))
+ encStr = "AES(128)";
+
+ else if ((XSTRNCMP(n0,"AES256",6) == 0) ||
+ (XSTRNCMP(n1,"AES256",6) == 0) ||
+ (XSTRNCMP(n2,"AES256",6) == 0) ||
+ (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"256",3) == 0) ||
+ (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"256",3) == 0))
+ encStr = "AES(256)";
+
+ else if ((XSTRNCMP(n0,"CAMELLIA256",11) == 0) ||
+ (XSTRNCMP(n2,"CAMELLIA256",11) == 0))
+ encStr = "CAMELLIA(256)";
+ else if ((XSTRNCMP(n0,"CAMELLIA128",11) == 0) ||
+ (XSTRNCMP(n2,"CAMELLIA128",11) == 0))
+ encStr = "CAMELLIA(128)";
+ else if ((XSTRNCMP(n0,"RC4",3) == 0) || (XSTRNCMP(n2,"RC4",3) == 0))
+ encStr = "RC4";
+ else if (((XSTRNCMP(n0,"DES",3) == 0) || (XSTRNCMP(n2,"DES",3) == 0)) &&
+ ((XSTRNCMP(n1,"CBC3",4) == 0) || (XSTRNCMP(n3,"CBC3",4) == 0)))
+ encStr = "3DES";
+ else if ((XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) ||
+ (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0))
+ encStr = "CHACHA20/POLY1305(256)";
+ else if ((XSTRNCMP(n0,"NULL",4) == 0) || (XSTRNCMP(n1,"NULL",4) == 0) ||
+ (XSTRNCMP(n2,"NULL",4) == 0) ||
+ ((XSTRNCMP(n0,"TLS13",5) == 0) && (XSTRNCMP(n3,"",0) == 0)))
+ encStr = "None";
+ else if ((XSTRNCMP(n0,"IDEA",4) == 0))
+ encStr = "IDEA";
+ else if ((XSTRNCMP(n0,"RABBIT",4) == 0))
+ encStr = "RABBIT";
+ else if ((XSTRNCMP(n0,"HC128",5) == 0))
+ encStr = "HC128";
+ else
+ encStr = "unknown";
+
+ return encStr;
+}
+
+/* Returns the MAC string of a cipher or "unknown" on failure */
+const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]) {
+
+ const char* macStr = NULL;
+ const char *n1,*n2,*n3,*n4;
+ n1 = n[1];
+ n2 = n[2];
+ n3 = n[3];
+ n4 = n[4];
+
+ if ((XSTRNCMP(n4,"SHA256",6) == 0) || (XSTRNCMP(n3,"SHA256",6) == 0) ||
+ (XSTRNCMP(n2,"SHA256",6) == 0) || (XSTRNCMP(n1,"SHA256",6) == 0))
+ macStr = "SHA256";
+ else if ((XSTRNCMP(n4,"SHA384",6) == 0) ||
+ (XSTRNCMP(n3,"SHA384",6) == 0) ||
+ (XSTRNCMP(n2,"SHA384",6) == 0) ||
+ (XSTRNCMP(n1,"SHA384",6) == 0))
+ macStr = "SHA384";
+ else if ((XSTRNCMP(n4,"SHA",3) == 0) || (XSTRNCMP(n3,"SHA",3) == 0) ||
+ (XSTRNCMP(n2,"SHA",3) == 0) || (XSTRNCMP(n1,"SHA",3) == 0) ||
+ (XSTRNCMP(n1,"MD5",3) == 0))
+ macStr = "SHA1";
+ else if ((XSTRNCMP(n3,"GCM",3) == 0) ||
+ (XSTRNCMP(n1,"CCM",3) == 0) ||
+ (XSTRNCMP(n2,"CCM",3) == 0) || (XSTRNCMP(n3,"CCM",3) == 0) ||
+ (XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) ||
+ (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0))
+ macStr = "AEAD";
+ else
+ macStr = "unknown";
+
+ return macStr;
+}
+
+/* Returns the number of bits based on the cipher enc string, or 0 on failure */
+int SetCipherBits(const char* enc) {
+ int ret = WOLFSSL_FAILURE;
+
+ if ((XSTRNCMP(enc,"AESGCM(256)",11) == 0) ||
+ (XSTRNCMP(enc,"AES(256)",8) == 0) ||
+ (XSTRNCMP(enc,"CAMELLIA(256)",13) == 0) ||
+ (XSTRNCMP(enc,"CHACHA20/POLY1305(256)",22) == 0))
+ ret = 256;
+ else if
+ ((XSTRNCMP(enc,"3DES",4) == 0))
+ ret = 168;
+ else if
+ ((XSTRNCMP(enc,"AESGCM(128)",11) == 0) ||
+ (XSTRNCMP(enc,"AES(128)",8) == 0) ||
+ (XSTRNCMP(enc,"CAMELLIA(128)",13) == 0) ||
+ (XSTRNCMP(enc,"IDEA",4) == 0) ||
+ (XSTRNCMP(enc,"RC4",3) == 0))
+ ret = 128;
+ else if
+ ((XSTRNCMP(enc,"DES",3) == 0))
+ ret = 56;
+
+ return ret;
+}
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite)
+{
+#ifndef NO_ERROR_STRINGS
+ int i;
+ const char* nameIana = "NONE";
+
+ for (i = 0; i < GetCipherNamesSize(); i++) {
+ if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+ (cipher_names[i].cipherSuite == cipherSuite)) {
+ nameIana = cipher_names[i].name_iana;
+ break;
+ }
+ }
+ return nameIana;
+#else
+ (void)cipherSuite0;
+ (void)cipherSuite;
+ return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return NULL;
+ }
+
+ return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite);
}
+const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return NULL;
+ }
+
+ return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite);
+}
+
+int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
+ byte* cipherSuite)
+{
+ int ret = BAD_FUNC_ARG;
+ int i;
+ unsigned long len = (unsigned long)XSTRLEN(name);
+
+ for (i = 0; i < GetCipherNamesSize(); i++) {
+ if (XSTRNCMP(name, cipher_names[i].name, len) == 0) {
+ *cipherSuite0 = cipher_names[i].cipherSuite0;
+ *cipherSuite = cipher_names[i].cipherSuite;
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
/**
Set the enabled cipher suites.
@param [out] suites Suites structure.
@param [in] list List of cipher suites, only supports full name from
- cipher_name[] delimited by ':'.
+ cipher_names[] delimited by ':'.
@return true on success, else false.
*/
-int SetCipherList(Suites* suites, const char* list)
+int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list)
{
int ret = 0;
int idx = 0;
@@ -8868,8 +18793,9 @@ int SetCipherList(Suites* suites, const char* list)
return 0;
}
- if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0)
- return 1; /* wolfSSL defualt */
+ if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 ||
+ XSTRNCMP(next, "DEFAULT", 7) == 0)
+ return 1; /* wolfSSL default */
do {
char* current = next;
@@ -8885,22 +18811,67 @@ int SetCipherList(Suites* suites, const char* list)
name[(length == sizeof(name)) ? length - 1 : length] = 0;
for (i = 0; i < suiteSz; i++) {
- if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
- suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE
- : (XSTRSTR(name, "EC")) ? ECC_BYTE
- : (XSTRSTR(name, "CCM")) ? ECC_BYTE
- : 0x00; /* normal */
+ if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0
+ #ifndef NO_ERROR_STRINGS
+ || XSTRNCMP(name, cipher_names[i].name_iana, sizeof(name)) == 0
+ #endif
+ ) {
+ #ifdef WOLFSSL_DTLS
+ /* don't allow stream ciphers with DTLS */
+ if (ctx->method->version.major == DTLS_MAJOR) {
+ if (XSTRSTR(name, "RC4") ||
+ XSTRSTR(name, "HC128") ||
+ XSTRSTR(name, "RABBIT"))
+ {
+ WOLFSSL_MSG("Stream ciphers not supported with DTLS");
+ continue;
+ }
- suites->suites[idx++] = (byte)cipher_name_idx[i];
+ }
+ #endif /* WOLFSSL_DTLS */
+ if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) {
+ WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low");
+ return 0; /* suites buffer not large enough, error out */
+ }
+
+ suites->suites[idx++] = cipher_names[i].cipherSuite0;
+ suites->suites[idx++] = cipher_names[i].cipherSuite;
/* The suites are either ECDSA, RSA, PSK, or Anon. The RSA
* suites don't necessarily have RSA in the name. */
+ #ifdef WOLFSSL_TLS13
+ if (cipher_names[i].cipherSuite0 == TLS13_BYTE ||
+ (cipher_names[i].cipherSuite0 == ECC_BYTE &&
+ (cipher_names[i].cipherSuite == TLS_SHA256_SHA256 ||
+ cipher_names[i].cipherSuite == TLS_SHA384_SHA384))) {
+ #ifndef NO_RSA
+ haveRSAsig = 1;
+ #endif
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
+ haveECDSAsig = 1;
+ #endif
+ }
+ else
+ #endif
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
haveECDSAsig = 1;
- else if (XSTRSTR(name, "ADH"))
+ else
+ #endif
+ #ifdef HAVE_ANON
+ if (XSTRSTR(name, "ADH"))
haveAnon = 1;
- else if ((haveRSAsig == 0) && (XSTRSTR(name, "PSK") == NULL))
+ else
+ #endif
+ if (haveRSAsig == 0
+ #ifndef NO_PSK
+ && (XSTRSTR(name, "PSK") == NULL)
+ #endif
+ ) {
haveRSAsig = 1;
+ }
ret = 1; /* found at least one */
break;
@@ -8910,59 +18881,205 @@ int SetCipherList(Suites* suites, const char* list)
while (next++); /* ++ needed to skip ':' */
if (ret) {
+ int keySz = 0;
+ #ifndef NO_CERTS
+ keySz = ctx->privateKeySz;
+ #endif
suites->setSuites = 1;
suites->suiteSz = (word16)idx;
- InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon);
+ InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1,
+ keySz);
}
+ (void)ctx;
+
return ret;
}
-static void PickHashSigAlgo(WOLFSSL* ssl,
- const byte* hashSigAlgo, word32 hashSigAlgoSz)
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
+int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
{
word32 i;
+ int ret = MATCH_SUITE_ERROR;
ssl->suites->sigAlgo = ssl->specs.sig_algo;
- ssl->suites->hashAlgo = sha_mac;
+
+ /* set defaults */
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ ssl->suites->hashAlgo = sha256_mac;
+ #ifndef NO_CERTS
+ ssl->suites->sigAlgo = ssl->buffers.keyType;
+ #endif
+ }
+#ifndef WOLFSSL_NO_TLS12
+ else if (IsAtLeastTLSv1_2(ssl)) {
+ #ifdef WOLFSSL_ALLOW_TLS_SHA1
+ ssl->suites->hashAlgo = sha_mac;
+ #else
+ ssl->suites->hashAlgo = sha256_mac;
+ #endif
+ }
+ else {
+ ssl->suites->hashAlgo = sha_mac;
+ }
+#endif
+
+ if (hashSigAlgoSz == 0)
+ return 0;
/* i+1 since peek a byte ahead for type */
- for (i = 0; (i+1) < hashSigAlgoSz; i += 2) {
- if (hashSigAlgo[i+1] == ssl->specs.sig_algo) {
- if (hashSigAlgo[i] == sha_mac) {
+ for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) {
+ byte hashAlgo = 0, sigAlgo = 0;
+
+ DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo);
+ #ifdef HAVE_ED25519
+ if (ssl->pkCurveOID == ECC_ED25519_OID) {
+ if (sigAlgo != ed25519_sa_algo)
+ continue;
+ if (sigAlgo == ed25519_sa_algo &&
+ ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
+ ssl->suites->sigAlgo = sigAlgo;
+ ssl->suites->hashAlgo = sha512_mac;
+ ret = 0;
break;
}
- #ifndef NO_SHA256
- else if (hashSigAlgo[i] == sha256_mac) {
- ssl->suites->hashAlgo = sha256_mac;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ if (ssl->pkCurveOID == ECC_ED448_OID) {
+ if (sigAlgo != ed448_sa_algo)
+ continue;
+
+ if (sigAlgo == ed448_sa_algo &&
+ ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
+ ssl->suites->sigAlgo = sigAlgo;
+ ssl->suites->hashAlgo = sha512_mac;
+ ret = 0;
break;
}
+ }
+ #endif
+ #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC)
+ if (IsAtLeastTLSv1_3(ssl->version) && sigAlgo == ssl->suites->sigAlgo &&
+ sigAlgo == ecc_dsa_sa_algo) {
+
+ int digestSz = GetMacDigestSize(hashAlgo);
+ if (digestSz <= 0)
+ continue;
+
+ /* TLS 1.3 signature algorithms for ECDSA match hash length with
+ * key size.
+ */
+ if (digestSz != ssl->buffers.keySz)
+ continue;
+
+ ssl->suites->hashAlgo = hashAlgo;
+ ssl->suites->sigAlgo = sigAlgo;
+ ret = 0;
+ break; /* done selected sig/hash algorithms */
+ }
+ else
+ #endif
+ /* For ECDSA the `USE_ECDSA_KEYSZ_HASH_ALGO` build option will choose a hash
+ * algorithm that matches the ephemeral ECDHE key size or the next highest
+ * available. This workaround resolves issue with some peer's that do not
+ * properly support scenarios such as a P-256 key hashed with SHA512.
+ */
+ #if defined(HAVE_ECC) && defined(USE_ECDSA_KEYSZ_HASH_ALGO)
+ if (sigAlgo == ssl->suites->sigAlgo && sigAlgo == ecc_dsa_sa_algo) {
+ int digestSz = GetMacDigestSize(hashAlgo);
+ if (digestSz <= 0)
+ continue;
+
+ /* For ecc_dsa_sa_algo, pick hash algo that is curve size unless
+ algorithm in not compiled in, then choose next highest */
+ if (digestSz == ssl->eccTempKeySz) {
+ ssl->suites->hashAlgo = hashAlgo;
+ ssl->suites->sigAlgo = sigAlgo;
+ #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
#endif
- #ifdef WOLFSSL_SHA384
- else if (hashSigAlgo[i] == sha384_mac) {
- ssl->suites->hashAlgo = sha384_mac;
- break;
+ ret = 0;
+ break; /* done selected sig/hash algorithms */
}
+ /* not strong enough, so keep checking hashSigAlso list */
+ if (digestSz < ssl->eccTempKeySz)
+ continue;
+
+ /* mark as highest and check remainder of hashSigAlgo list */
+ ssl->suites->hashAlgo = hashAlgo;
+ ssl->suites->sigAlgo = sigAlgo;
+ ret = 0;
+ }
+ else
+ #endif
+ #ifdef WC_RSA_PSS
+ if (IsAtLeastTLSv1_3(ssl->version) &&
+ ssl->suites->sigAlgo == rsa_sa_algo &&
+ sigAlgo != rsa_pss_sa_algo) {
+ continue;
+ }
+ else if (sigAlgo == ssl->suites->sigAlgo ||
+ (sigAlgo == rsa_pss_sa_algo &&
+ (ssl->suites->sigAlgo == rsa_sa_algo)))
+ #else
+ if (sigAlgo == ssl->suites->sigAlgo)
+ #endif
+ {
+ /* pick highest available between both server and client */
+ switch (hashAlgo) {
+ case sha_mac:
+ #ifdef WOLFSSL_SHA224
+ case sha224_mac:
+ #endif
+ #ifndef NO_SHA256
+ case sha256_mac:
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case sha384_mac:
#endif
#ifdef WOLFSSL_SHA512
- else if (hashSigAlgo[i] == sha512_mac) {
- ssl->suites->hashAlgo = sha512_mac;
- break;
- }
+ case sha512_mac:
#endif
+ /* not strong enough, so keep checking hashSigAlso list */
+ if (hashAlgo < ssl->suites->hashAlgo) {
+ ret = 0;
+ continue;
+ }
+ /* mark as highest and check remainder of hashSigAlgo list */
+ ssl->suites->hashAlgo = hashAlgo;
+ ssl->suites->sigAlgo = sigAlgo;
+ break;
+ default:
+ continue;
+ }
+ ret = 0;
+ break;
+ }
+#if defined(WOLFSSL_TLS13)
+ else if (ssl->specs.sig_algo == 0 && IsAtLeastTLSv1_3(ssl->version)) {
+ }
+#endif
+ else if (ssl->specs.sig_algo == 0)
+ {
+ ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
+ ret = 0;
}
}
-}
+ return ret;
+}
+#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
-#ifdef WOLFSSL_CALLBACKS
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- /* Initialisze HandShakeInfo */
- void InitHandShakeInfo(HandShakeInfo* info)
+ /* Initialize HandShakeInfo */
+ void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl)
{
int i;
+ info->ssl = ssl;
info->cipherName[0] = 0;
for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
info->packetNames[i][0] = 0;
@@ -8971,36 +19088,46 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
/* Set Final HandShakeInfo parameters */
- void FinishHandShakeInfo(HandShakeInfo* info, const WOLFSSL* ssl)
+ void FinishHandShakeInfo(HandShakeInfo* info)
{
int i;
- int sz = sizeof(cipher_name_idx)/sizeof(int);
+ int sz = GetCipherNamesSize();
for (i = 0; i < sz; i++)
- if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
- if (ssl->options.cipherSuite0 == ECC_BYTE)
+ if (info->ssl->options.cipherSuite ==
+ (byte)cipher_names[i].cipherSuite) {
+ if (info->ssl->options.cipherSuite0 == ECC_BYTE)
continue; /* ECC suites at end */
- XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
+ XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ);
+ info->cipherName[MAX_CIPHERNAME_SZ] = '\0';
break;
}
/* error max and min are negative numbers */
- if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
- info->negotiationError = ssl->error;
+ if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR)
+ info->negotiationError = info->ssl->error;
}
/* Add name to info packet names, increase packet name count */
- void AddPacketName(const char* name, HandShakeInfo* info)
+ void AddPacketName(WOLFSSL* ssl, const char* name)
{
+ #ifdef WOLFSSL_CALLBACKS
+ HandShakeInfo* info = &ssl->handShakeInfo;
if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
- XSTRNCPY(info->packetNames[info->numberPackets++], name,
- MAX_PACKETNAME_SZ);
+ char* packetName = info->packetNames[info->numberPackets];
+ XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+ packetName[MAX_PACKETNAME_SZ] = '\0';
+ info->numberPackets++;
}
+ #endif
+ (void)ssl;
+ (void)name;
}
- /* Initialisze TimeoutInfo */
+ #ifdef WOLFSSL_CALLBACKS
+ /* Initialize TimeoutInfo */
void InitTimeoutInfo(TimeoutInfo* info)
{
int i;
@@ -9034,18 +19161,61 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
+ /* Add packet name to previously added packet info */
+ void AddLateName(const char* name, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ char* packetName = info->packets[info->numberPackets-1].packetName;
+ XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+ packetName[MAX_PACKETNAME_SZ] = '\0';
+ }
+ }
- /* Add PacketInfo to TimeoutInfo */
- void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
- int sz, void* heap)
+ /* Add record header to previously added packet info */
+ void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ if (info->packets[info->numberPackets - 1].bufferValue)
+ XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
+ RECORD_HEADER_SZ);
+ else
+ XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
+ RECORD_HEADER_SZ);
+ }
+ }
+
+ #endif /* WOLFSSL_CALLBACKS */
+
+
+ /* Add PacketInfo to TimeoutInfo
+ *
+ * ssl WOLFSSL structure sending or receiving packet
+ * name name of packet being sent
+ * type type of packet being sent
+ * data data bing sent with packet
+ * sz size of data buffer
+ * written 1 if this packet is being written to wire, 0 if being read
+ * heap custom heap to use for mallocs/frees
+ */
+ void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
+ const byte* data, int sz, int written, void* heap)
{
+ #ifdef WOLFSSL_CALLBACKS
+ TimeoutInfo* info = &ssl->timeoutInfo;
+
if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
- Timeval currTime;
+ WOLFSSL_TIMEVAL currTime;
/* may add name after */
- if (name)
- XSTRNCPY(info->packets[info->numberPackets].packetName, name,
- MAX_PACKETNAME_SZ);
+ if (name) {
+ char* packetName = info->packets[info->numberPackets].packetName;
+ XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+ packetName[MAX_PACKETNAME_SZ] = '\0';
+ }
/* add data, put in buffer if bigger than static buffer */
info->packets[info->numberPackets].valueSz = sz;
@@ -9053,7 +19223,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
XMEMCPY(info->packets[info->numberPackets].value, data, sz);
else {
info->packets[info->numberPackets].bufferValue =
- XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
+ (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
if (!info->packets[info->numberPackets].bufferValue)
/* let next alloc catch, just don't fill, not fatal here */
info->packets[info->numberPackets].valueSz = 0;
@@ -9068,42 +19238,293 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
currTime.tv_usec;
info->numberPackets++;
}
+ #endif /* WOLFSSL_CALLBACKS */
+ #ifdef OPENSSL_EXTRA
+ if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) {
+ /* version from hex to dec 16 is 16^1, 256 from 16^2 and
+ 4096 from 16^3 */
+ int version = (ssl->version.minor & 0X0F) +
+ (ssl->version.minor & 0xF0) * 16 +
+ (ssl->version.major & 0X0F) * 256 +
+ (ssl->version.major & 0xF0) * 4096;
+
+ ssl->protoMsgCb(written, version, type,
+ (const void *)(data + RECORD_HEADER_SZ),
+ (size_t)(sz - RECORD_HEADER_SZ),
+ ssl, ssl->protoMsgCtx);
+ }
+ #endif /* OPENSSL_EXTRA */
+ (void)written;
+ (void)name;
+ (void)heap;
+ (void)type;
+ (void)ssl;
}
+#endif /* WOLFSSL_CALLBACKS */
+
+#if !defined(NO_CERTS)
- /* Add packet name to previsouly added packet info */
- void AddLateName(const char* name, TimeoutInfo* info)
- {
- /* make sure we have a valid previous one */
- if (info->numberPackets > 0 && info->numberPackets <
- MAX_PACKETS_HANDSHAKE) {
- XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
- MAX_PACKETNAME_SZ);
+/* Decode the private key - RSA/ECC/Ed25519/Ed448 - and creates a key object.
+ * The signature type is set as well.
+ * The maximum length of a signature is returned.
+ *
+ * ssl The SSL/TLS object.
+ * length The length of a signature.
+ * returns 0 on success, otherwise failure.
+ */
+int DecodePrivateKey(WOLFSSL *ssl, word16* length)
+{
+ int ret = BAD_FUNC_ARG;
+ int keySz;
+ word32 idx;
+
+#ifdef HAVE_PK_CALLBACKS
+ /* allow no private key if using PK callbacks and CB is set */
+ if (wolfSSL_IsPrivatePkSet(ssl)) {
+ *length = GetPrivateKeySigSize(ssl);
+ return 0;
+ }
+ else
+#endif
+
+ /* make sure private key exists */
+ if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) {
+ WOLFSSL_MSG("Private key missing!");
+ ERROR_OUT(NO_PRIVATE_KEY, exit_dpk);
+ }
+
+#ifdef HAVE_PKCS11
+ if (ssl->buffers.keyDevId != INVALID_DEVID && ssl->buffers.keyId) {
+ if (ssl->buffers.keyType == rsa_sa_algo)
+ ssl->hsType = DYNAMIC_TYPE_RSA;
+ else if (ssl->buffers.keyType == ecc_dsa_sa_algo)
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_dpk;
+ }
+
+ if (ssl->buffers.keyType == rsa_sa_algo) {
+ #ifndef NO_RSA
+ ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsKey,
+ ssl->buffers.key->buffer, ssl->buffers.key->length,
+ ssl->heap, ssl->buffers.keyDevId);
+ if (ret == 0) {
+ if (ssl->buffers.keySz < ssl->options.minRsaKeySz) {
+ WOLFSSL_MSG("RSA key size too small");
+ ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = (word16)ssl->buffers.keySz;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else if (ssl->buffers.keyType == ecc_dsa_sa_algo) {
+ #ifdef HAVE_ECC
+ ret = wc_ecc_init_id((ecc_key*)ssl->hsKey, ssl->buffers.key->buffer,
+ ssl->buffers.key->length, ssl->heap,
+ ssl->buffers.keyDevId);
+ if (ret == 0) {
+ if (ssl->buffers.keySz < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ECC key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz);
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
}
+ goto exit_dpk;
}
+#endif
- /* Add record header to previsouly added packet info */
- void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
- {
- /* make sure we have a valid previous one */
- if (info->numberPackets > 0 && info->numberPackets <
- MAX_PACKETS_HANDSHAKE) {
- if (info->packets[info->numberPackets - 1].bufferValue)
- XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
- RECORD_HEADER_SZ);
- else
- XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
- RECORD_HEADER_SZ);
+#ifndef NO_RSA
+ if (ssl->buffers.keyType == rsa_sa_algo || ssl->buffers.keyType == 0) {
+ ssl->hsType = DYNAMIC_TYPE_RSA;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_dpk;
+ }
+
+ WOLFSSL_MSG("Trying RSA private key");
+
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an RSA private key. */
+ ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+ (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+ if (ret == 0) {
+ WOLFSSL_MSG("Using RSA private key");
+
+ /* It worked so check it meets minimum key size requirements. */
+ keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+ if (keySz < 0) { /* check if keySz has error case */
+ ERROR_OUT(keySz, exit_dpk);
+ }
+
+ if (keySz < ssl->options.minRsaKeySz) {
+ WOLFSSL_MSG("RSA key size too small");
+ ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = (word16)keySz;
+
+ goto exit_dpk;
}
}
+#endif /* !NO_RSA */
-#endif /* WOLFSSL_CALLBACKS */
+#ifdef HAVE_ECC
+#ifndef NO_RSA
+ FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+#endif /* !NO_RSA */
+
+ if (ssl->buffers.keyType == ecc_dsa_sa_algo || ssl->buffers.keyType == 0) {
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_dpk;
+ }
+
+ #ifndef NO_RSA
+ WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
+ #else
+ WOLFSSL_MSG("Trying ECC private key");
+ #endif
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an ECC private key. */
+ ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+ (ecc_key*)ssl->hsKey,
+ ssl->buffers.key->length);
+ if (ret == 0) {
+ WOLFSSL_MSG("Using ECC private key");
+
+ /* Check it meets the minimum ECC key size requirements. */
+ keySz = wc_ecc_size((ecc_key*)ssl->hsKey);
+ if (keySz < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ECC key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
+
+ goto exit_dpk;
+ }
+ }
+#endif
+#ifdef HAVE_ED25519
+ #if !defined(NO_RSA) || defined(HAVE_ECC)
+ FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+ #endif
+
+ if (ssl->buffers.keyType == ed25519_sa_algo || ssl->buffers.keyType == 0) {
+ ssl->hsType = DYNAMIC_TYPE_ED25519;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_dpk;
+ }
+
+ #ifdef HAVE_ECC
+ WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work");
+ #elif !defined(NO_RSA)
+ WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work");
+ #else
+ WOLFSSL_MSG("Trying ED25519 private key");
+ #endif
+
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an ED25519 private key. */
+ ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+ (ed25519_key*)ssl->hsKey,
+ ssl->buffers.key->length);
+ if (ret == 0) {
+ WOLFSSL_MSG("Using ED25519 private key");
+
+ /* Check it meets the minimum ECC key size requirements. */
+ if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ED25519 key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = ED25519_SIG_SIZE;
+
+ goto exit_dpk;
+ }
+ }
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ #if !defined(NO_RSA) || defined(HAVE_ECC)
+ FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+ #endif
+
+ if (ssl->buffers.keyType == ed448_sa_algo || ssl->buffers.keyType == 0) {
+ ssl->hsType = DYNAMIC_TYPE_ED448;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_dpk;
+ }
+
+ #ifdef HAVE_ED25519
+ WOLFSSL_MSG("Trying ED448 private key, ED25519 didn't work");
+ #elif defined(HAVE_ECC)
+ WOLFSSL_MSG("Trying ED448 private key, ECC didn't work");
+ #elif !defined(NO_RSA)
+ WOLFSSL_MSG("Trying ED448 private key, RSA didn't work");
+ #else
+ WOLFSSL_MSG("Trying ED447 private key");
+ #endif
+
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an ED448 private key. */
+ ret = wc_Ed448PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+ (ed448_key*)ssl->hsKey,
+ ssl->buffers.key->length);
+ if (ret == 0) {
+ WOLFSSL_MSG("Using ED448 private key");
+
+ /* Check it meets the minimum ECC key size requirements. */
+ if (ED448_KEY_SIZE < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ED448 key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = ED448_SIG_SIZE;
+
+ goto exit_dpk;
+ }
+ }
+#endif /* HAVE_ED448 */
+
+ (void)idx;
+ (void)keySz;
+ (void)length;
+exit_dpk:
+ return ret;
+}
+#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
/* client only parts */
#ifndef NO_WOLFSSL_CLIENT
+#ifndef WOLFSSL_NO_TLS12
+
+ /* handle generation of client_hello (1) */
int SendClientHello(WOLFSSL* ssl)
{
byte *output;
@@ -9113,6 +19534,15 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
? ssl->session.sessionIDSz
: 0;
int ret;
+ word16 extSz = 0;
+
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version))
+ return SendTls13ClientHello(ssl);
+#endif
+
+ WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+ WOLFSSL_ENTER("SendClientHello");
if (ssl->suites == NULL) {
WOLFSSL_MSG("Bad suites pointer in SendClientHello");
@@ -9123,28 +19553,47 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if (ssl->options.resuming && ssl->session.ticketLen > 0) {
SessionTicket* ticket;
- ticket = TLSX_SessionTicket_Create(0,
- ssl->session.ticket, ssl->session.ticketLen);
+ ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket,
+ ssl->session.ticketLen, ssl->heap);
if (ticket == NULL) return MEMORY_E;
- ret = TLSX_UseSessionTicket(&ssl->extensions, ticket);
- if (ret != SSL_SUCCESS) return ret;
+ ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap);
+ if (ret != WOLFSSL_SUCCESS) {
+ TLSX_SessionTicket_Free(ticket, ssl->heap);
+ return ret;
+ }
idSz = 0;
}
#endif
-
length = VERSION_SZ + RAN_LEN
+ idSz + ENUM_LEN
+ ssl->suites->suiteSz + SUITE_LEN
+ COMP_LEN + ENUM_LEN;
#ifdef HAVE_TLS_EXTENSIONS
- length += TLSX_GetRequestSize(ssl);
+ /* auto populate extensions supported unless user defined */
+ if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
+ return ret;
+ #ifdef HAVE_QSH
+ if (QSH_Init(ssl) != 0)
+ return MEMORY_E;
+ #endif
+ extSz = 0;
+ ret = TLSX_GetRequestSize(ssl, client_hello, &extSz);
+ if (ret != 0)
+ return ret;
+ length += extSz;
#else
- if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
- length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ;
- }
+ if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
+ extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
+ + ssl->suites->hashSigAlgoSz;
+#ifdef HAVE_EXTENDED_MASTER
+ if (ssl->options.haveEMS)
+ extSz += HELLO_EXT_SZ;
+#endif
+ if (extSz != 0)
+ length += extSz + HELLO_EXT_SZ_SZ;
#endif
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
@@ -9157,41 +19606,41 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
#endif
- if (ssl->keys.encryptionOn)
+ if (IsEncryptionOn(ssl, 1))
sendSz += MAX_MSG_EXTRA;
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, length, client_hello, ssl);
- /* client hello, first version */
+ /* client hello, first version */
output[idx++] = ssl->version.major;
output[idx++] = ssl->version.minor;
ssl->chVersion = ssl->version; /* store in case changed */
- /* then random */
+ /* then random */
if (ssl->options.connectState == CONNECT_BEGIN) {
ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
if (ret != 0)
return ret;
- /* store random */
+ /* store random */
XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
} else {
#ifdef WOLFSSL_DTLS
- /* send same random on hello again */
+ /* send same random on hello again */
XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
#endif
}
idx += RAN_LEN;
- /* then session id */
+ /* then session id */
output[idx++] = (byte)idSz;
if (idSz) {
XMEMCPY(output + idx, ssl->session.sessionID,
@@ -9199,7 +19648,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
idx += ssl->session.sessionIDSz;
}
- /* then DTLS cookie */
+ /* then DTLS cookie */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
byte cookieSz = ssl->arrays->cookieSz;
@@ -9211,13 +19660,13 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
}
#endif
- /* then cipher suites */
+ /* then cipher suites */
c16toa(ssl->suites->suiteSz, output + idx);
- idx += 2;
+ idx += OPAQUE16_LEN;
XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
idx += ssl->suites->suiteSz;
- /* last, compression */
+ /* last, compression */
output[idx++] = COMP_LEN;
if (ssl->options.usingCompression)
output[idx++] = ZLIB_COMPRESSION;
@@ -9225,71 +19674,102 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
output[idx++] = NO_COMPRESSION;
#ifdef HAVE_TLS_EXTENSIONS
- idx += TLSX_WriteRequest(ssl, output + idx);
+ extSz = 0;
+ ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz);
+ if (ret != 0)
+ return ret;
+ idx += extSz;
(void)idx; /* suppress analyzer warning, keep idx current */
#else
- if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
- {
- int i;
- /* add in the extensions length */
- c16toa(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz, output + idx);
- idx += 2;
+ if (extSz != 0) {
+ c16toa(extSz, output + idx);
+ idx += HELLO_EXT_SZ_SZ;
- c16toa(HELLO_EXT_SIG_ALGO, output + idx);
- idx += 2;
- c16toa(HELLO_EXT_SIGALGO_SZ+ssl->suites->hashSigAlgoSz, output+idx);
- idx += 2;
- c16toa(ssl->suites->hashSigAlgoSz, output + idx);
- idx += 2;
- for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
- output[idx] = ssl->suites->hashSigAlgo[i];
+ if (IsAtLeastTLSv1_2(ssl)) {
+ if (ssl->suites->hashSigAlgoSz) {
+ word16 i;
+ /* extension type */
+ c16toa(HELLO_EXT_SIG_ALGO, output + idx);
+ idx += HELLO_EXT_TYPE_SZ;
+ /* extension data length */
+ c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz,
+ output + idx);
+ idx += HELLO_EXT_SZ_SZ;
+ /* sig algos length */
+ c16toa(ssl->suites->hashSigAlgoSz, output + idx);
+ idx += HELLO_EXT_SIGALGO_SZ;
+ for (i=0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
+ output[idx] = ssl->suites->hashSigAlgo[i];
+ }
+ }
}
+#ifdef HAVE_EXTENDED_MASTER
+ if (ssl->options.haveEMS) {
+ c16toa(HELLO_EXT_EXTMS, output + idx);
+ idx += HELLO_EXT_TYPE_SZ;
+ c16toa(0, output + idx);
+ idx += HELLO_EXT_SZ_SZ;
+ }
+#endif
}
#endif
- if (ssl->keys.encryptionOn) {
+ if (IsEncryptionOn(ssl, 1)) {
byte* input;
int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
if (input == NULL)
return MEMORY_E;
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
- sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
if (sendSz < 0)
return sendSz;
} else {
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+ return ret;
+ }
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
}
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- }
- #endif
-
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+#ifdef OPENSSL_EXTRA
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
-#ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
if (ssl->toInfoOn)
- AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
+ AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendClientHello", ret);
+ WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
+
+ return ret;
}
+ /* handle processing of DTLS hello_verify_request (3) */
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size)
{
@@ -9298,23 +19778,26 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
word32 begin = *inOutIdx;
#ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
- &ssl->handShakeInfo);
+ if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest");
if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
#endif
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
- DtlsPoolReset(ssl);
+ DtlsMsgPoolReset(ssl);
}
#endif
- if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size)
+ if (OPAQUE16_LEN + OPAQUE8_LEN > size)
return BUFFER_ERROR;
XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN);
*inOutIdx += OPAQUE16_LEN;
+ if (pv.major != DTLS_MAJOR ||
+ (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR))
+ return VERSION_ERROR;
+
cookieSz = input[(*inOutIdx)++];
if (cookieSz) {
@@ -9335,7 +19818,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
- static INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
+ static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
{
int ret = 0;
@@ -9347,7 +19830,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
#ifdef HAVE_SESSION_TICKET
/* server may send blank ticket which may not be expected to indicate
- * exisiting one ok but will also be sending a new one */
+ * existing one ok but will also be sending a new one */
ret = ret || (ssl->session.ticketLen > 0);
#endif
@@ -9358,42 +19841,42 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
return ret;
}
- static int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
- word32 helloSz)
+ /* 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 cs0; /* cipher suite bytes 0, 1 */
- byte cs1;
- ProtocolVersion pv;
- byte compression;
- word32 i = *inOutIdx;
- word32 begin = i;
-
-#ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
-#endif
-
- /* protocol version, random and session id length check */
- if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
- return BUFFER_ERROR;
+ #ifdef WOLFSSL_TLS13_DRAFT
+ if (pv.major == TLS_DRAFT_MAJOR) {
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_3_MINOR;
+ }
+ #endif
- /* protocol version */
- XMEMCPY(&pv, input + i, OPAQUE16_LEN);
- i += OPAQUE16_LEN;
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS);
+ }
+ #endif
if (pv.minor > ssl->version.minor) {
WOLFSSL_MSG("Server using higher version, fatal error");
return VERSION_ERROR;
}
- else if (pv.minor < ssl->version.minor) {
+ if (pv.minor < ssl->version.minor) {
WOLFSSL_MSG("server using lower version");
+ /* Check for downgrade attack. */
if (!ssl->options.downgrade) {
- WOLFSSL_MSG(" no downgrade allowed, fatal error");
+ WOLFSSL_MSG("\tno downgrade allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
- WOLFSSL_MSG(" version below minimum allowed, fatal error");
+ WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
return VERSION_ERROR;
}
@@ -9406,24 +19889,107 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
#endif
+ /* Checks made - OK to downgrade. */
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
- WOLFSSL_MSG(" downgrading to SSLv3");
+ WOLFSSL_MSG("\tdowngrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
/* turn off tls 1.1+ */
- WOLFSSL_MSG(" downgrading to TLSv1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1");
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
- WOLFSSL_MSG(" downgrading to TLSv1.1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
+ else if (pv.minor == TLSv1_2_MINOR) {
+ WOLFSSL_MSG(" downgrading to TLSv1.2");
+ ssl->version.minor = TLSv1_2_MINOR;
+ }
+ }
+
+#ifdef OPENSSL_EXTRA
+ /* 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 &&
+ ssl->options.mask > 0) {
+ if (ssl->version.minor == TLSv1_2_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+ WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+ ssl->version.minor = TLSv1_1_MINOR;
+ }
+ if (ssl->version.minor == TLSv1_1_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+ WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = TLSv1_MINOR;
+ }
+ if (ssl->version.minor == TLSv1_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_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 == SSLv3_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+ WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+ return VERSION_ERROR;
+ }
+
+ if (ssl->version.minor < ssl->options.minDowngrade) {
+ WOLFSSL_MSG("\tversion below minimum allowed, fatal 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");
+
+#ifdef WOLFSSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
+ if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+
+ /* protocol version, random and session id length check */
+ if (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)
+ return ret;
+
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(pv)) {
+ byte type = server_hello;
+ return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
}
+#endif
/* random */
XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
@@ -9470,6 +20036,29 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
ssl->options.cipherSuite = cs1;
compression = input[i++];
+#ifndef WOLFSSL_NO_STRICT_CIPHER_SUITE
+ {
+ word32 idx, found = 0;
+ /* confirm server_hello cipher suite is one sent in client_hello */
+ for (idx = 0; idx < ssl->suites->suiteSz; idx += 2) {
+ if (ssl->suites->suites[idx] == cs0 &&
+ ssl->suites->suites[idx+1] == cs1) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ WOLFSSL_MSG("ServerHello did not use cipher suite from ClientHello");
+ return MATCH_SUITE_ERROR;
+ }
+ }
+#endif /* !WOLFSSL_NO_STRICT_CIPHER_SUITE */
+
+ if (compression != NO_COMPRESSION && !ssl->options.usingCompression) {
+ WOLFSSL_MSG("Server forcing compression w/o support");
+ return COMPRESSION_ERROR;
+ }
+
if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
WOLFSSL_MSG("Server refused compression, turning off");
ssl->options.usingCompression = 0; /* turn off if server refused */
@@ -9477,11 +20066,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
*inOutIdx = i;
- /* tls extensions */
- if ( (i - begin) < helloSz) {
#ifdef HAVE_TLS_EXTENSIONS
+ if ( (i - begin) < helloSz) {
if (TLSX_SupportExtensions(ssl)) {
- int ret = 0;
word16 totalExtSz;
if ((i - begin) + OPAQUE16_LEN > helloSz)
@@ -9493,27 +20080,94 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if ((i - begin) + totalExtSz > helloSz)
return BUFFER_ERROR;
- if ((ret = TLSX_Parse(ssl, (byte *) input + i,
- totalExtSz, 0, NULL)))
+ if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
+ server_hello, NULL)))
return ret;
i += totalExtSz;
*inOutIdx = i;
}
else
-#endif
*inOutIdx = begin + helloSz; /* skip extensions */
}
+ else
+ ssl->options.haveEMS = 0; /* If no extensions, no EMS */
+#else
+ {
+ int allowExt = 0;
+ byte pendingEMS = 0;
+
+ if ( (i - begin) < helloSz) {
+ if (ssl->version.major == SSLv3_MAJOR &&
+ ssl->version.minor >= TLSv1_MINOR) {
+
+ allowExt = 1;
+ }
+#ifdef WOLFSSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR)
+ allowExt = 1;
+#endif
+
+ 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 (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
+ return BUFFER_ERROR;
+
+ ato16(&input[i], &extId);
+ i += OPAQUE16_LEN;
+ ato16(&input[i], &extSz);
+ i += OPAQUE16_LEN;
+
+ if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
+ return BUFFER_ERROR;
+
+ if (extId == 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
ssl->options.serverState = SERVER_HELLO_COMPLETE;
- if (ssl->keys.encryptionOn) {
+ 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
}
#ifdef HAVE_SECRET_CALLBACK
if (ssl->sessionSecretCb != NULL) {
- int secretSz = SECRET_LEN, ret;
+ int secretSz = SECRET_LEN;
ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
&secretSz, ssl->sessionSecretCtx);
if (ret != 0 || secretSz != SECRET_LEN)
@@ -9521,23 +20175,89 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
}
#endif /* HAVE_SECRET_CALLBACK */
- if (ssl->options.resuming) {
+ ret = CompleteServerHello(ssl);
+
+ WOLFSSL_LEAVE("DoServerHello", ret);
+ WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+ return ret;
+ }
+
+#ifdef WOLFSSL_TLS13
+ /* returns 1 if able to do TLS 1.3 otherwise 0 */
+ static int TLSv1_3_Capable(WOLFSSL* ssl)
+ {
+ #ifndef WOLFSSL_TLS13
+ return 0;
+ #else
+ int ret = 0;
+
+ if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
+ ret = 1;
+ }
+
+ #ifdef OPENSSL_EXTRA
+ if ((wolfSSL_get_options(ssl) & SSL_OP_NO_TLSv1_3)) {
+ /* option set at run time to disable TLS 1.3 */
+ ret = 0;
+ }
+ #endif
+ return ret;
+ #endif
+ }
+#endif /* WOLFSSL_TLS13 */
+
+ int CompleteServerHello(WOLFSSL* ssl)
+ {
+ int ret;
+
+ 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
+ * demands it.
+ */
+ if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+ (vers == 0 || vers == 1)) {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ return VERSION_ERROR;
+ }
+ }
+ else
+ #endif
+ if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+ ssl->ctx->method->version.minor == TLSv1_2_MINOR) {
+ /* TLS v1.2 capable client not allowed to downgrade when
+ * connecting to TLS v1.2 capable server.
+ */
+ if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+ vers == 0) {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ return VERSION_ERROR;
+ }
+ }
+ }
+ else {
if (DSH_CheckSessionId(ssl)) {
if (SetCipherSpecs(ssl) == 0) {
- int ret = -1;
XMEMCPY(ssl->arrays->masterSecret,
ssl->session.masterSecret, SECRET_LEN);
- #ifdef NO_OLD_TLS
+ #ifdef NO_OLD_TLS
+ ret = DeriveTlsKeys(ssl);
+ #else
+ ret = -1; /* default value */
+ #ifndef NO_TLS
+ if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
- #else
- #ifndef NO_TLS
- if (ssl->options.tls)
- ret = DeriveTlsKeys(ssl);
- #endif
- if (!ssl->options.tls)
- ret = DeriveKeys(ssl);
- #endif
+ #endif
+ if (!ssl->options.tls)
+ ret = DeriveKeys(ssl);
+ #endif /* NO_OLD_TLS */
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
return ret;
@@ -9552,15 +20272,17 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
ssl->options.resuming = 0; /* server denied resumption try */
}
}
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- DtlsPoolReset(ssl);
- }
- #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ DtlsMsgPoolReset(ssl);
+ }
+ #endif
return SetCipherSpecs(ssl);
}
+#endif /* WOLFSSL_NO_TLS12 */
+
/* Make sure client setup is valid for this suite, true on success */
int VerifyClientSuite(WOLFSSL* ssl)
@@ -9586,23 +20308,32 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
return 1; /* success */
}
+#ifndef WOLFSSL_NO_TLS12
#ifndef NO_CERTS
- /* just read in and ignore for now TODO: */
+ /* handle processing of certificate_request (13) */
static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*
inOutIdx, word32 size)
{
word16 len;
word32 begin = *inOutIdx;
+ #ifdef OPENSSL_EXTRA
+ int ret;
+ WOLFSSL_X509* x509 = NULL;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ #endif
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
+ WOLFSSL_ENTER("DoCertificateRequest");
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
- AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ AddPacketName(ssl, "CertificateRequest");
if (ssl->toInfoOn)
AddLateName("CertificateRequest", &ssl->timeoutInfo);
#endif
- if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
+ if (OPAQUE8_LEN > size)
return BUFFER_ERROR;
len = input[(*inOutIdx)++];
@@ -9624,8 +20355,25 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
if ((*inOutIdx - begin) + len > size)
return BUFFER_ERROR;
- PickHashSigAlgo(ssl, input + *inOutIdx, len);
+ if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 &&
+ ssl->buffers.certificate &&
+ ssl->buffers.certificate->buffer) {
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+ WOLFSSL_MSG("Using PK for client private key");
+ return INVALID_PARAMETER;
+ }
+ #endif
+ if (ssl->buffers.key && ssl->buffers.key->buffer) {
+ return INVALID_PARAMETER;
+ }
+ }
*inOutIdx += len;
+ #ifdef WC_RSA_PSS
+ ssl->pssAlgo = 0;
+ if (ssl->suites->sigAlgo == rsa_pss_sa_algo)
+ ssl->pssAlgo |= 1 << ssl->suites->hashAlgo;
+ #endif
}
/* authorities */
@@ -9654,1667 +20402,3589 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
len -= OPAQUE16_LEN + dnSz;
}
+ #ifdef OPENSSL_EXTRA
+ /* call client cert callback if no cert has been loaded */
+ if ((ssl->ctx->CBClientCert != NULL) &&
+ (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)) {
+
+ ret = ssl->ctx->CBClientCert(ssl, &x509, &pkey);
+ if (ret == 1) {
+ if ((wolfSSL_use_certificate(ssl, x509) != WOLFSSL_SUCCESS) ||
+ (wolfSSL_use_PrivateKey(ssl, pkey) != WOLFSSL_SUCCESS)) {
+ return CLIENT_CERT_CB_ERROR;
+ }
+ wolfSSL_X509_free(x509);
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ } else if (ret < 0) {
+ return WOLFSSL_ERROR_WANT_X509_LOOKUP;
+ }
+ }
+ #endif
+
/* don't send client cert or cert verify if user hasn't provided
cert and private key */
- if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
- ssl->options.sendVerify = SEND_CERT;
+ if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) {
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+ WOLFSSL_MSG("Using PK for client private key");
+ ssl->options.sendVerify = SEND_CERT;
+ }
+ #endif
+ if (ssl->buffers.key && ssl->buffers.key->buffer) {
+ ssl->options.sendVerify = SEND_CERT;
+ }
+ }
+ #ifdef OPENSSL_EXTRA
+ else
+ #else
else if (IsTLS(ssl))
+ #endif
+ {
ssl->options.sendVerify = SEND_BLANK_CERT;
+ }
- if (ssl->keys.encryptionOn)
+ 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
+ }
+
+ WOLFSSL_LEAVE("DoCertificateRequest", 0);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
return 0;
}
#endif /* !NO_CERTS */
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- static int CheckCurveId(int oid)
+ static int CheckCurveId(int tlsCurveId)
{
- int ret = 0;
+ int ret = ECC_CURVE_ERROR;
+
+ switch (tlsCurveId) {
+ #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_SECPR2
+ case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID;
+ #endif /* HAVE_ECC_SECPR2 */
+ #ifdef HAVE_ECC_KOBLITZ
+ case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_ECC_X25519: return ECC_X25519_OID;
+ #endif
+ #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #ifdef HAVE_ECC_BRAINPOOL
+ case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #ifdef HAVE_CURVE448
+ case WOLFSSL_ECC_X448: return ECC_X448_OID;
+ #endif
+ #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_BRAINPOOL
+ case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+ #ifdef HAVE_ECC_BRAINPOOL
+ case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID;
+ #endif /* !NO_ECC_SECP */
+ #endif
+ }
- switch (oid) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case WOLFSSL_ECC_SECP160R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case WOLFSSL_ECC_SECP192R1:
+ return ret;
+ }
+
+#endif /* HAVE_ECC */
+
+/* Persistable DoServerKeyExchange arguments */
+typedef struct DskeArgs {
+ byte* output; /* not allocated */
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
+ byte* verifySig;
#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case WOLFSSL_ECC_SECP224R1:
+ word32 idx;
+ word32 begin;
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
+ word16 verifySigSz;
#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case WOLFSSL_ECC_SECP256R1:
+ word16 sigSz;
+ byte sigAlgo;
+ byte hashAlgo;
+#if !defined(NO_RSA) && defined(WC_RSA_PSS)
+ int bits;
#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case WOLFSSL_ECC_SECP384R1:
+} DskeArgs;
+
+static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs)
+{
+ DskeArgs* args = (DskeArgs*)pArgs;
+
+ (void)ssl;
+ (void)args;
+
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
+ if (args->verifySig) {
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
+ }
#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case WOLFSSL_ECC_SECP521R1:
+}
+
+#ifndef NO_DH
+static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size,
+ DskeArgs* args)
+{
+ int ret = 0;
+ word16 length;
+#ifdef HAVE_FFDHE
+ const DhParams* params = NULL;
+ int group = 0;
#endif
- break;
- default:
- ret = -1;
- }
+ ssl->buffers.weOwnDH = 1;
- return ret;
+ ssl->buffers.serverDH_P.buffer = NULL;
+ ssl->buffers.serverDH_G.buffer = NULL;
+ ssl->buffers.serverDH_Pub.buffer = NULL;
+
+ /* p */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
}
-#endif /* HAVE_ECC */
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
- word32* inOutIdx, word32 size)
- {
- word16 length = 0;
- word32 begin = *inOutIdx;
- int ret = 0;
- #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0)
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+ }
- (void)length; /* shut up compiler warnings */
- (void)begin;
- (void)ssl;
- (void)input;
- (void)size;
- (void)ret;
+ if (length < ssl->options.minDhKeySz) {
+ WOLFSSL_MSG("Server using a DH key that is too small");
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk);
+ }
+ if (length > ssl->options.maxDhKeySz) {
+ WOLFSSL_MSG("Server using a DH key that is too big");
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk);
+ }
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
- #endif
+ ssl->buffers.serverDH_P.buffer =
+ (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ssl->buffers.serverDH_P.buffer) {
+ ssl->buffers.serverDH_P.length = length;
+ }
+ else {
+ ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+ }
- #ifndef NO_PSK
- if (ssl->specs.kea == psk_kea) {
+ XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
+ length);
+ args->idx += length;
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ ssl->options.dhKeySz = length;
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ /* g */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx,
- min(length, MAX_PSK_ID_LEN));
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+ }
- ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0;
- *inOutIdx += length;
+ ssl->buffers.serverDH_G.buffer =
+ (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ssl->buffers.serverDH_G.buffer) {
+ ssl->buffers.serverDH_G.length = length;
+ }
+ else {
+ ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+ }
- return 0;
- }
- #endif
- #ifndef NO_DH
- if (ssl->specs.kea == diffie_hellman_kea)
- {
- /* p */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
+ length);
+ args->idx += length;
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ /* pub */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- if (length < ssl->options.minDhKeySz) {
- WOLFSSL_MSG("Server using a DH key that is too small");
- SendAlert(ssl, alert_fatal, handshake_failure);
- return DH_KEY_SIZE_E;
- }
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+ }
- ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ ssl->buffers.serverDH_Pub.buffer =
+ (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ssl->buffers.serverDH_Pub.buffer) {
+ ssl->buffers.serverDH_Pub.length = length;
+ }
+ else {
+ ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+ }
- if (ssl->buffers.serverDH_P.buffer)
- ssl->buffers.serverDH_P.length = length;
- else
- return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
+ length);
+ args->idx += length;
- XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
+#ifdef HAVE_FFDHE
+ switch (ssl->options.dhKeySz) {
+ #ifdef HAVE_FFDHE_2048
+ case 2048/8:
+ params = wc_Dh_ffdhe2048_Get();
+ group = WOLFSSL_FFDHE_2048;
+ break;
+ #endif
+ #ifdef HAVE_FFDHE_3072
+ case 3072/8:
+ params = wc_Dh_ffdhe3072_Get();
+ group = WOLFSSL_FFDHE_3072;
+ break;
+ #endif
+ #ifdef HAVE_FFDHE_4096
+ case 4096/8:
+ params = wc_Dh_ffdhe4096_Get();
+ group = WOLFSSL_FFDHE_4096;
+ break;
+ #endif
+ #ifdef HAVE_FFDHE_6144
+ case 6144/8:
+ params = wc_Dh_ffdhe6144_Get();
+ group = WOLFSSL_FFDHE_6144;
+ break;
+ #endif
+ #ifdef HAVE_FFDHE_8192
+ case 8192/8:
+ params = wc_Dh_ffdhe8192_Get();
+ group = WOLFSSL_FFDHE_8192;
+ break;
+ #endif
+ default:
+ break;
+ }
- ssl->options.dhKeySz = length;
+ if (params == NULL || params->g_len != ssl->buffers.serverDH_G.length ||
+ (XMEMCMP(ssl->buffers.serverDH_G.buffer, params->g,
+ params->g_len) != 0) ||
+ (XMEMCMP(ssl->buffers.serverDH_P.buffer, params->p,
+ params->p_len) != 0)) {
+ WOLFSSL_MSG("Server not using FFDHE parameters");
+ #ifdef WOLFSSL_REQUIRE_FFDHE
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ ERROR_OUT(DH_PARAMS_NOT_FFDHE_E, exit_gdpk);
+ #endif
+ }
+ else {
+ ssl->namedGroup = group;
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ ssl->options.dhDoKeyTest = 0;
+ #endif
+ }
+#endif /* HAVE_FFDHE */
- /* g */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+exit_gdpk:
+ return ret;
+}
+#endif
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+/* handle processing of server_key_exchange (12) */
+static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
+ word32* inOutIdx, word32 size)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ DskeArgs* args = (DskeArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+#else
+ DskeArgs args[1];
+#endif
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ (void)input;
+ (void)size;
- ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
+ WOLFSSL_ENTER("DoServerKeyExchange");
- if (ssl->buffers.serverDH_G.buffer)
- ssl->buffers.serverDH_G.length = length;
- else
- return MEMORY_ERROR;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_dske;
+ }
+ else
+#endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(DskeArgs));
+ args->idx = *inOutIdx;
+ args->begin = *inOutIdx;
+ args->sigAlgo = ssl->specs.sig_algo;
+ args->hashAlgo = sha_mac;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeDskeArgs;
+ #endif
+ }
- XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ #ifdef WOLFSSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "ServerKeyExchange");
+ if (ssl->toInfoOn)
+ AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
+ #endif
- /* pub */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ int srvHintLen;
+ word16 length;
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- if (ssl->buffers.serverDH_Pub.buffer)
- ssl->buffers.serverDH_Pub.length = length;
- else
- return MEMORY_ERROR;
+ /* get PSK server hint from the wire */
+ srvHintLen = 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 */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ ret = GetDhPublicKey(ssl, input, size, args);
+ if (ret != 0)
+ goto exit_dske;
+ break;
+ }
+ #endif /* !NO_DH */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ byte b;
+ #ifdef HAVE_ECC
+ int curveId;
+ #endif
+ int curveOid;
+ word16 length;
- XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
- } /* dh_kea */
- #endif /* NO_DH */
+ if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+ OPAQUE8_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- #ifdef HAVE_ECC
- if (ssl->specs.kea == ecc_diffie_hellman_kea)
- {
- byte b;
+ b = input[args->idx++];
+ if (b != named_curve) {
+ ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+ }
- if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size)
- return BUFFER_ERROR;
+ args->idx += 1; /* curve type, eat leading 0 */
+ b = input[args->idx++];
+ if ((curveOid = CheckCurveId(b)) < 0) {
+ ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+ }
+ ssl->ecdhCurveOID = curveOid;
+ #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
+ #endif
+
+ length = input[args->idx++];
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- b = input[(*inOutIdx)++];
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (ssl->peerX25519Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerX25519KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- if (b != named_curve)
- return ECC_CURVETYPE_ERROR;
+ if ((ret = wc_curve25519_check_public(
+ input + args->idx, length,
+ EC25519_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- *inOutIdx += 1; /* curve type, eat leading 0 */
- b = input[(*inOutIdx)++];
+ if (wc_curve25519_import_public_ex(input + args->idx,
+ length, ssl->peerX25519Key,
+ EC25519_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- if (CheckCurveId(b) != 0) {
- return ECC_CURVE_ERROR;
- }
+ args->idx += length;
+ ssl->peerX25519KeyPresent = 1;
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (ssl->peerX448Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerX448KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+ ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- length = input[(*inOutIdx)++];
+ if ((ret = wc_curve448_check_public(
+ input + args->idx, length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if (wc_curve448_import_public_ex(input + args->idx,
+ length, ssl->peerX448Key,
+ EC448_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- if (ssl->peerEccKey == NULL) {
- /* alloc/init on demand */
- ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
- ssl->ctx->heap, DYNAMIC_TYPE_ECC);
- if (ssl->peerEccKey == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_E;
- }
- wc_ecc_init(ssl->peerEccKey);
- } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- wc_ecc_init(ssl->peerEccKey);
- }
+ args->idx += length;
+ ssl->peerX448KeyPresent = 1;
+ break;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ if (ssl->peerEccKey == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey) != 0)
- return ECC_PEERKEY_ERROR;
+ curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+ if (wc_ecc_import_x963_ex(input + args->idx, length,
+ ssl->peerEccKey, curveId) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- *inOutIdx += length;
- ssl->peerEccKeyPresent = 1;
- }
- #endif /* HAVE_ECC */
+ args->idx += length;
+ ssl->peerEccKeyPresent = 1;
+ #endif
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ int srvHintLen;
+ word16 length;
- #if !defined(NO_DH) && !defined(NO_PSK)
- if (ssl->specs.kea == dhe_psk_kea) {
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx,
- min(length, MAX_PSK_ID_LEN));
+ /* get PSK server hint from the wire */
+ srvHintLen = 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;
- ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0;
- *inOutIdx += length;
+ ret = GetDhPublicKey(ssl, input, size, args);
+ if (ret != 0)
+ goto exit_dske;
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ byte b;
+ int curveOid, curveId;
+ int srvHintLen;
+ word16 length;
- /* p */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- if (length < ssl->options.minDhKeySz) {
- WOLFSSL_MSG("Server using a DH key that is too small");
- SendAlert(ssl, alert_fatal, handshake_failure);
- return DH_KEY_SIZE_E;
- }
+ /* get PSK server hint from the wire */
+ srvHintLen = min(length, MAX_PSK_ID_LEN);
+ XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+ srvHintLen);
+ ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
- ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ args->idx += length;
- if (ssl->buffers.serverDH_P.buffer)
- ssl->buffers.serverDH_P.length = length;
- else
- return MEMORY_ERROR;
+ if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+ OPAQUE8_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
+ /* Check curve name and ID */
+ b = input[args->idx++];
+ if (b != named_curve) {
+ ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+ }
- ssl->options.dhKeySz = length;
+ args->idx += 1; /* curve type, eat leading 0 */
+ b = input[args->idx++];
+ if ((curveOid = CheckCurveId(b)) < 0) {
+ ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+ }
- /* g */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ length = input[args->idx++];
+ if ((args->idx - args->begin) + length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (ssl->peerX25519Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if ((ret = wc_curve25519_check_public(
+ input + args->idx, length,
+ EC25519_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ if (wc_curve25519_import_public_ex(input + args->idx,
+ length, ssl->peerX25519Key,
+ EC25519_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- if (ssl->buffers.serverDH_G.buffer)
- ssl->buffers.serverDH_G.length = length;
- else
- return MEMORY_ERROR;
+ args->idx += length;
+ ssl->peerX25519KeyPresent = 1;
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (ssl->peerX448Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+ ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
+ if ((ret = wc_curve448_check_public(
+ input + args->idx, length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- /* pub */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ if (wc_curve448_import_public_ex(input + args->idx,
+ length, ssl->peerX448Key,
+ EC448_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ args->idx += length;
+ ssl->peerX448KeyPresent = 1;
+ break;
+ }
+ #endif
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if (ssl->peerEccKey == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ } else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
- ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
+ curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+ if (wc_ecc_import_x963_ex(input + args->idx, length,
+ ssl->peerEccKey, curveId) != 0) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+ }
- if (ssl->buffers.serverDH_Pub.buffer)
- ssl->buffers.serverDH_Pub.length = length;
- else
- return MEMORY_ERROR;
+ args->idx += length;
+ ssl->peerEccKeyPresent = 1;
+ break;
+ }
+ #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch(ssl->specs.kea) */
- XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length);
- *inOutIdx += length;
- }
- #endif /* !NO_DH || !NO_PSK */
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dske;
+ }
- #if !defined(NO_DH) || defined(HAVE_ECC)
- if (!ssl->options.usingAnon_cipher &&
- (ssl->specs.kea == ecc_diffie_hellman_kea ||
- ssl->specs.kea == diffie_hellman_kea))
- {
-#ifndef NO_OLD_TLS
-#ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = NULL;
- Sha* sha = NULL;
-#else
- Md5 md5[1];
- Sha sha[1];
-#endif
-#endif
-#ifndef NO_SHA256
-#ifdef WOLFSSL_SMALL_STACK
- Sha256* sha256 = NULL;
- byte* hash256 = NULL;
-#else
- Sha256 sha256[1];
- byte hash256[SHA256_DIGEST_SIZE];
-#endif
-#endif
-#ifdef WOLFSSL_SHA384
-#ifdef WOLFSSL_SMALL_STACK
- Sha384* sha384 = NULL;
- byte* hash384 = NULL;
-#else
- Sha384 sha384[1];
- byte hash384[SHA384_DIGEST_SIZE];
-#endif
-#endif
-#ifdef WOLFSSL_SHA512
-#ifdef WOLFSSL_SMALL_STACK
- Sha512* sha512 = NULL;
- byte* hash512 = NULL;
-#else
- Sha512 sha512[1];
- byte hash512[SHA512_DIGEST_SIZE];
-#endif
-#endif
-#ifdef WOLFSSL_SMALL_STACK
- byte* hash = NULL;
- byte* messageVerify = NULL;
-#else
- byte hash[FINISHED_SZ];
- byte messageVerify[MAX_DH_SZ];
-#endif
- byte hashAlgo = sha_mac;
- byte sigAlgo = ssl->specs.sig_algo;
- word16 verifySz = (word16) (*inOutIdx - begin);
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* case TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
-#ifndef NO_OLD_TLS
- byte doMd5 = 0;
- byte doSha = 0;
-#endif
-#ifndef NO_SHA256
- byte doSha256 = 0;
-#endif
-#ifdef WOLFSSL_SHA384
- byte doSha384 = 0;
-#endif
-#ifdef WOLFSSL_SHA512
- byte doSha512 = 0;
-#endif
+ case TLS_ASYNC_BUILD:
+ {
+ switch(ssl->specs.kea)
+ {
+ case psk_kea:
+ case dhe_psk_kea:
+ case ecdhe_psk_kea:
+ {
+ /* Nothing to do in this sub-state */
+ break;
+ }
- (void)hash;
- (void)sigAlgo;
- (void)hashAlgo;
+ case diffie_hellman_kea:
+ case ecc_diffie_hellman_kea:
+ {
+ #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+ && !defined(HAVE_ED448)
+ ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+ #else
+ enum wc_HashType hashType;
+ word16 verifySz;
- /* save message for hash verify */
- if (verifySz > MAX_DH_SZ)
- ERROR_OUT(BUFFER_ERROR, done);
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
- #ifdef WOLFSSL_SMALL_STACK
- messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (messageVerify == NULL)
- ERROR_OUT(MEMORY_E, done);
- #endif
+ verifySz = (word16)(args->idx - args->begin);
+ if (verifySz > MAX_DH_SZ) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- XMEMCPY(messageVerify, input + begin, verifySz);
+ if (IsAtLeastTLSv1_2(ssl)) {
+ if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN >
+ size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- if (IsAtLeastTLSv1_2(ssl)) {
- byte setHash = 0;
- if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size)
- ERROR_OUT(BUFFER_ERROR, done);
+ DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+ &args->sigAlgo);
+ args->idx += 2;
+ hashType = HashAlgoToType(args->hashAlgo);
+ if (hashType == WC_HASH_TYPE_NONE) {
+ ERROR_OUT(ALGO_ID_E, exit_dske);
+ }
+ } else {
+ /* only using sha and md5 for rsa */
+ #ifndef NO_OLD_TLS
+ hashType = WC_HASH_TYPE_SHA;
+ if (args->sigAlgo == rsa_sa_algo) {
+ hashType = WC_HASH_TYPE_MD5_SHA;
+ }
+ #else
+ ERROR_OUT(ALGO_ID_E, exit_dske);
+ #endif
+ }
- hashAlgo = input[(*inOutIdx)++];
- sigAlgo = input[(*inOutIdx)++];
+ /* signature */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
- switch (hashAlgo) {
- case sha512_mac:
- #ifdef WOLFSSL_SHA512
- doSha512 = 1;
- setHash = 1;
+ ato16(input + args->idx, &args->verifySigSz);
+ args->idx += OPAQUE16_LEN;
+
+ if ((args->idx - args->begin) + args->verifySigSz > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
+
+ /* buffer for signature */
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dske);
+ }
+ ssl->buffers.sig.length = SEED_LEN + verifySz;
+
+ /* build message to hash */
+ XMEMCPY(ssl->buffers.sig.buffer,
+ ssl->arrays->clientRandom, RAN_LEN);
+ XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN],
+ ssl->arrays->serverRandom, RAN_LEN);
+ XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2],
+ input + args->begin, verifySz); /* message */
+
+ if (args->sigAlgo != ed25519_sa_algo) {
+ int digest_sz = wc_HashGetDigestSize(hashType);
+ if (digest_sz <= 0) {
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
+ ssl->buffers.digest.length = (unsigned int)digest_sz;
+
+ /* buffer for hash */
+ ssl->buffers.digest.buffer = (byte*)XMALLOC(
+ ssl->buffers.digest.length, ssl->heap,
+ DYNAMIC_TYPE_DIGEST);
+ if (ssl->buffers.digest.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dske);
+ }
+
+ /* Perform hash */
+ ret = wc_Hash(hashType, ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length);
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
+
+ switch (args->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
#endif
+ case rsa_sa_algo:
+ {
+ if (ssl->peerRsaKey == NULL ||
+ !ssl->peerRsaKeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_dske);
+ }
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ {
+ if (!ssl->peerEccDsaKeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_dske);
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519)
+ case ed25519_sa_algo:
+ {
+ if (!ssl->peerEd25519KeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_dske);
+ }
+ break;
+ }
+ #endif /* HAVE_ED25519 */
+ #if defined(HAVE_ED448)
+ case ed448_sa_algo:
+ {
+ if (!ssl->peerEd448KeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_dske);
+ }
+ break;
+ }
+ #endif /* HAVE_ED448 */
+
+ default:
+ ret = ALGO_ID_E;
+ } /* switch (args->sigAlgo) */
+
+ #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
break;
+ }
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch(ssl->specs.kea) */
- case sha384_mac:
- #ifdef WOLFSSL_SHA384
- doSha384 = 1;
- setHash = 1;
- #endif
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dske;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_DO:
+ {
+ switch(ssl->specs.kea)
+ {
+ case psk_kea:
+ case dhe_psk_kea:
+ case ecdhe_psk_kea:
+ {
+ /* Nothing to do in this sub-state */
break;
+ }
- case sha256_mac:
- #ifndef NO_SHA256
- doSha256 = 1;
- setHash = 1;
+ case diffie_hellman_kea:
+ case ecc_diffie_hellman_kea:
+ {
+ #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+ && !defined(HAVE_ED448)
+ ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+ #else
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
+
+ if (args->verifySig == NULL) {
+ args->verifySig = (byte*)XMALLOC(args->verifySigSz,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (args->verifySig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dske);
+ }
+ XMEMCPY(args->verifySig, input + args->idx,
+ args->verifySigSz);
+ }
+
+ switch (args->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
#endif
+ case rsa_sa_algo:
+ {
+ ret = RsaVerify(ssl,
+ args->verifySig, args->verifySigSz,
+ &args->output,
+ args->sigAlgo, args->hashAlgo,
+ ssl->peerRsaKey,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerRsaKey
+ #else
+ NULL
+ #endif
+ );
+
+ if (ret >= 0) {
+ args->sigSz = (word16)ret;
+ #ifdef WC_RSA_PSS
+ args->bits = mp_count_bits(&ssl->peerRsaKey->n);
+ #endif
+ ret = 0;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ /* peerRsaKey */
+ FreeKey(ssl, DYNAMIC_TYPE_RSA,
+ (void**)&ssl->peerRsaKey);
+ ssl->peerRsaKeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ {
+ ret = EccVerify(ssl,
+ args->verifySig, args->verifySigSz,
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ ssl->peerEccDsaKey,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEccDsaKey
+ #else
+ NULL
+ #endif
+ );
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ /* peerEccDsaKey */
+ FreeKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccDsaKey);
+ ssl->peerEccDsaKeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519)
+ case ed25519_sa_algo:
+ {
+ ret = Ed25519Verify(ssl,
+ args->verifySig, args->verifySigSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ ssl->peerEd25519Key,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEd25519Key
+ #else
+ NULL
+ #endif
+ );
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ /* peerEccDsaKey */
+ FreeKey(ssl, DYNAMIC_TYPE_ED25519,
+ (void**)&ssl->peerEd25519Key);
+ ssl->peerEd25519KeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* HAVE_ED25519 */
+ #if defined(HAVE_ED448)
+ case ed448_sa_algo:
+ {
+ ret = Ed448Verify(ssl,
+ args->verifySig, args->verifySigSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ ssl->peerEd448Key,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEd448Key
+ #else
+ NULL
+ #endif
+ );
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ /* peerEccDsaKey */
+ FreeKey(ssl, DYNAMIC_TYPE_ED448,
+ (void**)&ssl->peerEd448Key);
+ ssl->peerEd448KeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* HAVE_ED448 */
+
+ default:
+ ret = ALGO_ID_E;
+ } /* switch (sigAlgo) */
+ #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
break;
+ }
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch(ssl->specs.kea) */
- case sha_mac:
- #ifndef NO_OLD_TLS
- doSha = 1;
- setHash = 1;
- #endif
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dske;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_VERIFY:
+ {
+ switch(ssl->specs.kea)
+ {
+ case psk_kea:
+ case dhe_psk_kea:
+ case ecdhe_psk_kea:
+ {
+ /* Nothing to do in this sub-state */
break;
+ }
+ case diffie_hellman_kea:
+ case ecc_diffie_hellman_kea:
+ {
+ #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+ && !defined(HAVE_ED448)
+ ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+ #else
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
+
+ /* increment index after verify is done */
+ args->idx += args->verifySigSz;
+
+ switch(args->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #ifdef HAVE_SELFTEST
+ ret = wc_RsaPSS_CheckPadding(
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ args->output, args->sigSz,
+ HashAlgoToType(args->hashAlgo));
+ #else
+ ret = wc_RsaPSS_CheckPadding_ex(
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ args->output, args->sigSz,
+ HashAlgoToType(args->hashAlgo),
+ -1, args->bits);
+ #endif
+ if (ret != 0)
+ return ret;
+ break;
+ #endif
+ case rsa_sa_algo:
+ {
+ if (IsAtLeastTLSv1_2(ssl)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ byte* encodedSig;
+ #else
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ #endif
+ word32 encSigSz;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dske);
+ }
+ #endif
+
+ encSigSz = wc_EncodeSignature(encodedSig,
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ TypeHash(args->hashAlgo));
+ if (encSigSz != args->sigSz || !args->output ||
+ XMEMCMP(args->output, encodedSig,
+ min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+ ret = VERIFY_SIGN_ERROR;
+ }
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ #endif
+ if (ret != 0) {
+ goto exit_dske;
+ }
+ }
+ else if (args->sigSz != FINISHED_SZ ||
+ !args->output ||
+ XMEMCMP(args->output,
+ ssl->buffers.digest.buffer,
+ FINISHED_SZ) != 0) {
+ ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske);
+ }
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ /* Nothing to do in this algo */
+ break;
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519)
+ case ed25519_sa_algo:
+ /* Nothing to do in this algo */
+ break;
+ #endif /* HAVE_ED25519 */
+ #if defined(HAVE_ED448)
+ case ed448_sa_algo:
+ /* Nothing to do in this algo */
+ break;
+ #endif /* HAVE_ED448 */
+ default:
+ ret = ALGO_ID_E;
+ } /* switch (sigAlgo) */
+ #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
+ break;
+ }
default:
- ERROR_OUT(ALGO_ID_E, done);
+ ret = BAD_KEA_TYPE_E;
+ } /* switch(ssl->specs.kea) */
+
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dske;
}
- if (setHash == 0) {
- ERROR_OUT(ALGO_ID_E, done);
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ 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
}
- } else {
- /* only using sha and md5 for rsa */
- #ifndef NO_OLD_TLS
- doSha = 1;
- if (sigAlgo == rsa_sa_algo) {
- doMd5 = 1;
+ /* QSH extensions */
+ #ifdef HAVE_QSH
+ if (ssl->peerQSHKeyPresent) {
+ word16 name;
+ int qshSz;
+
+ /* extension name */
+ ato16(input + args->idx, &name);
+ args->idx += OPAQUE16_LEN;
+
+ if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+ /* if qshSz is larger than 0 it is the length of
+ buffer used */
+ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx,
+ size, 0)) < 0) {
+ ERROR_OUT(qshSz, exit_dske);
+ }
+ args->idx += qshSz;
}
- #else
- ERROR_OUT(ALGO_ID_E, done);
- #endif
+ else {
+ /* unknown extension sent server ignored handshake */
+ ERROR_OUT(BUFFER_ERROR, exit_dske);
+ }
+ }
+ #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) */
- /* signature */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- ERROR_OUT(BUFFER_ERROR, done);
+exit_dske:
- ato16(input + *inOutIdx, &length);
- *inOutIdx += OPAQUE16_LEN;
+ WOLFSSL_LEAVE("DoServerKeyExchange", ret);
+ WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
- if ((*inOutIdx - begin) + length > size)
- ERROR_OUT(BUFFER_ERROR, done);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E) {
+ /* Mark message as not received so it can process again */
+ ssl->msgsReceived.got_server_key_exchange = 0;
- /* inOutIdx updated at the end of the function */
+ return ret;
+ }
+#endif /* WOLFSSL_ASYNC_CRYPT */
- /* verify signature */
- #ifdef WOLFSSL_SMALL_STACK
- hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (hash == NULL)
- ERROR_OUT(MEMORY_E, done);
- #endif
+ /* Final cleanup */
+ FreeDskeArgs(ssl, args);
+ FreeKeyExchange(ssl);
-#ifndef NO_OLD_TLS
- /* md5 */
- #ifdef WOLFSSL_SMALL_STACK
- if (doMd5) {
- md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5 == NULL)
- ERROR_OUT(MEMORY_E, done);
- }
+ return ret;
+}
+
+
+#ifdef HAVE_QSH
+
+#ifdef HAVE_NTRU
+/* Encrypt a byte array using ntru
+ key a struct containing the public key to use
+ bufIn array to be encrypted
+ inSz size of bufIn array
+ bufOut cipher text out
+ outSz will be set to the new size of cipher text
+ */
+static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz,
+ byte* bufOut, word16* outSz)
+{
+ int ret;
+ DRBG_HANDLE drbg;
+
+ /* sanity checks on input arguments */
+ if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+ return BAD_FUNC_ARG;
+
+ if (key->pub.buffer == NULL)
+ return BAD_FUNC_ARG;
+
+ switch (key->name) {
+ case WOLFSSL_NTRU_EESS439:
+ case WOLFSSL_NTRU_EESS593:
+ case WOLFSSL_NTRU_EESS743:
+ break;
+ default:
+ WOLFSSL_MSG("Unknown QSH encryption key!");
+ return -1;
+ }
+
+ /* set up ntru drbg */
+ ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+ if (ret != DRBG_OK)
+ return NTRU_DRBG_ERROR;
+
+ /* encrypt the byte array */
+ ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer,
+ inSz, bufIn, outSz, bufOut);
+ ntru_crypto_drbg_uninstantiate(drbg);
+ if (ret != NTRU_OK)
+ return NTRU_ENCRYPT_ERROR;
+
+ return ret;
+}
+
+/* Decrypt a byte array using ntru
+ key a struct containing the private key to use
+ bufIn array to be decrypted
+ inSz size of bufIn array
+ bufOut plain text out
+ outSz will be set to the new size of plain text
+ */
+
+static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz,
+ byte* bufOut, word16* outSz)
+{
+ int ret;
+ DRBG_HANDLE drbg;
+
+ /* sanity checks on input arguments */
+ if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+ return BAD_FUNC_ARG;
+
+ if (key->pri.buffer == NULL)
+ return BAD_FUNC_ARG;
+
+ switch (key->name) {
+ case WOLFSSL_NTRU_EESS439:
+ case WOLFSSL_NTRU_EESS593:
+ case WOLFSSL_NTRU_EESS743:
+ break;
+ default:
+ WOLFSSL_MSG("Unknown QSH decryption key!");
+ return -1;
+ }
+
+
+ /* set up drbg */
+ ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+ if (ret != DRBG_OK)
+ return NTRU_DRBG_ERROR;
+
+ /* decrypt cipher text */
+ ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer,
+ inSz, bufIn, outSz, bufOut);
+ ntru_crypto_drbg_uninstantiate(drbg);
+ if (ret != NTRU_OK)
+ return NTRU_ENCRYPT_ERROR;
+
+ return ret;
+}
+#endif /* HAVE_NTRU */
+
+int QSH_Init(WOLFSSL* ssl)
+{
+ /* check so not initializing twice when running DTLS */
+ if (ssl->QSH_secret != NULL)
+ return 0;
+
+ /* malloc memory for holding generated secret information */
+ if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap,
+ DYNAMIC_TYPE_QSH)) == NULL)
+ return MEMORY_E;
+
+ ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+ DYNAMIC_TYPE_SECRET);
+ if (ssl->QSH_secret->CliSi == NULL)
+ return MEMORY_E;
+
+ ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+ DYNAMIC_TYPE_SECRET);
+ if (ssl->QSH_secret->SerSi == NULL)
+ return MEMORY_E;
+
+ /* initialize variables */
+ ssl->QSH_secret->list = NULL;
+ ssl->QSH_secret->CliSi->length = 0;
+ ssl->QSH_secret->CliSi->buffer = NULL;
+ ssl->QSH_secret->SerSi->length = 0;
+ ssl->QSH_secret->SerSi->buffer = NULL;
+
+ return 0;
+}
+
+
+static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn,
+ byte* out, word32* szOut)
+{
+ int ret = 0;
+ word16 size = *szOut;
+
+ (void)in;
+ (void)szIn;
+ (void)out;
+ (void)szOut;
+
+ WOLFSSL_MSG("Encrypting QSH key material");
+
+ switch (key->name) {
+ #ifdef HAVE_NTRU
+ case WOLFSSL_NTRU_EESS439:
+ case WOLFSSL_NTRU_EESS593:
+ case WOLFSSL_NTRU_EESS743:
+ ret = NtruSecretEncrypt(key, in, szIn, out, &size);
+ break;
#endif
- if (doMd5) {
- wc_InitMd5(md5);
- wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
- wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
- wc_Md5Update(md5, messageVerify, verifySz);
- wc_Md5Final(md5, hash);
- }
- /* sha */
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha) {
- sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (sha == NULL)
- ERROR_OUT(MEMORY_E, done);
- }
+ default:
+ WOLFSSL_MSG("Unknown QSH encryption key!");
+ return -1;
+ }
+
+ *szOut = size;
+
+ return ret;
+}
+
+
+/* Decrypt using Quantum Safe Handshake algorithms */
+int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut)
+{
+ int ret = 0;
+ word16 size = *szOut;
+
+ (void)in;
+ (void)szIn;
+ (void)out;
+ (void)szOut;
+
+ WOLFSSL_MSG("Decrypting QSH key material");
+
+ switch (key->name) {
+ #ifdef HAVE_NTRU
+ case WOLFSSL_NTRU_EESS439:
+ case WOLFSSL_NTRU_EESS593:
+ case WOLFSSL_NTRU_EESS743:
+ ret = NtruSecretDecrypt(key, in, szIn, out, &size);
+ break;
#endif
- if (doSha) {
- ret = wc_InitSha(sha);
- if (ret != 0) goto done;
- wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
- wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
- wc_ShaUpdate(sha, messageVerify, verifySz);
- wc_ShaFinal(sha, hash + MD5_DIGEST_SIZE);
- }
+ default:
+ WOLFSSL_MSG("Unknown QSH decryption key!");
+ return -1;
+ }
+
+ *szOut = size;
+
+ return ret;
+}
+
+
+/* Get the max cipher text for corresponding encryption scheme
+ (encrypting 48 or max plain text whichever is smaller)
+ */
+static word32 QSH_MaxSecret(QSHKey* key)
+{
+ int ret = 0;
+#ifdef HAVE_NTRU
+ byte isNtru = 0;
+ word16 inSz = 48;
+ word16 outSz;
+ DRBG_HANDLE drbg = 0;
+ byte bufIn[48];
#endif
-#ifndef NO_SHA256
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha256) {
- sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha256 == NULL || hash256 == NULL)
- ERROR_OUT(MEMORY_E, done);
- }
- #endif
- if (doSha256) {
- if (!(ret = wc_InitSha256(sha256))
- && !(ret = wc_Sha256Update(sha256, ssl->arrays->clientRandom,
- RAN_LEN))
- && !(ret = wc_Sha256Update(sha256, ssl->arrays->serverRandom,
- RAN_LEN))
- && !(ret = wc_Sha256Update(sha256, messageVerify, verifySz)))
- ret = wc_Sha256Final(sha256, hash256);
- if (ret != 0) goto done;
+ if (key == NULL || key->pub.length == 0)
+ return 0;
+
+ switch(key->name) {
+#ifdef HAVE_NTRU
+ case WOLFSSL_NTRU_EESS439:
+ isNtru = 1;
+ break;
+ case WOLFSSL_NTRU_EESS593:
+ isNtru = 1;
+ break;
+ case WOLFSSL_NTRU_EESS743:
+ isNtru = 1;
+ break;
+#endif
+ default:
+ WOLFSSL_MSG("Unknown QSH encryption scheme size!");
+ return 0;
+ }
+
+#ifdef HAVE_NTRU
+ if (isNtru) {
+ ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+ if (ret != DRBG_OK)
+ return NTRU_DRBG_ERROR;
+ ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length,
+ key->pub.buffer, inSz, bufIn, &outSz, NULL);
+ if (ret != NTRU_OK) {
+ return NTRU_ENCRYPT_ERROR;
}
+ ntru_crypto_drbg_uninstantiate(drbg);
+ ret = outSz;
+ }
#endif
-#ifdef WOLFSSL_SHA384
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha384) {
- sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha384 == NULL || hash384 == NULL)
- ERROR_OUT(MEMORY_E, done);
+ return ret;
+}
+
+/* Generate the secret byte material for pms
+ returns length on success and -1 on fail
+ */
+static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer)
+{
+ int sz = 0;
+ int plainSz = 48; /* lesser of 48 and max plain text able to encrypt */
+ int offset = 0;
+ word32 tmpSz = 0;
+ buffer* buf;
+ QSHKey* current;
+ QSHScheme* schmPre = NULL;
+ QSHScheme* schm = NULL;
+
+ if (ssl == NULL)
+ return -1;
+
+ WOLFSSL_MSG("Generating QSH secret key material");
+
+ current = ssl->peerQSHKey;
+ /* get size of buffer needed */
+ while (current) {
+ if (current->pub.length != 0) {
+ sz += plainSz;
}
- #endif
- if (doSha384) {
- if (!(ret = wc_InitSha384(sha384))
- && !(ret = wc_Sha384Update(sha384, ssl->arrays->clientRandom,
- RAN_LEN))
- && !(ret = wc_Sha384Update(sha384, ssl->arrays->serverRandom,
- RAN_LEN))
- && !(ret = wc_Sha384Update(sha384, messageVerify, verifySz)))
- ret = wc_Sha384Final(sha384, hash384);
- if (ret != 0) goto done;
+ current = (QSHKey*)current->next;
+ }
+
+ /* allocate memory for buffer */
+ if (isServer) {
+ buf = ssl->QSH_secret->SerSi;
+ }
+ else {
+ buf = ssl->QSH_secret->CliSi;
+ }
+ buf->length = sz;
+ buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET);
+ if (buf->buffer == NULL) {
+ WOLFSSL_ERROR(MEMORY_E);
+ }
+
+ /* create secret information */
+ sz = 0;
+ current = ssl->peerQSHKey;
+ while (current) {
+ schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap,
+ DYNAMIC_TYPE_QSH);
+ if (schm == NULL)
+ return MEMORY_E;
+
+ /* initialize variables */
+ schm->name = 0;
+ schm->PK = NULL;
+ schm->PKLen = 0;
+ schm->next = NULL;
+ if (ssl->QSH_secret->list == NULL) {
+ ssl->QSH_secret->list = schm;
+ }
+ else {
+ if (schmPre)
+ schmPre->next = schm;
}
-#endif
-#ifdef WOLFSSL_SHA512
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha512) {
- sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha512 == NULL || hash512 == NULL)
- ERROR_OUT(MEMORY_E, done);
+ tmpSz = QSH_MaxSecret(current);
+
+ if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap,
+ DYNAMIC_TYPE_SECRET)) == NULL)
+ return -1;
+
+ /* store info for writing extension */
+ schm->name = current->name;
+
+ /* no key to use for encryption */
+ if (tmpSz == 0) {
+ current = (QSHKey*)current->next;
+ continue;
}
- #endif
- if (doSha512) {
- if (!(ret = wc_InitSha512(sha512))
- && !(ret = wc_Sha512Update(sha512, ssl->arrays->clientRandom,
- RAN_LEN))
- && !(ret = wc_Sha512Update(sha512, ssl->arrays->serverRandom,
- RAN_LEN))
- && !(ret = wc_Sha512Update(sha512, messageVerify, verifySz)))
- ret = wc_Sha512Final(sha512, hash512);
- if (ret != 0) goto done;
+
+ if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz)
+ != 0) {
+ return -1;
}
-#endif
+ if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK,
+ &tmpSz) != 0) {
+ return -1;
+ }
+ schm->PKLen = tmpSz;
-#ifndef NO_RSA
- /* rsa */
- if (sigAlgo == rsa_sa_algo)
- {
- byte* out = NULL;
- byte doUserRsa = 0;
- word32 verifiedSz = 0;
+ sz += tmpSz;
+ offset += plainSz;
+ schmPre = schm;
+ current = (QSHKey*)current->next;
+ }
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaVerifyCb)
- doUserRsa = 1;
- #endif /*HAVE_PK_CALLBACKS */
+ return sz;
+}
- if (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)
- ERROR_OUT(NO_PEER_KEY, done);
- if (doUserRsa) {
- #ifdef HAVE_PK_CALLBACKS
- verifiedSz = ssl->ctx->RsaVerifyCb(ssl,
- (byte *)input + *inOutIdx,
- length, &out,
- ssl->buffers.peerRsaKey.buffer,
- ssl->buffers.peerRsaKey.length,
- ssl->RsaVerifyCtx);
- #endif /*HAVE_PK_CALLBACKS */
- }
- else
- verifiedSz = wc_RsaSSL_VerifyInline((byte *)input + *inOutIdx,
- length, &out, ssl->peerRsaKey);
+static word32 QSH_KeyGetSize(WOLFSSL* ssl)
+{
+ word32 sz = 0;
+ QSHKey* current;
- if (IsAtLeastTLSv1_2(ssl)) {
- word32 encSigSz;
-#ifndef NO_OLD_TLS
- byte* digest = &hash[MD5_DIGEST_SIZE];
- int typeH = SHAh;
- int digestSz = SHA_DIGEST_SIZE;
-#else
- byte* digest = hash256;
- int typeH = SHA256h;
- int digestSz = SHA256_DIGEST_SIZE;
-#endif
-#ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig = NULL;
-#else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
+ if (ssl == NULL)
+ return -1;
- if (hashAlgo == sha_mac) {
- #ifndef NO_SHA
- digest = &hash[MD5_DIGEST_SIZE];
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = hash256;
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = hash384;
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = hash512;
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- #endif
- }
+ current = ssl->peerQSHKey;
+ sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */
+ sz += OPAQUE24_LEN;
+ /* get size of buffer needed */
+ while (current) {
+ sz += OPAQUE16_LEN; /* scheme id */
+ sz += OPAQUE16_LEN; /* encrypted key len*/
+ sz += QSH_MaxSecret(current);
+ current = (QSHKey*)current->next;
+ }
- #ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL)
- ERROR_OUT(MEMORY_E, done);
- #endif
+ return sz;
+}
- if (digest == NULL)
- ERROR_OUT(ALGO_ID_E, done);
- encSigSz = wc_EncodeSignature(encodedSig, digest, digestSz,
- typeH);
- if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig,
- min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0)
- ret = VERIFY_SIGN_ERROR;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- if (ret != 0)
- goto done;
- }
- else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out,
- hash, FINISHED_SZ) != 0)
- ERROR_OUT(VERIFY_SIGN_ERROR, done);
- } else
-#endif
-#ifdef HAVE_ECC
- /* ecdsa */
- if (sigAlgo == ecc_dsa_sa_algo) {
- int verify = 0;
-#ifndef NO_OLD_TLS
- byte* digest = &hash[MD5_DIGEST_SIZE];
- word32 digestSz = SHA_DIGEST_SIZE;
+/* handle QSH key Exchange
+ return 0 on success
+ */
+static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("QSH KeyExchange");
+
+ ret = QSH_GenerateSerCliSecret(ssl, isServer);
+ if (ret < 0)
+ return MEMORY_E;
+
+ return 0;
+}
+
+#endif /* HAVE_QSH */
+
+
+typedef struct SckeArgs {
+ byte* output; /* not allocated */
+ byte* encSecret;
+ byte* input;
+ word32 encSz;
+ word32 length;
+ int sendSz;
+ int inputSz;
+} SckeArgs;
+
+static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
+{
+ SckeArgs* args = (SckeArgs*)pArgs;
+
+ (void)ssl;
+
+ if (args->encSecret) {
+ XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+ args->encSecret = NULL;
+ }
+ if (args->input) {
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
+ }
+}
+
+/* handle generation client_key_exchange (16) */
+int SendClientKeyExchange(WOLFSSL* ssl)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ SckeArgs* args = (SckeArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
#else
- byte* digest = hash256;
- word32 digestSz = SHA256_DIGEST_SIZE;
+ SckeArgs args[1];
#endif
- byte doUserEcc = 0;
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->EccVerifyCb)
- doUserEcc = 1;
+ WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+ WOLFSSL_ENTER("SendClientKeyExchange");
+
+#ifdef OPENSSL_EXTRA
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ ssl->cbmode = SSL_CB_MODE_WRITE;
+ if (ssl->CBIS != NULL)
+ ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_scke;
+ }
+ else
+#endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(SckeArgs));
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeSckeArgs;
+ #endif
+ }
+
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ switch (ssl->specs.kea) {
+ #ifndef NO_RSA
+ case rsa_kea:
+ if (ssl->peerRsaKey == NULL ||
+ ssl->peerRsaKeyPresent == 0) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+ break;
#endif
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ if (ssl->buffers.serverDH_P.buffer == NULL ||
+ ssl->buffers.serverDH_G.buffer == NULL ||
+ ssl->buffers.serverDH_Pub.buffer == NULL) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+ break;
+ #endif /* NO_DH */
+ #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 */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ if (ssl->buffers.serverDH_P.buffer == NULL ||
+ ssl->buffers.serverDH_G.buffer == NULL ||
+ ssl->buffers.serverDH_Pub.buffer == NULL) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
- if (!ssl->peerEccDsaKeyPresent)
- ERROR_OUT(NO_PEER_KEY, done);
+ /* 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_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_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);
+ }
- if (IsAtLeastTLSv1_2(ssl)) {
- if (hashAlgo == sha_mac) {
- #ifndef NO_SHA
- digest = &hash[MD5_DIGEST_SIZE];
- digestSz = SHA_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = hash256;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = hash384;
- digestSz = SHA384_DIGEST_SIZE;
+ #ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent) {
+ /* Check client ECC public key */
+ if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ break;
+ }
#endif
- }
- else if (hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = hash512;
- digestSz = SHA512_DIGEST_SIZE;
+
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
+
+ ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+ ssl->peerX25519Key);
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent) {
+ /* Check client ECC public key */
+ if (!ssl->peerX448Key) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ break;
+ }
#endif
- }
- }
- if (doUserEcc) {
- #ifdef HAVE_PK_CALLBACKS
- ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, length,
- digest, digestSz,
- ssl->buffers.peerEccDsaKey.buffer,
- ssl->buffers.peerEccDsaKey.length,
- &verify, ssl->EccVerifyCtx);
- #endif
- }
- else {
- ret = wc_ecc_verify_hash(input + *inOutIdx, length,
- digest, digestSz, &verify, ssl->peerEccDsaKey);
- }
- if (ret != 0 || verify == 0)
- ERROR_OUT(VERIFY_SIGN_ERROR, done);
- }
- else
-#endif /* HAVE_ECC */
- ERROR_OUT(ALGO_ID_E, done);
- /* signature length */
- *inOutIdx += length;
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE448;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
+ ssl->peerX448Key);
+ break;
+ }
+ #endif
+ /* Check client ECC public key */
+ if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+ !ssl->peerEccKey->dp) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
- done:
-#ifdef WOLFSSL_SMALL_STACK
- #ifndef NO_OLD_TLS
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifndef NO_SHA256
- XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA384
- XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA512
- XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- if (ret != 0)
- return ret;
- }
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- if (ssl->keys.encryptionOn) {
- *inOutIdx += ssl->keys.padSz;
- }
+ /* create ephemeral private key */
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
- return 0;
-#else /* !NO_DH or HAVE_ECC */
- return NOT_COMPILED_IN; /* not supported by build */
-#endif /* !NO_DH or HAVE_ECC */
+ ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
- #undef ERROR_OUT
- }
+ break;
+ #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ if (ssl->peerNtruKeyPresent == 0) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+ break;
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ #ifdef HAVE_ECC
+ ecc_key* peerKey;
+ #endif
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (ssl->ctx->X25519SharedSecretCb != NULL)
+ break;
+ }
+ else
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (ssl->ctx->X448SharedSecretCb != NULL)
+ break;
+ }
+ else
+ #endif
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
+ #endif /* HAVE_PK_CALLBACKS */
- int SendClientKeyExchange(WOLFSSL* ssl)
- {
-#ifdef WOLFSSL_SMALL_STACK
- byte* encSecret = NULL;
-#else
- byte encSecret[MAX_ENCRYPT_SZ];
-#endif
- word32 encSz = 0;
- word32 idx = 0;
- int ret = 0;
- byte doUserRsa = 0;
+ #ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent) {
+ if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
- (void)doUserRsa;
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
-#ifdef HAVE_PK_CALLBACKS
- #ifndef NO_RSA
- if (ssl->ctx->RsaEncCb)
- doUserRsa = 1;
- #endif /* NO_RSA */
-#endif /*HAVE_PK_CALLBACKS */
+ ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+ ssl->peerX25519Key);
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent) {
+ if (!ssl->peerX448Key) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
- #ifdef WOLFSSL_SMALL_STACK
- encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encSecret == NULL)
- return MEMORY_E;
- #endif
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE448;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
- switch (ssl->specs.kea) {
- #ifndef NO_RSA
- case rsa_kea:
- ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret,
- SECRET_LEN);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
+ ssl->peerX448Key);
+ break;
+ }
#endif
- return ret;
- }
+ #ifdef HAVE_ECC
+ if (ssl->specs.static_ecdh) {
+ /* Note: EccDsa is really fixed Ecc key here */
+ if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+ peerKey = ssl->peerEccDsaKey;
+ }
+ else {
+ if (!ssl->peerEccKey || !ssl->peerEccKeyPresent) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
+ peerKey = ssl->peerEccKey;
+ }
+ if (peerKey == NULL) {
+ ERROR_OUT(NO_PEER_KEY, exit_scke);
+ }
- ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
- ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
- ssl->arrays->preMasterSz = SECRET_LEN;
+ /* create ephemeral private key */
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ goto exit_scke;
+ }
- if (ssl->peerRsaKey == NULL || ssl->peerRsaKeyPresent == 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey);
#endif
- return NO_PEER_KEY;
+
+ break;
}
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
- if (doUserRsa) {
- #ifdef HAVE_PK_CALLBACKS
- #ifndef NO_RSA
- encSz = MAX_ENCRYPT_SZ;
- ret = ssl->ctx->RsaEncCb(ssl,
- ssl->arrays->preMasterSecret,
- SECRET_LEN,
- encSecret, &encSz,
- ssl->buffers.peerRsaKey.buffer,
- ssl->buffers.peerRsaKey.length,
- ssl->RsaEncCtx);
- #endif /* NO_RSA */
- #endif /*HAVE_PK_CALLBACKS */
+ 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;
+ args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap,
+ DYNAMIC_TYPE_SECRET);
+ if (args->encSecret == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scke);
+ }
+ 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(MEMORY_E, exit_scke);
}
- else {
- ret = wc_RsaPublicEncrypt(ssl->arrays->preMasterSecret,
- SECRET_LEN, encSecret, MAX_ENCRYPT_SZ,
- ssl->peerRsaKey, ssl->rng);
- if (ret > 0) {
- encSz = ret;
- ret = 0; /* set success to 0 */
+ XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+ }
+
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ /* build PreMasterSecret with RNG data */
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+ if (tsip_useable(ssl)) {
+ ret = tsip_generatePremasterSecret(
+ &ssl->arrays->preMasterSecret[VERSION_SZ],
+ ENCRYPT_LEN - VERSION_SZ);
+ } else {
+ #endif
+ ret = wc_RNG_GenerateBlock(ssl->rng,
+ &ssl->arrays->preMasterSecret[VERSION_SZ],
+ SECRET_LEN - VERSION_SZ);
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
}
+ #endif
+ if (ret != 0) {
+ goto exit_scke;
+ }
+
+ ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+ ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+
+ ssl->arrays->preMasterSz = SECRET_LEN;
+
+ break;
}
- break;
- #endif
- #ifndef NO_DH
- case diffie_hellman_kea:
+ #endif /* !NO_RSA */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
{
- buffer serverP = ssl->buffers.serverDH_P;
- buffer serverG = ssl->buffers.serverDH_G;
- buffer serverPub = ssl->buffers.serverDH_Pub;
- #ifdef WOLFSSL_SMALL_STACK
- byte* priv = NULL;
- #else
- byte priv[ENCRYPT_LEN];
- #endif
- word32 privSz = 0;
- DhKey key;
+ ssl->buffers.sig.length = ENCRYPT_LEN;
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scke);
+ }
- if (serverP.buffer == 0 || serverG.buffer == 0 ||
- serverPub.buffer == 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return NO_PEER_KEY;
+ ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+ (void**)&ssl->buffers.serverDH_Key);
+ if (ret != 0) {
+ goto exit_scke;
}
- #ifdef WOLFSSL_SMALL_STACK
- priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (priv == NULL) {
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
+ !defined(WOLFSSL_OLD_PRIME_CHECK)
+ if (ssl->options.dhDoKeyTest &&
+ !ssl->options.dhKeyTested)
+ {
+ ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length,
+ NULL, 0, 0, ssl->rng);
+ if (ret != 0) {
+ goto exit_scke;
+ }
+ ssl->options.dhKeyTested = 1;
+ }
+ else
+ #endif
+ {
+ ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+ if (ret != 0) {
+ goto exit_scke;
+ }
}
- #endif
- wc_InitDhKey(&key);
- ret = wc_DhSetKey(&key, serverP.buffer, serverP.length,
- serverG.buffer, serverG.length);
- if (ret == 0)
- /* for DH, encSecret is Yc, agree is pre-master */
- ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz,
- encSecret, &encSz);
- if (ret == 0)
- ret = wc_DhAgree(&key, ssl->arrays->preMasterSecret,
- &ssl->arrays->preMasterSz, priv, privSz,
- serverPub.buffer, serverPub.length);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- wc_FreeDhKey(&key);
+ /* for DH, encSecret is Yc, agree is pre-master */
+ ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+ args->encSecret, &args->encSz);
+
+ /* set the max agree result size */
+ ssl->arrays->preMasterSz = ENCRYPT_LEN;
+ break;
}
- break;
- #endif /* NO_DH */
- #ifndef NO_PSK
- case psk_kea:
+ #endif /* !NO_DH */
+ #ifndef NO_PSK
+ case psk_kea:
{
byte* pms = ssl->arrays->preMasterSecret;
-
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
ssl->arrays->server_hint, ssl->arrays->client_identity,
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return PSK_KEY_ERROR;
+ ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
- encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
- if (encSz > MAX_PSK_ID_LEN) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return CLIENT_ID_ERROR;
+ ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+ args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+ if (args->encSz > MAX_PSK_ID_LEN) {
+ ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
}
- XMEMCPY(encSecret, ssl->arrays->client_identity, encSz);
+ XMEMCPY(args->encSecret, ssl->arrays->client_identity,
+ args->encSz);
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += 2;
+ pms += OPAQUE16_LEN;
XMEMSET(pms, 0, ssl->arrays->psk_keySz);
pms += ssl->arrays->psk_keySz;
c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += 2;
+ pms += OPAQUE16_LEN;
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4;
+ ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) +
+ (2 * OPAQUE16_LEN);
ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->psk_keySz = 0; /* No further need */
+ break;
}
- break;
- #endif /* NO_PSK */
- #if !defined(NO_DH) && !defined(NO_PSK)
- case dhe_psk_kea:
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
- byte* es = encSecret;
- buffer serverP = ssl->buffers.serverDH_P;
- buffer serverG = ssl->buffers.serverDH_G;
- buffer serverPub = ssl->buffers.serverDH_Pub;
- #ifdef WOLFSSL_SMALL_STACK
- byte* priv = NULL;
- #else
- byte priv[ENCRYPT_LEN];
- #endif
- word32 privSz = 0;
- word32 pubSz = 0;
- word32 esSz = 0;
- DhKey key;
-
- if (serverP.buffer == 0 || serverG.buffer == 0 ||
- serverPub.buffer == 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ word32 esSz = 0;
+ args->output = args->encSecret;
+
+ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+ ssl->arrays->server_hint, ssl->arrays->client_identity,
+ MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+ if (ssl->arrays->psk_keySz == 0 ||
+ ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+ }
+ ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+ esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+
+ if (esSz > MAX_PSK_ID_LEN) {
+ ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+ }
+
+ ssl->buffers.sig.length = ENCRYPT_LEN;
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scke);
+ }
+
+ c16toa((word16)esSz, args->output);
+ args->output += OPAQUE16_LEN;
+ XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+ args->output += esSz;
+ args->encSz = esSz + OPAQUE16_LEN;
+
+ args->length = 0;
+
+ ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+ (void**)&ssl->buffers.serverDH_Key);
+ if (ret != 0) {
+ goto exit_scke;
+ }
+
+ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
+ !defined(WOLFSSL_OLD_PRIME_CHECK)
+ if (ssl->options.dhDoKeyTest &&
+ !ssl->options.dhKeyTested)
+ {
+ ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length,
+ NULL, 0, 0, ssl->rng);
+ if (ret != 0) {
+ goto exit_scke;
+ }
+ ssl->options.dhKeyTested = 1;
+ }
+ else
#endif
- return NO_PEER_KEY;
+ {
+ ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+ if (ret != 0) {
+ goto exit_scke;
+ }
}
+ /* for DH, encSecret is Yc, agree is pre-master */
+ ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+ args->output + OPAQUE16_LEN, &args->length);
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ word32 esSz = 0;
+ args->output = args->encSecret;
+
+ /* Send PSK client identity */
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
ssl->arrays->server_hint, ssl->arrays->client_identity,
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return PSK_KEY_ERROR;
+ ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
+ ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
-
if (esSz > MAX_PSK_ID_LEN) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+ }
+
+ /* place size and identity in output buffer sz:identity */
+ c16toa((word16)esSz, args->output);
+ args->output += OPAQUE16_LEN;
+ XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+ args->output += esSz;
+ args->encSz = esSz + OPAQUE16_LEN;
+
+ /* length is used for public key size */
+ args->length = MAX_ENCRYPT_SZ;
+
+ /* Create shared ECC key leaving room at the beginning
+ of buffer for size of shared key. */
+ ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ break;
+ }
#endif
- return CLIENT_ID_ERROR;
+
+ ret = wc_curve25519_export_public_ex(
+ (curve25519_key*)ssl->hsKey,
+ args->output + OPAQUE8_LEN, &args->length,
+ EC25519_LITTLE_ENDIAN);
+ if (ret != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+ }
+
+ break;
}
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- #ifdef WOLFSSL_SMALL_STACK
- priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (priv == NULL) {
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ ret = wc_curve448_export_public_ex(
+ (curve448_key*)ssl->hsKey,
+ args->output + OPAQUE8_LEN, &args->length,
+ EC448_LITTLE_ENDIAN);
+ if (ret != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+ }
+
+ break;
}
#endif
- c16toa((word16)esSz, es);
- es += OPAQUE16_LEN;
- XMEMCPY(es, ssl->arrays->client_identity, esSz);
- es += esSz;
- encSz = esSz + OPAQUE16_LEN;
-
- wc_InitDhKey(&key);
- ret = wc_DhSetKey(&key, serverP.buffer, serverP.length,
- serverG.buffer, serverG.length);
- if (ret == 0)
- /* for DH, encSecret is Yc, agree is pre-master */
- ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz,
- es + OPAQUE16_LEN, &pubSz);
- if (ret == 0)
- ret = wc_DhAgree(&key, pms + OPAQUE16_LEN,
- &ssl->arrays->preMasterSz, priv, privSz,
- serverPub.buffer, serverPub.length);
- wc_FreeDhKey(&key);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
#endif
+
+ /* Place ECC key in output buffer, leaving room for size */
+ ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+ args->output + OPAQUE8_LEN, &args->length);
if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
}
- c16toa((word16)pubSz, es);
- encSz += pubSz + OPAQUE16_LEN;
- c16toa((word16)ssl->arrays->preMasterSz, pms);
- ssl->arrays->preMasterSz += OPAQUE16_LEN;
- pms += ssl->arrays->preMasterSz;
-
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz +=
- ssl->arrays->psk_keySz + OPAQUE16_LEN;
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0; /* No further need */
+ break;
}
- break;
- #endif /* !NO_DH && !NO_PSK */
- #ifdef HAVE_NTRU
- case ntru_kea:
+ #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
{
- word32 rc;
- word16 cipherLen = MAX_ENCRYPT_SZ;
- DRBG_HANDLE drbg;
- static uint8_t const wolfsslStr[] = {
- 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U'
- };
-
ret = wc_RNG_GenerateBlock(ssl->rng,
- ssl->arrays->preMasterSecret, SECRET_LEN);
+ ssl->arrays->preMasterSecret, SECRET_LEN);
if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
+ goto exit_scke;
}
ssl->arrays->preMasterSz = SECRET_LEN;
+ args->encSz = MAX_ENCRYPT_SZ;
+ break;
+ }
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ ssl->arrays->preMasterSz = ENCRYPT_LEN;
- if (ssl->peerNtruKeyPresent == 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #ifdef HAVE_CURVE25519
+ if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ break;
+ }
#endif
- return NO_PEER_KEY;
+
+ ret = wc_curve25519_export_public_ex(
+ (curve25519_key*)ssl->hsKey,
+ args->encSecret + OPAQUE8_LEN, &args->encSz,
+ EC25519_LITTLE_ENDIAN);
+ if (ret != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+ }
+
+ break;
}
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->hsType == DYNAMIC_TYPE_CURVE448) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- rc = ntru_crypto_drbg_instantiate(MAX_NTRU_BITS, wolfsslStr,
- sizeof(wolfsslStr), GetEntropy,
- &drbg);
- if (rc != DRBG_OK) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ret = wc_curve448_export_public_ex(
+ (curve448_key*)ssl->hsKey,
+ args->encSecret + OPAQUE8_LEN, &args->encSz,
+ EC448_LITTLE_ENDIAN);
+ if (ret != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+ }
+
+ break;
+ }
+ #endif
+ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
+ #endif
+
+ /* Place ECC key in buffer, leaving room for size */
+ ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+ args->encSecret + OPAQUE8_LEN, &args->encSz);
+ if (ret != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+ }
+ #endif /* HAVE_ECC */
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+ 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_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_DO:
+ {
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+ if (tsip_useable(ssl) &&
+ wc_RsaEncryptSize(ssl->peerRsaKey) == 256) {
+ ret = tsip_generateEncryptPreMasterSecret(ssl,
+ args->encSecret,
+ &args->encSz);
+
+ } else
#endif
- return NTRU_DRBG_ERROR;
+ ret = RsaEnc(ssl,
+ ssl->arrays->preMasterSecret, SECRET_LEN,
+ args->encSecret, &args->encSz,
+ ssl->peerRsaKey,
+ #if defined(HAVE_PK_CALLBACKS)
+ &ssl->buffers.peerRsaKey
+ #else
+ NULL
+ #endif
+ );
+
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+ ssl->buffers.serverDH_Pub.buffer,
+ ssl->buffers.serverDH_Pub.length,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz);
+ break;
+ }
+ #endif /* !NO_DH */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+ ssl->buffers.serverDH_Pub.buffer,
+ ssl->buffers.serverDH_Pub.length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &ssl->arrays->preMasterSz);
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ #ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent) {
+ ret = X25519SharedSecret(ssl,
+ (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+ args->output + OPAQUE8_LEN, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
+ #endif
+ ) {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ }
+ break;
}
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent) {
+ ret = X448SharedSecret(ssl,
+ (curve448_key*)ssl->hsKey, ssl->peerX448Key,
+ args->output + OPAQUE8_LEN, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
+ #endif
+ ) {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ }
+ break;
+ }
+ #endif
+ ret = EccSharedSecret(ssl,
+ (ecc_key*)ssl->hsKey, ssl->peerEccKey,
+ args->output + OPAQUE8_LEN, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ FreeKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ word32 rc;
+ word16 tmpEncSz = (word16)args->encSz;
+ DRBG_HANDLE drbg;
+ rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+ if (rc != DRBG_OK) {
+ ERROR_OUT(NTRU_DRBG_ERROR, exit_scke);
+ }
rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,
ssl->peerNtruKey,
ssl->arrays->preMasterSz,
ssl->arrays->preMasterSecret,
- &cipherLen, encSecret);
+ &tmpEncSz,
+ args->encSecret);
+ args->encSz = tmpEncSz;
ntru_crypto_drbg_uninstantiate(drbg);
if (rc != NTRU_OK) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return NTRU_ENCRYPT_ERROR;
+ ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke);
}
-
- encSz = cipherLen;
ret = 0;
+ break;
}
- break;
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- case ecc_diffie_hellman_kea:
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
{
- ecc_key myKey;
- ecc_key* peerKey = NULL;
- word32 size = MAX_ENCRYPT_SZ;
+ #ifdef HAVE_ECC
+ ecc_key* peerKey;
+ #endif
- if (ssl->specs.static_ecdh) {
- /* TODO: EccDsa is really fixed Ecc change naming */
- if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
- !ssl->peerEccDsaKey->dp) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent) {
+ ret = X25519SharedSecret(ssl,
+ (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+ args->encSecret + OPAQUE8_LEN, &args->encSz,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
#endif
- return NO_PEER_KEY;
+ ) {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
}
- peerKey = ssl->peerEccDsaKey;
+ break;
}
- else {
- if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
- !ssl->peerEccKey->dp) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent) {
+ ret = X448SharedSecret(ssl,
+ (curve448_key*)ssl->hsKey, ssl->peerX448Key,
+ args->encSecret + OPAQUE8_LEN, &args->encSz,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
#endif
- return NO_PEER_KEY;
+ ) {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
}
- peerKey = ssl->peerEccKey;
+ break;
}
-
- if (peerKey == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return NO_PEER_KEY;
+ #endif
+ #ifdef HAVE_ECC
+ peerKey = (ssl->specs.static_ecdh) ?
+ ssl->peerEccDsaKey : ssl->peerEccKey;
+
+ ret = EccSharedSecret(ssl,
+ (ecc_key*)ssl->hsKey, peerKey,
+ args->encSecret + OPAQUE8_LEN, &args->encSz,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
+ #endif
+ && !ssl->options.keepResources) {
+ FreeKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
}
+ #endif
- wc_ecc_init(&myKey);
- ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ECC_MAKEKEY_ERROR;
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+ 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_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_VERIFY:
+ {
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ break;
+ }
+ #endif /* !NO_DH */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ byte* pms = ssl->arrays->preMasterSecret;
+
+ /* validate args */
+ if (args->output == NULL || args->length == 0) {
+ ERROR_OUT(BAD_FUNC_ARG, exit_scke);
}
- /* precede export with 1 byte length */
- ret = wc_ecc_export_x963(&myKey, encSecret + 1, &size);
- encSecret[0] = (byte)size;
- encSz = size + 1;
+ c16toa((word16)args->length, args->output);
+ args->encSz += args->length + OPAQUE16_LEN;
+ c16toa((word16)ssl->arrays->preMasterSz, pms);
+ ssl->arrays->preMasterSz += OPAQUE16_LEN;
+ pms += ssl->arrays->preMasterSz;
- if (ret != 0)
- ret = ECC_EXPORT_ERROR;
- else {
- size = sizeof(ssl->arrays->preMasterSecret);
- ret = wc_ecc_shared_secret(&myKey, peerKey,
- ssl->arrays->preMasterSecret, &size);
- if (ret != 0)
- ret = ECC_SHARED_ERROR;
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16)ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+ XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->preMasterSz +=
+ ssl->arrays->psk_keySz + OPAQUE16_LEN;
+ ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->psk_keySz = 0; /* No further need */
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ byte* pms = ssl->arrays->preMasterSecret;
+
+ /* validate args */
+ if (args->output == NULL || args->length > ENCRYPT_LEN) {
+ ERROR_OUT(BAD_FUNC_ARG, exit_scke);
}
- ssl->arrays->preMasterSz = size;
- wc_ecc_free(&myKey);
+ /* place size of public key in output buffer */
+ *args->output = (byte)args->length;
+ args->encSz += args->length + OPAQUE8_LEN;
+
+ /* Create pre master secret is the concatenation of
+ eccSize + eccSharedKey + pskSize + pskKey */
+ c16toa((word16)ssl->arrays->preMasterSz, pms);
+ ssl->arrays->preMasterSz += OPAQUE16_LEN;
+ pms += ssl->arrays->preMasterSz;
+
+ c16toa((word16)ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+ XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->preMasterSz +=
+ ssl->arrays->psk_keySz + OPAQUE16_LEN;
+
+ ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->psk_keySz = 0; /* No further need */
+ break;
}
- break;
- #endif /* HAVE_ECC */
- default:
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ALGO_ID_E; /* unsupported kea */
- }
+ #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ break;
+ }
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ /* place size of public key in buffer */
+ *args->encSecret = (byte)args->encSz;
+ args->encSz += OPAQUE8_LEN;
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
- if (ret == 0) {
- byte *output;
- int sendSz;
- word32 tlsSz = 0;
+ 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_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_FINALIZE:
+ {
+ word32 tlsSz = 0;
+ word32 idx = 0;
+
+ #ifdef HAVE_QSH
+ word32 qshSz = 0;
+ if (ssl->peerQSHKeyPresent) {
+ qshSz = QSH_KeyGetSize(ssl);
+ }
+ #endif
- if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
+ if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) {
tlsSz = 2;
+ }
if (ssl->specs.kea == ecc_diffie_hellman_kea ||
- ssl->specs.kea == dhe_psk_kea) /* always off */
+ ssl->specs.kea == dhe_psk_kea ||
+ ssl->specs.kea == ecdhe_psk_kea) { /* always off */
tlsSz = 0;
+ }
- sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ args->sendSz = args->encSz + tlsSz + idx;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
- idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
- }
- #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ }
+ #endif
- if (ssl->keys.encryptionOn)
- sendSz += MAX_MSG_EXTRA;
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
+
+ #ifdef HAVE_QSH
+ args->encSz += qshSz;
+ args->sendSz += qshSz;
+ #endif
/* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_scke;
}
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
- AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
+ #ifdef HAVE_QSH
+ if (ssl->peerQSHKeyPresent) {
+ byte idxSave = idx;
+ idx = args->sendSz - qshSz;
- if (tlsSz) {
- c16toa((word16)encSz, &output[idx]);
- idx += 2;
- }
- XMEMCPY(output + idx, encSecret, encSz);
- idx += encSz;
+ if (QSH_KeyExchangeWrite(ssl, 0) != 0) {
+ ERROR_OUT(MEMORY_E, exit_scke);
+ }
- if (ssl->keys.encryptionOn) {
- byte* input;
- int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */
+ /* extension type */
+ c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx);
+ idx += OPAQUE16_LEN;
- input = (byte*)XMALLOC(inputSz, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (input == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return MEMORY_E;
+ /* write to output and check amount written */
+ if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+ args->output + idx) > qshSz - OPAQUE16_LEN) {
+ ERROR_OUT(MEMORY_E, exit_scke);
}
- XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (sendSz < 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return sendSz;
- }
- } else {
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
+ idx = idxSave;
+ }
+ #endif
+
+ AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl);
+
+ #ifdef HAVE_QSH
+ if (ssl->peerQSHKeyPresent) {
+ args->encSz -= qshSz;
+ }
+ #endif
+ if (tlsSz) {
+ c16toa((word16)args->encSz, &args->output[idx]);
+ idx += OPAQUE16_LEN;
+ }
+ XMEMCPY(args->output + idx, args->encSecret, args->encSz);
+ idx += args->encSz;
+
+ if (IsEncryptionOn(ssl, 1)) {
+ args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */
+ args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ if (args->input == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scke);
}
+
+ XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+ args->inputSz);
}
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
+ /* 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);
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL; /* make sure its not double free'd on cleanup */
+
+ if (ret >= 0) {
+ args->sendSz = ret;
+ ret = 0;
}
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
#endif
+ ret = HashOutput(ssl, args->output, args->sendSz, 0);
+ }
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
+ if (ret != 0) {
+ goto exit_scke;
+ }
- ssl->buffers.outputBuffer.length += sendSz;
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
+ goto exit_scke;
+ }
+ }
+ #endif
- if (ssl->options.groupMessages)
- ret = 0;
- else
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "ClientKeyExchange");
+ if (ssl->toInfoOn)
+ AddPacketInfo(ssl, "ClientKeyExchange", handshake,
+ args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += args->sendSz;
+
+ if (!ssl->options.groupMessages) {
ret = SendBuffered(ssl);
+ }
+ if (ret == 0 || ret == WANT_WRITE) {
+ int tmpRet = MakeMasterSecret(ssl);
+ if (tmpRet != 0) {
+ ret = tmpRet; /* save WANT_WRITE unless more serious */
+ }
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ }
+ break;
}
+ default:
+ ret = INPUT_CASE_ERROR;
+ } /* switch(ssl->options.asyncState) */
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+exit_scke:
- if (ret == 0 || ret == WANT_WRITE) {
- int tmpRet = MakeMasterSecret(ssl);
- if (tmpRet != 0)
- ret = tmpRet; /* save WANT_WRITE unless more serious */
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- }
- /* No further need for PMS */
- ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
- ssl->arrays->preMasterSz = 0;
+ WOLFSSL_LEAVE("SendClientKeyExchange", ret);
+ WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E)
return ret;
+#endif
+
+ /* No further need for PMS */
+ if (ssl->arrays->preMasterSecret != NULL) {
+ ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
}
+ ssl->arrays->preMasterSz = 0;
+
+ /* Final cleanup */
+ FreeSckeArgs(ssl, args);
+ FreeKeyExchange(ssl);
+
+ return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
#ifndef NO_CERTS
- int SendCertificateVerify(WOLFSSL* ssl)
+
+#ifdef HAVE_PK_CALLBACKS
+ int GetPrivateKeySigSize(WOLFSSL* ssl)
{
- byte *output;
- int sendSz = MAX_CERT_VERIFY_SZ, length, ret;
- word32 idx = 0;
- word32 sigOutSz = 0;
-#ifndef NO_RSA
- RsaKey key;
- int initRsaKey = 0;
-#endif
- int usingEcc = 0;
-#ifdef HAVE_ECC
- ecc_key eccKey;
-#endif
+ int sigSz = 0;
- (void)idx;
+ if (ssl == NULL)
+ return 0;
- if (ssl->options.sendVerify == SEND_BLANK_CERT)
- return 0; /* sent blank cert, can't verify */
+ switch (ssl->buffers.keyType) {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #endif
+ case rsa_sa_algo:
+ sigSz = ssl->buffers.keySz;
+ ssl->hsType = DYNAMIC_TYPE_RSA;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz);
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ break;
+ #endif
+ #ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ sigSz = ED25519_SIG_SIZE; /* fixed known value */
+ ssl->hsType = DYNAMIC_TYPE_ED25519;
+ break;
+ #endif
+ #ifdef HAVE_ED448
+ case ed448_sa_algo:
+ sigSz = ED448_SIG_SIZE; /* fixed known value */
+ ssl->hsType = DYNAMIC_TYPE_ED448;
+ break;
+ #endif
+ default:
+ break;
+ }
+ return sigSz;
+ }
+#endif /* HAVE_PK_CALLBACKS */
- if (ssl->keys.encryptionOn)
- sendSz += MAX_MSG_EXTRA;
+#ifndef WOLFSSL_NO_TLS12
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
- return ret;
+#ifndef WOLFSSL_NO_CLIENT_AUTH
+typedef struct ScvArgs {
+ byte* output; /* not allocated */
+#ifndef NO_RSA
+ byte* verifySig;
+#endif
+ byte* verify; /* not allocated */
+ byte* input;
+ word32 idx;
+ word32 extraSz;
+ word32 sigSz;
+ int sendSz;
+ int inputSz;
+ word16 length;
+ byte sigAlgo;
+} ScvArgs;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
+static void FreeScvArgs(WOLFSSL* ssl, void* pArgs)
+{
+ ScvArgs* args = (ScvArgs*)pArgs;
- ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
- if (ret != 0)
- return ret;
+ (void)ssl;
-#ifdef HAVE_ECC
- wc_ecc_init(&eccKey);
-#endif
#ifndef NO_RSA
- ret = wc_InitRsaKey(&key, ssl->heap);
- if (ret == 0) initRsaKey = 1;
- if (ret == 0)
- ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
- ssl->buffers.key.length);
- if (ret == 0)
- sigOutSz = wc_RsaEncryptSize(&key);
- else
+ if (args->verifySig) {
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
+ }
#endif
- {
- #ifdef HAVE_ECC
- WOLFSSL_MSG("Trying ECC client cert, RSA didn't work");
+ if (args->input) {
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
+ }
+}
- idx = 0;
- ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &eccKey,
- ssl->buffers.key.length);
- if (ret == 0) {
- WOLFSSL_MSG("Using ECC client cert");
- usingEcc = 1;
- sigOutSz = MAX_ENCODED_SIG_SZ;
- }
- else {
- WOLFSSL_MSG("Bad client cert type");
- }
- #endif
- }
- if (ret == 0) {
- byte* verify = (byte*)&output[RECORD_HEADER_SZ +
- HANDSHAKE_HEADER_SZ];
-#ifndef NO_OLD_TLS
- byte* signBuffer = ssl->hsHashes->certHashes.md5;
+/* handle generation of certificate_verify (15) */
+int SendCertificateVerify(WOLFSSL* ssl)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ScvArgs* args = (ScvArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
#else
- byte* signBuffer = NULL;
+ ScvArgs args[1];
#endif
- word32 signSz = FINISHED_SZ;
- word32 extraSz = 0; /* tls 1.2 hash/sig */
-#ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig = NULL;
-#else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
+
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+ WOLFSSL_ENTER("SendCertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_scv;
+ }
+ else
#endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(ScvArgs));
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeScvArgs;
+ #endif
+ }
-#ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL) {
- #ifndef NO_RSA
- if (initRsaKey)
- wc_FreeRsaKey(&key);
- #endif
- #ifdef HAVE_ECC
- wc_ecc_free(&eccKey);
- #endif
- return MEMORY_E;
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+ return 0; /* sent blank cert, can't verify */
}
-#endif
- (void)encodedSig;
- (void)signSz;
- (void)signBuffer;
+ args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- #endif
- length = sigOutSz;
- if (IsAtLeastTLSv1_2(ssl)) {
- verify[0] = ssl->suites->hashAlgo;
- verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo;
- extraSz = HASH_SIG_SIZE;
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_scv;
}
- if (usingEcc) {
-#ifdef HAVE_ECC
- word32 localSz = MAX_ENCODED_SIG_SZ;
- word32 digestSz;
- byte* digest;
- byte doUserEcc = 0;
-#ifndef NO_OLD_TLS
- /* old tls default */
- digestSz = SHA_DIGEST_SIZE;
- digest = ssl->hsHashes->certHashes.sha;
-#else
- /* new tls default */
- digestSz = SHA256_DIGEST_SIZE;
- digest = ssl->hsHashes->certHashes.sha256;
-#endif
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
- #ifdef HAVE_PK_CALLBACKS
- #ifdef HAVE_ECC
- if (ssl->ctx->EccSignCb)
- doUserEcc = 1;
- #endif /* HAVE_ECC */
- #endif /*HAVE_PK_CALLBACKS */
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* case TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
- if (IsAtLeastTLSv1_2(ssl)) {
- if (ssl->suites->hashAlgo == sha_mac) {
- #ifndef NO_SHA
- digest = ssl->hsHashes->certHashes.sha;
- digestSz = SHA_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = ssl->hsHashes->certHashes.sha256;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = ssl->hsHashes->certHashes.sha384;
- digestSz = SHA384_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = ssl->hsHashes->certHashes.sha512;
- digestSz = SHA512_DIGEST_SIZE;
- #endif
- }
- }
+ case TLS_ASYNC_BUILD:
+ {
+ ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+ if (ret != 0) {
+ goto exit_scv;
+ }
- if (doUserEcc) {
- #ifdef HAVE_PK_CALLBACKS
- #ifdef HAVE_ECC
- ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
- encodedSig, &localSz,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->EccSignCtx);
- #endif /* HAVE_ECC */
- #endif /*HAVE_PK_CALLBACKS */
- }
- else {
- ret = wc_ecc_sign_hash(digest, digestSz, encodedSig,
- &localSz, ssl->rng, &eccKey);
+ if (ssl->buffers.key == NULL) {
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+ args->length = GetPrivateKeySigSize(ssl);
+ else
+ #endif
+ ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+ }
+ else {
+ /* Decode private key. */
+ ret = DecodePrivateKey(ssl, &args->length);
+ if (ret != 0) {
+ goto exit_scv;
}
- if (ret == 0) {
- length = localSz;
- c16toa((word16)length, verify + extraSz); /* prepend hdr */
- XMEMCPY(verify + extraSz + VERIFY_HEADER,encodedSig,length);
+ }
+
+ if (args->length == 0) {
+ ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+ }
+
+ /* idx is used to track verify pointer offset to output */
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
+ args->extraSz = 0; /* tls 1.2 hash/sig */
+
+ /* build encoded signature buffer */
+ ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ;
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scv);
+ }
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ #ifndef NO_OLD_TLS
+ #ifndef NO_SHA
+ /* old tls default */
+ SetDigest(ssl, sha_mac);
+ #endif
+ #else
+ #ifndef NO_SHA256
+ /* new tls default */
+ SetDigest(ssl, sha256_mac);
+ #endif
+ #endif /* !NO_OLD_TLS */
+
+ if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+ #ifdef WC_RSA_PSS
+ if (IsAtLeastTLSv1_2(ssl) &&
+ (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) {
+ args->sigAlgo = rsa_pss_sa_algo;
}
-#endif
+ else
+ #endif
+ args->sigAlgo = rsa_sa_algo;
}
-#ifndef NO_RSA
+ else if (ssl->hsType == DYNAMIC_TYPE_ECC)
+ args->sigAlgo = ecc_dsa_sa_algo;
+ else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
+ args->sigAlgo = ed25519_sa_algo;
+ else if (ssl->hsType == DYNAMIC_TYPE_ED448)
+ args->sigAlgo = ed448_sa_algo;
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo,
+ args->verify);
+ args->extraSz = HASH_SIG_SIZE;
+ SetDigest(ssl, ssl->suites->hashAlgo);
+ }
+ #ifndef NO_OLD_TLS
else {
- byte doUserRsa = 0;
+ /* if old TLS load MD5 and SHA hash as value to sign */
+ XMEMCPY(ssl->buffers.sig.buffer,
+ (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ);
+ }
+ #endif
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaSignCb)
- doUserRsa = 1;
- #endif /*HAVE_PK_CALLBACKS */
+ #ifndef NO_RSA
+ if (args->sigAlgo == rsa_sa_algo) {
+ ssl->buffers.sig.length = FINISHED_SZ;
+ args->sigSz = ENCRYPT_LEN;
if (IsAtLeastTLSv1_2(ssl)) {
- /*
- * MSVC Compiler complains because it can not
- * guarantee any of the conditionals will succeed in
- * assigning a value before wc_EncodeSignature executes.
- */
- byte* digest = NULL;
- int digestSz = 0;
- int typeH = 0;
- int didSet = 0;
-
- if (ssl->suites->hashAlgo == sha_mac) {
- #ifndef NO_SHA
- digest = ssl->hsHashes->certHashes.sha;
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- didSet = 1;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = ssl->hsHashes->certHashes.sha256;
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- didSet = 1;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = ssl->hsHashes->certHashes.sha384;
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- didSet = 1;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = ssl->hsHashes->certHashes.sha512;
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- didSet = 1;
- #endif
- }
+ ssl->buffers.sig.length = wc_EncodeSignature(
+ ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ TypeHash(ssl->suites->hashAlgo));
+ }
- if (didSet == 0) {
- /* defaults */
- #ifndef NO_OLD_TLS
- digest = ssl->hsHashes->certHashes.sha;
- digestSz = SHA_DIGEST_SIZE;
- typeH = SHAh;
- #else
- digest = ssl->hsHashes->certHashes.sha256;
- digestSz = SHA256_DIGEST_SIZE;
- typeH = SHA256h;
- #endif
- }
+ /* prepend hdr */
+ c16toa(args->length, args->verify + args->extraSz);
+ }
+ #ifdef WC_RSA_PSS
+ else if (args->sigAlgo == rsa_pss_sa_algo) {
+ XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length);
+ ssl->buffers.sig.length = ssl->buffers.digest.length;
+ args->sigSz = ENCRYPT_LEN;
+
+ /* prepend hdr */
+ c16toa(args->length, args->verify + args->extraSz);
+ }
+ #endif
+ #endif /* !NO_RSA */
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (args->sigAlgo == ed25519_sa_algo) {
+ ret = Ed25519CheckPubKey(ssl);
+ if (ret != 0)
+ goto exit_scv;
+ }
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (args->sigAlgo == ed448_sa_algo) {
+ ret = Ed448CheckPubKey(ssl);
+ if (ret != 0)
+ goto exit_scv;
+ }
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
- signSz = wc_EncodeSignature(encodedSig, digest,digestSz,typeH);
- signBuffer = encodedSig;
- }
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
- c16toa((word16)length, verify + extraSz); /* prepend hdr */
- if (doUserRsa) {
- #ifdef HAVE_PK_CALLBACKS
- #ifndef NO_RSA
- word32 ioLen = ENCRYPT_LEN;
- ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
- verify + extraSz + VERIFY_HEADER,
- &ioLen,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->RsaSignCtx);
- #endif /* NO_RSA */
- #endif /*HAVE_PK_CALLBACKS */
- }
- else {
- ret = wc_RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
- VERIFY_HEADER, ENCRYPT_LEN, &key, ssl->rng);
- }
+ case TLS_ASYNC_DO:
+ {
+ #ifdef HAVE_ECC
+ if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+ ecc_key* key = (ecc_key*)ssl->hsKey;
- if (ret > 0)
- ret = 0; /* RSA reset */
+ ret = EccSign(ssl,
+ ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+ ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
}
-#endif
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+ ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+ ret = Ed25519Sign(ssl,
+ ssl->hsHashes->messages, ssl->hsHashes->length,
+ ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+ }
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (ssl->hsType == DYNAMIC_TYPE_ED448) {
+ ed448_key* key = (ed448_key*)ssl->hsKey;
+
+ ret = Ed448Sign(ssl,
+ ssl->hsHashes->messages, ssl->hsHashes->length,
+ ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+ }
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+ #ifndef NO_RSA
+ if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
+
+ /* restore verify pointer */
+ args->verify = &args->output[args->idx];
+
+ ret = RsaSign(ssl,
+ ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+ args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz,
+ args->sigAlgo, ssl->suites->hashAlgo, key,
+ ssl->buffers.key
+ );
+ }
+ #endif /* !NO_RSA */
- if (ret == 0) {
- AddHeaders(output, length + extraSz + VERIFY_HEADER,
- certificate_verify, ssl);
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_scv;
+ }
- sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
- extraSz + VERIFY_HEADER;
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
+ case TLS_ASYNC_VERIFY:
+ {
+ /* restore verify pointer */
+ args->verify = &args->output[args->idx];
- if (ssl->keys.encryptionOn) {
- byte* input;
- int inputSz = sendSz - RECORD_HEADER_SZ;
- /* build msg adds rec hdr */
- input = (byte*)XMALLOC(inputSz, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (input == NULL)
- ret = MEMORY_E;
- else {
- XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
- sendSz = BuildMessage(ssl, output,
- MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA,
- input, inputSz, handshake);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ switch (ssl->hsType) {
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+ #ifdef HAVE_ECC
+ case DYNAMIC_TYPE_ECC:
+ #endif
+ #ifdef HAVE_ED25519
+ case DYNAMIC_TYPE_ED25519:
+ #endif
+ #ifdef HAVE_ED448
+ case DYNAMIC_TYPE_ED448:
+ #endif
+ args->length = (word16)ssl->buffers.sig.length;
+ /* prepend hdr */
+ c16toa(args->length, args->verify + args->extraSz);
+ XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
+ ssl->buffers.sig.buffer, ssl->buffers.sig.length);
+ break;
+ #endif
+ #ifndef NO_RSA
+ case DYNAMIC_TYPE_RSA:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
- if (sendSz < 0)
- ret = sendSz;
+ if (args->verifySig == NULL) {
+ args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (args->verifySig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scv);
+ }
+ XMEMCPY(args->verifySig, args->verify + args->extraSz +
+ VERIFY_HEADER, args->sigSz);
}
- } else {
- ret = HashOutput(ssl, output, sendSz, 0);
+
+ /* check for signature faults */
+ ret = VerifyRsaSign(ssl,
+ args->verifySig, args->sigSz,
+ ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+ args->sigAlgo, ssl->suites->hashAlgo, key,
+ ssl->buffers.key
+ );
+ break;
}
+ #endif /* !NO_RSA */
+ default:
+ break;
+ }
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- }
- #endif
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_scv;
}
- }
-#ifndef NO_RSA
- if (initRsaKey)
- wc_FreeRsaKey(&key);
-#endif
-#ifdef HAVE_ECC
- wc_ecc_free(&eccKey);
-#endif
- if (ret == 0) {
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateVerify", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_FINALIZE:
+ {
+ if (args->output == NULL) {
+ ERROR_OUT(BUFFER_ERROR, exit_scv);
+ }
+ AddHeaders(args->output, (word32)args->length + args->extraSz +
+ VERIFY_HEADER, certificate_verify, ssl);
+
+ args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
+ (word32)args->length + args->extraSz + VERIFY_HEADER;
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ if (IsEncryptionOn(ssl, 1)) {
+ args->inputSz = args->sendSz - RECORD_HEADER_SZ;
+ /* build msg adds rec hdr */
+ args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ if (args->input == NULL) {
+ ERROR_OUT(MEMORY_E, exit_scv);
+ }
+
+ XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+ 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,
+ MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
+ args->input, args->inputSz, handshake,
+ 1, 0, 1);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ goto exit_scv;
#endif
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- return 0;
- else
- return SendBuffered(ssl);
+
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL; /* make sure its not double free'd on cleanup */
+
+ if (ret >= 0) {
+ args->sendSz = ret;
+ ret = 0;
+ }
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ ret = HashOutput(ssl, args->output, args->sendSz, 0);
+ }
+
+ if (ret != 0) {
+ goto exit_scv;
+ }
+
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz);
+ }
+ #endif
+
+
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "CertificateVerify");
+ if (ssl->toInfoOn)
+ AddPacketInfo(ssl, "CertificateVerify", handshake,
+ args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += args->sendSz;
+
+ if (!ssl->options.groupMessages) {
+ ret = SendBuffered(ssl);
+ }
+ break;
}
- else
- return ret;
+ default:
+ ret = INPUT_CASE_ERROR;
+ } /* switch(ssl->options.asyncState) */
+
+exit_scv:
+
+ WOLFSSL_LEAVE("SendCertificateVerify", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E) {
+ return ret;
}
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+ /* Digest is not allocated, so do this to prevent free */
+ ssl->buffers.digest.buffer = NULL;
+ ssl->buffers.digest.length = 0;
+
+ /* Final cleanup */
+ FreeScvArgs(ssl, args);
+ FreeKeyExchange(ssl);
+
+ return ret;
+}
+#endif /* WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* WOLFSSL_NO_TLS12 */
+
#endif /* NO_CERTS */
+
#ifdef HAVE_SESSION_TICKET
-int DoSessionTicket(WOLFSSL* ssl,
- const byte* input, word32* inOutIdx, word32 size)
+int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length)
+{
+ /* Free old dynamic ticket if we already had one */
+ if (ssl->session.isDynamic) {
+ XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ ssl->session.ticket = ssl->session.staticTicket;
+ ssl->session.isDynamic = 0;
+ }
+
+ if (length > sizeof(ssl->session.staticTicket)) {
+ byte* sessionTicket =
+ (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ if (sessionTicket == NULL)
+ return MEMORY_E;
+ ssl->session.ticket = sessionTicket;
+ ssl->session.isDynamic = 1;
+ }
+ ssl->session.ticketLen = (word16)length;
+
+ if (length > 0) {
+ XMEMCPY(ssl->session.ticket, ticket, length);
+ if (ssl->session_ticket_cb != NULL) {
+ ssl->session_ticket_cb(ssl,
+ ssl->session.ticket, ssl->session.ticketLen,
+ ssl->session_ticket_ctx);
+ }
+ /* Create a fake sessionID based on the ticket, this will
+ * supersede the existing session cache info. */
+ ssl->options.haveSessionId = 1;
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ XMEMCPY(ssl->session.sessionID,
+ ssl->session.ticket + length - ID_LEN, ID_LEN);
+ }
+ else
+#endif
+ XMEMCPY(ssl->arrays->sessionID,
+ ssl->session.ticket + length - ID_LEN, ID_LEN);
+ }
+
+ return 0;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of session_ticket (4) */
+static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+ word32 size)
{
word32 begin = *inOutIdx;
word32 lifetime;
word16 length;
+ int ret;
if (ssl->expect_session_ticket == 0) {
WOLFSSL_MSG("Unexpected session ticket");
return SESSION_TICKET_EXPECT_E;
}
- if ((*inOutIdx - begin) + OPAQUE32_LEN > size)
+ if (OPAQUE32_LEN > size)
return BUFFER_ERROR;
ato32(input + *inOutIdx, &lifetime);
@@ -11326,60 +23996,138 @@ int DoSessionTicket(WOLFSSL* ssl,
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
- if (length > sizeof(ssl->session.ticket))
- return SESSION_TICKET_LEN_E;
-
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;
- /* If the received ticket including its length is greater than
- * a length value, the save it. Otherwise, don't save it. */
+ if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
+ return ret;
+ *inOutIdx += length;
if (length > 0) {
- XMEMCPY(ssl->session.ticket, input + *inOutIdx, length);
- *inOutIdx += length;
- ssl->session.ticketLen = length;
ssl->timeout = lifetime;
- if (ssl->session_ticket_cb != NULL) {
- ssl->session_ticket_cb(ssl,
- ssl->session.ticket, ssl->session.ticketLen,
- ssl->session_ticket_ctx);
- }
- /* Create a fake sessionID based on the ticket, this will
- * supercede the existing session cache info. */
- ssl->options.haveSessionId = 1;
- XMEMCPY(ssl->arrays->sessionID,
- ssl->session.ticket + length - ID_LEN, ID_LEN);
#ifndef NO_SESSION_CACHE
AddSession(ssl);
#endif
-
- }
- else {
- ssl->session.ticketLen = 0;
}
- if (ssl->keys.encryptionOn) {
+ 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
}
ssl->expect_session_ticket = 0;
return 0;
}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
#endif /* HAVE_SESSION_TICKET */
#endif /* NO_WOLFSSL_CLIENT */
+#ifdef HAVE_ECC
+ /* returns the WOLFSSL_* version of the curve from the OID sum */
+ word16 GetCurveByOID(int oidSum) {
+ switch(oidSum) {
+ #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP160R1_OID:
+ return WOLFSSL_ECC_SECP160R1;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_SECPR2
+ case ECC_SECP160R2_OID:
+ return WOLFSSL_ECC_SECP160R2;
+ #endif /* HAVE_ECC_SECPR2 */
+ #ifdef HAVE_ECC_KOBLITZ
+ case ECC_SECP160K1_OID:
+ return WOLFSSL_ECC_SECP160K1;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP192R1_OID:
+ return WOLFSSL_ECC_SECP192R1;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case ECC_SECP192K1_OID:
+ return WOLFSSL_ECC_SECP192K1;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP224R1_OID:
+ return WOLFSSL_ECC_SECP224R1;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case ECC_SECP224K1_OID:
+ return WOLFSSL_ECC_SECP224K1;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #endif
+ #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP256R1_OID:
+ return WOLFSSL_ECC_SECP256R1;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_KOBLITZ
+ case ECC_SECP256K1_OID:
+ return WOLFSSL_ECC_SECP256K1;
+ #endif /* HAVE_ECC_KOBLITZ */
+ #ifdef HAVE_ECC_BRAINPOOL
+ case ECC_BRAINPOOLP256R1_OID:
+ return WOLFSSL_ECC_BRAINPOOLP256R1;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP384R1_OID:
+ return WOLFSSL_ECC_SECP384R1;
+ #endif /* !NO_ECC_SECP */
+ #ifdef HAVE_ECC_BRAINPOOL
+ case ECC_BRAINPOOLP384R1_OID:
+ return WOLFSSL_ECC_BRAINPOOLP384R1;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+ #ifdef HAVE_ECC_BRAINPOOL
+ case ECC_BRAINPOOLP512R1_OID:
+ return WOLFSSL_ECC_BRAINPOOLP512R1;
+ #endif /* HAVE_ECC_BRAINPOOL */
+ #endif
+ #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+ #ifndef NO_ECC_SECP
+ case ECC_SECP521R1_OID:
+ return WOLFSSL_ECC_SECP521R1;
+ #endif /* !NO_ECC_SECP */
+ #endif
+ default:
+ WOLFSSL_MSG("Curve OID not compiled in or implemented");
+ return 0;
+ }
+ }
+#endif /* HAVE_ECC */
+
#ifndef NO_WOLFSSL_SERVER
+#ifndef WOLFSSL_NO_TLS12
+
+ /* handle generation of server_hello (2) */
int SendServerHello(WOLFSSL* ssl)
{
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- int ret;
- byte sessIdSz = ID_LEN;
+ int ret;
+ byte *output;
+ word16 length;
+ word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ byte sessIdSz = ID_LEN;
+ byte echoId = 0; /* ticket echo id flag */
+ byte cacheOff = 0; /* session cache off flag */
+
+ WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
+ WOLFSSL_ENTER("SendServerHello");
length = VERSION_SZ + RAN_LEN
+ ID_LEN + ENUM_LEN
@@ -11387,49 +24135,115 @@ int DoSessionTicket(WOLFSSL* ssl,
+ ENUM_LEN;
#ifdef HAVE_TLS_EXTENSIONS
- length += TLSX_GetResponseSize(ssl);
-
+ ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+ if (ret != 0)
+ return ret;
#ifdef HAVE_SESSION_TICKET
- if (ssl->options.useTicket && ssl->arrays->sessionIDSz == 0) {
- /* no session id */
- length -= ID_LEN;
- sessIdSz = 0;
+ if (ssl->options.useTicket) {
+ /* echo session id sz can be 0,32 or bogus len in between */
+ sessIdSz = ssl->arrays->sessionIDSz;
+ if (sessIdSz > ID_LEN) {
+ WOLFSSL_MSG("Bad bogus session id len");
+ return BUFFER_ERROR;
+ }
+ if (!IsAtLeastTLSv1_3(ssl->version))
+ length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */
+ echoId = 1;
}
#endif /* HAVE_SESSION_TICKET */
+#else
+ if (ssl->options.haveEMS) {
+ length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
+ }
+#endif
+
+ /* is the session cache off at build or runtime */
+#ifdef NO_SESSION_CACHE
+ cacheOff = 1;
+#else
+ if (ssl->options.sessionCacheOff == 1) {
+ cacheOff = 1;
+ }
#endif
- /* check for avalaible size */
- if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0)
+ /* if no session cache don't send a session ID unless we're echoing
+ * an ID as part of session tickets */
+ if (echoId == 0 && cacheOff == 1) {
+ length -= ID_LEN; /* adjust ID_LEN assumption */
+ sessIdSz = 0;
+ }
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ /* Server Hello should use 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;
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif /* WOLFSSL_DTLS */
+
+ if (IsEncryptionOn(ssl, 1))
+ sendSz += MAX_MSG_EXTRA;
+
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
AddHeaders(output, length, server_hello, ssl);
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
/* now write to output */
- /* first version */
- output[idx++] = ssl->version.major;
- output[idx++] = ssl->version.minor;
+ /* first version */
+ output[idx++] = (byte)ssl->version.major;
+ output[idx++] = (byte)ssl->version.minor;
- /* then random */
+ /* then random and session id */
if (!ssl->options.resuming) {
- ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
- RAN_LEN);
+ /* generate random part and session id */
+ ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
+ RAN_LEN + sizeof(sessIdSz) + sessIdSz);
if (ret != 0)
return ret;
- }
- XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
- idx += RAN_LEN;
+#ifdef WOLFSSL_TLS13
+ if (TLSv1_3_Capable(ssl)) {
+ /* TLS v1.3 capable server downgraded. */
+ XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+ tls13Downgrade, TLS13_DOWNGRADE_SZ);
+ output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
+ }
+ else
+#endif
+ if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+ ssl->ctx->method->version.minor == TLSv1_2_MINOR &&
+ !IsAtLeastTLSv1_2(ssl)) {
+ /* TLS v1.2 capable server downgraded. */
+ XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+ tls13Downgrade, TLS13_DOWNGRADE_SZ);
+ output[idx + RAN_LEN - 1] = 0;
+ }
+
+ /* store info in SSL for later */
+ XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
+ idx += RAN_LEN;
+ output[idx++] = sessIdSz;
+ XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
+ ssl->arrays->sessionIDSz = sessIdSz;
+ }
+ else {
+ /* If resuming, use info from SSL */
+ XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+ output[idx++] = sessIdSz;
+ XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
+ }
+ idx += sessIdSz;
#ifdef SHOW_SECRETS
{
@@ -11440,1427 +24254,1715 @@ int DoSessionTicket(WOLFSSL* ssl,
printf("\n");
}
#endif
- /* then session id */
- output[idx++] = sessIdSz;
- if (sessIdSz) {
-
- if (!ssl->options.resuming) {
- ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID,
- sessIdSz);
- if (ret != 0) return ret;
- }
-
- XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
- idx += sessIdSz;
- }
- /* then cipher suite */
+ /* then cipher suite */
output[idx++] = ssl->options.cipherSuite0;
output[idx++] = ssl->options.cipherSuite;
- /* then compression */
+ /* then compression */
if (ssl->options.usingCompression)
output[idx++] = ZLIB_COMPRESSION;
else
output[idx++] = NO_COMPRESSION;
- /* last, extensions */
+ /* last, extensions */
#ifdef HAVE_TLS_EXTENSIONS
- TLSX_WriteResponse(ssl, output + idx);
+ {
+ word16 offset = 0;
+ ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset);
+ if (ret != 0)
+ return ret;
+ idx += offset;
+ }
+#else
+#ifdef HAVE_EXTENDED_MASTER
+ if (ssl->options.haveEMS) {
+ c16toa(HELLO_EXT_SZ, output + idx);
+ idx += HELLO_EXT_SZ_SZ;
+
+ c16toa(HELLO_EXT_EXTMS, output + idx);
+ idx += HELLO_EXT_TYPE_SZ;
+ c16toa(0, output + idx);
+ /*idx += HELLO_EXT_SZ_SZ;*/
+ /* idx is not used after this point. uncomment the line above
+ * if adding any more extensions in the future. */
+ }
+#endif
#endif
- ssl->buffers.outputBuffer.length += sendSz;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- }
- #endif
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ return sendSz;
+ } else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ ret = HashOutput(ssl, output, sendSz, 0);
+ if (ret != 0)
+ return ret;
+ }
+
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "ServerHello");
+ if (ssl->toInfoOn)
+ AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
+ #endif
ssl->options.serverState = SERVER_HELLO_COMPLETE;
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+ return ret;
+ }
+ #endif
if (ssl->options.groupMessages)
- return 0;
+ ret = 0;
else
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendServerHello", ret);
+ WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+ return ret;
}
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC)
- static byte SetCurveId(int size)
+ static byte SetCurveId(ecc_key* key)
{
- switch(size) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case 20:
- return WOLFSSL_ECC_SECP160R1;
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case 24:
- return WOLFSSL_ECC_SECP192R1;
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case 28:
- return WOLFSSL_ECC_SECP224R1;
-#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case 32:
- return WOLFSSL_ECC_SECP256R1;
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case 48:
- return WOLFSSL_ECC_SECP384R1;
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case 66:
- return WOLFSSL_ECC_SECP521R1;
-#endif
- default:
- return 0;
+ if (key == NULL || key->dp == NULL) {
+ WOLFSSL_MSG("SetCurveId: Invalid key!");
+ return 0;
}
+
+ return (byte)GetCurveByOID(key->dp->oidSum);
}
#endif /* HAVE_ECC */
+ typedef struct SskeArgs {
+ byte* output; /* not allocated */
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ (!defined(NO_DH) && !defined(NO_RSA))
+ byte* sigDataBuf;
+ #endif
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ byte* exportBuf;
+ #endif
+ #ifndef NO_RSA
+ byte* verifySig;
+ #endif
+ byte* input;
+ word32 idx;
+ word32 tmpSigSz;
+ word32 length;
+ word32 sigSz;
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ (!defined(NO_DH) && !defined(NO_RSA))
+ word32 sigDataSz;
+ #endif
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ word32 exportSz;
+ #endif
+ #ifdef HAVE_QSH
+ word32 qshSz;
+ #endif
+ int sendSz;
+ int inputSz;
+ } SskeArgs;
- int SendServerKeyExchange(WOLFSSL* ssl)
+ static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs)
{
- int ret = 0;
- (void)ssl;
- #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0)
-
- #ifndef NO_PSK
- if (ssl->specs.kea == psk_kea)
- {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- if (ssl->arrays->server_hint[0] == 0) return 0; /* don't send */
-
- /* include size part */
- length = (word32)XSTRLEN(ssl->arrays->server_hint);
- if (length > MAX_PSK_ID_LEN)
- return SERVER_HINT_ERROR;
-
- length += HINT_LEN_SZ;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
- return ret;
+ SskeArgs* args = (SskeArgs*)pArgs;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
-
- AddHeaders(output, length, server_key_exchange, ssl);
-
- /* key data */
- c16toa((word16)(length - HINT_LEN_SZ), output + idx);
- idx += HINT_LEN_SZ;
- XMEMCPY(output + idx, ssl->arrays->server_hint,length -HINT_LEN_SZ);
-
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- #endif
-
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
-
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
- #endif
+ (void)ssl;
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- ret = 0;
- else
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+ if (args->exportBuf) {
+ XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
+ args->exportBuf = NULL;
}
- #endif /*NO_PSK */
-
- #if !defined(NO_DH) && !defined(NO_PSK)
- if (ssl->specs.kea == dhe_psk_kea) {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- word32 hintLen;
- int sendSz;
- DhKey dhKey;
-
- if (ssl->buffers.serverDH_P.buffer == NULL ||
- ssl->buffers.serverDH_G.buffer == NULL)
- return NO_DH_PARAMS;
-
- if (ssl->buffers.serverDH_Pub.buffer == NULL) {
- ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Pub.buffer == NULL)
- return MEMORY_E;
- }
-
- if (ssl->buffers.serverDH_Priv.buffer == NULL) {
- ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Priv.buffer == NULL)
- return MEMORY_E;
- }
-
- wc_InitDhKey(&dhKey);
- ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng,
- ssl->buffers.serverDH_Priv.buffer,
- &ssl->buffers.serverDH_Priv.length,
- ssl->buffers.serverDH_Pub.buffer,
- &ssl->buffers.serverDH_Pub.length);
- wc_FreeDhKey(&dhKey);
- if (ret != 0)
- return ret;
-
- length = LENGTH_SZ * 3 + /* p, g, pub */
- ssl->buffers.serverDH_P.length +
- ssl->buffers.serverDH_G.length +
- ssl->buffers.serverDH_Pub.length;
-
- /* include size part */
- hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
- if (hintLen > MAX_PSK_ID_LEN)
- return SERVER_HINT_ERROR;
- length += hintLen + HINT_LEN_SZ;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
-
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
- return ret;
-
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
-
- AddHeaders(output, length, server_key_exchange, ssl);
-
- /* key data */
- c16toa((word16)hintLen, output + idx);
- idx += HINT_LEN_SZ;
- XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen);
- idx += hintLen;
-
- /* add p, g, pub */
- c16toa((word16)ssl->buffers.serverDH_P.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length);
- idx += ssl->buffers.serverDH_P.length;
-
- /* g */
- c16toa((word16)ssl->buffers.serverDH_G.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- idx += ssl->buffers.serverDH_G.length;
-
- /* pub */
- c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer,
- ssl->buffers.serverDH_Pub.length);
- idx += ssl->buffers.serverDH_Pub.length;
- (void)idx; /* suppress analyzer warning, and keep idx current */
-
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- #endif
-
- ret = HashOutput(ssl, output, sendSz, 0);
+ #endif
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ (!defined(NO_DH) && !defined(NO_RSA))
+ if (args->sigDataBuf) {
+ XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->sigDataBuf = NULL;
+ }
+ #endif
+ #ifndef NO_RSA
+ if (args->verifySig) {
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
+ }
+ #endif
+ (void)args;
+ }
- if (ret != 0)
- return ret;
+ /* handle generation of server_key_exchange (12) */
+ int SendServerKeyExchange(WOLFSSL* ssl)
+ {
+ int ret;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ SskeArgs* args = (SskeArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+ #else
+ SskeArgs args[1];
+ #endif
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
- #endif
+ WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
+ WOLFSSL_ENTER("SendServerKeyExchange");
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- ret = 0;
- else
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_sske;
}
- #endif /* !NO_DH && !NO_PSK */
-
- #ifdef HAVE_ECC
- if (ssl->specs.kea == ecc_diffie_hellman_kea)
+ else
+ #endif
{
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- word32 sigSz;
- word32 preSigSz, preSigIdx;
- #ifndef NO_RSA
- RsaKey rsaKey;
- #endif
- ecc_key dsaKey;
- #ifdef WOLFSSL_SMALL_STACK
- byte* exportBuf = NULL;
- #else
- byte exportBuf[MAX_EXPORT_ECC_SZ];
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(SskeArgs));
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeSskeArgs;
#endif
- word32 expSz = MAX_EXPORT_ECC_SZ;
-
- #ifndef NO_OLD_TLS
- byte doMd5 = 0;
- byte doSha = 0;
- #endif
- #ifndef NO_SHA256
- byte doSha256 = 0;
- #endif
- #ifdef WOLFSSL_SHA384
- byte doSha384 = 0;
- #endif
- #ifdef WOLFSSL_SHA512
- byte doSha512 = 0;
- #endif
-
- if (ssl->specs.static_ecdh) {
- WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchagne");
- return 0;
- }
-
- /* curve type, named curve, length(1) */
- length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
- /* pub key size */
- WOLFSSL_MSG("Using ephemeral ECDH");
+ }
- /* need ephemeral key now, create it if missing */
- if (ssl->eccTempKey == NULL) {
- /* alloc/init on demand */
- ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
- ssl->ctx->heap, DYNAMIC_TYPE_ECC);
- if (ssl->eccTempKey == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- wc_ecc_init(ssl->eccTempKey);
- }
- if (ssl->eccTempKeyPresent == 0) {
- if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz,
- ssl->eccTempKey) != 0) {
- return ECC_MAKEKEY_ERROR;
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ #ifdef HAVE_QSH
+ if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) {
+ args->qshSz = QSH_KeyGetSize(ssl);
}
- ssl->eccTempKeyPresent = 1;
- }
-
- #ifdef WOLFSSL_SMALL_STACK
- exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (exportBuf == NULL)
- return MEMORY_E;
- #endif
-
- if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0)
- ERROR_OUT(ECC_EXPORT_ERROR, done_a);
- length += expSz;
-
- preSigSz = length;
- preSigIdx = idx;
-
- #ifndef NO_RSA
- ret = wc_InitRsaKey(&rsaKey, ssl->heap);
- if (ret != 0)
- goto done_a;
- #endif
-
- wc_ecc_init(&dsaKey);
-
- /* sig length */
- length += LENGTH_SZ;
-
- if (!ssl->buffers.key.buffer) {
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
#endif
- wc_ecc_free(&dsaKey);
- ERROR_OUT(NO_PRIVATE_KEY, done_a);
- }
- #ifndef NO_RSA
- if (ssl->specs.sig_algo == rsa_sa_algo) {
- /* rsa sig size */
- word32 i = 0;
- ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i,
- &rsaKey, ssl->buffers.key.length);
- if (ret != 0)
- goto done_a;
- sigSz = wc_RsaEncryptSize(&rsaKey);
- } else
- #endif
-
- if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
- /* ecdsa sig size */
- word32 i = 0;
- ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
- &dsaKey, ssl->buffers.key.length);
- if (ret != 0)
- goto done_a;
- sigSz = wc_ecc_sig_size(&dsaKey); /* worst case estimate */
- }
- else {
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
- #endif
- wc_ecc_free(&dsaKey);
- ERROR_OUT(ALGO_ID_E, done_a); /* unsupported type */
- }
- length += sigSz;
-
- if (IsAtLeastTLSv1_2(ssl))
- length += HASH_SIG_SIZE;
-
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ /* Do some checks / debug msgs */
+ switch(ssl->specs.kea)
+ {
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ WOLFSSL_MSG("Using ephemeral ECDH PSK");
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ #if defined(HAVE_ECC)
+ case ecc_diffie_hellman_kea:
+ {
+ if (ssl->specs.static_ecdh) {
+ WOLFSSL_MSG("Using Static ECDH, not sending "
+ "ServerKeyExchange");
+ ERROR_OUT(0, exit_sske);
+ }
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- preSigIdx = idx;
- }
- #endif
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
- #endif
- wc_ecc_free(&dsaKey);
- goto done_a;
- }
+ WOLFSSL_MSG("Using ephemeral ECDH");
+ break;
+ }
+ #endif /* HAVE_ECC */
+ }
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
+ /* Preparing keys */
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ /* Nothing to do in this sub-state */
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA))
+ #if !defined(NO_PSK)
+ case dhe_psk_kea:
+ #endif
+ #if !defined(NO_RSA)
+ case diffie_hellman_kea:
+ #endif
+ {
+ /* Allocate DH key buffers and generate key */
+ if (ssl->buffers.serverDH_P.buffer == NULL ||
+ ssl->buffers.serverDH_G.buffer == NULL) {
+ ERROR_OUT(NO_DH_PARAMS, exit_sske);
+ }
- /* record and message headers will be added below, when we're sure
- of the sig length */
+ if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+ /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
+ ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+ ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ }
- /* key exchange data */
- output[idx++] = named_curve;
- output[idx++] = 0x00; /* leading zero */
- output[idx++] = SetCurveId(wc_ecc_size(ssl->eccTempKey));
- output[idx++] = (byte)expSz;
- XMEMCPY(output + idx, exportBuf, expSz);
- idx += expSz;
- if (IsAtLeastTLSv1_2(ssl)) {
- byte setHash = 0;
+ if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+ /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
+ ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+ ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+ if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ }
- output[idx++] = ssl->suites->hashAlgo;
- output[idx++] = ssl->suites->sigAlgo;
+ ssl->options.dhKeySz =
+ (word16)ssl->buffers.serverDH_P.length;
- switch (ssl->suites->hashAlgo) {
- case sha512_mac:
- #ifdef WOLFSSL_SHA512
- doSha512 = 1;
- setHash = 1;
- #endif
- break;
+ ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+ (void**)&ssl->buffers.serverDH_Key);
+ if (ret != 0) {
+ goto exit_sske;
+ }
- case sha384_mac:
- #ifdef WOLFSSL_SHA384
- doSha384 = 1;
- setHash = 1;
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+ !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ if (ssl->options.dhDoKeyTest &&
+ !ssl->options.dhKeyTested)
+ {
+ ret = wc_DhSetCheckKey(
+ ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length,
+ NULL, 0, 0, ssl->rng);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ ssl->options.dhKeyTested = 1;
+ }
+ else
#endif
- break;
+ {
+ ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- case sha256_mac:
- #ifndef NO_SHA256
- doSha256 = 1;
- setHash = 1;
- #endif
+ ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_Priv.buffer,
+ (word32*)&ssl->buffers.serverDH_Priv.length,
+ ssl->buffers.serverDH_Pub.buffer,
+ (word32*)&ssl->buffers.serverDH_Pub.length);
break;
+ }
+ #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ /* Fall through to create temp ECC key */
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ /* need ephemeral key now, create it if missing */
+ if (ssl->eccTempKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->eccTempKey);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- case sha_mac:
- #ifndef NO_OLD_TLS
- doSha = 1;
- setHash = 1;
- #endif
- break;
+ if (ssl->eccTempKeyPresent == 0) {
+ ret = X25519MakeKey(ssl,
+ (curve25519_key*)ssl->eccTempKey, NULL);
+ if (ret == 0 || ret == WC_PENDING_E) {
+ ssl->eccTempKeyPresent =
+ DYNAMIC_TYPE_CURVE25519;
+ }
+ }
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ /* need ephemeral key now, create it if missing */
+ if (ssl->eccTempKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->eccTempKey);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- default:
- WOLFSSL_MSG("Bad hash sig algo");
- break;
- }
+ if (ssl->eccTempKeyPresent == 0) {
+ ret = X448MakeKey(ssl,
+ (curve448_key*)ssl->eccTempKey, NULL);
+ if (ret == 0 || ret == WC_PENDING_E) {
+ ssl->eccTempKeyPresent =
+ DYNAMIC_TYPE_CURVE448;
+ }
+ }
+ break;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ /* need ephemeral key now, create it if missing */
+ if (ssl->eccTempKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->eccTempKey);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- if (setHash == 0) {
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
+ if (ssl->eccTempKeyPresent == 0) {
+ ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
+ if (ret == 0 || ret == WC_PENDING_E) {
+ ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC;
+ }
+ }
#endif
- wc_ecc_free(&dsaKey);
- ERROR_OUT(ALGO_ID_E, done_a);
- }
- } else {
- /* only using sha and md5 for rsa */
- #ifndef NO_OLD_TLS
- doSha = 1;
- if (ssl->suites->sigAlgo == rsa_sa_algo) {
- doMd5 = 1;
+ break;
}
- #else
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
- #endif
- wc_ecc_free(&dsaKey);
- ERROR_OUT(ALGO_ID_E, done_a);
- #endif
- }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ default:
+ /* Skip ServerKeyExchange */
+ goto exit_sske;
+ } /* switch(ssl->specs.kea) */
- /* Signtaure length will be written later, when we're sure what it
- is */
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_sske;
+ }
- #ifdef HAVE_FUZZER
- if (ssl->fuzzerCb)
- ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE,
- ssl->fuzzerCtx);
- #endif
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* case TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
- /* do signature */
+ case TLS_ASYNC_BUILD:
{
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = NULL;
- Sha* sha = NULL;
- #else
- Md5 md5[1];
- Sha sha[1];
- #endif
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- byte* hash = NULL;
- #else
- byte hash[FINISHED_SZ];
+ #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
+ defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
+ word32 preSigSz, preSigIdx;
#endif
- #ifndef NO_SHA256
- #ifdef WOLFSSL_SMALL_STACK
- Sha256* sha256 = NULL;
- byte* hash256 = NULL;
- #else
- Sha256 sha256[1];
- byte hash256[SHA256_DIGEST_SIZE];
- #endif
- #endif
- #ifdef WOLFSSL_SHA384
- #ifdef WOLFSSL_SMALL_STACK
- Sha384* sha384 = NULL;
- byte* hash384 = NULL;
- #else
- Sha384 sha384[1];
- byte hash384[SHA384_DIGEST_SIZE];
- #endif
- #endif
- #ifdef WOLFSSL_SHA512
- #ifdef WOLFSSL_SMALL_STACK
- Sha512* sha512 = NULL;
- byte* hash512 = NULL;
- #else
- Sha512 sha512[1];
- byte hash512[SHA512_DIGEST_SIZE];
- #endif
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- hash = (byte*)XMALLOC(FINISHED_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (hash == NULL)
- ERROR_OUT(MEMORY_E, done_a);
- #endif
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- #ifndef NO_OLD_TLS
- /* md5 */
- #ifdef WOLFSSL_SMALL_STACK
- if (doMd5) {
- md5 = (Md5*)XMALLOC(sizeof(Md5), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (md5 == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- }
- #endif
- if (doMd5) {
- wc_InitMd5(md5);
- wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
- wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
- wc_Md5Update(md5, output + preSigIdx, preSigSz);
- wc_Md5Final(md5, hash);
- }
- /* sha */
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha) {
- sha = (Sha*)XMALLOC(sizeof(Sha), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- }
- #endif
- if (doSha) {
- ret = wc_InitSha(sha);
- if (ret != 0) goto done_a2;
- wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
- wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
- wc_ShaUpdate(sha, output + preSigIdx, preSigSz);
- wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]);
- }
- #endif
+ if (ssl->arrays->server_hint[0] == 0) {
+ ERROR_OUT(0, exit_sske); /* don't send */
+ }
- #ifndef NO_SHA256
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha256) {
- sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha256 == NULL || hash256 == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- }
- #endif
+ /* include size part */
+ args->length = (word32)XSTRLEN(ssl->arrays->server_hint);
+ if (args->length > MAX_PSK_ID_LEN) {
+ ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+ }
- if (doSha256) {
- if (!(ret = wc_InitSha256(sha256))
- && !(ret = wc_Sha256Update(sha256,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha256Update(sha256,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha256Update(sha256,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha256Final(sha256, hash256);
+ args->length += HINT_LEN_SZ;
+ args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+ RECORD_HEADER_SZ;
- if (ret != 0) goto done_a2;
- }
- #endif
+ #ifdef HAVE_QSH
+ args->length += args->qshSz;
+ args->sendSz += args->qshSz;
+ #endif
- #ifdef WOLFSSL_SHA384
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha384) {
- sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha384 == NULL || hash384 == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- }
- #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
- if (doSha384) {
- if (!(ret = wc_InitSha384(sha384))
- && !(ret = wc_Sha384Update(sha384,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha384Update(sha384,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha384Update(sha384,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha384Final(sha384, hash384);
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- if (ret != 0) goto done_a2;
- }
- #endif
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_sske;
+ }
- #ifdef WOLFSSL_SHA512
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha512) {
- sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha512 == NULL || hash512 == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- }
- #endif
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
- if (doSha512) {
- if (!(ret = wc_InitSha512(sha512))
- && !(ret = wc_Sha512Update(sha512,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha512Update(sha512,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha512Update(sha512,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha512Final(sha512, hash512);
+ AddHeaders(args->output, args->length,
+ server_key_exchange, ssl);
- if (ret != 0) goto done_a2;
- }
- #endif
+ /* key data */
+ #ifdef HAVE_QSH
+ c16toa((word16)(args->length - args->qshSz -
+ HINT_LEN_SZ), args->output + args->idx);
+ #else
+ c16toa((word16)(args->length - HINT_LEN_SZ),
+ args->output + args->idx);
+ #endif
- #ifndef NO_RSA
- if (ssl->suites->sigAlgo == rsa_sa_algo) {
- byte* signBuffer = hash;
- word32 signSz = FINISHED_SZ;
- byte doUserRsa = 0;
- #ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig = NULL;
- #else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- #endif
+ args->idx += HINT_LEN_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->arrays->server_hint,
+ args->length - HINT_LEN_SZ);
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ word32 hintLen;
+
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ args->length = LENGTH_SZ * 3 + /* p, g, pub */
+ ssl->buffers.serverDH_P.length +
+ ssl->buffers.serverDH_G.length +
+ ssl->buffers.serverDH_Pub.length;
+
+ /* include size part */
+ hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+ if (hintLen > MAX_PSK_ID_LEN) {
+ ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+ }
+ args->length += hintLen + HINT_LEN_SZ;
+ args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+ RECORD_HEADER_SZ;
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaSignCb)
- doUserRsa = 1;
- #endif
+ #ifdef HAVE_QSH
+ args->length += args->qshSz;
+ args->sendSz += args->qshSz;
+ #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
- #ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL)
- ERROR_OUT(MEMORY_E, done_a2);
- #endif
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- if (IsAtLeastTLSv1_2(ssl)) {
- byte* digest = &hash[MD5_DIGEST_SIZE];
- int typeH = SHAh;
- int digestSz = SHA_DIGEST_SIZE;
-
- if (ssl->suites->hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = hash256;
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_sske;
}
- else if (ssl->suites->hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = hash384;
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- #endif
+
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ AddHeaders(args->output, args->length,
+ server_key_exchange, ssl);
+
+ /* key data */
+ c16toa((word16)hintLen, args->output + args->idx);
+ args->idx += HINT_LEN_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->arrays->server_hint, hintLen);
+ args->idx += hintLen;
+
+ /* add p, g, pub */
+ c16toa((word16)ssl->buffers.serverDH_P.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length);
+ args->idx += ssl->buffers.serverDH_P.length;
+
+ /* g */
+ c16toa((word16)ssl->buffers.serverDH_G.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+ args->idx += ssl->buffers.serverDH_G.length;
+
+ /* pub */
+ c16toa((word16)ssl->buffers.serverDH_Pub.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_Pub.buffer,
+ ssl->buffers.serverDH_Pub.length);
+ /* No need to update idx, since sizes are already set */
+ /* args->idx += ssl->buffers.serverDH_Pub.length; */
+ break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ word32 hintLen;
+
+ /* curve type, named curve, length(1) */
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+ args->exportSz = MAX_EXPORT_ECC_SZ;
+ args->exportBuf = (byte*)XMALLOC(args->exportSz,
+ ssl->heap, DYNAMIC_TYPE_DER);
+ if (args->exportBuf == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
}
- else if (ssl->suites->hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = hash512;
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- #endif
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (wc_curve25519_export_public_ex(
+ (curve25519_key*)ssl->eccTempKey,
+ args->exportBuf, &args->exportSz,
+ EC25519_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
}
-
- if (digest == NULL) {
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
- #endif
- wc_ecc_free(&dsaKey);
- ERROR_OUT(ALGO_ID_E, done_a2);
+ else
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (wc_curve448_export_public_ex(
+ (curve448_key*)ssl->eccTempKey,
+ args->exportBuf, &args->exportSz,
+ EC448_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
}
- signSz = wc_EncodeSignature(encodedSig, digest,
- digestSz, typeH);
- signBuffer = encodedSig;
- }
- /* write sig size here */
- c16toa((word16)sigSz, output + idx);
- idx += LENGTH_SZ;
+ else
+ #endif
+ {
+ if (wc_ecc_export_x963(ssl->eccTempKey,
+ args->exportBuf, &args->exportSz) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
+ }
+ args->length += args->exportSz;
- if (doUserRsa) {
- #ifdef HAVE_PK_CALLBACKS
- word32 ioLen = sigSz;
- ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
- output + idx, &ioLen,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->RsaSignCtx);
- #endif /*HAVE_PK_CALLBACKS */
- }
- else
- ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx,
- sigSz, &rsaKey, ssl->rng);
+ /* include size part */
+ hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+ if (hintLen > MAX_PSK_ID_LEN) {
+ ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+ }
+ args->length += hintLen + HINT_LEN_SZ;
+ args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- wc_FreeRsaKey(&rsaKey);
- wc_ecc_free(&dsaKey);
+ #ifdef HAVE_QSH
+ args->length += args->qshSz;
+ args->sendSz += args->qshSz;
+ #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- if (ret < 0)
- goto done_a2;
- } else
- #endif
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_sske;
+ }
- if (ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
- #ifndef NO_OLD_TLS
- byte* digest = &hash[MD5_DIGEST_SIZE];
- word32 digestSz = SHA_DIGEST_SIZE;
- #else
- byte* digest = hash256;
- word32 digestSz = SHA256_DIGEST_SIZE;
- #endif
- word32 sz = sigSz;
- byte doUserEcc = 0;
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ /* key data */
+ c16toa((word16)hintLen, args->output + args->idx);
+ args->idx += HINT_LEN_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->arrays->server_hint, hintLen);
+ args->idx += hintLen;
+
+ /* ECC key exchange data */
+ args->output[args->idx++] = named_curve;
+ args->output[args->idx++] = 0x00; /* leading zero */
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID)
+ args->output[args->idx++] = WOLFSSL_ECC_X25519;
+ else
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID)
+ args->output[args->idx++] = WOLFSSL_ECC_X448;
+ else
+ #endif
+ {
+ #ifdef HAVE_ECC
+ args->output[args->idx++] =
+ SetCurveId(ssl->eccTempKey);
+ #endif
+ }
+ args->output[args->idx++] = (byte)args->exportSz;
+ XMEMCPY(args->output + args->idx, args->exportBuf,
+ args->exportSz);
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ enum wc_HashType hashType;
+
+ /* curve type, named curve, length(1) */
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+ /* Export temp ECC key and add to length */
+ args->exportSz = MAX_EXPORT_ECC_SZ;
+ args->exportBuf = (byte*)XMALLOC(args->exportSz,
+ ssl->heap, DYNAMIC_TYPE_DER);
+ if (args->exportBuf == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (wc_curve25519_export_public_ex(
+ (curve25519_key*)ssl->eccTempKey,
+ args->exportBuf, &args->exportSz,
+ EC25519_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
+ }
+ else
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (wc_curve448_export_public_ex(
+ (curve448_key*)ssl->eccTempKey,
+ args->exportBuf, &args->exportSz,
+ EC448_LITTLE_ENDIAN) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
+ }
+ else
+ #endif
+ {
+ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+ if (wc_ecc_export_x963(ssl->eccTempKey,
+ args->exportBuf, &args->exportSz) != 0) {
+ ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+ }
+ #endif
+ }
+ args->length += args->exportSz;
- #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
- if (ssl->ctx->EccSignCb)
- doUserEcc = 1;
- #endif
+ preSigSz = args->length;
+ preSigIdx = args->idx;
- if (IsAtLeastTLSv1_2(ssl)) {
- if (ssl->suites->hashAlgo == sha_mac) {
- #ifndef NO_SHA
- digest = &hash[MD5_DIGEST_SIZE];
- digestSz = SHA_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = hash256;
- digestSz = SHA256_DIGEST_SIZE;
+ if (ssl->buffers.key == NULL) {
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+ args->tmpSigSz = GetPrivateKeySigSize(ssl);
+ if (args->tmpSigSz == 0) {
+ ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+ }
+ }
+ else
#endif
+ ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
}
- else if (ssl->suites->hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = hash384;
- digestSz = SHA384_DIGEST_SIZE;
+ else {
+ switch(ssl->suites->sigAlgo) {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
#endif
- }
- else if (ssl->suites->hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = hash512;
- digestSz = SHA512_DIGEST_SIZE;
+ case rsa_sa_algo:
+ {
+ word16 keySz;
+
+ ssl->buffers.keyType = rsa_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+
+ args->tmpSigSz = (word32)keySz;
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ {
+ word16 keySz;
+
+ ssl->buffers.keyType = ecc_dsa_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ /* worst case estimate */
+ args->tmpSigSz = keySz;
+ break;
+ }
#endif
- }
- }
+ #ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ {
+ word16 keySz;
+
+ ssl->buffers.keyType = ed25519_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_sske;
+ }
- if (doUserEcc) {
- #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
- ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
- output + LENGTH_SZ + idx, &sz,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->EccSignCtx);
- #endif
- }
- else {
- ret = wc_ecc_sign_hash(digest, digestSz,
- output + LENGTH_SZ + idx, &sz, ssl->rng, &dsaKey);
- }
- #ifndef NO_RSA
- wc_FreeRsaKey(&rsaKey);
- #endif
- wc_ecc_free(&dsaKey);
+ /* worst case estimate */
+ args->tmpSigSz = ED25519_SIG_SIZE;
+ break;
+ }
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ed448_sa_algo:
+ {
+ word16 keySz;
+
+ ssl->buffers.keyType = ed448_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_sske;
+ }
- if (ret < 0)
- goto done_a2;
+ /* worst case estimate */
+ args->tmpSigSz = ED448_SIG_SIZE;
+ break;
+ }
+ #endif /* HAVE_ED448 */
+ default:
+ ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */
+ } /* switch(ssl->specs.sig_algo) */
+ }
- /* Now that we know the real sig size, write it. */
- c16toa((word16)sz, output + idx);
+ /* sig length */
+ args->length += LENGTH_SZ;
+ args->length += args->tmpSigSz;
- /* And adjust length and sendSz from estimates */
- length += sz - sigSz;
- sendSz += sz - sigSz;
- }
+ if (IsAtLeastTLSv1_2(ssl)) {
+ args->length += HASH_SIG_SIZE;
+ }
- done_a2:
- #ifdef WOLFSSL_SMALL_STACK
- #ifndef NO_OLD_TLS
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #ifndef NO_SHA256
- XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA384
- XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA512
- XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #endif
+ args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- if (ret < 0)
- goto done_a;
- }
+ #ifdef HAVE_QSH
+ args->length += args->qshSz;
+ args->sendSz += args->qshSz;
+ #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ preSigIdx = args->idx;
+ }
+ #endif
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- AddHeaders(output, length, server_key_exchange, ssl);
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_sske;
+ }
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- goto done_a;
- #endif
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
- if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0)
- goto done_a;
+ /* record and message headers will be added below, when we're sure
+ of the sig length */
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
+ /* key exchange data */
+ args->output[args->idx++] = named_curve;
+ args->output[args->idx++] = 0x00; /* leading zero */
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID)
+ args->output[args->idx++] = WOLFSSL_ECC_X25519;
+ else
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID)
+ args->output[args->idx++] = WOLFSSL_ECC_X448;
+ else
+ #endif
+ {
+ #ifdef HAVE_ECC
+ args->output[args->idx++] =
+ SetCurveId(ssl->eccTempKey);
+ #endif
+ }
+ args->output[args->idx++] = (byte)args->exportSz;
+ XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz);
+ args->idx += args->exportSz;
+
+ /* Determine hash type */
+ if (IsAtLeastTLSv1_2(ssl)) {
+ EncodeSigAlg(ssl->suites->hashAlgo,
+ ssl->suites->sigAlgo,
+ &args->output[args->idx]);
+ args->idx += 2;
+
+ hashType = HashAlgoToType(ssl->suites->hashAlgo);
+ if (hashType == WC_HASH_TYPE_NONE) {
+ ERROR_OUT(ALGO_ID_E, exit_sske);
+ }
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- ret = 0;
- else
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ } else {
+ /* only using sha and md5 for rsa */
+ #ifndef NO_OLD_TLS
+ hashType = WC_HASH_TYPE_SHA;
+ if (ssl->suites->sigAlgo == rsa_sa_algo) {
+ hashType = WC_HASH_TYPE_MD5_SHA;
+ }
+ #else
+ ERROR_OUT(ALGO_ID_E, exit_sske);
+ #endif
+ }
- done_a:
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ /* Signature length will be written later, when we're sure what it is */
- return ret;
- }
- #endif /* HAVE_ECC */
+ #ifdef HAVE_FUZZER
+ if (ssl->fuzzerCb) {
+ ssl->fuzzerCb(ssl, args->output + preSigIdx,
+ preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+ }
+ #endif
- #if !defined(NO_DH) && !defined(NO_RSA)
- if (ssl->specs.kea == diffie_hellman_kea) {
- byte *output;
- word32 length = 0, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- word32 sigSz = 0, i = 0;
- word32 preSigSz = 0, preSigIdx = 0;
- RsaKey rsaKey;
- DhKey dhKey;
-
- if (ssl->buffers.serverDH_P.buffer == NULL ||
- ssl->buffers.serverDH_G.buffer == NULL)
- return NO_DH_PARAMS;
-
- if (ssl->buffers.serverDH_Pub.buffer == NULL) {
- ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Pub.buffer == NULL)
- return MEMORY_E;
- }
+ /* Assemble buffer to hash for signature */
+ args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+ args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (args->sigDataBuf == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+ RAN_LEN);
+ XMEMCPY(args->sigDataBuf+RAN_LEN,
+ ssl->arrays->serverRandom, RAN_LEN);
+ XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+ args->output + preSigIdx, preSigSz);
+
+ if (ssl->suites->sigAlgo != ed25519_sa_algo &&
+ ssl->suites->sigAlgo != ed448_sa_algo) {
+ ssl->buffers.sig.length =
+ wc_HashGetDigestSize(hashType);
+ if ((int)ssl->buffers.sig.length < 0) {
+ ERROR_OUT(HASH_TYPE_E, exit_sske);
+ }
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(
+ ssl->buffers.sig.length,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
- if (ssl->buffers.serverDH_Priv.buffer == NULL) {
- ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Priv.buffer == NULL)
- return MEMORY_E;
- }
+ /* Perform hash */
+ ret = wc_Hash(hashType, args->sigDataBuf,
+ args->sigDataSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- wc_InitDhKey(&dhKey);
- ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng,
- ssl->buffers.serverDH_Priv.buffer,
- &ssl->buffers.serverDH_Priv.length,
- ssl->buffers.serverDH_Pub.buffer,
- &ssl->buffers.serverDH_Pub.length);
- wc_FreeDhKey(&dhKey);
+ args->sigSz = args->tmpSigSz;
+
+ /* Sign hash to create signature */
+ switch (ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ case rsa_sa_algo:
+ {
+ /* For TLS 1.2 re-encode signature */
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte* encodedSig = (byte*)XMALLOC(
+ MAX_ENCODED_SIG_SZ, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+
+ ssl->buffers.sig.length =
+ wc_EncodeSignature(encodedSig,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ TypeHash(ssl->suites->hashAlgo));
+
+ /* Replace sig buffer with new one */
+ XFREE(ssl->buffers.sig.buffer, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ ssl->buffers.sig.buffer = encodedSig;
+ }
- if (ret != 0) return ret;
+ /* write sig size here */
+ c16toa((word16)args->sigSz,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ break;
+ }
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ /* write sig size here */
+ c16toa((word16)args->sigSz,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ break;
+ #endif
+ #endif /* !NO_RSA */
+ case ecc_dsa_sa_algo:
+ {
+ break;
+ }
+ #ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ ret = Ed25519CheckPubKey(ssl);
+ if (ret != 0)
+ goto exit_sske;
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ed448_sa_algo:
+ ret = Ed448CheckPubKey(ssl);
+ if (ret != 0)
+ goto exit_sske;
+ break;
+ #endif /* HAVE_ED448 */
+ } /* switch(ssl->specs.sig_algo) */
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #if !defined(NO_DH) && !defined(NO_RSA)
+ case diffie_hellman_kea:
+ {
+ enum wc_HashType hashType;
+
+ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ args->length = LENGTH_SZ * 3; /* p, g, pub */
+ args->length += ssl->buffers.serverDH_P.length +
+ ssl->buffers.serverDH_G.length +
+ ssl->buffers.serverDH_Pub.length;
+
+ preSigIdx = args->idx;
+ preSigSz = args->length;
+
+ if (!ssl->options.usingAnon_cipher) {
+ word16 keySz;
+
+ /* sig length */
+ args->length += LENGTH_SZ;
+
+ if (ssl->buffers.key == NULL) {
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+ keySz = (word32)GetPrivateKeySigSize(ssl);
+ else
+ #endif
+ ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+ }
+ else
+ {
+ if (ssl->buffers.keyType == 0)
+ ssl->buffers.keyType = rsa_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- length = LENGTH_SZ * 3; /* p, g, pub */
- length += ssl->buffers.serverDH_P.length +
- ssl->buffers.serverDH_G.length +
- ssl->buffers.serverDH_Pub.length;
+ if (keySz == 0) { /* test if keySz has error */
+ ERROR_OUT(keySz, exit_sske);
+ }
- preSigIdx = idx;
- preSigSz = length;
+ args->tmpSigSz = (word32)keySz;
+ args->length += args->tmpSigSz;
- if (!ssl->options.usingAnon_cipher) {
- ret = wc_InitRsaKey(&rsaKey, ssl->heap);
- if (ret != 0) return ret;
+ if (IsAtLeastTLSv1_2(ssl)) {
+ args->length += HASH_SIG_SIZE;
+ }
+ }
- /* sig length */
- length += LENGTH_SZ;
+ args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+ RECORD_HEADER_SZ;
- if (!ssl->buffers.key.buffer)
- return NO_PRIVATE_KEY;
+ #ifdef HAVE_QSH
+ args->length += args->qshSz;
+ args->sendSz += args->qshSz;
+ #endif
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ preSigIdx = args->idx;
+ }
+ #endif
- ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i, &rsaKey,
- ssl->buffers.key.length);
- if (ret == 0) {
- sigSz = wc_RsaEncryptSize(&rsaKey);
- length += sigSz;
- }
- else {
- wc_FreeRsaKey(&rsaKey);
- return ret;
- }
+ if (IsEncryptionOn(ssl, 1)) {
+ args->sendSz += MAX_MSG_EXTRA;
+ }
- if (IsAtLeastTLSv1_2(ssl))
- length += HASH_SIG_SIZE;
- }
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+ goto exit_sske;
+ }
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ /* get output buffer */
+ args->output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ AddHeaders(args->output, args->length,
+ server_key_exchange, ssl);
+
+ /* add p, g, pub */
+ c16toa((word16)ssl->buffers.serverDH_P.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length);
+ args->idx += ssl->buffers.serverDH_P.length;
+
+ /* g */
+ c16toa((word16)ssl->buffers.serverDH_G.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+ args->idx += ssl->buffers.serverDH_G.length;
+
+ /* pub */
+ c16toa((word16)ssl->buffers.serverDH_Pub.length,
+ args->output + args->idx);
+ args->idx += LENGTH_SZ;
+ XMEMCPY(args->output + args->idx,
+ ssl->buffers.serverDH_Pub.buffer,
+ ssl->buffers.serverDH_Pub.length);
+ args->idx += ssl->buffers.serverDH_Pub.length;
+
+ #ifdef HAVE_FUZZER
+ if (ssl->fuzzerCb) {
+ ssl->fuzzerCb(ssl, args->output + preSigIdx,
+ preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+ }
+ #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- preSigIdx = idx;
- }
- #endif
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
- /* check for available size */
- if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
- if (!ssl->options.usingAnon_cipher)
- wc_FreeRsaKey(&rsaKey);
- return ret;
- }
+ /* Determine hash type */
+ if (IsAtLeastTLSv1_2(ssl)) {
+ EncodeSigAlg(ssl->suites->hashAlgo,
+ ssl->suites->sigAlgo,
+ &args->output[args->idx]);
+ args->idx += 2;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.length;
+ hashType = HashAlgoToType(ssl->suites->hashAlgo);
+ if (hashType == WC_HASH_TYPE_NONE) {
+ ERROR_OUT(ALGO_ID_E, exit_sske);
+ }
+ } else {
+ /* only using sha and md5 for rsa */
+ #ifndef NO_OLD_TLS
+ hashType = WC_HASH_TYPE_SHA;
+ if (ssl->suites->sigAlgo == rsa_sa_algo) {
+ hashType = WC_HASH_TYPE_MD5_SHA;
+ }
+ #else
+ ERROR_OUT(ALGO_ID_E, exit_sske);
+ #endif
+ }
- AddHeaders(output, length, server_key_exchange, ssl);
+ /* signature size */
+ c16toa((word16)args->tmpSigSz, args->output + args->idx);
+ args->idx += LENGTH_SZ;
- /* add p, g, pub */
- c16toa((word16)ssl->buffers.serverDH_P.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length);
- idx += ssl->buffers.serverDH_P.length;
+ /* Assemble buffer to hash for signature */
+ args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+ args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (args->sigDataBuf == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+ RAN_LEN);
+ XMEMCPY(args->sigDataBuf+RAN_LEN,
+ ssl->arrays->serverRandom, RAN_LEN);
+ XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+ args->output + preSigIdx, preSigSz);
+
+ if (ssl->suites->sigAlgo != ed25519_sa_algo &&
+ ssl->suites->sigAlgo != ed448_sa_algo) {
+ ssl->buffers.sig.length =
+ wc_HashGetDigestSize(hashType);
+ ssl->buffers.sig.buffer = (byte*)XMALLOC(
+ ssl->buffers.sig.length, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (ssl->buffers.sig.buffer == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
- /* g */
- c16toa((word16)ssl->buffers.serverDH_G.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- idx += ssl->buffers.serverDH_G.length;
+ /* Perform hash */
+ ret = wc_Hash(hashType, args->sigDataBuf,
+ args->sigDataSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length);
+ if (ret != 0) {
+ goto exit_sske;
+ }
+ }
- /* pub */
- c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer,
- ssl->buffers.serverDH_Pub.length);
- idx += ssl->buffers.serverDH_Pub.length;
+ args->sigSz = args->tmpSigSz;
+
+ /* Sign hash to create signature */
+ switch (ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ case rsa_sa_algo:
+ {
+ /* For TLS 1.2 re-encode signature */
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte* encodedSig = (byte*)XMALLOC(
+ MAX_ENCODED_SIG_SZ, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+
+ ssl->buffers.sig.length =
+ wc_EncodeSignature(encodedSig,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ TypeHash(ssl->suites->hashAlgo));
+
+ /* Replace sig buffer with new one */
+ XFREE(ssl->buffers.sig.buffer, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ ssl->buffers.sig.buffer = encodedSig;
+ }
+ break;
+ }
+ #endif /* NO_RSA */
+ } /* switch (ssl->suites->sigAlgo) */
+ break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+ } /* switch(ssl->specs.kea) */
- #ifdef HAVE_FUZZER
- if (ssl->fuzzerCb)
- ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE,
- ssl->fuzzerCtx);
- #endif
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_sske;
+ }
- /* Add signature */
- if (!ssl->options.usingAnon_cipher) {
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = NULL;
- Sha* sha = NULL;
- #else
- Md5 md5[1];
- Sha sha[1];
- #endif
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- byte* hash = NULL;
- #else
- byte hash[FINISHED_SZ];
- #endif
- #ifndef NO_SHA256
- #ifdef WOLFSSL_SMALL_STACK
- Sha256* sha256 = NULL;
- byte* hash256 = NULL;
- #else
- Sha256 sha256[1];
- byte hash256[SHA256_DIGEST_SIZE];
- #endif
- #endif
- #ifdef WOLFSSL_SHA384
- #ifdef WOLFSSL_SMALL_STACK
- Sha384* sha384 = NULL;
- byte* hash384 = NULL;
- #else
- Sha384 sha384[1];
- byte hash384[SHA384_DIGEST_SIZE];
- #endif
- #endif
- #ifdef WOLFSSL_SHA512
- #ifdef WOLFSSL_SMALL_STACK
- Sha512* sha512 = NULL;
- byte* hash512 = NULL;
- #else
- Sha512 sha512[1];
- byte hash512[SHA512_DIGEST_SIZE];
- #endif
- #endif
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
- #ifndef NO_OLD_TLS
- byte doMd5 = 0;
- byte doSha = 0;
- #endif
- #ifndef NO_SHA256
- byte doSha256 = 0;
- #endif
- #ifdef WOLFSSL_SHA384
- byte doSha384 = 0;
- #endif
- #ifdef WOLFSSL_SHA512
- byte doSha512 = 0;
- #endif
+ case TLS_ASYNC_DO:
+ {
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)
+ case ecc_diffie_hellman_kea:
+ {
+ /* Sign hash to create signature */
+ switch (ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #endif
+ case rsa_sa_algo:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
+
+ ret = RsaSign(ssl,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ args->output + args->idx,
+ &args->sigSz,
+ ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+ key,
+ ssl->buffers.key
+ );
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ {
+ ecc_key* key = (ecc_key*)ssl->hsKey;
+
+ ret = EccSign(ssl,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ args->output + LENGTH_SZ + args->idx,
+ &args->sigSz,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ {
+ ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+ ret = Ed25519Sign(ssl,
+ args->sigDataBuf, args->sigDataSz,
+ args->output + LENGTH_SZ + args->idx,
+ &args->sigSz,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+ break;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ case ed448_sa_algo:
+ {
+ ed448_key* key = (ed448_key*)ssl->hsKey;
+
+ ret = Ed448Sign(ssl,
+ args->sigDataBuf, args->sigDataSz,
+ args->output + LENGTH_SZ + args->idx,
+ &args->sigSz,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+ break;
+ }
+ #endif
+ } /* switch(ssl->specs.sig_algo) */
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #if !defined(NO_DH) && !defined(NO_RSA)
+ case diffie_hellman_kea:
+ {
+ /* Sign hash to create signature */
+ switch (ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #endif
+ case rsa_sa_algo:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
- /* Add hash/signature algo ID */
- if (IsAtLeastTLSv1_2(ssl)) {
- byte setHash = 0;
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
- output[idx++] = ssl->suites->hashAlgo;
- output[idx++] = ssl->suites->sigAlgo;
+ ret = RsaSign(ssl,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ args->output + args->idx,
+ &args->sigSz,
+ ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+ key,
+ ssl->buffers.key
+ );
+ break;
+ }
+ #endif /* NO_RSA */
+ } /* switch (ssl->suites->sigAlgo) */
- switch (ssl->suites->hashAlgo) {
- case sha512_mac:
- #ifdef WOLFSSL_SHA512
- doSha512 = 1;
- setHash = 1;
- #endif
break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+ } /* switch(ssl->specs.kea) */
- case sha384_mac:
- #ifdef WOLFSSL_SHA384
- doSha384 = 1;
- setHash = 1;
- #endif
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_sske;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_VERIFY:
+ {
+ switch(ssl->specs.kea)
+ {
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ /* Nothing to do in this sub-state */
+ break;
+ }
+ #endif /* !NO_PSK */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ /* Nothing to do in this sub-state */
+ break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ /* Nothing to do in this sub-state */
break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ switch(ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #endif
+ case rsa_sa_algo:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
+
+ if (args->verifySig == NULL) {
+ if (args->sigSz == 0) {
+ ERROR_OUT(BAD_COND_E, exit_sske);
+ }
+ args->verifySig = (byte*)XMALLOC(
+ args->sigSz, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (!args->verifySig) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ XMEMCPY(args->verifySig,
+ args->output + args->idx, args->sigSz);
+ }
- case sha256_mac:
- #ifndef NO_SHA256
- doSha256 = 1;
- setHash = 1;
+ /* check for signature faults */
+ ret = VerifyRsaSign(ssl,
+ args->verifySig, args->sigSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+ key, ssl->buffers.key
+ );
+ break;
+ }
#endif
+ case ecc_dsa_sa_algo:
+ #ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ #endif
+ #ifdef HAVE_ED448
+ case ed448_sa_algo:
+ #endif
+ {
+ /* Now that we know the real sig size, write it. */
+ c16toa((word16)args->sigSz,
+ args->output + args->idx);
+
+ /* And adjust length and sendSz from estimates */
+ args->length += args->sigSz - args->tmpSigSz;
+ args->sendSz += args->sigSz - args->tmpSigSz;
+ break;
+ }
+ default:
+ ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */
+ } /* switch(ssl->specs.sig_algo) */
break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #if !defined(NO_DH) && !defined(NO_RSA)
+ case diffie_hellman_kea:
+ {
+ switch (ssl->suites->sigAlgo)
+ {
+ #ifndef NO_RSA
+ #ifndef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ #endif
+ case rsa_sa_algo:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
- case sha_mac:
- #ifndef NO_OLD_TLS
- doSha = 1;
- setHash = 1;
+ if (ssl->options.usingAnon_cipher) {
+ break;
+ }
+
+ if (args->verifySig == NULL) {
+ if (args->sigSz == 0) {
+ ERROR_OUT(BAD_COND_E, exit_sske);
+ }
+ args->verifySig = (byte*)XMALLOC(
+ args->sigSz, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (!args->verifySig) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ XMEMCPY(args->verifySig,
+ args->output + args->idx, args->sigSz);
+ }
+
+ /* check for signature faults */
+ ret = VerifyRsaSign(ssl,
+ args->verifySig, args->sigSz,
+ ssl->buffers.sig.buffer,
+ ssl->buffers.sig.length,
+ ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+ key, ssl->buffers.key
+ );
+ break;
+ }
#endif
+ } /* switch (ssl->suites->sigAlgo) */
break;
+ }
+ #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+ } /* switch(ssl->specs.kea) */
- default:
- WOLFSSL_MSG("Bad hash sig algo");
- break;
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_sske;
}
- if (setHash == 0) {
- wc_FreeRsaKey(&rsaKey);
- return ALGO_ID_E;
- }
- } else {
- /* only using sha and md5 for rsa */
- #ifndef NO_OLD_TLS
- doSha = 1;
- if (ssl->suites->sigAlgo == rsa_sa_algo) {
- doMd5 = 1;
- }
- #else
- wc_FreeRsaKey(&rsaKey);
- return ALGO_ID_E;
- #endif
- }
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ FALL_THROUGH;
- /* signature size */
- c16toa((word16)sigSz, output + idx);
- idx += LENGTH_SZ;
+ case TLS_ASYNC_FINALIZE:
+ {
+ #ifdef HAVE_QSH
+ if (ssl->peerQSHKeyPresent) {
+ if (args->qshSz > 0) {
+ args->idx = args->sendSz - args->qshSz;
+ if (QSH_KeyExchangeWrite(ssl, 1) != 0) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
- /* do signature */
- #ifdef WOLFSSL_SMALL_STACK
- hash = (byte*)XMALLOC(FINISHED_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (hash == NULL)
- return MEMORY_E; /* No heap commitment before this point,
- from now on, the resources are freed
- at done_b. */
- #endif
+ /* extension type */
+ c16toa(TLSX_QUANTUM_SAFE_HYBRID,
+ args->output + args->idx);
+ args->idx += OPAQUE16_LEN;
- #ifndef NO_OLD_TLS
- /* md5 */
- #ifdef WOLFSSL_SMALL_STACK
- if (doMd5) {
- md5 = (Md5*)XMALLOC(sizeof(Md5), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (md5 == NULL)
- ERROR_OUT(MEMORY_E, done_b);
+ /* write to output and check amount written */
+ if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+ args->output + args->idx) >
+ args->qshSz - OPAQUE16_LEN) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
+ }
}
#endif
- if (doMd5) {
- wc_InitMd5(md5);
- wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
- wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
- wc_Md5Update(md5, output + preSigIdx, preSigSz);
- wc_Md5Final(md5, hash);
- }
- /* sha */
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha) {
- sha = (Sha*)XMALLOC(sizeof(Sha), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha == NULL)
- ERROR_OUT(MEMORY_E, done_b);
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ if (ssl->specs.kea == ecdhe_psk_kea ||
+ ssl->specs.kea == ecc_diffie_hellman_kea) {
+ /* Check output to make sure it was set */
+ if (args->output) {
+ AddHeaders(args->output, args->length,
+ server_key_exchange, ssl);
+ }
+ else {
+ ERROR_OUT(BUFFER_ERROR, exit_sske);
+ }
}
- #endif
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+ if (IsEncryptionOn(ssl, 1)) {
+ args->inputSz = args->length + HANDSHAKE_HEADER_SZ;
+ /* buildmsg adds rechdr */
+ args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ if (args->input == NULL) {
+ ERROR_OUT(MEMORY_E, exit_sske);
+ }
- if (doSha) {
- if ((ret = wc_InitSha(sha)) != 0)
- goto done_b;
- wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
- wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
- wc_ShaUpdate(sha, output + preSigIdx, preSigSz);
- wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]);
- }
- #endif
+ if (args->output == NULL) {
+ ERROR_OUT(BUFFER_ERROR, exit_sske);
+ }
- #ifndef NO_SHA256
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha256) {
- sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha256 == NULL || hash256 == NULL)
- ERROR_OUT(MEMORY_E, done_b);
+ XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+ args->inputSz);
+ ret = BuildMessage(ssl, args->output, args->sendSz,
+ args->input, args->inputSz, handshake, 1, 0, 0);
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
+ /* make sure its not double free'd on cleanup */
+
+ if (ret >= 0) {
+ args->sendSz = ret;
+ ret = 0;
+ }
}
- #endif
-
- if (doSha256) {
- if (!(ret = wc_InitSha256(sha256))
- && !(ret = wc_Sha256Update(sha256,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha256Update(sha256,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha256Update(sha256,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha256Final(sha256, hash256);
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl,
+ args->output, args->sendSz)) != 0) {
+ goto exit_sske;
+ }
+ }
- if (ret != 0) goto done_b;
- }
- #endif
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
- #ifdef WOLFSSL_SHA384
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha384) {
- sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha384 == NULL || hash384 == NULL)
- ERROR_OUT(MEMORY_E, done_b);
+ ret = HashOutput(ssl, args->output, args->sendSz, 0);
+ if (ret != 0) {
+ goto exit_sske;
+ }
}
- #endif
-
- if (doSha384) {
- if (!(ret = wc_InitSha384(sha384))
- && !(ret = wc_Sha384Update(sha384,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha384Update(sha384,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha384Update(sha384,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha384Final(sha384, hash384);
- if (ret != 0) goto done_b;
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn) {
+ AddPacketName(ssl, "ServerKeyExchange");
}
- #endif
-
- #ifdef WOLFSSL_SHA512
- #ifdef WOLFSSL_SMALL_STACK
- if (doSha512) {
- sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sha512 == NULL || hash512 == NULL)
- ERROR_OUT(MEMORY_E, done_b);
+ if (ssl->toInfoOn) {
+ AddPacketInfo(ssl, "ServerKeyExchange", handshake,
+ args->output, args->sendSz, WRITE_PROTO, ssl->heap);
}
#endif
- if (doSha512) {
- if (!(ret = wc_InitSha512(sha512))
- && !(ret = wc_Sha512Update(sha512,
- ssl->arrays->clientRandom, RAN_LEN))
- && !(ret = wc_Sha512Update(sha512,
- ssl->arrays->serverRandom, RAN_LEN))
- && !(ret = wc_Sha512Update(sha512,
- output + preSigIdx, preSigSz)))
- ret = wc_Sha512Final(sha512, hash512);
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_END;
+ } /* case TLS_ASYNC_FINALIZE */
+ FALL_THROUGH;
- if (ret != 0) goto done_b;
+ case TLS_ASYNC_END:
+ {
+ ssl->buffers.outputBuffer.length += args->sendSz;
+ if (!ssl->options.groupMessages) {
+ ret = SendBuffered(ssl);
}
- #endif
- #ifndef NO_RSA
- if (ssl->suites->sigAlgo == rsa_sa_algo) {
- byte* signBuffer = hash;
- word32 signSz = FINISHED_SZ;
- #ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig = NULL;
- #else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- #endif
- byte doUserRsa = 0;
-
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaSignCb)
- doUserRsa = 1;
- #endif
-
- #ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL)
- ERROR_OUT(MEMORY_E, done_b);
- #endif
-
- if (IsAtLeastTLSv1_2(ssl)) {
- byte* digest = &hash[MD5_DIGEST_SIZE];
- int typeH = SHAh;
- int digestSz = SHA_DIGEST_SIZE;
-
- if (ssl->suites->hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = hash256;
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = hash384;
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- #endif
- }
- else if (ssl->suites->hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = hash512;
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- #endif
- }
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ break;
+ }
+ default:
+ ret = INPUT_CASE_ERROR;
+ } /* switch(ssl->options.asyncState) */
- if (digest == NULL) {
- ret = ALGO_ID_E;
- } else {
- signSz = wc_EncodeSignature(encodedSig, digest,
- digestSz, typeH);
- signBuffer = encodedSig;
- }
- }
- if (doUserRsa && ret == 0) {
- #ifdef HAVE_PK_CALLBACKS
- word32 ioLen = sigSz;
- ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
- output + idx, &ioLen,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->RsaSignCtx);
- #endif
- } else if (ret == 0) {
- ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx,
- sigSz, &rsaKey, ssl->rng);
- }
+ exit_sske:
- wc_FreeRsaKey(&rsaKey);
+ WOLFSSL_LEAVE("SendServerKeyExchange", ret);
+ WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- }
- #endif
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E)
+ return ret;
+ #endif /* WOLFSSL_ASYNC_CRYPT */
- done_b:
- #ifdef WOLFSSL_SMALL_STACK
- #ifndef NO_OLD_TLS
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #ifndef NO_SHA256
- XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA384
- XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #ifdef WOLFSSL_SHA512
- XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #endif
+ /* Final cleanup */
+ FreeSskeArgs(ssl, args);
+ FreeKeyExchange(ssl);
- if (ret < 0) return ret;
- }
+ return ret;
+ }
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return ret;
- #endif
+#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \
+ defined(OPENSSL_ALL)
- if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0)
- return ret;
+ /* search suites for specific one, idx on success, negative on error */
+#ifndef WOLFSSL_TLS13
+ static
+#endif
+ int FindSuite(Suites* suites, byte first, byte second)
+ {
+ int i;
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
+ if (suites == NULL || suites->suiteSz == 0) {
+ WOLFSSL_MSG("Suites pointer error or suiteSz 0");
+ return SUITES_ERROR;
+ }
- ssl->buffers.outputBuffer.length += sendSz;
- if (ssl->options.groupMessages)
- ret = 0;
- else
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
+ if (suites->suites[i] == first &&
+ suites->suites[i+1] == second )
+ return i;
}
- #endif /* NO_DH */
- return ret;
- #undef ERROR_OUT
+ return MATCH_SUITE_ERROR;
}
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
/* Make sure server cert/key are valid for this suite, true on success */
static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
@@ -12903,10 +26005,10 @@ int DoSessionTicket(WOLFSSL* ssl,
}
}
- if (CipherRequires(first, second, REQUIRES_ECC_DSA)) {
- WOLFSSL_MSG("Requires ECCDSA");
- if (ssl->options.haveECDSAsig == 0) {
- WOLFSSL_MSG("Don't have ECCDSA");
+ if (CipherRequires(first, second, REQUIRES_ECC)) {
+ WOLFSSL_MSG("Requires ECC");
+ if (ssl->options.haveECC == 0) {
+ WOLFSSL_MSG("Don't have ECC");
return 0;
}
}
@@ -12944,56 +26046,128 @@ int DoSessionTicket(WOLFSSL* ssl,
}
}
-#ifdef HAVE_SUPPORTED_CURVES
- if (!TLSX_ValidateEllipticCurves(ssl, first, second)) {
- WOLFSSL_MSG("Don't have matching curves");
+#if !defined(WOLFSSL_OLDTLS_AEAD_CIPHERSUITES)
+ if (CipherRequires(first, second, REQUIRES_AEAD)) {
+ WOLFSSL_MSG("Requires AEAD");
+ if (ssl->version.major == SSLv3_MAJOR &&
+ ssl->version.minor < TLSv1_2_MINOR) {
+ WOLFSSL_MSG("Version of SSL does not support AEAD ciphers");
return 0;
+ }
+
+ }
+#endif
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)
+ if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
+ WOLFSSL_MSG("Don't have matching curves");
+ return 0;
}
#endif
/* ECCDHE is always supported if ECC on */
+#ifdef HAVE_QSH
+ /* need to negotiate a classic suite in addition to TLS_QSH */
+ if (first == QSH_BYTE && second == TLS_QSH) {
+ if (TLSX_SupportExtensions(ssl)) {
+ ssl->options.haveQSH = 1; /* matched TLS_QSH */
+ }
+ else {
+ WOLFSSL_MSG("Version of SSL connection does not support "
+ "TLS_QSH");
+ }
+ return 0;
+ }
+#endif
+
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version) &&
+ ssl->options.side == WOLFSSL_SERVER_END) {
+ /* Try to establish a key share. */
+ int ret = TLSX_KeyShare_Establish(ssl);
+ if (ret == KEY_SHARE_ERROR)
+ ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+ else if (ret != 0)
+ return 0;
+ }
+ else if (first == TLS13_BYTE || (first == ECC_BYTE &&
+ (second == TLS_SHA256_SHA256 || second == TLS_SHA384_SHA384))) {
+ /* Can't negotiate TLS 1.3 cipher suites with lower protocol
+ * version. */
+ return 0;
+ }
+#endif
+
return 1;
}
+#ifndef NO_WOLFSSL_SERVER
+ static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i,
+ word16 j)
+ {
+ if (ssl->suites->suites[i] == peerSuites->suites[j] &&
+ ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
+
+ if (VerifyServerSuite(ssl, i)) {
+ int result;
+ WOLFSSL_MSG("Verified suite validity");
+ ssl->options.cipherSuite0 = ssl->suites->suites[i];
+ ssl->options.cipherSuite = ssl->suites->suites[i+1];
+ result = SetCipherSpecs(ssl);
+ if (result == 0) {
+ result = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
+ peerSuites->hashSigAlgoSz);
+ }
+ return result;
+ }
+ else {
+ WOLFSSL_MSG("Could not verify suite validity, continue");
+ }
+ }
- static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
+ return MATCH_SUITE_ERROR;
+ }
+
+ int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
{
+ int ret;
word16 i, j;
WOLFSSL_ENTER("MatchSuite");
/* & 0x1 equivalent % 2 */
if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
- return MATCH_SUITE_ERROR;
+ return BUFFER_ERROR;
if (ssl->suites == NULL)
return SUITES_ERROR;
- /* start with best, if a match we are good */
- for (i = 0; i < ssl->suites->suiteSz; i += 2)
- for (j = 0; j < peerSuites->suiteSz; j += 2)
- if (ssl->suites->suites[i] == peerSuites->suites[j] &&
- ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
-
- if (VerifyServerSuite(ssl, i)) {
- int result;
- WOLFSSL_MSG("Verified suite validity");
- ssl->options.cipherSuite0 = ssl->suites->suites[i];
- ssl->options.cipherSuite = ssl->suites->suites[i+1];
- result = SetCipherSpecs(ssl);
- if (result == 0)
- PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
- peerSuites->hashSigAlgoSz);
- return result;
- }
- else {
- WOLFSSL_MSG("Could not verify suite validity, continue");
- }
+
+ if (!ssl->options.useClientOrder) {
+ /* Server order */
+ for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+ for (j = 0; j < peerSuites->suiteSz; j += 2) {
+ ret = CompareSuites(ssl, peerSuites, i, j);
+ if (ret != MATCH_SUITE_ERROR)
+ return ret;
+ }
+ }
+ }
+ else {
+ /* Client order */
+ for (j = 0; j < peerSuites->suiteSz; j += 2) {
+ for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+ ret = CompareSuites(ssl, peerSuites, i, j);
+ if (ret != MATCH_SUITE_ERROR)
+ return ret;
}
+ }
+ }
return MATCH_SUITE_ERROR;
}
-
+#endif
#ifdef OLD_HELLO_ALLOWED
@@ -13007,12 +26181,13 @@ int DoSessionTicket(WOLFSSL* ssl,
word16 i, j;
ProtocolVersion pv;
Suites clSuites;
+ int ret = -1;
(void)inSz;
WOLFSSL_MSG("Got old format client hello");
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
- AddPacketName("ClientHello", &ssl->handShakeInfo);
+ AddPacketName(ssl, "ClientHello");
if (ssl->toInfoOn)
AddLateName("ClientHello", &ssl->timeoutInfo);
#endif
@@ -13046,62 +26221,71 @@ int DoSessionTicket(WOLFSSL* ssl,
if (ssl->version.minor > pv.minor) {
byte haveRSA = 0;
byte havePSK = 0;
+ int keySz = 0;
+
if (!ssl->options.downgrade) {
WOLFSSL_MSG("Client trying to connect with lesser version");
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
- WOLFSSL_MSG(" version below minimum allowed, fatal error");
+ WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
- WOLFSSL_MSG(" downgrading to SSLv3");
+ WOLFSSL_MSG("\tdowngrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
- WOLFSSL_MSG(" downgrading to TLSv1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1");
/* turn off tls 1.1+ */
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
- WOLFSSL_MSG(" downgrading to TLSv1.1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
+ else if (pv.minor == TLSv1_2_MINOR) {
+ WOLFSSL_MSG(" downgrading to TLSv1.2");
+ ssl->version.minor = TLSv1_2_MINOR;
+ }
#ifndef NO_RSA
haveRSA = 1;
#endif
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
+#ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+#endif
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
}
/* suite size */
ato16(&input[idx], &clSuites.suiteSz);
- idx += 2;
+ idx += OPAQUE16_LEN;
- if (clSuites.suiteSz > MAX_SUITE_SZ)
+ if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
return BUFFER_ERROR;
clSuites.hashSigAlgoSz = 0;
/* session size */
ato16(&input[idx], &sessionSz);
- idx += 2;
+ idx += OPAQUE16_LEN;
if (sessionSz > ID_LEN)
return BUFFER_ERROR;
/* random size */
ato16(&input[idx], &randomSz);
- idx += 2;
+ idx += OPAQUE16_LEN;
if (randomSz > RAN_LEN)
return BUFFER_ERROR;
@@ -13110,10 +26294,10 @@ int DoSessionTicket(WOLFSSL* ssl,
for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
byte first = input[idx++];
if (!first) { /* implicit: skip sslv2 type */
- XMEMCPY(&clSuites.suites[j], &input[idx], 2);
- j += 2;
+ XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN);
+ j += SUITE_LEN;
}
- idx += 2;
+ idx += SUITE_LEN;
}
clSuites.suiteSz = j;
@@ -13136,14 +26320,14 @@ int DoSessionTicket(WOLFSSL* ssl,
ssl->options.usingCompression = 0; /* turn off */
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+ ssl->cbmode = SSL_CB_MODE_WRITE;
*inOutIdx = idx;
ssl->options.haveSessionId = 1;
/* DoClientHello uses same resume code */
if (ssl->options.resuming) { /* let's try */
- int ret = -1;
WOLFSSL_SESSION* session = GetSession(ssl,
- ssl->arrays->masterSecret);
+ ssl->arrays->masterSecret, 1);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
@@ -13154,13 +26338,13 @@ int DoSessionTicket(WOLFSSL* ssl,
WOLFSSL_MSG("Session lookup for resume failed");
ssl->options.resuming = 0;
} else {
+ #ifdef HAVE_EXT_CACHE
+ wolfSSL_SESSION_free(session);
+ #endif
if (MatchSuite(ssl, &clSuites) < 0) {
WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
return UNSUPPORTED_SUITE;
}
- #ifdef SESSION_CERTS
- ssl->session = *session; /* restore session certs. */
- #endif
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
@@ -13183,79 +26367,299 @@ int DoSessionTicket(WOLFSSL* ssl,
}
}
- return MatchSuite(ssl, &clSuites);
+ ret = MatchSuite(ssl, &clSuites);
+ if (ret != 0)return ret;
+ return SanityCheckMsgReceived(ssl, client_hello);
}
#endif /* OLD_HELLO_ALLOWED */
+#ifndef WOLFSSL_NO_TLS12
+
+ int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites)
+ {
+ int ret = 0;
+ WOLFSSL_SESSION* session;
+
+ (void)bogusID;
+
+ session = GetSession(ssl, ssl->arrays->masterSecret, 1);
+ #ifdef HAVE_SESSION_TICKET
+ if (ssl->options.useTicket == 1) {
+ session = &ssl->session;
+ } else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
+ WOLFSSL_MSG("Bogus session ID without session ticket");
+ return BUFFER_ERROR;
+ }
+ #endif
+
+ if (!session) {
+ WOLFSSL_MSG("Session lookup for resume failed");
+ ssl->options.resuming = 0;
+ }
+ else if (session->haveEMS != ssl->options.haveEMS) {
+ /* RFC 7627, 5.3, server-side */
+ /* if old sess didn't have EMS, but new does, full handshake */
+ if (!session->haveEMS && ssl->options.haveEMS) {
+ WOLFSSL_MSG("Attempting to resume a session that didn't "
+ "use EMS with a new session with EMS. Do full "
+ "handshake.");
+ ssl->options.resuming = 0;
+ }
+ /* if old sess used EMS, but new doesn't, MUST abort */
+ else if (session->haveEMS && !ssl->options.haveEMS) {
+ WOLFSSL_MSG("Trying to resume a session with EMS without "
+ "using EMS");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ #endif
+ return EXT_MASTER_SECRET_NEEDED_E;
+ }
+ #ifdef HAVE_EXT_CACHE
+ wolfSSL_SESSION_free(session);
+ #endif
+ }
+ else {
+ #ifndef NO_RESUME_SUITE_CHECK
+ int j;
+
+ /* Check client suites include the one in session */
+ for (j = 0; j < clSuites->suiteSz; j += 2) {
+ if (clSuites->suites[j] == session->cipherSuite0 &&
+ clSuites->suites[j+1] == session->cipherSuite) {
+ break;
+ }
+ }
+ if (j == clSuites->suiteSz) {
+ WOLFSSL_MSG("Prev session's cipher suite not in ClientHello");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ return UNSUPPORTED_SUITE;
+ }
+ #endif
+
+ #ifdef HAVE_EXT_CACHE
+ wolfSSL_SESSION_free(session);
+ #endif
+ if (MatchSuite(ssl, clSuites) < 0) {
+ WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
+ return UNSUPPORTED_SUITE;
+ }
+
+ ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+ RAN_LEN);
+ if (ret != 0)
+ return ret;
- static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+ #ifdef NO_OLD_TLS
+ ret = DeriveTlsKeys(ssl);
+ #else
+ #ifndef NO_TLS
+ if (ssl->options.tls)
+ ret = DeriveTlsKeys(ssl);
+ #endif
+ if (!ssl->options.tls)
+ ret = DeriveKeys(ssl);
+ #endif
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ }
+
+ return ret;
+ }
+
+
+ /* handle processing of client_hello (1) */
+ int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
{
byte b;
+ byte bogusID = 0; /* flag for a bogus session id */
ProtocolVersion pv;
Suites clSuites;
word32 i = *inOutIdx;
word32 begin = i;
+ int ret = 0;
+#ifdef WOLFSSL_DTLS
+ Hmac cookieHmac;
+ byte peerCookie[MAX_COOKIE_LEN];
+ byte peerCookieSz = 0;
+ byte cookieType;
+ byte cookieSz = 0;
+
+ XMEMSET(&cookieHmac, 0, sizeof(Hmac));
+#endif /* WOLFSSL_DTLS */
+
+ WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
+ WOLFSSL_ENTER("DoClientHello");
#ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
#endif
-
/* protocol version, random and session id length check */
- if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+ if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
/* protocol version */
XMEMCPY(&pv, input + i, OPAQUE16_LEN);
ssl->chVersion = pv; /* store */
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ #if defined(NO_SHA) && defined(NO_SHA256)
+ #error "DTLS needs either SHA or SHA-256"
+ #endif /* NO_SHA && NO_SHA256 */
+
+ #if !defined(NO_SHA) && defined(NO_SHA256)
+ cookieType = WC_SHA;
+ cookieSz = WC_SHA_DIGEST_SIZE;
+ #endif /* NO_SHA */
+ #ifndef NO_SHA256
+ cookieType = WC_SHA256;
+ cookieSz = WC_SHA256_DIGEST_SIZE;
+ #endif /* NO_SHA256 */
+ ret = wc_HmacSetKey(&cookieHmac, cookieType,
+ ssl->buffers.dtlsCookieSecret.buffer,
+ ssl->buffers.dtlsCookieSecret.length);
+ if (ret != 0) return ret;
+ ret = wc_HmacUpdate(&cookieHmac,
+ (const byte*)ssl->buffers.dtlsCtx.peer.sa,
+ ssl->buffers.dtlsCtx.peer.sz);
+ if (ret != 0) return ret;
+ ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
+ if (ret != 0) return ret;
+ }
+#endif /* WOLFSSL_DTLS */
i += OPAQUE16_LEN;
- if (ssl->version.minor > pv.minor) {
- byte haveRSA = 0;
- byte havePSK = 0;
+ /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
+ if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
+ pv.minor = TLSv1_2_MINOR;
+
+ if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
+ (ssl->options.dtls && ssl->version.minor != DTLS_MINOR
+ && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
+ && pv.minor != DTLSv1_2_MINOR)) {
+
+ word16 haveRSA = 0;
+ word16 havePSK = 0;
+ int keySz = 0;
if (!ssl->options.downgrade) {
WOLFSSL_MSG("Client trying to connect with lesser version");
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
- WOLFSSL_MSG(" version below minimum allowed, fatal error");
+ WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
- WOLFSSL_MSG(" downgrading to SSLv3");
+ WOLFSSL_MSG("\tdowngrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
/* turn off tls 1.1+ */
- WOLFSSL_MSG(" downgrading to TLSv1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1");
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
- WOLFSSL_MSG(" downgrading to TLSv1.1");
+ WOLFSSL_MSG("\tdowngrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
+ else if (pv.minor == TLSv1_2_MINOR) {
+ WOLFSSL_MSG(" downgrading to TLSv1.2");
+ ssl->version.minor = TLSv1_2_MINOR;
+ }
#ifndef NO_RSA
haveRSA = 1;
#endif
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
+#ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+#endif
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
+
+#ifdef OPENSSL_EXTRA
+ /* 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 &&
+ ssl->options.mask > 0) {
+ int reset = 0;
+ if (ssl->version.minor == TLSv1_2_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+ WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+ ssl->version.minor = TLSv1_1_MINOR;
+ reset = 1;
+ }
+ if (ssl->version.minor == TLSv1_1_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+ WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = TLSv1_MINOR;
+ reset = 1;
+ }
+ if (ssl->version.minor == TLSv1_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_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;
+ reset = 1;
+ }
+ if (ssl->version.minor == SSLv3_MINOR &&
+ (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+ WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+ return VERSION_ERROR;
+ }
+
+ if (ssl->version.minor < ssl->options.minDowngrade) {
+ WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+ return VERSION_ERROR;
+ }
+
+ if (reset) {
+ word16 haveRSA = 0;
+ word16 havePSK = 0;
+ int keySz = 0;
+
+ #ifndef NO_RSA
+ haveRSA = 1;
+ #endif
+ #ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+ #endif
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
+
+ /* reset cipher suites to account for TLS version change */
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
}
+#endif
/* random */
XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
+ if (ret != 0) return ret;
+ }
+#endif /* WOLFSSL_DTLS */
i += RAN_LEN;
#ifdef SHOW_SECRETS
@@ -13271,13 +26675,26 @@ int DoSessionTicket(WOLFSSL* ssl,
/* session id */
b = input[i++];
- if (b == ID_LEN) {
- if ((i - begin) + ID_LEN > helloSz)
+#ifdef HAVE_SESSION_TICKET
+ if (b > 0 && b < ID_LEN) {
+ bogusID = 1;
+ WOLFSSL_MSG("Client sent bogus session id, let's allow for echo");
+ }
+#endif
+
+ if (b == ID_LEN || bogusID) {
+ if ((i - begin) + b > helloSz)
return BUFFER_ERROR;
- XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
- ssl->arrays->sessionIDSz = ID_LEN;
- i += ID_LEN;
+ XMEMCPY(ssl->arrays->sessionID, input + i, b);
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+ if (ret != 0) return ret;
+ }
+#endif /* WOLFSSL_DTLS */
+ ssl->arrays->sessionIDSz = b;
+ i += b;
ssl->options.resuming = 1; /* client wants to resume */
WOLFSSL_MSG("Client wants to resume session");
}
@@ -13293,30 +26710,18 @@ int DoSessionTicket(WOLFSSL* ssl,
if ((i - begin) + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
- b = input[i++];
-
- if (b) {
- byte cookie[MAX_COOKIE_LEN];
+ peerCookieSz = input[i++];
- if (b > MAX_COOKIE_LEN)
+ if (peerCookieSz) {
+ if (peerCookieSz > MAX_COOKIE_LEN)
return BUFFER_ERROR;
- if ((i - begin) + b > helloSz)
+ if ((i - begin) + peerCookieSz > helloSz)
return BUFFER_ERROR;
- if (ssl->ctx->CBIOCookie == NULL) {
- WOLFSSL_MSG("Your Cookie callback is null, please set");
- return COOKIE_ERROR;
- }
-
- if ((ssl->ctx->CBIOCookie(ssl, cookie, COOKIE_SZ,
- ssl->IOCB_CookieCtx) != COOKIE_SZ)
- || (b != COOKIE_SZ)
- || (XMEMCMP(cookie, input + i, b) != 0)) {
- return COOKIE_ERROR;
- }
+ XMEMCPY(peerCookie, input + i, peerCookieSz);
- i += b;
+ i += peerCookieSz;
}
}
#endif
@@ -13332,10 +26737,49 @@ int DoSessionTicket(WOLFSSL* ssl,
if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
- if (clSuites.suiteSz > MAX_SUITE_SZ)
+ if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
return BUFFER_ERROR;
XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+ /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+ if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
+ TLSX* extension;
+
+ /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+ ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
+ if (ret != WOLFSSL_SUCCESS)
+ return ret;
+
+ extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
+ if (extension) {
+ ssl->secure_renegotiation =
+ (SecureRenegotiation*)extension->data;
+ ssl->secure_renegotiation->enabled = 1;
+ }
+ }
+#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
+#if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL)
+ /* check for TLS_FALLBACK_SCSV suite */
+ if (FindSuite(&clSuites, TLS_FALLBACK_SCSV, 0) >= 0) {
+ WOLFSSL_MSG("Found Fallback SCSV");
+ if (ssl->ctx->method->version.minor > pv.minor) {
+ WOLFSSL_MSG("Client trying to connect with lesser version");
+ SendAlert(ssl, alert_fatal, inappropriate_fallback);
+ return VERSION_ERROR;
+ }
+ }
+#endif
+
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = wc_HmacUpdate(&cookieHmac,
+ input + i - OPAQUE16_LEN,
+ clSuites.suiteSz + OPAQUE16_LEN);
+ if (ret != 0) return ret;
+ }
+#endif /* WOLFSSL_DTLS */
i += clSuites.suiteSz;
clSuites.hashSigAlgoSz = 0;
@@ -13345,37 +26789,106 @@ int DoSessionTicket(WOLFSSL* ssl,
if ((i - begin) + b > helloSz)
return BUFFER_ERROR;
- if (ssl->options.usingCompression) {
- int match = 0;
+ if (b == 0) {
+ WOLFSSL_MSG("No compression types in list");
+#ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, decode_error);
+#endif
+ return COMPRESSION_ERROR;
+ }
+
+#ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ byte newCookie[MAX_COOKIE_LEN];
+
+ ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+ if (ret != 0) return ret;
+ ret = wc_HmacFinal(&cookieHmac, newCookie);
+ if (ret != 0) return ret;
+
+ /* If a cookie callback is set, call it to overwrite the cookie.
+ * This should be deprecated. The code now calculates the cookie
+ * using an HMAC as expected. */
+ if (ssl->ctx->CBIOCookie != NULL &&
+ ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
+ ssl->IOCB_CookieCtx) != cookieSz) {
+ return COOKIE_ERROR;
+ }
+
+ /* Check the cookie, see if we progress the state machine. */
+ if (peerCookieSz != cookieSz ||
+ XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
+
+ /* Send newCookie to client in a HelloVerifyRequest message
+ * and let the state machine alone. */
+ ssl->msgsReceived.got_client_hello = 0;
+ ssl->keys.dtls_handshake_number = 0;
+ ssl->keys.dtls_expected_peer_handshake_number = 0;
+ *inOutIdx += helloSz;
+ return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
+ }
+
+ /* This was skipped in the DTLS case so we could handle the hello
+ * verify request. */
+ ret = HashInput(ssl, input + *inOutIdx, helloSz);
+ if (ret != 0) return ret;
+ }
+#endif /* WOLFSSL_DTLS */
+
+ {
+ /* compression match types */
+ int matchNo = 0;
+ int matchZlib = 0;
while (b--) {
byte comp = input[i++];
- if (comp == ZLIB_COMPRESSION)
- match = 1;
+ if (comp == NO_COMPRESSION) {
+ matchNo = 1;
+ }
+ if (comp == ZLIB_COMPRESSION) {
+ matchZlib = 1;
+ }
}
- if (!match) {
- WOLFSSL_MSG("Not matching compression, turning off");
+ if (ssl->options.usingCompression == 0 && matchNo) {
+ WOLFSSL_MSG("Matched No Compression");
+ } else if (ssl->options.usingCompression && matchZlib) {
+ WOLFSSL_MSG("Matched zlib Compression");
+ } else if (ssl->options.usingCompression && matchNo) {
+ WOLFSSL_MSG("Could only match no compression, turning off");
ssl->options.usingCompression = 0; /* turn off */
+ } else {
+ WOLFSSL_MSG("Could not match compression");
+#ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+#endif
+ return COMPRESSION_ERROR;
}
}
- else
- i += b; /* ignore, since we're not on */
*inOutIdx = i;
/* tls extensions */
if ((i - begin) < helloSz) {
#ifdef HAVE_TLS_EXTENSIONS
- if (TLSX_SupportExtensions(ssl)) {
- int ret = 0;
+ #ifdef HAVE_QSH
+ QSH_Init(ssl);
+ #endif
+ if (TLSX_SupportExtensions(ssl))
#else
- if (IsAtLeastTLSv1_2(ssl)) {
+ if (IsAtLeastTLSv1_2(ssl))
#endif
+ {
/* Process the hello extension. Skip unsupported. */
word16 totalExtSz;
+#ifdef HAVE_TLS_EXTENSIONS
+ /* auto populate extensions supported unless user defined */
+ if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
+ return ret;
+#endif
+
if ((i - begin) + OPAQUE16_LEN > helloSz)
return BUFFER_ERROR;
@@ -13386,9 +26899,23 @@ int DoSessionTicket(WOLFSSL* ssl,
return BUFFER_ERROR;
#ifdef HAVE_TLS_EXTENSIONS
- if ((ret = TLSX_Parse(ssl, (byte *) input + i,
- totalExtSz, 1, &clSuites)))
+ /* tls extensions */
+ if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
+ client_hello, &clSuites)))
return ret;
+ #ifdef WOLFSSL_TLS13
+ if (TLSX_Find(ssl->extensions,
+ TLSX_SUPPORTED_VERSIONS) != NULL) {
+ WOLFSSL_MSG(
+ "Client attempting to connect with higher version");
+ return VERSION_ERROR;
+ }
+ #endif
+ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ if((ret=SNI_Callback(ssl)))
+ return ret;
+ ssl->options.side = WOLFSSL_SERVER_END;
+ #endif
i += totalExtSz;
#else
@@ -13407,19 +26934,30 @@ int DoSessionTicket(WOLFSSL* ssl,
return BUFFER_ERROR;
if (extId == HELLO_EXT_SIG_ALGO) {
- ato16(&input[i], &clSuites.hashSigAlgoSz);
+ word16 hashSigAlgoSz;
+
+ ato16(&input[i], &hashSigAlgoSz);
i += OPAQUE16_LEN;
- if (OPAQUE16_LEN + clSuites.hashSigAlgoSz > extSz)
+ if (OPAQUE16_LEN + hashSigAlgoSz > extSz)
return BUFFER_ERROR;
+ clSuites.hashSigAlgoSz = hashSigAlgoSz;
+ if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+ WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
+ "truncating");
+ clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+ }
+
XMEMCPY(clSuites.hashSigAlgo, &input[i],
- min(clSuites.hashSigAlgoSz, HELLO_EXT_SIGALGO_MAX));
- i += clSuites.hashSigAlgoSz;
+ clSuites.hashSigAlgoSz);
- if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX)
- clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX;
+ i += hashSigAlgoSz;
}
+#ifdef HAVE_EXTENDED_MASTER
+ else if (extId == HELLO_EXT_EXTMS)
+ ssl->options.haveEMS = 1;
+#endif
else
i += extSz;
@@ -13436,291 +26974,547 @@ int DoSessionTicket(WOLFSSL* ssl,
ssl->options.haveSessionId = 1;
/* ProcessOld uses same resume code */
- if (ssl->options.resuming && (!ssl->options.dtls ||
- ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */
- int ret = -1;
- WOLFSSL_SESSION* session = GetSession(ssl,
- ssl->arrays->masterSecret);
- #ifdef HAVE_SESSION_TICKET
- if (ssl->options.useTicket == 1) {
- session = &ssl->session;
- }
+ if (ssl->options.resuming) {
+ ret = HandleTlsResumption(ssl, bogusID, &clSuites);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_SECURE_RENEGOTIATION
+ if (ssl->secure_renegotiation &&
+ ssl->secure_renegotiation->enabled &&
+ IsEncryptionOn(ssl, 0))
+ ssl->secure_renegotiation->startScr = 1;
#endif
- if (!session) {
- WOLFSSL_MSG("Session lookup for resume failed");
- ssl->options.resuming = 0;
+ if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
+ WOLFSSL_LEAVE("DoClientHello", ret);
+ WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+ return ret;
}
- else {
- if (MatchSuite(ssl, &clSuites) < 0) {
- WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
- return UNSUPPORTED_SUITE;
- }
- #ifdef SESSION_CERTS
- ssl->session = *session; /* restore session certs. */
- #endif
+ }
- ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
- RAN_LEN);
- if (ret != 0)
- return ret;
+#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_DH_DEFAULT_PARAMS)
+ #if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES)
+ if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) != NULL) {
+ /* Set FFDHE parameters or clear DHE parameters if FFDH parameters
+ * present and no matches in the server's list. */
+ ret = TLSX_SupportedFFDHE_Set(ssl);
+ if (ret != 0)
+ return ret;
+ }
+ #endif
+#endif
- #ifdef NO_OLD_TLS
- ret = DeriveTlsKeys(ssl);
- #else
- #ifndef NO_TLS
- if (ssl->options.tls)
- ret = DeriveTlsKeys(ssl);
- #endif
- if (!ssl->options.tls)
- ret = DeriveKeys(ssl);
- #endif
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ ret = MatchSuite(ssl, &clSuites);
+#ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_ERROR)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret < 0)
+ SendAlert(ssl, alert_fatal, handshake_failure);
+#endif
- return ret;
- }
+#ifdef HAVE_SECURE_RENEGOTIATION
+ if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
+ IsEncryptionOn(ssl, 0)) {
+ ssl->secure_renegotiation->startScr = 1;
}
- return MatchSuite(ssl, &clSuites);
+#endif
+ WOLFSSL_LEAVE("DoClientHello", ret);
+ WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+ return ret;
}
-#if !defined(NO_RSA) || defined(HAVE_ECC)
- static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx,
- word32 size)
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+ defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+
+ typedef struct DcvArgs {
+ byte* output; /* not allocated */
+ word32 sendSz;
+ word16 sz;
+ word32 sigSz;
+ word32 idx;
+ word32 begin;
+ byte hashAlgo;
+ byte sigAlgo;
+ } DcvArgs;
+
+ static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs)
{
- word16 sz = 0;
- int ret = VERIFY_CERT_ERROR; /* start in error state */
- byte hashAlgo = sha_mac;
- byte sigAlgo = anonymous_sa_algo;
- word32 begin = *inOutIdx;
+ DcvArgs* args = (DcvArgs*)pArgs;
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateVerify", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("CertificateVerify", &ssl->timeoutInfo);
- #endif
+ (void)ssl;
+ (void)args;
+ }
+ /* handle processing of certificate_verify (15) */
+ static int DoCertificateVerify(WOLFSSL* ssl, byte* input,
+ word32* inOutIdx, word32 size)
+ {
+ int ret = 0;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ DcvArgs* args = (DcvArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+ #else
+ DcvArgs args[1];
+ #endif
- if (IsAtLeastTLSv1_2(ssl)) {
- if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size)
- return BUFFER_ERROR;
+ WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
+ WOLFSSL_ENTER("DoCertificateVerify");
- hashAlgo = input[(*inOutIdx)++];
- sigAlgo = input[(*inOutIdx)++];
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_dcv;
+ }
+ else
+ #endif
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(DcvArgs));
+ args->hashAlgo = sha_mac;
+ args->sigAlgo = anonymous_sa_algo;
+ args->idx = *inOutIdx;
+ args->begin = *inOutIdx;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeDcvArgs;
+ #endif
}
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ #ifdef WOLFSSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, "CertificateVerify");
+ if (ssl->toInfoOn)
+ AddLateName("CertificateVerify", &ssl->timeoutInfo);
+ #endif
- ato16(input + *inOutIdx, &sz);
- *inOutIdx += OPAQUE16_LEN;
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* case TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
- if ((*inOutIdx - begin) + sz > size || sz > ENCRYPT_LEN)
- return BUFFER_ERROR;
+ case TLS_ASYNC_BUILD:
+ {
+ if (IsAtLeastTLSv1_2(ssl)) {
+ if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcv);
+ }
- /* RSA */
-#ifndef NO_RSA
- if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
- byte* out = NULL;
- int outLen = 0;
- byte doUserRsa = 0;
+ DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+ &args->sigAlgo);
+ args->idx += 2;
+ }
+ #ifndef NO_RSA
+ else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0)
+ args->sigAlgo = rsa_sa_algo;
+ #endif
+ #ifdef HAVE_ECC
+ else if (ssl->peerEccDsaKeyPresent)
+ args->sigAlgo = ecc_dsa_sa_algo;
+ #endif
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ else if (ssl->peerEd25519KeyPresent)
+ args->sigAlgo = ed25519_sa_algo;
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ else if (ssl->peerEd448KeyPresent)
+ args->sigAlgo = ed448_sa_algo;
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcv);
+ }
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaVerifyCb)
- doUserRsa = 1;
- #endif /*HAVE_PK_CALLBACKS */
+ ato16(input + args->idx, &args->sz);
+ args->idx += OPAQUE16_LEN;
- WOLFSSL_MSG("Doing RSA peer cert verify");
+ if ((args->idx - args->begin) + args->sz > size ||
+ args->sz > ENCRYPT_LEN) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcv);
+ }
- if (doUserRsa) {
- #ifdef HAVE_PK_CALLBACKS
- outLen = ssl->ctx->RsaVerifyCb(ssl, input + *inOutIdx, sz,
- &out,
- ssl->buffers.peerRsaKey.buffer,
- ssl->buffers.peerRsaKey.length,
- ssl->RsaVerifyCtx);
- #endif /*HAVE_PK_CALLBACKS */
- }
- else {
- outLen = wc_RsaSSL_VerifyInline(input + *inOutIdx, sz, &out,
- ssl->peerRsaKey);
- }
+ #ifdef HAVE_ECC
+ if (ssl->peerEccDsaKeyPresent) {
+
+ WOLFSSL_MSG("Doing ECC peer cert verify");
+
+ /* make sure a default is defined */
+ #if !defined(NO_SHA)
+ SetDigest(ssl, sha_mac);
+ #elif !defined(NO_SHA256)
+ SetDigest(ssl, sha256_mac);
+ #elif defined(WOLFSSL_SHA384)
+ SetDigest(ssl, sha384_mac);
+ #elif defined(WOLFSSL_SHA512)
+ SetDigest(ssl, sha512_mac);
+ #else
+ #error No digest enabled for ECC sig verify
+ #endif
- if (IsAtLeastTLSv1_2(ssl)) {
-#ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig = NULL;
-#else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
- word32 sigSz;
- byte* digest = ssl->hsHashes->certHashes.sha;
- int typeH = SHAh;
- int digestSz = SHA_DIGEST_SIZE;
+ if (IsAtLeastTLSv1_2(ssl)) {
+ if (args->sigAlgo != ecc_dsa_sa_algo) {
+ WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+ }
-#ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL)
- return MEMORY_E;
-#endif
+ SetDigest(ssl, args->hashAlgo);
+ }
+ }
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (ssl->peerEd25519KeyPresent) {
+ WOLFSSL_MSG("Doing ED25519 peer cert verify");
+ if (IsAtLeastTLSv1_2(ssl) &&
+ args->sigAlgo != ed25519_sa_algo) {
+ WOLFSSL_MSG(
+ "Oops, peer sent ED25519 key but not in verify");
+ }
+ }
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (ssl->peerEd448KeyPresent) {
+ WOLFSSL_MSG("Doing ED448 peer cert verify");
+ if (IsAtLeastTLSv1_2(ssl) &&
+ args->sigAlgo != ed448_sa_algo) {
+ WOLFSSL_MSG(
+ "Oops, peer sent ED448 key but not in verify");
+ }
+ }
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* case TLS_ASYNC_BUILD */
+ FALL_THROUGH;
- if (sigAlgo != rsa_sa_algo) {
- WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
+ case TLS_ASYNC_DO:
+ {
+ #ifndef NO_RSA
+ if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+ WOLFSSL_MSG("Doing RSA peer cert verify");
+
+ ret = RsaVerify(ssl,
+ input + args->idx,
+ args->sz,
+ &args->output,
+ args->sigAlgo, args->hashAlgo,
+ ssl->peerRsaKey,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerRsaKey
+ #else
+ NULL
+ #endif
+ );
+ if (ret >= 0) {
+ if (args->sigAlgo == rsa_sa_algo)
+ args->sendSz = ret;
+ else {
+ args->sigSz = ret;
+ args->sendSz = ssl->buffers.digest.length;
+ }
+ ret = 0;
+ }
}
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ if (ssl->peerEccDsaKeyPresent) {
+ WOLFSSL_MSG("Doing ECC peer cert verify");
- if (hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = ssl->hsHashes->certHashes.sha256;
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
+ ret = EccVerify(ssl,
+ input + args->idx, args->sz,
+ ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+ ssl->peerEccDsaKey,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEccDsaKey
+ #else
+ NULL
#endif
+ );
}
- else if (hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = ssl->hsHashes->certHashes.sha384;
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
+ #endif /* HAVE_ECC */
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (ssl->peerEd25519KeyPresent) {
+ WOLFSSL_MSG("Doing Ed25519 peer cert verify");
+
+ ret = Ed25519Verify(ssl,
+ input + args->idx, args->sz,
+ ssl->hsHashes->messages, ssl->hsHashes->prevLen,
+ ssl->peerEd25519Key,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEd25519Key
+ #else
+ NULL
#endif
+ );
}
- else if (hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = ssl->hsHashes->certHashes.sha512;
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (ssl->peerEd448KeyPresent) {
+ WOLFSSL_MSG("Doing Ed448 peer cert verify");
+
+ ret = Ed448Verify(ssl,
+ input + args->idx, args->sz,
+ ssl->hsHashes->messages, ssl->hsHashes->prevLen,
+ ssl->peerEd448Key,
+ #ifdef HAVE_PK_CALLBACKS
+ &ssl->buffers.peerEd448Key
+ #else
+ NULL
#endif
+ );
}
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
- sigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH);
-
- if (outLen == (int)sigSz && out && XMEMCMP(out, encodedSig,
- min(sigSz, MAX_ENCODED_SIG_SZ)) == 0)
- ret = 0; /* verified */
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* handle async pending */
+ if (ret == WC_PENDING_E)
+ goto exit_dcv;
+ #endif
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- }
- else {
- if (outLen == FINISHED_SZ && out && XMEMCMP(out,
- &ssl->hsHashes->certHashes,
- FINISHED_SZ) == 0) {
- ret = 0; /* verified */
+ /* Check for error */
+ if (ret != 0) {
+ ret = SIG_VERIFY_E;
+ goto exit_dcv;
}
- }
- }
-#endif
-#ifdef HAVE_ECC
- if (ssl->peerEccDsaKeyPresent) {
- int verify = 0;
- int err = -1;
- byte* digest = ssl->hsHashes->certHashes.sha;
- word32 digestSz = SHA_DIGEST_SIZE;
- byte doUserEcc = 0;
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->EccVerifyCb)
- doUserEcc = 1;
- #endif
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* case TLS_ASYNC_DO */
+ FALL_THROUGH;
- WOLFSSL_MSG("Doing ECC peer cert verify");
+ case TLS_ASYNC_VERIFY:
+ {
+ #ifndef NO_RSA
+ if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+ if (IsAtLeastTLSv1_2(ssl)) {
+ #ifdef WC_RSA_PSS
+ if (args->sigAlgo == rsa_pss_sa_algo) {
+ SetDigest(ssl, args->hashAlgo);
+
+ #ifdef HAVE_SELFTEST
+ ret = wc_RsaPSS_CheckPadding(
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ args->output, args->sigSz,
+ HashAlgoToType(args->hashAlgo));
+ #else
+ ret = wc_RsaPSS_CheckPadding_ex(
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ args->output, args->sigSz,
+ HashAlgoToType(args->hashAlgo), -1,
+ mp_count_bits(&ssl->peerRsaKey->n));
+ #endif
+ if (ret != 0) {
+ ret = SIG_VERIFY_E;
+ goto exit_dcv;
+ }
+ }
+ else
+ #endif
+ {
+ #ifdef WOLFSSL_SMALL_STACK
+ byte* encodedSig;
+ #else
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ #endif
- if (IsAtLeastTLSv1_2(ssl)) {
- if (sigAlgo != ecc_dsa_sa_algo) {
- WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
- }
+ #ifdef WOLFSSL_SMALL_STACK
+ encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dcv);
+ }
+ #endif
- if (hashAlgo == sha256_mac) {
- #ifndef NO_SHA256
- digest = ssl->hsHashes->certHashes.sha256;
- digestSz = SHA256_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha384_mac) {
- #ifdef WOLFSSL_SHA384
- digest = ssl->hsHashes->certHashes.sha384;
- digestSz = SHA384_DIGEST_SIZE;
- #endif
- }
- else if (hashAlgo == sha512_mac) {
- #ifdef WOLFSSL_SHA512
- digest = ssl->hsHashes->certHashes.sha512;
- digestSz = SHA512_DIGEST_SIZE;
- #endif
+ if (args->sigAlgo != rsa_sa_algo) {
+ WOLFSSL_MSG("Oops, peer sent RSA key but not "
+ "in verify");
+ }
+
+ SetDigest(ssl, args->hashAlgo);
+
+ args->sigSz = wc_EncodeSignature(encodedSig,
+ ssl->buffers.digest.buffer,
+ ssl->buffers.digest.length,
+ TypeHash(args->hashAlgo));
+
+ if (args->sendSz != args->sigSz || !args->output ||
+ XMEMCMP(args->output, encodedSig,
+ min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+ ret = VERIFY_CERT_ERROR;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ #endif
+ }
+ }
+ else {
+ if (args->sendSz != FINISHED_SZ || !args->output ||
+ XMEMCMP(args->output,
+ &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) {
+ ret = VERIFY_CERT_ERROR;
+ }
+ }
}
- }
+ #endif /* !NO_RSA */
- if (doUserEcc) {
- #ifdef HAVE_PK_CALLBACKS
- ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, sz, digest,
- digestSz,
- ssl->buffers.peerEccDsaKey.buffer,
- ssl->buffers.peerEccDsaKey.length,
- &verify, ssl->EccVerifyCtx);
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* case TLS_ASYNC_VERIFY */
+ 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
+ }
+
+ ssl->options.havePeerVerify = 1;
+
+ /* Set final index */
+ args->idx += args->sz;
+ *inOutIdx = args->idx;
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_END;
+ } /* case TLS_ASYNC_FINALIZE */
+
+ case TLS_ASYNC_END:
+ {
+ break;
}
- else {
- err = wc_ecc_verify_hash(input + *inOutIdx, sz, digest,
- digestSz, &verify, ssl->peerEccDsaKey);
- }
+ default:
+ ret = INPUT_CASE_ERROR;
+ } /* switch(ssl->options.asyncState) */
- if (err == 0 && verify == 1)
- ret = 0; /* verified */
+ exit_dcv:
+
+ WOLFSSL_LEAVE("DoCertificateVerify", ret);
+ WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E) {
+ /* Mark message as not received so it can process again */
+ ssl->msgsReceived.got_certificate_verify = 0;
+
+ return ret;
}
-#endif
- *inOutIdx += sz;
+ #endif /* WOLFSSL_ASYNC_CRYPT */
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_ERROR)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == SIG_VERIFY_E)
+ SendAlert(ssl, alert_fatal, decrypt_error);
+ else if (ret != 0)
+ SendAlert(ssl, alert_fatal, bad_certificate);
+ #endif
+ /* Digest is not allocated, so do this to prevent free */
+ ssl->buffers.digest.buffer = NULL;
+ ssl->buffers.digest.length = 0;
- if (ret == 0)
- ssl->options.havePeerVerify = 1;
+ /* Final cleanup */
+ FreeDcvArgs(ssl, args);
+ FreeKeyExchange(ssl);
return ret;
}
-#endif /* !NO_RSA || HAVE_ECC */
+#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */
+
+ /* handle generation of server_hello_done (14) */
int SendServerHelloDone(WOLFSSL* ssl)
{
- byte *output;
- int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int ret;
+ byte* output;
+ int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int ret;
+
+ WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND);
+ WOLFSSL_ENTER("SendServerHelloDone");
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+
+ if (IsEncryptionOn(ssl, 1))
+ sendSz += MAX_MSG_EXTRA;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- #endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, 0, server_hello_done, ssl);
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
- return 0;
- }
- #endif
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */
+
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- ret = HashOutput(ssl, output, sendSz, 0);
+ if (sendSz < 0)
+ return sendSz;
+ } else {
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+ return ret;
+ }
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
+ }
-#ifdef WOLFSSL_CALLBACKS
+ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+ AddPacketName(ssl, "ServerHelloDone");
if (ssl->toInfoOn)
- AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
-#endif
+ AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz,
+ WRITE_PROTO, ssl->heap);
+ #endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendServerHelloDone", ret);
+ WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND);
+
+ return ret;
}
+#endif /* !WOLFSSL_NO_TLS12 */
#ifdef HAVE_SESSION_TICKET
@@ -13734,6 +27528,17 @@ int DoSessionTicket(WOLFSSL* ssl,
byte suite[SUITE_LEN]; /* cipher suite when created */
byte msecret[SECRET_LEN]; /* master secret */
word32 timestamp; /* born on */
+ word16 haveEMS; /* have extended master secret */
+#ifdef WOLFSSL_TLS13
+ word32 ageAdd; /* Obfuscation of age */
+ word16 namedGroup; /* Named group used */
+ #ifndef WOLFSSL_TLS13_DRAFT_18
+ TicketNonce ticketNonce; /* Ticket nonce */
+ #endif
+ #ifdef WOLFSSL_EARLY_DATA
+ word32 maxEarlyDataSz; /* Max size of early data */
+ #endif
+#endif
} InternalTicket;
/* fit within SESSION_TICKET_LEN */
@@ -13747,7 +27552,7 @@ int DoSessionTicket(WOLFSSL* ssl,
} ExternalTicket;
/* create a new session ticket, 0 on success */
- static int CreateTicket(WOLFSSL* ssl)
+ int CreateTicket(WOLFSSL* ssl)
{
InternalTicket it;
ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
@@ -13755,6 +27560,8 @@ int DoSessionTicket(WOLFSSL* ssl,
int ret;
byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */
+ XMEMSET(&it, 0, sizeof(it));
+
/* build internal */
it.pv.major = ssl->version.major;
it.pv.minor = ssl->version.minor;
@@ -13762,17 +27569,47 @@ int DoSessionTicket(WOLFSSL* ssl,
it.suite[0] = ssl->options.cipherSuite0;
it.suite[1] = ssl->options.cipherSuite;
- XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
- c32toa(LowResTimer(), (byte*)&it.timestamp);
+ #ifdef WOLFSSL_EARLY_DATA
+ it.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+ #endif
+
+ if (!ssl->options.tls1_3) {
+ XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
+ c32toa(LowResTimer(), (byte*)&it.timestamp);
+ it.haveEMS = ssl->options.haveEMS;
+ }
+ else {
+#ifdef WOLFSSL_TLS13
+ /* Client adds to ticket age to obfuscate. */
+ ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd,
+ sizeof(it.ageAdd));
+ if (ret != 0)
+ return BAD_TICKET_ENCRYPT;
+ ssl->session.ticketAdd = it.ageAdd;
+ it.namedGroup = ssl->session.namedGroup;
+ it.timestamp = TimeNowInMilliseconds();
+ /* Resumption master secret. */
+ XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN);
+ #ifndef WOLFSSL_TLS13_DRAFT_18
+ XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce,
+ sizeof(TicketNonce));
+ #endif
+#endif
+ }
/* build external */
XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
/* encrypt */
encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */
- ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
+ if (ssl->ctx->ticketEncCb == NULL) {
+ ret = WOLFSSL_TICKET_RET_FATAL;
+ }
+ else {
+ ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
et->enc_ticket, sizeof(InternalTicket),
&encLen, ssl->ctx->ticketEncCtx);
+ }
if (ret == WOLFSSL_TICKET_RET_OK) {
if (encLen < (int)sizeof(InternalTicket) ||
encLen > WOLFSSL_TICKET_ENC_SZ) {
@@ -13830,6 +27667,9 @@ int DoSessionTicket(WOLFSSL* ssl,
int outLen;
word16 inLen;
+ WOLFSSL_START(WC_FUNC_TICKET_DO);
+ WOLFSSL_ENTER("DoClientTicket");
+
if (len > SESSION_TICKET_LEN ||
len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
return BAD_TICKET_MSG_SZ;
@@ -13844,19 +27684,75 @@ int DoSessionTicket(WOLFSSL* ssl,
return BAD_TICKET_MSG_SZ;
}
outLen = inLen; /* may be reduced by user padding */
- ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
+
+ if (ssl->ctx->ticketEncCb == NULL) {
+ ret = WOLFSSL_TICKET_RET_FATAL;
+ }
+ else {
+ ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
et->enc_ticket + inLen, 0,
et->enc_ticket, inLen, &outLen,
ssl->ctx->ticketEncCtx);
+ }
if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
- if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) {
+ if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) {
WOLFSSL_MSG("Bad user ticket decrypt len");
return BAD_TICKET_KEY_CB_SZ;
}
/* get master secret */
- if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE)
- XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
+ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
+ if (ssl->version.minor < it->pv.minor) {
+ WOLFSSL_MSG("Ticket has greater version");
+ return VERSION_ERROR;
+ }
+ else if (ssl->version.minor > it->pv.minor) {
+ if (!ssl->options.downgrade) {
+ WOLFSSL_MSG("Ticket has lesser version");
+ return VERSION_ERROR;
+ }
+
+ WOLFSSL_MSG("Downgrading protocol due to ticket");
+
+ if (it->pv.minor < ssl->options.minDowngrade)
+ return VERSION_ERROR;
+ ssl->version.minor = it->pv.minor;
+ }
+
+
+ if (!IsAtLeastTLSv1_3(ssl->version)) {
+ XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
+ /* Copy the haveExtendedMasterSecret property from the ticket to
+ * the saved session, so the property may be checked later. */
+ ssl->session.haveEMS = it->haveEMS;
+ #ifndef NO_RESUME_SUITE_CHECK
+ ssl->session.cipherSuite0 = it->suite[0];
+ ssl->session.cipherSuite = it->suite[1];
+ #endif
+ }
+ else {
+#ifdef WOLFSSL_TLS13
+ /* Restore information to renegotiate. */
+ ssl->session.ticketSeen = it->timestamp;
+ ssl->session.ticketAdd = it->ageAdd;
+ ssl->session.cipherSuite0 = it->suite[0];
+ ssl->session.cipherSuite = it->suite[1];
+ #ifdef WOLFSSL_EARLY_DATA
+ ssl->session.maxEarlyDataSz = it->maxEarlyDataSz;
+ #endif
+ /* Resumption master secret. */
+ XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN);
+ #ifndef WOLFSSL_TLS13_DRAFT_18
+ XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce,
+ sizeof(TicketNonce));
+ #endif
+ ssl->session.namedGroup = it->namedGroup;
+#endif
+ }
+ }
+
+ WOLFSSL_LEAVE("DoClientTicket", ret);
+ WOLFSSL_END(WC_FUNC_TICKET_DO);
return ret;
}
@@ -13871,12 +27767,8 @@ int DoSessionTicket(WOLFSSL* ssl,
word32 length = SESSION_HINT_SZ + LENGTH_SZ;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- length += DTLS_RECORD_EXTRA;
- idx += DTLS_RECORD_EXTRA;
- }
- #endif
+ WOLFSSL_START(WC_FUNC_TICKET_SEND);
+ WOLFSSL_ENTER("SendTicket");
if (ssl->options.createTicket) {
ret = CreateTicket(ssl);
@@ -13886,11 +27778,21 @@ int DoSessionTicket(WOLFSSL* ssl,
length += ssl->session.ticketLen;
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ if (!ssl->options.dtls) {
+ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
+ sendSz += MAX_MSG_EXTRA;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ }
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
@@ -13906,23 +27808,114 @@ int DoSessionTicket(WOLFSSL* ssl,
/* ticket */
XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
- /* idx += ssl->session.ticketLen; */
+ idx += ssl->session.ticketLen;
+
+ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+ byte* input;
+ int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 1, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ return sendSz;
+ }
+ else {
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+ return ret;
+
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ }
+ #endif
+ ret = HashOutput(ssl, output, sendSz, 0);
+ if (ret != 0)
+ return ret;
+ }
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0) return ret;
ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendTicket", ret);
+ WOLFSSL_END(WC_FUNC_TICKET_SEND);
+
+ return ret;
}
#endif /* HAVE_SESSION_TICKET */
+#ifndef WOLFSSL_NO_TLS12
+
+#if defined(HAVE_SECURE_RENEGOTIATION) && \
+ defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
+ !defined(WOLFSSL_NO_SERVER)
+
+ /* handle generation of server's hello_request (0) */
+ int SendHelloRequest(WOLFSSL* ssl)
+ {
+ byte* output;
+ int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int ret;
+
+ WOLFSSL_START(WC_FUNC_HELLO_REQUEST_SEND);
+ WOLFSSL_ENTER("SendHelloRequest");
+
+ if (IsEncryptionOn(ssl, 1))
+ sendSz += MAX_MSG_EXTRA;
+
+ /* check for available size */
+ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get output buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.length;
+
+ AddHeaders(output, 0, hello_request, ssl);
+
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */
+
+ input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+ handshake, 0, 0, 0);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (sendSz < 0)
+ return sendSz;
+ }
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ ret = SendBuffered(ssl);
+
+ WOLFSSL_LEAVE("SendHelloRequest", ret);
+ WOLFSSL_END(WC_FUNC_HELLO_REQUEST_SEND);
+
+ return ret;
+ }
+
+#endif /* HAVE_SECURE_RENEGOTIATION && HAVE_SERVER_RENEGOTIATION_INFO */
#ifdef WOLFSSL_DTLS
- int SendHelloVerifyRequest(WOLFSSL* ssl)
+ /* handle generation of DTLS hello_verify_request (3) */
+ static int SendHelloVerifyRequest(WOLFSSL* ssl,
+ const byte* cookie, byte cookieSz)
{
byte* output;
- byte cookieSz = COOKIE_SZ;
int length = VERSION_SZ + ENUM_LEN + cookieSz;
int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
int sendSz = length + idx;
@@ -13932,457 +27925,1488 @@ int DoSessionTicket(WOLFSSL* ssl,
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
- /* get ouput buffer */
+ /* get output buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
+ /* Hello Verify Request should use 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;
AddHeaders(output, length, hello_verify_request, ssl);
- output[idx++] = ssl->chVersion.major;
- output[idx++] = ssl->chVersion.minor;
+#ifdef OPENSSL_EXTRA
+ output[idx++] = DTLS_MAJOR;
+ output[idx++] = DTLS_MINOR;
+#else
+ output[idx++] = ssl->version.major;
+ output[idx++] = ssl->version.minor;
+#endif
output[idx++] = cookieSz;
- if (ssl->ctx->CBIOCookie == NULL) {
- WOLFSSL_MSG("Your Cookie callback is null, please set");
+ if (cookie == NULL || cookieSz == 0)
return COOKIE_ERROR;
- }
- if ((ret = ssl->ctx->CBIOCookie(ssl, output + idx, cookieSz,
- ssl->IOCB_CookieCtx)) < 0)
- return ret;
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
+ XMEMCPY(output + idx, cookie, cookieSz);
-#ifdef WOLFSSL_CALLBACKS
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn)
- AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
+ AddPacketName(ssl, "HelloVerifyRequest");
if (ssl->toInfoOn)
- AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
+ AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output,
+ sendSz, WRITE_PROTO, ssl->heap);
#endif
- ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
-#endif
+#endif /* WOLFSSL_DTLS */
+ typedef struct DckeArgs {
+ byte* output; /* not allocated */
+ word32 length;
+ word32 idx;
+ word32 begin;
+ word32 sigSz;
+ #ifndef NO_RSA
+ int lastErr;
+ #endif
+ } DckeArgs;
+
+ static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs)
+ {
+ DckeArgs* args = (DckeArgs*)pArgs;
+
+ (void)ssl;
+ (void)args;
+ }
+
+ /* handle processing client_key_exchange (16) */
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
{
- int ret = 0;
- word32 length = 0;
- byte* out = NULL;
- word32 begin = *inOutIdx;
+ int ret;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ DckeArgs* args = (DckeArgs*)ssl->async.args;
+ typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+ (void)sizeof(args_test);
+ #else
+ DckeArgs args[1];
+ #endif
- (void)length; /* shut up compiler warnings */
- (void)out;
- (void)input;
(void)size;
- (void)begin;
+ (void)input;
- if (ssl->options.side != WOLFSSL_SERVER_END) {
- WOLFSSL_MSG("Client received client keyexchange, attack?");
- WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
- return SSL_FATAL_ERROR;
- }
+ WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
+ WOLFSSL_ENTER("DoClientKeyExchange");
- if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
- WOLFSSL_MSG("Client sending keyexchange at wrong time");
- SendAlert(ssl, alert_fatal, unexpected_message);
- return OUT_OF_ORDER_E;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+ if (ret != WC_NOT_PENDING_E) {
+ /* Check for error */
+ if (ret < 0)
+ goto exit_dcke;
+ }
+ else
+ #endif /* WOLFSSL_ASYNC_CRYPT */
+ {
+ /* Reset state */
+ ret = 0;
+ ssl->options.asyncState = TLS_ASYNC_BEGIN;
+ XMEMSET(args, 0, sizeof(DckeArgs));
+ args->idx = *inOutIdx;
+ args->begin = *inOutIdx;
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ ssl->async.freeArgs = FreeDckeArgs;
+ #endif
}
- #ifndef NO_CERTS
- if (ssl->options.verifyPeer && ssl->options.failNoCert)
- if (!ssl->options.havePeerCert) {
- WOLFSSL_MSG("client didn't present peer cert");
- return NO_PEER_CERT;
+ /* Do Client Key Exchange State Machine */
+ switch(ssl->options.asyncState)
+ {
+ case TLS_ASYNC_BEGIN:
+ {
+ /* Sanity checks */
+ if (ssl->options.side != WOLFSSL_SERVER_END) {
+ WOLFSSL_MSG("Client received client keyexchange, attack?");
+ WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+ ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke);
}
- #endif
- #ifdef WOLFSSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
- #endif
+ if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+ WOLFSSL_MSG("Client sending keyexchange at wrong time");
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ ERROR_OUT(OUT_OF_ORDER_E, exit_dcke);
+ }
- switch (ssl->specs.kea) {
- #ifndef NO_RSA
- case rsa_kea:
+ #ifndef NO_CERTS
+ if (ssl->options.verifyPeer && ssl->options.failNoCert) {
+ if (!ssl->options.havePeerCert) {
+ WOLFSSL_MSG("client didn't present peer cert");
+ ERROR_OUT(NO_PEER_CERT, exit_dcke);
+ }
+ }
+
+ if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) {
+ if (!ssl->options.havePeerCert &&
+ !ssl->options.usingPSK_cipher) {
+ WOLFSSL_MSG("client didn't present peer cert");
+ return NO_PEER_CERT;
+ }
+ }
+ #endif /* !NO_CERTS */
+
+ #if defined(WOLFSSL_CALLBACKS)
+ if (ssl->hsInfoOn) {
+ AddPacketName(ssl, "ClientKeyExchange");
+ }
+ if (ssl->toInfoOn) {
+ AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
+ }
+ #endif
+
+ 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(MEMORY_E, exit_dcke);
+ }
+ XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+ }
+
+ switch (ssl->specs.kea) {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ break;
+ } /* rsa_kea */
+ #endif /* !NO_RSA */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ /* sanity check that PSK server callback has been set */
+ if (ssl->options.server_psk_cb == NULL) {
+ WOLFSSL_MSG("No server PSK callback set");
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
+ break;
+ }
+ #endif /* !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ /* make sure private key exists */
+ if (ssl->buffers.key == NULL ||
+ ssl->buffers.key->buffer == NULL) {
+ ERROR_OUT(NO_PRIVATE_KEY, exit_dcke);
+ }
+ break;
+ }
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ break;
+ }
+ #endif /* !NO_DH */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ /* sanity check that PSK server callback has been set */
+ if (ssl->options.server_psk_cb == NULL) {
+ WOLFSSL_MSG("No server PSK callback set");
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ /* sanity check that PSK server callback has been set */
+ if (ssl->options.server_psk_cb == NULL) {
+ WOLFSSL_MSG("No server PSK callback set");
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ default:
+ WOLFSSL_MSG("Bad kea type");
+ ret = BAD_KEA_TYPE_E;
+ } /* switch (ssl->specs.kea) */
+
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_BUILD;
+ } /* TLS_ASYNC_BEGIN */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_BUILD:
{
- word32 idx = 0;
- RsaKey key;
- byte doUserRsa = 0;
+ switch (ssl->specs.kea) {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ word16 keySz;
+
+ ssl->buffers.keyType = rsa_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ args->length = (word32)keySz;
+ ssl->arrays->preMasterSz = SECRET_LEN;
- #ifdef HAVE_PK_CALLBACKS
- if (ssl->ctx->RsaDecCb)
- doUserRsa = 1;
- #endif
+ if (ssl->options.tls) {
+ word16 check;
- ret = wc_InitRsaKey(&key, ssl->heap);
- if (ret != 0) return ret;
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if (ssl->buffers.key.buffer)
- ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx,
- &key, ssl->buffers.key.length);
- else
- return NO_PRIVATE_KEY;
+ ato16(input + args->idx, &check);
+ args->idx += OPAQUE16_LEN;
- if (ret == 0) {
- length = wc_RsaEncryptSize(&key);
- ssl->arrays->preMasterSz = SECRET_LEN;
+ if ((word32)check != args->length) {
+ WOLFSSL_MSG("RSA explicit size doesn't match");
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ #endif
+ ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke);
+ }
+ }
+
+ if ((args->idx - args->begin) + args->length > size) {
+ WOLFSSL_MSG("RSA message too big");
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if (ssl->options.tls) {
- word16 check;
+ /* pre-load PreMasterSecret with RNG data */
+ ret = wc_RNG_GenerateBlock(ssl->rng,
+ &ssl->arrays->preMasterSecret[VERSION_SZ],
+ SECRET_LEN - VERSION_SZ);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ args->output = NULL;
+ break;
+ } /* rsa_kea */
+ #endif /* !NO_RSA */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ byte* pms = ssl->arrays->preMasterSecret;
+ word16 ci_sz;
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- ato16(input + *inOutIdx, &check);
- *inOutIdx += OPAQUE16_LEN;
+ ato16(input + args->idx, &ci_sz);
+ args->idx += OPAQUE16_LEN;
- if ((word32) check != length) {
- WOLFSSL_MSG("RSA explicit size doesn't match");
- wc_FreeRsaKey(&key);
- return RSA_PRIVATE_ERROR;
+ if (ci_sz > MAX_PSK_ID_LEN) {
+ ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
}
+
+ if ((args->idx - args->begin) + ci_sz > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+
+ XMEMCPY(ssl->arrays->client_identity,
+ input + args->idx, ci_sz);
+ args->idx += ci_sz;
+
+ ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */
+ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays->client_identity, ssl->arrays->psk_key,
+ MAX_PSK_KEY_LEN);
+
+ if (ssl->arrays->psk_keySz == 0 ||
+ ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
+
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16) ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+
+ XMEMSET(pms, 0, ssl->arrays->psk_keySz);
+ pms += ssl->arrays->psk_keySz;
+
+ c16toa((word16) ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+
+ XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->preMasterSz =
+ (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2);
+ break;
}
+ #endif /* !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ word16 cipherLen;
+ word16 plainLen = ENCRYPT_LEN;
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + length > size) {
- WOLFSSL_MSG("RSA message too big");
- wc_FreeRsaKey(&key);
- return BUFFER_ERROR;
+ ato16(input + args->idx, &cipherLen);
+ args->idx += OPAQUE16_LEN;
+
+ if (cipherLen > MAX_NTRU_ENCRYPT_SZ) {
+ ERROR_OUT(NTRU_KEY_ERROR, exit_dcke);
+ }
+
+ if ((args->idx - args->begin) + cipherLen > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+
+ if (NTRU_OK != ntru_crypto_ntru_decrypt(
+ (word16) ssl->buffers.key->length,
+ ssl->buffers.key->buffer, cipherLen,
+ input + args->idx, &plainLen,
+ ssl->arrays->preMasterSecret)) {
+ ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+ }
+
+ if (plainLen != SECRET_LEN) {
+ ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+ }
+
+ args->idx += cipherLen;
+ ssl->arrays->preMasterSz = plainLen;
+ break;
}
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ #ifdef HAVE_ECC
+ ecc_key* private_key = ssl->eccTempKey;
+
+ /* handle static private key */
+ if (ssl->specs.static_ecdh &&
+ ssl->ecdhCurveOID != ECC_X25519_OID &&
+ ssl->ecdhCurveOID != ECC_X448_OID) {
+ word16 keySz;
+
+ ssl->buffers.keyType = ecc_dsa_sa_algo;
+ ret = DecodePrivateKey(ssl, &keySz);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ private_key = (ecc_key*)ssl->hsKey;
+ }
+ #endif
+
+ /* import peer ECC key */
+ if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, decode_error);
+ #endif
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+
+ args->length = input[args->idx++];
+
+ if ((args->idx - args->begin) + args->length > size) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, decode_error);
+ #endif
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if (doUserRsa) {
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
#ifdef HAVE_PK_CALLBACKS
- ret = ssl->ctx->RsaDecCb(ssl,
- input + *inOutIdx, length, &out,
- ssl->buffers.key.buffer,
- ssl->buffers.key.length,
- ssl->RsaDecCtx);
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ break;
+ }
#endif
- }
- else {
- ret = wc_RsaPrivateDecryptInline(input + *inOutIdx, length,
- &out, &key);
- }
+ if (ssl->peerX25519Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ } else if (ssl->peerX25519KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
+
+ if ((ret = wc_curve25519_check_public(
+ input + args->idx, args->length,
+ EC25519_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal,
+ illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- *inOutIdx += length;
+ if (wc_curve25519_import_public_ex(
+ input + args->idx, args->length,
+ ssl->peerX25519Key,
+ EC25519_LITTLE_ENDIAN)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- if (ret == SECRET_LEN) {
- XMEMCPY(ssl->arrays->preMasterSecret, out, SECRET_LEN);
- if (ssl->arrays->preMasterSecret[0] !=
- ssl->chVersion.major
- || ssl->arrays->preMasterSecret[1] !=
- ssl->chVersion.minor)
- ret = PMS_VERSION_ERROR;
- else
- ret = MakeMasterSecret(ssl);
+ ssl->arrays->preMasterSz = CURVE25519_KEYSIZE;
+
+ ssl->peerX25519KeyPresent = 1;
+
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ break;
+ }
+ #endif
+ if (ssl->peerX448Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ } else if (ssl->peerX448KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+ ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
+
+ if ((ret = wc_curve448_check_public(
+ input + args->idx, args->length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal,
+ illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
+
+ if (wc_curve448_import_public_ex(
+ input + args->idx, args->length,
+ ssl->peerX448Key,
+ EC448_LITTLE_ENDIAN)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
+
+ ssl->arrays->preMasterSz = CURVE448_KEY_SIZE;
+
+ ssl->peerX448KeyPresent = 1;
+
+ break;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
+ #endif
+
+ if (!ssl->specs.static_ecdh &&
+ ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+ ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+ }
+
+ if (ssl->peerEccKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ } else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+ ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
+
+ if (wc_ecc_import_x963_ex(input + args->idx,
+ args->length, ssl->peerEccKey,
+ private_key->dp->id)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
+
+ ssl->arrays->preMasterSz = private_key->dp->size;
+
+ ssl->peerEccKeyPresent = 1;
+ #endif /* HAVE_ECC */
+
+ break;
}
- else {
- ret = RSA_PRIVATE_ERROR;
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ word16 clientPubSz;
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+
+ ato16(input + args->idx, &clientPubSz);
+ args->idx += OPAQUE16_LEN;
+
+ if ((args->idx - args->begin) + clientPubSz > size) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, decode_error);
+ #endif
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+
+ args->sigSz = clientPubSz;
+
+ ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+ (void**)&ssl->buffers.serverDH_Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+
+ ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
+
+ /* set the max agree result size */
+ ssl->arrays->preMasterSz = ENCRYPT_LEN;
+ break;
}
- }
+ #endif /* !NO_DH */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ word16 clientSz;
+
+ /* Read in the PSK hint */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- wc_FreeRsaKey(&key);
- }
- break;
- #endif
- #ifndef NO_PSK
- case psk_kea:
- {
- byte* pms = ssl->arrays->preMasterSecret;
- word16 ci_sz;
+ ato16(input + args->idx, &clientSz);
+ args->idx += OPAQUE16_LEN;
+ if (clientSz > MAX_PSK_ID_LEN) {
+ ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ if ((args->idx - args->begin) + clientSz > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- ato16(input + *inOutIdx, &ci_sz);
- *inOutIdx += OPAQUE16_LEN;
+ XMEMCPY(ssl->arrays->client_identity, input + args->idx,
+ clientSz);
+ args->idx += clientSz;
+ ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
- if (ci_sz > MAX_PSK_ID_LEN)
- return CLIENT_ID_ERROR;
+ /* Read in the DHE business */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + ci_sz > size)
- return BUFFER_ERROR;
+ ato16(input + args->idx, &clientSz);
+ args->idx += OPAQUE16_LEN;
- XMEMCPY(ssl->arrays->client_identity, input + *inOutIdx, ci_sz);
- *inOutIdx += ci_sz;
+ if ((args->idx - args->begin) + clientSz > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0;
- ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays->client_identity, ssl->arrays->psk_key,
- MAX_PSK_KEY_LEN);
+ args->sigSz = clientSz;
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
- return PSK_KEY_ERROR;
+ ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+ (void**)&ssl->buffers.serverDH_Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
+ ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_P.buffer,
+ ssl->buffers.serverDH_P.length,
+ ssl->buffers.serverDH_G.buffer,
+ ssl->buffers.serverDH_G.length);
- XMEMSET(pms, 0, ssl->arrays->psk_keySz);
- pms += ssl->arrays->psk_keySz;
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ word16 clientSz;
+
+ /* Read in the PSK hint */
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
+ ato16(input + args->idx, &clientSz);
+ args->idx += OPAQUE16_LEN;
+ if (clientSz > MAX_PSK_ID_LEN) {
+ ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+ }
+ if ((args->idx - args->begin) + clientSz > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4;
+ XMEMCPY(ssl->arrays->client_identity,
+ input + args->idx, clientSz);
+ args->idx += clientSz;
+ ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
- ret = MakeMasterSecret(ssl);
+ /* import peer ECC key */
+ if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- /* No further need for PSK */
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0;
- }
- break;
- #endif /* NO_PSK */
- #ifdef HAVE_NTRU
- case ntru_kea:
- {
- word16 cipherLen;
- word16 plainLen = sizeof(ssl->arrays->preMasterSecret);
+ args->length = input[args->idx++];
- if (!ssl->buffers.key.buffer)
- return NO_PRIVATE_KEY;
+ if ((args->idx - args->begin) + args->length > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
- ato16(input + *inOutIdx, &cipherLen);
- *inOutIdx += OPAQUE16_LEN;
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
- return NTRU_KEY_ERROR;
+ if (ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG(
+ "X25519 ephemeral key not made correctly");
+ ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + cipherLen > size)
- return BUFFER_ERROR;
+ if (ssl->peerX25519Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ } else if (ssl->peerX25519KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
- if (NTRU_OK != ntru_crypto_ntru_decrypt(
- (word16) ssl->buffers.key.length,
- ssl->buffers.key.buffer, cipherLen,
- input + *inOutIdx, &plainLen,
- ssl->arrays->preMasterSecret))
- return NTRU_DECRYPT_ERROR;
+ if ((ret = wc_curve25519_check_public(
+ input + args->idx, args->length,
+ EC25519_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal,
+ illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- if (plainLen != SECRET_LEN)
- return NTRU_DECRYPT_ERROR;
+ if (wc_curve25519_import_public_ex(
+ input + args->idx, args->length,
+ ssl->peerX25519Key,
+ EC25519_LITTLE_ENDIAN)) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- *inOutIdx += cipherLen;
+ ssl->peerX25519KeyPresent = 1;
- ssl->arrays->preMasterSz = plainLen;
- ret = MakeMasterSecret(ssl);
- }
- break;
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- case ecc_diffie_hellman_kea:
- {
- if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
- return BUFFER_ERROR;
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- length = input[(*inOutIdx)++];
+ if (ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG(
+ "X448 ephemeral key not made correctly");
+ ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+ }
- if ((*inOutIdx - begin) + length > size)
- return BUFFER_ERROR;
+ if (ssl->peerX448Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ } else if (ssl->peerX448KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+ ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
- if (ssl->peerEccKey == NULL) {
- /* alloc/init on demand */
- ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
- ssl->ctx->heap, DYNAMIC_TYPE_ECC);
- if (ssl->peerEccKey == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_E;
- }
- wc_ecc_init(ssl->peerEccKey);
- } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- wc_ecc_init(ssl->peerEccKey);
- }
+ if ((ret = wc_curve448_check_public(
+ input + args->idx, args->length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == BUFFER_E)
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == ECC_OUT_OF_RANGE_E)
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal,
+ illegal_parameter);
+ }
+ #endif
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey))
- return ECC_PEERKEY_ERROR;
+ if (wc_curve448_import_public_ex(
+ input + args->idx, args->length,
+ ssl->peerX448Key,
+ EC448_LITTLE_ENDIAN)) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- *inOutIdx += length;
- ssl->peerEccKeyPresent = 1;
+ ssl->peerX448KeyPresent = 1;
- length = sizeof(ssl->arrays->preMasterSecret);
+ break;
+ }
+ #endif
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ break;
+ }
+ #endif
- if (ssl->specs.static_ecdh) {
- ecc_key staticKey;
- word32 i = 0;
+ if (ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+ ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+ }
- wc_ecc_init(&staticKey);
- ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
- &staticKey, ssl->buffers.key.length);
+ if (ssl->peerEccKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
+ else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+ ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0) {
+ goto exit_dcke;
+ }
+ }
+ if (wc_ecc_import_x963_ex(input + args->idx,
+ args->length, ssl->peerEccKey,
+ ssl->eccTempKey->dp->id)) {
+ ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+ }
- if (ret == 0)
- ret = wc_ecc_shared_secret(&staticKey, ssl->peerEccKey,
- ssl->arrays->preMasterSecret, &length);
+ ssl->peerEccKeyPresent = 1;
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch (ssl->specs.kea) */
- wc_ecc_free(&staticKey);
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dcke;
}
- else {
- if (ssl->eccTempKeyPresent == 0) {
- WOLFSSL_MSG("Ecc ephemeral key not made correctly");
- ret = ECC_MAKEKEY_ERROR;
- } else {
- ret = wc_ecc_shared_secret(ssl->eccTempKey,ssl->peerEccKey,
- ssl->arrays->preMasterSecret, &length);
+
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_DO;
+ } /* TLS_ASYNC_BUILD */
+ FALL_THROUGH;
+
+ case TLS_ASYNC_DO:
+ {
+ switch (ssl->specs.kea) {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ RsaKey* key = (RsaKey*)ssl->hsKey;
+
+ ret = RsaDec(ssl,
+ input + args->idx,
+ args->length,
+ &args->output,
+ &args->sigSz,
+ key,
+ #ifdef HAVE_PK_CALLBACKS
+ ssl->buffers.key
+ #else
+ NULL
+ #endif
+ );
+
+ /* Errors that can occur here that should be
+ * indistinguishable:
+ * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
+ */
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ goto exit_dcke;
+ #endif
+ if (ret == BAD_FUNC_ARG)
+ goto exit_dcke;
+
+ args->lastErr = ret - (SECRET_LEN - args->sigSz);
+ ret = 0;
+ break;
+ } /* rsa_kea */
+ #endif /* !NO_RSA */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ break;
+ }
+ #endif /* !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ break;
}
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ void* private_key = ssl->eccTempKey;
+ (void)private_key;
+
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ ret = X25519SharedSecret(ssl,
+ (curve25519_key*)private_key,
+ ssl->peerX25519Key,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_SERVER_END
+ );
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ ret = X448SharedSecret(ssl,
+ (curve448_key*)private_key,
+ ssl->peerX448Key,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_SERVER_END
+ );
+ break;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ if (ssl->specs.static_ecdh) {
+ private_key = ssl->hsKey;
+ }
+
+ /* Generate shared secret */
+ ret = EccSharedSecret(ssl,
+ (ecc_key*)private_key, ssl->peerEccKey,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_SERVER_END
+ );
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ FreeKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ }
+ #endif
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_Priv.buffer,
+ ssl->buffers.serverDH_Priv.length,
+ input + args->idx,
+ (word16)args->sigSz,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz);
+ break;
+ }
+ #endif /* !NO_DH */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+ ssl->buffers.serverDH_Priv.buffer,
+ ssl->buffers.serverDH_Priv.length,
+ input + args->idx,
+ (word16)args->sigSz,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &ssl->arrays->preMasterSz);
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ ret = X25519SharedSecret(ssl,
+ (curve25519_key*)ssl->eccTempKey,
+ ssl->peerX25519Key,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &args->sigSz,
+ WOLFSSL_SERVER_END
+ );
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ }
+ break;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ ret = X448SharedSecret(ssl,
+ (curve448_key*)ssl->eccTempKey,
+ ssl->peerX448Key,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &args->sigSz,
+ WOLFSSL_SERVER_END
+ );
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret != WC_PENDING_E)
+ #endif
+ {
+ FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ }
+ break;
+ }
+ #endif
+ /* Generate shared secret */
+ ret = EccSharedSecret(ssl,
+ ssl->eccTempKey, ssl->peerEccKey,
+ input + args->idx, &args->length,
+ ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+ &args->sigSz,
+ WOLFSSL_SERVER_END
+ );
+ if (!ssl->specs.static_ecdh
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_PENDING_E
+ #endif
+ ) {
+ FreeKey(ssl, DYNAMIC_TYPE_ECC,
+ (void**)&ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ }
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch (ssl->specs.kea) */
+
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dcke;
}
- if (ret != 0)
- return ECC_SHARED_ERROR;
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_VERIFY;
+ } /* TLS_ASYNC_DO */
+ FALL_THROUGH;
- ssl->arrays->preMasterSz = length;
- ret = MakeMasterSecret(ssl);
- }
- break;
- #endif /* HAVE_ECC */
- #ifndef NO_DH
- case diffie_hellman_kea:
+ case TLS_ASYNC_VERIFY:
{
- word16 clientPubSz;
- DhKey dhKey;
+ switch (ssl->specs.kea) {
+ #ifndef NO_RSA
+ case rsa_kea:
+ {
+ byte mask;
+ int i;
+
+ /* Add the signature length to idx */
+ args->idx += args->length;
+
+ #ifdef DEBUG_WOLFSSL
+ /* check version (debug warning message only) */
+ if (args->output != NULL) {
+ if (args->output[0] != ssl->chVersion.major ||
+ args->output[1] != ssl->chVersion.minor) {
+ WOLFSSL_MSG("preMasterSecret version mismatch");
+ }
+ }
+ #endif
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ /* RFC5246 7.4.7.1:
+ * Treat incorrectly formatted message blocks and/or
+ * mismatched version numbers in a manner
+ * indistinguishable from correctly formatted RSA blocks
+ */
+
+ ret = args->lastErr;
+ args->lastErr = 0; /* reset */
+ /* On error 'ret' will be negative - top bit set */
+ mask = ((unsigned int)ret >>
+ ((sizeof(ret) * 8) - 1)) - 1;
+
+ /* build PreMasterSecret */
+ ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+ ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+
+ if (args->output != NULL) {
+ /* Use random secret on error */
+ for (i = VERSION_SZ; i < SECRET_LEN; i++) {
+ ssl->arrays->preMasterSecret[i] =
+ ctMaskSel(mask, args->output[i],
+ ssl->arrays->preMasterSecret[i]);
+ }
+ }
+ /* preMasterSecret has RNG and version set
+ * return proper length and ignore error
+ * error will be caught as decryption error
+ */
+ args->sigSz = SECRET_LEN;
+ ret = 0;
+ break;
+ } /* rsa_kea */
+ #endif /* !NO_RSA */
+ #ifndef NO_PSK
+ case psk_kea:
+ {
+ break;
+ }
+ #endif /* !NO_PSK */
+ #ifdef HAVE_NTRU
+ case ntru_kea:
+ {
+ break;
+ }
+ #endif /* HAVE_NTRU */
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ case ecc_diffie_hellman_kea:
+ {
+ /* skip past the imported peer key */
+ args->idx += args->length;
+ break;
+ }
+ #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+ #ifndef NO_DH
+ case diffie_hellman_kea:
+ {
+ args->idx += (word16)args->sigSz;
+ break;
+ }
+ #endif /* !NO_DH */
+ #if !defined(NO_DH) && !defined(NO_PSK)
+ case dhe_psk_kea:
+ {
+ byte* pms = ssl->arrays->preMasterSecret;
+ word16 clientSz = (word16)args->sigSz;
+
+ args->idx += clientSz;
+ c16toa((word16)ssl->arrays->preMasterSz, pms);
+ ssl->arrays->preMasterSz += OPAQUE16_LEN;
+ pms += ssl->arrays->preMasterSz;
+
+ /* Use the PSK hint to look up the PSK and add it to the
+ * preMasterSecret here. */
+ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays->client_identity, ssl->arrays->psk_key,
+ MAX_PSK_KEY_LEN);
+
+ if (ssl->arrays->psk_keySz == 0 ||
+ ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
- ato16(input + *inOutIdx, &clientPubSz);
- *inOutIdx += OPAQUE16_LEN;
+ c16toa((word16) ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
- if ((*inOutIdx - begin) + clientPubSz > size)
- return BUFFER_ERROR;
+ XMEMCPY(pms, ssl->arrays->psk_key,
+ ssl->arrays->psk_keySz);
+ ssl->arrays->preMasterSz += ssl->arrays->psk_keySz +
+ OPAQUE16_LEN;
+ break;
+ }
+ #endif /* !NO_DH && !NO_PSK */
+ #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)) && !defined(NO_PSK)
+ case ecdhe_psk_kea:
+ {
+ byte* pms = ssl->arrays->preMasterSecret;
+ word16 clientSz = (word16)args->sigSz;
+
+ /* skip past the imported peer key */
+ args->idx += args->length;
+
+ /* Add preMasterSecret */
+ c16toa(clientSz, pms);
+ ssl->arrays->preMasterSz = OPAQUE16_LEN + clientSz;
+ pms += ssl->arrays->preMasterSz;
+
+ /* Use the PSK hint to look up the PSK and add it to the
+ * preMasterSecret here. */
+ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays->client_identity, ssl->arrays->psk_key,
+ MAX_PSK_KEY_LEN);
+
+ if (ssl->arrays->psk_keySz == 0 ||
+ ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+ }
+
+ c16toa((word16) ssl->arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+
+ XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+ ssl->arrays->preMasterSz +=
+ ssl->arrays->psk_keySz + OPAQUE16_LEN;
+ break;
+ }
+ #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+ default:
+ ret = BAD_KEA_TYPE_E;
+ } /* switch (ssl->specs.kea) */
- wc_InitDhKey(&dhKey);
- ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = wc_DhAgree(&dhKey, ssl->arrays->preMasterSecret,
- &ssl->arrays->preMasterSz,
- ssl->buffers.serverDH_Priv.buffer,
- ssl->buffers.serverDH_Priv.length,
- input + *inOutIdx, clientPubSz);
- wc_FreeDhKey(&dhKey);
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dcke;
+ }
- *inOutIdx += clientPubSz;
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+ } /* TLS_ASYNC_VERIFY */
+ FALL_THROUGH;
- if (ret == 0)
- ret = MakeMasterSecret(ssl);
- }
- break;
- #endif /* NO_DH */
- #if !defined(NO_DH) && !defined(NO_PSK)
- case dhe_psk_kea:
+ case TLS_ASYNC_FINALIZE:
{
- byte* pms = ssl->arrays->preMasterSecret;
- word16 clientSz;
- DhKey dhKey;
+ 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
+ }
- /* Read in the PSK hint */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ #ifdef HAVE_QSH
+ word16 name;
+
+ if (ssl->options.haveQSH) {
+ /* extension name */
+ ato16(input + args->idx, &name);
+ args->idx += OPAQUE16_LEN;
+
+ if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+ int qshSz;
+ /* if qshSz is larger than 0 it is the
+ length of buffer used */
+ if ((qshSz = TLSX_QSHCipher_Parse(ssl,
+ input + args->idx,
+ size - args->idx + args->begin, 1)) < 0) {
+ ERROR_OUT(qshSz, exit_dcke);
+ }
+ args->idx += qshSz;
+ }
+ else {
+ /* unknown extension sent client ignored handshake */
+ ERROR_OUT(BUFFER_ERROR, exit_dcke);
+ }
+ }
+ #endif /* HAVE_QSH */
+ ret = MakeMasterSecret(ssl);
- ato16(input + *inOutIdx, &clientSz);
- *inOutIdx += OPAQUE16_LEN;
- if (clientSz > MAX_PSK_ID_LEN)
- return CLIENT_ID_ERROR;
+ /* Check for error */
+ if (ret != 0) {
+ goto exit_dcke;
+ }
- if ((*inOutIdx - begin) + clientSz > size)
- return BUFFER_ERROR;
+ /* Advance state and proceed */
+ ssl->options.asyncState = TLS_ASYNC_END;
+ } /* TLS_ASYNC_FINALIZE */
+ FALL_THROUGH;
- XMEMCPY(ssl->arrays->client_identity,
- input + *inOutIdx, clientSz);
- *inOutIdx += clientSz;
- ssl->arrays->client_identity[min(clientSz, MAX_PSK_ID_LEN-1)] =
- 0;
+ case TLS_ASYNC_END:
+ {
+ /* Set final index */
+ *inOutIdx = args->idx;
- /* Read in the DHE business */
- if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
- return BUFFER_ERROR;
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ #ifndef NO_CERTS
+ if (ssl->options.verifyPeer) {
+ ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+ }
+ #endif
+ break;
+ } /* TLS_ASYNC_END */
+ default:
+ ret = INPUT_CASE_ERROR;
+ } /* switch(ssl->options.asyncState) */
- ato16(input + *inOutIdx, &clientSz);
- *inOutIdx += OPAQUE16_LEN;
+ exit_dcke:
- if ((*inOutIdx - begin) + clientSz > size)
- return BUFFER_ERROR;
+ WOLFSSL_LEAVE("DoClientKeyExchange", ret);
+ WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
- wc_InitDhKey(&dhKey);
- ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = wc_DhAgree(&dhKey, pms + OPAQUE16_LEN,
- &ssl->arrays->preMasterSz,
- ssl->buffers.serverDH_Priv.buffer,
- ssl->buffers.serverDH_Priv.length,
- input + *inOutIdx, clientSz);
- wc_FreeDhKey(&dhKey);
-
- *inOutIdx += clientSz;
- c16toa((word16)ssl->arrays->preMasterSz, pms);
- ssl->arrays->preMasterSz += OPAQUE16_LEN;
- pms += ssl->arrays->preMasterSz;
-
- /* Use the PSK hint to look up the PSK and add it to the
- * preMasterSecret here. */
- ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays->client_identity, ssl->arrays->psk_key,
- MAX_PSK_KEY_LEN);
-
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
- return PSK_KEY_ERROR;
-
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
-
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz +=
- ssl->arrays->psk_keySz + OPAQUE16_LEN;
- if (ret == 0)
- ret = MakeMasterSecret(ssl);
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* Handle async operation */
+ if (ret == WC_PENDING_E) {
+ /* Mark message as not received so it can process again */
+ ssl->msgsReceived.got_client_key_exchange = 0;
- /* No further need for PSK */
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0;
- }
- break;
- #endif /* !NO_DH && !NO_PSK */
- default:
- {
- WOLFSSL_MSG("Bad kea type");
- ret = BAD_KEA_TYPE_E;
- }
- break;
+ return ret;
}
+ #endif /* WOLFSSL_ASYNC_CRYPT */
- /* No further need for PMS */
- ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+ /* Cleanup PMS */
+ if (ssl->arrays->preMasterSecret != NULL) {
+ ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+ }
ssl->arrays->preMasterSz = 0;
- if (ret == 0) {
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- #ifndef NO_CERTS
- if (ssl->options.verifyPeer)
- ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
- #endif
- }
+ /* Final cleanup */
+ FreeDckeArgs(ssl, args);
+ FreeKeyExchange(ssl);
return ret;
}
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+ defined(WOLFSSL_HAPROXY)
+ int SNI_Callback(WOLFSSL* ssl)
+ {
+ /* Stunnel supports a custom sni callback to switch an SSL's ctx
+ * when SNI is received. Call it now if exists */
+ if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) {
+ WOLFSSL_MSG("Calling custom sni callback");
+ if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg)
+ == alert_fatal) {
+ WOLFSSL_MSG("Error in custom sni callback. Fatal alert");
+ SendAlert(ssl, alert_fatal, unrecognized_name);
+ return FATAL_ERROR;
+ }
+ }
+ return 0;
+ }
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
#endif /* NO_WOLFSSL_SERVER */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
+{
+ int ret = 0;
+ WC_ASYNC_DEV* asyncDev;
+ WOLF_EVENT* event;
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* check for pending async */
+ asyncDev = ssl->async.dev;
+ if (asyncDev) {
+ /* grab event pointer */
+ event = &asyncDev->event;
+
+ ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL);
+ if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) {
+
+ /* advance key share state if doesn't need called again */
+ if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) {
+ (*state)++;
+ }
+
+ /* clear event */
+ XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT));
+
+ /* clear async dev */
+ ssl->async.dev = NULL;
+ }
+ }
+ else {
+ ret = WC_NOT_PENDING_E;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret);
+
+ return ret;
+}
+
+int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags)
+{
+ int ret;
+ WOLF_EVENT* event;
+
+ if (ssl == NULL || asyncDev == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* grab event pointer */
+ event = &asyncDev->event;
+
+ /* init event */
+ ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags);
+
+ WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret);
+
+ return ret;
+}
+
+int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev)
+{
+ int ret;
+ WOLF_EVENT* event;
+
+ if (ssl == NULL || asyncDev == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* grab event pointer */
+ event = &asyncDev->event;
+
+ /* store reference to active async operation */
+ ssl->async.dev = asyncDev;
+
+ /* place event into queue */
+ ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event);
+
+ /* success means return WC_PENDING_E */
+ if (ret == 0) {
+ ret = WC_PENDING_E;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret);
+
+ return ret;
+}
+
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+
+/* return the max record size */
+int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment)
+{
+ (void) ssl; /* Avoid compiler warnings */
+
+ if (maxFragment > MAX_RECORD_SIZE) {
+ maxFragment = MAX_RECORD_SIZE;
+ }
+
+#ifdef HAVE_MAX_FRAGMENT
+ if ((ssl->max_fragment != 0) && ((word16)maxFragment > ssl->max_fragment)) {
+ maxFragment = ssl->max_fragment;
+ }
+#endif /* HAVE_MAX_FRAGMENT */
+#ifdef WOLFSSL_DTLS
+ if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) {
+ maxFragment = MAX_UDP_SIZE;
+ }
+#endif
+
+ return maxFragment;
+}
+
+
+#undef ERROR_OUT
+
+#endif /* WOLFCRYPT_ONLY */