Index: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/tls13.c
===================================================================
--- azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/src/tls13.c	(revision 457)
+++ azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/tls13.c	(revision 464)
@@ -30,7 +30,6 @@
  * NO_PSK
  *    Do not enable Pre-Shared Keys.
- * TLS13_SUPPORTS_EXPORTERS
- *    Guard to compile out any code for exporter keys.
- *    Feature not supported yet.
+ * HAVE_KEYING_MATERIAL
+ *    Enables exporting keying material based on section 7.5 of RFC 8446.
  * WOLFSSL_ASYNC_CRYPT
  *    Enables the use of asynchronous cryptographic operations.
@@ -56,10 +55,4 @@
  * WOLFSSL_TLS13
  *    Enable TLS 1.3 protocol implementation.
- * WOLFSSL_TLS13_DRAFT_18
- *    Conform with Draft 18 of the TLS v1.3 specification.
- * WOLFSSL_TLS13_DRAFT_22
- *    Conform with Draft 22 of the TLS v1.3 specification.
- * WOLFSSL_TLS13_DRAFT_23
- *    Conform with Draft 23 of the TLS v1.3 specification.
  * WOLFSSL_TLS13_MIDDLEBOX_COMPAT
  *    Enable middlebox compatibility in the TLS 1.3 handshake.
@@ -119,5 +112,9 @@
 
 #ifndef HAVE_HKDF
-    #error The build option HAVE_HKDF is required for TLS 1.3
+    #ifndef _MSC_VER
+        #error "The build option HAVE_HKDF is required for TLS 1.3"
+    #else
+        #pragma message("error: The build option HAVE_HKDF is required for TLS 1.3")
+    #endif
 #endif
 
@@ -264,18 +261,9 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* Size of the TLS v1.3 label use when deriving keys. */
-#define TLS13_PROTOCOL_LABEL_SZ    9
-/* The protocol label for TLS v1.3. */
-static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, ";
-#else
 /* Size of the TLS v1.3 label use when deriving keys. */
 #define TLS13_PROTOCOL_LABEL_SZ    6
 /* The protocol label for TLS v1.3. */
 static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
-#endif
-
-#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \
-                                        !defined(NO_PSK)
+
 /* Derive a key from a message.
  *
@@ -370,5 +358,4 @@
                              hash, hashSz, digestAlg);
 }
-#endif
 
 /* Derive a key.
@@ -442,11 +429,4 @@
 
 #ifndef NO_PSK
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the binder key label. */
-#define BINDER_KEY_LABEL_SZ         23
-/* The binder key label. */
-static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
-    "external psk binder key";
-#else
 /* The length of the binder key label. */
 #define BINDER_KEY_LABEL_SZ         10
@@ -454,5 +434,5 @@
 static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
     "ext binder";
-#endif
+
 /* Derive the binder key.
  *
@@ -464,4 +444,7 @@
 {
     WOLFSSL_MSG("Derive Binder Key");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
                         binderKeyLabel, BINDER_KEY_LABEL_SZ,
@@ -471,11 +454,5 @@
 
 #ifdef HAVE_SESSION_TICKET
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the binder key resume label. */
-#define BINDER_KEY_RESUME_LABEL_SZ  25
-/* The binder key resume label. */
-static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
-    "resumption psk binder key";
-#else
+
 /* The length of the binder key resume label. */
 #define BINDER_KEY_RESUME_LABEL_SZ  10
@@ -483,5 +460,5 @@
 static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
     "res binder";
-#endif
+
 /* Derive the binder resumption key.
  *
@@ -493,4 +470,7 @@
 {
     WOLFSSL_MSG("Derive Binder Key - Resumption");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
                         binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ,
@@ -500,11 +480,5 @@
 
 #ifdef WOLFSSL_EARLY_DATA
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the early traffic label. */
-#define EARLY_TRAFFIC_LABEL_SZ      27
-/* The early traffic label. */
-static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
-    "client early traffic secret";
-#else
+
 /* The length of the early traffic label. */
 #define EARLY_TRAFFIC_LABEL_SZ      11
@@ -512,5 +486,5 @@
 static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
     "c e traffic";
-#endif
+
 /* Derive the early traffic key.
  *
@@ -523,4 +497,7 @@
     int ret;
     WOLFSSL_MSG("Derive Early Traffic Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->secret,
                     earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ,
@@ -538,12 +515,5 @@
 }
 
-#ifdef TLS13_SUPPORTS_EXPORTERS
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the early exporter label. */
-#define EARLY_EXPORTER_LABEL_SZ     28
-/* The early exporter label. */
-static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
-    "early exporter master secret";
-#else
+#ifdef HAVE_KEYING_MATERIAL
 /* The length of the early exporter label. */
 #define EARLY_EXPORTER_LABEL_SZ     12
@@ -551,5 +521,5 @@
 static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
     "e exp master";
-#endif
+
 /* Derive the early exporter key.
  *
@@ -562,4 +532,7 @@
     int ret;
     WOLFSSL_MSG("Derive Early Exporter Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->secret,
                     earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ,
@@ -579,11 +552,4 @@
 #endif
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the client handshake label. */
-#define CLIENT_HANDSHAKE_LABEL_SZ   31
-/* The client handshake label. */
-static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
-    "client handshake traffic secret";
-#else
 /* The length of the client handshake label. */
 #define CLIENT_HANDSHAKE_LABEL_SZ   12
@@ -591,5 +557,5 @@
 static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
     "c hs traffic";
-#endif
+
 /* Derive the client handshake key.
  *
@@ -602,4 +568,7 @@
     int ret;
     WOLFSSL_MSG("Derive Client Handshake Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
                     clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ,
@@ -617,11 +586,4 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the server handshake label. */
-#define SERVER_HANDSHAKE_LABEL_SZ   31
-/* The server handshake label. */
-static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
-    "server handshake traffic secret";
-#else
 /* The length of the server handshake label. */
 #define SERVER_HANDSHAKE_LABEL_SZ   12
@@ -629,5 +591,5 @@
 static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
     "s hs traffic";
-#endif
+
 /* Derive the server handshake key.
  *
@@ -640,4 +602,7 @@
     int ret;
     WOLFSSL_MSG("Derive Server Handshake Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
                     serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ,
@@ -655,11 +620,4 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the client application traffic label. */
-#define CLIENT_APP_LABEL_SZ         33
-/* The client application traffic label. */
-static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
-    "client application traffic secret";
-#else
 /* The length of the client application traffic label. */
 #define CLIENT_APP_LABEL_SZ         12
@@ -667,5 +625,5 @@
 static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
     "c ap traffic";
-#endif
+
 /* Derive the client application traffic key.
  *
@@ -678,4 +636,7 @@
     int ret;
     WOLFSSL_MSG("Derive Client Traffic Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
                     clientAppLabel, CLIENT_APP_LABEL_SZ,
@@ -693,11 +654,4 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the server application traffic label. */
-#define SERVER_APP_LABEL_SZ         33
-/* The  server application traffic label. */
-static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
-    "server application traffic secret";
-#else
 /* The length of the server application traffic label. */
 #define SERVER_APP_LABEL_SZ         12
@@ -705,5 +659,5 @@
 static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
     "s ap traffic";
-#endif
+
 /* Derive the server application traffic key.
  *
@@ -716,4 +670,7 @@
     int ret;
     WOLFSSL_MSG("Derive Server Traffic Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
                     serverAppLabel, SERVER_APP_LABEL_SZ,
@@ -731,12 +688,5 @@
 }
 
-#ifdef TLS13_SUPPORTS_EXPORTERS
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the exporter master secret label. */
-#define EXPORTER_MASTER_LABEL_SZ    22
-/* The exporter master secret label. */
-static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
-    "exporter master secret";
-#else
+#ifdef HAVE_KEYING_MATERIAL
 /* The length of the exporter master secret label. */
 #define EXPORTER_MASTER_LABEL_SZ    10
@@ -744,5 +694,5 @@
 static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
     "exp master";
