Check return codes from MD in ssl code
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 86267f5..312e2ec 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -2490,60 +2490,11 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
         if( md_alg == MBEDTLS_MD_NONE )
         {
-            mbedtls_md5_context mbedtls_md5;
-            mbedtls_sha1_context mbedtls_sha1;
-
-            mbedtls_md5_init( &mbedtls_md5 );
-
             hashlen = 36;
-
-            /*
-             * digitally-signed struct {
-             *     opaque md5_hash[16];
-             *     opaque sha_hash[20];
-             * };
-             *
-             * md5_hash
-             *     MD5(ClientHello.random + ServerHello.random
-             *                            + ServerParams);
-             * sha_hash
-             *     SHA(ClientHello.random + ServerHello.random
-             *                            + ServerParams);
-             */
-            if( ( ret = mbedtls_md5_starts_ext( &mbedtls_md5 ) ) != 0      ||
-                ( ret = mbedtls_md5_update_ext( &mbedtls_md5,
-                                    ssl->handshake->randbytes, 64 ) ) != 0 ||
-                ( ret = mbedtls_md5_update_ext( &mbedtls_md5, params,
-                                                params_len ) ) != 0        ||
-                ( ret = mbedtls_md5_finish_ext( &mbedtls_md5, hash ) ) != 0 )
-            {
-                mbedtls_md5_free( &mbedtls_md5 );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_*", ret );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+            ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params,
+                                                           params_len );
+            if( ret != 0 )
                 return( ret );
-            }
-
-            mbedtls_md5_free( &mbedtls_md5 );
-
-            mbedtls_sha1_init( &mbedtls_sha1 );
-
-            if( ( ret = mbedtls_sha1_starts_ext( &mbedtls_sha1 ) ) != 0    ||
-                ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1,
-                                    ssl->handshake->randbytes, 64 ) ) != 0 ||
-                ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1, params,
-                                                 params_len ) ) != 0       ||
-                ( ret = mbedtls_sha1_finish_ext( &mbedtls_sha1,
-                                                 hash + 16 ) ) != 0 )
-            {
-                mbedtls_sha1_free( &mbedtls_sha1 );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_*", ret );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-                return( ret );
-            }
-
-            mbedtls_sha1_free( &mbedtls_sha1 );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
@@ -2552,36 +2503,12 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
         if( md_alg != MBEDTLS_MD_NONE )
         {
-            mbedtls_md_context_t ctx;
-            const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-
-            mbedtls_md_init( &ctx );
-
             /* Info from md_alg will be used instead */
             hashlen = 0;
-
-            /*
-             * digitally-signed struct {
-             *     opaque client_random[32];
-             *     opaque server_random[32];
-             *     ServerDHParams params;
-             * };
-             */
-            if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0          ||
-                ( ret = mbedtls_md_starts( &ctx ) ) != 0                     ||
-                ( ret = mbedtls_md_update( &ctx,
-                                    ssl->handshake->randbytes, 64 ) ) != 0   ||
-                ( ret = mbedtls_md_update( &ctx, params, params_len ) ) != 0 ||
-                ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
-            {
-                mbedtls_md_free( &ctx );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_*", ret );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+            ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params,
+                                                          params_len, md_alg );
+            if( ret != 0 )
                 return( ret );
-            }
-
-            mbedtls_md_free( &ctx );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index f08a9bd..ab68715 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -3096,57 +3096,12 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
         if( md_alg == MBEDTLS_MD_NONE )
         {
-            mbedtls_md5_context mbedtls_md5;
-            mbedtls_sha1_context mbedtls_sha1;
-
-            mbedtls_md5_init( &mbedtls_md5 );
-
-            /*
-             * digitally-signed struct {
-             *     opaque md5_hash[16];
-             *     opaque sha_hash[20];
-             * };
-             *
-             * md5_hash
-             *     MD5(ClientHello.random + ServerHello.random
-             *                            + ServerParams);
-             * sha_hash
-             *     SHA(ClientHello.random + ServerHello.random
-             *                            + ServerParams);
-             */
-
-            if( ( ret = mbedtls_md5_starts_ext( &mbedtls_md5 ) ) != 0      ||
-                ( ret = mbedtls_md5_update_ext( &mbedtls_md5,
-                                    ssl->handshake->randbytes, 64 ) ) != 0 ||
-                ( ret = mbedtls_md5_update_ext( &mbedtls_md5, dig_signed,
-                                                dig_signed_len ) ) != 0    ||
-                ( ret = mbedtls_md5_finish_ext( &mbedtls_md5, hash ) ) != 0 )
-            {
-                mbedtls_md5_free( &mbedtls_md5 );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_*", ret );
-                return( ret );
-            }
-
-            mbedtls_md5_free( &mbedtls_md5 );
-
-            mbedtls_sha1_init( &mbedtls_sha1 );
-
-            if( ( ret = mbedtls_sha1_starts_ext( &mbedtls_sha1 ) ) != 0    ||
-                ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1,
-                                    ssl->handshake->randbytes, 64 ) ) != 0 ||
-                ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1, dig_signed,
-                                                 dig_signed_len ) ) != 0   ||
-                ( ret = mbedtls_sha1_finish_ext( &mbedtls_sha1,
-                                                 hash + 16 ) ) != 0 )
-            {
-                mbedtls_sha1_free( &mbedtls_sha1 );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_*", ret );
-                return( ret );
-            }
-
-            mbedtls_sha1_free( &mbedtls_sha1 );
-
             hashlen = 36;
