Merge pull request #5262 from xffbai/code-align-backport2.x

Backport 2.x: Fix (d)tls1_2 into (d)tls12 in version options
diff --git a/.travis.yml b/.travis.yml
index 56e1456..3354607 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,7 @@
       language: python # Needed to get pip for Python 3
       python: 3.5 # version from Ubuntu 16.04
       install:
-        - pip install mypy==0.780 pylint==2.4.4
+        - scripts/min_requirements.py
       script:
         - tests/scripts/all.sh -k 'check_*'
         - tests/scripts/all.sh -k test_default_out_of_box
diff --git a/ChangeLog.d/build-without-sha.txt b/ChangeLog.d/build-without-sha.txt
new file mode 100644
index 0000000..78ba276
--- /dev/null
+++ b/ChangeLog.d/build-without-sha.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix the build when no SHA2 module is included. Fixes #4930.
+   * Fix the build when only the bignum module is included. Fixes #4929.
diff --git a/ChangeLog.d/semi-public-structure-fields.txt b/ChangeLog.d/semi-public-structure-fields.txt
new file mode 100644
index 0000000..802f8de
--- /dev/null
+++ b/ChangeLog.d/semi-public-structure-fields.txt
@@ -0,0 +1,5 @@
+API changes
+   * Some fields of mbedtls_ssl_session and mbedtls_ssl_config are in a
+     different order. This only affects applications that define such
+     structures directly or serialize them.
+
diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h
index d6ad8e7..deb3c50 100644
--- a/include/mbedtls/entropy.h
+++ b/include/mbedtls/entropy.h
@@ -130,7 +130,7 @@
                               * -1 after free. */
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
     mbedtls_sha512_context  accumulator;
-#else
+#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR)
     mbedtls_sha256_context  accumulator;
 #endif
     int             source_count; /* Number of entries used in source. */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 2ed295a..209dbf6 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -974,6 +974,10 @@
  */
 struct mbedtls_ssl_session
 {
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    unsigned char mfl_code;     /*!< MaxFragmentLength negotiated by peer */
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t start;       /*!< starting time      */
 #endif
@@ -1002,10 +1006,6 @@
     uint32_t ticket_lifetime;   /*!< ticket lifetime hint    */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    unsigned char mfl_code;     /*!< MaxFragmentLength negotiated by peer */
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     int trunc_hmac;             /*!< flag for truncated hmac activation   */
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
@@ -1020,7 +1020,98 @@
  */
 struct mbedtls_ssl_config
 {
-    /* Group items by size (largest first) to minimize padding overhead */
+    /* Group items by size and reorder them to maximize usage of immediate offset access.    */
+
+    /*
+     * Numerical settings (char)
+     */
+
+    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            */
+    unsigned char min_minor_ver;    /*!< min. minor version used            */
+
+    /*
+     * Flags (could be bit-fields to save RAM, but separate bytes make
+     * the code smaller on architectures with an instruction for direct
+     * byte access).
+     */
+
+    uint8_t endpoint /*bool*/;      /*!< 0: client, 1: server               */
+    uint8_t transport /*bool*/;     /*!< stream (TLS) or datagram (DTLS)    */
+    uint8_t authmode /*2 bits*/;    /*!< MBEDTLS_SSL_VERIFY_XXX             */
+    /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
+    uint8_t allow_legacy_renegotiation /*2 bits*/; /*!< MBEDTLS_LEGACY_XXX  */
+#if defined(MBEDTLS_ARC4_C)
+    uint8_t arc4_disabled /*bool*/; /*!< blacklist RC4 ciphersuites?        */
+#endif
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    uint8_t mfl_code /*3 bits*/;    /*!< desired fragment length            */
+#endif
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    uint8_t encrypt_then_mac /*bool*/;  /*!< negotiate encrypt-then-mac?    */
+#endif
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    uint8_t extended_ms /*bool*/;   /*!< negotiate extended master secret?  */
+#endif
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    uint8_t anti_replay /*bool*/;   /*!< detect and prevent replay?         */
+#endif
+#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+    uint8_t cbc_record_splitting /*bool*/;  /*!< do cbc record splitting    */
+#endif
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    uint8_t disable_renegotiation /*bool*/; /*!< disable renegotiation?     */
+#endif
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+    uint8_t trunc_hmac /*bool*/;    /*!< negotiate truncated hmac?          */
+#endif
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint8_t session_tickets /*bool*/;   /*!< use session tickets?           */
+#endif
+#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C)
+    uint8_t fallback /*bool*/;      /*!< is this a fallback?                */
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+    uint8_t cert_req_ca_list /*bool*/;  /*!< enable sending CA list in
+                                          Certificate Request messages?     */
+#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    uint8_t ignore_unexpected_cid /*bool*/; /*!< Determines whether DTLS
+                                             *   record with unexpected CID
+                                             *   should lead to failure.    */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    uint8_t dtls_srtp_mki_support /*bool*/; /*!< support having mki_value
+                                                 in the use_srtp extension? */
+#endif
+
+    /*
+     * Numerical settings (int or larger)
+     */
+
+    uint32_t read_timeout;          /*!< timeout for mbedtls_ssl_read (ms)  */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    uint32_t hs_timeout_min;        /*!< initial value of the handshake
+                                         retransmission timeout (ms)        */
+    uint32_t hs_timeout_max;        /*!< maximum value of the handshake
+                                         retransmission timeout (ms)        */
+#endif
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    int renego_max_records;         /*!< grace period for renegotiation     */
+    unsigned char renego_period[8]; /*!< value of the record counters
+                                         that triggers renegotiation        */
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+    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
 
     /*
      * Pointers
@@ -1174,91 +1265,6 @@
     /*! number of supported profiles */
     size_t dtls_srtp_profile_list_len;
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-    /*
-     * Numerical settings (int then char)
-     */
-
-    uint32_t read_timeout;          /*!< timeout for mbedtls_ssl_read (ms)  */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    uint32_t hs_timeout_min;        /*!< initial value of the handshake
-                                         retransmission timeout (ms)        */
-    uint32_t hs_timeout_max;        /*!< maximum value of the handshake
-                                         retransmission timeout (ms)        */
-#endif
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    int renego_max_records;         /*!< grace period for renegotiation     */
-    unsigned char renego_period[8]; /*!< value of the record counters
-                                         that triggers renegotiation        */
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-    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            */
-    unsigned char min_minor_ver;    /*!< min. minor version used            */
-
-    /*
-     * Flags (bitfields)
-     */
-
-    unsigned int endpoint : 1;      /*!< 0: client, 1: server               */
-    unsigned int transport : 1;     /*!< stream (TLS) or datagram (DTLS)    */
-    unsigned int authmode : 2;      /*!< MBEDTLS_SSL_VERIFY_XXX             */
-    /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
-    unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX   */
-#if defined(MBEDTLS_ARC4_C)
-    unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites?        */
-#endif
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    unsigned int mfl_code : 3;      /*!< desired fragment length            */
-#endif
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac?    */
-#endif
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    unsigned int extended_ms : 1;   /*!< negotiate extended master secret?  */
-#endif
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    unsigned int anti_replay : 1;   /*!< detect and prevent replay?         */
-#endif
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    unsigned int cbc_record_splitting : 1;  /*!< do cbc record splitting    */
-#endif
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    unsigned int disable_renegotiation : 1; /*!< disable renegotiation?     */
-#endif
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    unsigned int trunc_hmac : 1;    /*!< negotiate truncated hmac?          */
-#endif
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    unsigned int session_tickets : 1;   /*!< use session tickets?           */
-#endif
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C)
-    unsigned int fallback : 1;      /*!< is this a fallback?                */
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-    unsigned int cert_req_ca_list : 1;  /*!< enable sending CA list in
-                                          Certificate Request messages?     */
-#endif
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    unsigned int ignore_unexpected_cid : 1; /*!< Determines whether DTLS
-                                             *   record with unexpected CID
-                                             *   should lead to failure.    */
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-    unsigned int dtls_srtp_mki_support : 1; /* support having mki_value
-                                               in the use_srtp extension     */
-#endif
 };
 
 struct mbedtls_ssl_context
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index bc30306..6913dc0 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -430,13 +430,63 @@
      * Handshake specific crypto variables
      */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    uint8_t max_major_ver;              /*!< max. major version client*/