-#endif
+
 /* Derive the exporter secret.
  *
@@ -754,5 +704,8 @@
 {
     int ret;
-    WOLFSSL_MSG("Derive Exporter Secret");
+    WOLFSSL_ENTER("Derive Exporter Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
                     exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ,
@@ -769,14 +722,105 @@
     return ret;
 }
+
+/* The length of the exporter label. */
+#define EXPORTER_LABEL_SZ    8
+/* The exporter label. */
+static const byte exporterLabel[EXPORTER_LABEL_SZ + 1] =
+    "exporter";
+/* Hash("") */
+#ifndef NO_SHA256
+static const byte emptySHA256Hash[] = {
+    0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8,
+    0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C,
+    0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
+};
+#endif
+#ifdef WOLFSSL_SHA384
+static const byte emptySHA384Hash[] = {
+    0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E,
+    0xB1, 0xB1, 0xE3, 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43,
+    0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, 0xE1, 0xDA, 0x27, 0x4E, 0xDE, 0xBF,
+    0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B
+};
+#endif
+#ifdef WOLFSSL_TLS13_SHA512
+static const byte emptySHA512Hash[] = {
+    0xCF, 0x83, 0xE1, 0x35, 0x7E, 0xEF, 0xB8, 0xBD, 0xF1, 0x54, 0x28, 0x50,
+    0xD6, 0x6D, 0x80, 0x07, 0xD6, 0x20, 0xE4, 0x05, 0x0B, 0x57, 0x15, 0xDC,
+    0x83, 0xF4, 0xA9, 0x21, 0xD3, 0x6C, 0xE9, 0xCE, 0x47, 0xD0, 0xD1, 0x3C,
+    0x5D, 0x85, 0xF2, 0xB0, 0xFF, 0x83, 0x18, 0xD2, 0x87, 0x7E, 0xEC, 0x2F,
+    0x63, 0xB9, 0x31, 0xBD, 0x47, 0x41, 0x7A, 0x81, 0xA5, 0x38, 0x32, 0x7A,
+    0xF9, 0x27, 0xDA, 0x3E
+};
+#endif
+/**
+ * Implement section 7.5 of RFC 8446
+ * @return  0 on success
+ *         <0 on failure
+ */
+int Tls13_Exporter(WOLFSSL* ssl, unsigned char *out, size_t outLen,
+        const char *label, size_t labelLen,
+        const unsigned char *context, size_t contextLen)
+{
+    int                 ret;
+    enum wc_HashType    hashType = WC_HASH_TYPE_NONE;
+    int                 hashLen = 0;
+    byte                hashOut[WC_MAX_DIGEST_SIZE];
+    const byte*         emptyHash = NULL;
+    byte                firstExpand[WC_MAX_DIGEST_SIZE];
+    const byte*         protocol = tls13ProtocolLabel;
+    word32              protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+
+    if (ssl->version.minor != TLSv1_3_MINOR)
+        return VERSION_ERROR;
+
+    switch (ssl->specs.mac_algorithm) {
+        #ifndef NO_SHA256
+        case sha256_mac:
+            hashType  = WC_HASH_TYPE_SHA256;
+            hashLen   = WC_SHA256_DIGEST_SIZE;
+            emptyHash = emptySHA256Hash;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hashType  = WC_HASH_TYPE_SHA384;
+            hashLen   = WC_SHA384_DIGEST_SIZE;
+            emptyHash = emptySHA384Hash;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hashType  = WC_HASH_TYPE_SHA512;
+            hashLen   = WC_SHA512_DIGEST_SIZE;
+            emptyHash = emptySHA512Hash;
+            break;
+        #endif
+    }
+
+    /* Derive-Secret(Secret, label, "") */
+    ret = HKDF_Expand_Label(firstExpand, hashLen,
+            ssl->arrays->exporterSecret, hashLen,
+            protocol, protocolLen, (byte*)label, (word32)labelLen,
+            emptyHash, hashLen, hashType);
+    if (ret != 0)
+        return ret;
+
+    /* Hash(context_value) */
+    ret = wc_Hash(hashType, context, (word32)contextLen, hashOut, WC_MAX_DIGEST_SIZE);
+    if (ret != 0)
+        return ret;
+
+    ret = HKDF_Expand_Label(out, (word32)outLen, firstExpand, hashLen,
+            protocol, protocolLen, exporterLabel, EXPORTER_LABEL_SZ,
+            hashOut, hashLen, hashType);
+
+    return ret;
+}
 #endif
 
 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the resumption master secret label. */
-#define RESUME_MASTER_LABEL_SZ      24
-/* The resumption master secret label. */
-static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
-    "resumption master secret";
-#else
 /* The length of the resumption master secret label. */
 #define RESUME_MASTER_LABEL_SZ      10
@@ -784,5 +828,5 @@
 static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
     "res master";
-#endif
+
 /* Derive the resumption secret.
  *
@@ -791,10 +835,20 @@
  * returns 0 on success, otherwise failure.
  */
-static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
-{
+int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
+{
+    byte* masterSecret;
+
     WOLFSSL_MSG("Derive Resumption Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
-                     resumeMasterLabel, RESUME_MASTER_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    if (ssl->arrays != NULL) {
+        masterSecret = ssl->arrays->masterSecret;
+    }
+    else {
+        masterSecret = ssl->session.masterSecret;
+    }
+    return DeriveKey(ssl, key, -1, masterSecret, resumeMasterLabel,
+                     RESUME_MASTER_LABEL_SZ, ssl->specs.mac_algorithm, 1);
 }
 #endif
@@ -818,11 +872,4 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the application traffic label. */
-#define APP_TRAFFIC_LABEL_SZ        26
-/* The application traffic label. */
-static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
-    "application traffic secret";
-#else
 /* The length of the application traffic label. */
 #define APP_TRAFFIC_LABEL_SZ        11
@@ -830,5 +877,5 @@
 static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
     "traffic upd";
-#endif
+
 /* Update the traffic secret.
  *
@@ -849,7 +896,10 @@
  * ssl  The SSL/TLS object.
  */
-static int DeriveEarlySecret(WOLFSSL* ssl)
+int DeriveEarlySecret(WOLFSSL* ssl)
 {
     WOLFSSL_MSG("Derive Early Secret");
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
     return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
@@ -862,5 +912,4 @@
 }
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
 /* The length of the derived label. */
 #define DERIVED_LABEL_SZ        7
@@ -868,23 +917,17 @@
 static const byte derivedLabel[DERIVED_LABEL_SZ + 1] =
     "derived";
-#endif
+
 /* Derive the handshake secret using HKDF Extract.
  *
  * ssl  The SSL/TLS object.
  */
-static int DeriveHandshakeSecret(WOLFSSL* ssl)
-{
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    WOLFSSL_MSG("Derive Handshake Secret");
-    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
-            ssl->arrays->secret, ssl->specs.hash_size,
-            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
-            ssl->specs.mac_algorithm);
-#else
+int DeriveHandshakeSecret(WOLFSSL* ssl)
+{
     byte key[WC_MAX_DIGEST_SIZE];
     int ret;
-
     WOLFSSL_MSG("Derive Handshake Secret");
-
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
                         derivedLabel, DERIVED_LABEL_SZ,
@@ -897,5 +940,4 @@
             ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
             ssl->specs.mac_algorithm);
-#endif
 }
 
@@ -904,17 +946,12 @@
  * ssl  The SSL/TLS object.
  */
-static int DeriveMasterSecret(WOLFSSL* ssl)
-{
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    WOLFSSL_MSG("Derive Master Secret");
-    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
-            ssl->arrays->preMasterSecret, ssl->specs.hash_size,
-            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
-#else
+int DeriveMasterSecret(WOLFSSL* ssl)
+{
     byte key[WC_MAX_DIGEST_SIZE];
     int ret;
-
     WOLFSSL_MSG("Derive Master Secret");
-
+    if (ssl == NULL || ssl->arrays == NULL) {
+        return BAD_FUNC_ARG;
+    }
     ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret,
                         derivedLabel, DERIVED_LABEL_SZ,
@@ -923,11 +960,19 @@
         return ret;
 
-    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
+    ret = Tls13_HKDF_Extract(ssl->arrays->masterSecret,
             key, ssl->specs.hash_size,
             ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
-#endif
-}
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
+
+#ifdef HAVE_KEYING_MATERIAL
+    if (ret != 0)
+        return ret;
+    /* Calculate exporter secret only when saving arrays */
+    if (ssl->options.saveArrays)
+        ret = DeriveExporterSecret(ssl, ssl->arrays->exporterSecret);
+#endif
+
+    return ret;
+}
+
 #if defined(HAVE_SESSION_TICKET)
 /* Length of the resumption label. */
@@ -943,6 +988,5 @@
  * returns 0 on success, otherwise failure.
  */
-static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen,
-                               byte* secret)
+int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret)
 {
     int         digestAlg;
@@ -982,5 +1026,4 @@
 }
 #endif /* HAVE_SESSION_TICKET */
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
 
 
@@ -999,4 +1042,8 @@
     int  hashSz = WC_SHA256_DIGEST_SIZE;
     int  ret = BAD_FUNC_ARG;
+
+    if (ssl == NULL || key == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
 
     /* Get the hash of the previous handshake messages. */
@@ -1071,5 +1118,5 @@
  * returns 0 on success, otherwise failure.
  */
-static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
+int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
 {
     int   ret = BAD_FUNC_ARG; /* Assume failure */
@@ -1282,6 +1329,6 @@
     word32 TimeNowInMilliseconds(void)
     {
-        const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
-        uint32_t *systemTickPtr = systemTickPointer();
+        const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
+        word32 *systemTickPtr = systemTickPointer();
 
         return (word32) (*systemTickPtr/systemTickTimeInHz) * 1000;
@@ -1407,4 +1454,36 @@
         return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000));
     }
