Merge branch 'profiles' into development

* profiles:
  Update Changelog for the profiles branch
  Add SSL presets.
  Implement sig_hashes
  Create API for mbedtls_ssl_conf_sig_hashes().
  Small internal changes in curve checking
  Extra check in verify_with_profile()
  Clarify a point in the documentation
  Fix define for ssl_conf_curves()
  Add mbedtls_ssl_conf_cert_profile()
  Implement cert profile checking
  Change data structure of profiles to bitfields
  Add pre-defined profiles for cert verification
  Create cert profile API (unimplemented yet)
  Remove duplicated tests for x509_verify_info()
  Add tests for dhm_min_bitlen
  Add dhmlen option in ssl_client2.c
  Add ssl_conf_dhm_min_bitlen()
diff --git a/ChangeLog b/ChangeLog
index 1d995c8..8c183a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,8 +9,12 @@
      ability to override the whole module.
    * New server-side implementation of session tickets that rotate keys to
      preserve forward secrecy, and allows sharing across multiple contexts.
-   * Reduced ROM fooprint of SHA-256 and added an option to reduce it even
-     more (at the expense of performance) MBEDTLS_SHA256_SMALLER.
+   * Added a concept of X.509 cerificate verification profile that controls
+     which algorithms and key sizes (curves for ECDSA) are acceptable.
+   * Expanded configurability of security parameters in the SSL module with
+     mbedtls_ssl_conf_dhm_min_bitlen() and mbedtls_ssl_conf_sig_hashes().
+   * Introduced a concept of presets for SSL security-relevant configuration
+     parameters.
 
 API Changes
    * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace.
@@ -129,6 +133,8 @@
      enabled in the default configuration, this is only noticeable if using a
      custom config.h
    * Default DHM parameters server-side upgraded from 1024 to 2048 bits.
+   * A minimum RSA key size of 2048 bits is now enforced during ceritificate
+     chain verification.
    * Negotiation of truncated HMAC is now disabled by default on server too.
    * The following functions are now case-sensitive:
      mbedtls_cipher_info_from_string()
@@ -157,6 +163,8 @@
 Changes
    * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now
      thread-safe if MBEDTLS_THREADING_C is enabled.
+   * Reduced ROM fooprint of SHA-256 and added an option to reduce it even
+     more (at the expense of performance) MBEDTLS_SHA256_SMALLER.
 
 = mbed TLS 1.3 branch
 
diff --git a/include/mbedtls/compat-1.3.h b/include/mbedtls/compat-1.3.h
index 8a3ab96..0af0a9e 100644
--- a/include/mbedtls/compat-1.3.h
+++ b/include/mbedtls/compat-1.3.h
@@ -585,9 +585,6 @@
 #if defined MBEDTLS_SSL_SESSION_TICKETS
 #define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS
 #endif
-#if defined MBEDTLS_SSL_SET_CURVES
-#define POLARSSL_SSL_SET_CURVES MBEDTLS_SSL_SET_CURVES
-#endif
 #if defined MBEDTLS_SSL_SRV_C
 #define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C
 #endif
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index f0d293c..02dd969 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1155,20 +1155,6 @@
 #define MBEDTLS_SSL_TRUNCATED_HMAC
 
 /**
- * \def MBEDTLS_SSL_SET_CURVES
- *
- * Enable mbedtls_ssl_conf_curves().
- *
- * This is disabled by default since it breaks binary compatibility with the
- * 1.3.x line. If you choose to enable it, you will need to rebuild your
- * application against the new header files, relinking will not be enough.
- * It will be enabled by default, or no longer an option, in the 1.4 branch.
- *
- * Uncomment to make mbedtls_ssl_conf_curves() available.
- */
-//#define MBEDTLS_SSL_SET_CURVES
-
-/**
  * \def MBEDTLS_THREADING_ALT
  *
  * Provide your own alternate threading implementation.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index fdd3595..c754b9b 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -70,6 +70,12 @@
 #define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED
 #endif
 
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED
+#endif
+
 /*
  * SSL Error codes
  */
@@ -190,6 +196,9 @@
 #define MBEDTLS_SSL_ARC4_ENABLED                0
 #define MBEDTLS_SSL_ARC4_DISABLED               1
 
+#define MBEDTLS_SSL_PRESET_DEFAULT              0
+#define MBEDTLS_SSL_PRESET_SUITEB               2
+
 /*
  * Default range for DTLS retransmission timer value, in milliseconds.
  * RFC 6347 4.2.4.1 says from 1 second to 60 seconds.
@@ -529,12 +538,17 @@
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
+    const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */
     mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s)        */
     mbedtls_x509_crt *ca_chain;     /*!< trusted CAs                        */
     mbedtls_x509_crl *ca_crl;       /*!< trusted CAs CRLs                   */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+    const int *sig_hashes;          /*!< allowed signature hashes           */
+#endif
+
+#if defined(MBEDTLS_ECP_C)
     const mbedtls_ecp_group_id *curve_list; /*!< allowed curves             */
 #endif
 
@@ -577,6 +591,10 @@
     unsigned int badmac_limit;      /*!< limit of records with a bad MAC    */
 #endif
 
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+    unsigned int dhm_min_bitlen;    /*!< min. bit length of the DHM prime   */
+#endif
+
     unsigned char max_major_ver;    /*!< max. major version used            */
     unsigned char max_minor_ver;    /*!< max. minor version used            */
     unsigned char min_major_ver;    /*!< min. major version used            */
