Patch equal preference

This commit is contained in:
2018-05-23 23:53:45 +09:00
parent ef253190c7
commit 568c1175f2
15 changed files with 407 additions and 157 deletions
+154 -62
View File
@@ -190,6 +190,7 @@ typedef struct cipher_order_st {
const SSL_CIPHER *cipher;
int active;
int dead;
int in_group;
struct cipher_order_st *next, *prev;
} CIPHER_ORDER;
@@ -682,6 +683,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
co_list[co_list_num].next = NULL;
co_list[co_list_num].prev = NULL;
co_list[co_list_num].active = 0;
co_list[co_list_num].in_group = 0;
co_list_num++;
}
@@ -775,8 +777,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
uint32_t alg_auth, uint32_t alg_enc,
uint32_t alg_mac, int min_tls,
uint32_t algo_strength, int rule,
int32_t strength_bits, CIPHER_ORDER **head_p,
CIPHER_ORDER **tail_p)
int32_t strength_bits, int in_group,
CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
{
CIPHER_ORDER *head, *tail, *curr, *next, *last;
const SSL_CIPHER *cp;
@@ -784,9 +786,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
#ifdef CIPHER_DEBUG
fprintf(stderr,
"Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
"Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d) g:%d\n",
rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
algo_strength, strength_bits);
algo_strength, strength_bits, in_group);
#endif
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
@@ -863,6 +865,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
if (!curr->active) {
ll_append_tail(&head, curr, &tail);
curr->active = 1;
curr->in_group = in_group;
}
}
/* Move the added cipher to this location */
@@ -870,6 +873,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
/* reverse == 0 */
if (curr->active) {
ll_append_tail(&head, curr, &tail);
curr->in_group = 0;
}
} else if (rule == CIPHER_DEL) {
/* reverse == 1 */
@@ -881,6 +885,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
*/
ll_append_head(&head, curr, &tail);
curr->active = 0;
curr->in_group = 0;
}
} else if (rule == CIPHER_BUMP) {
if (curr->active)
@@ -948,8 +953,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
*/
for (i = max_strength_bits; i >= 0; i--)
if (number_uses[i] > 0)
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
tail_p);
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0,
head_p, tail_p);
OPENSSL_free(number_uses);
return 1;
@@ -963,7 +968,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
int min_tls;
const char *l, *buf;
int j, multi, found, rule, retval, ok, buflen;
int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
uint32_t cipher_id = 0;
char ch;
@@ -974,18 +979,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
if (ch == '\0')
break; /* done */
if (ch == '-') {
if (in_group) {
if (ch == ']') {
if (!in_group) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
SSL_R_UNEXPECTED_GROUP_CLOSE);
retval = found = in_group = 0;
break;
}
if (*tail_p)
(*tail_p)->in_group = 0;
in_group = 0;
l++;
continue;
}
if (ch == '|') {
rule = CIPHER_ADD;
l++;
continue;
} else if (!(ch >= 'a' && ch <= 'z')
&& !(ch >= 'A' && ch <= 'Z')
&& !(ch >= '0' && ch <= '9')) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
retval = found = in_group = 0;
break;
} else {
rule = CIPHER_ADD;
}
} else if (ch == '-') {
rule = CIPHER_DEL;
l++;
} else if (ch == '+') {
rule = CIPHER_ORD;
l++;
} else if (ch == '!' && has_group) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
retval = found = in_group = 0;
break;
} else if (ch == '!') {
rule = CIPHER_KILL;
l++;
} else if (ch == '@' && has_group) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
retval = found = in_group = 0;
break;
} else if (ch == '@') {
rule = CIPHER_SPECIAL;
l++;
} else if (ch == '[') {
if (in_group) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_NESTED_GROUP);
retval = found = in_group = 0;
break;
}
in_group = 1;
has_group = 1;
l++;
continue;
} else {
rule = CIPHER_ADD;
}
@@ -1027,7 +1080,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
* alphanumeric, so we call this an error.
*/
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
retval = found = 0;
retval = found = in_group = 0;
l++;
break;
}
@@ -1206,8 +1259,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
} else if (found) {
ssl_cipher_apply_rule(cipher_id,
alg_mkey, alg_auth, alg_enc, alg_mac,
min_tls, algo_strength, rule, -1, head_p,
tail_p);
min_tls, algo_strength, rule, -1, in_group,
head_p, tail_p);
} else {
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
@@ -1216,6 +1269,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
break; /* done */
}
if (in_group) {
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
retval = 0;
}
return retval;
}
@@ -1380,7 +1438,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
if (ret && ctx->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
return update_cipher_list(&ctx->cipher_list->ciphers, &ctx->cipher_list_by_id,
ctx->tls13_ciphersuites);
}
@@ -1393,7 +1451,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
if (ret && s->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
return update_cipher_list(&s->cipher_list->ciphers, &s->cipher_list_by_id,
s->tls13_ciphersuites);
}
@@ -1402,17 +1460,20 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
STACK_OF(SSL_CIPHER) **cipher_list,
struct ssl_cipher_preference_list_st **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str,
CERT *c)
{
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i;
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i, tls13_len;
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
STACK_OF(SSL_CIPHER) *cipherstack;
STACK_OF(SSL_CIPHER) *cipherstack = NULL;
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
const SSL_CIPHER **ca_list = NULL;
const SSL_CIPHER **ca_list = NULL, *tmp = NULL;
uint8_t *in_group_flags = NULL;
unsigned int num_in_group_flags = 0;
struct ssl_cipher_preference_list_st *pref_list = NULL;
/*
* Return with error if nothing to do.
@@ -1461,16 +1522,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* 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);
-1, 0, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0,
&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,
ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, 0,
&head, &tail);
/*
@@ -1479,13 +1540,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* strength.
*/
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
-1, &head, &tail);
-1, 0, &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, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
/* Low priority for MD5 */
ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/*
@@ -1493,16 +1554,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* disabled. (For applications that allow them, they aren't too bad, but
* we prefer authenticated ciphers.)
*/
ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/* RC4 is sort-of broken -- move to the end */
ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/*
@@ -1518,7 +1579,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* 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, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1, 0,
&head, &tail);
/*
@@ -1534,15 +1595,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* 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,
ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
CIPHER_BUMP, -1, &head, &tail);
CIPHER_BUMP, -1, 0, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
CIPHER_BUMP, -1, &head, &tail);
CIPHER_BUMP, -1, 0, &head, &tail);
/* Now disable everything (maintaining the ordering!) */
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
/*
* We also need cipher aliases for selecting based on the rule_str.
@@ -1556,9 +1617,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
if (ca_list == NULL) {
OPENSSL_free(co_list);
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
return NULL; /* Failure */
goto err; /* Failure */
}
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
disabled_mkey, disabled_auth, disabled_enc,
@@ -1583,27 +1643,35 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
OPENSSL_free(ca_list); /* Not needed anymore */
if (!ok) { /* Rule processing failure */
OPENSSL_free(co_list);
return NULL;
}
if (!ok)
goto err; /* Rule processing failure */
/*
* Allocate new "cipherstack" for the result, return with error
* if we cannot get one.
*/
if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
OPENSSL_free(co_list);
return NULL;
}
if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
goto err;
in_group_flags = OPENSSL_malloc(num_of_ciphers);
if (!in_group_flags)
goto err;
/* Add TLSv1.3 ciphers first - we always prefer those if possible */
for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
tls13_len = sk_SSL_CIPHER_num(tls13_ciphersuites);
for (i = 0; i < tls13_len; i++) {
tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i);
if (!sk_SSL_CIPHER_push(cipherstack,
sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
sk_SSL_CIPHER_free(cipherstack);
return NULL;
tmp))
goto err;
/* Temporary - AES128, CHACHA20 priority adjustment of TLS 1.3. */
if (tmp->algorithm_enc == SSL_AES128GCM &&
tls13_len > (i + 1)) {
tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i + 1);
in_group_flags[num_in_group_flags++] = (tmp->algorithm_enc == SSL_CHACHA20POLY1305) ? 1 : 0;
}
else
in_group_flags[num_in_group_flags++] = 0;
}
/*
@@ -1612,26 +1680,50 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
*/
for (curr = head; curr != NULL; curr = curr->next) {
if (curr->active) {
if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
OPENSSL_free(co_list);
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher))
goto err;
in_group_flags[num_in_group_flags++] = curr->in_group;
#ifdef CIPHER_DEBUG
fprintf(stderr, "<%s>\n", curr->cipher->name);
#endif
}
}
OPENSSL_free(co_list); /* Not needed any longer */
if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
sk_SSL_CIPHER_free(cipherstack);
return NULL;
}
sk_SSL_CIPHER_free(*cipher_list);
*cipher_list = cipherstack;
OPENSSL_free(co_list); /* Not needed any longer */
co_list = NULL;
if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack))
goto err;
pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
if (!pref_list)
goto err;
pref_list->ciphers = cipherstack;
pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
if (!pref_list->in_group_flags)
goto err;
memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
OPENSSL_free(in_group_flags);
in_group_flags = NULL;
if (*cipher_list != NULL)
ssl_cipher_preference_list_free(*cipher_list);
*cipher_list = pref_list;
pref_list = NULL;
return cipherstack;
err:
if (co_list)
OPENSSL_free(co_list);
if (in_group_flags)
OPENSSL_free(in_group_flags);
if (cipherstack)
sk_SSL_CIPHER_free(cipherstack);
if (pref_list && pref_list->in_group_flags)
OPENSSL_free(pref_list->in_group_flags);
if (pref_list)
OPENSSL_free(pref_list);
return NULL;
}
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)