Add client-side support for ECDH key exchanges
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 0f9a731..76c943d 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1115,6 +1115,29 @@
 
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_check_server_ecdh_params( const ssl_context *ssl )
+{
+    SSL_DEBUG_MSG( 2, ( "ECDH curve size: %d",
+                        (int) ssl->handshake->ecdh_ctx.grp.nbits ) );
+
+    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
+        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
+    {
+        return( -1 );
+    }
+
+    SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
+
+    return( 0 );
+}
+#endif
+
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
 static int ssl_parse_server_ecdh_params( ssl_context *ssl,
                                          unsigned char **p,
@@ -1137,18 +1160,12 @@
         return( ret );
     }
 
-    SSL_DEBUG_MSG( 2, ( "ECDH curve size: %d",
-                        (int) ssl->handshake->ecdh_ctx.grp.nbits ) );
-
-    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
-        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
     {
         SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDH length)" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
-    SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
-
     return( ret );
 }
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@@ -1307,6 +1324,41 @@
           POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_get_ecdh_params_from_cert( ssl_context *ssl )
+{
+    int ret;
+    const ecp_keypair *peer_key;
+
+    if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                     POLARSSL_PK_ECKEY ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    peer_key = pk_ec( ssl->session_negotiate->peer_cert->pk );
+
+    if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
+                                 POLARSSL_ECDH_THEIRS ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret );
+        return( ret );
+    }
+
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH length)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
 static int ssl_parse_server_key_exchange( ssl_context *ssl )
 {
     int ret;
@@ -1335,6 +1387,21 @@
     ((void) end);
 #endif
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        ssl_get_ecdh_params_from_cert( ssl );
+
+        SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+    ((void) p);
+    ((void) end);
+#endif
+
     if( ( ret = ssl_read_record( ssl ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "ssl_read_record", ret );
@@ -1852,9 +1919,13 @@
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
     {
         /*
          * ECDH key exchange -- send client public value
@@ -1887,7 +1958,9 @@
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||