Index: asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/src/internal.c
===================================================================
--- asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/src/internal.c	(revision 364)
+++ asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/src/internal.c	(revision 372)
@@ -28,4 +28,10 @@
 #include <wolfssl/wolfcrypt/settings.h>
 
+/*
+ * WOLFSSL_SMALL_CERT_VERIFY:
+ *     Verify the certificate signature without using DecodedCert. Doubles up
+ *     on some code but allows smaller dynamic memory usage.
+ */
+
 #ifndef WOLFCRYPT_ONLY
 
@@ -39,4 +45,7 @@
     #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
 
@@ -82,4 +91,6 @@
     #error Cannot use both secure-renegotiation and renegotiation-indication
 #endif
+
+#ifndef WOLFSSL_NO_TLS12
 
 #ifndef NO_WOLFSSL_CLIENT
@@ -101,5 +112,6 @@
 #ifndef NO_WOLFSSL_SERVER
     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(WOLFSSL_NO_CLIENT_AUTH)
         static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
     #endif
@@ -109,8 +121,9 @@
 #endif
 
+#endif /* !WOLFSSL_NO_TLS12 */
 
 #ifdef WOLFSSL_DTLS
-    static INLINE int DtlsCheckWindow(WOLFSSL* ssl);
-    static INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
+    static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl);
+    static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
 #endif
 
@@ -129,4 +142,7 @@
 
 
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+
 /* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
 static const byte tls13Downgrade[7] = {
@@ -135,10 +151,13 @@
 #define TLS13_DOWNGRADE_SZ  sizeof(tls13Downgrade)
 
-
-#ifndef NO_OLD_TLS
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+
+#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);
-
-#endif
+                    int padSz, int content, int verify);
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
 
 #ifdef HAVE_QSH
@@ -160,6 +179,8 @@
     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;
@@ -171,6 +192,5 @@
 }
 
-
-static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
+static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
 {
     (void)isSend;
@@ -186,7 +206,8 @@
 
 
+#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 INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
 {
     int result = ssl->options.dtls;
@@ -200,4 +221,5 @@
     return result;
 }
+#endif /* DTLS || !WOLFSSL_NO_TLS12 */
 
 
@@ -524,6 +546,11 @@
 #endif
     exp[idx++] = sz;
+#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         = ssl->specs.key_size;
@@ -682,12 +709,19 @@
 #endif
     sz = exp[idx++];
-    if (sz > MAX_DIGEST_SIZE || sz + idx > len) {
+#ifndef WOLFSSL_AEAD_ONLY
+    if (sz > sizeof(keys->client_write_MAC_secret) || sz + idx > len) {
         return BUFFER_E;
     }
     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 > AES_256_KEY_SIZE || sz + idx > len) {
+    if (sz > sizeof(keys->client_write_key) || sz + idx > len) {
         return BUFFER_E;
     }
@@ -696,5 +730,5 @@
 
     sz = exp[idx++];
-    if (sz > MAX_WRITE_IV_SZ || sz + idx > len) {
+    if (sz > sizeof(keys->client_write_IV) || sz + idx > len) {
         return BUFFER_E;
     }
@@ -705,5 +739,5 @@
 
     sz = exp[idx++];
-    if (sz > AEAD_MAX_IMP_SZ || sz + idx > len) {
+    if (sz > sizeof(keys->aead_enc_imp_IV) || sz + idx > len) {
         return BUFFER_E;
     }
@@ -741,6 +775,8 @@
 #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;
@@ -904,6 +940,8 @@
 #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;
@@ -1312,6 +1350,7 @@
     }
 
-    /* do not allow stream ciphers with DTLS */
-    if (ssl->specs.cipher_type == stream) {
+    /* 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;
@@ -1331,4 +1370,49 @@
 }
 
+#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)
+    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
+
+#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 */
+
+    return InitSSL_Suites(ssl);
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
 
 /* Initialize SSL context, return 0 on success */
@@ -1343,5 +1427,5 @@
     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 (wc_InitMutex(&ctx->countMutex) < 0) {
@@ -1353,4 +1437,5 @@
 #ifndef NO_DH
     ctx->minDhKeySz  = MIN_DHKEY_SZ;
+    ctx->maxDhKeySz  = MAX_DHKEY_SZ;
 #endif
 #ifndef NO_RSA
@@ -1363,4 +1448,5 @@
 #ifdef OPENSSL_EXTRA
     ctx->verifyDepth = MAX_CHAIN_DEPTH;
+    ctx->cbioFlag = WOLFSSL_CBIO_NONE;
 #endif
 
@@ -1378,4 +1464,13 @@
             #endif
         #endif
+    #elif defined WOLFSSL_UIP
+        ctx->CBIORecv = uIPReceive;
+        ctx->CBIOSend = uIPSend;
+        #ifdef WOLFSSL_DTLS
+        if (method->version.major == DTLS_MAJOR) {
+            ctx->CBIOSendTo = uIPSendTo;
+            ctx->CBIORecvFrom = uIPRecvFrom;
+        }
+        #endif
     #else
         ctx->CBIORecv = EmbedReceive;
@@ -1397,16 +1492,24 @@
     ctx->CBIORecv = NetX_Receive;
     ctx->CBIOSend = NetX_Send;
+#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    ctx->CBIORecv = Mynewt_Receive;
+    ctx->CBIOSend = Mynewt_Send;
 #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)
+    if (method->side == WOLFSSL_CLIENT_END) {
+        ctx->haveECDSAsig  = 1;        /* always on client side */
+        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
     }
 #endif
@@ -1457,4 +1560,5 @@
 
     ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */
+    ctx->verifyDepth = MAX_CHAIN_DEPTH;
 
     return ret;
@@ -1474,10 +1578,15 @@
 
     XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
-    if (ctx->suites)
+    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_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 */
 
@@ -1486,4 +1595,5 @@
         wc_FreeRng(ctx->rng);
         XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG);
+        ctx->rng = NULL;
     }
 #endif /* SINGLE_THREADED */
@@ -1496,18 +1606,24 @@
             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);
+    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->data.name, NULL, DYNAMIC_TYPE_OPENSSL);
             XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL);
             ctx->ca_names = next;
         }
     #endif
-    #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
         while (ctx->x509Chain != NULL) {
             WOLFSSL_STACK *next = ctx->x509Chain->next;
@@ -1536,4 +1652,5 @@
             FreeOcspRequest(ctx->chainOcspRequest[i]);
             XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+            ctx->chainOcspRequest[i] = NULL;
         }
     }
@@ -1542,5 +1659,10 @@
 
 #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) {
@@ -1622,5 +1744,5 @@
     ssl->decrypt.chacha = NULL;
 #endif
-#ifdef HAVE_POLY1305
+#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
     ssl->auth.poly1305 = NULL;
 #endif
@@ -1681,5 +1803,5 @@
     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
@@ -1693,4 +1815,6 @@
 void InitCipherSpecs(CipherSpecs* cs)
 {
+    XMEMSET(cs, 0, sizeof(CipherSpecs));
+
     cs->bulk_cipher_algorithm = INVALID_BYTE;
     cs->cipher_type           = INVALID_BYTE;
@@ -1698,10 +1822,4 @@
     cs->kea                   = INVALID_BYTE;
     cs->sig_algo              = INVALID_BYTE;
-
-    cs->hash_size   = 0;
-    cs->static_ecdh = 0;
-    cs->key_size    = 0;
-    cs->iv_size     = 0;
-    cs->block_size  = 0;
 }
 
@@ -1714,5 +1832,7 @@
     (void)keySz;
 
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
     if (haveECDSAsig) {
+    #ifdef HAVE_ECC
         #ifdef WOLFSSL_SHA512
             suites->hashSigAlgo[idx++] = sha512_mac;
@@ -1732,4 +1852,5 @@
             suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
         #endif
+    #endif
         #ifdef HAVE_ED25519
             suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR;
@@ -1737,4 +1858,5 @@
         #endif
     }
+#endif /* HAVE_ECC || HAVE_ED25519 */
 
     if (haveRSAsig) {
@@ -1742,14 +1864,10 @@
             if (tls1_2) {
             #ifdef WOLFSSL_SHA512
-                if (keySz >= MIN_RSA_SHA512_PSS_BITS) {
                     suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
                     suites->hashSigAlgo[idx++] = sha512_mac;
-                }
             #endif
             #ifdef WOLFSSL_SHA384
-                if (keySz >= MIN_RSA_SHA384_PSS_BITS) {
                   suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
                   suites->hashSigAlgo[idx++] = sha384_mac;
-                }
             #endif
             #ifndef NO_SHA256
@@ -1778,11 +1896,13 @@
     }
 
+        #ifdef HAVE_ANON
     if (haveAnon) {
-        #ifdef HAVE_ANON
             suites->hashSigAlgo[idx++] = sha_mac;
             suites->hashSigAlgo[idx++] = anonymous_sa_algo;
-        #endif
-    }
-
+    }
+#endif
+
+    (void)haveAnon;
+    (void)haveECDSAsig;
     suites->hashSigAlgoSz = (word16)idx;
 }
@@ -1810,4 +1930,7 @@
     (void)haveStaticECC;
     (void)haveECC;
+    (void)side;
+    (void)haveRSA;    /* some builds won't read */
+    (void)haveRSAsig; /* non ecc builds won't read */
 
     if (suites == NULL) {
@@ -1819,13 +1942,52 @@
         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
+#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
@@ -1842,5 +2004,5 @@
 #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;
     }
@@ -1856,5 +2018,5 @@
 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
    if (tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
    }
@@ -1863,5 +2025,5 @@
 #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;
     }
@@ -1870,5 +2032,5 @@
 #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
     if (!dtls && tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
     }
@@ -1877,45 +2039,8 @@
 #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 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
-#endif /* WOLFSSL_TLS13 */
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
@@ -1949,5 +2074,5 @@
 #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;
     }
@@ -1956,5 +2081,5 @@
 #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;
     }
@@ -1963,5 +2088,5 @@
 #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;
     }
@@ -1970,5 +2095,5 @@
 #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;
     }
@@ -2005,6 +2130,20 @@
 #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
@@ -2012,5 +2151,5 @@
 #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;
     }
@@ -2019,5 +2158,5 @@
 #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;
     }
@@ -2026,5 +2165,5 @@
 #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;
     }
@@ -2056,5 +2195,5 @@
 #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;
     }
@@ -2267,5 +2406,5 @@
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
     if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
     }
@@ -2274,5 +2413,5 @@
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
     if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
     }
@@ -2283,5 +2422,5 @@
 #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;
     }
@@ -2291,5 +2430,5 @@
 #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;
     }
@@ -2298,5 +2437,5 @@
 #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
     if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
     }
@@ -2305,5 +2444,5 @@
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
     }
@@ -2312,5 +2451,5 @@
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
     }
@@ -2319,5 +2458,5 @@
 #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;
     }
@@ -2326,5 +2465,5 @@
 #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;
     }
@@ -2362,5 +2501,5 @@
 #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;
     }
@@ -2369,5 +2508,5 @@
 #ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
     }
@@ -2376,5 +2515,5 @@
 #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;
     }
@@ -2383,5 +2522,5 @@
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
     if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
     }
@@ -2390,5 +2529,5 @@
 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
     if (tls && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
     }
@@ -2397,5 +2536,5 @@
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
     if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
     }
@@ -2404,5 +2543,5 @@
 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
     if (tls && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
     }
@@ -2411,5 +2550,5 @@
 #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;
     }
@@ -2488,5 +2627,5 @@
 #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
     if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
     }
@@ -2495,5 +2634,5 @@
 #ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
     if (tls && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
     }
@@ -2509,5 +2648,5 @@
 #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
     if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
     }
@@ -2516,5 +2655,5 @@
 #ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
     if (tls && havePSK) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
     }
@@ -2523,5 +2662,5 @@
 #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;
     }
@@ -2530,5 +2669,5 @@
 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
     if (!dtls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
     }
@@ -2537,5 +2676,5 @@
 #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
     if (!dtls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
     }
@@ -2544,5 +2683,5 @@
 #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;
     }
@@ -2551,5 +2690,5 @@
 #ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
     if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
     }
@@ -2558,5 +2697,5 @@
 #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
     if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
     }
@@ -2565,5 +2704,5 @@
 #ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
     if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
     }
@@ -2572,5 +2711,5 @@
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256;
     }
@@ -2579,5 +2718,5 @@
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
     }
@@ -2586,5 +2725,5 @@
 #ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
     if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
     }
@@ -2593,5 +2732,5 @@
 #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;
     }
@@ -2600,5 +2739,5 @@
 #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;
     }
@@ -2607,5 +2746,5 @@
 #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;
     }
@@ -2614,5 +2753,5 @@
 #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;
     }
@@ -2621,5 +2760,5 @@
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
     }
@@ -2628,5 +2767,5 @@
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
     if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
     }
@@ -2635,5 +2774,5 @@
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
     if (tls && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
     }
@@ -2642,5 +2781,5 @@
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
     if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
     }
@@ -2649,8 +2788,10 @@
 #ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
     if (haveRSA) {
-        suites->suites[idx++] = 0;
+        suites->suites[idx++] = CIPHER_BYTE;
         suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
     }
 #endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
 
     suites->suiteSz = idx;
@@ -2668,5 +2809,5 @@
  * hsType   The signature type.
  */
-static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
+static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
 {
     switch (input[0]) {
@@ -2697,5 +2838,8 @@
 #endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
 
-#if !defined(NO_DH) || defined(HAVE_ECC)
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                       (!defined(NO_RSA) && defined(WC_RSA_PSS))
 
 static enum wc_HashType HashAlgoToType(int hashAlgo)
@@ -2726,7 +2870,9 @@
     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)
@@ -2737,8 +2883,11 @@
         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 */
@@ -2752,8 +2901,20 @@
         if (name->dynamicName)
             XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
-#ifdef OPENSSL_EXTRA
-        if (name->fullName.fullName != 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);
-#endif /* OPENSSL_EXTRA */
+                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;
@@ -2774,38 +2935,5 @@
     InitX509Name(&x509->issuer, 0);
     InitX509Name(&x509->subject, 0);
-    x509->version        = 0;
-    x509->pubKey.buffer  = NULL;
-    x509->sig.buffer     = NULL;
-    x509->derCert        = 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 */
 }
 
@@ -2823,5 +2951,5 @@
     FreeDer(&x509->derCert);
     XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
-    #ifdef OPENSSL_EXTRA
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
         XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
         XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
@@ -2832,12 +2960,12 @@
             XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
         }
-    #endif /* OPENSSL_EXTRA */
+    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
     if (x509->altNames)
-        FreeAltNames(x509->altNames, NULL);
+        FreeAltNames(x509->altNames, x509->heap);
 }
 
-#endif /* !NO_DH || HAVE_ECC */
-
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
 /* Encode the signature algorithm into buffer.
  *
@@ -2846,5 +2974,5 @@
  * output    The buffer to encode into.
  */
-static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
 {
     switch (hsType) {
@@ -2877,5 +3005,8 @@
         /* ED448: 0x0808 */
     }
+    (void)hashAlgo;
+    (void)output;
 }
+
 static void SetDigest(WOLFSSL* ssl, int hashAlgo)
 {
@@ -2907,7 +3038,11 @@
     } /* switch */
 }
-#endif
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !NO_CERTS */
 
 #ifndef NO_RSA
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
 static int TypeHash(int hashAlgo)
 {
@@ -2933,4 +3068,6 @@
     return 0;
 }
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
 
 #if defined(WC_RSA_PSS)
@@ -2969,12 +3106,19 @@
 int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
             word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
-            const byte* keyBuf, word32 keySz, void* ctx)
+            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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
     (void)sigAlgo;
     (void)hashAlgo;
@@ -2983,5 +3127,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3000,4 +3144,5 @@
     #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,
@@ -3015,4 +3160,5 @@
 #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);
@@ -3041,13 +3187,19 @@
 
 int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
-              int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz,
-              void* ctx)
+              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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
     (void)sigAlgo;
     (void)hashAlgo;
@@ -3056,5 +3208,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3072,4 +3224,5 @@
 #ifdef HAVE_PK_CALLBACKS
         if (ssl->ctx->RsaPssVerifyCb) {
+            void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl);
             ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out,
                                            TypeHash(hashAlgo), mgf,
@@ -3084,4 +3237,5 @@
 #ifdef HAVE_PK_CALLBACKS
     if (ssl->ctx->RsaVerifyCb) {
+        void* ctx = wolfSSL_GetRsaVerifyCtx(ssl);
         ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
     }
@@ -3105,11 +3259,23 @@
 
 /* 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)
+    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;
@@ -3117,5 +3283,5 @@
     WOLFSSL_ENTER("VerifyRsaSign");
 
-    if (verifySig == NULL || plain == NULL || key == NULL) {
+    if (verifySig == NULL || plain == NULL) {
         return BAD_FUNC_ARG;
     }
@@ -3127,8 +3293,10 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
+    if (key) {
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
         return ret;
+    }
 #endif
 
@@ -3141,6 +3309,23 @@
         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);
+        }
+        else
+    #endif /* HAVE_PK_CALLBACKS */
+        {
         ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
                                                                            key);
+        }
+
         if (ret > 0) {
             ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType);
@@ -3150,7 +3335,23 @@
     }
     else
-#endif
+#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 ||
@@ -3166,5 +3367,5 @@
     /* Handle async pending response */
 #ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
+    if (key && ret == WC_PENDING_E) {
         ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
     }
@@ -3176,18 +3377,27 @@
 }
 
+#ifndef WOLFSSL_NO_TLS12
+
 int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
-    RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx)
+    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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("RsaDec");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3197,6 +3407,6 @@
 #ifdef HAVE_PK_CALLBACKS
     if (ssl->ctx->RsaDecCb) {
-            ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz,
-                                                                    ctx);
+        void* ctx = wolfSSL_GetRsaDecCtx(ssl);
+        ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
     }
     else
@@ -3230,17 +3440,24 @@
 
 int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
-    RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx)
+    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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("RsaEnc");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3250,6 +3467,6 @@
 #ifdef HAVE_PK_CALLBACKS
     if (ssl->ctx->RsaEncCb) {
-            ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
-                                                                        ctx);
+        void* ctx = wolfSSL_GetRsaEncCtx(ssl);
+        ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx);
     }
     else
@@ -3277,4 +3494,6 @@
 }
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
 #endif /* NO_RSA */
 
@@ -3282,17 +3501,24 @@
 
 int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
-    word32* outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx)
+    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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("EccSign");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3302,4 +3528,5 @@
 #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);
@@ -3324,18 +3551,24 @@
 
 int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
-    word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz,
-    void* ctx)
+    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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("EccVerify");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3345,4 +3578,5 @@
 #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);
@@ -3426,5 +3660,5 @@
 int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
         byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
-        int side, void* ctx)
+        int side)
 {
     int ret;
@@ -3440,5 +3674,4 @@
     (void)pubKeySz;
     (void)side;
-    (void)ctx;
 
     WOLFSSL_ENTER("EccSharedSecret");
@@ -3456,5 +3689,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3464,4 +3697,5 @@
 #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);
@@ -3489,9 +3723,10 @@
     int ret = 0;
     int keySz = 0;
+    int ecc_curve = ECC_CURVE_DEF;
 
     WOLFSSL_ENTER("EccMakeKey");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
     if (ret != 0)
@@ -3499,4 +3734,5 @@
 #endif
 
+    /* get key size */
     if (peer == NULL) {
         keySz = ssl->eccTempKeySz;
@@ -3506,11 +3742,22 @@
     }
 
+    /* get curve type */
     if (ssl->ecdhCurveOID > 0) {
-        ret = wc_ecc_make_key_ex(ssl->rng, keySz, key,
-                 wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL));
-    }
-    else {
-        ret = wc_ecc_make_key(ssl->rng, keySz, key);
-        if (ret == 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;
     }
@@ -3530,4 +3777,41 @@
 
 #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 X25519.
  *
@@ -3540,21 +3824,27 @@
  * keySz  The length of the private key data in bytes.
  * ctx    The callback context.
- * returns 0 on succes, otherwise the valus is an error.
+ * 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, byte* keyBuf, word32 keySz,
-                void* ctx)
+                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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("Ed25519Sign");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3564,4 +3854,5 @@
 #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);
@@ -3595,21 +3886,27 @@
  * keySz  The length of the private key data in bytes.
  * ctx    The callback context.
- * returns 0 on succes, otherwise the valus is an error.
+ * 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, byte* keyBuf, word32 keySz,
-                  void* ctx)
+                  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)keyBuf;
-    (void)keySz;
-    (void)ctx;
+    (void)keyBufInfo;
 
     WOLFSSL_ENTER("Ed25519Verify");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3619,4 +3916,5 @@
 #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);
@@ -3645,4 +3943,6 @@
 }
 #endif /* HAVE_ED25519 */
+
+#ifndef WOLFSSL_NO_TLS12
 
 #ifdef HAVE_CURVE25519
@@ -3686,5 +3986,5 @@
 static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
         curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz,
-        byte* out, word32* outlen, int side, void* ctx)
+        byte* out, word32* outlen, int side)
 {
     int ret;
@@ -3694,10 +3994,9 @@
     (void)pubKeySz;
     (void)side;
-    (void)ctx;
 
     WOLFSSL_ENTER("X25519SharedSecret");
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
     if (ret != 0)
@@ -3711,4 +4010,5 @@
         ret = X25519GetKey(ssl, &otherKey);
         if (ret == 0) {
+            void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl);
             ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer,
                 pubKeySz, out, outlen, side, ctx);
@@ -3744,5 +4044,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
     if (ret != 0)
@@ -3750,7 +4050,18 @@
 #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)
+    }
+
+    if (ret == 0) {
         ssl->ecdhCurveOID = ECC_X25519_OID;
+    }
 
     /* Handle async pending response */
@@ -3766,6 +4077,4 @@
 }
 #endif /* HAVE_CURVE25519 */
-
-#endif /* !NO_CERTS */
 
 #if !defined(NO_CERTS) || !defined(NO_PSK)
@@ -3781,5 +4090,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
     if (ret != 0)
@@ -3813,5 +4122,5 @@
 
 #ifdef WOLFSSL_ASYNC_CRYPT
-    /* intialize event */
+    /* initialize event */
     ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
     if (ret != 0)
@@ -3819,5 +4128,18 @@
 #endif
 
-    ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub, otherPubSz);
+#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
+    {
+        ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub,
+                otherPubSz);
+    }
 
     /* Handle async pending response */
@@ -3835,4 +4157,119 @@
 #endif /* !NO_CERTS || !NO_PSK */
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
+
+#ifdef HAVE_PK_CALLBACKS
+int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
+{
+    int pkcbset = 0;
+    (void)ctx;
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_RSA)
+    if (0
+    #ifdef HAVE_ECC
+        || ctx->EccSignCb != NULL
+    #endif
+    #ifdef HAVE_ED25519
+        || ctx->Ed25519SignCb != 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; /* Squash unused var warnings */
+    (void)haveMcast;
+
+    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 = ssl->options.haveAnon;
+#endif /* HAVE_ANON*/
+#ifdef WOLFSSL_MULTICAST
+    haveMcast = ssl->options.haveMcast;
+#endif /* WOLFSSL_MULTICAST */
+
+#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)
+    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+                                        ssl->buffers.keyType == ed25519_sa_algo;
+#endif
+
+#ifndef NO_CERTS
+    keySz = ssl->buffers.keySz;
+#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, 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
+
+    return WOLFSSL_SUCCESS;
+}
 
 /* This function inherits a WOLFSSL_CTX's fields into an SSL object.
@@ -3848,18 +4285,14 @@
 int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
 {
-    byte havePSK = 0;
-    byte haveAnon = 0;
+    int ret = WOLFSSL_SUCCESS;
     byte newSSL;
-    byte haveRSA = 0;
-    byte haveMcast = 0;
-
-    (void)haveAnon; /* Squash unused var warnings */
-    (void)haveMcast;
 
     if (!ssl || !ctx)
         return BAD_FUNC_ARG;
 
+#ifndef SINGLE_THREADED
     if (ssl->suites == NULL && !writeDup)
         return BAD_FUNC_ARG;
+#endif
 
     newSSL = ssl->ctx == NULL; /* Assign after null check */
@@ -3870,18 +4303,4 @@
     }
 #endif
-
-
-#ifndef NO_RSA
-    haveRSA = 1;
-#endif
-#ifndef NO_PSK
-    havePSK = ctx->havePSK;
-#endif /* NO_PSK */
-#ifdef HAVE_ANON
-    haveAnon = ctx->haveAnon;
-#endif /* HAVE_ANON*/
-#ifdef WOLFSSL_MULTICAST
-    haveMcast = ctx->haveMcast;
-#endif /* WOLFSSL_MULTICAST */
 
     /* decrement previous CTX reference count if exists.
@@ -3904,10 +4323,13 @@
 #ifdef HAVE_ECC
     ssl->eccTempKeySz = ctx->eccTempKeySz;
+    ssl->ecdhCurveOID = ctx->ecdhCurveOID;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
     ssl->pkCurveOID = ctx->pkCurveOID;
-    ssl->ecdhCurveOID = ctx->ecdhCurveOID;
 #endif
 
 #ifdef OPENSSL_EXTRA
     ssl->options.mask = ctx->mask;
+    ssl->CBIS         = ctx->CBIS;
 #endif
     ssl->timeout = ctx->timeout;
@@ -3927,4 +4349,8 @@
     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
@@ -3938,4 +4364,5 @@
 #ifndef NO_DH
     ssl->options.minDhKeySz = ctx->minDhKeySz;
+    ssl->options.maxDhKeySz = ctx->maxDhKeySz;
 #endif
 #ifndef NO_RSA
@@ -3966,4 +4393,8 @@
 
 #ifndef NO_DH
+    #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;
@@ -3981,4 +4412,10 @@
     ssl->buffers.keySz   = ctx->privateKeySz;
 #endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                        !defined(NO_ED25519_CLIENT_AUTH)
+    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+                                        ssl->buffers.keyType == ed25519_sa_algo;
+#endif
+
 
 #ifdef WOLFSSL_ASYNC_CRYPT
@@ -3987,9 +4424,4 @@
 
     if (writeDup == 0) {
-        int keySz = 0;
-#ifndef NO_CERTS
-        keySz = ssl->buffers.keySz;
-#endif
-
 #ifndef NO_PSK
         if (ctx->server_hint[0]) {   /* set in CTX */