+    uint8_t max_minor_ver;              /*!< max. minor version client*/
+    uint8_t resume;                     /*!<  session resume indicator*/
+    uint8_t cli_exts;                   /*!< client extension presence*/
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    uint8_t sni_authmode;               /*!< authmode from SNI callback     */
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint8_t new_session_ticket;         /*!< use NewSessionTicket?    */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    uint8_t extended_ms;                /*!< use Extended Master Secret? */
+#endif
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    uint8_t async_in_progress;          /*!< an asynchronous operation is in progress */
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    unsigned char retransmit_state;     /*!<  Retransmission state           */
+#endif
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    uint8_t ecrs_enabled;               /*!< Handshake supports EC restart? */
+    enum { /* this complements ssl->state with info on intra-state operations */
+        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
+        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
+        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
+        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
+        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
+    } ecrs_state;                       /*!< current (or last) operation    */
+    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */
+    size_t ecrs_n;                      /*!< place for saving a length      */
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) &&                \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
     mbedtls_ssl_sig_hash_set_t hash_algs;             /*!<  Set of suitable sig-hash pairs */
 #endif
+
+    size_t pmslen;                      /*!<  premaster length        */
+
+    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
+
+    void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
+    void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
+    void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
+    mbedtls_ssl_tls_prf_cb *tls_prf;
+
 #if defined(MBEDTLS_DHM_C)
     mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */
 #endif
+
 /* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
  * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap
  * in functionality that access to ecdh_ctx structure is needed for
@@ -461,10 +511,12 @@
     size_t ecjpake_cache_len;                   /*!< Length of cached data */
 #endif
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ||      \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     const mbedtls_ecp_curve_info **curves;      /*!<  Supported elliptic curves */
 #endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_key_id_t psk_opaque;            /*!< Opaque PSK from the callback   */
@@ -472,65 +524,26 @@
     unsigned char *psk;                 /*!<  PSK from the callback         */
     size_t psk_len;                     /*!<  Length of PSK from callback   */
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_ssl_key_cert *key_cert;     /*!< chosen key/cert pair (server)  */
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    int sni_authmode;                   /*!< authmode from SNI callback     */
     mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI         */
     mbedtls_x509_crt *sni_ca_chain;     /*!< trusted CAs from SNI callback  */
     mbedtls_x509_crl *sni_ca_crl;       /*!< trusted CAs CRLs from SNI      */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
+
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    int ecrs_enabled;                   /*!< Handshake supports EC restart? */
     mbedtls_x509_crt_restart_ctx ecrs_ctx;  /*!< restart context            */
-    enum { /* this complements ssl->state with info on intra-state operations */
-        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
-        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
-        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
-        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
-        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
-    } ecrs_state;                       /*!< current (or last) operation    */
-    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */
-    size_t ecrs_n;                      /*!< place for saving a length      */
 #endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
     !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     mbedtls_pk_context peer_pubkey;     /*!< The public key from the peer.  */
 #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