@@ -1348,6 +1366,15 @@
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
+ * \brief          Set the X.509 security profile used for verification
+ *
+ * \param conf     SSL configuration
+ * \param profile  Profile to use
+ */
+void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
+                                    mbedtls_x509_crt_profile *profile );
+
+/**
  * \brief          Set the data required to verify peer certificate
  *
  * \param conf     SSL configuration
@@ -1477,7 +1504,20 @@
 int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx );
 #endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+/**
+ * \brief          Set the minimum length for Diffie-Hellman parameters.
+ *                 (Client-side only.)
+ *                 (Default: 1024 bits.)
+ *
+ * \param conf     SSL configuration
+ * \param bitlen   Minimum bit length of the DHM prime
+ */
+void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf,
+                                      unsigned int bitlen );
+#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_ECP_C)
 /**
  * \brief          Set the allowed curves in order of preference.
  *                 (Default: all defined curves.)
@@ -1490,14 +1530,49 @@
  *                 use. The server can override our preference order.
  *
  *                 Both sides: limits the set of curves used by peer to the
- *                 listed curves for any use (ECDH(E), certificates).
+ *                 listed curves for any use ECDHE and the end-entity
+ *                 certificate.
+ *
+ * \note           This has no influence on which curve are allowed inside the
+ *                 certificate chains, see \c mbedtls_ssl_conf_cert_profile()
+ *                 for that. For example, if the peer's certificate chain is
+ *                 EE -> CA_int -> CA_root, then the allowed curves for EE are
+ *                 controlled by \c mbedtls_ssl_conf_curves() but for CA_int
+ *                 and CA_root it's \c mbedtls_ssl_conf_cert_profile().
+ *
+ * \note           This list should be ordered by decreasing preference
+ *                 (preferred curve first).
  *
  * \param conf     SSL configuration
  * \param curves   Ordered list of allowed curves,
  *                 terminated by MBEDTLS_ECP_DP_NONE.
  */
-void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curves );
-#endif /* MBEDTLS_SSL_SET_CURVES */
+void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
+                              const mbedtls_ecp_group_id *curves );
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+/**
+ * \brief          Set the allowed hashes for signatures during the handshake.
+ *                 (Default: all available hashes.)
+ *
+ * \note           This only affects which hashes are offered and can be used
+ *                 for signatures during the handshake. Hashes for message
+ *                 authentication and the TLS PRF are controlled by the
+ *                 ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes
+ *                 used for certificate signature are controlled by the
+ *                 verification profile, see \c mbedtls_ssl_conf_cert_profile().
+ *
+ * \note           This list should be ordered by decreasing preference
+ *                 (preferred hash first).
+ *
+ * \param conf     SSL configuration
+ * \param hashes   Ordered list of allowed signature hashes,
+ *                 terminated by \c MBEDTLS_MD_NONE.
+ */
+void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
+                                  const int *hashes );
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
@@ -2093,6 +2168,8 @@
  * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER
  * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or
  *                  MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS
+ * \param preset   a MBEDTLS_SSL_PRESET_XXX value
+ *                 (currently unused).
  *
  * \note           See \c mbedtls_ssl_conf_transport() for notes on DTLS.
  *
@@ -2100,7 +2177,7 @@
  *                 MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error.
  */
 int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
-                                 int endpoint, int transport );
+                                 int endpoint, int transport, int preset );
 
 /**
  * \brief          Free an SSL configuration context
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 122c1ee..391ce5b 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -374,9 +374,15 @@
 #endif
 
 mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash );
+unsigned char mbedtls_ssl_hash_from_md_alg( int md );
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
-int mbedtls_ssl_curve_is_acceptable( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
+#if defined(MBEDTLS_ECP_C)
+int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
+                                mbedtls_md_type_t md );
 #endif
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index 7cb0d46..597053c 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -97,6 +97,13 @@
 #define MBEDTLS_X509_BADCERT_KEY_USAGE         0x0800  /**< Usage does not match the keyUsage extension. */
 #define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE     0x1000  /**< Usage does not match the extendedKeyUsage extension. */
 #define MBEDTLS_X509_BADCERT_NS_CERT_TYPE      0x2000  /**< Usage does not match the nsCertType extension. */
+#define MBEDTLS_X509_BADCERT_BAD_MD            0x4000  /**< The certificate is signed with an unacceptable hash. */
+#define MBEDTLS_X509_BADCERT_BAD_PK            0x8000  /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */
+#define MBEDTLS_X509_BADCERT_BAD_KEY         0x010000  /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */
+#define MBEDTLS_X509_BADCRL_BAD_MD           0x020000  /**< The CRL is signed with an unacceptable hash. */
+#define MBEDTLS_X509_BADCRL_BAD_PK           0x040000  /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */
+#define MBEDTLS_X509_BADCRL_BAD_KEY          0x080000  /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */
+
 /* \} name */
 /* \} addtogroup x509_module */
 
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 8aabfde..9f4160f 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -94,6 +94,26 @@
 }
 mbedtls_x509_crt;
 
+/**
+ * Build flag from an algorithm/curve identifier (pk, md, ecp)
+ * Since 0 is always XXX_NONE, ignore it.
+ */
+#define MBEDTLS_X509_ID_FLAG( id )   ( 1 << ( id - 1 ) )
+
+/**
+ * Security profile for certificate verification.
+ *
+ * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG().
+ */
+typedef struct
+{
+    uint32_t allowed_mds;       /**< MDs for signatures         */
+    uint32_t allowed_pks;       /**< PK algs for signatures     */
+    uint32_t allowed_curves;    /**< Elliptic curves for ECDSA  */
+    uint32_t rsa_min_bitlen;    /**< Minimum size for RSA keys  */
+}
+mbedtls_x509_crt_profile;
+
 #define MBEDTLS_X509_CRT_VERSION_1              0
 #define MBEDTLS_X509_CRT_VERSION_2              1
 #define MBEDTLS_X509_CRT_VERSION_3              2