@@ -4000,33 +4432,19 @@
 #endif /* NO_PSK */
 
-        if (ctx->suites)
+        if (ctx->suites) {
+#ifndef SINGLE_THREADED
             *ssl->suites = *ctx->suites;
-        else
+#else
+            ssl->suites = ctx->suites;
+#endif
+        }
+        else {
             XMEMSET(ssl->suites, 0, sizeof(Suites));
-
-        /* 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)
-            if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer
-                || !ssl->buffers.key || !ssl->buffers.key->buffer) {
-                WOLFSSL_MSG("Server missing certificate and/or private key");
-                return NO_PRIVATE_KEY;
-            }
-#endif
-
+            }
+
+        if (ssl->options.side != WOLFSSL_NEITHER_END) {
+            /* Defer initializing suites until accept or connect */
+            ret = InitSSL_Suites(ssl);
+        }
     }  /* writeDup check */
 
@@ -4037,9 +4455,12 @@
 #endif
 
+    ssl->CBIORecv = ctx->CBIORecv;
+    ssl->CBIOSend = ctx->CBIOSend;
 #ifdef OPENSSL_EXTRA
     ssl->readAhead = ctx->readAhead;
 #endif
-
-    return WOLFSSL_SUCCESS;
+    ssl->verifyDepth = ctx->verifyDepth;
+
+    return ret;
 }
 
@@ -4113,4 +4534,10 @@
         wc_Sha512Free(&ssl->hsHashes->hashSha512);
     #endif
+    #if defined(HAVE_ED25519) && !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);
@@ -4233,5 +4660,5 @@
     ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
 
-#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
+#ifdef KEEP_PEER_CERT
     InitX509(&ssl->peerCert, 0, ssl->heap);
 #endif
@@ -4247,4 +4674,11 @@
     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;
+    }
+    ssl->IOCB_ReadCtx  = ssl->mnCtx;  /* default Mynewt IO ctx, same for read */
+    ssl->IOCB_WriteCtx = ssl->mnCtx;  /* and write */
 #endif
 
@@ -4260,4 +4694,10 @@
     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
 
 #ifdef WOLFSSL_DTLS
@@ -4276,9 +4716,11 @@
 #endif
 
+#ifndef WOLFSSL_AEAD_ONLY
     #ifndef NO_OLD_TLS
         ssl->hmac = SSL_hmac; /* default to SSLv3 */
-    #else
+    #elif !defined(WOLFSSL_NO_TLS12)
         ssl->hmac = TLS_hmac;
     #endif
+#endif
 
 
@@ -4298,4 +4740,9 @@
         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
 
@@ -4306,5 +4753,5 @@
 #ifdef HAVE_ALPN
     ssl->alpn_client_list = NULL;
-    #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
         ssl->alpnSelect    = ctx->alpnSelect;
         ssl->alpnSelectArg = ctx->alpnSelectArg;
@@ -4321,4 +4768,11 @@
     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);
@@ -4336,4 +4790,5 @@
         }
         XMEMSET(ssl->arrays, 0, sizeof(Arrays));
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER)
         ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
             DYNAMIC_TYPE_SECRET);
@@ -4342,5 +4797,10 @@
         }
         XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
-
+#endif
+
+#ifdef SINGLE_THREADED
+        if (ctx->suites == NULL)
+#endif
+        {
         /* suites */
         ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
@@ -4351,4 +4811,5 @@
         }
     }
+    }
 
     /* Initialize SSL with the appropriate fields from it's ctx */
@@ -4387,8 +4848,10 @@
     }
 
+#ifdef HAVE_WRITE_DUP
     if (writeDup) {
         /* all done */
         return 0;
     }
+#endif
 
     /* hsHashes */
@@ -4434,4 +4897,15 @@
         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) {
+    /* use secure renegotiation by default (not recommend) */
+    #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
+        ret = wolfSSL_UseSecureRenegotiation(ssl);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+    #endif
     }
 #endif
@@ -4598,8 +5072,11 @@
 }
 
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+    defined(HAVE_CURVE25519)
 static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
 {
     int ret = 0;
+
+    (void)ssl;
 
     switch (type) {
@@ -4691,4 +5168,7 @@
         XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
     }
+#ifdef SINGLE_THREADED
+    if (ssl->suites != ssl->ctx->suites)
+#endif
     XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
     FreeHandshakeHashes(ssl);
@@ -4697,4 +5177,11 @@
     /* 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
@@ -4706,5 +5193,5 @@
     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) {
+    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);
@@ -4741,5 +5228,5 @@
 #endif
 #endif /* WOLFSSL_DTLS */
-#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+#ifdef OPENSSL_EXTRA
     if (ssl->biord != ssl->biowr)        /* only free write if different */
         wolfSSL_BIO_free(ssl->biowr);
@@ -4754,21 +5241,28 @@
     FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
     ssl->peerEccDsaKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    {
+        int dtype;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
 #ifdef HAVE_CURVE25519
-    if (!ssl->peerX25519KeyPresent &&
-            ssl->eccTempKeyPresent != DYNAMIC_TYPE_CURVE25519)
-#endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_ECC
+        if (ssl->peerX25519KeyPresent ||
+                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+    #endif /* HAVE_ECC */
     {
-        FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey);
+            dtype = DYNAMIC_TYPE_CURVE25519;
+    }
+    #endif /* HAVE_CURVE25519 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
         ssl->eccTempKeyPresent = 0;
     }
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
 #ifdef HAVE_CURVE25519
-    else {
-        FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->eccTempKey);
-        ssl->eccTempKeyPresent = 0;
-    }
     FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
     ssl->peerX25519KeyPresent = 0;
 #endif
-#endif /* HAVE_ECC */
 #ifdef HAVE_ED25519
     FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
@@ -4800,9 +5294,15 @@
 #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
-#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
+#ifdef KEEP_PEER_CERT
     FreeX509(&ssl->peerCert);
 #endif
@@ -4842,4 +5342,5 @@
         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;
@@ -4861,7 +5362,7 @@
         /* check if tracking stats */
         if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
-            XFREE(ssl_hint->stats, ssl->ctx->heap, DYNAMIC_TYPE_SSL);
-        }
-        XFREE(ssl->heap, ssl->ctx->heap, DYNAMIC_TYPE_SSL);
+            XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
+        }
+        XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
     #ifdef WOLFSSL_HEAP_TEST
     }
@@ -4886,5 +5387,12 @@
         ShrinkInputBuffer(ssl, NO_FORCED_FREE);
 
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    if (!ssl->options.tls1_3)
+#endif
+    {
     /* suites */
+#ifdef SINGLE_THREADED
+        if (ssl->suites != ssl->ctx->suites)
+#endif
     XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
     ssl->suites = NULL;
@@ -4892,7 +5400,19 @@
     /* hsHashes */
     FreeHandshakeHashes(ssl);
+    }
 
     /* RNG */
-    if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) {
+    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);
@@ -4913,8 +5433,16 @@
 #endif
 
+#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 */
@@ -4922,26 +5450,42 @@
     ssl->peerRsaKeyPresent = 0;
 #endif
+#ifdef HAVE_ECC
+        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_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)
+    {
+        int dtype;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
 #ifdef HAVE_CURVE25519
-    if (ssl->ecdhCurveOID != ECC_X25519_OID)
-#endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_ECC
+        if (ssl->peerX25519KeyPresent ||
+                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+    #endif /* HAVE_ECC */
     {
-        FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey);
+            dtype = DYNAMIC_TYPE_CURVE25519;
+    }
+    #endif /* HAVE_CURVE25519 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
         ssl->eccTempKeyPresent = 0;
     }
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
 #ifdef HAVE_CURVE25519
-    else {
-        FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->eccTempKey);
-        ssl->eccTempKeyPresent = 0;
-    }
     FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
     ssl->peerX25519KeyPresent = 0;
-#endif /* HAVE_CURVE25519 */
-#endif /* HAVE_ECC */
+#endif
+
 #ifndef NO_DH
     if (ssl->buffers.serverDH_Priv.buffer) {
@@ -4954,5 +5498,5 @@
     ssl->buffers.serverDH_Pub.buffer = NULL;
     /* parameters (p,g) may be owned by ctx */
-    if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
+    if (ssl->buffers.weOwnDH) {
         XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
         ssl->buffers.serverDH_G.buffer = NULL;
@@ -4961,8 +5505,13 @@
     }
 #endif /* !NO_DH */
+
 #ifndef NO_CERTS
     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);
@@ -4978,4 +5527,5 @@
         ssl->buffers.peerEd25519Key.buffer = NULL;
     #endif
+    }
 #endif /* HAVE_PK_CALLBACKS */
 
@@ -4991,4 +5541,11 @@
         ssl->session.ticketLen = 0;
     }
+#endif
+
+#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
 
@@ -5022,5 +5579,5 @@
 {
     if (ssl->ctx) {
-        FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
+        FreeSSL_Ctx(ssl->ctx); /* will decrement and free underlying CTX if 0 */
     }
     SSL_ResourceFree(ssl);
@@ -5029,8 +5586,10 @@
 }
 
-
-#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
-    || defined(HAVE_AESGCM) || defined(WOLFSSL_DTLS)
-static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
+#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \
+    ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \
+     && defined(HAVE_AEAD))
+
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
 {
     if (verify) {
@@ -5051,8 +5610,9 @@
     }
 }
+#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */
 
 
 #ifdef WOLFSSL_DTLS
-static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
+static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
 {
     if (order == PREV_ORDER) {
@@ -5098,5 +5658,5 @@
 }
 
-static INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
+static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
 {
     word32 seq;
@@ -5126,6 +5686,6 @@
 #endif /* WOLFSSL_DTLS */
 
-
-static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
 {
     word32 seq[2] = {0, 0};
@@ -5143,6 +5703,7 @@
     c32toa(seq[1], out + OPAQUE32_LEN);
 }
-#endif
-
+#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */
+#endif /* !NO_OLD_TLS || WOLFSSL_DTLS ||
+        *     ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM) && HAVE_AEAD) */
 
 #ifdef WOLFSSL_DTLS
@@ -5254,5 +5815,5 @@
         }
 
-        /* if no mesage data, just return */
+        /* if no message data, just return */
         if (fragSz == 0)
             return 0;
@@ -5615,4 +6176,6 @@
 }
 
+#ifndef WOLFSSL_NO_TLS12
+
 ProtocolVersion MakeDTLSv1_2(void)
 {
@@ -5623,4 +6186,6 @@
     return pv;
 }
+
+#endif /* !WOLFSSL_NO_TLS12 */
 
 #endif /* WOLFSSL_DTLS */
@@ -5786,16 +6351,67 @@
     }
 
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+
+    #define NU_TICKS_PER_SECOND 100
+
+    word32 LowResTimer(void)
+    {
+        /* 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
     /* Posix style time */
+    #ifndef USER_TIME
     #include <time.h>
+    #endif
 
     word32 LowResTimer(void)
     {
-        return (word32)time(0);
-    }
-
-
-#endif
-
+        return (word32)XTIME(0);
+    }
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+/* Store the message for use with CertificateVerify using Ed25519.
+ *
+ * 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 Ed25519Update(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 && !WOLFSSL_NO_CLIENT_AUTH */
 
 #ifndef NO_CERTS
@@ -5839,4 +6455,10 @@
             return ret;
 #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
     }
 
@@ -5890,4 +6512,10 @@
             return ret;
 #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
     }
 
@@ -5943,4 +6571,10 @@
             return ret;
 #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
     }
 
@@ -5962,6 +6596,11 @@
     rl->pvMajor = ssl->version.major;       /* type and version same in each */
 #ifdef WOLFSSL_TLS13
-    if (IsAtLeastTLSv1_3(ssl->version))
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+#ifdef WOLFSSL_TLS13_DRAFT_18
         rl->pvMinor = TLSv1_MINOR;
+#else
+        rl->pvMinor = TLSv1_2_MINOR;
+#endif
+    }
     else
 #endif
@@ -5993,4 +6632,6 @@
 
 
+#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,
@@ -6005,4 +6646,7 @@
     /* handshake header */
     hs = (HandShakeHeader*)output;
+    if (hs == NULL)
+        return;
+
     hs->type = type;
     c32to24(length, hs->length);         /* type and length same for each */
@@ -6020,5 +6664,4 @@
 }
 
-
 /* add both headers for handshake message */
 static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
@@ -6037,6 +6680,8 @@
     AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
 }
-
-
+#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */
+
+
+#ifndef WOLFSSL_NO_TLS12
 #ifndef NO_CERTS
 static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
@@ -6058,12 +6703,13 @@
 }
 #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;
@@ -6071,5 +6717,5 @@
 
 retry:
-    recvd = ssl->ctx->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+    recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
     if (recvd < 0)
         switch (recvd) {
@@ -6099,4 +6745,7 @@
                             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;
@@ -6110,6 +6759,6 @@
                 return -1;
 
+                #ifdef WOLFSSL_DTLS
             case WOLFSSL_CBIO_ERR_TIMEOUT:
-                #ifdef WOLFSSL_DTLS
                 if (IsDtlsNotSctpMode(ssl) &&
                     !ssl->options.handShakeDone &&
@@ -6119,6 +6768,6 @@
                     goto retry;
                 }
-                #endif
                 return -1;
+            #endif
 
             default:
@@ -6171,5 +6820,5 @@
 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;
@@ -6185,5 +6834,5 @@
 
     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,
@@ -6210,4 +6859,7 @@
                                 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;
@@ -6247,5 +6899,5 @@
 
 /* Grow the output buffer */
-static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
+static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
 {
     byte* tmp;
@@ -6444,5 +7096,10 @@
     if (rh->pvMajor != ssl->version.major ||
         (rh->pvMinor != ssl->version.minor &&
-         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_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
     {
@@ -6494,5 +7151,5 @@
 }
 
-
+#ifndef WOLFSSL_NO_TLS12
 static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                               byte *type, word32 *size, word32 totalSz)
@@ -6510,5 +7167,5 @@
     return 0;
 }
-
+#endif
 
 #ifdef WOLFSSL_DTLS
@@ -6669,31 +7326,13 @@
 #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_SHA384
-#ifdef WOLFSSL_SMALL_STACK
-    wc_Sha384* sha384;
-#else
-    wc_Sha384 sha384[1];
-#endif /* WOLFSSL_SMALL_STACK */
-#endif /* WOLFSSL_SHA384 */
 
     if (ssl == NULL)
         return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SHA384
-#ifdef WOLFSSL_SMALL_STACK
-    sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), ssl->heap, DYNAMIC_TYPE_HASHCTX);
-    if (sha384 == NULL)
-        return MEMORY_E;
-#endif /* WOLFSSL_SMALL_STACK */
-#endif /* WOLFSSL_SHA384 */
-
-    /* store current states, building requires get_digest which resets state */
-#ifdef WOLFSSL_SHA384
-    sha384[0] = ssl->hsHashes->hashSha384;
-#endif
 
 #ifndef NO_TLS
@@ -6711,21 +7350,10 @@
 #endif
 
-    /* restore */
-    if (IsAtLeastTLSv1_2(ssl)) {
-    #ifdef WOLFSSL_SHA384
-        ssl->hsHashes->hashSha384 = sha384[0];
-    #endif
-    }
-
-#ifdef WOLFSSL_SHA384
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sha384, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-#endif
-
     return ret;
 }
 
-
+#endif /* WOLFSSL_NO_TLS12 */
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
     /* cipher requirements */
     enum {
@@ -6747,8 +7375,12 @@
     {
 
+        (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)
@@ -6804,4 +7436,5 @@
             }
         }
+#endif /* HAVE_CHACHA */
 
         /* ECC extensions */
@@ -6809,5 +7442,5 @@
 
         switch (second) {
-
+#ifdef HAVE_ECC
 #ifndef NO_RSA
         case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
@@ -6835,5 +7468,5 @@
                 return 1;
             break;
-#endif
+    #endif /* !NO_DES3 */
 
 #ifndef NO_RC4
@@ -6849,5 +7482,5 @@
                 return 1;
             break;
-#endif
+    #endif /* !NO_RC4 */
 #endif /* NO_RSA */
 
@@ -6862,5 +7495,5 @@
                 return 1;
             break;
-#endif
+    #endif /* !NO_DES3  */
 #ifndef NO_RC4
         case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
@@ -6873,5 +7506,5 @@
                 return 1;
             break;
-#endif
+    #endif /* !NO_RC4 */
 #ifndef NO_RSA
         case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
@@ -6886,5 +7519,5 @@
                 return 1;
             break;
-#endif
+    #endif /* !NO_RSA */
 
         case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
@@ -6927,6 +7560,8 @@
                 return 1;
             break;
+#endif /* HAVE_ECC */
 
 #ifndef NO_RSA
+    #ifdef HAVE_ECC
         case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
             if (requirement == REQUIRES_RSA)
@@ -6952,5 +7587,6 @@
                 return 1;
             break;
-
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_AESCCM
         case TLS_RSA_WITH_AES_128_CCM_8 :
         case TLS_RSA_WITH_AES_256_CCM_8 :
@@ -6960,4 +7596,6 @@
                 return 1;
             break;
+    #endif /* HAVE_AESCCM */
+    #ifdef HAVE_ECC
 
         case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
@@ -6974,6 +7612,8 @@
                 return 1;
             break;
-#endif
-
+    #endif /* HAVE_ECC */
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
         case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
         case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
@@ -6996,5 +7636,7 @@
                 return 1;
             break;
-
+#endif /* HAVE_ECC */
+
+#ifndef NO_PSK
         case TLS_PSK_WITH_AES_128_CCM:
         case TLS_PSK_WITH_AES_256_CCM:
@@ -7012,5 +7654,6 @@
                 return 1;
             break;
-
+#endif /* !NO_PSK */
+#ifdef HAVE_ECC
         case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
             if (requirement == REQUIRES_ECC)
@@ -7027,5 +7670,5 @@
                 return 1;
             break;
-
+#endif /* HAVE_ECC */
         default:
             WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
@@ -7033,4 +7676,6 @@
         }   /* switch */
         }   /* if     */
+
+#endif /* !WOLFSSL_NO_TLS12 */
 
         /* Distinct TLS v1.3 cipher suites with cipher and digest only. */
@@ -7054,4 +7699,6 @@
         }
 
+#ifndef WOLFSSL_NO_TLS12
+
         if (first != ECC_BYTE && first != CHACHA_BYTE &&
             first != TLS13_BYTE) {   /* normal suites */
@@ -7059,4 +7706,5 @@
 
 #ifndef NO_RSA
+    #ifndef NO_RC4
         case SSL_RSA_WITH_RC4_128_SHA :
             if (requirement == REQUIRES_RSA)
@@ -7068,4 +7716,5 @@
                 return 1;
             break;
+    #endif /* NO_RC4 */
 
         case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
@@ -7074,8 +7723,10 @@
             break;
 
+    #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 :
@@ -7089,8 +7740,10 @@
             break;
 
+    #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 :
@@ -7099,8 +7752,10 @@
             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 :
@@ -7115,15 +7770,20 @@
             break;
 
+    #ifdef HAVE_NTRU
         case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
             if (requirement == REQUIRES_NTRU)
                 return 1;
             break;
-
+    #endif /* HAVE_NTRU */
+
+    #ifdef HAVE_IDEA
         case SSL_RSA_WITH_IDEA_CBC_SHA :
             if (requirement == REQUIRES_RSA)
                 return 1;
             break;
-#endif
-
+    #endif /* HAVE_IDEA */
+#endif /* !NO_RSA */
+
+#ifndef NO_PSK
         case TLS_PSK_WITH_AES_128_GCM_SHA256 :
         case TLS_PSK_WITH_AES_256_GCM_SHA384 :
@@ -7150,4 +7810,5 @@
                 return 1;
             break;
+#endif /* NO_PSK */
 
 #ifndef NO_RSA
@@ -7180,4 +7841,5 @@
             break;
 
+#ifndef NO_HC128
         case TLS_RSA_WITH_HC_128_MD5 :
             if (requirement == REQUIRES_RSA)
@@ -7194,5 +7856,7 @@
                 return 1;
             break;
-
+#endif /* NO_HC128 */
+
+#ifdef HAVE_BLAKE2
         case TLS_RSA_WITH_AES_128_CBC_B2B256:
         case TLS_RSA_WITH_AES_256_CBC_B2B256:
@@ -7200,9 +7864,12 @@
                 return 1;
             break;
-
+#endif /* HAVE_BLAKE2 */
+
+#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 :
@@ -7220,4 +7887,5 @@
             break;
 
+#ifdef HAVE_CAMELLIA
         case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
         case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
@@ -7239,4 +7907,5 @@
                 return 1;
             break;
+#endif /* HAVE_CAMELLIA */
 
         case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
@@ -7254,4 +7923,8 @@
                 return 1;
             break;
+        case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
 #endif
 #ifdef WOLFSSL_MULTICAST
@@ -7266,6 +7939,10 @@
         }  /* if ECC / Normal suites else */
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
         return 0;
     }
+
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
 
 
@@ -7280,4 +7957,5 @@
 int MatchDomainName(const char* pattern, int len, const char* str)
 {
+    int ret = 0;
     char p, s;
 
@@ -7288,5 +7966,5 @@
 
         p = (char)XTOLOWER((unsigned char)*pattern++);
-        if (p == 0)
+        if (p == '\0')
             break;
 
@@ -7312,12 +7990,16 @@
         }
 
-        if (*str != '\0')
+
+        if (len > 0) {
             str++;
-
-        if (len > 0)
             len--;
     }
-
-    return *str == '\0';
+    }
+
+    if (*str == '\0' && len == 0) {
+        ret = 1; /* success */
+    }
+
+    return ret;
 }
 
@@ -7337,5 +8019,5 @@
         WOLFSSL_MSG("\tindividual AltName check");
 
-        if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){
+        if (MatchDomainName(altName->name, altName->len, domain)){
             match = 1;
             break;
@@ -7374,6 +8056,5 @@
         WOLFSSL_MSG("\tindividual AltName check");
 
-        if (MatchDomainName(altName->name, (int)XSTRLEN(altName->name),
-                            domain)) {
+        if (MatchDomainName(altName->name, altName->len, domain)) {
             match = 1;
             *checkCN = 0;
@@ -7437,6 +8118,9 @@
 #endif
 
-#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
+#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)
 {
@@ -7452,5 +8136,5 @@
     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,
@@ -7464,10 +8148,10 @@
     }
     x509->issuer.x509 = x509;
-#endif /* OPENSSL_EXTRA */
+#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,
@@ -7480,13 +8164,17 @@
     }
     x509->subject.x509 = x509;
-#endif /* OPENSSL_EXTRA */
-#ifdef WOLFSSL_NGINX
-    XMEMCPY(x509->subject.raw, dCert->subjectRaw, dCert->subjectRawLen);
-    x509->subject.rawLen = dCert->subjectRawLen;
+#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';
@@ -7575,6 +8263,44 @@
     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;
@@ -7657,6 +8383,6 @@
         }
     #endif /* WOLFSSL_CERT_EXT */
-#endif /* OPENSSL_EXTRA */
-#ifdef HAVE_ECC
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
     x509->pkCurveOID = dCert->pkCurveOID;
 #endif /* HAVE_ECC */
@@ -7666,19 +8392,158 @@
 
 #endif /* KEEP_PEER_CERT || SESSION_CERTS */
+
+#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)
+{
+    int ret = 0;
+    OcspRequest* request;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        CertStatus* status;
+        OcspResponse* response;
+    #else
+        CertStatus status[1];
+        OcspResponse response[1];
+    #endif
+
+    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);
+
+    if (request == NULL)
+        return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
+
+    #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, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+            if (response)
+                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+
+            return MEMORY_ERROR;
+        }
+    #endif
+
+    InitOcspResponse(response, status, input +*inOutIdx, status_length);
+
+    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;
+
+    *inOutIdx += status_length;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(status,   ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    #endif
+
+    return ret;
+}
+#endif
+
+
+
+#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;
+
+        if (ssl && ssl->ctx->RsaVerifyCb) {
+            ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz,
+                ssl->RsaVerifyCtx);
+        }
+        return ret;
+    }
+#endif
+
+int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
+{
+    if (ssl == NULL || sigCtx == NULL)
+        return BAD_FUNC_ARG;
+
+    /* 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;
+}
+
+#endif /* HAVE_PK_CALLBACKS */
+
 
 typedef struct ProcPeerCertArgs {
     buffer*      certs;
 #ifdef WOLFSSL_TLS13
-    buffer*      exts; /* extentions */
+    buffer*      exts; /* extensions */
 #endif
     DecodedCert* dCert;
-    char*  domain;
     word32 idx;
     word32 begin;
     int    totalCerts; /* number of certs in certs buffer */
     int    count;
-    int    dCertInit;
     int    certIdx;
-    int    fatal;
     int    lastErr;
 #ifdef WOLFSSL_ALT_CERT_CHAINS
@@ -7688,11 +8553,204 @@
     byte   ctxSz;
 #endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    char   untrustedDepth;
+#endif
+    word16 fatal:1;
+    word16 verifyErr:1;
+    word16 dCertInit:1;
 #ifdef WOLFSSL_TRUST_PEER_CERT
-    byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */
-#endif
-#ifdef OPENSSL_EXTRA
-    char   untrustedDepth;
+    word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */
 #endif
 } ProcPeerCertArgs;
+
+/* 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)
+ */
+
+static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
+{
+    int verify_ok = 0, alertWhy = 0, use_cb = 0;
+
+    /* Determine return code and alert reason */
+    if (ret != 0) {
+        alertWhy = bad_certificate;
+        if (ret == ASN_AFTER_DATE_E ||
+            ret == ASN_BEFORE_DATE_E) {
+            alertWhy = certificate_expired;
+    }
+    }
+    else {
+        verify_ok = 1;
+    }
+
+    /* Determine if verify callback should be used */
+    if (ret != 0) {
+        if (!ssl->options.verifyNone) {
+            use_cb = 1; /* always report errors */
+        }
+    }
+#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 verify callback has been set */
+    if (use_cb && ssl->verifyCallback) {
+    #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 WOLFSSL_SMALL_STACK
+        store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+            sizeof(WOLFSSL_X509_STORE_CTX), ssl->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), ssl->heap,
+            DYNAMIC_TYPE_X509);
+        if (x509 == NULL) {
+            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509);
+            return MEMORY_E;
+    }
+#endif
+        domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, DYNAMIC_TYPE_STRING);
+        if (domain == NULL) {
+            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509);
+            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+            XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
+    #endif
+            return MEMORY_E;
+    }
+    #endif /* WOLFSSL_SMALL_STACK */
+
+        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';
+            }
+        }
+
+        store->error = ret;
+        store->error_depth = args->certIdx;
+        store->discardSessionCerts = 0;
+        store->domain = domain;
+        store->userCtx = ssl->verifyCbCtx;
+        store->certs = args->certs;
+        store->totalCerts = args->totalCerts;
+        store->ex_data = ssl;
+
+    #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;
+        }
+    #endif
+    #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, ssl->heap);
+            if (CopyDecodedToX509(x509, args->dCert) == 0) {
+                store->current_cert = x509;
+            }
+        }
+    #endif
+    #ifdef SESSION_CERTS
+        store->sesChain = &ssl->session.chain;
+    #endif
+        /* non-zero return code indicates failure override */
+        if (ssl->verifyCallback(verify_ok, store)) {
+            if (ret != 0) {
+                WOLFSSL_MSG("Verify callback overriding error!");
+                ret = 0;
+            }
+        }
+        else {
+            /* 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 (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 WOLFSSL_SMALL_STACK
+        XFREE(domain, ssl->heap, DYNAMIC_TYPE_STRING);
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
+        #endif
+        XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
+    #endif
+    }
+
+    if (ret != 0) {
+        if (!ssl->options.verifyNone) {
+            /* handle failure */
+            SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
+            ssl->options.isClosed = 1;
+        }
+
+        /* Report SSL error */
+        ssl->error = ret;
+    }
+
+    return ret;
+}
 
 static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