+#elif defined(WOLFSSL_LINUXKM)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
+        return (word32)(ktime_get_real_ns() / (s64)1000000);
+    #else
+        return (word32)(ktime_get_real_ns() / (ktime_t)1000000);
+    #endif
+    }
+#elif defined(FUSION_RTOS)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        struct timeval now;
+        if (FCL_GETTIMEOFDAY(&now, 0) < 0)
+            return (word32)GETTIME_ERROR; /* TODO: return 0 for failure */
+
+        /* Convert to milliseconds number. */
+        return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000);
+    }
+
 #else
     /* The time in milliseconds.
@@ -1419,5 +1498,6 @@
 
         if (gettimeofday(&now, 0) < 0)
-            return GETTIME_ERROR;
+            return (word32)GETTIME_ERROR; /* TODO: return 0 for failure */
+
         /* Convert to milliseconds number. */
         return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000);
@@ -1426,37 +1506,4 @@
 #endif /* HAVE_SESSION_TICKET || !NO_PSK */
 
-
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \
-                                    !defined(NO_PSK))
-/* Add input to all handshake hashes.
- *
- * ssl    The SSL/TLS object.
- * input  The data to hash.
- * sz     The size of the data to hash.
- * returns 0 on success, otherwise failure.
- */
-static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz)
-{
-    int ret = BAD_FUNC_ARG;
-
-#ifndef NO_SHA256
-    ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_SHA384
-    ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_TLS13_SHA512
-    ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-
-    return ret;
-}
-#endif
 
 /* Extract the handshake header information.
@@ -1502,10 +1549,6 @@
     rl->type    = type;
     rl->pvMajor = ssl->version.major;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    rl->pvMinor = TLSv1_MINOR;
-#else
     /* NOTE: May be TLSv1_MINOR when sending first ClientHello. */
     rl->pvMinor = TLSv1_2_MINOR;
-#endif
     c16toa((word16)length, rl->length);
 }
@@ -1584,5 +1627,5 @@
  * out          The buffer to write into.
  */
-static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+static WC_INLINE void WriteSEQTls13(WOLFSSL* ssl, int verifyOrder, byte* out)
 {
     word32 seq[2] = {0, 0};
@@ -1620,5 +1663,5 @@
 
     /* The nonce is the IV with the sequence XORed into the last bytes. */
-    WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
+    WriteSEQTls13(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
     for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++)
         nonce[i] = iv[i];
@@ -1628,5 +1671,5 @@
 
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-/* Encrypt with ChaCha20 and create authenication tag with Poly1305.
+/* Encrypt with ChaCha20 and create authentication tag with Poly1305.
  *
  * ssl     The SSL/TLS object.
@@ -1683,5 +1726,5 @@
 
 #ifdef HAVE_NULL_CIPHER
-/* Create authenication tag and copy data over input.
+/* Create authentication tag and copy data over input.
  *
  * ssl     The SSL/TLS object.
@@ -1765,9 +1808,6 @@
             WOLFSSL_MSG("Data to encrypt");
             WOLFSSL_BUFFER(input, dataSz);
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
-                                        !defined(WOLFSSL_TLS13_DRAFT_23)
             WOLFSSL_MSG("Additional Authentication Data");
             WOLFSSL_BUFFER(aad, aadSz);
-#endif
         #endif
 
@@ -1912,5 +1952,5 @@
 
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-/* Decrypt with ChaCha20 and check authenication tag with Poly1305.
+/* Decrypt with ChaCha20 and check authentication tag with Poly1305.
  *
  * ssl     The SSL/TLS object.
@@ -2068,9 +2108,6 @@
             WOLFSSL_MSG("Data to decrypt");
             WOLFSSL_BUFFER(input, dataSz);
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
-                                        !defined(WOLFSSL_TLS13_DRAFT_23)
             WOLFSSL_MSG("Additional Authentication Data");
             WOLFSSL_BUFFER(aad, aadSz);
-#endif
             WOLFSSL_MSG("Authentication tag");
             WOLFSSL_BUFFER(input + dataSz, macSz);
@@ -2351,15 +2388,8 @@
         #endif
             {
-#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \
-                                       defined(WOLFSSL_TLS13_DRAFT_23)
-                output += args->headerSz;
-                ret = EncryptTls13(ssl, output, output, args->size, NULL, 0,
-                                                                     asyncOkay);
-#else
                 const byte* aad = output;
                 output += args->headerSz;
                 ret = EncryptTls13(ssl, output, output, args->size, aad,
                                    RECORD_HEADER_SZ, asyncOkay);
-#endif
             }
             break;
@@ -2415,5 +2445,4 @@
 #endif
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
 #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
 /* Create Cookie extension using the hash of the first ClientHello.
@@ -2462,5 +2491,5 @@
  * returns 0 on success, otherwise failure.
  */
-static int RestartHandshakeHash(WOLFSSL* ssl)
+int RestartHandshakeHash(WOLFSSL* ssl)
 {
     int    ret;
@@ -2526,8 +2555,8 @@
     if (ret != 0)
         return ret;
-    ret = HashOutputRaw(ssl, header, sizeof(header));
+    ret = HashRaw(ssl, header, sizeof(header));
     if (ret != 0)
         return ret;
-    return HashOutputRaw(ssl, hash, hashSz);
+    return HashRaw(ssl, hash, hashSz);
 }
 
@@ -2541,5 +2570,5 @@
     0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
 };
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
 
 #ifndef NO_WOLFSSL_CLIENT
@@ -2578,13 +2607,8 @@
         /* Resumption PSK is master secret. */
         ssl->arrays->psk_keySz = ssl->specs.hash_size;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-        XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
-                ssl->arrays->psk_keySz);
-#else
         if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
                     ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
             return ret;
         }
-#endif
     }
 #endif
@@ -2594,4 +2618,5 @@
         const char* cipherName = NULL;
         byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
+        int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;
 
         /* Get the pre-shared key. */
@@ -2602,5 +2627,5 @@
                     &cipherName);
             if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
-                                                           &cipherSuite) != 0) {
+                                       &cipherSuite, &cipherSuiteFlags) != 0) {
                 return PSK_KEY_ERROR;
             }
@@ -2620,4 +2645,5 @@
             return PSK_KEY_ERROR;
         }
+        (void)cipherSuiteFlags;
     #else
         /* PSK information loaded during setting of default TLS extensions. */
@@ -2626,6 +2652,7 @@
 #endif
 
-    if (ssl->options.noPskDheKe)
+    if (ssl->options.noPskDheKe) {
         ssl->arrays->preMasterSz = 0;
+    }
 
     /* Derive the early secret using the PSK. */
@@ -2707,5 +2734,5 @@
 
     /* Hash binders to complete the hash of the ClientHello. */
-    ret = HashOutputRaw(ssl, output + idx, len);
+    ret = HashRaw(ssl, output + idx, len);
     if (ret < 0)
         return ret;
@@ -2778,5 +2805,4 @@
     length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz +
              SUITE_LEN + COMP_LEN + ENUM_LEN;
-#ifndef WOLFSSL_TLS13_DRAFT_18
     #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
     length += ID_LEN;
@@ -2785,5 +2811,4 @@
         length += ssl->session.sessionIDSz;
     #endif
-#endif
 
     /* Auto populate extensions supported unless user defined. */
@@ -2846,8 +2871,4 @@
     idx += RAN_LEN;
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* TLS v1.3 does not use session id - 0 length. */
-    output[idx++] = 0;
-#else
     if (ssl->session.sessionIDSz > 0) {
         /* Session resumption for old versions of protocol. */
@@ -2866,5 +2887,4 @@
     #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
     }
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
 
     /* Cipher suites */
@@ -2921,73 +2941,4 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* handle rocessing of TLS 1.3 hello_retry_request (6) */
-/* Parse and handle a HelloRetryRequest message.
- * Only a client will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of
- *           HelloRetryRequest.
- *           On exit, the index of byte after the HelloRetryRequest message.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input,
-                                    word32* inOutIdx, word32 totalSz)
-{
-    int             ret;
-    word32          begin = *inOutIdx;
-    word32          i = begin;
-    word16          totalExtSz;
-    ProtocolVersion pv;
-
-    WOLFSSL_ENTER("DoTls13HelloRetryRequest");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "HelloRetryRequest");
-    if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo);
-#endif
-
-    /* Version info and length field of extension data. */
-    if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-        return BUFFER_ERROR;
-
-    /* Protocol version. */
-    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-    i += OPAQUE16_LEN;
-    ret = CheckVersion(ssl, pv);
-    if (ret != 0)
-        return ret;
-
-    /* Length of extension data. */
-    ato16(&input[i], &totalExtSz);
-    i += OPAQUE16_LEN;
-    if (totalExtSz == 0) {
-        WOLFSSL_MSG("HelloRetryRequest must contain extensions");
-        return MISSING_HANDSHAKE_DATA;
-    }
-
-    /* Extension data. */
-    if (i - begin + totalExtSz > totalSz)
-        return BUFFER_ERROR;
-    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
-                          hello_retry_request, NULL)) != 0)
-        return ret;
-    /* The KeyShare extension parsing fails when not valid. */
-
-    /* Move index to byte after message. */
-    *inOutIdx = i + totalExtSz;
-
-    ssl->options.tls1_3 = 1;
-    ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
-
-    WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret);
-
-    return ret;
-}
-#endif
-
-
 /* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
 /* Handle the ServerHello message from the server.
@@ -3008,10 +2959,8 @@
     word32          begin = i;
     int             ret;
-#ifndef WOLFSSL_TLS13_DRAFT_18
     byte            sessIdSz;
     const byte*     sessId;
     byte            b;
     int             foundVersion;
-#endif
     word16          totalExtSz;
 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
@@ -3023,4 +2972,7 @@
     WOLFSSL_ENTER("DoTls13ServerHello");
 
+    if (ssl->arrays == NULL)
+        return BAD_FUNC_ARG;
+
 #ifdef WOLFSSL_CALLBACKS
     if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
@@ -3028,4 +2980,7 @@
 #endif
 
+    if (ssl == NULL || ssl->arrays == NULL)
+        return BAD_FUNC_ARG;
+
     /* Protocol version length check. */
     if (OPAQUE16_LEN > helloSz)
