]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Allow a minimum TLS protocol version to be specified
authorMichael Brown <mcb30@ipxe.org>
Fri, 12 Jun 2020 20:40:33 +0000 (21:40 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 12 Jun 2020 20:40:33 +0000 (21:40 +0100)
The supported ciphers and digest algorithms may already be specified
via config/crypto.h.  Extend this to allow a minimum TLS protocol
version to be specified.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/config/crypto.h
src/net/tls.c

index 1edcdce457c7cab44d49c6beea45a664f70d9a95..d3c34a94d717bd776e7777db12b23744bc72f468 100644 (file)
@@ -9,6 +9,9 @@
 
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
+/** Minimum TLS version */
+#define TLS_VERSION_MIN TLS_VERSION_TLS_1_0
+
 /** RSA public-key algorithm */
 #define CRYPTO_PUBKEY_RSA
 
index 12045b01e31c2325852a52422cbd00f18815a0aa..ea827600f38b7e14a8feedf4639344760e6b5d9f 100644 (file)
@@ -49,6 +49,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/validator.h>
 #include <ipxe/job.h>
 #include <ipxe/tls.h>
+#include <config/crypto.h>
 
 /* Disambiguate the various error causes */
 #define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )
@@ -244,6 +245,23 @@ static int tls_ready ( struct tls_connection *tls ) {
                 ( ! is_pending ( &tls->server_negotiation ) ) );
 }
 
+/**
+ * Check for TLS version
+ *
+ * @v tls              TLS connection
+ * @v version          TLS version
+ * @ret at_least       TLS connection is using at least the specified version
+ *
+ * Check that TLS connection uses at least the specified protocol
+ * version.  Optimise down to a compile-time constant true result if
+ * this is already guaranteed by the minimum supported version check.
+ */
+static inline __attribute__ (( always_inline )) int
+tls_version ( struct tls_connection *tls, unsigned int version ) {
+       return ( ( TLS_VERSION_MIN >= version ) ||
+                ( tls->version >= version ) );
+}
+
 /******************************************************************************
  *
  * Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier
@@ -540,7 +558,7 @@ static void tls_prf ( struct tls_connection *tls, void *secret,
 
        va_start ( seeds, out_len );
 
-       if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
+       if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
                /* Use P_SHA256 for TLSv1.2 and later */
                tls_p_hash_va ( tls, &sha256_algorithm, secret, secret_len,
                                out, out_len, seeds );
@@ -1239,7 +1257,7 @@ static int tls_send_certificate_verify ( struct tls_connection *tls ) {
        }
 
        /* TLSv1.2 and later use explicit algorithm identifiers */
-       if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
+       if ( tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
                sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
                if ( ! sig_hash ) {
                        DBGC ( tls, "TLS %p could not identify (%s,%s) "
@@ -1558,7 +1576,7 @@ static int tls_new_server_hello ( struct tls_connection *tls,
 
        /* Check and store protocol version */
        version = ntohs ( hello_a->version );
-       if ( version < TLS_VERSION_TLS_1_0 ) {
+       if ( version < TLS_VERSION_MIN ) {
                DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
                       tls, ( version >> 8 ), ( version & 0xff ) );
                return -ENOTSUP_VERSION;
@@ -1576,7 +1594,7 @@ static int tls_new_server_hello ( struct tls_connection *tls,
        /* Use MD5+SHA1 digest algorithm for handshake verification
         * for versions earlier than TLSv1.2.
         */
-       if ( tls->version < TLS_VERSION_TLS_1_2 ) {
+       if ( ! tls_version ( tls, TLS_VERSION_TLS_1_2 ) ) {
                tls->handshake_digest = &md5_sha1_algorithm;
                tls->handshake_ctx = tls->handshake_md5_sha1_ctx;
        }
@@ -2258,7 +2276,7 @@ static void * tls_assemble_block ( struct tls_connection *tls,
        void *padding;
 
        /* TLSv1.1 and later use an explicit IV */
-       iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? blocksize : 0 );
+       iv_len = ( tls_version ( tls, TLS_VERSION_TLS_1_1 ) ? blocksize : 0 );
 
        /* Calculate block-ciphered struct length */
        padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
@@ -2420,7 +2438,7 @@ static int tls_split_block ( struct tls_connection *tls,
 
        /* TLSv1.1 and later use an explicit IV */
        iobuf = list_first_entry ( rx_data, struct io_buffer, list );
-       iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
+       iv_len = ( tls_version ( tls, TLS_VERSION_TLS_1_1 ) ?
                   tls->rx_cipherspec.suite->cipher->blocksize : 0 );
        if ( iob_len ( iobuf ) < iv_len ) {
                DBGC ( tls, "TLS %p received underlength IV\n", tls );