Document cipher suite configuration. The cipher suite rules could also be anchored on SSL_TXT_* if desired. I currently documented them in prose largely because SSL_TXT_* also defines protocol version strings and those are weird; SSL_TXT_TLSV1_1 isn't even a cipher rule. (And, in fact, those are the only SSL_TXT_* macros that we can't blindly remove. I found some code that #ifdef's the version SSL_TXT_* macros to decide if version-locked SSL_METHODs are available.) Also they clutter the header. I was thinking maybe we should dump a lot of the random constants into a separate undocumented header or perhaps just unexport them. I'm slightly torn on this though and could easily be convinced in the other direction. (Playing devil's advocate, anchoring on SSL_TXT_* means we're less likely to forget to document one so long as adding a SSL_TXT_* macro is the convention.) Change-Id: Ide2ae44db9d6d8f29c24943090c210da0108dc37 Reviewed-on: https://boringssl-review.googlesource.com/5962 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index b2adb3f..b5b6371 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -913,6 +913,131 @@ SSL *ssl, const SSL_PRIVATE_KEY_METHOD *key_method); +/* Cipher suite configuration. + * + * OpenSSL uses a mini-language to configure cipher suites. The language + * maintains an ordered list of enabled ciphers, along with an ordered list of + * disabled but available ciphers. Initially, all ciphers are disabled with a + * default ordering. The cipher string is then interpreted as a sequence of + * directives, separated by colons, each of which modifies this state. + * + * Most directives consist of a one character or empty opcode followed by a + * selector which matches a subset of available ciphers. + * + * Available opcodes are: + * + * The empty opcode enables and appends all matching disabled ciphers to the + * end of the enabled list. The newly appended ciphers are ordered relative to + * each other matching their order in the disabled list. + * + * |-| disables all matching enabled ciphers and prepends them to the disabled + * list, with relative order from the enabled list preserved. This means the + * most recently disabled ciphers get highest preference relative to other + * disabled ciphers if re-enabled. + * + * |+| moves all matching enabled ciphers to the end of the enabled list, with + * relative order preserved. + * + * |!| deletes all matching ciphers, enabled or not, from either list. Deleted + * ciphers will not matched by future operations. + * + * A selector may be a specific cipher (using the OpenSSL name for the cipher) + * or one or more rules separated by |+|. The final selector matches the + * intersection of each rule. For instance, |AESGCM+aECDSA| matches + * ECDSA-authenticated AES-GCM ciphers. + * + * Available cipher rules are: + * + * |ALL| matches all ciphers. + * + * |kRSA|, |kDHE|, |kECDHE|, and |kPSK| match ciphers using plain RSA, DHE, + * ECDHE, and plain PSK key exchanges, respectively. Note that ECDHE_PSK is + * matched by |kECDHE| and not |kPSK|. + * + * |aRSA|, |aECDSA|, and |aPSK| match ciphers authenticated by RSA, ECDSA, and + * a pre-shared key, respectively. + * + * |RSA|, |DHE|, |ECDHE|, |PSK|, |ECDSA|, and |PSK| are aliases for the + * corresponding |k*| or |a*| cipher rule. |RSA| is an alias for |kRSA|, not + * |aRSA|. + * + * |3DES|, |RC4|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match + * ciphers whose bulk cipher use the corresponding encryption scheme. Note + * that |AES|, |AES128|, and |AES256| match both CBC and GCM ciphers. + * + * |MD5|, |SHA1|, |SHA256|, and |SHA384| match legacy cipher suites using the + * corresponding hash function in their MAC. AEADs are matched by none of + * these. + * + * |SHA| is an alias for |SHA1|. + * + * Although implemented, authentication-only ciphers match no rules and must be + * explicitly selected by name. + * + * Deprecated cipher rules: + * + * |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|, + * |kECDHE|, and |ECDHE|, respectively. + * + * |MEDIUM| and |HIGH| match ciphers historically labeled by OpenSSL as + * 'medium' and 'high', respectively. + * + * |FIPS| matches ciphers historically FIPS-approved in OpenSSL. + * + * |SSLv3| and |TLSv1| match ciphers available in TLS 1.1 or earlier. + * |TLSv1_2| matches ciphers new in TLS 1.2. This is confusing and should not + * be used. + * + * Unknown rules silently match nothing. + * + * The special |@STRENGTH| directive will sort all enabled ciphers by strength. + * + * The |DEFAULT| directive, when appearing at the front of the string, expands + * to the default ordering of available ciphers. + * + * If configuring a server, one may also configure equal-preference groups to + * partially respect the client's preferences when + * |SSL_OP_CIPHER_SERVER_PREFERENCE| is enabled. Ciphers in an equal-preference + * group have equal priority and use the client order. This may be used to + * enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305 + * based on client preferences. An equal-preference is specified with square + * brackets, combining multiple selectors separated by |. For example: + * + * [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256] + * + * Once an equal-preference group is used, future directives must be + * opcode-less. */ + +/* SSL_DEFAULT_CIPHER_LIST is the default cipher suite configuration. It is + * substituted when a cipher string starts with 'DEFAULT'. */ +#define SSL_DEFAULT_CIPHER_LIST "ALL" + +/* SSL_CTX_set_cipher_list configures the cipher list for |ctx|, evaluating + * |str| as a cipher string. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); + +/* SSL_CTX_set_cipher_list configures the TLS 1.0+ cipher list for |ctx|, + * evaluating |str| as a cipher string. It returns one on success and zero on + * failure. If set, servers will use this cipher suite list for TLS 1.0 or + * higher. */ +OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str); + +/* SSL_CTX_set_cipher_list configures the TLS 1.1+ cipher list for |ctx|, + * evaluating |str| as a cipher string. It returns one on success and zero on + * failure. If set, servers will use this cipher suite list for TLS 1.1 or + * higher. */ +OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str); + +/* SSL_set_cipher_list configures the cipher list for |ssl|, evaluating |str| as + * a cipher string. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int SSL_set_cipher_list(SSL *ssl, const char *str); + +/* SSL_get_ciphers returns the cipher list for |ssl|, in order of preference. If + * |SSL_CTX_set_cipher_list_tls10| or |SSL_CTX_set_cipher_list_tls11| has been + * used, the corresponding list for the current version is returned. */ +OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl); + + /* Connection information. */ /* SSL_get_peer_certificate returns the peer's leaf certificate or NULL if the @@ -2310,30 +2435,8 @@ #define SSL_TXT_ALL "ALL" -/* COMPLEMENTOF* definitions. These identifiers are used to (de-select) ciphers - * normally not being used. - * - * Example: "RC4" will activate all ciphers using RC4 including ciphers without - * authentication, which would normally disabled by DEFAULT (due the "!ADH" - * being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" will make sure - * that it is also disabled in the specific selection. COMPLEMENTOF* - * identifiers are portable between version, as adjustments to the default - * cipher setup will also be included here. - * - * COMPLEMENTOFDEFAULT does not experience the same special treatment that - * DEFAULT gets, as only selection is being done and no sorting as needed for - * DEFAULT. */ #define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" -/* The following cipher list is used by default. It also is substituted when an - * application-defined cipher list string starts with 'DEFAULT'. */ -#define SSL_DEFAULT_CIPHER_LIST "ALL" - -/* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always - * starts with a reasonable order, and all we have to do for DEFAULT is - * throwing out anonymous and unencrypted ciphersuites! (The latter are not - * actually enabled by ALL, but "ALL:RSA" would enable some of them.) */ - /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ #define SSL_SENT_SHUTDOWN 1 #define SSL_RECEIVED_SHUTDOWN 2 @@ -2536,20 +2639,15 @@ OPENSSL_EXPORT size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types); -OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str); -OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls10(SSL_CTX *, const char *str); -OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls11(SSL_CTX *, const char *str); OPENSSL_EXPORT int SSL_want(const SSL *s); OPENSSL_EXPORT int SSL_get_fd(const SSL *s); OPENSSL_EXPORT int SSL_get_rfd(const SSL *s); OPENSSL_EXPORT int SSL_get_wfd(const SSL *s); -OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *s, int n); OPENSSL_EXPORT int SSL_pending(const SSL *s); OPENSSL_EXPORT int SSL_set_fd(SSL *s, int fd); OPENSSL_EXPORT int SSL_set_rfd(SSL *s, int fd); OPENSSL_EXPORT int SSL_set_wfd(SSL *s, int fd); -OPENSSL_EXPORT int SSL_set_cipher_list(SSL *s, const char *str); OPENSSL_EXPORT const char *SSL_state_string(const SSL *s); OPENSSL_EXPORT const char *SSL_state_string_long(const SSL *s); @@ -2557,8 +2655,6 @@ OPENSSL_EXPORT int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses); OPENSSL_EXPORT int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses); -OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); - /* SSL_renegotiate_pending returns one if |ssl| is in the middle of a * renegotiation. */ OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl); @@ -2896,6 +2992,10 @@ * For example, "TLSv1.2" or "SSLv3". */ OPENSSL_EXPORT const char *SSL_get_version(const SSL *ssl); +/* SSL_get_cipher_list returns the name of the |n|th cipher in the output of + * |SSL_get_ciphers| or NULL if out of range. Use |SSL_get_ciphers| insteads. */ +OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *ssl, int n); + /* Private structures. *
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 74bd633..5190a53 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c
@@ -1367,29 +1367,27 @@ return ctx->session_cache_mode; } -/* return a STACK of the ciphers available for the SSL and in order of - * preference */ -STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) { - if (s == NULL) { +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) { + if (ssl == NULL) { return NULL; } - if (s->cipher_list != NULL) { - return s->cipher_list->ciphers; + if (ssl->cipher_list != NULL) { + return ssl->cipher_list->ciphers; } - if (s->version >= TLS1_1_VERSION && s->ctx != NULL && - s->ctx->cipher_list_tls11 != NULL) { - return s->ctx->cipher_list_tls11->ciphers; + if (ssl->version >= TLS1_1_VERSION && ssl->ctx != NULL && + ssl->ctx->cipher_list_tls11 != NULL) { + return ssl->ctx->cipher_list_tls11->ciphers; } - if (s->version >= TLS1_VERSION && s->ctx != NULL && - s->ctx->cipher_list_tls10 != NULL) { - return s->ctx->cipher_list_tls10->ciphers; + if (ssl->version >= TLS1_VERSION && ssl->ctx != NULL && + ssl->ctx->cipher_list_tls10 != NULL) { + return ssl->ctx->cipher_list_tls10->ciphers; } - if (s->ctx != NULL && s->ctx->cipher_list != NULL) { - return s->ctx->cipher_list->ciphers; + if (ssl->ctx != NULL && ssl->ctx->cipher_list != NULL) { + return ssl->ctx->cipher_list->ciphers; } return NULL; @@ -1413,16 +1411,15 @@ return NULL; } -/* The old interface to get the same thing as SSL_get_ciphers() */ -const char *SSL_get_cipher_list(const SSL *s, int n) { +const char *SSL_get_cipher_list(const SSL *ssl, int n) { const SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *sk; - if (s == NULL) { + if (ssl == NULL) { return NULL; } - sk = SSL_get_ciphers(s); + sk = SSL_get_ciphers(ssl); if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) { return NULL; } @@ -1435,20 +1432,15 @@ return c->name; } -/* specify the ciphers to be used by default by the SSL_CTX */ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { - STACK_OF(SSL_CIPHER) *sk; - - sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, - &ctx->cipher_list_by_id, str); - /* ssl_create_cipher_list may return an empty stack if it was unable to find - * a cipher matching the given rule string (for example if the rule string - * specifies a cipher which has been disabled). This is not an error as far - * as ssl_create_cipher_list is concerned, and hence ctx->cipher_list and - * ctx->cipher_list_by_id has been updated. */ - if (sk == NULL) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list, &ctx->cipher_list_by_id, str); + if (cipher_list == NULL) { return 0; - } else if (sk_SSL_CIPHER_num(sk) == 0) { + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); return 0; } @@ -1457,12 +1449,14 @@ } int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str) { - STACK_OF(SSL_CIPHER) *sk; - - sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls10, NULL, str); - if (sk == NULL) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list_tls10, NULL, str); + if (cipher_list == NULL) { return 0; - } else if (sk_SSL_CIPHER_num(sk) == 0) { + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); return 0; } @@ -1471,12 +1465,14 @@ } int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) { - STACK_OF(SSL_CIPHER) *sk; - - sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str); - if (sk == NULL) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list_tls11, NULL, str); + if (cipher_list == NULL) { return 0; - } else if (sk_SSL_CIPHER_num(sk) == 0) { + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); return 0; } @@ -1484,17 +1480,15 @@ return 1; } -/* specify the ciphers to be used by the SSL */ -int SSL_set_cipher_list(SSL *s, const char *str) { - STACK_OF(SSL_CIPHER) *sk; - - sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, - &s->cipher_list_by_id, str); - - /* see comment in SSL_CTX_set_cipher_list */ - if (sk == NULL) { +int SSL_set_cipher_list(SSL *ssl, const char *str) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ssl->ctx->method, &ssl->cipher_list, &ssl->cipher_list_by_id, str); + if (cipher_list == NULL) { return 0; - } else if (sk_SSL_CIPHER_num(sk) == 0) { + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); return 0; }