Introduce tools for transport-specific code
And use those tools in a few places. For now the purpose is just to validate
those tools before using them in all occurrences of transport-specific code.
The effect of these changes was measured with the following script:
```
set -eu
build() {
printf "\n$1\n"
CC=arm-none-eabi-gcc CFLAGS='-Werror -Os -march=armv6-m -mthumb' \
AR=arm-none-eabi-ar LD=arm-none-eabi-ld make clean lib >/dev/null
arm-none-eabi-size -t library/libmbedtls.a
}
git checkout -- include/mbedtls/config.h
scripts/config.pl unset MBEDTLS_NET_C
scripts/config.pl unset MBEDTLS_TIMING_C
scripts/config.pl unset MBEDTLS_FS_IO
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
build "both"
scripts/config.pl unset MBEDTLS_SSL_PROTO_TLS
build "DTLS-only"
scripts/config.pl set MBEDTLS_SSL_PROTO_TLS
scripts/config.pl unset MBEDTLS_SSL_PROTO_DTLS
scripts/config.pl unset MBEDTLS_SSL_DTLS_HELLO_VERIFY
scripts/config.pl unset MBEDTLS_SSL_DTLS_ANTI_REPLAY
scripts/config.pl unset MBEDTLS_SSL_DTLS_BADMAC_LIMIT
scripts/config.pl unset MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
build "TLS-only"
git checkout -- include/mbedtls/config.h
```
The output of the script is as follows:
```
both
text data bss dec hex filename
1820 0 4 1824 720 debug.o (ex library/libmbedtls.a)
0 0 0 0 0 net_sockets.o (ex library/libmbedtls.a)
548 0 0 548 224 ssl_cache.o (ex library/libmbedtls.a)
11155 0 596 11751 2de7 ssl_ciphersuites.o (ex library/libmbedtls.a)
17160 0 0 17160 4308 ssl_cli.o (ex library/libmbedtls.a)
460 0 0 460 1cc ssl_cookie.o (ex library/libmbedtls.a)
17637 0 0 17637 44e5 ssl_srv.o (ex library/libmbedtls.a)
800 0 0 800 320 ssl_ticket.o (ex library/libmbedtls.a)
39322 60 0 39382 99d6 ssl_tls.o (ex library/libmbedtls.a)
88902 60 600 89562 15dda (TOTALS)
DTLS-only
text data bss dec hex filename
1820 0 4 1824 720 debug.o (ex library/libmbedtls.a)
0 0 0 0 0 net_sockets.o (ex library/libmbedtls.a)
548 0 0 548 224 ssl_cache.o (ex library/libmbedtls.a)
11155 0 596 11751 2de7 ssl_ciphersuites.o (ex library/libmbedtls.a)
17072 0 0 17072 42b0 ssl_cli.o (ex library/libmbedtls.a)
460 0 0 460 1cc ssl_cookie.o (ex library/libmbedtls.a)
17565 0 0 17565 449d ssl_srv.o (ex library/libmbedtls.a)
800 0 0 800 320 ssl_ticket.o (ex library/libmbedtls.a)
38953 60 0 39013 9865 ssl_tls.o (ex library/libmbedtls.a)
88373 60 600 89033 15bc9 (TOTALS)
TLS-only
text data bss dec hex filename
1820 0 4 1824 720 debug.o (ex library/libmbedtls.a)
0 0 0 0 0 net_sockets.o (ex library/libmbedtls.a)
548 0 0 548 224 ssl_cache.o (ex library/libmbedtls.a)
11155 0 596 11751 2de7 ssl_ciphersuites.o (ex library/libmbedtls.a)
14916 0 0 14916 3a44 ssl_cli.o (ex library/libmbedtls.a)
460 0 0 460 1cc ssl_cookie.o (ex library/libmbedtls.a)
15852 0 0 15852 3dec ssl_srv.o (ex library/libmbedtls.a)
800 0 0 800 320 ssl_ticket.o (ex library/libmbedtls.a)
27623 60 0 27683 6c23 ssl_tls.o (ex library/libmbedtls.a)
73174 60 600 73834 1206a (TOTALS)
```
It can be seen that a DTLS-only build is now starting to be a bit smaller than
a dual-mode build, which is the purpose of the new build option.
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 45ea26a..173b6d5 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -264,6 +264,57 @@
#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0)
#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1)
+/*
+ * Helpers for code specific to TLS or DTLS.
+ *
+ * Goals for these helpers:
+ * - generate minimal code, eg don't test if mode is DTLS in a DTLS-only build
+ * - make the flow clear to the compiler, ie that in dual-mode builds,
+ * when there are two branchs, exactly one of them is taken
+ * - preserve readability
+ *
+ * There are three macros:
+ * - MBEDTLS_SSL_TRANSPORT_IS_TLS( transport )
+ * - MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport )
+ * - MBEDTLS_SSL_TRANSPORT_ELSE
+ *
+ * The first two are macros rather than static inline functions because some
+ * compilers (eg arm-none-eabi-gcc 5.4.1 20160919) don't propagate constants
+ * well enough for us with static inline functions.
+ *
+ * Usage 1 (can replace DTLS with TLS):
+ * #if defined(MBEDTLS_SSL_PROTO_DTLS)
+ * if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport ) )
+ * // DTLS-specific code
+ * #endif
+ *
+ * Usage 2 (can swap DTLS and TLS);
+ * #if defined(MBEDTLS_SSL_PROTO_DTLS)
+ * if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport ) )
+ * // DTLS-specific code
+ * MBEDTLS_SSL_TRANSPORT_ELSE
+ * #endif
+ * #if defined(MBEDTLS_SSL_PROTO_TLS)
+ * // TLS-specific code
+ * #endif
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_SSL_PROTO_TLS) /* both */
+#define MBEDTLS_SSL_TRANSPORT__BOTH /* shorcut for future tests */
+#define MBEDTLS_SSL_TRANSPORT_IS_TLS( transport ) \
+ ( (transport) == MBEDTLS_SSL_TRANSPORT_STREAM )
+#define MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport ) \
+ ( (transport) == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+#define MBEDTLS_SSL_TRANSPORT_ELSE else
+#elif defined(MBEDTLS_SSL_PROTO_DTLS) /* DTLS only */
+#define MBEDTLS_SSL_TRANSPORT_IS_TLS( transport ) 0
+#define MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport ) 1
+#define MBEDTLS_SSL_TRANSPORT_ELSE /* empty: no other branch */
+#else /* TLS only */
+#define MBEDTLS_SSL_TRANSPORT_IS_TLS( transport ) 1
+#define MBEDTLS_SSL_TRANSPORT_IS_DTLS( transport ) 0
+#define MBEDTLS_SSL_TRANSPORT_ELSE /* empty: no other branch */
+#endif /* TLS and/or DTLS */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -905,12 +956,14 @@
static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- return( 12 );
-#else
+#if !defined(MBEDTLS_SSL_PROTO__BOTH)
((void) ssl);
#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
+ return( 12 );
+#endif
return( 4 );
}