@@ -3035,20 +2990,5 @@
     XMEMCPY(&pv, input + i, OPAQUE16_LEN);
     i += OPAQUE16_LEN;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ret = CheckVersion(ssl, pv);
-    if (ret != 0)
-        return ret;
-    if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) {
-#ifndef WOLFSSL_NO_TLS12
-        if (ssl->options.downgrade) {
-            ssl->version = pv;
-            return DoServerHello(ssl, input, inOutIdx, helloSz);
-        }
-#endif
-
-        WOLFSSL_MSG("Client using higher version, fatal error");
-        return VERSION_ERROR;
-    }
-#else
+
 #ifndef WOLFSSL_NO_TLS12
     if (pv.major == ssl->version.major  && pv.minor < TLSv1_2_MINOR &&
@@ -3062,18 +3002,22 @@
     if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR)
         return VERSION_ERROR;
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Random length check */
-    if ((i - begin) + RAN_LEN > helloSz)
-        return BUFFER_ERROR;
-#else
+
     /* Random and session id length check */
     if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz)
         return BUFFER_ERROR;
 
-    if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0)
+    if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) {
         *extMsgType = hello_retry_request;
-#endif
+        /* A HelloRetryRequest comes in as an ServerHello for MiddleBox compat.
+         * Found message to be a HelloRetryRequest.
+         * Don't allow more than one HelloRetryRequest or ServerHello.
+         */
+        if (ssl->msgsReceived.got_hello_retry_request == 1) {
+            return DUPLICATE_MSG_E;
+        }
+        /* Update counts to reflect change of message type. */
+        ssl->msgsReceived.got_hello_retry_request++;
+        ssl->msgsReceived.got_server_hello--;
+    }
 
     /* Server random - keep for debugging. */
@@ -3081,5 +3025,4 @@
     i += RAN_LEN;
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Session id */
     sessIdSz = input[i++];
@@ -3088,16 +3031,10 @@
     sessId = input + i;
     i += sessIdSz;
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
     ssl->options.haveSessionId = 1;
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Ciphersuite check */
-    if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
-        return BUFFER_ERROR;
-#else
     /* Ciphersuite and compression check */
     if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
         return BUFFER_ERROR;
-#endif
 
     /* Set the cipher suite from the message. */
@@ -3105,5 +3042,4 @@
     ssl->options.cipherSuite  = input[i++];
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Compression */
     b = input[i++];
@@ -3112,7 +3048,5 @@
         return INVALID_PARAMETER;
     }
-#endif
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
+
     if ((i - begin) + OPAQUE16_LEN > helloSz) {
         if (!ssl->options.downgrade)
@@ -3123,7 +3057,5 @@
         ssl->options.haveEMS = 0;
     }
-    if ((i - begin) < helloSz)
-#endif
-    {
+    if ((i - begin) < helloSz) {
         /* Get extension length and length check. */
         if ((i - begin) + OPAQUE16_LEN > helloSz)
@@ -3134,5 +3066,4 @@
             return BUFFER_ERROR;
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
         /* Need to negotiate version first. */
         if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz,
@@ -3151,5 +3082,4 @@
             ssl->version.minor = pv.minor;
         }
-#endif
 
         /* Parse and handle extensions. */
@@ -3176,5 +3106,4 @@
 #endif /* HAVE_SECRET_CALLBACK */
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Version only negotiated in extensions for TLS v1.3.
      * Only now do we know how to deal with session id.
@@ -3208,5 +3137,5 @@
     }
 
-    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
     if (sessIdSz == 0)
         return INVALID_PARAMETER;
@@ -3219,5 +3148,5 @@
     else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0)
         return INVALID_PARAMETER;
-    #else
+#else
     if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
                   XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) {
@@ -3225,6 +3154,5 @@
         return INVALID_PARAMETER;
     }
-    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
-#endif
+#endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
 
     ret = SetCipherSpecs(ssl);
@@ -3246,8 +3174,5 @@
 
 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    if (*extMsgType == server_hello)
-#endif
-    {
+    if (*extMsgType == server_hello) {
         ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
         if (ext != NULL)
@@ -3265,7 +3190,4 @@
 #endif
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ssl->keys.encryptionOn = 1;
-#else
     if (*extMsgType == server_hello) {
         ssl->keys.encryptionOn = 1;
@@ -3278,5 +3200,4 @@
         ret = RestartHandshakeHash(ssl);
     }
-#endif
 
     WOLFSSL_LEAVE("DoTls13ServerHello", ret);
@@ -3358,4 +3279,5 @@
 }
 
+#ifndef NO_CERTS
 /* handle processing TLS v1.3 certificate_request (13) */
 /* Handle a TLS v1.3 CertificateRequest message.
@@ -3376,7 +3298,5 @@
     word32      begin = *inOutIdx;
     int         ret = 0;
-#ifndef WOLFSSL_TLS13_DRAFT_18
     Suites      peerSuites;
-#endif
 #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
     CertReqCtx* certReqCtx;
@@ -3386,7 +3306,6 @@
     WOLFSSL_ENTER("DoTls13CertificateRequest");
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     XMEMSET(&peerSuites, 0, sizeof(Suites));
-#endif
+
 #ifdef WOLFSSL_CALLBACKS
     if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest");
@@ -3420,53 +3339,4 @@
     *inOutIdx += len;
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Signature and hash algorithms. */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 &&
-                 ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
-                 ssl->buffers.key && ssl->buffers.key->buffer) {
-        return INVALID_PARAMETER;
-    }
-    *inOutIdx += len;
-
-    /* Length of certificate authority data. */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-
-    /* Certificate authorities. */
-    while (len) {
-        word16 dnSz;
-
-        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-            return BUFFER_ERROR;
-
-        ato16(input + *inOutIdx, &dnSz);
-        *inOutIdx += OPAQUE16_LEN;
-
-        if ((*inOutIdx - begin) + dnSz > size)
-            return BUFFER_ERROR;
-
-        *inOutIdx += dnSz;
-        len -= OPAQUE16_LEN + dnSz;
-    }
-
-    /* Certificate extensions */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    *inOutIdx += len;
-#else
     /* TODO: Add support for more extensions:
      *   signed_certificate_timestamp, certificate_authorities, oid_filters.
@@ -3486,5 +3356,4 @@
     }
     *inOutIdx += len;
-#endif
 
     if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
@@ -3494,14 +3363,18 @@
         #endif
     )) {
-#ifndef WOLFSSL_TLS13_DRAFT_18
         if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo,
                                                peerSuites.hashSigAlgoSz) != 0) {
             return INVALID_PARAMETER;
         }
-#endif
         ssl->options.sendVerify = SEND_CERT;
     }
     else {
+#ifndef WOLFSSL_NO_CLIENT_CERT_ERROR
         ssl->options.sendVerify = SEND_BLANK_CERT;
+#else
+        WOLFSSL_MSG("Certificate required but none set on client");
+        SendAlert(ssl, alert_fatal, illegal_parameter);
+        return NO_CERT_ERROR;
+#endif
     }
 
@@ -3514,5 +3387,5 @@
     return ret;
 }
-
+#endif /* !NO_CERTS */
 #endif /* !NO_WOLFSSL_CLIENT */
 
@@ -3576,4 +3449,5 @@
     byte          cipherSuite0 = TLS13_BYTE;
     byte          cipherSuite  = WOLFSSL_DEF_PSK_CIPHER;
+    int           cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;
 #endif
 
@@ -3625,5 +3499,5 @@
     #ifdef HAVE_SESSION_TICKET
         /* Decode the identity. */
-        if ((ret = DoClientTicket(ssl, current->identity, current->identityLen))
+        if (DoClientTicket(ssl, current->identity, current->identityLen)
                                                      == WOLFSSL_TICKET_RET_OK) {
             word32 now;
@@ -3642,5 +3516,6 @@
                 /* Invalid difference, fallback to full handshake. */
                 ssl->options.resuming = 0;
-                break;
+                /* Hash the rest of the ClientHello. */
+                return HashRaw(ssl, input + helloSz - bindersLen, bindersLen);
             }
 
@@ -3667,13 +3542,8 @@
             /* Resumption PSK is resumption master secret. */
             ssl->arrays->psk_keySz = ssl->specs.hash_size;
-        #ifdef WOLFSSL_TLS13_DRAFT_18
-            XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
-                    ssl->arrays->psk_keySz);
-        #else
             if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
                     ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
                 return ret;
             }
