-/* ssl/ssl_ciph.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#define CIPHER_DEL 3
#define CIPHER_ORD 4
#define CIPHER_SPECIAL 5
+/*
+ * Bump the ciphers to the top of the list.
+ * This rule isn't currently supported by the public cipherstring API.
+ */
+#define CIPHER_BUMP 6
typedef struct cipher_order_st {
const SSL_CIPHER *cipher;
* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in
* ALL!)
*/
- {0, SSL_TXT_CMPDEF, 0, 0, 0, ~SSL_eNULL, 0, 0, SSL_NOT_DEFAULT, 0, 0, 0},
+ {0, SSL_TXT_CMPDEF, 0, 0, 0, 0, 0, 0, SSL_NOT_DEFAULT, 0, 0, 0},
/*
* key exchange aliases (some of those using only a single bit here
{0, SSL_TXT_DH, 0, SSL_kDHE, 0, 0, 0, 0, 0, 0, 0,
0},
- {0, SSL_TXT_kECDHr, 0, SSL_kECDHr, 0, 0, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_kECDHe, 0, SSL_kECDHe, 0, 0, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_kECDH, 0, SSL_kECDHr | SSL_kECDHe, 0, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_kEECDH, 0, SSL_kECDHE, 0, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_kECDHE, 0, SSL_kECDHE, 0, 0, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_ECDH, 0, SSL_kECDHr | SSL_kECDHe | SSL_kECDHE, 0, 0, 0, 0, 0,
+ {0, SSL_TXT_ECDH, 0, SSL_kECDHE, 0, 0, 0, 0, 0,
0, 0, 0},
{0, SSL_TXT_kPSK, 0, SSL_kPSK, 0, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aDSS, 0, 0, SSL_aDSS, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_DSS, 0, 0, SSL_aDSS, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aNULL, 0, 0, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_aECDH, 0, 0, SSL_aECDH, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aPSK, 0, 0, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
0, 0},
{0, SSL_TXT_CAMELLIA128, 0, 0, 0, SSL_CAMELLIA128, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_CAMELLIA256, 0, 0, 0, SSL_CAMELLIA256, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_CAMELLIA, 0, 0, 0, SSL_CAMELLIA128 | SSL_CAMELLIA256, 0, 0, 0,
- 0, 0, 0},
+ {0, SSL_TXT_CAMELLIA, 0, 0, 0, SSL_CAMELLIA, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20, 0, 0, 0, 0, 0, 0 },
/* MAC aliases */
{0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5, 0, 0, 0, 0, 0},
ameth) <= 0)
pkey_id = 0;
}
- if (tmpeng)
- ENGINE_finish(tmpeng);
+ ENGINE_finish(tmpeng);
return pkey_id;
}
disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK;
#endif
#ifdef OPENSSL_NO_EC
- disabled_mkey_mask |= SSL_kECDHe | SSL_kECDHr | SSL_kECDHEPSK;
- disabled_auth_mask |= SSL_aECDSA | SSL_aECDH;
+ disabled_mkey_mask |= SSL_kECDHEPSK;
+ disabled_auth_mask |= SSL_aECDSA;
#endif
#ifdef OPENSSL_NO_PSK
disabled_mkey_mask |= SSL_PSK;
SSL_COMP *comp = NULL;
COMP_METHOD *method = COMP_zlib();
- MemCheck_off();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
if (COMP_get_type(method) != NID_undef
&& ssl_comp_methods != NULL) {
sk_SSL_COMP_sort(ssl_comp_methods);
}
}
- MemCheck_on();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
}
}
#ifdef CIPHER_DEBUG
fprintf(stderr,
- "Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n",
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl,
algo_strength, strength_bits);
#endif
- if (rule == CIPHER_DEL)
+ if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
reverse = 1; /* needed to maintain sorting between
* currently deleted ciphers */
} else {
#ifdef CIPHER_DEBUG
fprintf(stderr,
- "\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n",
+ "\nName: %s:\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n",
cp->name, cp->algorithm_mkey, cp->algorithm_auth,
cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl,
cp->algo_strength);
-#endif
-#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
- if (cipher_id && cipher_id != cp->id)
- continue;
#endif
if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
continue;
ll_append_head(&head, curr, &tail);
curr->active = 0;
}
+ } else if (rule == CIPHER_BUMP) {
+ if (curr->active)
+ ll_append_head(&head, curr, &tail);
} else if (rule == CIPHER_KILL) {
/* reverse == 0 */
if (head == curr)
disabled_mac, disabled_ssl, co_list, &head,
&tail);
- /* Now arrange all ciphers by preference: */
+ /* Now arrange all ciphers by preference. */
/*
* Everything else being equal, prefer ephemeral ECDH over other key
- * exchange mechanisms
+ * exchange mechanisms.
+ * For consistency, prefer ECDSA over RSA (though this only matters if the
+ * server has both certificates, and is using the DEFAULT, or a client
+ * preference).
*/
+ ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
+ -1, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
&tail);
- /* AES is our preferred symmetric cipher */
- ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, &head,
- &tail);
+
+ /* Within each strength group, we prefer GCM over CHACHA... */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
+ &head, &tail);
+
+ /*
+ * ...and generally, our preferred cipher is AES.
+ * Note that AEADs will be bumped to take preference after sorting by
+ * strength.
+ */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
+ -1, &head, &tail);
/* Temporarily enable everything else for sorting */
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
&tail);
- /* Move ciphers without forward secrecy to the end */
- ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
- &tail);
/*
* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1,
* &head, &tail);
return NULL;
}
+ /*
+ * Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
+ * TODO(openssl-team): is there an easier way to accomplish all this?
+ */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, SSL_TLSV1_2, 0, CIPHER_BUMP, -1,
+ &head, &tail);
+
+ /*
+ * Irrespective of strength, enforce the following order:
+ * (EC)DHE + AEAD > (EC)DHE > rest of AEAD > rest.
+ * Within each group, ciphers remain sorted by strength and previous
+ * preference, i.e.,
+ * 1) ECDHE > DHE
+ * 2) GCM > CHACHA
+ * 3) AES > rest
+ * 4) TLS 1.2 > legacy
+ *
+ * Because we now bump ciphers to the top of the list, we proceed in
+ * reverse order of preference.
+ */
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
+ CIPHER_BUMP, -1, &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
+ CIPHER_BUMP, -1, &head, &tail);
+
/* Now disable everything (maintaining the ordering!) */
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
{
const char *ver;
const char *kx, *au, *enc, *mac;
- uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl;
+ uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
static const char *format =
"%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
+ if (buf == NULL) {
+ len = 128;
+ buf = OPENSSL_malloc(len);
+ if (buf == NULL)
+ return NULL;
+ } else if (len < 128)
+ return NULL;
+
alg_mkey = cipher->algorithm_mkey;
alg_auth = cipher->algorithm_auth;
alg_enc = cipher->algorithm_enc;
alg_mac = cipher->algorithm_mac;
- alg_ssl = cipher->algorithm_ssl;
- if (alg_ssl & SSL_SSLV3)
- ver = "SSLv3";
- else if (alg_ssl & SSL_TLSV1)
- ver = "TLSv1.0";
- else if (alg_ssl & SSL_TLSV1_2)
- ver = "TLSv1.2";
- else
- ver = "unknown";
+ ver = SSL_CIPHER_get_version(cipher);
switch (alg_mkey) {
case SSL_kRSA:
case SSL_kDHE:
kx = "DH";
break;
- case SSL_kECDHr:
- kx = "ECDH/RSA";
- break;
- case SSL_kECDHe:
- kx = "ECDH/ECDSA";
- break;
case SSL_kECDHE:
kx = "ECDH";
break;
case SSL_aDSS:
au = "DSS";
break;
- case SSL_aECDH:
- au = "ECDH";
- break;
case SSL_aNULL:
au = "None";
break;
break;
}
- if (buf == NULL) {
- len = 128;
- buf = OPENSSL_malloc(len);
- if (buf == NULL)
- return ("OPENSSL_malloc Error");
- } else if (len < 128)
- return ("Buffer too small");
-
BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac);
return (buf);
char *SSL_CIPHER_get_version(const SSL_CIPHER *c)
{
- int i;
+ uint32_t alg_ssl;
if (c == NULL)
- return ("(NONE)");
- i = (int)(c->id >> 24L);
- if (i == 3)
- return ("TLSv1/SSLv3");
- else
- return ("unknown");
+ return "(NONE)";
+ alg_ssl = c->algorithm_ssl;
+
+ if (alg_ssl & SSL_SSLV3)
+ return "SSLv3";
+ if (alg_ssl & SSL_TLSV1)
+ return "TLSv1.0";
+ if (alg_ssl & SSL_TLSV1_2)
+ return "TLSv1.2";
+ return "unknown";
}
/* return the actual cipher being used */
return 0;
}
- MemCheck_off();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
comp = OPENSSL_malloc(sizeof(*comp));
if (comp == NULL) {
- MemCheck_on();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
return (1);
}
load_builtin_compressions();
if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
OPENSSL_free(comp);
- MemCheck_on();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
SSL_R_DUPLICATE_COMPRESSION_ID);
return (1);
- } else if ((ssl_comp_methods == NULL)
+ }
+ if ((ssl_comp_methods == NULL)
|| !sk_SSL_COMP_push(ssl_comp_methods, comp)) {
OPENSSL_free(comp);
- MemCheck_on();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
return (1);
- } else {
- MemCheck_on();
- return (0);
}
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ return (0);
}
#endif
/* For a cipher return the index corresponding to the certificate type */
int ssl_cipher_get_cert_index(const SSL_CIPHER *c)
{
- uint32_t alg_k, alg_a;
+ uint32_t alg_a;
- alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
- if (alg_k & (SSL_kECDHr | SSL_kECDHe)) {
- /*
- * we don't need to look at SSL_kECDHE since no certificate is needed
- * for anon ECDH and for authenticated ECDHE, the check for the auth
- * algorithm will set i correctly NOTE: For ECDH-RSA, we need an ECC
- * not an RSA cert but for ECDHE-RSA we need an RSA cert. Placing the
- * checks for SSL_kECDH before RSA checks ensures the correct cert is
- * chosen.
- */
- return SSL_PKEY_ECC;
- } else if (alg_a & SSL_aECDSA)
+ if (alg_a & SSL_aECDSA)
return SSL_PKEY_ECC;
else if (alg_a & SSL_aDSS)
return SSL_PKEY_DSA_SIGN;