diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 35443772..6dd0dd82 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -877,7 +877,7 @@ struct ssl_ctx_st { uint32_t options; uint32_t mode; - long max_cert_list; + uint32_t max_cert_list; struct cert_st /* CERT */ *cert; int read_ahead; @@ -917,7 +917,7 @@ struct ssl_ctx_st { /* Maximum amount of data to send in one fragment. actual record size can be * more than this due to padding and MAC overheads. */ - unsigned int max_send_fragment; + uint16_t max_send_fragment; /* TLS extensions servername callback */ int (*tlsext_servername_callback)(SSL *, int *, void *); @@ -1360,10 +1360,10 @@ struct ssl_st { uint32_t options; /* protocol behaviour */ uint32_t mode; /* API behaviour */ - long max_cert_list; + uint32_t max_cert_list; int client_version; /* what was passed, used for * SSLv3/TLS rollback check */ - unsigned int max_send_fragment; + uint16_t max_send_fragment; char *tlsext_hostname; /* should_ack_sni is true if the SNI extension should be acked. This is * only used by a server. */ @@ -1605,11 +1605,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) #define SSL_CTRL_SET_SESS_CACHE_MODE 44 #define SSL_CTRL_GET_SESS_CACHE_MODE 45 -#define SSL_CTRL_GET_MAX_CERT_LIST 50 -#define SSL_CTRL_SET_MAX_CERT_LIST 51 - -#define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52 - /* see tls1.h for macros based on these */ #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 @@ -2158,19 +2153,37 @@ OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void); * is resolved. */ OPENSSL_EXPORT int SSL_CTX_get_read_ahead(const SSL_CTX *ctx); OPENSSL_EXPORT void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes); -#define SSL_CTX_get_max_cert_list(ctx) \ - SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_CERT_LIST, 0, NULL) -#define SSL_CTX_set_max_cert_list(ctx, m) \ - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_CERT_LIST, m, NULL) -#define SSL_get_max_cert_list(ssl) \ - SSL_ctrl(ssl, SSL_CTRL_GET_MAX_CERT_LIST, 0, NULL) -#define SSL_set_max_cert_list(ssl, m) \ - SSL_ctrl(ssl, SSL_CTRL_SET_MAX_CERT_LIST, m, NULL) - -#define SSL_CTX_set_max_send_fragment(ctx, m) \ - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_SEND_FRAGMENT, m, NULL) -#define SSL_set_max_send_fragment(ssl, m) \ - SSL_ctrl(ssl, SSL_CTRL_SET_MAX_SEND_FRAGMENT, m, NULL) + +/* SSL_CTX_get_max_cert_list returns the maximum length, in bytes, of a peer + * certificate chain accepted by |ctx|. */ +OPENSSL_EXPORT size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx); + +/* SSL_CTX_set_max_cert_list sets the maximum length, in bytes, of a peer + * certificate chain to |max_cert_list|. This affects how much memory may be + * consumed during the handshake. */ +OPENSSL_EXPORT void SSL_CTX_set_max_cert_list(SSL_CTX *ctx, + size_t max_cert_list); + +/* SSL_get_max_cert_list returns the maximum length, in bytes, of a peer + * certificate chain accepted by |ssl|. */ +OPENSSL_EXPORT size_t SSL_get_max_cert_list(const SSL *ssl); + +/* SSL_set_max_cert_list sets the maximum length, in bytes, of a peer + * certificate chain to |max_cert_list|. This affects how much memory may be + * consumed during the handshake. */ +OPENSSL_EXPORT void SSL_set_max_cert_list(SSL *ssl, size_t max_cert_list); + +/* SSL_CTX_set_max_send_fragment sets the maximum length, in bytes, of records + * sent by |ctx|. Beyond this length, handshake messages and application data + * will be split into multiple records. */ +OPENSSL_EXPORT void SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, + size_t max_send_fragment); + +/* SSL_set_max_send_fragment sets the maximum length, in bytes, of records + * sent by |ssl|. Beyond this length, handshake messages and application data + * will be split into multiple records. */ +OPENSSL_EXPORT void SSL_set_max_send_fragment(SSL *ssl, + size_t max_send_fragment); /* SSL_CTX_set_tmp_dh_callback configures |ctx| to use |callback| to determine * the group for DHE ciphers. |callback| should ignore |is_export| and @@ -2387,6 +2400,9 @@ OPENSSL_EXPORT const char *SSLeay_version(int unused); #define SSL_CTRL_MODE doesnt_exist #define SSL_CTRL_GET_READ_AHEAD doesnt_exist #define SSL_CTRL_SET_READ_AHEAD doesnt_exist +#define SSL_CTRL_GET_MAX_CERT_LIST doesnt_exist +#define SSL_CTRL_SET_MAX_CERT_LIST doesnt_exist +#define SSL_CTRL_SET_MAX_SEND_FRAGMENT doesnt_exist #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB doesnt_exist #define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB doesnt_exist #define DTLS_CTRL_GET_TIMEOUT doesnt_exist @@ -2406,6 +2422,12 @@ OPENSSL_EXPORT const char *SSLeay_version(int unused); #define SSL_set_mode SSL_set_mode #define SSL_CTX_get_read_ahead SSL_CTX_get_read_ahead #define SSL_CTX_set_read_ahead SSL_CTX_set_read_ahead +#define SSL_CTX_get_max_cert_list SSL_CTX_get_max_cert_list +#define SSL_get_max_cert_list SSL_get_max_cert_list +#define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list +#define SSL_set_max_cert_list SSL_set_max_cert_list +#define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment +#define SSL_set_max_send_fragment SSL_set_max_send_fragment #define SSL_CTX_set_tlsext_servername_callback \ SSL_CTX_set_tlsext_servername_callback #define SSL_CTX_set_tlsext_ticket_key_cb SSL_CTX_set_tlsext_ticket_key_cb diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 6ce508fa..662f518f 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -470,8 +470,8 @@ static hm_fragment *dtls1_get_buffered_message( * be greater if the maximum certificate list size requires it. */ static size_t dtls1_max_handshake_message_len(const SSL *s) { size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; - if (max_len < (size_t)s->max_cert_list) { - return (size_t)s->max_cert_list; + if (max_len < s->max_cert_list) { + return s->max_cert_list; } return max_len; } diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 5efccd44..8bf3f0d4 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -925,7 +925,7 @@ int ssl3_get_server_certificate(SSL *s) { const uint8_t *data; n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B, - SSL3_MT_CERTIFICATE, s->max_cert_list, + SSL3_MT_CERTIFICATE, (long)s->max_cert_list, ssl_hash_message, &ok); if (!ok) { diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index bb224f85..8716f7c7 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -2220,7 +2220,7 @@ int ssl3_get_client_certificate(SSL *s) { int is_first_certificate = 1; n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, - s->max_cert_list, ssl_hash_message, &ok); + (long)s->max_cert_list, ssl_hash_message, &ok); if (!ok) { return n; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 961dec0f..7edcacf5 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -161,6 +161,9 @@ OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, ssl_alert_reason_code_mismatch); +/* kMaxHandshakeSize is the maximum size, in bytes, of a handshake message. */ +static const size_t kMaxHandshakeSize = (1u << 24) - 1; + static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl = CRYPTO_EX_DATA_CLASS_INIT; static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx = CRYPTO_EX_DATA_CLASS_INIT; @@ -1009,18 +1012,50 @@ uint32_t SSL_CTX_get_mode(const SSL_CTX *ctx) { return ctx->mode; } uint32_t SSL_get_mode(const SSL *ssl) { return ssl->mode; } -long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { - long l; +size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx) { + return ctx->max_cert_list; +} - switch (cmd) { - case SSL_CTRL_GET_MAX_CERT_LIST: - return s->max_cert_list; +void SSL_CTX_set_max_cert_list(SSL_CTX *ctx, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; + } + ctx->max_cert_list = (uint32_t)max_cert_list; +} - case SSL_CTRL_SET_MAX_CERT_LIST: - l = s->max_cert_list; - s->max_cert_list = larg; - return l; +size_t SSL_get_max_cert_list(const SSL *ssl) { + return ssl->max_cert_list; +} + +void SSL_set_max_cert_list(SSL *ssl, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; + } + ssl->max_cert_list = (uint32_t)max_cert_list; +} + +void SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ctx->max_send_fragment = (uint16_t)max_send_fragment; +} +void SSL_set_max_send_fragment(SSL *ssl, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ssl->max_send_fragment = (uint16_t)max_send_fragment; +} + +long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { + switch (cmd) { case SSL_CTRL_SET_MTU: if (larg < (long)dtls1_min_mtu()) { return 0; @@ -1031,13 +1066,6 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { } return 0; - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { - return 0; - } - s->max_send_fragment = larg; - return 1; - case SSL_CTRL_GET_RI_SUPPORT: if (s->s3) { return s->s3->send_connection_binding; @@ -1068,14 +1096,6 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { long l; switch (cmd) { - case SSL_CTRL_GET_MAX_CERT_LIST: - return ctx->max_cert_list; - - case SSL_CTRL_SET_MAX_CERT_LIST: - l = ctx->max_cert_list; - ctx->max_cert_list = larg; - return l; - case SSL_CTRL_SET_SESS_CACHE_SIZE: l = ctx->session_cache_size; ctx->session_cache_size = larg; @@ -1095,13 +1115,6 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { case SSL_CTRL_SESS_NUMBER: return lh_SSL_SESSION_num_items(ctx->sessions); - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { - return 0; - } - ctx->max_send_fragment = larg; - return 1; - default: return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); }