-        #endif
 
             /* Derive the early secret using the PSK. */
@@ -3694,5 +3564,5 @@
                              MAX_PSK_KEY_LEN, &cipherName)) != 0 &&
              GetCipherSuiteFromName(cipherName, &cipherSuite0,
-                                                          &cipherSuite) == 0) ||
+                                    &cipherSuite, &cipherSuiteFlags) == 0) ||
             (ssl->options.server_psk_cb != NULL &&
              (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
@@ -3705,4 +3575,5 @@
             suite[0] = cipherSuite0;
             suite[1] = cipherSuite;
+            (void)cipherSuiteFlags;
             if (!FindSuiteSSL(ssl, suite)) {
                 current = current->next;
@@ -3712,4 +3583,6 @@
             /* Default to ciphersuite if cb doesn't specify. */
             ssl->options.resuming = 0;
+            /* Don't send certificate request when using PSK. */
+            ssl->options.verifyPeer = 0;
 
             /* PSK age is always zero. */
@@ -3765,5 +3638,5 @@
 
     /* Hash the rest of the ClientHello. */
-    ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
+    ret = HashRaw(ssl, input + helloSz - bindersLen, bindersLen);
     if (ret != 0)
         return ret;
@@ -3807,4 +3680,5 @@
     modes = ext->val;
 
+#ifdef HAVE_SUPPORTED_CURVES
     ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
     /* Use (EC)DHE for forward-security if possible. */
@@ -3826,5 +3700,7 @@
         ext->resp = 1;
     }
-    else {
+    else
+#endif
+    {
         if ((modes & (1 << PSK_KE)) == 0)
             return PSK_KEY_ERROR;
@@ -3841,5 +3717,5 @@
 #endif
 
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+#if defined(WOLFSSL_SEND_HRR_COOKIE)
 /* Check that the Cookie data's integrity.
  *
@@ -3892,13 +3768,4 @@
 /* Length of the Cookie Extension excluding cookie data */
 #define HRR_COOKIE_HDR_SZ  (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* PV | CipherSuite | Ext Len */
-#define HRR_BODY_SZ        (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */
-#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
-                        HRR_BODY_SZ         + \
-                          HRR_KEY_SHARE_SZ  + \
-                          HRR_COOKIE_HDR_SZ)
-#else
 /* PV | Random | Session Id | CipherSuite | Compression | Ext Len */
 #define HRR_BODY_SZ        (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \
@@ -3910,5 +3777,5 @@
                           HRR_VERSIONS_SZ   + \
                           HRR_COOKIE_HDR_SZ)
-#endif
+
 
 /* Restart the handshake hash from the cookie value.
@@ -3942,38 +3809,18 @@
     if ((ret = InitHandshakeHashes(ssl)) != 0)
         return ret;
-    if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0)
-        return ret;
-    if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0)
+    if ((ret = HashRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashRaw(ssl, cookieData + idx, hashSz)) != 0)
         return ret;
 
     /* Reconstruct the HelloRetryMessage for handshake hash. */
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len;
-#else
     length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz +
              HRR_COOKIE_HDR_SZ + cookie->len;
     length += HRR_VERSIONS_SZ;
-#endif
     if (cookieDataSz > hashSz + OPAQUE16_LEN) {
         keyShareExt = 1;
         length += HRR_KEY_SHARE_SZ;
     }
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl);
-
-    idx += hashSz;
-    hrrIdx = HANDSHAKE_HEADER_SZ;
-    /* The negotiated protocol version. */
-    hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
-    hrr[hrrIdx++] = TLS_DRAFT_MINOR;
-    /* Cipher Suite */
-    hrr[hrrIdx++] = cookieData[idx++];
-    hrr[hrrIdx++] = cookieData[idx++];
-
-    /* Extensions' length */
-    length -= HRR_BODY_SZ;
-    c16toa(length, hrr + hrrIdx);
-    hrrIdx += 2;
-#else
+
     AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl);
 
@@ -4007,5 +3854,4 @@
     hrrIdx += 2;
 
-#endif
     /* Optional KeyShare Extension */
     if (keyShareExt) {
@@ -4017,5 +3863,4 @@
         hrr[hrrIdx++] = cookieData[idx++];
     }
-#ifndef WOLFSSL_TLS13_DRAFT_18
     c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx);
     hrrIdx += 2;
@@ -4029,5 +3874,5 @@
         hrr[hrrIdx++] = ssl->version.minor;
     #endif
-#endif
+
     /* Mandatory Cookie Extension */
     c16toa(TLSX_COOKIE, hrr + hrrIdx);
@@ -4045,7 +3890,7 @@
 #endif
 
-    if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0)
-        return ret;
-    return HashOutputRaw(ssl, cookieData, cookie->len);
+    if ((ret = HashRaw(ssl, hrr, hrrIdx)) != 0)
+        return ret;
+    return HashRaw(ssl, cookieData, cookie->len);
 }
 #endif
@@ -4205,4 +4050,6 @@
     }
 
+    /* From here on we are a TLS 1.3 ClientHello. */
+
     /* Client random */
     XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
@@ -4214,16 +4061,7 @@
 #endif
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Session id - empty in TLS v1.3 */
-    sessIdSz = input[i++];
-    if (sessIdSz > 0 && !ssl->options.downgrade) {
-        WOLFSSL_MSG("Client sent session id - not supported");
-        return BUFFER_ERROR;
-    }
-#else
     sessIdSz = input[i++];
     if (sessIdSz != ID_LEN && sessIdSz != 0)
         return INVALID_PARAMETER;
-#endif
 
     if (sessIdSz + i > helloSz) {
@@ -4251,24 +4089,4 @@
     clSuites.hashSigAlgoSz = 0;
 
-#ifdef HAVE_SERVER_RENEGOTIATION_INFO
-    ret = FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
-    if (ret == SUITES_ERROR)
-        return BUFFER_ERROR;
-    if (ret >= 0) {
-        TLSX* extension;
-
-        /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
-        ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
-        if (ret != WOLFSSL_SUCCESS)
-            return ret;
-
-        extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
-        if (extension) {
-            ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
-            ssl->secure_renegotiation->enabled = 1;
-        }
-    }
-#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
-
     /* Compression */
     b = input[i++];
@@ -4306,10 +4124,9 @@
     }
 
-#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
-                                                        defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_SNI
         if ((ret = SNI_Callback(ssl)) != 0)
             return ret;
         ssl->options.side = WOLFSSL_SERVER_END;
-#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+#endif
 
     i += totalExtSz;
@@ -4321,5 +4138,5 @@
     ssl->options.haveSessionId = 1;
 
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+#if defined(WOLFSSL_SEND_HRR_COOKIE)
     if (ssl->options.sendCookie &&
               ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
@@ -4340,5 +4157,5 @@
 
 #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
-     defined(HAVE_TLS_EXTENSIONS)
+                                                    defined(HAVE_TLS_EXTENSIONS)
     if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY) != NULL) {
         /* Refine list for PSK processing. */
@@ -4362,4 +4179,5 @@
 
     if (!usingPSK) {
+#ifndef NO_CERTS
         if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
             WOLFSSL_MSG("Client did not send a KeyShare extension");
@@ -4379,5 +4197,5 @@
         }
 
-#ifdef HAVE_NULL_CIPHER
+    #ifdef HAVE_NULL_CIPHER
         if (ssl->options.cipherSuite0 == ECC_BYTE &&
                               (ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
@@ -4386,5 +4204,5 @@
         }
         else
-#endif
+    #endif
         /* Check that the negotiated ciphersuite matches protocol version. */
         if (ssl->options.cipherSuite0 != TLS13_BYTE) {
@@ -4395,14 +4213,17 @@
         }
 
-#ifdef HAVE_SESSION_TICKET
+    #ifdef HAVE_SESSION_TICKET
         if (ssl->options.resuming) {
             ssl->options.resuming = 0;
             XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size);
         }
-#endif
+    #endif
 
         /* Derive early secret for handshake secret. */
         if ((ret = DeriveEarlySecret(ssl)) != 0)
             return ret;
+#else
+        ret = INVALID_PARAMETER;
+#endif
     }
 
@@ -4413,8 +4234,5 @@
 }
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* handle generation of TLS 1.3 hello_retry_request (6) */
-/* Send the HelloRetryRequest message to indicate the negotiated protocol
- * version and security parameters the server is willing to use.
+/* Send TLS v1.3 ServerHello message to client.
  * Only a server will send this message.
  *
@@ -4422,77 +4240,4 @@
  * returns 0 on success, otherwise failure.
  */