@@ -7702,8 +8760,4 @@
     (void)ssl;
 
-    if (args->domain) {
-        XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_STRING);
-        args->domain = NULL;
-    }
     if (args->certs) {
         XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
@@ -7729,9 +8783,13 @@
                      word32 totalSz)
 {
-    int ret = 0;
+    int ret = 0, sigRet = 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];
@@ -7753,4 +8811,19 @@
     }
     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
     {
@@ -7763,4 +8836,6 @@
     #ifdef WOLFSSL_ASYNC_CRYPT
         ssl->async.freeArgs = FreeProcPeerCertArgs;
+    #elif defined(WOLFSSL_NONBLOCK_OCSP)
+        ssl->nonblockarg = args;
     #endif
     }
@@ -7774,5 +8849,5 @@
         #ifdef WOLFSSL_CALLBACKS
             if (ssl->hsInfoOn)
-                AddPacketName("Certificate", &ssl->handShakeInfo);
+                AddPacketName(ssl, "Certificate");
             if (ssl->toInfoOn)
                 AddLateName("Certificate", &ssl->timeoutInfo);
@@ -7842,4 +8917,12 @@
 
             /* 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);
@@ -7848,5 +8931,5 @@
             }
             XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
-
+        #endif /* OPENSSL_EXTRA */
             /* Certificate List */
             if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
@@ -7855,5 +8938,5 @@
             c24to32(input + args->idx, &listSz);
             args->idx += OPAQUE24_LEN;
-            if (listSz > MAX_RECORD_SIZE) {
+            if (listSz > MAX_CERTIFICATE_SZ) {
                 ERROR_OUT(BUFFER_ERROR, exit_ppc);
             }
@@ -7868,10 +8951,15 @@
                 word32 certSz;
 
-                if (args->totalCerts >= MAX_CHAIN_DEPTH) {
                 #ifdef OPENSSL_EXTRA
+                if (args->totalCerts > ssl->verifyDepth) {
                     ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
-                #endif
                     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) {
@@ -7913,4 +9001,8 @@
                     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)
+                        return ret;
                 }
             #endif
@@ -7924,4 +9016,5 @@
 
             args->dCertInit = 0;
+#ifndef WOLFSSL_SMALL_CERT_VERIFY
             args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
                                                        DYNAMIC_TYPE_DCERT);
@@ -7929,4 +9022,5 @@
                 ERROR_OUT(MEMORY_E, exit_ppc);
             }
+#endif
 
             /* Advance state and proceed */
@@ -7947,4 +9041,15 @@
 
                     if (!args->dCertInit) {
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+                        if (args->dCert == NULL) {
+                            args->dCert = (DecodedCert*)XMALLOC(
+                                                 sizeof(DecodedCert), ssl->heap,
+                                                 DYNAMIC_TYPE_DCERT);
+                            if (args->dCert == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_ppc);
+                            }
+                        }
+#endif
+
                         InitDecodedCert(args->dCert,
                             cert->buffer, cert->length, ssl->heap);
@@ -7954,11 +9059,13 @@
                     #endif
                         args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
                     }
 
                     ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
                                                             ssl->ctx->cm);
-                    if (ret != 0 && ret != WC_PENDING_E)
-                        goto exit_ppc;
-
                 #ifdef WOLFSSL_ASYNC_CRYPT
                     if (ret == WC_PENDING_E) {
@@ -7968,4 +9075,6 @@
                     }
                 #endif
+                    if (ret != 0)
+                        goto exit_ppc;
 
                 #ifndef NO_SKID
@@ -8015,4 +9124,15 @@
 
                     if (!args->dCertInit) {
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+                        if (args->dCert == NULL) {
+                            args->dCert = (DecodedCert*)XMALLOC(
+                                                 sizeof(DecodedCert), ssl->heap,
+                                                 DYNAMIC_TYPE_DCERT);
+                            if (args->dCert == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_ppc);
+                            }
+                        }
+#endif
+
                         InitDecodedCert(args->dCert,
                             cert->buffer, cert->length, ssl->heap);
@@ -8022,11 +9142,13 @@
                     #endif
                         args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
                     }
 
                     ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
                                                                   ssl->ctx->cm);
-                    if (ret != 0 && ret != WC_PENDING_E) {
-                        goto exit_ppc;
-                    }
                 #ifdef WOLFSSL_ASYNC_CRYPT
                     if (ret == WC_PENDING_E) {
@@ -8036,4 +9158,7 @@
                     }
                 #endif
+                    if (ret != 0) {
+                        goto exit_ppc;
+                    }
 
                 #ifndef NO_SKID
@@ -8044,4 +9169,5 @@
                     if (!AlreadySigner(ssl->ctx->cm, subjectHash))
                         args->untrustedDepth = 1;
+
                     FreeDecodedCert(args->dCert);
                     args->dCertInit = 0;
@@ -8061,5 +9187,32 @@
                     cert = &args->certs[args->certIdx];
 
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+                    sigRet = 0;
+
+                    if (!ssl->options.verifyNone) {
+                        if (args->dCert != NULL) {
+                            if (args->dCertInit) {
+                                FreeDecodedCert(args->dCert);
+                                args->dCertInit = 0;
+                            }
+                            XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+                            args->dCert = NULL;
+                        }
+                        sigRet = CheckCertSignature(cert->buffer, cert->length,
+                                                       ssl->heap, ssl->ctx->cm);
+                    }
+#endif
                     if (!args->dCertInit) {
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+                        if (args->dCert == NULL) {
+                            args->dCert = (DecodedCert*)XMALLOC(
+                                                 sizeof(DecodedCert), ssl->heap,
+                                                 DYNAMIC_TYPE_DCERT);
+                            if (args->dCert == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_ppc);
+                            }
+                        }
+#endif
+
                         InitDecodedCert(args->dCert,
                             cert->buffer, cert->length, ssl->heap);
@@ -8069,10 +9222,31 @@
                     #endif
                         args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
                     }
 
+                    /* check if returning from non-blocking OCSP */
+                #ifdef WOLFSSL_NONBLOCK_OCSP
+                    if (args->lastErr != OCSP_WANT_READ)
+                    {
+                #endif
+
+#ifndef WOLFSSL_SMALL_CERT_VERIFY
+                    sigRet = ParseCertRelative(args->dCert, CERT_TYPE,
+                                    !ssl->options.verifyNone, ssl->ctx->cm);
+#else
                     ret = ParseCertRelative(args->dCert, CERT_TYPE,
-                                    !ssl->options.verifyNone, ssl->ctx->cm);
+                             !ssl->options.verifyNone ? VERIFY_NAME : NO_VERIFY,
+                             ssl->ctx->cm);
+                    if (ret != 0) {
+                        sigRet = ret;
+                        ret = 0;
+                    }
+#endif
                 #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
+                    if (sigRet == WC_PENDING_E) {
                         ret = wolfSSL_AsyncPush(ssl,
                             args->dCert->sigCtx.asyncDev);
@@ -8098,5 +9272,5 @@
                                     WOLFSSL_MSG(
                                         "RSA key size in cert chain error");
-                                    ret = RSA_KEY_SIZE_E;
+                                    sigRet = RSA_KEY_SIZE_E;
                                 }
                                 break;
@@ -8109,5 +9283,5 @@
                                     WOLFSSL_MSG(
                                         "ECC key size in cert chain error");
-                                    ret = ECC_KEY_SIZE_E;
+                                    sigRet = ECC_KEY_SIZE_E;
                                 }
                                 break;
@@ -8120,5 +9294,5 @@
                                     WOLFSSL_MSG(
                                         "ECC key size in cert chain error");
-                                    ret = ECC_KEY_SIZE_E;
+                                    sigRet = ECC_KEY_SIZE_E;
                                 }
                                 break;
@@ -8132,11 +9306,11 @@
                     } /* if (!ssl->options.verifyNone) */
 
-                    if (ret == 0 && args->dCert->isCA == 0) {
+                    if (sigRet == 0 && args->dCert->isCA == 0) {
                         WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
                     }
-                    else if (ret == 0 && ssl->options.verifyNone) {
+                    else if (sigRet == 0 && ssl->options.verifyNone) {
                         WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
                     }
-                    else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
+                    else if (sigRet == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
                         DerBuffer* add = NULL;
                         ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
@@ -8148,7 +9322,7 @@
                         XMEMCPY(add->buffer, cert->buffer, cert->length);
 
-                    #ifdef WOLFSSL_NGINX
+                    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
                         if (args->certIdx > args->untrustedDepth)
-                            args->untrustedDepth = args->certIdx + 1;
+                            args->untrustedDepth = (char)args->certIdx + 1;
                     #endif
 
@@ -8166,4 +9340,5 @@
 
                             /* clear last CA fail since CA cert was validated */
+                            if (!args->verifyErr)
                             args->lastCaErr = 0;
 
@@ -8175,16 +9350,6 @@
                     #endif
                     }
-                    else if (ret != 0) {
+                    else if (sigRet != 0) {
                         WOLFSSL_MSG("Failed to verify CA from chain");
-                    #ifdef WOLFSSL_ALT_CERT_CHAINS
-                        if (args->lastCaErr == 0) {
-                            /* store CA error and proceed to next cert */
-                            args->lastCaErr = ret;
-                            ret = 0;
-                        }
-                        else {
-                            args->lastErr = args->lastCaErr;
-                        }
-                    #endif
                     #ifdef OPENSSL_EXTRA
                         ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
@@ -8195,6 +9360,13 @@
                     }
 
+                #ifdef WOLFSSL_NONBLOCK_OCSP
+                    }
+                    else {
+                        args->lastErr = 0; /* clear last error */
+                    }
+                #endif
+
             #if defined(HAVE_OCSP) || defined(HAVE_CRL)
-                    if (ret == 0) {
+                    if (ret == 0 && sigRet == 0) {
                         int doCrlLookup = 1;
                 #ifdef HAVE_OCSP
@@ -8211,7 +9383,7 @@
                             ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
                                                     args->dCert, NULL, ssl);
-                        #ifdef WOLFSSL_ASYNC_CRYPT
-                            /* non-blocking socket re-entry requires async */
-                            if (ret == WANT_READ) {
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
                                 goto exit_ppc;
                             }
@@ -8231,7 +9403,7 @@
                             WOLFSSL_MSG("Doing Non Leaf CRL check");
                             ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
-                        #ifdef WOLFSSL_ASYNC_CRYPT
-                            /* non-blocking socket re-entry requires async */
-                            if (ret == WANT_READ) {
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
                                 goto exit_ppc;
                             }
@@ -8243,10 +9415,27 @@
                 #endif /* HAVE_CRL */
                         (void)doCrlLookup;
+
+                        if (ret != 0)
+                            sigRet = ret;
                     }
             #endif /* HAVE_OCSP || HAVE_CRL */
 
-                    if (ret != 0 && args->lastErr == 0) {
-                        args->lastErr = ret;   /* save error from last time */
-                        ret = 0; /* reset error */
+                    /* Do verify callback */
+                    sigRet = DoVerifyCallback(ssl, sigRet, args);
+
+                    /* Handle error codes */
+                #ifdef WOLFSSL_ALT_CERT_CHAINS
+                    if (args->lastCaErr == 0) {
+                        /* capture CA error and proceed to next cert */
+                        args->lastCaErr = sigRet;
+                        sigRet = 0;
+                    }
+                    else {
+                        args->lastErr = args->lastCaErr;
+                    }
+                #endif
+                    if (sigRet != 0 && args->lastErr == 0) {
+                        args->lastErr = sigRet;  /* save error from last time */
+                        sigRet = 0; /* reset error */
                     }
 
@@ -8257,4 +9446,6 @@
             } /* if (count > 0) */
 
+            if (sigRet != 0)
+                ret = sigRet;
             /* Check for error */
             if (ret != 0) {
@@ -8276,5 +9467,29 @@
                 cert = &args->certs[args->certIdx];
 
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+                sigRet = 0;
+
+                if (!ssl->options.verifyNone) {
+                    if (args->dCert != NULL) {
+                        if (args->dCertInit) {
+                            FreeDecodedCert(args->dCert);
+                            args->dCertInit = 0;
+                        }
+                        XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+                        args->dCert = NULL;
+                    }
+                    sigRet = CheckCertSignature(cert->buffer, cert->length,
+                                                       ssl->heap, ssl->ctx->cm);
+                }
+#endif
                 if (!args->dCertInit) {
+                    if (args->dCert == NULL) {
+                        args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
+                                                 ssl->heap, DYNAMIC_TYPE_DCERT);
+                        if (args->dCert == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_ppc);
+                        }
+                    }
+
                     InitDecodedCert(args->dCert,
                         cert->buffer, cert->length, ssl->heap);
@@ -8284,4 +9499,9 @@
                 #endif
                     args->dCertInit = 1;
+                #ifdef HAVE_PK_CALLBACKS
+                    ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                    if (ret != 0)
+                        goto exit_ppc;
+                #endif
                 }
 
@@ -8291,8 +9511,18 @@
                 {
                     /* only parse if not already present in dCert from above */
+#ifndef WOLFSSL_SMALL_CERT_VERIFY
+                    sigRet = ParseCertRelative(args->dCert, CERT_TYPE,
+                                    !ssl->options.verifyNone, ssl->ctx->cm);
+#else
                     ret = ParseCertRelative(args->dCert, CERT_TYPE,
-                                    !ssl->options.verifyNone, ssl->ctx->cm);
+                             !ssl->options.verifyNone ? VERIFY_NAME : NO_VERIFY,
+                             ssl->ctx->cm);
+                    if (ret != 0) {
+                        sigRet = ret;
+                        ret = 0;
+                    }
+#endif
                 #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
+                    if (sigRet == WC_PENDING_E) {
                         ret = wolfSSL_AsyncPush(ssl,
                             args->dCert->sigCtx.asyncDev);
@@ -8302,5 +9532,5 @@
                 }
 
-                if (ret == 0) {
+                if (sigRet == 0) {
                     WOLFSSL_MSG("Verified Peer's cert");
                 #ifdef OPENSSL_EXTRA
@@ -8313,9 +9543,25 @@
                     }
                 #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+
+                    /* check if fatal error */
+                    if (args->verifyErr) {
+                        args->fatal = 1;
+                        if (sigRet == 0) {
+                            sigRet = args->lastErr;
+                        }
+                    #ifdef WOLFSSL_ALT_CERT_CHAINS
+                        if (sigRet == 0) {
+                            sigRet = args->lastCaErr;
+                        }
+                    #endif
+                    }
+                    else {
                     args->fatal = 0;
                 }
-                else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
+                }
+                else if (sigRet == ASN_PARSE_E || sigRet == BUFFER_E) {
                     WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
                 #ifdef OPENSSL_EXTRA
+                    SendAlert(ssl, alert_fatal, bad_certificate);
                     ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
                 #endif
@@ -8330,9 +9576,13 @@
                         WOLFSSL_MSG(
                             "\tCallback override available, will continue");
-                        args->fatal = 0;
+                        /* check if fatal error */
+                        args->fatal = (args->verifyErr) ? 1 : 0;
                     }
                     else {
                         WOLFSSL_MSG("\tNo callback override available, fatal");
                         args->fatal = 1;
+                    #ifdef OPENSSL_EXTRA
+                        SendAlert(ssl, alert_fatal, bad_certificate);
+                    #endif
                     }
                 }
@@ -8350,5 +9600,5 @@
                                 "Peer sent different cert during scr, fatal");
                             args->fatal = 1;
-                            ret   = SCR_DIFFERENT_CERT_E;
+                            sigRet   = SCR_DIFFERENT_CERT_E;
                         }
                     }
@@ -8361,5 +9611,21 @@
                 }
             #endif /* HAVE_SECURE_RENEGOTIATION */
-
+            } /* if (count > 0) */
+
+            if (sigRet != 0)
+                ret = sigRet;
+            /* 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) {
@@ -8372,4 +9638,19 @@
                                                     args->dCert, ssl->heap);
                             doLookup = 0;
+                        #ifdef WOLFSSL_TLS13
+                            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 */
@@ -8388,7 +9669,6 @@
                         ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
                                                     args->dCert, NULL, ssl);
-                    #ifdef WOLFSSL_ASYNC_CRYPT
-                        /* non-blocking socket re-entry requires async */
-                        if (ret == WANT_READ) {
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
                             goto exit_ppc;
                         }
@@ -8409,7 +9689,6 @@
                         WOLFSSL_MSG("Doing Leaf CRL check");
                         ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
-                    #ifdef WOLFSSL_ASYNC_CRYPT
-                        /* non-blocking socket re-entry requires async */
-                        if (ret == WANT_READ) {
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
                             goto exit_ppc;
                         }
@@ -8433,10 +9712,21 @@
                     int copyRet = CopyDecodedToX509(&ssl->peerCert,
                                                                 args->dCert);
-                    if (copyRet == MEMORY_E)
+                    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) &&
@@ -8454,4 +9744,14 @@
                 }
 
+                #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) {
@@ -8475,4 +9775,5 @@
                     ssl->error = ret;
                 #ifdef OPENSSL_EXTRA
+                    SendAlert(ssl, alert_fatal, bad_certificate);
                     ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
                 #endif
@@ -8481,35 +9782,29 @@
 
                 ssl->options.havePeerCert = 1;
-            } /* 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) {
-                args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap,
-                                                    DYNAMIC_TYPE_STRING);
-                if (args->domain == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_ppc);
+
+                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;
                 }
-
-                /* store for callback use */
-                if (args->dCert->subjectCNLen < ASN_NAME_MAX) {
-                    XMEMCPY(args->domain, args->dCert->subjectCN, args->dCert->subjectCNLen);
-                    args->domain[args->dCert->subjectCNLen] = '\0';
                 }
                 else {
-                    args->domain[0] = '\0';
+                        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;
                 }
-
-                if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
+                    }
+                #else /* WOLFSSL_ALL_NO_CN_IN_SAN */
+                    /* Old behavior. */
                     if (MatchDomainName(args->dCert->subjectCN,
                                 args->dCert->subjectCNLen,
@@ -8524,4 +9819,5 @@
                         }
                     }
+                #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
                 }
 
@@ -8599,6 +9895,7 @@
                     case ECDSAk:
                     {
-                        int curveId;
                         int keyRet = 0;
+                        word32 idx = 0;
+
                         if (ssl->peerEccDsaKey == NULL) {
                             /* alloc/init on demand */
@@ -8611,9 +9908,8 @@
                         }
 
-                        curveId = wc_ecc_get_oid(args->dCert->keyOID, NULL, NULL);
                         if (keyRet != 0 ||
-                            wc_ecc_import_x963_ex(args->dCert->publicKey,
-                                    args->dCert->pubKeySize, ssl->peerEccDsaKey,
-                                                            curveId) != 0) {
+                            wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
+                                                ssl->peerEccDsaKey,
+                                                args->dCert->pubKeySize) != 0) {
                             ret = PEER_KEY_ERROR;
                         }
@@ -8697,17 +9993,10 @@
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ED25519 */
                     default:
                         break;
                 }
 
-                FreeDecodedCert(args->dCert);
-                args->dCertInit = 0;
-
-                /* release since we don't need it anymore */
-                if (args->dCert) {
-                    XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
-                    args->dCert = NULL;
-                }
+                /* args->dCert free'd in function cleanup after callback */
             } /* if (count > 0) */
 
@@ -8724,17 +10013,4 @@
         case TLS_ASYNC_FINALIZE:
         {
-        #ifdef WOLFSSL_SMALL_STACK
-            WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
-                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
-                                                    DYNAMIC_TYPE_X509_STORE);
-            if (store == NULL) {
-                ERROR_OUT(MEMORY_E, exit_ppc);
-            }
-        #else
-            WOLFSSL_X509_STORE_CTX  store[1];
-        #endif
-
-            XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
-
             /* load last error */
             if (args->lastErr != 0 && ret == 0) {
@@ -8748,97 +10024,7 @@
             }
         #endif
-            if (ret != 0) {
-                if (!ssl->options.verifyNone) {
-                    int why = bad_certificate;
-
-                    if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
-                        why = certificate_expired;
-                    }
-                    if (ssl->verifyCallback) {
-                        int ok;
-
-                        store->error = ret;
-                        store->error_depth = args->totalCerts;
-                        store->discardSessionCerts = 0;
-                        store->domain = args->domain;
-                        store->userCtx = ssl->verifyCbCtx;
-                        store->certs = args->certs;
-                        store->totalCerts = args->totalCerts;
-                    #ifdef KEEP_PEER_CERT
-                        if (ssl->peerCert.subject.sz > 0)
-                            store->current_cert = &ssl->peerCert;
-                        else
-                            store->current_cert = NULL;
-                    #else
-                        store->current_cert = NULL;
-                    #endif /* KEEP_PEER_CERT */
-                    #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS)
-                        store->ex_data = ssl;
-                    #endif
-                        ok = ssl->verifyCallback(0, store);
-                        if (ok) {
-                            WOLFSSL_MSG("Verify callback overriding error!");
-                            ret = 0;
-                        }
-                    #ifdef SESSION_CERTS
-                        if (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 */
-                    }
-                    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;
-                #ifdef WOLFSSL_WPAS
-                    store->error_depth = 0;
-                #else
-                    store->error_depth = args->totalCerts;
-                #endif
-                    store->discardSessionCerts = 0;
-                    store->domain = args->domain;
-                    store->userCtx = ssl->verifyCbCtx;
-                    store->certs = args->certs;
-                    store->totalCerts = args->totalCerts;
-                #ifdef KEEP_PEER_CERT
-                    if (ssl->peerCert.subject.sz > 0)
-                        store->current_cert = &ssl->peerCert;
-                    else
-                        store->current_cert = NULL;
-                #endif
-                    store->ex_data = ssl;
-
-                    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;
-                    #ifdef WOLFSSL_ALT_CERT_CHAINS
-                        ssl->session.altChain.count = 0;
-                    #endif
-                    }
-                #endif /* SESSION_CERTS */
-                }
-            }
-        #endif /* WOLFSSL_ALWAYS_VERIFY_CB */
+
+            /* Do verify callback */
+            ret = DoVerifyCallback(ssl, ret, args);
 
             if (ssl->options.verifyNone &&
@@ -8856,7 +10042,4 @@
             }
 
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
-        #endif
             /* Advance state and proceed */
             ssl->options.asyncState = TLS_ASYNC_END;
@@ -8880,14 +10063,24 @@
     WOLFSSL_LEAVE("ProcessPeerCerts", ret);
 
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E || ret == WANT_READ) {
-        /* Mark message as not recevied so it can process again */
+
+#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 */
+#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
+
     FreeKeyExchange(ssl);
 
@@ -8895,10 +10088,36 @@
 }
 
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of certificate (11) */
 static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                                                                 word32 size)
 {
-    return ProcessPeerCerts(ssl, input, inOutIdx, 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 OPENSSL_EXTRA
+    ssl->options.serverState = SERVER_CERT_COMPLETE;
+#endif
+
+    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)
@@ -8908,4 +10127,7 @@
     word32 status_length;
 
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
+    WOLFSSL_ENTER("DoCertificateStatus");
+
     if (size < ENUM_LEN + OPAQUE24_LEN)
         return BUFFER_ERROR;
@@ -8925,6 +10147,16 @@
 
         /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
-        case 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
@@ -8937,85 +10169,4 @@
 
             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, status_type, 0);
