Create MBEDTLS_SSL_KEYING_MATERIAL_EXPORT option

Add the option MBEDTLS_SSL_KEYING_MATERIAL_EXPORT to mbedtls_config.h
to control if the function mbedtls_ssl_export_keying_material() should
be available. By default, the option is disabled.

This is because the exporter for TLS 1.2 requires client_random and
server_random need to be stored after the handshake is complete.

Signed-off-by: Max Fillinger <max@max-fillinger.net>
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 2dc475b..ca1486d 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -737,6 +737,20 @@
  */
 //#define MBEDTLS_SSL_RECORD_SIZE_LIMIT
 
+/*
+ * \def MBEDTLS_SSL_KEYING_MATERIAL_EXPORT
+ *
+ * When this option is enabled, the client and server can extract additional
+ * shared symmetric keys after an SSL handshake using the function
+ * mbedtls_ssl_export_keying_material().
+ *
+ * The process for deriving the keys is specified in RFC 5705 for TLS 1.2 and
+ * in RFC 8446, Section 7.5, for TLS 1.3.
+ *
+ * Uncomment this macro to enable mbedtls_ssl_export_keying_material().
+ */
+//#define MBEDTLS_SSL_KEYING_MATERIAL_EXPORT
+
 /**
  * \def MBEDTLS_SSL_RENEGOTIATION
  *
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 9ded4e6..8383ead 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -676,6 +676,14 @@
 /* Length in number of bytes of the TLS sequence number */
 #define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8
 
+/* Helper to state that client_random and server_random need to be stored
+ * after the handshake is complete. This is required for context serialization
+ * and for the keying material exporter in TLS 1.2. */
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || \
+    (defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) && defined(MBEDTLS_SSL_PROTO_TLS1_2))
+#define MBEDTLS_SSL_KEEP_RANDBYTES
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -5407,7 +5415,7 @@
  *
  * \return            0 on success. An SSL specific error on failure.
  */
- #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
 int mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl,
                                        uint8_t *out, const size_t key_len,
                                        const char *label, const size_t label_len,
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index e51a3df..596e7bc 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -1118,10 +1118,11 @@
     unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+#if defined(MBEDTLS_SSL_KEEP_RANDBYTES)
     /* We need the Hello random bytes in order to re-derive keys from the
-     * Master Secret and other session info,
-     * see ssl_tls12_populate_transform() */
+     * Master Secret and other session info and for the keying material
+     * exporter in TLS 1.2.
+     * See ssl_tls12_populate_transform() */
     unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN +
                             MBEDTLS_CLIENT_HELLO_RANDOM_LEN];
     /*!< ServerHello.random+ClientHello.random */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index e4450b6..c20a68d 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -7746,7 +7746,7 @@
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
     transform->tls_version = tls_version;
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+#if defined(MBEDTLS_SSL_KEEP_RANDBYTES)
     memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes));
 #endif
 
@@ -8930,8 +8930,7 @@
 }
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 static int mbedtls_ssl_tls12_export_keying_material(const mbedtls_ssl_context *ssl,
@@ -9052,6 +9051,6 @@
     }
 }
 
-#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) */
+#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */
 
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 9e38f69..061096b 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -336,11 +336,7 @@
     "                        in the form of base64 code (serialize option\n"   \
     "                        must be set)\n"                                   \
     "                         default: \"\" (do nothing)\n"                    \
-    "                         option: a file path\n" \
-    "    exp_label=%%s       Label to input into TLS-Exporter\n" \
-    "                         default: None (don't try to export a key)\n" \
-    "    exp_len=%%d         Length of key to extract from TLS-Exporter \n" \
-    "                         default: 20\n"
+    "                         option: a file path\n"
 #else
 #define USAGE_SERIALIZATION ""
 #endif
@@ -370,6 +366,16 @@
 #define USAGE_TLS1_3_KEY_EXCHANGE_MODES ""
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
+#define USAGE_EXPORT \
+    "    exp_label=%%s       Label to input into TLS-Exporter\n" \
+    "                         default: None (don't try to export a key)\n" \
+    "    exp_len=%%d         Length of key to extract from TLS-Exporter \n" \
+    "                         default: 20\n"
+#else
+#define USAGE_EXPORT ""
+#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */
+
 /* USAGE is arbitrarily split to stay under the portable string literal
  * length limit: 4095 bytes in C99. */
 #define USAGE1 \
@@ -456,6 +462,7 @@
     "                                otherwise. The expansion of the macro\n" \
     "                                is printed if it is defined\n"           \
     USAGE_SERIALIZATION                                                       \
+    USAGE_EXPORT                                                              \
     "\n"
 
 /*
@@ -2499,7 +2506,7 @@
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
     if (opt.exp_label != NULL && opt.exp_len > 0) {
         unsigned char *exported_key = calloc((size_t) opt.exp_len, sizeof(unsigned int));
         if (exported_key == NULL) {
@@ -2522,7 +2529,7 @@
         mbedtls_printf("\n\n");
         fflush(stdout);
     }
-#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) */
+#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */
 
     /*
      * 6. Write the GET request
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 9eab6cd..5186006 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -471,13 +471,19 @@
     "                        in the form of base64 code (serialize option\n"   \
     "                        must be set)\n"                                   \
     "                         default: \"\" (do nothing)\n"                    \
-    "                         option: a file path\n" \
+    "                         option: a file path\n"
+#else
+#define USAGE_SERIALIZATION ""
+#endif
+
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
+#define USAGE_EXPORT \
     "    exp_label=%%s       Label to input into TLS-Exporter\n" \
     "                         default: None (don't try to export a key)\n" \
     "    exp_len=%%d         Length of key to extract from TLS-Exporter \n" \
     "                         default: 20\n"
 #else
-#define USAGE_SERIALIZATION ""
+#define USAGE_EXPORT ""
 #endif
 
 #define USAGE_KEY_OPAQUE_ALGS \
@@ -587,6 +593,7 @@
     "                                otherwise. The expansion of the macro\n" \
     "                                is printed if it is defined\n"           \
     USAGE_SERIALIZATION                                                       \
+    USAGE_EXPORT                                                              \
     "\n"
 
 #define PUT_UINT64_BE(out_be, in_le, i)                                   \
@@ -3619,7 +3626,7 @@
         mbedtls_printf("\n");
     }
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)
     if (opt.exp_label != NULL && opt.exp_len > 0) {
         unsigned char *exported_key = calloc((size_t) opt.exp_len, sizeof(unsigned int));
         if (exported_key == NULL) {
@@ -3642,7 +3649,7 @@
         mbedtls_printf("\n\n");
         fflush(stdout);
     }
-#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALZIATION) */
+#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
     else if (opt.use_srtp != 0) {