@@ -121,6 +141,23 @@
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
+ * Default security profile. Should provide a good balance between security
+ * and compatibility with current deployments.
+ */
+extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default;
+
+/**
+ * Expected next default profile. Recommended for new deployments.
+ * Currently targets a 128-bit security level, except for RSA-2048.
+ */
+extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next;
+
+/**
+ * NSA Suite B profile.
+ */
+extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb;
+
+/**
  * \brief          Parse a single DER formatted certificate and add it
  *                 to the chained list.
  *
@@ -232,6 +269,9 @@
  * \note           In case verification failed, the results can be displayed
  *                 using \c mbedtls_x509_crt_verify_info()
  *
+ * \note           Same as \c mbedtls_x509_crt_verify_with_profile() with the
+ *                 default security profile.
+ *
  * \param crt      a certificate to be verified
  * \param trust_ca the trusted CA chain
  * \param ca_crl   the CRL chain for trusted CA's
@@ -255,6 +295,41 @@
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy );
 
+/**
+ * \brief          Verify the certificate signature according to profile
+ *
+ * \note           Same as \c mbedtls_x509_crt_verify(), but with explicit
+ *                 security profile.
+ *
+ * \note           The restrictions on keys (RSA minimum size, allowed curves
+ *                 for ECDSA) only applys to (intermediate) CAs, not to the
+ *                 end-entity certificate.
+ *
+ * \param crt      a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param ca_crl   the CRL chain for trusted CA's
+ * \param profile  security profile for verification
+ * \param cn       expected Common Name (can be set to
+ *                 NULL if the CN must not be verified)
+ * \param flags    result of the verification
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ *
+ * \return         0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED
+ *                 in which case *flags will have one or more
+ *                 MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags
+ *                 set,
+ *                 or another error in case of a fatal error encountered
+ *                 during the verification process.
+ */
+int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
+                     mbedtls_x509_crt *trust_ca,
+                     mbedtls_x509_crl *ca_crl,
+                     const mbedtls_x509_crt_profile *profile,
+                     const char *cn, uint32_t *flags,
+                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy );
+
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
 /**
  * \brief          Check usage of certificate against keyUsage extension.
diff --git a/library/ecp.c b/library/ecp.c
index 31197ce..b733bcc 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -124,6 +124,8 @@
  *
  * Curves are listed in order: largest curves first, and for a given size,
  * fastest curves first. This provides the default order for the SSL module.
+ *
+ * Reminder: update profiles in x509_crt.c when adding a new curves!
  */
 static const mbedtls_ecp_curve_info ecp_supported_curves[] =
 {
diff --git a/library/md.c b/library/md.c
index 381ffc4..1d6191f 100644
--- a/library/md.c
+++ b/library/md.c
@@ -54,6 +54,9 @@
     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
 }
 
+/*
+ * Reminder: update profiles in x509_crt.c when adding a new hash!
+ */
 static const int supported_digests[] = {
 
 #if defined(MBEDTLS_SHA512_C)
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 6eb190c..e2c2d3f 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -156,6 +156,7 @@
 {
     unsigned char *p = buf;
     size_t sig_alg_len = 0;
+    const int *md;
 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
     unsigned char *sig_alg_list = buf + 6;
 #endif
@@ -170,55 +171,22 @@
     /*
      * Prepare signature_algorithms extension (TLS 1.2)
      */
-#if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_SHA512_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA512;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA384;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA256;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA224;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#if defined(MBEDTLS_SHA1_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA1;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#if defined(MBEDTLS_MD5_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_MD5;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#endif /* MBEDTLS_RSA_C */
+    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
+    {
 #if defined(MBEDTLS_ECDSA_C)
-#if defined(MBEDTLS_SHA512_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA512;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA384;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
+        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
+        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
 #endif
-#if defined(MBEDTLS_SHA256_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA256;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA224;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
+#if defined(MBEDTLS_RSA_C)
+        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
+        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
 #endif
-#if defined(MBEDTLS_SHA1_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA1;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
-#if defined(MBEDTLS_MD5_C)
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_MD5;
-    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
-#endif /* MBEDTLS_ECDSA_C */
+    }
 
     /*
      * enum {
-     *     none(0), mbedtls_md5(1), mbedtls_sha1(2), sha224(3), mbedtls_sha256(4), sha384(5),
-     *     mbedtls_sha512(6), (255)
+     *     none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+     *     sha512(6), (255)
      * } HashAlgorithm;
      *
      * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
@@ -255,7 +223,7 @@
     unsigned char *elliptic_curve_list = p + 6;
     size_t elliptic_curve_len = 0;
     const mbedtls_ecp_curve_info *info;
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_ECP_C)
     const mbedtls_ecp_group_id *grp_id;
 #else
     ((void) ssl);
@@ -265,7 +233,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_ECP_C)
     for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
     {
         info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
@@ -1648,10 +1616,11 @@
         return( ret );
     }
 
-    if( ssl->handshake->dhm_ctx.len < 64  ||
-        ssl->handshake->dhm_ctx.len > 512 )
+    if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (DHM length)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
+                                    ssl->handshake->dhm_ctx.len * 8,
+                                    ssl->conf->dhm_min_bitlen ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
@@ -1682,8 +1651,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
-    if( ! mbedtls_ssl_curve_is_acceptable( ssl, ssl->handshake->ecdh_ctx.grp.id ) )
+#if defined(MBEDTLS_ECP_C)
+    if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 )
 #else
     if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
         ssl->handshake->ecdh_ctx.grp.nbits > 521 )
@@ -1835,9 +1804,7 @@
           MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
 static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
                                           unsigned char **p,
                                           unsigned char *end,
@@ -1877,18 +1844,25 @@
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
+    /*
+     * Check if the hash is acceptable
+     */
+    if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "server used HashAlgorithm "
+                                    "that was not offered" ) );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) );
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) );
     *p += 2;
 
     return( 0 );
 }
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 7db5a3c..457362f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -211,7 +211,7 @@
      *
      * So, just look at the HashAlgorithm part.
      */
-    for( md_cur = mbedtls_md_list(); *md_cur != MBEDTLS_MD_NONE; md_cur++ ) {
+    for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) {
         for( p = buf + 2; p < end; p += 2 ) {
             if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) {
                 ssl->handshake->sig_alg = p[0];
@@ -2641,7 +2641,7 @@
          * } ServerECDHParams;
          */
         const mbedtls_ecp_curve_info **curve = NULL;
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_ECP_C)
         const mbedtls_ecp_group_id *gid;
 
         /* Match our preference list against the offered curves */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index ee32502..48dfd04 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4064,10 +4064,13 @@
         /*
          * Main check: verify certificate
          */