-                        ssl->status_request_v2 = 0;
-                        break;
-                    }
-                #endif
-
-                return BUFFER_ERROR;
-            } while(0);
-
-            if (request == NULL)
-                return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
-
-            #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, NULL, DYNAMIC_TYPE_OCSP_STATUS);
-                    if (response)
-                        XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
-
-                    return MEMORY_ERROR;
-                }
-            #endif
-
-            InitOcspResponse(response, status, input +*inOutIdx, status_length);
-
-            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;
-
-            *inOutIdx += status_length;
-
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(status,   ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
-                XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-            #endif
-
-        }
-        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;
@@ -9105,9 +10256,21 @@
         SendAlert(ssl, alert_fatal, bad_certificate_status_response);
 
+    if (IsEncryptionOn(ssl, 0)) {
+        if (*inOutIdx + ssl->keys.padSz > size)
+            return BUFFER_E;
+        *inOutIdx += ssl->keys.padSz;
+    }
+
+    WOLFSSL_LEAVE("DoCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO);
+
     return ret;
 }
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
 #endif /* !NO_CERTS */
 
+#ifndef WOLFSSL_NO_TLS12
 
 static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
@@ -9116,4 +10279,7 @@
     (void)input;
 
+    WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO);
+    WOLFSSL_ENTER("DoHelloRequest");
+
     if (size) /* must be 0 */
         return BUFFER_ERROR;
@@ -9134,4 +10300,6 @@
     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;
     }
@@ -9148,4 +10316,7 @@
     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;
@@ -9156,5 +10327,5 @@
 
     #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
         if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
     #endif
@@ -9176,4 +10347,5 @@
             XMEMCPY(ssl->secure_renegotiation->client_verify_data,
                     input + *inOutIdx, TLS_FINISHED_SZ);
+        ssl->secure_renegotiation->verifySet = 1;
     }
 #endif
@@ -9184,5 +10356,14 @@
     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) {
+#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;
@@ -9191,9 +10372,21 @@
     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) {
+#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;
         }
     }
+
+    WOLFSSL_LEAVE("DoFinished", 0);
+    WOLFSSL_END(WC_FUNC_FINISHED_DO);
 
     return 0;
@@ -9524,4 +10717,26 @@
                   (ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
 
+#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) {
@@ -9530,11 +10745,13 @@
     }
 
-#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
@@ -9573,9 +10790,23 @@
      * hashed later if the DTLS cookie is correct. */
     if (type != hello_request &&
-            !(IsDtlsNotSctpMode(ssl) && type == client_hello) &&
-            ssl->error != WC_PENDING_E) {
+            !(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;
     }
+
+#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) {
@@ -9595,4 +10826,22 @@
         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)
+        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;
 
@@ -9633,5 +10882,5 @@
     #ifdef WOLFSSL_CALLBACKS
         if (ssl->hsInfoOn)
-            AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+            AddPacketName(ssl, "ServerHelloDone");
         if (ssl->toInfoOn)
             AddLateName("ServerHelloDone", &ssl->timeoutInfo);
@@ -9656,4 +10905,27 @@
         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)
+        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)) {
+            /* access beyond input + size should be checked against totalSz */
+            if (*inOutIdx + ssl->keys.padSz > totalSz)
+                return BUFFER_E;
+
+            *inOutIdx += ssl->keys.padSz;
+        }
         break;
 
@@ -9663,10 +10935,11 @@
         break;
 
-#if !defined(NO_RSA) || defined(HAVE_ECC)
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
+                                                !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 || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
 
 #endif /* !NO_WOLFSSL_SERVER */
@@ -9677,5 +10950,4 @@
         break;
     }
-
     if (ret == 0 && expectedIdx != *inOutIdx) {
         WOLFSSL_MSG("Extra data in handshake message");
@@ -9684,8 +10956,11 @@
         ret = DECODE_E;
     }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) {
+        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 && *inOutIdx > 0) {
+    if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
         *inOutIdx -= HANDSHAKE_HEADER_SZ;
     #ifdef WOLFSSL_DTLS
@@ -9695,5 +10970,10 @@
     #endif
     }
-#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);
@@ -9716,4 +10996,6 @@
         if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
             return PARSE_ERROR;
+
+        ssl->options.handShakeState = type;
 
         return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
@@ -9800,7 +11082,9 @@
 }
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
 #ifdef WOLFSSL_DTLS
 
-static INLINE int DtlsCheckWindow(WOLFSSL* ssl)
+static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
 {
     word32* window;
@@ -9903,5 +11187,5 @@
 
 #ifdef WOLFSSL_MULTICAST
-static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
                                          word32 second, word32 max)
 {
@@ -9920,5 +11204,5 @@
 
 
-static INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
+static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
 {
     word32* window;
@@ -10042,5 +11326,5 @@
     /* 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 &&
@@ -10051,8 +11335,10 @@
         ret = DoHandShakeMsgType(ssl, item->msg,
                                  &idx, item->type, item->sz, item->sz);
+    #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);
@@ -10180,7 +11466,8 @@
 #endif
 
+#ifndef WOLFSSL_NO_TLS12
 
 #ifdef HAVE_AEAD
-static INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
+static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
 {
     int i;
@@ -10246,9 +11533,9 @@
 
 /* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
- * the implmentation follows an older draft for creating the nonce and MAC.
- * The flag oldPoly gets set automaticlly depending on what cipher suite was
+ * 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 comparision to the more recent RFC.
+ * draft in comparison to the more recent RFC.
  *
  * ssl   WOLFSSL structure to get cipher and TLS state from
@@ -10397,9 +11684,9 @@
 
 /* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
- * the implmentation follows an older draft for creating the nonce and MAC.
- * The flag oldPoly gets set automaticlly depending on what cipher suite was
+ * 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 comparision to the more recent RFC.
+ * draft in comparison to the more recent RFC.
  *
  * ssl   WOLFSSL structure to get cipher and TLS state from
@@ -10538,5 +11825,5 @@
 
 
-static INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
+static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
     word16 sz, int asyncOkay)
 {
@@ -10563,5 +11850,5 @@
         case wolfssl_triple_des:
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             asyncDev = &ssl->encrypt.des3->asyncDev;
             ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
@@ -10579,8 +11866,8 @@
     #endif
 
-    #ifdef BUILD_AES
+    #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
         case wolfssl_aes:
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             asyncDev = &ssl->encrypt.aes->asyncDev;
             ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
@@ -10606,5 +11893,5 @@
 
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             asyncDev = &ssl->encrypt.aes->asyncDev;
             ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
@@ -10715,5 +12002,5 @@
 }
 
-static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
+static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
     int asyncOkay)
 {
@@ -10807,5 +12094,5 @@
 }
 
-static INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
+static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
                            word16 sz)
 {
@@ -10827,5 +12114,5 @@
         case wolfssl_triple_des:
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
                 WC_ASYNC_FLAG_CALL_AGAIN);
@@ -10843,8 +12130,8 @@
     #endif
 
-    #ifdef BUILD_AES
+    #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
         case wolfssl_aes:
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
                 WC_ASYNC_FLAG_CALL_AGAIN);
@@ -10869,5 +12156,5 @@
 
         #ifdef WOLFSSL_ASYNC_CRYPT
-            /* intialize event */
+            /* initialize event */
             ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
                 WC_ASYNC_FLAG_CALL_AGAIN);
@@ -10964,5 +12251,5 @@
 }
 
-static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
                            word16 sz)
 {
@@ -11067,4 +12354,6 @@
 }
 
+#endif /* !WOLFSSL_NO_TLS12 */
+
 /* Check conditions for a cipher to have an explicit IV.
  *
@@ -11072,5 +12361,5 @@
  * returns 1 if the cipher in use has an explicit IV and 0 otherwise.
  */
-static INLINE int CipherHasExpIV(WOLFSSL *ssl)
+static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl)
 {
 #ifdef WOLFSSL_TLS13
@@ -11092,4 +12381,5 @@
 #endif
 
+#ifndef WOLFSSL_AEAD_ONLY
     if (ssl->specs.cipher_type == block) {
         if (encryptSz % ssl->specs.block_size) {
@@ -11106,5 +12396,7 @@
             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 (CipherHasExpIV(ssl))
@@ -11121,172 +12413,5 @@
 
 
-#ifndef NO_OLD_TLS
-
-static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
-{
-    wc_Md5 md5;
-    int i;
-
-    wc_InitMd5(&md5);   /* no error check on purpose, dummy round */
-
-    for (i = 0; i < rounds; i++)
-        wc_Md5Update(&md5, data, sz);
-    wc_Md5Free(&md5); /* in case needed to release resources */
-}
-
-
-
-/* do a dummy sha round */
-static INLINE void ShaRounds(int rounds, const byte* data, int sz)
-{
-    wc_Sha sha;
-    int i;
-
-    wc_InitSha(&sha);  /* no error check on purpose, dummy round */
-
-    for (i = 0; i < rounds; i++)
-        wc_ShaUpdate(&sha, data, sz);
-    wc_ShaFree(&sha); /* in case needed to release resources */
-}
-#endif
-
-
-#ifndef NO_SHA256
-
-static INLINE void Sha256Rounds(int rounds, const byte* data, int sz)
-{
-    wc_Sha256 sha256;
-    int i;
-
-    wc_InitSha256(&sha256);  /* no error check on purpose, dummy round */
-
-    for (i = 0; i < rounds; i++) {
-        wc_Sha256Update(&sha256, data, sz);
-        /* no error check on purpose, dummy round */
-    }
-    wc_Sha256Free(&sha256); /* in case needed to release resources */
-}
-
-#endif
-
-
-#ifdef WOLFSSL_SHA384
-
-static INLINE void Sha384Rounds(int rounds, const byte* data, int sz)
-{
-    wc_Sha384 sha384;
-    int i;
-
-    wc_InitSha384(&sha384);  /* no error check on purpose, dummy round */
-
-    for (i = 0; i < rounds; i++) {
-        wc_Sha384Update(&sha384, data, sz);
-        /* no error check on purpose, dummy round */
-    }
-    wc_Sha384Free(&sha384); /* in case needed to release resources */
-}
-
-#endif
-
-
-#ifdef WOLFSSL_SHA512
-
-static INLINE void Sha512Rounds(int rounds, const byte* data, int sz)
-{
-    wc_Sha512 sha512;
-    int i;
-
-    wc_InitSha512(&sha512);  /* no error check on purpose, dummy round */
-
-    for (i = 0; i < rounds; i++) {
-        wc_Sha512Update(&sha512, data, sz);
-        /* no error check on purpose, dummy round */
-    }
-    wc_Sha512Free(&sha512); /* in case needed to release resources */
-}
-
-#endif
-
-
-#ifdef WOLFSSL_RIPEMD
-
-static 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)
-{
-    (void)rounds;
-    (void)data;
-    (void)sz;
-
-    switch (type) {
-        case no_mac :
-            break;
-
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
-        case md5_mac :
-            Md5Rounds(rounds, data, sz);
-            break;
-#endif
-
-#ifndef NO_SHA
-        case sha_mac :
-            ShaRounds(rounds, data, sz);
-            break;
-#endif
-#endif
-
-#ifndef NO_SHA256
-        case sha256_mac :
-            Sha256Rounds(rounds, data, sz);
-            break;
-#endif
-
-#ifdef WOLFSSL_SHA384
-        case sha384_mac :
-            Sha384Rounds(rounds, data, sz);
-            break;
-#endif
-
-#ifdef WOLFSSL_SHA512
-        case sha512_mac :
-            Sha512Rounds(rounds, data, sz);
-            break;
-#endif
-
-#ifdef WOLFSSL_RIPEMD
-        case rmd_mac :
-            RmdRounds(rounds, data, sz);
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Bad round type");
-            break;
-    }
-}
-
-
-/* do number of compression rounds on dummy data */
-static INLINE void CompressRounds(WOLFSSL* ssl, int rounds, const byte* dummy)
-{
-    if (rounds)
-        DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER);
-}
-
-
+#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)
@@ -11297,5 +12422,5 @@
     for (i = 0; i < length; i++) {
         compareSum |= a[i] ^ pad;
-    }
+}
 
     return compareSum;
@@ -11303,71 +12428,122 @@
 
 
-/* get compression extra rounds */
-static INLINE int GetRounds(int pLen, int padLen, int t)
+/* Mask the padding bytes with the expected values.
+ * Constant time implementation - does maximum pad size possible.
+ *
+ * data   Message data.
+ * sz     Size of the message including MAC and padding and padding length.
+ * macSz  Size of the MAC.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskPadding(const byte* data, int sz, int macSz)
 {
-    int  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;
+    int i;
+    int checkSz = sz - 1;
+    byte paddingSz = data[sz - 1];
+    byte mask;
+    byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
+
+    if (checkSz > TLS_MAX_PAD_SZ)
+        checkSz = TLS_MAX_PAD_SZ;
+
+    for (i = 0; i < checkSz; i++) {
+        mask = ctMaskLTE(i, paddingSz);
+        good |= mask & (data[sz - 1 - i] ^ paddingSz);
 }
 
+    return good;
+}
+
+/* Mask the MAC in the message with the MAC calculated.
+ * Constant time implementation - starts looking for MAC where maximum padding
+ * size has it.
+ *
+ * data    Message data.
+ * sz      Size of the message including MAC and padding and padding length.
+ * macSz   Size of the MAC data.
+ * expMac  Expected MAC value.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
+{
+    int i, j;
+    unsigned char mac[WC_MAX_DIGEST_SIZE];
+    int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
+    int macEnd = sz - 1 - data[sz - 1];
+    int macStart = macEnd - macSz;
+    int r = 0;
+    unsigned char started, notEnded;
+    unsigned char good = 0;
+
+    scanStart &= (~scanStart) >> (sizeof(int) * 8 - 1);
+    macStart &= (~macStart) >> (sizeof(int) * 8 - 1);
+
+    /* Div on Intel has different speeds depending on value.
+     * Use a bitwise AND or mod a specific value (converted to mul). */
+    if ((macSz & (macSz - 1)) == 0)
+        r = (macSz - (scanStart - macStart)) & (macSz - 1);
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
+#endif
+
+    XMEMSET(mac, 0, macSz);
+    for (i = scanStart; i < sz; i += macSz) {
+        for (j = 0; j < macSz && j + i < sz; j++) {
+            started = ctMaskGTE(i + j, macStart);
+            notEnded = ctMaskLT(i + j, macEnd);
+            mac[j] |= started & notEnded & data[i + j];
+    }
+}
+
+    if ((macSz & (macSz - 1)) == 0) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) & (macSz - 1)];
+    }
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE];
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE];
+    }
+#endif
+
+    return good;
+}
 
 /* timing resistant pad/verify check, return 0 on success */
-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;
-    }
-
-    /* treat any faulure as 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 faulure as verify MAC error. */
     if (ret != 0)
         ret = VERIFY_MAC_ERROR;
@@ -11375,4 +12551,5 @@
     return ret;
 }
+#endif
 
 
@@ -11389,5 +12566,5 @@
 
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData) {
+    if (ssl->earlyData != no_early_data) {
     }
     else
@@ -11399,9 +12576,12 @@
     }
 
+#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) {
+    else
+#endif
+    if (ssl->specs.cipher_type == aead) {
         if (CipherHasExpIV(ssl))
             ivExtra = AESGCM_EXP_IV_SZ;
@@ -11414,5 +12594,5 @@
     }
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData) {
+    if (ssl->earlyData != no_early_data) {
         if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
             SendAlert(ssl, alert_fatal, unexpected_message);
@@ -11459,12 +12639,12 @@
     byte code;
 
-    #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 + alert bytes level/code */
-            AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
+            AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx -
                           RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE,
-                          ssl->heap);
+                          READ_PROTO, ssl->heap);
     #endif
 
@@ -11554,5 +12734,5 @@
     /* read data from network */
     do {
-        in = Receive(ssl,
+        in = wolfSSLReceive(ssl,
                      ssl->buffers.inputBuffer.buffer +
                      ssl->buffers.inputBuffer.length,
@@ -11584,7 +12764,8 @@
 
 
-static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
+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;
@@ -11597,5 +12778,6 @@
     word32 digestSz = ssl->specs.hash_size;
 #endif
-    byte   verify[MAX_DIGEST_SIZE];
+    byte   verify[WC_MAX_DIGEST_SIZE];
+
 
     if (ssl->specs.cipher_type == block) {
@@ -11625,5 +12807,5 @@
             }
             PadCheck(dummy, (byte)pad, MAX_PAD_SIZE);  /* timing only */
-            ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
+            ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
                             content, 1);
             if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
@@ -11635,5 +12817,5 @@
     }
     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;
@@ -11642,11 +12824,18 @@
             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;
@@ -11670,6 +12859,12 @@
 #endif
 
-    if (ssl->error != 0 && ssl->error != WANT_READ &&
-        ssl->error != WANT_WRITE && ssl->error != WC_PENDING_E) {
+    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;
@@ -11836,5 +13031,12 @@
         case decryptMessage:
 
-            if (IsEncryptionOn(ssl, 0) && 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;
 
@@ -11854,15 +13056,30 @@
                 else {
                     if (!ssl->options.tls1_3) {
+                #ifndef WOLFSSL_NO_TLS12
                         ret = Decrypt(ssl,
                                       in->buffer + in->idx,
                                       in->buffer + in->idx,
                                       ssl->curSize);
+                #else
+                        ret = DECRYPT_ERROR;
+                #endif
                     }
-                    else {
+                    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);
+                                           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;
@@ -11877,10 +13094,14 @@
 
                 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 (CipherHasExpIV(ssl))
                         ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
+            #endif
                 }
                 else {
@@ -11923,5 +13144,12 @@
         case verifyMessage:
 
-            if (IsEncryptionOn(ssl, 0) && 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
+            {
                 if (!atomicUser) {
                     ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
@@ -11956,8 +13184,14 @@
 #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->keys.padSz++;
-                    ssl->curRL.type = ssl->buffers.inputBuffer.buffer[
-                        ssl->buffers.inputBuffer.length - ssl->keys.padSz];
+                    ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
+                    ssl->keys.padSz = ssl->buffers.inputBuffer.length - i;
                 }
 #endif
@@ -11990,8 +13224,12 @@
                     }
                     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 {
@@ -12007,5 +13245,5 @@
                                 ssl->earlyData &&
                                 ssl->options.handShakeState == HANDSHAKE_DONE) {
-                            ssl->earlyData = 0;
+                            ssl->earlyData = no_early_data;
                             ssl->options.processReply = doProcessInit;
                             return ZERO_RETURN;
@@ -12022,17 +13260,41 @@
                 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->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) {
@@ -12119,4 +13381,5 @@
                     if (ret != 0)
                         return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
                     break;
 
@@ -12214,4 +13477,19 @@
     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) {
@@ -12226,5 +13504,5 @@
     }
 
-    /* check for avalaible size */
+    /* check for available size */
     if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
         return ret;
@@ -12256,9 +13534,9 @@
         }
     #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;
@@ -12278,9 +13556,9 @@
 
 
-#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;
@@ -12294,4 +13572,6 @@
     byte conLen[ENUM_LEN + LENGTH_SZ];     /* content & length */
     const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
+
+    (void)padLen;
 
 #ifdef HAVE_FUZZER
@@ -12391,5 +13671,5 @@
     return 0;
 }
-#endif /* NO_OLD_TLS */
+#endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */
 
 
@@ -12538,6 +13818,7 @@
 }
 
-#endif /* WOLFSSL_LEANPSK */
-
+#endif /* !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
 /* Persistable BuildMessage arguments */
 typedef struct BuildMsgArgs {
@@ -12549,5 +13830,5 @@
     word16 size;
     word32 ivSz;      /* TLSv1.1  IV */
-    byte   iv[AES_BLOCK_SIZE]; /* max size */
+    byte*  iv;
 } BuildMsgArgs;
 
@@ -12559,6 +13840,10 @@
     (void)args;
 
-    /* no allocations in BuildMessage */
+    if (args->iv) {
+        XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT);
+        args->iv = NULL;
 }
+}
+#endif
 
 /* Build SSL Message, encrypted */
@@ -12566,4 +13851,5 @@
              int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
 {
+#ifndef WOLFSSL_NO_TLS12
     int ret = 0;
     BuildMsgArgs* args;
@@ -12574,4 +13860,5 @@
     (void)sizeof(args_test);
 #endif
+#endif
 
     WOLFSSL_ENTER("BuildMessage");
@@ -12581,4 +13868,8 @@
     }
 
+#ifdef WOLFSSL_NO_TLS12
+    return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+                                               hashOutput, sizeOnly, asyncOkay);
+#else
 #ifdef WOLFSSL_TLS13
     if (ssl->options.tls1_3) {
@@ -12623,9 +13914,9 @@
             /* catch mistaken sizeOnly parameter */
             if (!sizeOnly && (output == NULL || input == NULL) ) {
-                return BAD_FUNC_ARG;
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
             }
             if (sizeOnly && (output || input) ) {
                 WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output");
-                return BAD_FUNC_ARG;
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
             }
 
@@ -12650,4 +13941,5 @@
         #endif
 
+        #ifndef WOLFSSL_AEAD_ONLY
             if (ssl->specs.cipher_type == block) {
                 word32 blockSz = ssl->specs.block_size;
@@ -12656,12 +13948,16 @@
                     args->sz  += args->ivSz;
 
-                    if (args->ivSz > (word32)sizeof(args->iv))
+                    if (args->ivSz > MAX_IV_SZ)
                         ERROR_OUT(BUFFER_E, exit_buildmsg);
                 }
                 args->sz += 1;       /* pad byte */
                 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
@@ -12684,4 +13980,8 @@
 
             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)
@@ -12701,7 +14001,7 @@
 
             /* write to output */
-            if (args->ivSz) {
+            if (args->ivSz > 0) {
                 XMEMCPY(output + args->idx, args->iv,
-                                        min(args->ivSz, sizeof(args->iv)));
+                                        min(args->ivSz, MAX_IV_SZ));
                 args->idx += args->ivSz;
             }
@@ -12714,6 +14014,4 @@
         case BUILD_MSG_HASH:
         {
-            word32 i;
-
             if (type == handshake && hashOutput) {
                 ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
@@ -12721,10 +14019,13 @@
                     goto exit_buildmsg;
             }
+        #ifndef WOLFSSL_AEAD_ONLY
             if (ssl->specs.cipher_type == block) {
                 word32 tmpIdx = args->idx + args->digestSz;
+                word32 i;
 
                 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;
@@ -12744,15 +14045,17 @@
         #endif
 
+        #ifndef WOLFSSL_AEAD_ONLY
             if (ssl->specs.cipher_type != aead) {
         #ifdef HAVE_TRUNCATED_HMAC
-            if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) {
+                if (ssl->truncated_hmac &&
+                                        ssl->specs.hash_size > args->digestSz) {
             #ifdef WOLFSSL_SMALL_STACK
                 byte* hmac = NULL;
             #else
-                byte  hmac[MAX_DIGEST_SIZE];
+                    byte  hmac[WC_MAX_DIGEST_SIZE];
             #endif
 
             #ifdef WOLFSSL_SMALL_STACK
-                hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, ssl->heap,
+                    hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
                                                        DYNAMIC_TYPE_DIGEST);
                 if (hmac == NULL)
@@ -12760,6 +14063,7 @@
             #endif
 
-                ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz,
-                                                                       type, 0);
+                    ret = ssl->hmac(ssl, hmac,
+                                     output + args->headerSz + args->ivSz, inSz,
+                                     -1, type, 0);
                 XMEMCPY(output + args->idx, hmac, args->digestSz);
 
@@ -12770,11 +14074,10 @@
             else
         #endif
-                ret = ssl->hmac(ssl, output + args->idx, output + args->headerSz + args->ivSz,
-                                                                inSz, type, 0);
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-            }
+                {
+                    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;
@@ -12804,4 +14107,9 @@
     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)
@@ -12810,8 +14118,13 @@
     /* 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)
@@ -12827,4 +14140,7 @@
     int              outputSz;
 
+    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+    WOLFSSL_ENTER("SendFinished");
+
     /* setup encrypt keys */
     if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
@@ -12889,4 +14205,10 @@
 #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;
@@ -12895,4 +14217,10 @@
     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;
@@ -12900,18 +14228,137 @@
     }
 
-    #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))
+static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
+                             DecodedCert* cert, byte* certData, word32 length)
+{
+    int ret;
+
+    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;
+}
+
+
+int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
+                       buffer* response)
+{
+    int          ret = 0;
+    OcspRequest* request;
+
+    if (ssl == NULL || ocspRequest == NULL || response == NULL)
+        return BAD_FUNC_ARG;
+
+    request = *ocspRequest;
+
+    XMEMSET(response, 0, sizeof(*response));
+
+    /* 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;
+
+        if (ret == 0) {
+            ret = CreateOcspRequest(ssl, request, cert, der->buffer,
+                                                                   der->length);
+        }
+
+        if (request != NULL && ret != 0) {
+            FreeOcspRequest(request);
+            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;
+        }
+}
+
+    *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)
 {
@@ -12920,8 +14367,18 @@
     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) {
+    #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;
@@ -12929,4 +14386,7 @@
         length = CERT_HEADER_SZ;
         listSz = 0;
+    #ifdef OPENSSL_EXTRA
+        }
+    #endif
     }
     else {
@@ -12957,6 +14417,10 @@
 
     maxFragment = MAX_RECORD_SIZE;
+
     if (ssl->options.dtls) {
     #ifdef WOLFSSL_DTLS
+        /* 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;
@@ -12964,8 +14428,5 @@
     }
 
-    #ifdef HAVE_MAX_FRAGMENT
-    if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment)
-        maxFragment = ssl->max_fragment;
-    #endif /* HAVE_MAX_FRAGMENT */
+    maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment);
 
     while (length > 0 && ret == 0) {
@@ -13132,10 +14593,10 @@
     #endif
 
-    #ifdef WOLFSSL_CALLBACKS
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
         if (ssl->hsInfoOn)
-            AddPacketName("Certificate", &ssl->handShakeInfo);
+            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
 
@@ -13152,12 +14613,17 @@
                 ssl->keys.dtls_handshake_number++;
         #endif
-        if (ssl->options.side == WOLFSSL_SERVER_END)
+        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)
 {
@@ -13167,5 +14633,5 @@
     word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
     word32 dnLen = 0;
-#ifdef WOLFSSL_NGINX
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
     WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
 #endif
@@ -13174,8 +14640,11 @@
     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;
 
-#ifdef WOLFSSL_NGINX
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
     /* Certificate Authorities */
     names = ssl->ctx->ca_names;
@@ -13196,10 +14665,14 @@
     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;
-        }
     #endif