-int SendTls13HelloRetryRequest(WOLFSSL* ssl)
-{
-    int    ret;
-    byte*  output;
-    word32 length;
-    word16 len;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    int    sendSz;
-
-    WOLFSSL_ENTER("SendTls13HelloRetryRequest");
-
-    /* Get the length of the extensions that will be written. */
-    len = 0;
-    ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len);
-    /* There must be extensions sent to indicate what client needs to do. */
-    if (ret != 0)
-        return MISSING_HANDSHAKE_DATA;
-
-    /* Protocol version + Extensions */
-    length = OPAQUE16_LEN + len;
-    sendSz = idx + length;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-    /* Add record and handshake headers. */
-    AddTls13Headers(output, length, hello_retry_request, ssl);
-
-    /* The negotiated protocol version. */
-    output[idx++] = TLS_DRAFT_MAJOR;
-    output[idx++] = TLS_DRAFT_MINOR;
-
-    /* Add TLS extensions. */
-    ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL);
-    if (ret != 0)
-        return ret;
-    idx += len;
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn)
-        AddPacketName(ssl, "HelloRetryRequest");
-    if (ssl->toInfoOn) {
-        AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz,
-                      WRITE_PROTO, ssl->heap);
-    }
-#endif
-    if ((ret = HashOutput(ssl, output, idx, 0)) != 0)
-        return ret;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret);
-
-    return ret;
-}
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-
-/* Send TLS v1.3 ServerHello message to client.
- * Only a server will send this message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-#ifdef WOLFSSL_TLS13_DRAFT_18
-static
-#endif
 /* handle generation of TLS 1.3 server_hello (2) */
 int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
@@ -4507,5 +4252,4 @@
     WOLFSSL_ENTER("SendTls13ServerHello");
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     if (extMsgType == hello_retry_request) {
         WOLFSSL_MSG("wolfSSL Doing HelloRetryRequest");
@@ -4513,13 +4257,5 @@
             return ret;
     }
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Protocol version, server random, cipher suite and extensions. */
-    length = VERSION_SZ + RAN_LEN + SUITE_LEN;
-    ret = TLSX_GetResponseSize(ssl, server_hello, &length);
-    if (ret != 0)
-        return ret;
-#else
+
     /* Protocol version, server random, session id, cipher suite, compression
      * and extensions.
@@ -4530,5 +4266,4 @@
     if (ret != 0)
         return ret;
-#endif
     sendSz = idx + length;
 
@@ -4544,13 +4279,7 @@
     AddTls13Headers(output, length, server_hello, ssl);
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* The negotiated protocol version. */
-    output[idx++] = TLS_DRAFT_MAJOR;
-    output[idx++] = TLS_DRAFT_MINOR;
-#else
     /* The protocol version must be TLS v1.2 for middleboxes. */
     output[idx++] = ssl->version.major;
     output[idx++] = TLSv1_2_MINOR;
-#endif
 
     if (extMsgType == server_hello) {
@@ -4559,10 +4288,9 @@
             return ret;
     }
-#ifndef WOLFSSL_TLS13_DRAFT_18
     else {
         /* HelloRetryRequest message has fixed value for random. */
         XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
     }
-#endif
+
     /* Store in SSL for debugging. */
     XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
@@ -4574,5 +4302,4 @@
 #endif
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     output[idx++] = ssl->session.sessionIDSz;
     if (ssl->session.sessionIDSz > 0) {
@@ -4580,5 +4307,4 @@
         idx += ssl->session.sessionIDSz;
     }
-#endif
 
     /* Chosen cipher suite */
@@ -4586,8 +4312,6 @@
     output[idx++] = ssl->options.cipherSuite;
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Compression not supported in TLS v1.3. */
     output[idx++] = 0;
-#endif
 
     /* Extensions */
@@ -4610,16 +4334,9 @@
     #endif
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ssl->options.serverState = SERVER_HELLO_COMPLETE;
-#else
     if (extMsgType == server_hello)
         ssl->options.serverState = SERVER_HELLO_COMPLETE;
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    if (!ssl->options.groupMessages)
-#else
+
     if (!ssl->options.groupMessages || extMsgType != server_hello)
-#endif
+
         ret = SendBuffered(ssl);
 
@@ -4651,5 +4368,5 @@
     ssl->keys.encryptionOn = 1;
 
-#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
+#if defined(HAVE_SUPPORTED_CURVES) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
     if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0)
         return ret;
@@ -4750,7 +4467,5 @@
     word32 i;
     word16 reqSz;
-#ifndef WOLFSSL_TLS13_DRAFT_18
     TLSX*  ext;
-#endif
 
     WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
@@ -4760,46 +4475,4 @@
         InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz);
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ;
-    reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
-
-    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
-    /* Always encrypted and make room for padding. */
-    sendSz += MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, reqSz, certificate_request, ssl);
-
-    /* Certificate request context. */
-    output[i++] = reqCtxLen;
-    if (reqCtxLen != 0) {
-        XMEMCPY(output + i, reqCtx, reqCtxLen);
-        i += reqCtxLen;
-    }
-
-    /* supported hash/sig */
-    c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
-    i += LENGTH_SZ;
-
-    XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
-    i += ssl->suites->hashSigAlgoSz;
-
-    /* Certificate authorities not supported yet - empty buffer. */
-    c16toa(0, &output[i]);
-    i += REQ_HEADER_SZ;
-
-    /* Certificate extensions. */
-    c16toa(0, &output[i]);  /* auth's */
-    i += REQ_HEADER_SZ;
-#else
     ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS);
     if (ext == NULL)
@@ -4841,5 +4514,4 @@
         return ret;
     i += reqSz;
-#endif
 
     /* Always encrypted. */
@@ -5181,5 +4853,5 @@
 #endif /* HAVE_ECC */
 
-#ifndef NO_RSA
+#if !defined(NO_RSA) && defined(WC_RSA_PSS)
 /* Check that the decrypted signature matches the encoded signature
  * based on the digest of the signature data.
@@ -5224,5 +4896,5 @@
     return ret;
 }
-#endif /* !NO_RSA */
+#endif /* !NO_RSA && WC_RSA_PSS */
 #endif /* !NO_RSA || HAVE_ECC */
 
@@ -5534,4 +5206,7 @@
 }
 
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+     defined(HAVE_ED448)) && \
+    (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH))
 typedef struct Scv13Args {
     byte*  output; /* not allocated */
@@ -5650,5 +5325,5 @@
             }
 
-            if (args->length <= 0) {
+            if (args->length == 0) {
                 ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
             }
@@ -5657,6 +5332,8 @@
             if (ssl->hsType == DYNAMIC_TYPE_RSA)
                 args->sigAlgo = rsa_pss_sa_algo;
+        #ifdef HAVE_ECC
             else if (ssl->hsType == DYNAMIC_TYPE_ECC)
                 args->sigAlgo = ecc_dsa_sa_algo;
+        #endif
         #ifdef HAVE_ED25519
             else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
@@ -5667,4 +5344,7 @@
                 args->sigAlgo = ed448_sa_algo;
         #endif
+            else {
+                ERROR_OUT(ALGO_ID_E, exit_scv);
+            }
             EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify);
 
@@ -5913,5 +5593,7 @@
     return ret;
 }
-
+#endif
+
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
 /* handle processing TLS v1.3 certificate (11) */
 /* Parse and handle a TLS v1.3 Certificate message.
@@ -5954,4 +5636,5 @@
     return ret;
 }
+#endif
 
 #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
@@ -6078,10 +5761,14 @@
             if (args->sigAlgo == ed25519_sa_algo &&
                                                   !ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify");
+                WOLFSSL_MSG("Peer sent ED22519 sig but not ED22519 cert");
+                ret = SIG_VERIFY_E;
+                goto exit_dcv;
             }
         #endif
         #ifdef HAVE_ED448
             if (args->sigAlgo == ed448_sa_algo && !ssl->peerEd448KeyPresent) {
-                WOLFSSL_MSG("Oops, peer sent ED448 key but not in verify");
+                WOLFSSL_MSG("Peer sent ED448 sig but not ED448 cert");
+                ret = SIG_VERIFY_E;
+                goto exit_dcv;
             }
         #endif
@@ -6089,15 +5776,19 @@
             if (args->sigAlgo == ecc_dsa_sa_algo &&
                                                    !ssl->peerEccDsaKeyPresent) {
-                WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+                WOLFSSL_MSG("Peer sent ECC sig but not ECC cert");
+                ret = SIG_VERIFY_E;
+                goto exit_dcv;
             }
         #endif
         #ifndef NO_RSA
             if (args->sigAlgo == rsa_sa_algo) {
-                WOLFSSL_MSG("Oops, peer sent PKCS#1.5 signature");
+                WOLFSSL_MSG("Peer sent PKCS#1.5 algo but not in certificate");
                 ERROR_OUT(INVALID_PARAMETER, exit_dcv);
             }
             if (args->sigAlgo == rsa_pss_sa_algo &&
                          (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
-                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
+                WOLFSSL_MSG("Peer sent RSA sig but not RSA cert");
+                ret = SIG_VERIFY_E;
+                goto exit_dcv;
             }
         #endif
@@ -6261,5 +5952,5 @@
         case TLS_ASYNC_VERIFY:
         {
-        #ifndef NO_RSA
+        #if !defined(NO_RSA) && defined(WC_RSA_PSS)
             if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
                 ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo,
@@ -6271,5 +5962,5 @@
                 ssl->peerRsaKeyPresent = 0;
             }
-        #endif /* !NO_RSA */
+        #endif /* !NO_RSA && WC_RSA_PSS */
 
             /* Advance state and proceed */