-        ret = mbedtls_x509_crt_verify( ssl->session_negotiate->peer_cert,
-                               ca_chain, ca_crl, ssl->hostname,
-                              &ssl->session_negotiate->verify_result,
-                               ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+        ret = mbedtls_x509_crt_verify_with_profile(
+                                ssl->session_negotiate->peer_cert,
+                                ca_chain, ca_crl,
+                                ssl->conf->cert_profile,
+                                ssl->hostname,
+                               &ssl->session_negotiate->verify_result,
+                                ssl->conf->f_vrfy, ssl->conf->p_vrfy );
 
         if( ret != 0 )
         {
@@ -4078,20 +4081,20 @@
          * Secondary checks: always done, but change 'ret' only if it was 0
          */
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_ECP_C)
         {
             const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
 
             /* If certificate uses an EC key, make sure the curve is OK */
             if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
-                ! mbedtls_ssl_curve_is_acceptable( ssl, mbedtls_pk_ec( *pk )->grp.id ) )
+                mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
                 if( ret == 0 )
                     ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
             }
         }
-#endif /* MBEDTLS_SSL_SET_CURVES */
+#endif /* MBEDTLS_ECP_C */
 
         if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
                                   ciphersuite_info,
@@ -5292,6 +5295,12 @@
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
+void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
+                                    mbedtls_x509_crt_profile *profile )
+{
+    conf->cert_profile = profile;
+}
+
 /* Append a new keycert entry to a (possibly empty) list */
 static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
                                 mbedtls_x509_crt *cert,
@@ -5458,7 +5467,29 @@
 }
 #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+/*
+ * Set the minimum length for Diffie-Hellman parameters
+ */
+void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf,
+                                      unsigned int bitlen )
+{
+    conf->dhm_min_bitlen = bitlen;
+}
+#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+/*
+ * Set allowed/preferred hashes for handshake signatures
+ */
+void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
+                                  const int *hashes )
+{
+    conf->sig_hashes = hashes;
+}
+#endif
+
+#if defined(MBEDTLS_ECP_C)
 /*
  * Set the allowed elliptic curves
  */
@@ -6581,11 +6612,33 @@
     memset( conf, 0, sizeof( mbedtls_ssl_config ) );
 }
 
+static int ssl_preset_suiteb_ciphersuites[] = {
+    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    0
+};
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+static int ssl_preset_suiteb_hashes[] = {
+    MBEDTLS_MD_SHA256,
+    MBEDTLS_MD_SHA384,
+    MBEDTLS_MD_NONE
+};
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = {
+    MBEDTLS_ECP_DP_SECP256R1,
+    MBEDTLS_ECP_DP_SECP384R1,
+    MBEDTLS_ECP_DP_NONE
+};
+#endif
+
 /*
  * Load default in mbetls_ssl_config
  */
 int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
-                                 int endpoint, int transport )
+                                 int endpoint, int transport, int preset )
 {
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
     int ret;
@@ -6596,19 +6649,9 @@
     mbedtls_ssl_conf_endpoint( conf, endpoint );
     mbedtls_ssl_conf_transport( conf, transport );
 
-    conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
-    conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */
-    conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION;
-    conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /* DTLS starts with TLS 1.1 */
-        conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2;
-    }
-#endif
-
+    /*
+     * Things that are common to all presets
+     */
 #if defined(MBEDTLS_SSL_CLI_C)
     if( endpoint == MBEDTLS_SSL_IS_CLIENT )
     {
@@ -6619,12 +6662,6 @@
     }
 #endif
 
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
-                           mbedtls_ssl_list_ciphersuites();
-
 #if defined(MBEDTLS_ARC4_C)
     conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED;
 #endif
@@ -6641,10 +6678,6 @@
     conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED;
 #endif
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
-    conf->curve_list = mbedtls_ecp_grp_id_list( );
-#endif
-
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
     conf->f_cookie_write = ssl_cookie_write_dummy;
     conf->f_cookie_check = ssl_cookie_check_dummy;
@@ -6666,17 +6699,86 @@
 #endif
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-    if( endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
-        if( ( ret = mbedtls_ssl_conf_dh_param( conf,
-                        MBEDTLS_DHM_RFC5114_MODP_2048_P,
-                        MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 )
-        {
-            return( ret );
-        }
-    }
+            if( endpoint == MBEDTLS_SSL_IS_SERVER )
+            {
+                if( ( ret = mbedtls_ssl_conf_dh_param( conf,
+                                MBEDTLS_DHM_RFC5114_MODP_2048_P,
+                                MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 )
+                {
+                    return( ret );
+                }
+            }
 #endif
 
+    /*
+     * Preset-specific defaults
+     */
+    switch( preset )
+    {
+        /*
+         * NSA Suite B
+         */
+        case MBEDTLS_SSL_PRESET_SUITEB:
+            conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+            conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
+            conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION;
+            conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION;
+
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
+                                   ssl_preset_suiteb_ciphersuites;
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+            conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+            conf->sig_hashes = ssl_preset_suiteb_hashes;
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+            conf->curve_list = ssl_preset_suiteb_curves;
+#endif
+
+        /*
+         * Default
+         */
+        default:
+            conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+            conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */
+            conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION;
+            conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+            if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+                conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2;
+#endif
+
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
+            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
+                                   mbedtls_ssl_list_ciphersuites();
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+            conf->cert_profile = &mbedtls_x509_crt_profile_default;
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+            conf->sig_hashes = mbedtls_md_list();
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+            conf->curve_list = mbedtls_ecp_grp_id_list();
+#endif
+
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+            conf->dhm_min_bitlen = 1024;
+#endif
+    }
+
     return( 0 );
 }
 
@@ -6745,7 +6847,7 @@
 #endif /* MBEDTLS_PK_C */
 
 /*
- * Convert between SSL_HASH_XXX and MBEDTLS_MD_XXX
+ * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX
  */
 mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash )
 {
@@ -6776,22 +6878,78 @@
     }
 }
 
-#if defined(MBEDTLS_SSL_SET_CURVES)
 /*
- * Check is a curve proposed by the peer is in our list.
- * Return 1 if we're willing to use it, 0 otherwise.
+ * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX
  */
-int mbedtls_ssl_curve_is_acceptable( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id )
+unsigned char mbedtls_ssl_hash_from_md_alg( int md )
+{
+    switch( md )
+    {
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( MBEDTLS_SSL_HASH_MD5 );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( MBEDTLS_SSL_HASH_SHA1 );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( MBEDTLS_SSL_HASH_SHA224 );
+        case MBEDTLS_MD_SHA256:
+            return( MBEDTLS_SSL_HASH_SHA256 );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( MBEDTLS_SSL_HASH_SHA384 );
+        case MBEDTLS_MD_SHA512:
+            return( MBEDTLS_SSL_HASH_SHA512 );
+#endif
+        default:
+            return( MBEDTLS_SSL_HASH_NONE );
+    }
+}
+
+#if defined(MBEDTLS_ECP_C)
+/*
+ * Check if a curve proposed by the peer is in our list.
+ * Return 0 if we're willing to use it, -1 otherwise.
+ */
+int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id )
 {
     const mbedtls_ecp_group_id *gid;
 
+    if( ssl->conf->curve_list == NULL )
+        return( -1 );
+
     for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
         if( *gid == grp_id )
-            return( 1 );
+            return( 0 );
 
-    return( 0 );
+    return( -1 );
 }
