ssl_client.c: Adapt TLS random generation and writing to TLS 1.2 case

Signed-off-by: Ronald Cron <ronald.cron@arm.com>
diff --git a/library/ssl_client.c b/library/ssl_client.c
index cb9a560..2759de4 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -24,11 +24,21 @@
 #if defined(MBEDTLS_SSL_CLI_C)
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
 
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free      free
+#endif
+
 #include <string.h>
 
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
-#include "mbedtls/platform.h"
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
 
 #include "ssl_client.h"
 #include "ssl_misc.h"
@@ -229,7 +239,23 @@
                                ssl->conf->transport, p );
     p += 2;
 
-    /* Write the random bytes ( random ).*/
+    /* ...
+     * Random random;
+     * ...
+     *
+     * with for TLS 1.2
+     * struct {
+     *     uint32 gmt_unix_time;
+     *     opaque random_bytes[28];
+     * } Random;
+     *
+     * and for TLS 1.3
+     * opaque Random[32];
+     *
+     * The random bytes have been prepared by ssl_prepare_client_hello() into
+     * the ssl->handshake->randbytes buffer and are copied here into the
+     * output buffer.
+     */
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
     memcpy( p, ssl->handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
     MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes",
@@ -345,6 +371,43 @@
     return( 0 );
 }
 
+static int ssl_generate_random( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *randbytes = ssl->handshake->randbytes;
+    size_t gmt_unix_time_len = 0;
+
+    /*
+     * Generate the random bytes
+     *
+     * TLS 1.2 case:
+     * struct {
+     *     uint32 gmt_unix_time;
+     *     opaque random_bytes[28];
+     * } Random;
+     *
+     * TLS 1.3 case:
+     * opaque Random[32];
+     */
+    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    {
+#if defined(MBEDTLS_HAVE_TIME)
+        mbedtls_time_t gmt_unix_time = mbedtls_time( NULL );
+        MBEDTLS_PUT_UINT32_BE( gmt_unix_time, randbytes, 0 );
+        gmt_unix_time_len = 4;
+
+        MBEDTLS_SSL_DEBUG_MSG( 3,
+            ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+               (long long) gmt_unix_time ) );
+#endif /* MBEDTLS_HAVE_TIME */
+    }
+
+    ret = ssl->conf->f_rng( ssl->conf->p_rng,
+                            randbytes + gmt_unix_time_len,
+                            MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len );
+    return( ret );
+}
+
 static int ssl_prepare_client_hello( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -378,12 +441,22 @@
         }
     }
 
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng,
-                                  ssl->handshake->randbytes,
-                                  MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 )
+    /*
+     * But when responding to a verify request where we MUST reuse the
+     * previoulsy generated random bytes (RFC 6347 4.2.1), generate the
+     * random bytes.
+     */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->handshake->cookie == NULL ) )
+#endif
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
-        return( ret );
+        ret = ssl_generate_random( ssl );
+        if( ret != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "Random bytes generation failed", ret );
+            return( ret );
+        }
     }
 
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)