@@ -6291,4 +5982,9 @@
             /* Advance state and proceed */
             ssl->options.asyncState = TLS_ASYNC_END;
+
+        #if !defined(NO_WOLFSSL_CLIENT)
+            if (ssl->options.side == WOLFSSL_CLIENT_END)
+                ssl->options.serverState = SERVER_CERT_VERIFY_COMPLETE;
+        #endif
         } /* case TLS_ASYNC_FINALIZE */
 
@@ -6326,4 +6022,5 @@
 }
 #endif /* !NO_RSA || HAVE_ECC */
+#endif /* !NO_CERTS */
 
 /* Parse and handle a TLS v1.3 Finished message.
@@ -6338,5 +6035,5 @@
  * returns 0 on success and otherwise failure.
  */
-static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                            word32 size, word32 totalSz, int sniff)
 {
@@ -6377,17 +6074,20 @@
         secret = ssl->keys.server_write_MAC_secret;
     }
-    else
+    else {
         secret = ssl->keys.client_write_MAC_secret;
-
-    ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
-    if (ret != 0)
-        return ret;
-    if (size != finishedSz)
-        return BUFFER_ERROR;
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
-        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
-    #endif
+    }
+
+    if (sniff == NO_SNIFF) {
+        ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
+        if (ret != 0)
+            return ret;
+        if (size != finishedSz)
+            return BUFFER_ERROR;
+    }
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+    if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+#endif
 
     if (sniff == NO_SNIFF) {
@@ -6433,5 +6133,4 @@
     return 0;
 }
-#endif /* NO_CERTS */
 
 /* Send the TLS v1.3 Finished message.
@@ -6502,11 +6201,4 @@
     if (sendSz < 0)
         return BUILD_MSG_ERROR;
-
-#ifndef NO_SESSION_CACHE
-    if (!ssl->options.resuming && (ssl->options.side == WOLFSSL_SERVER_END ||
-            (ssl->options.side == WOLFSSL_SERVER_END && ssl->arrays != NULL))) {
-        AddSession(ssl);    /* just try */
-    }
-#endif
 
     #ifdef WOLFSSL_CALLBACKS
@@ -6839,8 +6531,6 @@
     word16 length;
     word32 now;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    const byte*  nonce;
-    byte         nonceLength;
-#endif
+    const byte* nonce;
+    byte        nonceLength;
 
     WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO);
@@ -6861,5 +6551,4 @@
     *inOutIdx += SESSION_ADD_SZ;
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Ticket nonce. */
     if ((*inOutIdx - begin) + 1 > size)
@@ -6875,5 +6564,4 @@
     nonce = input + *inOutIdx;
     *inOutIdx += nonceLength;
-#endif
 
     /* Ticket length. */
@@ -6902,9 +6590,7 @@
     ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
     #endif
-#ifndef WOLFSSL_TLS13_DRAFT_18
     ssl->session.ticketNonce.len = nonceLength;
     if (nonceLength > 0)
         XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength);
-#endif
     ssl->session.namedGroup     = ssl->namedGroup;
 
@@ -7002,12 +6688,12 @@
     if (ssl->earlyData != no_early_data) {
         static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 };
-        ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
+        ret = HashRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
         if (ret != 0)
             return ret;
     }
 #endif
-    if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0)
-        return ret;
-    if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0)
+    if ((ret = HashRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashRaw(ssl, mac, finishedSz)) != 0)
         return ret;
 
@@ -7069,5 +6755,4 @@
 #endif
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Start ticket nonce at 0 and go up to 255. */
     if (ssl->session.ticketNonce.len == 0) {
@@ -7077,5 +6762,4 @@
     else
         ssl->session.ticketNonce.data[0]++;
-#endif
 
     if (!ssl->options.noTicketTls13) {
@@ -7099,8 +6783,6 @@
     length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ +
              ssl->session.ticketLen + extSz;
-#ifndef WOLFSSL_TLS13_DRAFT_18
     /* Nonce */
     length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ;
-#endif
     sendSz = idx + length + MAX_MSG_EXTRA;
 
@@ -7123,8 +6805,6 @@
     idx += SESSION_ADD_SZ;
 
-#ifndef WOLFSSL_TLS13_DRAFT_18
     output[idx++] = ssl->session.ticketNonce.len;
     output[idx++] = ssl->session.ticketNonce.data[0];
-#endif
 
     /* length */
@@ -7161,6 +6841,8 @@
     ssl->buffers.outputBuffer.length += sendSz;
 
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
+    /* Always send as this is either directly after server's Finished or only
+     * message after client's Finished.
+     */
+    ret = SendBuffered(ssl);
 
     WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0);
@@ -7212,17 +6894,9 @@
             }
         #endif