+    }
     /* check for available size */
     if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
@@ -13228,5 +14701,5 @@
     if (IsAtLeastTLSv1_2(ssl)) {
         c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
-        i += LENGTH_SZ;
+        i += OPAQUE16_LEN;
 
         XMEMCPY(&output[i],
@@ -13238,10 +14711,10 @@
     c16toa((word16)dnLen, &output[i]);  /* auth's */
     i += REQ_HEADER_SZ;
-#ifdef WOLFSSL_NGINX
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
     names = ssl->ctx->ca_names;
     while (names != NULL) {
         byte seq[MAX_SEQ_SZ];
 
-        c16toa(names->data.name->rawLen +
+        c16toa((word16)names->data.name->rawLen +
                SetSequence(names->data.name->rawLen, seq), &output[i]);
         i += OPAQUE16_LEN;
@@ -13254,29 +14727,50 @@
     (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;
         }
-        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("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;
 }
 
@@ -13365,10 +14859,10 @@
     #endif
 
-    #ifdef WOLFSSL_CALLBACKS
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
         if (ret == 0 && ssl->hsInfoOn)
-            AddPacketName("CertificateStatus", &ssl->handShakeInfo);
+            AddPacketName(ssl, "CertificateStatus");
         if (ret == 0 && ssl->toInfoOn)
-            AddPacketInfo("CertificateStatus", &ssl->timeoutInfo, output,
-                                                             sendSz, ssl->heap);
+            AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
     #endif
 
@@ -13386,5 +14880,5 @@
 #endif /* NO_WOLFSSL_SERVER */
 
-
+/* handle generation of certificate_status (22) */
 int SendCertificateStatus(WOLFSSL* ssl)
 {
@@ -13392,4 +14886,5 @@
     byte status_type = 0;
 
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
     WOLFSSL_ENTER("SendCertificateStatus");
 
@@ -13415,12 +14910,32 @@
             buffer response;
 
-            XMEMSET(&response, 0, sizeof(response));
-
-            /* 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;
+            ret = CreateOcspResponse(ssl, &request, &response);
+            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 (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
+                                              || ssl->buffers.weOwnCertChain)) {
+                buffer der;
+                word32 idx = 0;
                 #ifdef WOLFSSL_SMALL_STACK
                     DecodedCert* cert = NULL;
@@ -13428,8 +14943,4 @@
                     DecodedCert  cert[1];
                 #endif
-
-                /* unable to fetch status. skip. */
-                if (der->buffer == NULL || der->length == 0)
-                    return 0;
 
             #ifdef WOLFSSL_SMALL_STACK
@@ -13439,49 +14950,29 @@
                     return MEMORY_E;
             #endif
-
-                InitDecodedCert(cert, der->buffer, der->length, ssl->heap);
-                /* TODO: Setup async support here */
-                if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
-                                                          ssl->ctx->cm)) != 0) {
-                    WOLFSSL_MSG("ParseCert failed");
-                }
-                else {
-                    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest),
-                                          ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                    if (request) {
-                        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);
-                                }
-                            }
-                        }
-                        else {
-                            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                            request = NULL;
-                        }
-                    }
-                    else {
-                        ret = MEMORY_E;
-                    }
-                }
-
-                FreeDecodedCert(cert);
-
+                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,
-                                                                     &response);
+                        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+                                                    request, &responses[i + 1]);
 
                 /* Suppressing, not critical */
@@ -13492,100 +14983,21 @@
                 }
 
-                if (response.buffer) {
-                    if (ret == 0)
-                        ret = BuildCertificateStatus(ssl, status_type,
-                                                                  &response, 1);
-
-                    XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                    response.buffer = NULL;
+
+                        i++;
+                        FreeOcspRequest(request);
                 }
-
-            }
-
-            if (request != ssl->ctx->certOcspRequest)
+            }
+
                 XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-
-            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));
-
-            /* unable to fetch status. skip. */
-            if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
-                return 0;
-
-            if (!request || 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
-
-                InitDecodedCert(cert, der->buffer, der->length, ssl->heap);
-                /* TODO: Setup async support here */
-                if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
-                                                          ssl->ctx->cm)) != 0) {
-                    WOLFSSL_MSG("ParseCert failed");
-                }
-                else {
-                    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest),
-                                          ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                    if (request) {
-                        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);
-                                }
-                            }
-                        }
-                        else {
-                            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                            request = NULL;
-                        }
-                    }
-                    else {
-                        ret = MEMORY_E;
-                    }
-                }
-
-                FreeDecodedCert(cert);
-
             #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,
-                                                                 &responses[0]);
+        }
+            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 */
@@ -13596,124 +15008,19 @@
                 }
             }
-
-            if (request != ssl->ctx->certOcspRequest)
-                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-
-            if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
-                                              || ssl->buffers.weOwnCertChain)) {
-                buffer der;
-                word32 idx = 0;
-            #ifdef WOLFSSL_SMALL_STACK
-                DecodedCert* cert = NULL;
-            #else
-                DecodedCert  cert[1];
-            #endif
-
-                XMEMSET(&der, 0, sizeof(buffer));
-
-            #ifdef WOLFSSL_SMALL_STACK
-                cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
-                                             DYNAMIC_TYPE_DCERT);
-                if (cert == NULL)
-                    return MEMORY_E;
-            #endif
-
-                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;
-
-                    InitDecodedCert(cert, der.buffer, der.length, ssl->heap);
-                    /* TODO: Setup async support here */
-                    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
-                                                      ssl->ctx->cm)) != 0) {
-                        WOLFSSL_MSG("ParseCert failed");
-                        break;
-                    }
-                    else {
-                        request = (OcspRequest*)XMALLOC(sizeof(OcspRequest),
-                                          ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                        if (request == NULL) {
-                            FreeDecodedCert(cert);
-
-                            ret = MEMORY_E;
-                            break;
                         }
 
-                        ret = InitOcspRequest(request, cert, 0, ssl->heap);
+            if (responses[0].buffer) {
                         if (ret == 0) {
-                            /* make sure ctx OCSP request is updated */
-                            if (!ssl->buffers.weOwnCertChain) {
-                                wolfSSL_Mutex* ocspLock =
-                                    &ssl->ctx->cm->ocsp_stapling->ocspLock;
-                                if (wc_LockMutex(ocspLock) == 0) {
-                                    if (ssl->ctx->chainOcspRequest[i] == NULL)
-                                        ssl->ctx->chainOcspRequest[i] = request;
-                                    wc_UnLockMutex(ocspLock);
-                                }
-                            }
-                        }
-                        else {
-                            FreeDecodedCert(cert);
-                            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                            request = NULL;
-                            break;
-                        }
-
-                        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;
-                        }
-
-                        if (request != ssl->ctx->chainOcspRequest[i])
-                            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-
-                        i++;
-                    }
-
-                    FreeDecodedCert(cert);
-                }
-
-            #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)
+                    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;
@@ -13726,4 +15033,7 @@
     }
 
+    WOLFSSL_LEAVE("SendCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND);
+
     return ret;
 }
@@ -13731,4 +15041,5 @@
 #endif /* !NO_CERTS */
 
+#endif /* WOLFSSL_NO_TLS12 */
 
 int SendData(WOLFSSL* ssl, const void* data, int sz)
@@ -13738,7 +15049,13 @@
         ret,
         dtlsExtra = 0;
-
-    if (ssl->error == WANT_WRITE || ssl->error == WC_PENDING_E)
+    int groupMsgs = 0;
+
+    if (ssl->error == WANT_WRITE
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
         ssl->error = 0;
+    }
 
 #ifdef WOLFSSL_DTLS
@@ -13752,9 +15069,12 @@
 
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData) {
+    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
@@ -13764,8 +15084,10 @@
         WOLFSSL_MSG("handshake not complete, trying to finish");
         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;
         }
@@ -13773,10 +15095,14 @@
 
     /* 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;
         }
@@ -13811,8 +15137,5 @@
         if (sent == sz) break;
 
-        len = min(sz - sent, OUTPUT_RECORD_SIZE);
-#ifdef HAVE_MAX_FRAGMENT
-        len = min(len, ssl->max_fragment);
-#endif
+        len = wolfSSL_GetMaxRecordSize(ssl, sz - sent);
 
 #ifdef WOLFSSL_DTLS
@@ -13863,13 +15186,17 @@
         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;
         }
 
@@ -13878,5 +15205,5 @@
         /* 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;
         }
@@ -13894,5 +15221,9 @@
 
     /* reset error state */
-    if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) {
+    if (ssl->error == WANT_READ
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
         ssl->error = 0;
     }
@@ -13913,5 +15244,5 @@
 
 #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData) {
+    if (ssl->earlyData != no_early_data) {
     }
     else
@@ -13935,8 +15266,8 @@
     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)) != WOLFSSL_SUCCESS)
             return  err;
+        ssl->secure_renegotiation->startScr = 0;  /* only start once */
     }
 #endif
@@ -14026,4 +15357,9 @@
     }
 
+   #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_CB_ALERT, type);
+        }
+   #endif
    #ifdef WOLFSSL_DTLS
         if (ssl->options.dtls)
@@ -14035,4 +15371,8 @@
     if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
         return ret;
+
+    /* Check output buffer */
+    if (ssl->buffers.outputBuffer.buffer == NULL)
+        return BUFFER_E;
 
     /* get output buffer */
@@ -14072,9 +15412,10 @@
         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
 
@@ -14103,4 +15444,9 @@
     switch (error) {
 
+#ifdef WOLFSSL_WPAS
+    case 0 :
+        return "ok";
+#endif
+
     case UNSUPPORTED_SUITE :
         return "unsupported cipher suite";
@@ -14191,7 +15537,4 @@
         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";
@@ -14231,13 +15574,4 @@
         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";
@@ -14325,7 +15659,4 @@
         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";
@@ -14430,4 +15761,7 @@
         return "Invalid OCSP Status Error";
 
+    case OCSP_WANT_READ:
+        return "OCSP nonblock wants read";
+
     case RSA_KEY_SIZE_E:
         return "RSA key too small";
@@ -14464,5 +15798,5 @@
 
     case BAD_KEY_SHARE_DATA:
-        return "The Key Share data contains group that was in Client Hello";
+        return "The Key Share data contains group that wasn't in Client Hello";
 
     case MISSING_HANDSHAKE_DATA:
@@ -14477,4 +15811,7 @@
     case INVALID_PARAMETER:
         return "The security parameter is invalid";
+
+    case UNSUPPORTED_EXTENSION:
+        return "TLS Extension not requested by the client";
 
     case KEY_SHARE_ERROR:
@@ -14508,946 +15845,488 @@
 }
 
-
-/* be sure to add to cipher_name_idx too !!!! */
-static const char* const cipher_names[] =
+#ifndef NO_ERROR_STRINGS
+    #define SUITE_INFO(x,y,z,w) {(x),(y),(z),(w)}
+#else
+    #define SUITE_INFO(x,y,z,w) {(x),(z),(w)}
+#endif
+
+static const CipherSuiteInfo cipher_names[] =
 {
+#ifndef WOLFSSL_NO_TLS12
+
 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
-    "RC4-SHA",
+    SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
-    "RC4-MD5",
+    SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5),
 #endif
 
 #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-    "DES-CBC3-SHA",
+    SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-    "AES128-SHA",
+    SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-    "AES256-SHA",
+    SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_NULL_SHA
-    "NULL-SHA",
+    SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
-    "NULL-SHA256",
+    SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-    "DHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    "DHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    "DHE-PSK-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-    "DHE-PSK-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-    "PSK-AES256-GCM-SHA384",
+    SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-    "PSK-AES128-GCM-SHA256",
+    SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-    "DHE-PSK-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-    "DHE-PSK-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-    "PSK-AES256-CBC-SHA384",
+    SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-    "PSK-AES128-CBC-SHA256",
+    SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-    "PSK-AES128-CBC-SHA",
+    SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-    "PSK-AES256-CBC-SHA",
+    SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-    "DHE-PSK-AES128-CCM",
+    SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-    "DHE-PSK-AES256-CCM",
+    SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
-    "PSK-AES128-CCM",
+    SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
-    "PSK-AES256-CCM",
+    SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
-    "PSK-AES128-CCM-8",
+    SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
-    "PSK-AES256-CCM-8",
+    SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-    "DHE-PSK-NULL-SHA384",
+    SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-    "DHE-PSK-NULL-SHA256",
+    SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
-    "PSK-NULL-SHA384",
+    SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
-    "PSK-NULL-SHA256",
+    SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_NULL_SHA
-    "PSK-NULL-SHA",
+    SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
-    "HC128-MD5",
+    SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
-    "HC128-SHA",
+    SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
-    "HC128-B2B256",
+    SUITE_INFO("HC128-B2B256","TLS_RSA_WITH_HC_128_B2B256",CIPHER_BYTE,TLS_RSA_WITH_HC_128_B2B256),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
-    "AES128-B2B256",
+    SUITE_INFO("AES128-B2B256","TLS_RSA_WITH_AES_128_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_B2B256),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
-    "AES256-B2B256",
+    SUITE_INFO("AES256-B2B256","TLS_RSA_WITH_AES_256_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_B2B256),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
-    "RABBIT-SHA",
+    SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA),
 #endif
 
 #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-    "NTRU-RC4-SHA",
+    SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-    "NTRU-DES-CBC3-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),
 #endif
 
 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-    "NTRU-AES128-SHA",
+    SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-    "NTRU-AES256-SHA",
+    SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
-    "AES128-CCM-8",
+    SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
-    "AES256-CCM-8",
+    SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-    "ECDHE-ECDSA-AES128-CCM",
+	SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-    "ECDHE-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-    "ECDHE-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-    "ECDHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-    "ECDHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-    "ECDHE-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-    "ECDHE-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-    "ECDHE-RSA-RC4-SHA",
+    SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-    "ECDHE-RSA-DES-CBC3-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-    "ECDHE-ECDSA-RC4-SHA",
+    SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-    "ECDHE-ECDSA-DES-CBC3-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-    "AES128-SHA256",
+    SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-    "AES256-SHA256",
+    SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-    "DHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-    "DHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-    "ECDH-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-    "ECDH-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-    "ECDH-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-    "ECDH-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-    "ECDH-RSA-RC4-SHA",
+    SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-    "ECDH-RSA-DES-CBC3-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-    "ECDH-ECDSA-RC4-SHA",
+    SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-    "ECDH-ECDSA-DES-CBC3-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-    "AES128-GCM-SHA256",
+    SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-    "AES256-GCM-SHA384",
+    SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    "DHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    "DHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    "ECDHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    "ECDHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-    "ECDHE-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-    "ECDHE-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-    "ECDH-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-    "ECDH-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-    "ECDH-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-    "ECDH-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-    "CAMELLIA128-SHA",
+    SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-    "DHE-RSA-CAMELLIA128-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-    "CAMELLIA256-SHA",
+    SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-    "DHE-RSA-CAMELLIA256-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    "CAMELLIA128-SHA256",
+    SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    "DHE-RSA-CAMELLIA128-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),
 #endif
 
 #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    "CAMELLIA256-SHA256",
+    SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    "DHE-RSA-CAMELLIA256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-    "ECDHE-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-    "ECDHE-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-    "ECDH-RSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-    "ECDH-ECDSA-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-    "ECDHE-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-    "ECDHE-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-    "ECDH-RSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-    "ECDH-ECDSA-AES256-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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    "ECDHE-RSA-CHACHA20-POLY1305",
+    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-    "ECDHE-ECDSA-CHACHA20-POLY1305",
+    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    "DHE-RSA-CHACHA20-POLY1305",
+    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    "ECDHE-RSA-CHACHA20-POLY1305-OLD",
+    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),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    "ECDHE-ECDSA-CHACHA20-POLY1305-OLD",
+    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),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    "DHE-RSA-CHACHA20-POLY1305-OLD",
+    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),
 #endif
 
 #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-    "ADH-AES128-SHA",
+    SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA),
+#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),
 #endif
 
 #ifdef BUILD_TLS_QSH
-    "QSH",
+    SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH),
 #endif
 
 #ifdef HAVE_RENEGOTIATION_INDICATION
-    "RENEGOTIATION-INFO",
+    SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV),
 #endif
 
 #ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-    "IDEA-CBC-SHA",
+    SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-    "ECDHE-ECDSA-NULL-SHA",
+    SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-    "ECDHE-PSK-NULL-SHA256",
+    SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-    "ECDHE-PSK-AES128-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),
 #endif
 
 #ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-    "PSK-CHACHA20-POLY1305",
+    SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    "ECDHE-PSK-CHACHA20-POLY1305",
+    SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    "DHE-PSK-CHACHA20-POLY1305",
+    SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-    "EDH-RSA-DES-CBC3-SHA",
-#endif
+    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),
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+    SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256),
+#endif
+
+#endif /* WOLFSSL_NO_TLS12 */
 
 #ifdef BUILD_TLS_AES_128_GCM_SHA256
-    "TLS13-AES128-GCM-SHA256",
+    SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256),
 #endif
 
 #ifdef BUILD_TLS_AES_256_GCM_SHA384
-    "TLS13-AES256-GCM-SHA384",
+    SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384),
 #endif
 
 #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
-    "TLS13-CHACHA20-POLY1305-SHA256",
+    SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256),
 #endif
 
 #ifdef BUILD_TLS_AES_128_CCM_SHA256
-    "TLS13-AES128-CCM-SHA256",
+    SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256),
 #endif
 
 #ifdef BUILD_TLS_AES_128_CCM_8_SHA256
-    "TLS13-AES128-CCM-8-SHA256",
-#endif
-
-#ifdef BUILD_WDM_WITH_NULL_SHA256
-    "WDM-NULL-SHA256",
+    SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256),
 #endif
 };
 
 
-/* cipher suite number that matches above name table */
-static int cipher_name_idx[] =
-{
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
-    SSL_RSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
-    SSL_RSA_WITH_RC4_128_MD5,
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-    SSL_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-    TLS_RSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-    TLS_RSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
-    TLS_RSA_WITH_NULL_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
-    TLS_RSA_WITH_NULL_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-    TLS_PSK_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-    TLS_PSK_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-    TLS_PSK_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-    TLS_PSK_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-    TLS_PSK_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-    TLS_PSK_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-    TLS_DHE_PSK_WITH_AES_128_CCM,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-    TLS_DHE_PSK_WITH_AES_256_CCM,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
-    TLS_PSK_WITH_AES_128_CCM,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
-    TLS_PSK_WITH_AES_256_CCM,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
-    TLS_PSK_WITH_AES_128_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
-    TLS_PSK_WITH_AES_256_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-    TLS_DHE_PSK_WITH_NULL_SHA384,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-    TLS_DHE_PSK_WITH_NULL_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
-    TLS_PSK_WITH_NULL_SHA384,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
-    TLS_PSK_WITH_NULL_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
-    TLS_PSK_WITH_NULL_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
-    TLS_RSA_WITH_HC_128_MD5,
-#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,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
-    TLS_RSA_WITH_RABBIT_SHA,
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-    TLS_NTRU_RSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-    TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-    TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-    TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
-    TLS_RSA_WITH_AES_128_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
-    TLS_RSA_WITH_AES_256_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-    TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-    TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-    TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-    TLS_RSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-    TLS_RSA_WITH_AES_256_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-    TLS_ECDH_RSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-    TLS_RSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-    TLS_RSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-    TLS_DH_anon_WITH_AES_128_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_QSH
-    TLS_QSH,
-#endif
-
-#ifdef HAVE_RENEGOTIATION_INDICATION
-    TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-    SSL_RSA_WITH_IDEA_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-    TLS_ECDHE_PSK_WITH_NULL_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-    TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-
-#ifdef BUILD_TLS_AES_128_GCM_SHA256
-    TLS_AES_128_GCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_AES_256_GCM_SHA384
-    TLS_AES_256_GCM_SHA384,
-#endif
-
-#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
-    TLS_CHACHA20_POLY1305_SHA256,
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_SHA256
-    TLS_AES_128_CCM_SHA256,
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
-    TLS_AES_128_CCM_8_SHA256,
-#endif
-
-#ifdef BUILD_WDM_WITH_NULL_SHA256
-    WDM_WITH_NULL_SHA256,
-#endif
-};
-
-
 /* returns the cipher_names array */
-const char* const* GetCipherNames(void)
+const CipherSuiteInfo* GetCipherNames(void)
 {
     return cipher_names;
@@ -15455,53 +16334,45 @@
 
 
-/* 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));
 }
 
-/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
-const char* GetCipherNameInternal(const char* cipherName, int cipherSuite)
+
+const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite)
 {
-    const char* result = NULL;
-    const char* first;
     int i;
-
-    if (cipherName == NULL) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-
-    first = (XSTRSTR(cipherName, "CHACHA")) ? "CHACHA"
-          : (XSTRSTR(cipherName, "EC"))     ? "EC"
-          : (XSTRSTR(cipherName, "CCM"))    ? "CCM"
-          : NULL; /* normal */
-
-    for (i = 0; i < (int)(sizeof(cipher_name_idx)/sizeof(int)); i++) {
-        if (cipher_name_idx[i] == cipherSuite) {
-            const char* nameFound = cipher_names[i];
-
-            /* extra sanity check on returned cipher name */
-            if (nameFound == NULL) {
-                continue;
-            }
-
-            /* if first is null then not any */
-            if (first == NULL) {
-                if (    !XSTRSTR(nameFound, "CHACHA") &&
-                        !XSTRSTR(nameFound, "EC") &&
-                        !XSTRSTR(nameFound, "CCM")) {
-                    result = nameFound;
-                    break;
-                }
-            }
-            else if (XSTRSTR(nameFound, first)) {
-                result = nameFound;
-                break;
-            }
-        }
-    }
-
-    return result;
+    const char* nameInternal = NULL;
+
+    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;
+}
+
+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
 }
 
@@ -15509,442 +16380,37 @@
 {
     if (ssl == NULL) {
-        WOLFSSL_MSG("Bad argument");
         return NULL;
     }
 
-    return GetCipherNameInternal(
-        wolfSSL_CIPHER_get_name(&ssl->cipher),
-        ssl->options.cipherSuite);
+    return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite);
 }
 