-#endif /* MBEDTLS_SSL_SET_CURVES */
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED)
+/*
+ * Check if a hash proposed by the peer is in our list.
+ * Return 0 if we're willing to use it, -1 otherwise.
+ */
+int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
+                                mbedtls_md_type_t md )
+{
+    const int *cur;
+
+    if( ssl->conf->sig_hashes == NULL )
+        return( -1 );
+
+    for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
+        if( *cur == (int) md )
+            return( 0 );
+
+    return( -1 );
+}
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME__SIGNATURE_ENABLED */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
diff --git a/library/version_features.c b/library/version_features.c
index e534b32..7ad0f02 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -385,9 +385,6 @@
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     "MBEDTLS_SSL_TRUNCATED_HMAC",
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-#if defined(MBEDTLS_SSL_SET_CURVES)
-    "MBEDTLS_SSL_SET_CURVES",
-#endif /* MBEDTLS_SSL_SET_CURVES */
 #if defined(MBEDTLS_THREADING_ALT)
     "MBEDTLS_THREADING_ALT",
 #endif /* MBEDTLS_THREADING_ALT */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index a26715a..bedc6e9 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -82,6 +82,127 @@
 }
 
 /*
+ * Default profile
+ */
+const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
+{
+    /* Hashes from SHA-1 and above */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
+    0xFFFFFFF, /* Any PK alg    */
+    0xFFFFFFF, /* Any curve     */
+    2048,
+};
+
+/*
+ * Next-default profile
+ */
+const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
+{
+    /* Hashes from SHA-256 and above */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
+    0xFFFFFFF, /* Any PK alg    */
+#if defined(MBEDTLS_ECP_C)
+    /* Curves at or above 128-bit security level */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
+#else
+    0,
+#endif
+    2048,
+};
+
+/*
+ * NSA Suite B Profile
+ */
+const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
+{
+    /* Only SHA-256 and 384 */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
+    /* Only ECDSA */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ),
+#if defined(MBEDTLS_ECP_C)
+    /* Only NIST P-256 and P-384 */
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
+#else
+    0,
+#endif
+    0,
+};
+
+/*
+ * Check md_alg against profile
+ * Return 0 if md_alg acceptable for this profile, -1 otherwise
+ */
+static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
+                                      mbedtls_md_type_t md_alg )
+{
+    if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
+        return( 0 );
+
+    return( -1 );
+}
+
+/*
+ * Check pk_alg against profile
+ * Return 0 if pk_alg acceptable for this profile, -1 otherwise
+ */
+static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
+                                      mbedtls_pk_type_t pk_alg )
+{
+    if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
+        return( 0 );
+
+    return( -1 );
+}
+
+/*
+ * Check key against profile
+ * Return 0 if pk_alg acceptable for this profile, -1 otherwise
+ */
+static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
+                                   mbedtls_pk_type_t pk_alg,
+                                   const mbedtls_pk_context *pk )
+{
+#if defined(MBEDTLS_RSA_C)
+    if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
+    {
+        if( mbedtls_pk_get_size( pk ) >= profile->rsa_min_bitlen )
+            return( 0 );
+
+        return( -1 );
+    }
+#endif
+
+#if defined(MBEDTLS_ECDSA_C)
+    if( pk_alg == MBEDTLS_PK_ECDSA )
+    {
+        mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
+
+        if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
+            return( 0 );
+
+        return( -1 );
+    }
+#endif
+
+    return( -1 );
+}
+
+/*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
 static int x509_get_version( unsigned char **p,
@@ -1401,6 +1522,12 @@
     { MBEDTLS_X509_BADCERT_KEY_USAGE,     "Usage does not match the keyUsage extension" },
     { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
     { MBEDTLS_X509_BADCERT_NS_CERT_TYPE,  "Usage does not match the nsCertType extension" },
+    { MBEDTLS_X509_BADCERT_BAD_MD,        "The certificate is signed with an unacceptable hash." },
+    { MBEDTLS_X509_BADCERT_BAD_PK,        "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
+    { MBEDTLS_X509_BADCERT_BAD_KEY,       "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
+    { MBEDTLS_X509_BADCRL_BAD_MD,         "The CRL is signed with an unacceptable hash." },
+    { MBEDTLS_X509_BADCRL_BAD_PK,         "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
+    { MBEDTLS_X509_BADCRL_BAD_KEY,        "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
     { 0, NULL }
 };
 
@@ -1502,7 +1629,8 @@
  * Check that the given certificate is valid according to the CRL.
  */
 static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
-                               mbedtls_x509_crl *crl_list)
+                               mbedtls_x509_crl *crl_list,
+                               const mbedtls_x509_crt_profile *profile )
 {
     int flags = 0;
     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
@@ -1542,6 +1670,12 @@
         /*
          * Check if CRL is correctly signed by the trusted CA
          */
+        if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
+            flags |= MBEDTLS_X509_BADCRL_BAD_MD;
+
+        if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
+            flags |= MBEDTLS_X509_BADCRL_BAD_PK;
+
         md_info = mbedtls_md_info_from_type( crl_list->sig_md );
         if( md_info == NULL )
         {
@@ -1554,6 +1688,9 @@
 
         mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
 
+        if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 )
+            flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
         if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
                            crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
                            crl_list->sig.p, crl_list->sig.len ) != 0 )
@@ -1582,6 +1719,7 @@
 
         crl_list = crl_list->next;
     }