-        #ifdef WOLFSSL_TLS13_DRAFT_18
-            if (ssl->msgsReceived.got_server_hello) {
+            if (ssl->msgsReceived.got_server_hello == 1) {
                 WOLFSSL_MSG("Duplicate ServerHello received");
                 return DUPLICATE_MSG_E;
             }
-            ssl->msgsReceived.got_server_hello = 1;
-        #else
-            if (ssl->msgsReceived.got_server_hello == 2) {
-                WOLFSSL_MSG("Duplicate ServerHello received");
-                return DUPLICATE_MSG_E;
-            }
             ssl->msgsReceived.got_server_hello++;
-        #endif
 
             break;
@@ -7273,27 +6947,4 @@
 #endif
 
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    #ifndef NO_WOLFSSL_CLIENT
-        case hello_retry_request:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("HelloRetryRequest received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("HelloRetryRequest received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_hello_retry_request) {
-                WOLFSSL_MSG("Duplicate HelloRetryRequest received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_hello_retry_request = 1;
-
-            break;
-    #endif
-#endif
-
 #ifndef NO_WOLFSSL_CLIENT
         case encrypted_extensions:
@@ -7377,4 +7028,5 @@
             if (ssl->options.serverState ==
                                          SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
+                                                  ssl->arrays != NULL &&
                                                   ssl->arrays->psk_keySz != 0) {
                 WOLFSSL_MSG("CertificateRequset received while using PSK");
@@ -7403,4 +7055,5 @@
                 /* Server's authenticating with PSK must not send this. */
                 if (ssl->options.serverState == SERVER_CERT_COMPLETE &&
+                                                  ssl->arrays != NULL &&
                                                   ssl->arrays->psk_keySz != 0) {
                     WOLFSSL_MSG("CertificateVerify received while using PSK");
@@ -7441,6 +7094,17 @@
                     return OUT_OF_ORDER_E;
                 }
-                if (ssl->options.serverState <
+                /* Must have seen certificate and verify from server except when
+                 * using PSK. */
+            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                if (ssl->arrays != NULL && ssl->arrays->psk_keySz != 0) {
+                    if (ssl->options.serverState !=
                                          SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                        WOLFSSL_MSG("Finished received out of order");
+                        return OUT_OF_ORDER_E;
+                    }
+                }
+                else
+            #endif
+                if (ssl->options.serverState != SERVER_CERT_VERIFY_COMPLETE) {
                     WOLFSSL_MSG("Finished received out of order");
                     return OUT_OF_ORDER_E;
@@ -7450,5 +7114,5 @@
         #ifndef NO_WOLFSSL_SERVER
             if (ssl->options.side == WOLFSSL_SERVER_END) {
-                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                if (ssl->options.serverState != SERVER_FINISHED_COMPLETE) {
                     WOLFSSL_MSG("Finished received out of order");
                     return OUT_OF_ORDER_E;
@@ -7531,5 +7195,5 @@
     if (ssl->options.handShakeState == HANDSHAKE_DONE &&
             type != session_ticket && type != certificate_request &&
-            type != certificate && type != key_update) {
+            type != certificate && type != key_update && type != finished) {
         WOLFSSL_MSG("HandShake message after handshake complete");
         SendAlert(ssl, alert_fatal, unexpected_message);
@@ -7556,11 +7220,4 @@
 #ifndef NO_WOLFSSL_CLIENT
     /* Messages only received by client. */
-    #ifdef WOLFSSL_TLS13_DRAFT_18
-    case hello_retry_request:
-        WOLFSSL_MSG("processing hello retry request");
-        ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size);
-        break;
-    #endif
-
     case server_hello:
         WOLFSSL_MSG("processing server hello");
@@ -7572,5 +7229,5 @@
                                                IsAtLeastTLSv1_3(ssl->version)) {
             ssl->options.cacheMessages = 0;
-            if (ssl->hsHashes->messages != NULL) {
+            if ((ssl->hsHashes != NULL) && (ssl->hsHashes->messages != NULL)) {
                 XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
                 ssl->hsHashes->messages = NULL;
@@ -7614,5 +7271,6 @@
 
     /* Messages received by both client and server. */
-#ifndef NO_CERTS
+#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
+                           !defined(WOLFSSL_NO_CLIENT_AUTH))
     case certificate:
         WOLFSSL_MSG("processing certificate");
@@ -7676,14 +7334,16 @@
 
                 if ((ret = DeriveTls13Keys(ssl, handshake_key,
-                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                                        ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
                     return ret;
                 }
         #ifdef WOLFSSL_EARLY_DATA
-                if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-                    return ret;
-        #else
+                if (ssl->earlyData != no_early_data) {
+                    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                        return ret;
+                }
+                else
+        #endif
                 if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
                     return ret;
-        #endif
             }
 
@@ -7693,11 +7353,11 @@
         #ifdef WOLFSSL_EARLY_DATA
                 if ((ret = DeriveTls13Keys(ssl, traffic_key,
-                                       ENCRYPT_AND_DECRYPT_SIDE,
-                                       ssl->earlyData == no_early_data)) != 0) {
+                                    ENCRYPT_AND_DECRYPT_SIDE,
+                                    ssl->earlyData == no_early_data)) != 0) {
                     return ret;
                 }
         #else
                 if ((ret = DeriveTls13Keys(ssl, traffic_key,
-                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                                        ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
                     return ret;
                 }
@@ -7711,7 +7371,11 @@
                 ssl->options.connectState  = FIRST_REPLY_DONE;
                 ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
-
-                if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS)
-                    ret = POST_HAND_AUTH_ERROR;
+                ssl->options.processReply = 0; /* doProcessInit */
+
+                if (wolfSSL_connect_TLSv13(ssl) != WOLFSSL_SUCCESS) {
+                    ret = ssl->error;
+                    if (ret != WC_PENDING_E)
+                        ret = POST_HAND_AUTH_ERROR;
+                }
             }
         #endif
@@ -7756,10 +7420,11 @@
     int    ret = 0;
     word32 inputLength;
+    byte   type;
+    word32 size = 0;
 
     WOLFSSL_ENTER("DoTls13HandShakeMsg()");
 
     if (ssl->arrays == NULL) {
-        byte   type;
-        word32 size;
+
 
         if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
@@ -7778,6 +7443,4 @@
      * pending message size will be non-zero. */
     if (ssl->arrays->pendingMsgSz == 0) {
-        byte   type;
-        word32 size;
 
         if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
@@ -7879,5 +7542,5 @@
     if (ssl->buffers.outputBuffer.length > 0
     #ifdef WOLFSSL_ASYNC_CRYPT
-        /* do not send buffered or advance state if last error was an 
+        /* do not send buffered or advance state if last error was an
             async pending operation */
         && ssl->error != WC_PENDING_E
@@ -7917,6 +7580,5 @@
     #ifdef WOLFSSL_EARLY_DATA
             if (ssl->earlyData != no_early_data) {
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+        #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
                 if ((ssl->error = SendChangeCipher(ssl)) != 0) {
                     WOLFSSL_ERROR(ssl->error);
@@ -7941,12 +7603,4 @@
             }
 
-            ssl->options.connectState = HELLO_AGAIN;
-            WOLFSSL_MSG("connect state: HELLO_AGAIN");
-            FALL_THROUGH;
-
-        case HELLO_AGAIN:
-            if (ssl->options.certOnly)
-                return WOLFSSL_SUCCESS;
-
             if (!ssl->options.tls1_3) {
     #ifndef WOLFSSL_NO_TLS12
@@ -7954,13 +7608,19 @@
                     return wolfSSL_connect(ssl);
     #endif
-
                 WOLFSSL_MSG("Client using higher version, fatal error");
                 return VERSION_ERROR;
             }
 
+            ssl->options.connectState = HELLO_AGAIN;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN:
+            if (ssl->options.certOnly)
+                return WOLFSSL_SUCCESS;
+
             if (ssl->options.serverState ==
                                           SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+        #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
                 if (!ssl->options.sentChangeCipher) {
                     if ((ssl->error = SendChangeCipher(ssl)) != 0) {
@@ -8011,6 +7671,5 @@
 
         case FIRST_REPLY_FIRST:
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+        #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
             if (!ssl->options.sentChangeCipher) {
                 if ((ssl->error = SendChangeCipher(ssl)) != 0) {
@@ -8043,5 +7702,7 @@
 
         case FIRST_REPLY_THIRD:
-        #ifndef NO_CERTS
+        #if (!defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \
+             defined(HAVE_ED25519) || defined(HAVE_ED448))) && \
+             (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH))
             if (!ssl->options.resuming && ssl->options.sendVerify) {
                 ssl->error = SendTls13CertificateVerify(ssl);
@@ -8172,4 +7833,5 @@
 #endif
 
+#ifdef HAVE_SUPPORTED_CURVES
 /* Create a key share entry from group.
  * Generates a key pair.
@@ -8213,4 +7875,5 @@
     return WOLFSSL_SUCCESS;
 }
+#endif
 
 /* Do not send a ticket after TLS v1.3 handshake for resumption.
@@ -8414,7 +8077,11 @@
         return NOT_READY_ERROR;
 
+#ifdef HAVE_SUPPORTED_CURVES
     /* Return supported groups only. */
     return TLSX_SupportedCurve_Preferred(ssl, 1);
 #else
+    return 0;
+#endif
+#else
     return SIDE_ERROR;
 #endif
@@ -8422,4 +8089,5 @@
 #endif
 
+#if defined(HAVE_SUPPORTED_CURVES)
 /* Sets the key exchange groups in rank order on a context.
  *
@@ -8432,6 +8100,7 @@
 int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count)
 {
-    int i;
-
+    int ret, i;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_set_groups");
     if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
         return BAD_FUNC_ARG;
@@ -8439,6 +8108,16 @@
         return BAD_FUNC_ARG;
 
-    for (i = 0; i < count; i++)
-        ctx->group[i] = (word16)groups[i];
+    ctx->numGroups = 0;
+    TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap);
+    for (i = 0; i < count; i++) {
+        /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups
+         * are valid */
+        if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, groups[i]))
+                != WOLFSSL_SUCCESS) {
+            TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap);
+            return ret;
+        }
+        ctx->group[i] = groups[i];
+    }
     ctx->numGroups = (byte)count;
 
@@ -8456,6 +8135,7 @@
 int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count)
 {
-    int i;
-
+    int ret, i;
+
+    WOLFSSL_ENTER("wolfSSL_set_groups");
     if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
         return BAD_FUNC_ARG;
@@ -8463,10 +8143,21 @@
         return BAD_FUNC_ARG;
 
-    for (i = 0; i < count; i++)
-        ssl->group[i] = (word16)groups[i];
+    ssl->numGroups = 0;
+    TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap);
+    for (i = 0; i < count; i++) {
+        /* Call to wolfSSL_UseSupportedCurve also checks if input groups
+                 * are valid */
+        if ((ret = wolfSSL_UseSupportedCurve(ssl, groups[i]))
+                != WOLFSSL_SUCCESS) {
+            TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap);
+            return ret;
+        }
+        ssl->group[i] = groups[i];
+    }
     ssl->numGroups = (byte)count;
 
     return WOLFSSL_SUCCESS;
 }
+#endif /* HAVE_SUPPORTED_CURVES */
 
 #ifndef NO_PSK
@@ -8607,5 +8298,5 @@
     if (ssl->buffers.outputBuffer.length > 0
     #ifdef WOLFSSL_ASYNC_CRYPT
-        /* do not send buffered or advance state if last error was an 
+        /* do not send buffered or advance state if last error was an
             async pending operation */
         && ssl->error != WC_PENDING_E
@@ -8653,19 +8344,4 @@
 
         case TLS13_ACCEPT_CLIENT_HELLO_DONE :
-#ifdef WOLFSSL_TLS13_DRAFT_18
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
-#else
             if (ssl->options.serverState ==
                                           SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
@@ -8696,5 +8372,4 @@
             WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
             FALL_THROUGH;
-#endif
 
         case TLS13_ACCEPT_FIRST_REPLY_DONE :
@@ -8724,6 +8399,5 @@
 
         case TLS13_SERVER_HELLO_SENT :
-    #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+    #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
             if (!ssl->options.sentChangeCipher) {
                 if ((ssl->error = SendChangeCipher(ssl)) != 0) {
@@ -8740,4 +8414,5 @@
 
         case TLS13_ACCEPT_THIRD_REPLY_DONE :
+#ifdef HAVE_SUPPORTED_CURVES
             if (!ssl->options.noPskDheKe) {
                 ssl->error = TLSX_KeyShare_DeriveSecret(ssl);
@@ -8745,4 +8420,5 @@
                     return WOLFSSL_FATAL_ERROR;
             }
+#endif
 
             if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) {
@@ -8784,5 +8460,6 @@
 
         case TLS13_CERT_SENT :
-#ifndef NO_CERTS
+#if !defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \
+     defined(HAVE_ED25519) || defined(HAVE_ED448))
             if (!ssl->options.resuming && ssl->options.sendVerify) {
                 if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) {