-    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
-
-    unsigned char *verify_cookie;       /*!<  Cli: HelloVerifyRequest cookie
-                                              Srv: unused                    */
-    unsigned char verify_cookie_len;    /*!<  Cli: cookie length
-                                              Srv: flag for sending a cookie */
-
-    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
-    unsigned char retransmit_state;     /*!<  Retransmission state           */
-    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
-    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
-    unsigned char *cur_msg_p;           /*!<  Position in current message    */
-    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
-                                              flight being received          */
-    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
-                                              resending messages             */
-    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
-                                              for resending messages         */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    /* The state of CID configuration in this handshake. */
-
-    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
-                         *   has been negotiated. Possible values are
-                         *   #MBEDTLS_SSL_CID_ENABLED and
-                         *   #MBEDTLS_SSL_CID_DISABLED. */
-    unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
-    uint8_t peer_cid_len;                                  /*!< The length of
-                                                            *   \c peer_cid.  */
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
     struct
     {
         size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
@@ -557,6 +570,37 @@
 
     } buffering;
 
+    unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
+    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
+
+    unsigned char *verify_cookie;       /*!<  Cli: HelloVerifyRequest cookie
+                                              Srv: unused                    */
+    unsigned char verify_cookie_len;    /*!<  Cli: cookie length
+                                              Srv: flag for sending a cookie */
+
+    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
+    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
+    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
+    unsigned char *cur_msg_p;           /*!<  Position in current message    */
+    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
+                                              flight being received          */
+    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
+                                              resending messages             */
+    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
+                                              for resending messages         */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* The state of CID configuration in this handshake. */
+
+    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
+                         *   has been negotiated. Possible values are
+                         *   #MBEDTLS_SSL_CID_ENABLED and
+                         *   #MBEDTLS_SSL_CID_DISABLED. */
+    unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
+    uint8_t peer_cid_len;                                  /*!< The length of
+                                                            *   \c peer_cid.  */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
     uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -565,8 +609,8 @@
      */
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
-       mbedtls_md5_context fin_md5;
-      mbedtls_sha1_context fin_sha1;
+    mbedtls_md5_context fin_md5;
+    mbedtls_sha1_context fin_sha1;
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #if defined(MBEDTLS_SHA256_C)
@@ -585,35 +629,10 @@
 #endif
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-    void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
-    void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
-    void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
-    mbedtls_ssl_tls_prf_cb *tls_prf;
-
-    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
-
-    size_t pmslen;                      /*!<  premaster length        */
-
     unsigned char randbytes[64];        /*!<  random bytes            */
     unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
                                         /*!<  premaster secret        */
 
-    int resume;                         /*!<  session resume indicator*/
-    int max_major_ver;                  /*!< max. major version client*/
-    int max_minor_ver;                  /*!< max. minor version client*/
-    int cli_exts;                       /*!< client extension presence*/
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    int new_session_ticket;             /*!< use NewSessionTicket?    */
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    int extended_ms;                    /*!< use Extended Master Secret? */
-#endif
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     /** Asynchronous operation context. This field is meant for use by the
      * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 877c19b..b0b57c3 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -159,10 +159,10 @@
  * the owner of a key.
  *
  * \param[out] attributes  The attribute structure to write to.
- * \param owner_id         The key owner identifier.
+ * \param owner            The key owner identifier.
  */
 static void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes,
-                                      mbedtls_key_owner_id_t owner_id );
+                                      mbedtls_key_owner_id_t owner );
 #endif
 
 /** Set the location of a persistent key.
diff --git a/include/psa/crypto_driver_common.h b/include/psa/crypto_driver_common.h
index 1b6f322..26363c6 100644
--- a/include/psa/crypto_driver_common.h
+++ b/include/psa/crypto_driver_common.h
@@ -42,6 +42,9 @@
  * of these types. */
 #include "crypto_types.h"
 #include "crypto_values.h"
+/* Include size definitions which are used to size some arrays in operation
+ * structures. */
+#include <psa/crypto_sizes.h>
 
 /** For encrypt-decrypt functions, whether the operation is an encryption
  * or a decryption. */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 1310bb5..3ee0482 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -30,6 +30,7 @@
 
 #include "mbedtls/platform_util.h"
 
+#include "crypto_types.h"
 #include "crypto_compat.h"
 
 #ifdef __cplusplus
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 94242f8..23a02a5 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -175,9 +175,6 @@
 {
     uint8_t *info;
     size_t info_length;
-    psa_mac_operation_t hmac;
-    uint8_t prk[PSA_HASH_MAX_SIZE];
-    uint8_t output_block[PSA_HASH_MAX_SIZE];
 #if PSA_HASH_MAX_SIZE > 0xff
 #error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
 #endif
@@ -185,6 +182,9 @@
     uint8_t block_number;
     unsigned int state : 2;
     unsigned int info_set : 1;
+    uint8_t output_block[PSA_HASH_MAX_SIZE];
+    uint8_t prk[PSA_HASH_MAX_SIZE];
+    struct psa_mac_operation_s hmac;
 } psa_hkdf_key_derivation_t;
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
diff --git a/library/base64.c b/library/base64.c
index a516c1d..83daa0b 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -22,7 +22,7 @@
 #if defined(MBEDTLS_BASE64_C)
 
 #include "mbedtls/base64.h"
-#include "base64_invasive.h"
+#include "constant_time_internal.h"
 
 #include <stdint.h>
 