+
     return( flags );
 }
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
@@ -1764,7 +1902,9 @@
 
 static int x509_crt_verify_top(
                 mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca,
-                mbedtls_x509_crl *ca_crl, int path_cnt, uint32_t *flags,
+                mbedtls_x509_crl *ca_crl,
+                const mbedtls_x509_crt_profile *profile,
+                int path_cnt, uint32_t *flags,
                 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                 void *p_vrfy )
 {
@@ -1780,6 +1920,12 @@
     if( mbedtls_x509_time_is_future( &child->valid_from ) )
         *flags |= MBEDTLS_X509_BADCERT_FUTURE;
 
+    if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
+        *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
+
+    if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
+        *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+
     /*
      * Child is the top of the chain. Check against the trust_ca list.
      */
@@ -1820,6 +1966,9 @@
             continue;
         }
 
+        if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 )
+            *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
         if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk,
                            child->sig_md, hash, mbedtls_md_get_size( md_info ),
                            child->sig.p, child->sig.len ) != 0 )
@@ -1846,7 +1995,7 @@
     {
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
         /* Check trusted CA's CRL for the chain's top crt */
-        *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl );
+        *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile );
 #else
         ((void) ca_crl);
 #endif
@@ -1880,8 +2029,10 @@
 }
 
 static int x509_crt_verify_child(
-                mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt *trust_ca,
-                mbedtls_x509_crl *ca_crl, int path_cnt, uint32_t *flags,
+                mbedtls_x509_crt *child, mbedtls_x509_crt *parent,
+                mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl,
+                const mbedtls_x509_crt_profile *profile,
+                int path_cnt, uint32_t *flags,
                 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                 void *p_vrfy )
 {
@@ -1891,6 +2042,8 @@
     mbedtls_x509_crt *grandparent;
     const mbedtls_md_info_t *md_info;
 
+    (void) profile; /* WIP */
+
     /* path_cnt is 0 for the first intermediate CA */
     if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
     {
@@ -1904,6 +2057,12 @@
     if( mbedtls_x509_time_is_future( &child->valid_from ) )
         *flags |= MBEDTLS_X509_BADCERT_FUTURE;
 
+    if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
+        *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
+
+    if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
+        *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+
     md_info = mbedtls_md_info_from_type( child->sig_md );
     if( md_info == NULL )
     {
@@ -1916,6 +2075,9 @@
     {
         mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash );
 
+        if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 )
+            *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
         if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
                            child->sig_md, hash, mbedtls_md_get_size( md_info ),
                            child->sig.p, child->sig.len ) != 0 )
@@ -1926,7 +2088,7 @@
 
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
     /* Check trusted CA's CRL for the given crt */
-    *flags |= x509_crt_verifycrl(child, parent, ca_crl);
+    *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile );
 #endif
 
     /* Look for a grandparent upwards the chain */
@@ -1942,14 +2104,14 @@
     /* Is our parent part of the chain or at the top? */
     if( grandparent != NULL )
     {
-        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl,
+        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, profile,
                                 path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
     else
     {
-        ret = x509_crt_verify_top( parent, trust_ca, ca_crl,
+        ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile,
                                 path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
@@ -1975,6 +2137,22 @@
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy )
 {
+    return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
+                &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
+}
+
+
+/*
+ * Verify the certificate validity, with profile
+ */
+int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
+                     mbedtls_x509_crt *trust_ca,
+                     mbedtls_x509_crl *ca_crl,
+                     const mbedtls_x509_crt_profile *profile,
+                     const char *cn, uint32_t *flags,
+                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy )
+{
     size_t cn_len;
     int ret;
     int pathlen = 0;
@@ -1982,6 +2160,9 @@
     mbedtls_x509_name *name;
     mbedtls_x509_sequence *cur = NULL;
 
+    if( profile == NULL )
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
     *flags = 0;
 
     if( cn != NULL )
@@ -2044,14 +2225,14 @@
     /* Are we part of the chain or at the top? */
     if( parent != NULL )
     {
-        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl,
+        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile,
                                      pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
     else
     {
-        ret = x509_crt_verify_top( crt, trust_ca, ca_crl,
+        ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile,
                                    pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index 4052975..cc0d051 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -163,7 +163,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                    MBEDTLS_SSL_IS_CLIENT,
-                   MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ) != 0 )
+                   MBEDTLS_SSL_TRANSPORT_DATAGRAM,
+                   MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index 4eabf98..3ad10ce 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -199,7 +199,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_SERVER,
-                    MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_DATAGRAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c
index 090e018..2d1dcb9 100644
--- a/programs/ssl/mini_client.c
+++ b/programs/ssl/mini_client.c
@@ -191,7 +191,8 @@
 
     if( mbedtls_ssl_config_defaults( &conf,
                 MBEDTLS_SSL_IS_CLIENT,
-                MBEDTLS_SSL_TRANSPORT_STREAM) != 0 )
+                MBEDTLS_SSL_TRANSPORT_STREAM,
+                MBEDTLS_SSL_PRESET_DEFAULT ) != 0 )
     {
         ret = ssl_config_defaults_failed;
         goto exit;
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index 6ff0e14..b672305 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -153,7 +153,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_CLIENT,
-                    MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 960412a..b8a4a62 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -95,6 +95,7 @@
 #define DFL_MFL_CODE            MBEDTLS_SSL_MAX_FRAG_LEN_NONE
 #define DFL_TRUNC_HMAC          -1
 #define DFL_RECSPLIT            -1
+#define DFL_DHMLEN              -1
 #define DFL_RECONNECT           0
 #define DFL_RECO_DELAY          0
 #define DFL_TICKETS             MBEDTLS_SSL_SESSION_TICKETS_ENABLED
@@ -164,6 +165,13 @@
 #define USAGE_RECSPLIT
 #endif
 
+#if defined(MBEDTLS_DHM_C)
+#define USAGE_DHMLEN \
+    "    dhmlen=%%d           default: (library default: 1024 bits)\n"
+#else
+#define USAGE_DHMLEN
+#endif
+
 #if defined(MBEDTLS_SSL_ALPN)
 #define USAGE_ALPN \
     "    alpn=%%s             default: \"\" (disabled)\n"   \
@@ -246,6 +254,7 @@
     USAGE_EMS                                               \
     USAGE_ETM                                               \
     USAGE_RECSPLIT                                          \
+    USAGE_DHMLEN                                            \
     "\n"                                                    \
     "    arc4=%%d             default: (library default: 0)\n" \
     "    min_version=%%s      default: (library default: tls1)\n"       \
@@ -289,6 +298,7 @@
     unsigned char mfl_code;     /* code for maximum fragment length         */
     int trunc_hmac;             /* negotiate truncated hmac or not          */
     int recsplit;               /* enable record splitting?                 */
+    int dhmlen;                 /* minimum DHM params len in bits           */
     int reconnect;              /* attempt to resume session                */
     int reco_delay;             /* delay in seconds before resuming session */
     int tickets;                /* enable / disable session tickets         */
@@ -468,6 +478,7 @@
     opt.mfl_code            = DFL_MFL_CODE;
     opt.trunc_hmac          = DFL_TRUNC_HMAC;
     opt.recsplit            = DFL_RECSPLIT;
+    opt.dhmlen              = DFL_DHMLEN;
     opt.reconnect           = DFL_RECONNECT;
     opt.reco_delay          = DFL_RECO_DELAY;
     opt.tickets             = DFL_TICKETS;
@@ -758,6 +769,12 @@
             if( opt.recsplit < 0 || opt.recsplit > 1 )
                 goto usage;
         }
+        else if( strcmp( p, "dhmlen" ) == 0 )
+        {
+            opt.dhmlen = atoi( q );
+            if( opt.dhmlen < 0 )
+                goto usage;
+        }
         else
             goto usage;
     }