+            ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash,
+                                                           dig_signed,
+                                                           dig_signed_len );
+            if( ret != 0 )
+                return( ret );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
@@ -3155,36 +3110,14 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
         if( md_alg != MBEDTLS_MD_NONE )
         {
-            mbedtls_md_context_t ctx;
-            const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-
-            mbedtls_md_init( &ctx );
-
             /* Info from md_alg will be used instead */
             hashlen = 0;
-
-            /*
-             * digitally-signed struct {
-             *     opaque client_random[32];
-             *     opaque server_random[32];
-             *     ServerDHParams params;
-             * };
-             */
-            if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0          ||
-                ( ret = mbedtls_md_starts( &ctx ) ) != 0                     ||
-                ( ret = mbedtls_md_update( &ctx,
-                                    ssl->handshake->randbytes, 64 ) ) != 0   ||
-                ( ret = mbedtls_md_update( &ctx, dig_signed,
-                                           dig_signed_len ) ) != 0           ||
-                ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
-            {
-                mbedtls_md_free( &ctx );
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_*", ret );
+            ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash,
+                                                          dig_signed,
+                                                          dig_signed_len,
+                                                          md_alg );
+            if( ret != 0 )
                 return( ret );
-            }
-
-
-            mbedtls_md_free( &ctx );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index b04917d..f93537a 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -8043,4 +8043,148 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 }
 
+#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
+    defined(MBEDTLS_SSL_PROTO_TLS1_1)
+int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
+                                        unsigned char *output,
+                                        unsigned char *data, size_t data_len )
+{
+    int ret = 0;
+    mbedtls_md5_context mbedtls_md5;
+    mbedtls_sha1_context mbedtls_sha1;
+
+    mbedtls_md5_init( &mbedtls_md5 );
+    mbedtls_sha1_init( &mbedtls_sha1 );
+
+    /*
+     * digitally-signed struct {
+     *     opaque md5_hash[16];
+     *     opaque sha_hash[20];
+     * };
+     *
+     * md5_hash
+     *     MD5(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     * sha_hash
+     *     SHA(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     */
+    if( ( ret = mbedtls_md5_starts_ext( &mbedtls_md5 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md5_update_ext( &mbedtls_md5,
+                                        ssl->handshake->randbytes, 64 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md5_update_ext( &mbedtls_md5, data, data_len ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md5_finish_ext( &mbedtls_md5, output ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ext", ret );
+        goto exit;
+    }
+
+    if( ( ret = mbedtls_sha1_starts_ext( &mbedtls_sha1 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1,
+                                         ssl->handshake->randbytes, 64 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_sha1_update_ext( &mbedtls_sha1, data,
+                                         data_len ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ext", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_sha1_finish_ext( &mbedtls_sha1,
+                                         output + 16 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ext", ret );
+        goto exit;
+    }
+
+exit:
+    mbedtls_md5_free( &mbedtls_md5 );
+    mbedtls_sha1_free( &mbedtls_sha1 );
+
+    if( ret != 0 )
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+
+    return( ret );
+
+}
+#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
+          MBEDTLS_SSL_PROTO_TLS1_1 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2)
+int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
+                                       unsigned char *output,
+                                       unsigned char *data, size_t data_len,
+                                       mbedtls_md_type_t md_alg )
+{
+    int ret = 0;
+    mbedtls_md_context_t ctx;
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
+
+    mbedtls_md_init( &ctx );
+
+    /*
+     * digitally-signed struct {
+     *     opaque client_random[32];
+     *     opaque server_random[32];
+     *     ServerDHParams params;
+     * };
+     */
+    if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
+        goto exit;
+    }
+    if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret );
+        goto exit;
+    }
+
+exit:
+    mbedtls_md_free( &ctx );
+
+    if( ret != 0 )
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+
+    return( ret );
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
+          MBEDTLS_SSL_PROTO_TLS1_2 */
+
 #endif /* MBEDTLS_SSL_TLS_C */