@@ -38,41 +38,6 @@
 
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 
-/* Return 0xff if low <= c <= high, 0 otherwise.
- *
- * Constant flow with respect to c.
- */
-MBEDTLS_STATIC_TESTABLE
-unsigned char mbedtls_base64_mask_of_range( unsigned char low,
-                                            unsigned char high,
-                                            unsigned char c )
-{
-    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
-    unsigned low_mask = ( (unsigned) c - low ) >> 8;
-    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
-    unsigned high_mask = ( (unsigned) high - c ) >> 8;
-    return( ~( low_mask | high_mask ) & 0xff );
-}
-
-/* Given a value in the range 0..63, return the corresponding Base64 digit.
- * The implementation assumes that letters are consecutive (e.g. ASCII
- * but not EBCDIC).
- */
-MBEDTLS_STATIC_TESTABLE
-unsigned char mbedtls_base64_enc_char( unsigned char val )
-{
-    unsigned char digit = 0;
-    /* For each range of values, if val is in that range, mask digit with
-     * the corresponding value. Since val can only be in a single range,
-     * only at most one masking will change digit. */
-    digit |= mbedtls_base64_mask_of_range(  0, 25, val ) & ( 'A' + val );
-    digit |= mbedtls_base64_mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
-    digit |= mbedtls_base64_mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
-    digit |= mbedtls_base64_mask_of_range( 62, 62, val ) & '+';
-    digit |= mbedtls_base64_mask_of_range( 63, 63, val ) & '/';
-    return( digit );
-}
-
 /*
  * Encode a buffer into base64 format
  */
@@ -113,12 +78,12 @@
         C2 = *src++;
         C3 = *src++;
 
-        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
-        *p++ = mbedtls_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
+        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
                                         & 0x3F );
-        *p++ = mbedtls_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
                                         & 0x3F );
-        *p++ = mbedtls_base64_enc_char( C3 & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F );
     }
 
     if( i < slen )
@@ -126,12 +91,12 @@
         C1 = *src++;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
-        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
-        *p++ = mbedtls_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
                                         & 0x3F );
 
         if( ( i + 1 ) < slen )
-             *p++ = mbedtls_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
+             *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
         else *p++ = '=';
 
         *p++ = '=';
@@ -143,35 +108,6 @@
     return( 0 );
 }
 
-/* Given a Base64 digit, return its value.
- * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
- * return -1.
- *
- * The implementation assumes that letters are consecutive (e.g. ASCII
- * but not EBCDIC).
- *
- * The implementation is constant-flow (no branch or memory access depending
- * on the value of c) unless the compiler inlines and optimizes a specific
- * access.
- */
-MBEDTLS_STATIC_TESTABLE
-signed char mbedtls_base64_dec_value( unsigned char c )
-{
-    unsigned char val = 0;
-    /* For each range of digits, if c is in that range, mask val with
-     * the corresponding value. Since c can only be in a single range,
-     * only at most one masking will change val. Set val to one plus
-     * the desired value so that it stays 0 if c is in none of the ranges. */
-    val |= mbedtls_base64_mask_of_range( 'A', 'Z', c ) & ( c - 'A' +  0 + 1 );
-    val |= mbedtls_base64_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
-    val |= mbedtls_base64_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
-    val |= mbedtls_base64_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
-    val |= mbedtls_base64_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
-    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
-     * a digit with the value v. */
-    return( val - 1 );
-}
-
 /*
  * Decode a base64-formatted buffer
  */
@@ -224,7 +160,7 @@
         {
             if( equals != 0 )
                 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-            if( mbedtls_base64_dec_value( src[i] ) < 0 )
+            if( mbedtls_ct_base64_dec_value( src[i] ) < 0 )
                 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
         }
         n++;
@@ -259,7 +195,7 @@
         if( *src == '=' )
             ++equals;
         else