@@ -1042,7 +1059,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_CLIENT,
-                    opt.transport ) ) != 0 )
+                    opt.transport,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret );
         goto exit;
@@ -1091,6 +1109,11 @@
                                     : MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED );
 #endif
 
+#if defined(MBEDTLS_DHM_C)
+    if( opt.dhmlen != DFL_DHMLEN )
+        mbedtls_ssl_conf_dhm_min_bitlen( &conf, opt.dhmlen );
+#endif
+
 #if defined(MBEDTLS_SSL_ALPN)
     if( opt.alpn_string != NULL )
         if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 )
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 1f50c25..bafaa01 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -177,7 +177,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_SERVER,
-                    MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 9587b7a..c06d0c0 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -587,7 +587,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_CLIENT,
-                    MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c
index 2f414bf..3af66d0 100644
--- a/programs/ssl/ssl_pthread_server.c
+++ b/programs/ssl/ssl_pthread_server.c
@@ -412,7 +412,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_SERVER,
-                    MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n",
                 -ret );
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index 6c837e9..f2f969c 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -193,7 +193,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_SERVER,
-                    MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                    MBEDTLS_SSL_TRANSPORT_STREAM,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 78632a5..de51d45 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -1533,7 +1533,8 @@
 
     if( ( ret = mbedtls_ssl_config_defaults( &conf,
                     MBEDTLS_SSL_IS_SERVER,
-                    opt.transport ) ) != 0 )
+                    opt.transport,
+                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret );
         goto exit;
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 7ae9015..d93aeba 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -399,7 +399,8 @@
          */
         if( ( ret = mbedtls_ssl_config_defaults( &conf,
                         MBEDTLS_SSL_IS_CLIENT,
-                        MBEDTLS_SSL_TRANSPORT_STREAM ) ) != 0 )
+                        MBEDTLS_SSL_TRANSPORT_STREAM,
+                        MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
         {
             mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
             goto exit;
diff --git a/scripts/data_files/rename-1.3-2.0.txt b/scripts/data_files/rename-1.3-2.0.txt
index d395091..bfe2eb2 100644
--- a/scripts/data_files/rename-1.3-2.0.txt
+++ b/scripts/data_files/rename-1.3-2.0.txt
@@ -881,7 +881,6 @@
 POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION
 POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION
 POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS
-POLARSSL_SSL_SET_CURVES MBEDTLS_SSL_SET_CURVES
 POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C
 POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
 POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
diff --git a/tests/data_files/dh.1000.pem b/tests/data_files/dh.1000.pem
new file mode 100644
index 0000000..172f19f
--- /dev/null
+++ b/tests/data_files/dh.1000.pem
@@ -0,0 +1,34 @@
+
+Recommended key length: 160 bits
+
+generator:
+	23:84:3c:0d:55:8c:b9:7d:a9:d5:9a:80:82:fb:50:
+	89:29:71:8e:8e:a1:29:2e:df:db:01:34:41:e7:66:
+	fa:60:dc:bc:34:83:45:70:e0:61:e9:a6:25:23:c2:
+	77:33:a9:8a:90:94:21:ff:84:d2:7b:36:39:9b:e5:
+	f0:88:2b:35:98:64:28:58:27:be:fa:bf:e3:60:cc:
+	c4:61:60:59:78:a7:e1:a3:b3:a7:3e:7e:5b:a8:d7:
+	b7:ba:25:0e:b1:9e:79:03:b5:83:ba:43:34:b6:c1:
+	ce:45:66:72:07:64:8a:af:14:d8:ae:18:19:ba:25:
+	a6:d9:36:f8:8c:
+
+prime:
+	9e:a4:a8:c4:29:fe:76:18:02:4f:76:c9:29:0e:f2:
+	ba:0d:92:08:9d:d9:b3:28:41:5d:88:4e:fe:3c:ae:
+	c1:d4:3e:7e:fb:d8:2c:bf:7b:63:70:99:9e:c4:ac:
+	d0:1e:7c:4e:22:07:d2:b5:f9:9a:9e:52:e2:97:9d:
+	c3:cb:0d:66:33:75:95:a7:96:6e:69:ec:16:bd:06:
+	4a:1a:dc:b2:d4:29:23:ab:2e:8f:7f:6a:84:1d:82:
+	23:6e:42:8c:1e:70:3d:21:bb:b9:b9:8f:f9:fd:9c:
+	53:08:e4:e8:5a:04:ca:5f:8f:73:55:ac:e1:41:20:
+	c7:43:fa:8f:99:
+
+
+-----BEGIN DH PARAMETERS-----
+MIIBAwJ+AJ6kqMQp/nYYAk92ySkO8roNkgid2bMoQV2ITv48rsHUPn772Cy/e2Nw
+mZ7ErNAefE4iB9K1+ZqeUuKXncPLDWYzdZWnlm5p7Ba9Bkoa3LLUKSOrLo9/aoQd
+giNuQowecD0hu7m5j/n9nFMI5OhaBMpfj3NVrOFBIMdD+o+ZAn0jhDwNVYy5fanV
+moCC+1CJKXGOjqEpLt/bATRB52b6YNy8NINFcOBh6aYlI8J3M6mKkJQh/4TSezY5
+m+XwiCs1mGQoWCe++r/jYMzEYWBZeKfho7OnPn5bqNe3uiUOsZ55A7WDukM0tsHO
+RWZyB2SKrxTYrhgZuiWm2Tb4jAICAKA=
+-----END DH PARAMETERS-----
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index fab278f..934f772 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2304,6 +2304,43 @@
             -c "value of 'DHM: P ' (1024 bits)" \
             -c "value of 'DHM: G ' (2 bits)"
 
+# Tests for DHM client-side size checking
+
+run_test    "DHM size: server default, client default, OK" \
+            "$P_SRV" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1" \
+            0 \
+            -C "DHM prime too short:"
+
+run_test    "DHM size: server default, client 2048, OK" \
+            "$P_SRV" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=2048" \
+            0 \
+            -C "DHM prime too short:"
+
+run_test    "DHM size: server 1024, client default, OK" \
+            "$P_SRV dhm_file=data_files/dhparams.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1" \
+            0 \
+            -C "DHM prime too short:"
+
+run_test    "DHM size: server 1000, client default, rejected" \
+            "$P_SRV dhm_file=data_files/dh.1000.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1" \
+            1 \
+            -c "DHM prime too short:"
+
+run_test    "DHM size: server default, client 2049, rejected" \
+            "$P_SRV" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=2049" \
+            1 \
+            -c "DHM prime too short:"
+
 # Tests for PSK callback
 
 run_test    "PSK callback: psk, no callback" \
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 800f6ac..8d3448c 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -20,7 +20,8 @@
 
     TEST_ASSERT( mbedtls_ssl_config_defaults( &conf,
                  MBEDTLS_SSL_IS_CLIENT,
-                 MBEDTLS_SSL_TRANSPORT_DATAGRAM ) == 0 );
+                 MBEDTLS_SSL_TRANSPORT_DATAGRAM,
+                 MBEDTLS_SSL_PRESET_DEFAULT ) == 0 );
     TEST_ASSERT( mbedtls_ssl_setup( &ssl, &conf ) == 0 );
 
     /* Read previous record numbers */
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 5f3fff8..22ff610 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -272,28 +272,7 @@
 x509_verify_info:MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCRL_EXPIRED:"":"The certificate validity has expired\nThe CRL is expired\n"
 
 X509 Verify Information: two issues, one unknown
