mbedtls_ssl_handshake_params: reorder fields to save code size

Reorder fields mbedtls_ssl_handshake_params in order to save code on Arm
Thumb builds. The general idea is to put often-used fields in the direct
access window of 128 elements from the beginning of the structure.

The reordering is a human selection based on a report of field offset and
use counts, and informed by measuring the code size with various
arrangements. Some notes:
* This is the same reordering as the corresponding commit in #5189 for 2.2x.
* I moved most byte-sized fields at the beginning where they're sure to be
  in the direct access window.
* I moved buffering earlier because it can be around the threshold depending
  on the configuration, and it's accessed in a lot of places.
* I moved several fields, including update_checksum and friends, early so
  that they're guaranteed to be in the early access window.

Results (arm-none-eabi-gcc 7.3.1, build_arm_none_eabi_gcc_m0plus build):
library/ssl_cli.o: 19763 -> 19687 (diff: 76)
library/ssl_msg.o: 24874 -> 24834 (diff: 40)
library/ssl_srv.o: 20754 -> 20562 (diff: 192)
library/ssl_tls.o: 21003 -> 20907 (diff: 96)
library/ssl_tls13_client.o: 7284 -> 7272 (diff: 12)
library/ssl_tls13_generic.o: 4749 -> 4721 (diff: 28)
library/ssl_tls13_keys.o: 5133 -> 5077 (diff: 56)

Results (same architecture, config-suite-b.h + MBEDTLS_ECDH_LEGACY_CONTEXT +
MBEDTLS_ECP_RESTARTABLE):
library/ssl_cli.o: 3000 -> 2936 (diff: 64)
library/ssl_msg.o: 3084 -> 3080 (diff: 4)
library/ssl_srv.o: 3428 -> 3400 (diff: 28)
library/ssl_tls.o: 6754 -> 6730 (diff: 24)

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2021-11-29 12:18:09 +01:00
parent 55490d4e1f
commit ec45c1e174

View file

@ -525,6 +525,56 @@ typedef struct
*/ */
struct mbedtls_ssl_handshake_params struct mbedtls_ssl_handshake_params
{ {
/* Frequently-used boolean or byte fields (placed early to take
* advantage of smaller code size for indirect access on Arm Thumb) */
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_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? */
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
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;
/* /*
* Handshake specific crypto variables * Handshake specific crypto variables
*/ */
@ -532,11 +582,6 @@ struct mbedtls_ssl_handshake_params
int tls1_3_kex_modes; /*!< key exchange modes for TLS 1.3 */ int tls1_3_kex_modes; /*!< key exchange modes for TLS 1.3 */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
const uint16_t *group_list;
unsigned char group_list_heap_allocated;
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */
@ -587,65 +632,17 @@ struct mbedtls_ssl_handshake_params
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
uint8_t sni_authmode; /*!< authmode from SNI callback */
mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ 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_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
uint8_t 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) !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */
#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #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[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< 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 struct
{ {
size_t total_bytes_buffered; /*!< Cumulative size of heap allocated size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
@ -672,6 +669,38 @@ struct mbedtls_ssl_handshake_params
} buffering; } buffering;
#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 */
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[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< 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 */ uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */
#endif /* MBEDTLS_SSL_PROTO_DTLS */ #endif /* MBEDTLS_SSL_PROTO_DTLS */
@ -702,11 +731,6 @@ struct mbedtls_ssl_handshake_params
#endif #endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #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;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
uint16_t offered_group_id; /* The NamedGroup value for the group uint16_t offered_group_id; /* The NamedGroup value for the group
* that is being used for ephemeral * that is being used for ephemeral
@ -749,20 +773,12 @@ struct mbedtls_ssl_handshake_params
/* End of state-local variables. */ /* End of state-local variables. */
mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
size_t pmslen; /*!< premaster length */
unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +
MBEDTLS_SERVER_HELLO_RANDOM_LEN]; MBEDTLS_SERVER_HELLO_RANDOM_LEN];
/*!< random bytes */ /*!< random bytes */
unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
/*!< premaster secret */ /*!< premaster secret */
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_SSL_PROTO_TLS1_3_EXPERIMENTAL) #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
int extensions_present; /*!< extension presence; Each bitfield int extensions_present; /*!< extension presence; Each bitfield
represents an extension and defined represents an extension and defined
@ -778,18 +794,6 @@ struct mbedtls_ssl_handshake_params
mbedtls_ssl_tls1_3_handshake_secrets tls13_hs_secrets; mbedtls_ssl_tls1_3_handshake_secrets tls13_hs_secrets;
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
#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_ASYNC_PRIVATE) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/** Asynchronous operation context. This field is meant for use by the /** Asynchronous operation context. This field is meant for use by the
* asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
@ -798,6 +802,11 @@ struct mbedtls_ssl_handshake_params
* The library does not use it internally. */ * The library does not use it internally. */
void *user_async_ctx; void *user_async_ctx;
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
const uint16_t *group_list;
unsigned char group_list_heap_allocated;
#endif
}; };
typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;