-
-const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite,
-    const unsigned char cipherSuite0)
+const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
 {
-
-    WOLFSSL_ENTER("wolfSSL_get_cipher_name_from_suite");
-
-    (void)cipherSuite;
-    (void)cipherSuite0;
-
-#ifndef NO_ERROR_STRINGS
-
-#if defined(HAVE_CHACHA)
-    if (cipherSuite0 == CHACHA_BYTE) {
-        /* ChaCha suites */
-        switch (cipherSuite) {
-#ifdef HAVE_POLY1305
-#ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
-
-            case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
-
-            case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-                return "TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
-
-            case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-                return "TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
-#endif
-            case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
-
-            case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-                return "TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
-#ifndef NO_PSK
-            case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256";
-            case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256";
-            case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-                return "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256";
-#endif /* NO_PSK */
-#endif /* HAVE_POLY1305 */
-        } /* switch */
-    } /* chacha */
-#endif /* HAVE_CHACHA */
-
-#if defined(HAVE_ECC) || defined(HAVE_AESCCM)
-        /* Awkwardly, the ECC cipher suites use the ECC_BYTE as expected,
-         * but the AES-CCM cipher suites also use it, even the ones that
-         * aren't ECC. */
-    if (cipherSuite0 == ECC_BYTE) {
-        /* ECC suites */
-        switch (cipherSuite) {
-#ifdef HAVE_ECC
-    #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
-    #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
-    #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
-    #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
-    #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
-                return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
-    #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
-                return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
-    #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
-                return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
-    #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
-                return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
-#ifndef NO_SHA
-    #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
-                return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
-            case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
-                return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
-    #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
-                return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
-            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
-                return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
-    #ifndef NO_RC4
-        #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
-                return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
-        #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
-                return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
-    #endif /* !NO_RC4 */
-    #ifndef NO_DES3
-        #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
-                return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
-        #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
-                return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
-    #endif /* !NO_DES3 */
-
-    #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
-                return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
-            case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
-                return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
-    #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
-                return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
-            case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
-                return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
-    #ifndef NO_RC4
-        #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_RC4_128_SHA :
-                return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
-        #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
-                return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
-    #endif /* !NO_RC4 */
-    #ifndef NO_DES3
-        #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
-                return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
-        #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
-                return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
-    #endif /* !NO_DES3 */
-#endif /* HAVE_ECC */
-
-#ifdef HAVE_AESGCM
-    #ifndef NO_RSA
-            case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
-            case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
-    #endif /* !NO_RSA */
-            case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
-            case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
-    #ifndef NO_RSA
-            case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
-            case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
-    #endif /* !NO_RSA */
-            case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
-            case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
-#endif /* HAVE_AESGCM */
-
-            case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
-                return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
-    #ifndef NO_PSK
-            case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
-                return "TLS_ECDHE_PSK_WITH_NULL_SHA256";
-            case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
-                return "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256";
-    #endif /* !NO_PSK */
-    #ifndef NO_RSA
-            case TLS_RSA_WITH_AES_128_CCM_8 :
-                return "TLS_RSA_WITH_AES_128_CCM_8";
-            case TLS_RSA_WITH_AES_256_CCM_8 :
-                return "TLS_RSA_WITH_AES_256_CCM_8";
-    #endif /* !NO_RSA */
-    #ifndef NO_PSK
-            case TLS_PSK_WITH_AES_128_CCM_8 :
-                return "TLS_PSK_WITH_AES_128_CCM_8";
-            case TLS_PSK_WITH_AES_256_CCM_8 :
-                return "TLS_PSK_WITH_AES_256_CCM_8";
-            case TLS_PSK_WITH_AES_128_CCM :
-                return "TLS_PSK_WITH_AES_128_CCM";
-            case TLS_PSK_WITH_AES_256_CCM :
-                return "TLS_PSK_WITH_AES_256_CCM";
-            case TLS_DHE_PSK_WITH_AES_128_CCM :
-                return "TLS_DHE_PSK_WITH_AES_128_CCM";
-            case TLS_DHE_PSK_WITH_AES_256_CCM :
-                return "TLS_DHE_PSK_WITH_AES_256_CCM";
-    #endif /* !NO_PSK */
-    #ifdef HAVE_ECC
-            case TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
-                return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM";
-            case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-                return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8";
-            case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
-                return "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8";
-    #endif /* HAVE_ECC */
-#endif /* HAVE_AESGCM */
-
-            default:
-                return "NONE";
-        } /* switch */
-    } /* ECC and AES CCM/GCM */
-#endif  /* HAVE_ECC || HAVE_AESCCM*/
-
-    if (cipherSuite0 == TLS13_BYTE) {
-        /* TLS v1.3 suites */
-        switch (cipherSuite) {
-#ifdef WOLFSSL_TLS13
-    #ifdef HAVE_AESGCM
-            case TLS_AES_128_GCM_SHA256 :
-                return "TLS_AES_128_GCM_SHA256";
-            case TLS_AES_256_GCM_SHA384 :
-                return "TLS_AES_256_GCM_SHA384";
-    #endif
-
-    #ifdef HAVE_CHACHA
-            case TLS_CHACHA20_POLY1305_SHA256 :
-                return "TLS_CHACHA20_POLY1305_SHA256";
-    #endif
-
-    #ifdef HAVE_AESCCM
-            case TLS_AES_128_CCM_SHA256 :
-                return "TLS_AES_128_CCM_SHA256";
-            case TLS_AES_128_CCM_8_SHA256 :
-                return "TLS_AES_256_CCM_8_SHA256";
-    #endif
-#endif
-
-            default:
-                return "NONE";
-        }
-    }
-
-    if (cipherSuite0 != ECC_BYTE &&
-        cipherSuite0 != CHACHA_BYTE &&
-        cipherSuite0 != TLS13_BYTE) {
-
-        /* normal suites */
-        switch (cipherSuite) {
-#ifndef NO_RSA
-    #ifndef NO_RC4
-        #ifndef NO_SHA
-            case SSL_RSA_WITH_RC4_128_SHA :
-                return "SSL_RSA_WITH_RC4_128_SHA";
-        #endif /* !NO_SHA */
-        #ifndef NO_MD5
-            case SSL_RSA_WITH_RC4_128_MD5 :
-                return "SSL_RSA_WITH_RC4_128_MD5";
-        #endif /* !NO_MD5 */
-    #endif /* !NO_RC4 */
-    #ifndef NO_SHA
-        #ifndef NO_DES3
-            case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
-                return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
-        #endif /* !NO_DES3 */
-        #ifdef HAVE_IDEA
-            case SSL_RSA_WITH_IDEA_CBC_SHA :
-                return "SSL_RSA_WITH_IDEA_CBC_SHA";
-        #endif /* HAVE_IDEA */
-
-            case TLS_RSA_WITH_AES_128_CBC_SHA :
-                return "TLS_RSA_WITH_AES_128_CBC_SHA";
-            case TLS_RSA_WITH_AES_256_CBC_SHA :
-                return "TLS_RSA_WITH_AES_256_CBC_SHA";
-    #endif /* !NO_SHA */
-            case TLS_RSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_RSA_WITH_AES_128_CBC_SHA256";
-            case TLS_RSA_WITH_AES_256_CBC_SHA256 :
-                return "TLS_RSA_WITH_AES_256_CBC_SHA256";
-    #ifdef HAVE_BLAKE2
-            case TLS_RSA_WITH_AES_128_CBC_B2B256:
-                return "TLS_RSA_WITH_AES_128_CBC_B2B256";
-            case TLS_RSA_WITH_AES_256_CBC_B2B256:
-                return "TLS_RSA_WITH_AES_256_CBC_B2B256";
-    #endif /* HAVE_BLAKE2 */
-    #ifndef NO_SHA
-            case TLS_RSA_WITH_NULL_SHA :
-                return "TLS_RSA_WITH_NULL_SHA";
-    #endif /* !NO_SHA */
-            case TLS_RSA_WITH_NULL_SHA256 :
-                return "TLS_RSA_WITH_NULL_SHA256";
-#endif /* NO_RSA */
-
-#ifndef NO_PSK
-    #ifndef NO_SHA
-            case TLS_PSK_WITH_AES_128_CBC_SHA :
-                return "TLS_PSK_WITH_AES_128_CBC_SHA";
-            case TLS_PSK_WITH_AES_256_CBC_SHA :
-                return "TLS_PSK_WITH_AES_256_CBC_SHA";
-    #endif /* !NO_SHA */
-    #ifndef NO_SHA256
-            case TLS_PSK_WITH_AES_128_CBC_SHA256 :
-                return "TLS_PSK_WITH_AES_128_CBC_SHA256";
-            case TLS_PSK_WITH_NULL_SHA256 :
-                return "TLS_PSK_WITH_NULL_SHA256";
-            case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
-                return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
-            case TLS_DHE_PSK_WITH_NULL_SHA256 :
-                return "TLS_DHE_PSK_WITH_NULL_SHA256";
-        #ifdef HAVE_AESGCM
-            case TLS_PSK_WITH_AES_128_GCM_SHA256 :
-                return "TLS_PSK_WITH_AES_128_GCM_SHA256";
-            case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
-                return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
-        #endif /* HAVE_AESGCM */
-    #endif /* !NO_SHA256 */
-    #ifdef WOLFSSL_SHA384
-            case TLS_PSK_WITH_AES_256_CBC_SHA384 :
-                return "TLS_PSK_WITH_AES_256_CBC_SHA384";
-            case TLS_PSK_WITH_NULL_SHA384 :
-                return "TLS_PSK_WITH_NULL_SHA384";
-            case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
-                return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
-            case TLS_DHE_PSK_WITH_NULL_SHA384 :
-                return "TLS_DHE_PSK_WITH_NULL_SHA384";
-        #ifdef HAVE_AESGCM
-            case TLS_PSK_WITH_AES_256_GCM_SHA384 :
-                return "TLS_PSK_WITH_AES_256_GCM_SHA384";
-            case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
-                return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
-        #endif /* HAVE_AESGCM */
-    #endif /* WOLFSSL_SHA384 */
-    #ifndef NO_SHA
-            case TLS_PSK_WITH_NULL_SHA :
-                return "TLS_PSK_WITH_NULL_SHA";
-    #endif /* !NO_SHA */
-    #endif /* NO_PSK */
-
-    #ifndef NO_RSA
-            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
-                return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
-            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
-                return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
-    #ifndef NO_SHA
-            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
-                return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
-            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
-                return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
-        #ifndef NO_DES3
-            case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-                return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
-         #endif
-    #endif /* !NO_RSA */
-    #ifndef NO_HC128
-        #ifndef NO_MD5
-            case TLS_RSA_WITH_HC_128_MD5 :
-                return "TLS_RSA_WITH_HC_128_MD5";
-        #endif /* !NO_MD5 */
-        #ifndef NO_SHA
-            case TLS_RSA_WITH_HC_128_SHA :
-                return "TLS_RSA_WITH_HC_128_SHA";
-        #endif /* !NO_SHA */
-        #ifdef HAVE_BLAKE2
-            case TLS_RSA_WITH_HC_128_B2B256:
-                return "TLS_RSA_WITH_HC_128_B2B256";
-        #endif /* HAVE_BLAKE2 */
-    #endif /* !NO_HC128 */
-    #ifndef NO_SHA
-        #ifndef NO_RABBIT
-            case TLS_RSA_WITH_RABBIT_SHA :
-                return "TLS_RSA_WITH_RABBIT_SHA";
-        #endif /* !NO_RABBIT */
-        #ifdef HAVE_NTRU
-            #ifndef NO_RC4
-            case TLS_NTRU_RSA_WITH_RC4_128_SHA :
-                return "TLS_NTRU_RSA_WITH_RC4_128_SHA";
-            #endif /* !NO_RC4 */
-            #ifndef NO_DES3
-            case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
-                return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA";
-            #endif /* !NO_DES3 */
-            case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
-                return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
-            case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
-                return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA";
-        #endif /* HAVE_NTRU */
-
-        #ifdef HAVE_QSH
-            case TLS_QSH :
-                return "TLS_QSH";
-        #endif /* HAVE_QSH */
-    #endif /* !NO_SHA */
-
-            case TLS_RSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_RSA_WITH_AES_128_GCM_SHA256";
-            case TLS_RSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_RSA_WITH_AES_256_GCM_SHA384";
-            case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
-                return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
-            case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
-                return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
-    #ifndef NO_SHA
-            case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
-                return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA";
-            case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
-                return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA";
-    #endif /* !NO_SHA */
-            case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-                return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256";
-            case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-                return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256";
-    #ifndef NO_SHA
-            case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
-                return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA";
-            case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
-                return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA";
-    #endif /* !NO_SHA */
-            case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-                return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256";
-            case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-                return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256";
-#endif /* !NO_PSK */
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-            case TLS_DH_anon_WITH_AES_128_CBC_SHA :
-                return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
-#endif
-#ifdef BUILD_WDM_WITH_NULL_SHA256
-            case WDM_WITH_NULL_SHA256 :
-                return "WDM_WITH_NULL_SHA256";
-#endif
-            default:
-                return "NONE";
-        } /* switch */
-    } /* normal / PSK */
-#endif /* NO_ERROR_STRINGS */
-
-    return "NONE";
+    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;
+}
 
 /**
@@ -15974,5 +16440,5 @@
     if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 ||
                         XSTRNCMP(next, "DEFAULT", 7) == 0)
-        return 1; /* wolfSSL defualt */
+        return 1; /* wolfSSL default */
 
     do {
@@ -15990,5 +16456,5 @@
 
         for (i = 0; i < suiteSz; i++) {
-            if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
+            if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0) {
             #ifdef WOLFSSL_DTLS
                 /* don't allow stream ciphers with DTLS */
@@ -16010,24 +16476,53 @@
                 }
 
-                suites->suites[idx++] = (XSTRSTR(name, "TLS13"))  ? TLS13_BYTE
-                                      : (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE
-                                      : (XSTRSTR(name, "QSH"))    ? QSH_BYTE
-                                      : (XSTRSTR(name, "EC"))     ? ECC_BYTE
-                                      : (XSTRSTR(name, "CCM"))    ? ECC_BYTE
-                                      : 0x00; /* normal */
-                suites->suites[idx++] = (byte)cipher_name_idx[i];
-
+                suites->suites[idx++] =
+            #ifdef WOLFSSL_TLS13
+                    (XSTRSTR(name, "TLS13"))  ? TLS13_BYTE :
+            #endif
+            #ifdef HAVE_CHACHA
+                    (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE :
+            #endif
+            #ifdef HAVE_QSH
+                    (XSTRSTR(name, "QSH"))    ? QSH_BYTE :
+            #endif
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    (XSTRSTR(name, "EC"))     ? ECC_BYTE :
+            #endif
+            #ifdef HAVE_AESCCM
+                    (XSTRSTR(name, "CCM"))    ? ECC_BYTE :
+            #endif
+                    CIPHER_BYTE; /* normal */
+
+                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 (XSTRSTR(name, "TLS13")) {
+                #ifndef NO_RSA
                     haveRSAsig = 1;
+                #endif
+                #if defined(HAVE_ECC) || defined(HAVE_ED25519)
                     haveECDSAsig = 1;
+                #endif
                 }
-                else if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
+                else
+            #endif
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+                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 */
@@ -16054,4 +16549,5 @@
 }
 
+
 #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
 void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
@@ -16069,4 +16565,5 @@
     #endif
     }
+#ifndef WOLFSSL_NO_TLS12
     else if (IsAtLeastTLSv1_2(ssl)) {
     #ifdef WOLFSSL_ALLOW_TLS_SHA1
@@ -16079,4 +16576,5 @@
         ssl->suites->hashAlgo = sha_mac;
     }
+#endif
 
     /* i+1 since peek a byte ahead for type */
@@ -16085,5 +16583,5 @@
 
         DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo);
-    #ifdef HAVE_ECC
+    #ifdef HAVE_ED25519
         if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo)
             continue;
@@ -16096,31 +16594,79 @@
         }
     #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 higest
+     * 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) {
+            word32 digestSz = 0;
+            switch (hashAlgo) {
+            #ifndef NO_SHA
+                case sha_mac:
+                    digestSz = WC_SHA_DIGEST_SIZE;
+                break;
+            #endif
+            #ifndef NO_SHA256
+                case sha256_mac:
+                    digestSz = WC_SHA256_DIGEST_SIZE;
+                break;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case sha384_mac:
+                    digestSz = WC_SHA384_DIGEST_SIZE;
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case sha512_mac:
+                    digestSz = WC_SHA512_DIGEST_SIZE;
+                break;
+            #endif
+                default:
+                    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;
+                return; /* 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;
+            }
+        else
+    #endif
         if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo &&
                                          ssl->suites->sigAlgo == rsa_sa_algo)) {
-            if (hashAlgo == sha_mac) {
+            /* pick highest available between both server and client */
+            switch (hashAlgo) {
+                case sha_mac:
+            #ifndef NO_SHA256
+                case sha256_mac:
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case sha384_mac:
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case sha512_mac:
+            #endif
+                    /* not strong enough, so keep checking hashSigAlso list */
+                    if (hashAlgo < ssl->suites->hashAlgo)
+                        continue;
+                    /* mark as highest and check remainder of hashSigAlgo list */
+                    ssl->suites->hashAlgo = hashAlgo;
                 ssl->suites->sigAlgo = sigAlgo;
                 break;
-            }
-            #ifndef NO_SHA256
-            else if (hashAlgo == sha256_mac) {
-                ssl->suites->hashAlgo = sha256_mac;
-                ssl->suites->sigAlgo = sigAlgo;
-                break;
-            }
-            #endif
-            #ifdef WOLFSSL_SHA384
-            else if (hashAlgo == sha384_mac) {
-                ssl->suites->hashAlgo = sha384_mac;
-                ssl->suites->sigAlgo = sigAlgo;
-                break;
-            }
-            #endif
-            #ifdef WOLFSSL_SHA512
-            else if (hashAlgo == sha512_mac) {
-                ssl->suites->hashAlgo = sha512_mac;
-                ssl->suites->sigAlgo = sigAlgo;
-                break;
-            }
-            #endif
+                default:
+                    continue;
+            }
+            break;
         }
         else if (ssl->specs.sig_algo == 0) {
@@ -16128,11 +16674,10 @@
         }
     }
-
 }
 #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
 
-#ifdef WOLFSSL_CALLBACKS
-
-    /* Initialisze HandShakeInfo */
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+
+    /* Initialize HandShakeInfo */
     void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl)
     {
@@ -16151,11 +16696,13 @@
     {
         int i;
-        int sz = sizeof(cipher_name_idx)/sizeof(int);
+        int sz = GetCipherNamesSize();
 
         for (i = 0; i < sz; i++)
-            if (info->ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
+            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;
             }
@@ -16168,14 +16715,22 @@
 
     /* 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);
-        }
-    }
-
-
-    /* Initialisze TimeoutInfo */
+            char* packetName = info->packetNames[info->numberPackets];
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+            info->numberPackets++;
+        }
+    #endif
+        (void)ssl;
+        (void)name;
+    }
+
+
+    #ifdef WOLFSSL_CALLBACKS
+    /* Initialize TimeoutInfo */
     void InitTimeoutInfo(TimeoutInfo* info)
     {
@@ -16211,16 +16766,59 @@
     }
 
-
-    /* Add PacketInfo to TimeoutInfo */
-    void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
-                       int sz, void* heap)
+    /* 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) {
+            char* packetName = info->packets[info->numberPackets-1].packetName;
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+        }
+    }
+
+    /* 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);
+        }
+    }
+
+    #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;
 
             /* 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 */
@@ -16245,40 +16843,188 @@
             info->numberPackets++;
         }
-    }
-
-
-    /* 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);
-        }
-    }
-
-    /* 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);
-        }
+    #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) && (defined(WOLFSSL_TLS13) || \
+                                                    !defined(NO_WOLFSSL_CLIENT))
+
+/* Decode the private key - RSA, ECC, or Ed25519 - 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;
+
+    /* 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);
+    }
+
+#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 */
+
+#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 */
+
+    (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)
     {
@@ -16292,5 +17038,4 @@
         word16             extSz = 0;
 
-
 #ifdef WOLFSSL_TLS13
         if (IsAtLeastTLSv1_3(ssl->version))
@@ -16298,4 +17043,7 @@
 #endif
 
+        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+        WOLFSSL_ENTER("SendClientHello");
+
         if (ssl->suites == NULL) {
             WOLFSSL_MSG("Bad suites pointer in SendClientHello");
@@ -16312,5 +17060,8 @@
 
             ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap);
-            if (ret != WOLFSSL_SUCCESS) return ret;
+            if (ret != WOLFSSL_SUCCESS) {
+                TLSX_SessionTicket_Free(ticket, ssl->heap);
+                return ret;
+            }
 
             idSz = 0;
@@ -16330,6 +17081,8 @@
             return MEMORY_E;
     #endif
-        extSz = TLSX_GetRequestSize(ssl, client_hello);
-        if (extSz != 0)
+        extSz = 0;
+        ret = TLSX_GetRequestSize(ssl, client_hello, &extSz);
+        if (ret != 0)
+            return ret;
             length += extSz;
 #else
@@ -16427,5 +17180,9 @@
 
 #ifdef HAVE_TLS_EXTENSIONS
-        idx += TLSX_WriteRequest(ssl, output + idx, client_hello);
+        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 */
@@ -16481,4 +17238,8 @@
         } else {
             #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                        return ret;
+                }
                 if (ssl->options.dtls)
                     DtlsSEQIncrement(ssl, CUR_ORDER);
@@ -16489,26 +17250,30 @@
         }
 
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                    return ret;
-            }
-        #endif
-
         ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-
-#ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+		if (ssl->CBIS != NULL)
+			ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#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)
@@ -16519,6 +17284,5 @@
 
 #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
-                                         &ssl->handShakeInfo);
+        if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest");
         if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
 #endif
@@ -16560,5 +17324,5 @@
 
 
-    static INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
+    static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
     {
         int ret = 0;
@@ -16592,8 +17356,5 @@
     int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
     {
-#ifdef WOLFSSL_TLS13
-        /* TODO: [TLS13] Remove this.
-         * Translate the draft TLS v1.3 version to final version.
-         */
+    #ifdef WOLFSSL_TLS13_DRAFT
         if (pv.major == TLS_DRAFT_MAJOR) {
             pv.major = SSLv3_MAJOR;
@@ -16602,5 +17363,10 @@
 #endif
 
-        /* Check for upgrade attack. */
+        #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");
@@ -16692,4 +17458,5 @@
     }
 
+    /* handle processing of server_hello (2) */
     int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                       word32 helloSz)
@@ -16703,6 +17470,9 @@
         int             ret;
 
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
+        WOLFSSL_ENTER("DoServerHello");
+
 #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
         if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
 #endif
@@ -16721,6 +17491,8 @@
 
 #ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(pv))
-            return DoTls13ServerHello(ssl, input, inOutIdx, helloSz);
+        if (IsAtLeastTLSv1_3(pv)) {
+            byte type = server_hello;
+            return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
+        }
 #endif
 
@@ -16728,31 +17500,4 @@
         XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
         i += RAN_LEN;
-
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
-            /* TLS v1.3 capable client not allowed to downgrade when connecting
-             * to TLS v1.3 capable server.
-             */
-            if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1),
-                             tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
-                             (*(input + i - 1) == 0 || *(input + i - 1) == 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(input + i - (TLS13_DOWNGRADE_SZ + 1),
-                        tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
-                                                        *(input + i - 1) == 0) {
-                SendAlert(ssl, alert_fatal, illegal_parameter);
-                return VERSION_ERROR;
-            }
-        }
 
         /* session id */
@@ -16823,6 +17568,6 @@
                     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;
 
@@ -16912,5 +17657,47 @@
 #endif /* HAVE_SECRET_CALLBACK */
 
-        if (ssl->options.resuming) {
+        ret = CompleteServerHello(ssl);
+
+        WOLFSSL_LEAVE("DoServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+        return ret;
+    }
+
+    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 (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
+                /* 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) {
@@ -16952,4 +17739,6 @@
     }
 
+#endif /* WOLFSSL_NO_TLS12 */
+
 
     /* Make sure client setup is valid for this suite, true on success */
@@ -16977,7 +17766,8 @@
     }
 
+#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)
@@ -16986,7 +17776,10 @@
         word32 begin = *inOutIdx;
 
+        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);
@@ -17052,13 +17845,30 @@
         /* don't send client cert or cert verify if user hasn't provided
            cert and private key */
-        if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
-            ssl->buffers.key && ssl->buffers.key->buffer)
+        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 (IsEncryptionOn(ssl, 0))
             *inOutIdx += ssl->keys.padSz;
 
+        WOLFSSL_LEAVE("DoCertificateRequest", 0);
+        WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
+
         return 0;
     }
@@ -17066,5 +17876,5 @@
 
 
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
 
     static int CheckCurveId(int tlsCurveId)
@@ -17143,10 +17953,10 @@
 typedef struct DskeArgs {
     byte*  output; /* not allocated */
-#if !defined(NO_DH) || defined(HAVE_ECC)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
     byte*  verifySig;
 #endif
     word32 idx;
     word32 begin;
-#if !defined(NO_DH) || defined(HAVE_ECC)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
     word16 verifySigSz;
 #endif
@@ -17163,5 +17973,5 @@
     (void)args;
 
-#if !defined(NO_DH) || defined(HAVE_ECC)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
     if (args->verifySig) {
         XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
@@ -17171,4 +17981,5 @@
 }
 
+/* handle processing of server_key_exchange (12) */
 static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
                                word32* inOutIdx, word32 size)
@@ -17183,4 +17994,8 @@
 #endif
 
+    (void)input;
+    (void)size;
+
+    WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
     WOLFSSL_ENTER("DoServerKeyExchange");
 
@@ -17214,5 +18029,5 @@
         #ifdef WOLFSSL_CALLBACKS
             if (ssl->hsInfoOn)
-                AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+                AddPacketName(ssl, "ServerKeyExchange");
             if (ssl->toInfoOn)
                 AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
@@ -17269,4 +18084,9 @@
                         ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
                     }
+                    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_dske);
+                    }
 
                     ssl->buffers.serverDH_P.buffer =
@@ -17310,4 +18130,6 @@
                     args->idx += length;
 
+                    ssl->buffers.weOwnDH = 1;
+
                     /* pub */
                     if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
@@ -17337,9 +18159,12 @@
                 }
             #endif /* !NO_DH */
-            #ifdef HAVE_ECC
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                 case ecc_diffie_hellman_kea:
                 {
                     byte b;
-                    int curveId, curveOid;
+                #ifdef HAVE_ECC
+                    int curveId;
+                #endif
+                    int curveOid;
                     word16 length;
 
@@ -17374,5 +18199,5 @@
                                 goto exit_dske;
                             }
-                        } else if (ssl->peerEccKeyPresent) {
+                        } else if (ssl->peerX25519KeyPresent) {
                             ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
                                            ssl->peerX25519Key);
@@ -17394,4 +18219,5 @@
                     }
              #endif
+                #ifdef HAVE_ECC
                     if (ssl->peerEccKey == NULL) {
                         ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
@@ -17417,6 +18243,7 @@
                     ssl->peerEccKeyPresent = 1;
                     break;
+                #endif
                 }
-            #endif /* HAVE_ECC */
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
             #if !defined(NO_DH) && !defined(NO_PSK)
                 case dhe_psk_kea:
@@ -17457,4 +18284,9 @@
                     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_dske);
+                    }
+                    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_dske);
@@ -17501,4 +18333,6 @@
                     args->idx += length;
 
+                    ssl->buffers.weOwnDH = 1;
+
                     /* pub */
                     if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
@@ -17528,5 +18362,6 @@
                 }
             #endif /* !NO_DH || !NO_PSK */
-            #if defined(HAVE_ECC) && !defined(NO_PSK)
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                 case ecdhe_psk_kea:
                 {
@@ -17607,5 +18442,5 @@
 
                     if (ssl->peerEccKey == NULL) {
-                        AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
                                  (void**)&ssl->peerEccKey);
                         if (ret != 0) {
@@ -17630,5 +18465,5 @@
                     break;
                 }
-            #endif /* HAVE_ECC || !NO_PSK */
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
                 default:
                     ret = BAD_KEA_TYPE_E;
@@ -17660,5 +18495,5 @@
                 case ecc_diffie_hellman_kea:
                 {
-            #if defined(NO_DH) && !defined(HAVE_ECC)
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
                     ERROR_OUT(NOT_COMPILED_IN, exit_dske);
             #else
@@ -17729,7 +18564,11 @@
 
                     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.length =
-                                                 wc_HashGetDigestSize(hashType);
                         ssl->buffers.digest.buffer = (byte*)XMALLOC(
                             ssl->buffers.digest.length, ssl->heap,
@@ -17773,5 +18612,5 @@
                         }
                     #endif /* HAVE_ECC */
-                    #ifdef HAVE_ED25519
+                    #if defined(HAVE_ED25519)
                         case ed25519_sa_algo:
                         {
@@ -17781,5 +18620,5 @@
                             break;
                         }
-                    #endif /* HAVE_ECC */
+                    #endif /* HAVE_ED25519 */
 
                     default:
@@ -17787,5 +18626,5 @@
                     } /* switch (args->sigAlgo) */
 
-            #endif /* NO_DH && !HAVE_ECC */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
                     break;
                 }