-            x |= mbedtls_base64_dec_value( *src );
+            x |= mbedtls_ct_base64_dec_value( *src );
 
         if( ++accumulated_digits == 4 )
         {
diff --git a/library/base64_invasive.h b/library/base64_invasive.h
deleted file mode 100644
index ed5f7cb..0000000
--- a/library/base64_invasive.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * \file base_invasive.h
- *
- * \brief Base64 module: interfaces for invasive testing only.
- *
- * The interfaces in this file are intended for testing purposes only.
- * They SHOULD NOT be made available in library integrations except when
- * building the library for testing.
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-#ifndef MBEDTLS_BASE64_INVASIVE_H
-#define MBEDTLS_BASE64_INVASIVE_H
-
-#include "common.h"
-
-#if defined(MBEDTLS_TEST_HOOKS)
-/* Return 0xff if low <= c <= high, 0 otherwise.
- *
- * Constant flow with respect to c.
- */
-unsigned char mbedtls_base64_mask_of_range( unsigned char low,
-                                            unsigned char high,
-                                            unsigned char c );
-
-/* Given a value in the range 0..63, return the corresponding Base64 digit.
- *
- * Operates in constant time (no branches or memory access depending on val).
- */
-unsigned char mbedtls_base64_enc_char( unsigned char val );
-
-/* Given a Base64 digit, return its value.
- * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
- * return -1.
- *
- * Operates in constant time (no branches or memory access depending on c).
- */
-signed char mbedtls_base64_dec_value( unsigned char c );
-#endif /* MBEDTLS_TEST_HOOKS */
-
-#endif /* MBEDTLS_BASE64_INVASIVE_H */
diff --git a/library/bignum.c b/library/bignum.c
index b147a54..62e7f76 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -43,6 +43,7 @@
 #include "mbedtls/error.h"
 #include "constant_time_internal.h"
 
+#include <limits.h>
 #include <string.h>
 
 #if defined(MBEDTLS_PLATFORM_C)
diff --git a/library/constant_time.c b/library/constant_time.c
index b0e5dde..18f1b20 100644
--- a/library/constant_time.c
+++ b/library/constant_time.c
@@ -40,6 +40,10 @@
 #include "mbedtls/rsa.h"
 #endif
 
+#if defined(MBEDTLS_BASE64_C)
+#include "constant_time_invasive.h"
+#endif
+
 #include <string.h>
 
 int mbedtls_ct_memcmp( const void *a,
@@ -150,6 +154,26 @@
 
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
 
+#if defined(MBEDTLS_BASE64_C)
+
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
+ */
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low,
+                                              unsigned char high,
+                                              unsigned char c )
+{
+    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
+    unsigned low_mask = ( (unsigned) c - low ) >> 8;
+    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
+    unsigned high_mask = ( (unsigned) high - c ) >> 8;
+    return( ~( low_mask | high_mask ) & 0xff );
+}
+
+#endif /* MBEDTLS_BASE64_C */
+
 unsigned mbedtls_ct_size_bool_eq( size_t x,
                                   size_t y )
 {
@@ -301,6 +325,41 @@
 
 #endif /* MBEDTLS_BIGNUM_C */
 
+#if defined(MBEDTLS_BASE64_C)
+
+unsigned char mbedtls_ct_base64_enc_char( unsigned char value )
+{
+    unsigned char digit = 0;
+    /* For each range of values, if value is in that range, mask digit with
+     * the corresponding value. Since value can only be in a single range,
+     * only at most one masking will change digit. */
+    digit |= mbedtls_ct_uchar_mask_of_range(  0, 25, value ) & ( 'A' + value );
+    digit |= mbedtls_ct_uchar_mask_of_range( 26, 51, value ) & ( 'a' + value - 26 );
+    digit |= mbedtls_ct_uchar_mask_of_range( 52, 61, value ) & ( '0' + value - 52 );
+    digit |= mbedtls_ct_uchar_mask_of_range( 62, 62, value ) & '+';
+    digit |= mbedtls_ct_uchar_mask_of_range( 63, 63, value ) & '/';
+    return( digit );
+}
+
+signed char mbedtls_ct_base64_dec_value( unsigned char c )
+{
+    unsigned char val = 0;
+    /* For each range of digits, if c is in that range, mask val with
+     * the corresponding value. Since c can only be in a single range,
+     * only at most one masking will change val. Set val to one plus
+     * the desired value so that it stays 0 if c is in none of the ranges. */
+    val |= mbedtls_ct_uchar_mask_of_range( 'A', 'Z', c ) & ( c - 'A' +  0 + 1 );
+    val |= mbedtls_ct_uchar_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
+    val |= mbedtls_ct_uchar_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
+    val |= mbedtls_ct_uchar_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
+    val |= mbedtls_ct_uchar_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
+     * a digit with the value v. */
+    return( val - 1 );
+}
+
+#endif /* MBEDTLS_BASE64_C */
+
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
 /** Shift some data towards the left inside a buffer.
diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h
index 69cd092..bbb3a90 100644
--- a/library/constant_time_internal.h
+++ b/library/constant_time_internal.h
@@ -167,6 +167,35 @@
 
 #endif /* MBEDTLS_BIGNUM_C */
 
+#if defined(MBEDTLS_BASE64_C)
+
+/** Given a value in the range 0..63, return the corresponding Base64 digit.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * \param value     A value in the range 0..63.
+ *
+ * \return          A base64 digit converted from \p value.
+ */
+unsigned char mbedtls_ct_base64_enc_char( unsigned char value );
+
+/** Given a Base64 digit, return its value.
+ *
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * \param c     A base64 digit.
+ *
+ * \return      The value of the base64 digit \p c.
+ */
+signed char mbedtls_ct_base64_dec_value( unsigned char c );
+
+#endif /* MBEDTLS_BASE64_C */
+
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
 
 /** Conditional memcpy without branches.
diff --git a/library/constant_time_invasive.h b/library/constant_time_invasive.h
new file mode 100644
index 0000000..4620ca1
--- /dev/null
+++ b/library/constant_time_invasive.h
@@ -0,0 +1,51 @@
+/**
+ * \file constant_time_invasive.h
+ *
+ * \brief Constant-time module: interfaces for invasive testing only.
+ *
+ * The interfaces in this file are intended for testing purposes only.
+ * They SHOULD NOT be made available in library integrations except when
+ * building the library for testing.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H
+#define MBEDTLS_CONSTANT_TIME_INVASIVE_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+/** Turn a value into a mask:
+ * - if \p low <= \p c <= \p high,
+ *   return the all-bits 1 mask, aka (unsigned) -1
+ * - otherwise, return the all-bits 0 mask, aka 0
+ *
+ * \param low   The value to analyze.
+ * \param high  The value to analyze.
+ * \param c     The value to analyze.
+ *
+ * \return      All-bits-one if \p low <= \p c <= \p high, otherwise zero.
+ */
+unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low,
+                                              unsigned char high,
+                                              unsigned char c );
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 9bcdb7f..e3db912 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -108,9 +108,9 @@
 
 typedef struct
 {
-    mbedtls_psa_random_context_t rng;
     unsigned initialized : 1;
     unsigned rng_state : 2;
+    mbedtls_psa_random_context_t rng;
 } psa_global_data_t;
 
 static psa_global_data_t global_data;
diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c
index b43287b..16a3711 100644
--- a/library/psa_crypto_aead.c
+++ b/library/psa_crypto_aead.c
@@ -32,6 +32,8 @@
 
 typedef struct
 {
+    psa_algorithm_t core_alg;
+    uint8_t tag_length;
     union
     {
         unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
@@ -45,11 +47,9 @@
         mbedtls_chachapoly_context chachapoly;
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
     } ctx;
-    psa_algorithm_t core_alg;
-    uint8_t tag_length;
 } aead_operation_t;
 
-#define AEAD_OPERATION_INIT {{0}, 0, 0}
+#define AEAD_OPERATION_INIT {0, 0, {0}}
 
 static void psa_aead_abort_internal( aead_operation_t *operation )
 {
diff --git a/programs/fuzz/common.c b/programs/fuzz/common.c
index ac39ee2..e12ee3b 100644
--- a/programs/fuzz/common.c
+++ b/programs/fuzz/common.c
@@ -1,4 +1,5 @@
 #include "common.h"
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/scripts/ci.requirements.txt b/scripts/ci.requirements.txt
new file mode 100644
index 0000000..18b40ec
--- /dev/null
+++ b/scripts/ci.requirements.txt
@@ -0,0 +1,10 @@
+# Python package requirements for Mbed TLS testing.
+
+# Use a known version of Pylint, because new versions tend to add warnings
+# that could start rejecting our code.
+# 2.4.4 is the version in Ubuntu 20.04. It supports Python >=3.5.
+pylint == 2.4.4
+
+# Use the earliest version of mypy that works with our code base.
+# See https://github.com/ARMmbed/mbedtls/pull/3953 .
+mypy >= 0.780
diff --git a/scripts/maintainer.requirements.txt b/scripts/maintainer.requirements.txt
new file mode 100644
index 0000000..b149921
--- /dev/null
+++ b/scripts/maintainer.requirements.txt
@@ -0,0 +1,10 @@
+# Python packages that are only useful to Mbed TLS maintainers.
+
+-r ci.requirements.txt
+
+# For source code analyses
+clang
+
+# For building some test vectors
+pycryptodomex
+pycryptodome-test-vectors
diff --git a/scripts/min_requirements.py b/scripts/min_requirements.py
new file mode 100755
index 0000000..eecab1c
--- /dev/null
+++ b/scripts/min_requirements.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+"""Install all the required Python packages, with the minimum Python version.
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+import tempfile
+import typing
+
+from typing import List, Optional
+from mbedtls_dev import typing_util
+
+def pylint_doesn_t_notice_that_certain_types_are_used_in_annotations(
+        _list: List[typing.Any],
+) -> None:
+    pass
+
+
+class Requirements:
+    """Collect and massage Python requirements."""
+
+    def __init__(self) -> None:
+        self.requirements = [] #type: List[str]
+
+    def adjust_requirement(self, req: str) -> str:
+        """Adjust a requirement to the minimum specified version."""
+        # allow inheritance #pylint: disable=no-self-use
+        # If a requirement specifies a minimum version, impose that version.
+        req = re.sub(r'>=|~=', r'==', req)
+        return req
+
+    def add_file(self, filename: str) -> None:
+        """Add requirements from the specified file.
+
+        This method supports a subset of pip's requirement file syntax:
+        * One requirement specifier per line, which is passed to
+          `adjust_requirement`.
+        * Comments (``#`` at the beginning of the line or after whitespace).
+        * ``-r FILENAME`` to include another file.
+        """
+        for line in open(filename):
+            line = line.strip()
+            line = re.sub(r'(\A|\s+)#.*', r'', line)
+            if not line:
+                continue
+            m = re.match(r'-r\s+', line)
+            if m:
+                nested_file = os.path.join(os.path.dirname(filename),
+                                           line[m.end(0):])
+                self.add_file(nested_file)
+                continue
+            self.requirements.append(self.adjust_requirement(line))
+
+    def write(self, out: typing_util.Writable) -> None:
+        """List the gathered requirements."""
+        for req in self.requirements:
+            out.write(req + '\n')
+
+    def install(
+            self,
+            pip_general_options: Optional[List[str]] = None,
+            pip_install_options: Optional[List[str]] = None,
+    ) -> None:
+        """Call pip to install the requirements."""
+        if pip_general_options is None:
+            pip_general_options = []
+        if pip_install_options is None:
+            pip_install_options = []
+        with tempfile.TemporaryDirectory() as temp_dir:
+            # This is more complicated than it needs to be for the sake
+            # of Windows. Use a temporary file rather than the command line
+            # to avoid quoting issues. Use a temporary directory rather
+            # than NamedTemporaryFile because with a NamedTemporaryFile on
+            # Windows, the subprocess can't open the file because this process
+            # has an exclusive lock on it.
+            req_file_name = os.path.join(temp_dir, 'requirements.txt')
+            with open(req_file_name, 'w') as req_file:
+                self.write(req_file)
+            subprocess.check_call([sys.executable, '-m', 'pip'] +
+                                  pip_general_options +
+                                  ['install'] + pip_install_options +
+                                  ['-r', req_file_name])
+
+DEFAULT_REQUIREMENTS_FILE = 'ci.requirements.txt'
+
+def main() -> None:
+    """Command line entry point."""
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--no-act', '-n',
+                        action='store_true',
+                        help="Don't act, just print what will be done")
+    parser.add_argument('--pip-install-option',
+                        action='append', dest='pip_install_options',
+                        help="Pass this option to pip install")
+    parser.add_argument('--pip-option',
+                        action='append', dest='pip_general_options',
+                        help="Pass this general option to pip")
+    parser.add_argument('--user',
+                        action='append_const', dest='pip_install_options',
+                        const='--user',
+                        help="Install to the Python user install directory"
+                             " (short for --pip-install-option --user)")
+    parser.add_argument('files', nargs='*', metavar='FILE',
+                        help="Requirement files"
+                             " (default: {} in the script's directory)" \
+                             .format(DEFAULT_REQUIREMENTS_FILE))
+    options = parser.parse_args()
+    if not options.files:
+        options.files = [os.path.join(os.path.dirname(__file__),
+                                      DEFAULT_REQUIREMENTS_FILE)]
+    reqs = Requirements()
+    for filename in options.files:
+        reqs.add_file(filename)
+    reqs.write(sys.stdout)
+    if not options.no_act:
+        reqs.install(pip_general_options=options.pip_general_options,
+                     pip_install_options=options.pip_install_options)
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/docker/bionic/Dockerfile b/tests/docker/bionic/Dockerfile
index 1d24aa3..3132be9 100644
--- a/tests/docker/bionic/Dockerfile
+++ b/tests/docker/bionic/Dockerfile
@@ -160,7 +160,3 @@
 
 ENV GNUTLS_NEXT_CLI=/usr/local/gnutls-3.6.5/bin/gnutls-cli
 ENV GNUTLS_NEXT_SERV=/usr/local/gnutls-3.6.5/bin/gnutls-serv
-
-RUN pip3 install --no-cache-dir \
-    mbed-host-tests \
-    mock
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index 4e078e3..b0638d7 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -457,6 +457,139 @@
 
         return enum_consts
 
+    IGNORED_CHUNK_REGEX = re.compile('|'.join([
+        r'/\*.*?\*/', # block comment entirely on one line
+        r'//.*', # line comment
+        r'(?P<string>")(?:[^\\\"]|\\.)*"', # string literal
+    ]))
+
+    def strip_comments_and_literals(self, line, in_block_comment):
+        """Strip comments and string literals from line.
+
+        Continuation lines are not supported.
+
+        If in_block_comment is true, assume that the line starts inside a
+        block comment.
+
+        Return updated values of (line, in_block_comment) where:
+        * Comments in line have been replaced by a space (or nothing at the
+          start or end of the line).
+        * String contents have been removed.
+        * in_block_comment indicates whether the line ends inside a block
+          comment that continues on the next line.
+        """
+
+        # Terminate current multiline comment?
+        if in_block_comment:
+            m = re.search(r"\*/", line)
+            if m:
+                in_block_comment = False
+                line = line[m.end(0):]
+            else:
+                return '', True
+
+        # Remove full comments and string literals.
+        # Do it all together to handle cases like "/*" correctly.
+        # Note that continuation lines are not supported.
+        line = re.sub(self.IGNORED_CHUNK_REGEX,
+                      lambda s: '""' if s.group('string') else ' ',
+                      line)
+
+        # Start an unfinished comment?
+        # (If `/*` was part of a complete comment, it's already been removed.)
+        m = re.search(r"/\*", line)
+        if m:
+            in_block_comment = True
+            line = line[:m.start(0)]
+
+        return line, in_block_comment
+
+    IDENTIFIER_REGEX = re.compile('|'.join([
+        # Match " something(a" or " *something(a". Functions.
+        # Assumptions:
+        # - function definition from return type to one of its arguments is
+        #   all on one line
+        # - function definition line only contains alphanumeric, asterisk,
+        #   underscore, and open bracket
+        r".* \**(\w+) *\( *\w",
+        # Match "(*something)(".
+        r".*\( *\* *(\w+) *\) *\(",
+        # Match names of named data structures.
+        r"(?:typedef +)?(?:struct|union|enum) +(\w+)(?: *{)?$",
+        # Match names of typedef instances, after closing bracket.
+        r"}? *(\w+)[;[].*",
+    ]))
+    # The regex below is indented for clarity.
+    EXCLUSION_LINES = re.compile("|".join([
+        r"extern +\"C\"",
+        r"(typedef +)?(struct|union|enum)( *{)?$",
+        r"} *;?$",
+        r"$",
+        r"//",
+        r"#",
+    ]))
+
+    def parse_identifiers_in_file(self, header_file, identifiers):
+        """
+        Parse all lines of a header where a function/enum/struct/union/typedef
+        identifier is declared, based on some regex and heuristics. Highly
+        dependent on formatting style.
+
+        Append found matches to the list ``identifiers``.
+        """
+
+        with open(header_file, "r", encoding="utf-8") as header:
+            in_block_comment = False
+            # The previous line variable is used for concatenating lines
+            # when identifiers are formatted and spread across multiple
+            # lines.
+            previous_line = ""
+
+            for line_no, line in enumerate(header):
+                line, in_block_comment = \
+                    self.strip_comments_and_literals(line, in_block_comment)
+
+                if self.EXCLUSION_LINES.match(line):
+                    previous_line = ""
+                    continue
+
+                # If the line contains only space-separated alphanumeric
+                # characters (or underscore, asterisk, or open parenthesis),
+                # and nothing else, high chance it's a declaration that
+                # continues on the next line
+                if re.search(r"^([\w\*\(]+\s+)+$", line):
+                    previous_line += line
+                    continue
+
+                # If previous line seemed to start an unfinished declaration
+                # (as above), concat and treat them as one.
+                if previous_line:
+                    line = previous_line.strip() + " " + line.strip() + "\n"
+                    previous_line = ""
+
+                # Skip parsing if line has a space in front = heuristic to
+                # skip function argument lines (highly subject to formatting
+                # changes)
+                if line[0] == " ":
+                    continue
+
+                identifier = self.IDENTIFIER_REGEX.search(line)
+
+                if not identifier:
+                    continue
+
+                # Find the group that matched, and append it
+                for group in identifier.groups():
+                    if not group:
+                        continue
+
+                    identifiers.append(Match(
+                        header_file,
+                        line,
+                        line_no,
+                        identifier.span(),
+                        group))
+
     def parse_identifiers(self, include, exclude=None):
         """
         Parse all lines of a header where a function/enum/struct/union/typedef
@@ -469,99 +602,13 @@
 
         Returns a List of Match objects with identifiers.
         """
-        identifier_regex = re.compile(
-            # Match " something(a" or " *something(a". Functions.
-            # Assumptions:
-            # - function definition from return type to one of its arguments is
-            #   all on one line
-            # - function definition line only contains alphanumeric, asterisk,
-            #   underscore, and open bracket
-            r".* \**(\w+) *\( *\w|"
-            # Match "(*something)(".
-            r".*\( *\* *(\w+) *\) *\(|"
-            # Match names of named data structures.
-            r"(?:typedef +)?(?:struct|union|enum) +(\w+)(?: *{)?$|"
-            # Match names of typedef instances, after closing bracket.
-            r"}? *(\w+)[;[].*"
-        )
-        # The regex below is indented for clarity.
-        exclusion_lines = re.compile(
-            r"^("
-                r"extern +\"C\"|" # pylint: disable=bad-continuation
-                r"(typedef +)?(struct|union|enum)( *{)?$|"
-                r"} *;?$|"
-                r"$|"
-                r"//|"
-                r"#"
-            r")"
-        )
 
         files = self.get_files(include, exclude)
         self.log.debug("Looking for identifiers in {} files".format(len(files)))
 
         identifiers = []
         for header_file in files:
-            with open(header_file, "r", encoding="utf-8") as header:
-                in_block_comment = False
-                # The previous line variable is used for concatenating lines
-                # when identifiers are formatted and spread across multiple
-                # lines.
-                previous_line = ""
-
-                for line_no, line in enumerate(header):
-                    # Skip parsing this line if a block comment ends on it,
-                    # but don't skip if it has just started -- there is a chance
-                    # it ends on the same line.
-                    if re.search(r"/\*", line):
-                        in_block_comment = not in_block_comment
-                    if re.search(r"\*/", line):
-                        in_block_comment = not in_block_comment
-                        continue
-
-                    if in_block_comment:
-                        previous_line = ""
-                        continue
-
-                    if exclusion_lines.search(line):
-                        previous_line = ""
-                        continue
-
-                    # If the line contains only space-separated alphanumeric
-                    # characters (or underscore, asterisk, or, open bracket),
-                    # and nothing else, high chance it's a declaration that
-                    # continues on the next line
-                    if re.search(r"^([\w\*\(]+\s+)+$", line):
-                        previous_line += line
-                        continue
-
-                    # If previous line seemed to start an unfinished declaration
-                    # (as above), concat and treat them as one.
-                    if previous_line:
-                        line = previous_line.strip() + " " + line.strip() + "\n"
-                        previous_line = ""
-
-                    # Skip parsing if line has a space in front = heuristic to
-                    # skip function argument lines (highly subject to formatting
-                    # changes)
-                    if line[0] == " ":
-                        continue
-
-                    identifier = identifier_regex.search(line)
-
-                    if not identifier:
-                        continue
-
-                    # Find the group that matched, and append it
-                    for group in identifier.groups():
-                        if not group:
-                            continue
-
-                        identifiers.append(Match(
-                            header_file,
-                            line,
-                            line_no,
-                            identifier.span(),
-                            group))
+            self.parse_identifiers_in_file(header_file, identifiers)
 
         return identifiers
 
diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function
index 67fbb67..7baa3d5 100644
--- a/tests/suites/test_suite_base64.function
+++ b/tests/suites/test_suite_base64.function
@@ -1,6 +1,7 @@
 /* BEGIN_HEADER */
 #include "mbedtls/base64.h"
-#include "base64_invasive.h"
+#include "constant_time_internal.h"
+#include "constant_time_invasive.h"
 #include <test/constant_flow.h>
 
 #if defined(MBEDTLS_TEST_HOOKS)
@@ -24,7 +25,7 @@
     {
         mbedtls_test_set_step( c );
         TEST_CF_SECRET( &c, sizeof( c ) );
-        unsigned char m = mbedtls_base64_mask_of_range( low, high, c );
+        unsigned char m = mbedtls_ct_uchar_mask_of_range( low, high, c );
         TEST_CF_PUBLIC( &c, sizeof( c ) );
         TEST_CF_PUBLIC( &m, sizeof( m ) );
         if( low <= c && c <= high )
@@ -42,7 +43,7 @@
     {
         mbedtls_test_set_step( value );
         TEST_CF_SECRET( &value, sizeof( value ) );
-        unsigned char digit = mbedtls_base64_enc_char( value );
+        unsigned char digit = mbedtls_ct_base64_enc_char( value );
         TEST_CF_PUBLIC( &value, sizeof( value ) );
         TEST_CF_PUBLIC( &digit, sizeof( digit ) );
         TEST_EQUAL( digit, base64_digits[value] );
@@ -66,7 +67,7 @@
         else
             expected = p - base64_digits;
         TEST_CF_SECRET( &c, sizeof( c ) );
-        signed char actual = mbedtls_base64_dec_value( c );
+        signed char actual = mbedtls_ct_base64_dec_value( c );
         TEST_CF_PUBLIC( &c, sizeof( c ) );
         TEST_CF_PUBLIC( &actual, sizeof( actual ) );
         TEST_EQUAL( actual, expected );
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 08972c3..88ffe1b 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -256,10 +256,10 @@
     <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\size.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />

-    <ClInclude Include="..\..\library\base64_invasive.h" />

     <ClInclude Include="..\..\library\check_crypto_config.h" />

     <ClInclude Include="..\..\library\common.h" />

     <ClInclude Include="..\..\library\constant_time_internal.h" />

+    <ClInclude Include="..\..\library\constant_time_invasive.h" />

     <ClInclude Include="..\..\library\ecp_invasive.h" />

     <ClInclude Include="..\..\library\mps_common.h" />

     <ClInclude Include="..\..\library\mps_error.h" />