-x509_verify_info:MBEDTLS_X509_BADCERT_OTHER | 0x8000:"":"Other reason (can be used by verify callback)\nUnknown reason (this should not happen)\n"
-
-X509 Verify Information: empty, with prefix
-x509_verify_info:0:"  ! ":""
-
-X509 Verify Information: one issue, with prefix
-x509_verify_info:MBEDTLS_X509_BADCERT_MISSING:"  ! ":"  ! Certificate was missing\n"
-
-X509 Verify Information: two issues, with prefix
-x509_verify_info:MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCRL_EXPIRED:"  ! ":"  ! The certificate validity has expired\n  ! The CRL is expired\n"
-
-X509 Verify Information: empty
-x509_verify_info:0:"":""
-
-X509 Verify Information: one issue
-x509_verify_info:MBEDTLS_X509_BADCERT_MISSING:"":"Certificate was missing\n"
-
-X509 Verify Information: two issues
-x509_verify_info:MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCRL_EXPIRED:"":"The certificate validity has expired\nThe CRL is expired\n"
-
-X509 Verify Information: two issues, one unknown
-x509_verify_info:MBEDTLS_X509_BADCERT_OTHER | 0x8000:"":"Other reason (can be used by verify callback)\nUnknown reason (this should not happen)\n"
+x509_verify_info:MBEDTLS_X509_BADCERT_OTHER | 0x80000000:"":"Other reason (can be used by verify callback)\nUnknown reason (this should not happen)\n"
 
 X509 Verify Information: empty, with prefix
 x509_verify_info:0:"  ! ":""
@@ -434,11 +413,11 @@
 
 X509 Certificate verification #12 (Valid Cert MD4 Digest)
 depends_on:MBEDTLS_MD4_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_verify:"data_files/cert_md4.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
+x509_verify:"data_files/cert_md4.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_BAD_MD:"NULL"
 
 X509 Certificate verification #13 (Valid Cert MD5 Digest)
 depends_on:MBEDTLS_MD5_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-x509_verify:"data_files/cert_md5.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
+x509_verify:"data_files/cert_md5.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_BAD_MD:"NULL"
 
 X509 Certificate verification #14 (Valid Cert SHA1 Digest)
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
@@ -690,7 +669,7 @@
 
 X509 Certificate verification #75 (encoding mismatch)
 depends_on:MBEDTLS_PEM_PARSE_C
-x509_verify:"data_files/enco-cert-utf8str.pem":"data_files/enco-ca-prstr.pem":"data_files/crl.pem":"NULL":0:0:"NULL"
+x509_verify:"data_files/enco-cert-utf8str.pem":"data_files/enco-ca-prstr.pem":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_BAD_KEY:"NULL"
 
 X509 Certificate verification #76 (multiple CRLs, not revoked)
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
@@ -714,7 +693,7 @@
 
 X509 Certificate verification #81 (multiple CRLs, none relevant)
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
-x509_verify:"data_files/enco-cert-utf8str.pem":"data_files/enco-ca-prstr.pem":"data_files/crl_cat_rsa-ec.pem":"NULL":0:0:"NULL"
+x509_verify:"data_files/enco-cert-utf8str.pem":"data_files/enco-ca-prstr.pem":"data_files/crl_cat_rsa-ec.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_BAD_KEY:"NULL"
 
 X509 Parse Selftest
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_CERTS_C