@@ -17819,5 +18658,5 @@
                 case ecc_diffie_hellman_kea:
                 {
-            #if defined(NO_DH) && !defined(HAVE_ECC)
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
                     ERROR_OUT(NOT_COMPILED_IN, exit_dske);
             #else
@@ -17850,9 +18689,7 @@
                                 ssl->peerRsaKey,
                             #ifdef HAVE_PK_CALLBACKS
-                                ssl->buffers.peerRsaKey.buffer,
-                                ssl->buffers.peerRsaKey.length,
-                                ssl->RsaVerifyCtx
+                                &ssl->buffers.peerRsaKey
                             #else
-                                NULL, 0, NULL
+                                NULL
                             #endif
                             );
@@ -17861,4 +18698,13 @@
                                 args->sigSz = (word16)ret;
                                 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;
@@ -17874,16 +18720,23 @@
                                 ssl->peerEccDsaKey,
                             #ifdef HAVE_PK_CALLBACKS
-                                ssl->buffers.peerEccDsaKey.buffer,
-                                ssl->buffers.peerEccDsaKey.length,
-                                ssl->EccVerifyCtx
+                                &ssl->buffers.peerEccDsaKey
                             #else
-                                NULL, 0, NULL
+                                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 */
-                    #ifdef HAVE_ED25519
+                    #if defined(HAVE_ED25519)
                         case ed25519_sa_algo:
                         {
@@ -17894,20 +18747,27 @@
                                 ssl->peerEd25519Key,
                             #ifdef HAVE_PK_CALLBACKS
-                                ssl->buffers.peerEccDsaKey.buffer,
-                                ssl->buffers.peerEccDsaKey.length,
-                                ssl->Ed25519VerifyCtx
+                                &ssl->buffers.peerEd25519Key
                             #else
-                                NULL, 0, NULL
+                                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_ECC */
+                    #endif /* HAVE_ED25519 */
 
                     default:
                         ret = ALGO_ID_E;
                     } /* switch (sigAlgo) */
-            #endif /* NO_DH && !HAVE_ECC */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
                     break;
                 }
@@ -17941,5 +18801,5 @@
                 case ecc_diffie_hellman_kea:
                 {
-            #if defined(NO_DH) && !defined(HAVE_ECC)
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
                     ERROR_OUT(NOT_COMPILED_IN, exit_dske);
             #else
@@ -18014,13 +18874,13 @@
                             break;
                     #endif /* HAVE_ECC */
-                    #ifdef HAVE_ED25519
+                    #if defined(HAVE_ED25519)
                         case ed25519_sa_algo:
                             /* Nothing to do in this algo */
                             break;
-                    #endif /* HAVE_ECC */
+                    #endif /* HAVE_ED25519 */
                         default:
                             ret = ALGO_ID_E;
                     } /* switch (sigAlgo) */
-            #endif /* NO_DH && !HAVE_ECC */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
                     break;
                 }
@@ -18091,9 +18951,10 @@
 
     WOLFSSL_LEAVE("DoServerKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
 
 #ifdef WOLFSSL_ASYNC_CRYPT
     /* Handle async operation */
     if (ret == WC_PENDING_E) {
-        /* Mark message as not recevied so it can process again */
+        /* Mark message as not received so it can process again */
         ssl->msgsReceived.got_server_key_exchange = 0;
 
@@ -18518,4 +19379,5 @@
 }
 
+/* handle generation client_key_exchange (16) */
 int SendClientKeyExchange(WOLFSSL* ssl)
 {
@@ -18529,5 +19391,13 @@
 #endif
 
+    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
@@ -18596,5 +19466,6 @@
                     break;
             #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK)
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                 case ecdhe_psk_kea:
                     /* sanity check that PSK client callback has been set */
@@ -18643,5 +19514,5 @@
                 #endif
 
-                    /* create private key */
+                    /* create ephemeral private key */
                     ssl->hsType = DYNAMIC_TYPE_ECC;
                     ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
@@ -18702,7 +19573,6 @@
                 #ifdef HAVE_ECC
                     if (ssl->specs.static_ecdh) {
-                        /* TODO: EccDsa is really fixed Ecc change naming */
-                        if (!ssl->peerEccDsaKey ||
-                                !ssl->peerEccDsaKeyPresent ||
+                        /* Note: EccDsa is really fixed Ecc key here */
+                        if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
                                     !ssl->peerEccDsaKey->dp) {
                             ERROR_OUT(NO_PEER_KEY, exit_scke);
@@ -18721,5 +19591,5 @@
                     }
 
-                    /* create private key */
+                    /* create ephemeral private key */
                     ssl->hsType = DYNAMIC_TYPE_ECC;
                     ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
@@ -18757,4 +19627,12 @@
                 ERROR_OUT(MEMORY_E, exit_scke);
             }
+            if (ssl->arrays->preMasterSecret == NULL) {
+                ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN,
+                                                ssl->heap, DYNAMIC_TYPE_SECRET);
+                if (ssl->arrays->preMasterSecret == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+                XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+            }
 
             switch(ssl->specs.kea)
@@ -18763,6 +19641,8 @@
                 case rsa_kea:
                 {
+                    /* build PreMasterSecret with RNG data */
                     ret = wc_RNG_GenerateBlock(ssl->rng,
-                        ssl->arrays->preMasterSecret, SECRET_LEN);
+                        &ssl->arrays->preMasterSecret[VERSION_SZ],
+                        SECRET_LEN - VERSION_SZ);
                     if (ret != 0) {
                         goto exit_scke;
@@ -18791,4 +19671,23 @@
                     }
 
+                    #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,
@@ -18798,4 +19697,5 @@
                     if (ret != 0) {
                         goto exit_scke;
+                    }
                     }
 
@@ -18886,4 +19786,23 @@
                     }
 
+                    #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,
@@ -18894,4 +19813,5 @@
                         goto exit_scke;
                     }
+                    }
 
                     /* for DH, encSecret is Yc, agree is pre-master */
@@ -18902,5 +19822,6 @@
                 }
             #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK)
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                 case ecdhe_psk_kea:
                 {
@@ -18972,5 +19893,5 @@
                     break;
                 }
-            #endif /* HAVE_ECC && !NO_PSK */
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
             #ifdef HAVE_NTRU
                 case ntru_kea:
@@ -19012,5 +19933,5 @@
                     }
                 #endif
-                #ifdef HAVE_ECC
+                #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
                 #ifdef HAVE_PK_CALLBACKS
                     /* if callback then use it for shared secret */
@@ -19057,9 +19978,7 @@
                         ssl->peerRsaKey,
                     #if defined(HAVE_PK_CALLBACKS)
-                        ssl->buffers.peerRsaKey.buffer,
-                        ssl->buffers.peerRsaKey.length,
-                        ssl->RsaEncCtx
+                        &ssl->buffers.peerRsaKey
                     #else
-                        NULL, 0, NULL
+                        NULL
                     #endif
                     );
@@ -19098,5 +20017,6 @@
                 }
             #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK)
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                 case ecdhe_psk_kea:
                 {
@@ -19108,11 +20028,15 @@
                             ssl->arrays->preMasterSecret + OPAQUE16_LEN,
                             &ssl->arrays->preMasterSz,
-                            WOLFSSL_CLIENT_END,
-                        #ifdef HAVE_PK_CALLBACKS
-                            ssl->EccSharedSecretCtx
-                        #else
-                            NULL
+                            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;
                     }
@@ -19123,11 +20047,14 @@
                         ssl->arrays->preMasterSecret + OPAQUE16_LEN,
                         &ssl->arrays->preMasterSz,
-                        WOLFSSL_CLIENT_END,
-                    #ifdef HAVE_PK_CALLBACKS
-                        ssl->EccSharedSecretCtx
-                    #else
-                        NULL
-                    #endif
+                        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;
                 }
@@ -19173,11 +20100,15 @@
                             ssl->arrays->preMasterSecret,
                             &ssl->arrays->preMasterSz,
-                            WOLFSSL_CLIENT_END,
-                        #ifdef HAVE_PK_CALLBACKS
-                            ssl->EccSharedSecretCtx
-                        #else
-                            NULL
+                            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;
                     }
@@ -19192,11 +20123,15 @@
                         ssl->arrays->preMasterSecret,
                         &ssl->arrays->preMasterSz,
-                        WOLFSSL_CLIENT_END,
-                    #ifdef HAVE_PK_CALLBACKS
-                        ssl->EccSharedSecretCtx
-                    #else
-                        NULL
-                    #endif
+                        WOLFSSL_CLIENT_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;
+                    }
                 #endif
 
@@ -19269,5 +20204,6 @@
                 }
             #endif /* !NO_DH && !NO_PSK */
-            #if defined(HAVE_ECC) && !defined(NO_PSK)
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                 case ecdhe_psk_kea:
                 {
@@ -19283,5 +20219,5 @@
                     args->encSz += args->length + OPAQUE8_LEN;
 
-                    /* Create pre master secret is the concatination of
+                    /* Create pre master secret is the concatenation of
                        eccSize + eccSharedKey + pskSize + pskKey */
                     c16toa((word16)ssl->arrays->preMasterSz, pms);
@@ -19299,5 +20235,5 @@
                     break;
                 }
-            #endif /* HAVE_ECC && !NO_PSK */
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
             #ifdef HAVE_NTRU
                 case ntru_kea:
@@ -19306,5 +20242,5 @@
                 }
             #endif /* HAVE_NTRU */
-            #ifdef HAVE_ECC
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                 case ecc_diffie_hellman_kea:
                 {
@@ -19314,5 +20250,5 @@
                     break;
                 }
-            #endif /* HAVE_ECC */
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
 
                 default:
@@ -19467,10 +20403,10 @@
         #endif
 
-        #ifdef WOLFSSL_CALLBACKS
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
             if (ssl->hsInfoOn)
-                AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+                AddPacketName(ssl, "ClientKeyExchange");
             if (ssl->toInfoOn)
-                AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
-                              args->output, args->sendSz, ssl->heap);
+                AddPacketInfo(ssl, "ClientKeyExchange", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
         #endif
 
@@ -19496,4 +20432,5 @@
 
     WOLFSSL_LEAVE("SendClientKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
 
 #ifdef WOLFSSL_ASYNC_CRYPT
@@ -19504,5 +20441,7 @@
 
     /* No further need for PMS */
+    if (ssl->arrays->preMasterSecret != NULL) {
     ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+    }
     ssl->arrays->preMasterSz = 0;
 
@@ -19514,147 +20453,48 @@
 }
 
+#endif /* !WOLFSSL_NO_TLS12 */
 
 #ifndef NO_CERTS
-/* Decode the private key - RSA, ECC, or Ed25519 - 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;
-    int      keySz;
-    word32   idx;
-
-    /* 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_PK_CALLBACKS
+    int GetPrivateKeySigSize(WOLFSSL* ssl)
+    {
+        int sigSz = 0;
+
+        if (ssl == NULL)
+            return 0;
+
+        switch (ssl->buffers.keyType) {
 #ifndef NO_RSA
-    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 */
-
-#ifdef HAVE_ECC
-#ifndef NO_RSA
-    FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
-#endif /* !NO_RSA */
-
-    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
-
-    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. */
-        (void)keySz;
-        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
-
-exit_dpk:
-    return ret;
+        #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
+            default:
+                break;
 }
-
-
+        return sigSz;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef WOLFSSL_NO_CLIENT_AUTH
 typedef struct ScvArgs {
     byte*  output; /* not allocated */
@@ -19691,4 +20531,5 @@
 }
 
+/* handle generation of certificate_verify (15) */
 int SendCertificateVerify(WOLFSSL* ssl)
 {
@@ -19702,4 +20543,5 @@
 #endif
 
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
     WOLFSSL_ENTER("SendCertificateVerify");
 
@@ -19731,5 +20573,5 @@
             }
 
-            args->sendSz = MAX_CERT_VERIFY_SZ;
+            args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
             if (IsEncryptionOn(ssl, 1)) {
                 args->sendSz += MAX_MSG_EXTRA;
@@ -19757,8 +20599,22 @@
             }
 
+            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 (args->length <= 0) {
+                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
             }
 
@@ -19849,4 +20705,11 @@
             }
         #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 */
 
             /* Advance state and proceed */
@@ -19865,32 +20728,28 @@
                     ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
                     key,
-            #if defined(HAVE_PK_CALLBACKS)
-                    ssl->buffers.key->buffer,
-                    ssl->buffers.key->length,
-                    ssl->EccSignCtx
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
             #else
-                    NULL, 0, NULL
+                    NULL
             #endif
                 );
             }
         #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
+        #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->buffers.digest.buffer, ssl->buffers.digest.length,
+                    ssl->hsHashes->messages, ssl->hsHashes->length,
                     ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
                     key,
-            #if defined(HAVE_PK_CALLBACKS)
-                    ssl->buffers.key->buffer,
-                    ssl->buffers.key->length,
-                    ssl->Ed25519SignCtx
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
             #else
-                    NULL, 0, NULL
+                    NULL
             #endif
                 );
             }
-        #endif /* HAVE_ECC */
+        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
         #ifndef NO_RSA
             if (ssl->hsType == DYNAMIC_TYPE_RSA) {
@@ -19904,10 +20763,5 @@
                     args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz,
                     args->sigAlgo, ssl->suites->hashAlgo, key,
-                    ssl->buffers.key->buffer, ssl->buffers.key->length,
-                #ifdef HAVE_PK_CALLBACKS
-                    ssl->RsaSignCtx
-                #else
-                    NULL
-                #endif
+                    ssl->buffers.key
                 );
             }
@@ -19938,5 +20792,5 @@
             }
         #endif /* HAVE_ECC */
-        #ifdef HAVE_ECC
+        #ifdef HAVE_ED25519
             if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
                 args->length = (word16)ssl->buffers.sig.length;
@@ -19946,5 +20800,5 @@
                         ssl->buffers.sig.buffer, ssl->buffers.sig.length);
             }
-        #endif /* HAVE_ECC */
+        #endif /* HAVE_ED25519 */
         #ifndef NO_RSA
             if (ssl->hsType == DYNAMIC_TYPE_RSA) {
@@ -19965,5 +20819,6 @@
                     args->verifySig, args->sigSz,
                     ssl->buffers.sig.buffer, ssl->buffers.sig.length,
-                    args->sigAlgo, ssl->suites->hashAlgo, key
+                    args->sigAlgo, ssl->suites->hashAlgo, key,
+                    ssl->buffers.key
                 );
             }
@@ -20054,10 +20909,10 @@
 
 
-        #ifdef WOLFSSL_CALLBACKS
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
             if (ssl->hsInfoOn)
-                AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+                AddPacketName(ssl, "CertificateVerify");
             if (ssl->toInfoOn)
-                AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
-                              args->output, args->sendSz, ssl->heap);
+                AddPacketInfo(ssl, "CertificateVerify", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
         #endif
 
@@ -20076,4 +20931,5 @@
 
     WOLFSSL_LEAVE("SendCertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
 
 #ifdef WOLFSSL_ASYNC_CRYPT
@@ -20094,4 +20950,7 @@
     return ret;
 }
+#endif /* WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* WOLFSSL_NO_TLS12 */
 
 #endif /* NO_CERTS */
@@ -20116,5 +20975,5 @@
         ssl->session.isDynamic = 1;
     }
-    ssl->session.ticketLen = length;
+    ssl->session.ticketLen = (word16)length;
 
     if (length > 0) {
@@ -20128,4 +20987,11 @@
          * supercede 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);
@@ -20135,4 +21001,7 @@
 }
 
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of session_ticket (4) */
 static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
     word32 size)
@@ -20181,4 +21050,7 @@
     return 0;
 }
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
 #endif /* HAVE_SESSION_TICKET */
 
@@ -20187,13 +21059,20 @@
 #ifndef NO_WOLFSSL_SERVER
 
+#ifndef WOLFSSL_NO_TLS12
+
+    /* handle generation of server_hello (2) */
     int SendServerHello(WOLFSSL* ssl)
     {
+        int    ret;
         byte              *output;
-        word32             length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        word16 length;
+        word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
         int                sendSz;
-        int                ret;
         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
@@ -20203,5 +21082,7 @@
 
 #ifdef HAVE_TLS_EXTENSIONS
-        length += TLSX_GetResponseSize(ssl, server_hello);
+        ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+        if (ret != 0)
+            return ret;
     #ifdef HAVE_SESSION_TICKET
         if (ssl->options.useTicket) {
@@ -20223,5 +21104,5 @@
 #endif
 
-        /* is the session cahce off at build or runtime */
+        /* is the session cache off at build or runtime */
 #ifdef NO_SESSION_CACHE
         cacheOff = 1;
@@ -20238,12 +21119,4 @@
             sessIdSz = 0;
         }
-
-        /* check for avalaible size */
-        if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
 
         sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
@@ -20258,10 +21131,22 @@
         }
         #endif /* WOLFSSL_DTLS */
+
+        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, length, server_hello, ssl);
 
         /* now write to output */
         /* first version */
-        output[idx++] = ssl->version.major;
-        output[idx++] = ssl->version.minor;
+        output[idx++] = (byte)ssl->version.major;
+        output[idx++] = (byte)ssl->version.minor;
 
         /* then random and session id */
@@ -20278,5 +21163,5 @@
                 XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
                         tls13Downgrade, TLS13_DOWNGRADE_SZ);
-                output[idx + RAN_LEN - 1] = IsAtLeastTLSv1_2(ssl);
+                output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
             }
             else
@@ -20329,5 +21214,11 @@
         /* last, extensions */
 #ifdef HAVE_TLS_EXTENSIONS
-        TLSX_WriteResponse(ssl, output + idx, server_hello);
+        {
+            word16 offset = 0;
+            ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset);
+            if (ret != 0)
+                return ret;
+            idx += offset;
+        }
 #else
 #ifdef HAVE_EXTENDED_MASTER
@@ -20341,44 +21232,69 @@
             /*idx += HELLO_EXT_SZ_SZ;*/
             /* idx is not used after this point. uncomment the line above
-             * if adding any more extentions in the future. */
-        }
-#endif
-#endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                    return ret;
-            }
-
-            if (ssl->options.dtls) {
+             * if adding any more extensions in the future. */
+        }
+#endif
+#endif
+
+        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_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);
-            }
         #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("ServerHello", &ssl->handShakeInfo);
+            AddPacketName(ssl, "ServerHello");
         if (ssl->toInfoOn)
-            AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
-                          ssl->heap);
+            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;
+        }
+
+        if (ssl->options.dtls) {
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+        }
+    #endif
 
         if (ssl->options.groupMessages)
-            return 0;
+            ret = 0;
         else
-            return SendBuffered(ssl);
-    }
-
-
-#ifdef HAVE_ECC
+            ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+        return ret;
+    }
+
+
+#if defined(HAVE_ECC)
 
     static byte SetCurveId(ecc_key* key)
@@ -20439,8 +21355,4 @@
     #endif
     #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
-        #ifdef HAVE_CURVE25519
-            case ECC_X25519_OID:
-                return WOLFSSL_ECC_X25519;
-        #endif
         #ifndef NO_ECC_SECP
             case ECC_SECP384R1_OID:
@@ -20469,12 +21381,13 @@
     }
 
-#endif /* HAVE_ECC */
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
 
     typedef struct SskeArgs {
         byte*  output; /* not allocated */
-    #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA))
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
         byte*  sigDataBuf;
     #endif
-    #if defined(HAVE_ECC)
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
         byte*  exportBuf;
     #endif
@@ -20482,12 +21395,14 @@
         byte*  verifySig;
     #endif
+        byte*  input;
         word32 idx;
         word32 tmpSigSz;
         word32 length;
         word32 sigSz;
-    #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA))
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
         word32 sigDataSz;
     #endif
-    #if defined(HAVE_ECC)
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
         word32 exportSz;
     #endif
@@ -20496,4 +21411,5 @@
     #endif
         int    sendSz;
+        int    inputSz;
     } SskeArgs;
 
@@ -20504,5 +21420,5 @@
         (void)ssl;
 
-    #if defined(HAVE_ECC)
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
         if (args->exportBuf) {
             XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
@@ -20510,5 +21426,6 @@
         }
     #endif
-    #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA))
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
         if (args->sigDataBuf) {
             XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
@@ -20525,4 +21442,5 @@
     }
 
+    /* handle generation of server_key_exchange (12) */
     int SendServerKeyExchange(WOLFSSL* ssl)
     {
@@ -20536,4 +21454,5 @@
     #endif
 
+        WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
         WOLFSSL_ENTER("SendServerKeyExchange");
 
@@ -20570,5 +21489,6 @@
                 switch(ssl->specs.kea)
                 {
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -20576,6 +21496,6 @@
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
-                #ifdef HAVE_ECC
+                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC)
                     case ecc_diffie_hellman_kea:
                     {
@@ -20583,10 +21503,4 @@
                             WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange");
                             ERROR_OUT(0, exit_sske);
-                        }
-
-                        /* make sure private key exists */
-                        if (ssl->buffers.key == NULL ||
-                                            ssl->buffers.key->buffer == NULL) {
-                            ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
                         }
 
@@ -20650,4 +21564,25 @@
                         }
 
+                        #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
+                        {
                         ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
                             ssl->buffers.serverDH_P.buffer,
@@ -20658,4 +21593,5 @@
                             goto exit_sske;
                         }
+                        }
 
                         ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
@@ -20667,8 +21603,9 @@
                     }
                 #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                         /* Fall through to create temp ECC key */
-                #endif /* HAVE_ECC && !NO_PSK */
+                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
                 #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
@@ -20709,6 +21646,4 @@
 
                         if (ssl->eccTempKeyPresent == 0) {
-                            /* TODO: Need to first do wc_EccPrivateKeyDecode,
-                                then we know curve dp */
                             ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
                             if (ret == 0 || ret == WC_PENDING_E) {
@@ -20737,5 +21672,6 @@
             case TLS_ASYNC_BUILD:
             {
-            #if (!defined(NO_DH) && !defined(NO_RSA)) || defined(HAVE_ECC)
+            #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
+                                                       defined(HAVE_CURVE25519))
                 word32 preSigSz, preSigIdx;
             #endif
@@ -20773,4 +21709,9 @@
                         }
                     #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
                         /* check for available size */
                         if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
@@ -20831,4 +21772,8 @@
                         }
                     #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
 
                         /* check for available size */
@@ -20881,5 +21826,6 @@
                     }
                 #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -20933,4 +21879,9 @@
                         }
                     #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
                         /* check for available size */
                         if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
@@ -20958,6 +21909,8 @@
                     #endif
                         {
+                    #ifdef HAVE_ECC
                             args->output[args->idx++] =
                                                     SetCurveId(ssl->eccTempKey);
+                    #endif
                         }
                         args->output[args->idx++] = (byte)args->exportSz;
@@ -20966,6 +21919,6 @@
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
-                #ifdef HAVE_ECC
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
                     {
@@ -20995,8 +21948,10 @@
                     #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;
@@ -21005,6 +21960,18 @@
                         preSigIdx = args->idx;
 
-                        switch(ssl->suites->sigAlgo)
-                        {
+                        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 {
+                            switch(ssl->suites->sigAlgo) {
                         #ifndef NO_RSA
                         #ifdef WC_RSA_PSS
@@ -21043,4 +22010,5 @@
                             }
                         #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
                             case ecc_dsa_sa_algo:
                             {
@@ -21069,9 +22037,9 @@
                                         ssl->options.minEccKeySz) {
                                     WOLFSSL_MSG("ECC key size too small");
-                                    ret = ECC_KEY_SIZE_E;
-                                    goto exit_sske;
+                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
                                 }
                                 break;
                             }
+                        #endif
                         #ifdef HAVE_ED25519
                             case ed25519_sa_algo:
@@ -21093,4 +22061,5 @@
                                     goto exit_sske;
                                 }
+
                                 /* worst case estimate */
                                 args->tmpSigSz = ED25519_SIG_SIZE;
@@ -21100,13 +22069,13 @@
                                         ssl->options.minEccKeySz) {
                                     WOLFSSL_MSG("Ed25519 key size too small");
-                                    ret = ECC_KEY_SIZE_E;
-                                    goto exit_sske;
+                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
                                 }
                                 break;
                             }
-                        #endif
+                        #endif /* HAVE_ED25519 */
                             default:
                                 ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
                         } /* switch(ssl->specs.sig_algo) */
+                        }
 
                         /* sig length */
@@ -21131,4 +22100,8 @@
                         }
                     #endif
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
                         /* check for available size */
                         if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
@@ -21152,6 +22125,8 @@
                     #endif
                         {
+                    #ifdef HAVE_ECC
                             args->output[args->idx++] =
                                                     SetCurveId(ssl->eccTempKey);
+                    #endif
                         }
                         args->output[args->idx++] = (byte)args->exportSz;
@@ -21270,15 +22245,19 @@
                         #endif
                         #endif /* !NO_RSA */
-                        #ifdef HAVE_ED25519
-                            case ed25519_sa_algo:
-                        #endif
                             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 */
                         } /* switch(ssl->specs.sig_algo) */
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
                 #if !defined(NO_DH) && !defined(NO_RSA)
                     case diffie_hellman_kea:
@@ -21296,12 +22275,20 @@
 
                         if (!ssl->options.usingAnon_cipher) {
-                            word32   i = 0;
                             int      keySz;
 
-                            /* make sure private key exists */
-                            if (ssl->buffers.key == NULL ||
-                                            ssl->buffers.key->buffer == NULL) {
+                            /* 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
+                            {
+                                word32 i = 0;
 
                             ssl->hsType = DYNAMIC_TYPE_RSA;
@@ -21311,17 +22298,18 @@
                             }
 
-                            /* sig length */
-                            args->length += LENGTH_SZ;
-
                             ret = wc_RsaPrivateKeyDecode(
                                 ssl->buffers.key->buffer, &i,
-                                (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+                                    (RsaKey*)ssl->hsKey,
+                                    ssl->buffers.key->length);
                             if (ret != 0) {
                                 goto exit_sske;
                             }
                             keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
-                            if (keySz < 0) { /* test if keySz has error */
+                            }
+
+                            if (keySz <= 0) { /* test if keySz has error */
                                 ERROR_OUT(keySz, exit_sske);
                             }
+
                             args->tmpSigSz = (word32)keySz;
                             args->length += args->tmpSigSz;
@@ -21351,4 +22339,8 @@
                         }
                     #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
 
                         /* check for available size */
@@ -21526,11 +22518,12 @@
                     }
                 #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
-                #ifdef HAVE_ECC
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
                     {
@@ -21553,8 +22546,22 @@
                                     ssl->suites->sigAlgo, ssl->suites->hashAlgo,
                                     key,
-                                    ssl->buffers.key->buffer,
-                                    ssl->buffers.key->length,
+                                    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->RsaSignCtx
+                                    ssl->buffers.key
                             #else
                                     NULL
@@ -21563,25 +22570,5 @@
                                 break;
                             }
-                        #endif /* !NO_RSA */
-                            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,
-                            #if defined(HAVE_PK_CALLBACKS)
-                                    ssl->buffers.key->buffer,
-                                    ssl->buffers.key->length,
-                                    ssl->EccSignCtx
-                            #else
-                                    NULL, 0, NULL
-                            #endif
-                                );
-                                break;
-                            }
+                        #endif /* HAVE_ECC */
                         #ifdef HAVE_ED25519
                             case ed25519_sa_algo:
@@ -21594,10 +22581,8 @@
                                     &args->sigSz,
                                     key,
-                            #if defined(HAVE_PK_CALLBACKS)
-                                    ssl->buffers.key->buffer,
-                                    ssl->buffers.key->length,
-                                    ssl->Ed25519SignCtx
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
                             #else
-                                    NULL, 0, NULL
+                                    NULL
                             #endif
                                 );
@@ -21608,5 +22593,5 @@
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
                 #if !defined(NO_DH) && !defined(NO_RSA)
                     case diffie_hellman_kea:
@@ -21634,11 +22619,5 @@
                                     ssl->suites->sigAlgo, ssl->suites->hashAlgo,
                                     key,
-                                    ssl->buffers.key->buffer,
-                                    ssl->buffers.key->length,
-                                #ifdef HAVE_PK_CALLBACKS
-                                    ssl->RsaSignCtx
-                                #else
-                                    NULL
-                                #endif
+                                    ssl->buffers.key
                                 );
                                 break;
@@ -21680,5 +22659,6 @@
                     }
                 #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -21686,6 +22666,6 @@
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
-                #ifdef HAVE_ECC
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
                     {
@@ -21720,5 +22700,5 @@
                                     ssl->buffers.sig.length,
                                     ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key
+                                    key, ssl->buffers.key
                                 );
                                 break;
@@ -21726,4 +22706,7 @@
                         #endif
                             case ecc_dsa_sa_algo:
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                        #endif
                             {
                                 /* Now that we know the real sig size, write it. */
@@ -21736,17 +22719,4 @@
                                 break;
                             }
-                        #ifdef HAVE_ED25519
-                            case ed25519_sa_algo:
-                            {
-                                /* 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;
-                            }
-                        #endif
                             default:
                                 ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
@@ -21754,5 +22724,5 @@
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
                 #if !defined(NO_DH) && !defined(NO_RSA)
                     case diffie_hellman_kea:
@@ -21792,5 +22762,5 @@
                                     ssl->buffers.sig.length,
                                     ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key
+                                    key, ssl->buffers.key
                                 );
                                 break;
@@ -21838,5 +22808,5 @@
             #endif
 
-            #if defined(HAVE_ECC)
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                 if (ssl->specs.kea == ecdhe_psk_kea ||
                     ssl->specs.kea == ecc_diffie_hellman_kea) {
@@ -21850,9 +22820,33 @@
                     }
                 }
-            #endif /* HAVE_ECC */
-
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+                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);
+                    }
+
+                    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;
+                    }
+                }
+                else {
             #ifdef WOLFSSL_DTLS
                 if (IsDtlsNotSctpMode(ssl)) {
-                    if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
+                        if ((ret = DtlsMsgPoolSave(ssl,
+                                            args->output, args->sendSz)) != 0) {
                         goto exit_sske;
                     }
@@ -21867,12 +22861,13 @@
                     goto exit_sske;
                 }
-
-            #ifdef WOLFSSL_CALLBACKS
+                }
+
+            #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
                 if (ssl->hsInfoOn) {
-                    AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+                    AddPacketName(ssl, "ServerKeyExchange");
                 }
                 if (ssl->toInfoOn) {
-                    AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
-                        args->output, args->sendSz, ssl->heap);
+                    AddPacketInfo(ssl, "ServerKeyExchange", handshake,
+                        args->output, args->sendSz, WRITE_PROTO, ssl->heap);
                 }
             #endif
@@ -21900,4 +22895,5 @@
 
         WOLFSSL_LEAVE("SendServerKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
 
     #ifdef WOLFSSL_ASYNC_CRYPT
@@ -21936,4 +22932,6 @@
 
 #endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
 
     /* Make sure server cert/key are valid for this suite, true on success */
@@ -22019,5 +23017,6 @@
         }
 
-#ifdef HAVE_SUPPORTED_CURVES
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                  defined(HAVE_SUPPORTED_CURVES)
         if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
             WOLFSSL_MSG("Don't have matching curves");
@@ -22035,5 +23034,6 @@
             }
             else {
-                WOLFSSL_MSG("Version of SSL connection does not support TLS_QSH");
+                WOLFSSL_MSG("Version of SSL connection does not support "
+                            "TLS_QSH");
             }
             return 0;
@@ -22047,7 +23047,12 @@
             int ret = TLSX_KeyShare_Establish(ssl);
             if (ret == KEY_SHARE_ERROR)
-                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST;
+                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
             else if (ret != 0)
                 return 0;
+        }
+        else if (first == TLS13_BYTE) {
+            /* Can't negotiate TLS 1.3 cipher suites with lower protocol
+             * version. */
+            return 0;
         }
 #endif
@@ -22133,4 +23138,5 @@
         ProtocolVersion pv;
         Suites          clSuites;
+        int ret = -1;
 
         (void)inSz;
@@ -22138,5 +23144,5 @@
 #ifdef WOLFSSL_CALLBACKS
         if (ssl->hsInfoOn)
-            AddPacketName("ClientHello", &ssl->handShakeInfo);
+            AddPacketName(ssl, "ClientHello");
         if (ssl->toInfoOn)
             AddLateName("ClientHello", &ssl->timeoutInfo);
@@ -22172,4 +23178,6 @@
             byte haveRSA = 0;
             byte havePSK = 0;
+            int  keySz   = 0;
+
             if (!ssl->options.downgrade) {
                 WOLFSSL_MSG("Client trying to connect with lesser version");
@@ -22207,6 +23215,9 @@
             havePSK = ssl->options.havePSK;
 #endif
-
-            InitSuites(ssl->suites, ssl->version, ssl->keySz, 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,
@@ -22266,4 +23277,5 @@
 
         ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+        ssl->cbmode = SSL_CB_MODE_WRITE;
         *inOutIdx = idx;
 
@@ -22271,5 +23283,4 @@
         /* DoClientHello uses same resume code */
         if (ssl->options.resuming) {  /* let's try */
-            int ret = -1;
             WOLFSSL_SESSION* session = GetSession(ssl,
                                                   ssl->arrays->masterSecret, 1);
@@ -22313,10 +23324,85 @@
         }
 
-        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 = GetSession(ssl,
+                                                  ssl->arrays->masterSecret, 1);
+
+        (void)bogusID;
+
+        #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");
+                return EXT_MASTER_SECRET_NEEDED_E;
+            }
+        #ifdef HAVE_EXT_CACHE
+            wolfSSL_SESSION_free(session);
+        #endif
+        }
+        else {
+        #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;
+
+            #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)
@@ -22328,4 +23414,5 @@
         word32          i = *inOutIdx;
         word32          begin = i;
+        int             ret = 0;
 #ifdef WOLFSSL_DTLS
         Hmac            cookieHmac;
@@ -22338,9 +23425,11 @@
 #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)
@@ -22352,5 +23441,4 @@
 #ifdef WOLFSSL_DTLS
         if (IsDtlsNotSctpMode(ssl)) {
-            int ret;
             #if defined(NO_SHA) && defined(NO_SHA256)
                 #error "DTLS needs either SHA or SHA-256"
@@ -22379,4 +23467,8 @@
         i += OPAQUE16_LEN;
 
+        /* 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
@@ -22499,5 +23591,5 @@
 #ifdef WOLFSSL_DTLS
         if (IsDtlsNotSctpMode(ssl)) {
-            int ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
+            ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
             if (ret != 0) return ret;
         }
@@ -22532,5 +23624,5 @@
 #ifdef WOLFSSL_DTLS
             if (IsDtlsNotSctpMode(ssl)) {
-                int ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+                ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
                 if (ret != 0) return ret;
             }
@@ -22588,9 +23680,8 @@
         /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
         if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
-            int ret = 0;
-
-            ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
+            ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions);
             if (ret != WOLFSSL_SUCCESS)
                 return ret;
+            ssl->secure_renegotiation->enabled = 1;
         }
 #endif /* HAVE_SERVER_RENEGOTIATION_INFO */
@@ -22598,5 +23689,5 @@
 #ifdef WOLFSSL_DTLS
         if (IsDtlsNotSctpMode(ssl)) {
-            int ret = wc_HmacUpdate(&cookieHmac,
+            ret = wc_HmacUpdate(&cookieHmac,
                                     input + i - OPAQUE16_LEN,
                                     clSuites.suiteSz + OPAQUE16_LEN);
@@ -22621,5 +23712,4 @@
         if (IsDtlsNotSctpMode(ssl)) {
             byte newCookie[MAX_COOKIE_LEN];
-            int ret;
 
             ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
@@ -22658,5 +23748,5 @@
 
         {
-            /* copmression match types */
+            /* compression match types */
             int matchNo = 0;
             int matchZlib = 0;
@@ -22694,9 +23784,9 @@
             QSH_Init(ssl);
         #endif
-            if (TLSX_SupportExtensions(ssl)) {
-                int ret = 0;
+            if (TLSX_SupportExtensions(ssl))
 #else
-            if (IsAtLeastTLSv1_2(ssl)) {
-#endif
+            if (IsAtLeastTLSv1_2(ssl))
+#endif
+            {
                 /* Process the hello extension. Skip unsupported. */
                 word16 totalExtSz;
@@ -22730,9 +23820,9 @@
                 }
     #endif
-#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    #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 /*HAVE_STUNNEL*/
+    #endif
 
                 i += totalExtSz;
@@ -22753,16 +23843,23 @@
 
                     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;
-
-                        if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX)
-                            clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX;
+                                                      clSuites.hashSigAlgoSz);
+
+                        i += hashSigAlgoSz;
                     }
 #ifdef HAVE_EXTENDED_MASTER
@@ -22787,73 +23884,31 @@
         /* ProcessOld uses same resume code */
         if (ssl->options.resuming) {
-            int ret = -1;
-            WOLFSSL_SESSION* 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;
+            ret = HandleTlsResumption(ssl, bogusID, &clSuites);
+            if (ret != 0)
+                return ret;
+            if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
+                WOLFSSL_LEAVE("DoClientHello", ret);
+                WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+                return ret;
+            }
                 }
-            #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");
-                    return EXT_MASTER_SECRET_NEEDED_E;
-                }
-#ifdef HAVE_EXT_CACHE
-                wolfSSL_SESSION_free(session);
-#endif
-            }
-            else {
-#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;
-
-                #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);
+        ret = MatchSuite(ssl, &clSuites);
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
+            IsEncryptionOn(ssl, 0)) {
+        ssl->secure_renegotiation->startScr = 1;
+    }
                 #endif
-                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+        WOLFSSL_LEAVE("DoClientHello", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
 
                 return ret;
             }
-        }
-        return MatchSuite(ssl, &clSuites);
-    }
-
-
-#if !defined(NO_RSA) || defined(HAVE_ECC)
+
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
 
     typedef struct DcvArgs {
@@ -22876,4 +23931,5 @@
     }
 
+    /* handle processing of certificate_verify (15) */
     static int DoCertificateVerify(WOLFSSL* ssl, byte* input,
                                 word32* inOutIdx, word32 size)
@@ -22888,4 +23944,5 @@
     #endif
 
+        WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
         WOLFSSL_ENTER("DoCertificateVerify");
 
@@ -22919,5 +23976,5 @@
             #ifdef WOLFSSL_CALLBACKS
                 if (ssl->hsInfoOn)
-                    AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+                    AddPacketName(ssl, "CertificateVerify");
                 if (ssl->toInfoOn)
                     AddLateName("CertificateVerify", &ssl->timeoutInfo);
@@ -22948,8 +24005,8 @@
                     args->sigAlgo = ecc_dsa_sa_algo;
             #endif
-            #ifdef HAVE_ED25519
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
                 else if (ssl->peerEd25519KeyPresent)
                     args->sigAlgo = ed25519_sa_algo;
-            #endif
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
 
                 if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
@@ -22992,5 +24049,5 @@
                 }
             #endif /* HAVE_ECC */
-            #ifdef HAVE_ED25519
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
                 if (ssl->peerEd25519KeyPresent) {
                     WOLFSSL_MSG("Doing ED25519 peer cert verify");
@@ -23001,5 +24058,5 @@
                     }
                 }
-            #endif /* HAVE_ED25519 */
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
 
                 /* Advance state and proceed */
@@ -23021,9 +24078,7 @@
                         ssl->peerRsaKey,
                     #ifdef HAVE_PK_CALLBACKS
-                        ssl->buffers.peerRsaKey.buffer,
-                        ssl->buffers.peerRsaKey.length,
-                        ssl->RsaVerifyCtx
+                        &ssl->buffers.peerRsaKey
                     #else
-                        NULL, 0, NULL
+                        NULL
                     #endif
                     );
@@ -23048,13 +24103,27 @@
                         ssl->peerEccDsaKey,
                     #ifdef HAVE_PK_CALLBACKS
-                        ssl->buffers.peerEccDsaKey.buffer,
-                        ssl->buffers.peerEccDsaKey.length,
-                        ssl->EccVerifyCtx
+                        &ssl->buffers.peerEccDsaKey
                     #else
-                        NULL, 0, NULL
+                        NULL
                     #endif
                     );
                 }
             #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
+                    );
+                }
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
 
                 /* Check for error */
@@ -23083,5 +24152,5 @@
                                              HashAlgoToType(args->hashAlgo));
                             if (ret != 0)
-                                return ret;
+                                goto exit_dcv;
                         }
                         else
@@ -23141,4 +24210,8 @@
             case TLS_ASYNC_FINALIZE:
             {
+                if (IsEncryptionOn(ssl, 0)) {
+                    args->idx += ssl->keys.padSz;
+                }
+
                 ssl->options.havePeerVerify = 1;
 
@@ -23162,9 +24235,10 @@
 
         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 recevied so it can process again */
+            /* Mark message as not received so it can process again */
             ssl->msgsReceived.got_certificate_verify = 0;
 
@@ -23172,5 +24246,9 @@
         }
     #endif /* WOLFSSL_ASYNC_CRYPT */
-
+    #ifdef OPENSSL_EXTRA
+        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;
@@ -23184,6 +24262,7 @@
     }
 
-#endif /* !NO_RSA || HAVE_ECC */
-
+#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
+
+    /* handle generation of server_hello_done (14) */
     int SendServerHelloDone(WOLFSSL* ssl)
     {
@@ -23192,4 +24271,7 @@
         int   ret;
 
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND);
+        WOLFSSL_ENTER("SendServerHelloDone");
+
     #ifdef WOLFSSL_DTLS
         if (ssl->options.dtls)
@@ -23197,4 +24279,7 @@
     #endif
 
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
         /* check for available size */
         if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
@@ -23207,24 +24292,39 @@
         AddHeaders(output, 0, server_hello_done, 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, 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 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);
+            AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
     #endif
         ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
@@ -23232,7 +24332,13 @@
         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
@@ -23251,5 +24357,8 @@
 #ifdef WOLFSSL_TLS13
         word32          ageAdd;                /* Obfuscation of age */
-        byte            namedGroup;            /* Named group used */
+        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 */
@@ -23307,4 +24416,8 @@
             /* 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
         }
@@ -23375,4 +24488,7 @@
         word16          inLen;
 
+        WOLFSSL_START(WC_FUNC_TICKET_DO);
+        WOLFSSL_ENTER("DoClientTicket");
+
         if (len > SESSION_TICKET_LEN ||
              len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
@@ -23401,4 +24517,21 @@
         /* get master secret */
         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);
@@ -23419,8 +24552,15 @@
                 /* 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;
@@ -23437,4 +24577,7 @@
         word32             idx    = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
 
+        WOLFSSL_START(WC_FUNC_TICKET_SEND);
+        WOLFSSL_ENTER("SendTicket");
+
         if (ssl->options.createTicket) {
             ret = CreateTicket(ssl);
@@ -23445,10 +24588,14 @@
         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
-        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)
@@ -23471,6 +24618,23 @@
         /* 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) {
@@ -23481,16 +24645,81 @@
         }
         #endif
-
         ret = HashOutput(ssl, output, sendSz, 0);
-        if (ret != 0) return ret;
+            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
+    /* handle generation of DTLS hello_verify_request (3) */
     static int SendHelloVerifyRequest(WOLFSSL* ssl,
                                       const byte* cookie, byte cookieSz)
@@ -23530,10 +24759,10 @@
         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
 
@@ -23550,4 +24779,7 @@
         word32 begin;
         word32 sigSz;
+    #ifndef NO_RSA
+        int    lastErr;
+    #endif
     } DckeArgs;
 
@@ -23560,4 +24792,5 @@
     }
 
+    /* handle processing client_key_exchange (16) */
     static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
                                                                     word32 size)
@@ -23572,4 +24805,8 @@
     #endif
 
+        (void)size;
+        (void)input;
+
+        WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
         WOLFSSL_ENTER("DoClientKeyExchange");
 
@@ -23630,7 +24867,7 @@
             #endif /* !NO_CERTS */
 
-            #ifdef WOLFSSL_CALLBACKS
+            #if defined(WOLFSSL_CALLBACKS)
                 if (ssl->hsInfoOn) {
-                    AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+                    AddPacketName(ssl, "ClientKeyExchange");
                 }
                 if (ssl->toInfoOn) {
@@ -23639,13 +24876,17 @@
             #endif
 
+                if (ssl->arrays->preMasterSecret == NULL) {
+                    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:
                     {
-                        /* make sure private key exists */
-                        if (ssl->buffers.key == NULL ||
-                                            ssl->buffers.key->buffer == NULL) {
-                            ERROR_OUT(NO_PRIVATE_KEY, exit_dcke);
-                        }
                         break;
                     } /* rsa_kea */
@@ -23673,10 +24914,10 @@
                     }
                 #endif /* HAVE_NTRU */
-                #ifdef HAVE_ECC
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
                     {
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
                 #ifndef NO_DH
                     case diffie_hellman_kea:
@@ -23696,5 +24937,6 @@
                     }
                 #endif /* !NO_DH && !NO_PSK */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -23706,5 +24948,5 @@
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
                     default:
                         WOLFSSL_MSG("Bad kea type");
@@ -23773,4 +25015,12 @@
                             WOLFSSL_MSG("RSA message too big");
                             ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        /* 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;
                         }
 
@@ -24087,5 +25337,6 @@
                     }
                 #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -24225,4 +25476,5 @@
                     {
                         RsaKey* key = (RsaKey*)ssl->hsKey;
+
                         ret = RsaDec(ssl,
                             input + args->idx,
@@ -24231,12 +25483,24 @@
                             &args->sigSz,
                             key,
-                        #if defined(HAVE_PK_CALLBACKS)
-                            ssl->buffers.key->buffer,
-                            ssl->buffers.key->length,
-                            ssl->RsaDecCtx
+                        #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.key
                         #else
-                            NULL, 0, NULL
+                            NULL
                         #endif
                         );
+
+                        /*  Errors that can occur here that should be
+                         *  indistinguishable:
+                         *       RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
+                         */
+                        if (ret < 0 && ret != BAD_FUNC_ARG) {
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret == WC_PENDING_E)
+                                goto exit_dcke;
+                        #endif
+                            /* store error code for handling below */
+                            args->lastErr = ret;
+                            ret = 0;
+                        }
                         break;
                     } /* rsa_kea */
@@ -24258,4 +25522,5 @@
                     {
                         void* private_key = ssl->eccTempKey;
+                        (void)private_key;
 
                     #ifdef HAVE_CURVE25519
@@ -24267,10 +25532,5 @@
                                 ssl->arrays->preMasterSecret,
                                 &ssl->arrays->preMasterSz,
-                                WOLFSSL_SERVER_END,
-                            #ifdef HAVE_PK_CALLBACKS
-                                ssl->EccSharedSecretCtx
-                            #else
-                                NULL
-                            #endif
+                                WOLFSSL_SERVER_END
                             );
                             break;
@@ -24288,11 +25548,14 @@
                             ssl->arrays->preMasterSecret,
                             &ssl->arrays->preMasterSz,
-                            WOLFSSL_SERVER_END,
-                        #ifdef HAVE_PK_CALLBACKS
-                            ssl->EccSharedSecretCtx
-                        #else
-                            NULL
-                        #endif
+                            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;
@@ -24325,5 +25588,6 @@
                     }
                 #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -24336,11 +25600,14 @@
                                 ssl->arrays->preMasterSecret + OPAQUE16_LEN,
                                 &args->sigSz,
-                                WOLFSSL_SERVER_END,
-                            #ifdef HAVE_PK_CALLBACKS
-                                ssl->EccSharedSecretCtx
-                            #else
-                                NULL
-                            #endif
+                                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;
                         }
@@ -24352,11 +25619,15 @@
                             ssl->arrays->preMasterSecret + OPAQUE16_LEN,
                             &args->sigSz,
-                            WOLFSSL_SERVER_END,
-                        #ifdef HAVE_PK_CALLBACKS
-                            ssl->EccSharedSecretCtx
-                        #else
-                            NULL
-                        #endif
+                            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;
                     }
@@ -24385,14 +25656,36 @@
                         args->idx += args->length;
 
-                        if (args->sigSz == SECRET_LEN && args->output != NULL) {
-                            XMEMCPY(ssl->arrays->preMasterSecret, args->output, SECRET_LEN);
-                            if (ssl->arrays->preMasterSecret[0] != ssl->chVersion.major ||
-                                ssl->arrays->preMasterSecret[1] != ssl->chVersion.minor) {
-                                ERROR_OUT(PMS_VERSION_ERROR, exit_dcke);
-                            }
+                    #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");
                         }
-                        else {
-                            ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke);
                         }
+                    #endif
+
+                        /* RFC5246 7.4.7.1:
+                         * Treat incorrectly formatted message blocks and/or
+                         * mismatched version numbers in a manner
+                         * indistinguishable from correctly formatted RSA blocks
+                         */
+
+                        args->lastErr = 0; /* reset */
+
+                        /* build PreMasterSecret */
+                        ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                        ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+                        if (args->output != NULL) {
+                            XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ],
+                                    &args->output[VERSION_SZ],
+                                    SECRET_LEN - VERSION_SZ);
+                        }
+                        /* 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 */
@@ -24410,5 +25703,5 @@
                     }
                 #endif /* HAVE_NTRU */
-                #ifdef HAVE_ECC
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
                     case ecc_diffie_hellman_kea:
                     {
@@ -24417,5 +25710,5 @@
                         break;
                     }
-                #endif /* HAVE_ECC */
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
                 #ifndef NO_DH
                     case diffie_hellman_kea:
@@ -24457,5 +25750,6 @@
                     }
                 #endif /* !NO_DH && !NO_PSK */
-                #if defined(HAVE_ECC) && !defined(NO_PSK)
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
                     case ecdhe_psk_kea:
                     {
@@ -24490,5 +25784,5 @@
                         break;
                     }
-                #endif /* HAVE_ECC && !NO_PSK */
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
                     default:
                         ret = BAD_KEA_TYPE_E;
@@ -24507,4 +25801,8 @@
             case TLS_ASYNC_FINALIZE:
             {
+                if (IsEncryptionOn(ssl, 0)) {
+                    args->idx += ssl->keys.padSz;
+                }
+
             #ifdef HAVE_QSH
                 word16 name;
@@ -24564,9 +25862,10 @@
 
         WOLFSSL_LEAVE("DoClientKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
 
     #ifdef WOLFSSL_ASYNC_CRYPT
         /* Handle async operation */
         if (ret == WC_PENDING_E) {
-            /* Mark message as not recevied so it can process again */
+            /* Mark message as not received so it can process again */
             ssl->msgsReceived.got_client_key_exchange = 0;
 
@@ -24576,5 +25875,7 @@
 
         /* Cleanup PMS */
+        if (ssl->arrays->preMasterSecret != NULL) {
         ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+        }
         ssl->arrays->preMasterSz = 0;
 
@@ -24586,6 +25887,8 @@
     }
 
-
-#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY)
     int SNI_Callback(WOLFSSL* ssl)
     {
@@ -24603,5 +25906,6 @@
         return 0;
     }
-#endif /* HAVE_STUNNEL || WOLGSSL_NGINX */
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
 #endif /* NO_WOLFSSL_SERVER */
 
@@ -24699,4 +26003,28 @@
 
 
+/* 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) && (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
 
