ALL vs DEFAULT or how to properly order anonymous ciphers?
Currently the OpenSSL "DEFAULT" cipherlist serves two functions: - Sort the cipherlist to put the strongest, most desirable algorithms first. - Exclude ciphers that most applications should not be exposed to. Applications that don't need/want ciphers outside the "DEFAULT" list can further restrict the cipher choice with "DEFAULT:!this:!that" ... Things get more complicated for applications that want to support anonymous ciphers but still maintain a sensible cipher order: - With OpenSSL 0.9.7 we have: #define SSL_DEFAULT_CIPHER_LIST \ "ALL:!ADH:+RC4:@STRENGTH" - With OpenSSL 0.9.8 we have: #ifdef OPENSSL_NO_CAMELLIA # define SSL_DEFAULT_CIPHER_LIST\ "ALL:!ADH:+RC4:@STRENGTH" #else # define SSL_DEFAULT_CIPHER_LIST\ "AES:CAMELLIA:-ECCdraft:ALL:!ADH:+RC4:@STRENGTH" #endif - With OpenSSL 0.9.9 (dev) we have: #define SSL_DEFAULT_CIPHER_LIST \ "AES:CAMELLIA:ALL:!ADH:!AECDH:+aECDH:+kRSA:+RC4:@STRENGTH" If one wants a correctly ordered cipherlist with anonymous ciphers left in, one needs to use: - 0.9.7 ALL:+RC4:@STRENGTH - 0.9.8 (default build) "ALL:!ADH:+RC4:@STRENGTH" - 0.9.8 ( enable-camellia ) "AES:CAMELLIA:ALL:+RC4:@STRENGTH" removing ECCdraft is not necessary, because these are already excluded from the "ALL" cipher alias. - 0.9.9 "AES:CAMELLIA:ALL:+aECDH:+kRSA:+RC4:@STRENGTH" This volatility from release to release makes it impractical to define a correctly ordered default cipher list for "aNULL" applications that survives upgrades in the OpenSSL library with configuration changes in the application. Now it is true that the 0.9.9 list can be used with reasonably good results with 0.9.8 and 0.9.7 resulting in only minor deviations from the native (DEFAULT with aNULL left in) order for the earlier releases, the diffence being that ADH precedes kRSA in more cases (which is desirable). Still, the "DEFAULT" order is likely to change yet again in future releases, and it is going to be difficult to play "catchup" with an ever evolving DEFAULT cipher list. I am therefore asking the team to consider splitting the two features: - Sensible default order - Non-default cipher exclusion into two parts. The first part (ordering), should I believe be a feature of the "ALL" cipher_alias: ALL = preferred:all:+low-pref:@STRENGTH (preferred = AES:CAMELLIA) (all = legacy "ALL" cipher list) (low-pref = +aECDH:+kRSA:+RC4) an then "DEFAULT" is simply a filter on the already ordered "ALL" list: DEFAULT = "ALL:!aNULL". This would allow applications using "ALL" (or legacy ALL:+RC4:@STRENGTH which would be an equivalent more cumbersome way of getting the same result) to portably (release to release) arrive at a sensible cipherlist order. Comments? -- Viktor. __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Sat, Feb 17, 2007 at 11:45:58PM -0500, Victor Duchovni wrote: > Currently the OpenSSL "DEFAULT" cipherlist serves two functions: > > - Sort the cipherlist to put the strongest, most desirable algorithms > first. > > - Exclude ciphers that most applications should not be exposed to. > > Applications that don't need/want ciphers outside the "DEFAULT" list > can further restrict the cipher choice with "DEFAULT:!this:!that" ... > > Things get more complicated for applications that want to support > anonymous ciphers but still maintain a sensible cipher order: [...] ... since once you've used "DEFAULT", which involves "!ADH" or "!ADH:!AECDH" (both of which really should be "!aNULL"), you cannot re-enable anonymous ciphersuites. ("!this" unlike "-this" thoroughly disables the ciphersuite so that even "!this:this" cannot add it. E.g., "RSA:!RSA:RSA" is empty, whereas "RSA:-RSA:RSA" is equivalent to "RSA". It is intentional that DEFAULT is that strict. In fact, DEFAULT should be just as strict about ciphersuites without encryption, which it doesn't enable but doesn't thoroughly disable either -- "DEFAULT:RSA" will enable unencrypted authentication-only ciphersuites! This is a bug to be fixed.) > I am therefore asking the team to consider splitting the two features: > > - Sensible default order > > - Non-default cipher exclusion > > into two parts. The first part (ordering), should I believe be a feature > of the "ALL" cipher_alias: > > ALL = preferred:all:+low-pref:@STRENGTH > > (preferred = AES:CAMELLIA) > (all = legacy "ALL" cipher list) > (low-pref = +aECDH:+kRSA:+RC4) > > an then "DEFAULT" is simply a filter on the already ordered "ALL" list: > > DEFAULT = "ALL:!aNULL". > > This would allow applications using "ALL" (or legacy ALL:+RC4:@STRENGTH > which would be an equivalent more cumbersome way of getting the same > result) to portably (release to release) arrive at a sensible cipherlist > order. Yes, this makes sense. Currently, ciphers start being ordered by ID, which is rather arbitrary. Here's a patch that uses a reasonable order for "ALL" instead, and also includes "!eNULL" in "DEFAULT". This will go into the 0.9.9 branch. Bodo +++ ssl/ssl.h 19 Feb 2007 18:39:53 - @@ -315,8 +315,13 @@ /* 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 "AES:CAMELLIA:ALL:!ADH:!AECDH:+aECDH:+kRSA:+RC4:@STRENGTH" -/* low priority for ciphersuites w/o forwared secrecy (fixed ECDH, RSA key exchange), and for RC4 */ +#define SSL_DEFAULT_CIPHER_LIST"ALL:!aNULL:!eNULL" +/* As of OpenSSL 0.9.9, 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 Index: ssl/ssl_ciph.c === RCS file: /e/openssl/cvs/openssl/ssl/ssl_ciph.c,v retrieving revision 1.66 diff -u -r1.66 ssl_ciph.c --- ssl/ssl_ciph.c 17 Feb 2007 06:45:37 - 1.66 +++ ssl/ssl_ciph.c 19 Feb 2007 18:39:53 - @@ -1120,6 +1120,40 @@ disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl, co_list, &head, &tail); + + /* Now arrange all ciphers by preference: */ + + /* Temporarily enabled AES first (preferred cipher) */ + ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + + /* Temporarily enable everything else */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + + /* Move anonymous ciphers to the end. Usually, these will remain 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, &tail); + + /* Move ciphers without forward secrecy to then end */ + ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + ssl_cipher_apply_rule(0, 0, SSL_kPSK, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* RC4 is sort-of broken -- move the the end */ + ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* Now sort by symmetric encryption strength. The above ordering remains +* in force within each class */ + if (!ssl_cipher_strength_sort(&head, &tail)) + { + OPENSSL_free(co_list); + r
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Mon, Feb 19, 2007 at 07:43:50PM +0100, Bodo Moeller wrote: Thanks, a giant leap in the right direction! Nit-picking below: > + /* Move anonymous ciphers to the end. Usually, these will remain > 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, &tail); This is not quite right IMHO. I think the anonymous ciphers MUST be first, because: 1. Most applications use "DEFAULT" and don't see them at all. 2. Applications that want anonymous ciphers, typically don't disable the non-anonymous ones for interoperability reasons, so won't get to use them if they are not first. 3. Applications that are happy with anonymous ciphers don't check certs, so there is no reason to prefer ciphers with with certs, which just waste cycles. If the anonymous ciphers are last, perhaps: ALL+aNULL:ALL:@STRENGTH produces the desired order for applications that don't check certs, but I think it is cleaner to put the anonymous kEECDH and kEDH ciphers first, they use the strongest key-exchange mechanisms available, and best meed the authentication needs of apps that ignore authentication. I also think that kEECDH should be sorted ahead of kEDH, within the class of forward secrecy capable key-exchange mechanisms. The current somewhat adhoc initial order could be replaced by sort() (need not be stable for initial order) based on a systematic comparator: int ciph_compare(c1, c2) { if ((ret = (strength_compare(strength(c1), strength(c2 != 0) return ret; if ((ret = (enc_compare(enc(c1), enc(c2 != 0) return ret; if ((ret = (kx_compare(kx(c1), kx(c2 != 0) return ret; if ((ret = (auth_compare(auth(c1), auth(c2 != 0) return ret; if ((ret = (mac_compare(mac(c1), mac(c2 != 0) return ret; if ((ret = (proto_compare(proto(c1), proto(c2 != 0) return ret; } One then needs to decide how to separately rank the available ciphers, key exchange mechanisms, ... and whether the above relative order of comparisons (alg_bits, cipher, key-exchange, auth, mac, proto) is the right one. Regardless of the specific details, using a comparator makes the order more systematic. One can still quible over whether anonymous auth beats RSA auth, and I may not get my wish there, but I still think a sort based based on a linear order should be considered. Perhaps this is impractical, but it seems tempting to me... -- /"\ ASCII RIBBON NOTICE: If received in error, \ / CAMPAIGN Victor Duchovni please destroy and notify X AGAINST IT Security, sender. Sender does not waive / \ HTML MAILMorgan Stanley confidentiality or privilege, and use is prohibited. __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Mon, Feb 19, 2007 at 02:19:27PM -0500, Victor Duchovni wrote: > This is not quite right IMHO. I think the anonymous ciphers MUST be > first, because: > > 1. Most applications use "DEFAULT" and don't see them at all. > > 2. Applications that want anonymous ciphers, typically don't disable > the non-anonymous ones for interoperability reasons, so won't get to > use them if they are not first. > > 3. Applications that are happy with anonymous ciphers don't check > certs, so there is no reason to prefer ciphers with with certs, which > just waste cycles. > > If the anonymous ciphers are last, perhaps: > > ALL+aNULL:ALL:@STRENGTH > > produces the desired order for applications that don't check certs, but I > think it is cleaner to put the anonymous kEECDH and kEDH ciphers first, > they use the strongest key-exchange mechanisms available, and best meed > the authentication needs of apps that ignore authentication. Well, I have tested the "ALL+aNULL:ALL:+RC4:@STRENGTH" form against the new 0.9.9 code and current 0.9.7 and 0.9.8. And it behaves as I had hoped, so while I still think that aNULL should be first, if the consensus is that it should not, I have a work-around. As far as the 0.9.9 patch is concerned, is it possible to cache the initial sorted order? Some applications process cipherlists for every connection (destination dependent cipher lists), and it would be nice to keep this efficient, provided that there is negligbible or no additional cost for applications that set the cipherlist only once. -- Viktor. __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Mon, Feb 19, 2007 at 02:19:27PM -0500, Victor Duchovni wrote: > [...] I > think it is cleaner to put the anonymous kEECDH and kEDH ciphers first, > they use the strongest key-exchange mechanisms available, and best meed > the authentication needs of apps that ignore authentication. Allowing anonymous ciphersuites does not always mean that the application will ignore authentication, though. Many applications will merely tolerate anonymous ciphersuites, but still prefer authenticated ciphersuites if they can get one of those. > I also think that kEECDH should be sorted ahead of kEDH, within the class > of forward secrecy capable key-exchange mechanisms. Yes, that's reasonable. The current ciphersuite list processing code doesn't keep the order of deleted ciphersuites sufficiently stable to express this, but with some further changes this can be done: Index: ssl_ciph.c === RCS file: /e/openssl/cvs/openssl/ssl/ssl_ciph.c,v retrieving revision 1.68 diff -u -r1.68 ssl_ciph.c --- ssl_ciph.c 20 Feb 2007 13:25:36 - 1.68 +++ ssl_ciph.c 20 Feb 2007 15:45:29 - @@ -476,7 +476,7 @@ *head=curr->next; if (curr->prev != NULL) curr->prev->next=curr->next; - if (curr->next != NULL) /* should always be true */ + if (curr->next != NULL) curr->next->prev=curr->prev; (*tail)->next=curr; curr->prev= *tail; @@ -484,6 +484,22 @@ *tail=curr; } +static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, +CIPHER_ORDER **tail) + { + if (curr == *head) return; + if (curr == *tail) + *tail=curr->prev; + if (curr->next != NULL) + curr->next->prev=curr->prev; + if (curr->prev != NULL) + curr->prev->next=curr->next; + (*head)->prev=curr; + curr->next= *head; + curr->prev=NULL; + *head=curr; + } + static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long *enc, unsigned long *mac, unsigned long *ssl) { *mkey = 0; @@ -586,19 +602,27 @@ /* * Prepare linked list from list entries */ - for (i = 1; i < co_list_num - 1; i++) - { - co_list[i].prev = &(co_list[i-1]); - co_list[i].next = &(co_list[i+1]); - } if (co_list_num > 0) { - (*head_p) = &(co_list[0]); - (*head_p)->prev = NULL; - (*head_p)->next = &(co_list[1]); - (*tail_p) = &(co_list[co_list_num - 1]); - (*tail_p)->prev = &(co_list[co_list_num - 2]); - (*tail_p)->next = NULL; + co_list[0].prev = NULL; + + if (co_list_num > 1) + { + co_list[0].next = &co_list[1]; + + for (i = 1; i < co_list_num - 1; i++) + { + co_list[i].prev = &co_list[i - 1]; + co_list[i].next = &co_list[i + 1]; + } + + co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; + } + + co_list[co_list_num - 1].next = NULL; + + *head_p = &co_list[0]; + *tail_p = &co_list[co_list_num - 1]; } } @@ -679,22 +703,38 @@ int rule, int strength_bits, CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) { - CIPHER_ORDER *head, *tail, *curr, *curr2, *tail2; + CIPHER_ORDER *head, *tail, *curr, *curr2, *last; SSL_CIPHER *cp; + int reverse = 0; #ifdef CIPHER_DEBUG printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n", rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits); #endif - curr = head = *head_p; - curr2 = head; - tail2 = tail = *tail_p; + if (rule == CIPHER_DEL) + reverse = 1; /* needed to maintain sorting between currently deleted ciphers */ + + head = *head_p; + tail = *tail_p; + + if (reverse) + { + curr = tail; + last = head; + } + else + { + curr = head; + last = tail; + } + + curr2 = curr; for (;;) { - if ((curr == NULL) || (curr == tail2)) break; + if ((curr == NULL) || (curr == last)) break; curr = curr2; - curr2 = curr->next; + curr2 = reverse ? curr->prev : curr->next; cp = curr->cipher; @@ -736,6 +776,7 @@
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Mon, Feb 19, 2007 at 02:19:27PM -0500, Victor Duchovni wrote: > Regardless of the specific details, using a comparator makes the order > more systematic. One can still quible over whether anonymous auth beats > RSA auth, and I may not get my wish there, but I still think a sort based > based on a linear order should be considered. Perhaps this is impractical, > but it seems tempting to me... One advantage of using ssl_cipher_apply_rule() for all of this in ssl_ciph.c is that we can see how well ssl_cipher_apply_rule() does this kind of job (in terms of bugs, and missing features) -- we sort the ciphersuite list only in the kind of ways that are available to textual ciphersuite list specifications. Bodo __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Mon, Feb 19, 2007 at 03:22:44PM -0500, Victor Duchovni wrote: > As far as the 0.9.9 patch is concerned, is it possible to cache the > initial sorted order? Some applications process cipherlists for every > connection (destination dependent cipher lists), and it would be nice to > keep this efficient, provided that there is negligbible or no additional > cost for applications that set the cipherlist only once. It's true that the sorted order of "ALL" should be generated just once, and then cached, for better efficiency. Where and how to do this caching, though, is an optimization decision that will introduce certain complications, and should only be done once we are sure that the ciphersuite sorting code itself is OK. I'm thinking of caching the sorted list once per SSL_CTX, eventually. Bodo __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]
Re: ALL vs DEFAULT or how to properly order anonymous ciphers?
On Tue, Feb 20, 2007 at 05:08:07PM +0100, Bodo Moeller wrote: > On Mon, Feb 19, 2007 at 03:22:44PM -0500, Victor Duchovni wrote: > > > As far as the 0.9.9 patch is concerned, is it possible to cache the > > initial sorted order? Some applications process cipherlists for every > > connection (destination dependent cipher lists), and it would be nice to > > keep this efficient, provided that there is negligbible or no additional > > cost for applications that set the cipherlist only once. > > It's true that the sorted order of "ALL" should be generated just > once, and then cached, for better efficiency. Where and how to do > this caching, though, is an optimization decision that will introduce > certain complications, and should only be done once we are sure that > the ciphersuite sorting code itself is OK. Makes sense. > I'm thinking of caching the sorted list once per SSL_CTX, eventually. That seems very reasonable. In the mean-time, in Postfix 2.4, I am caching the cipher_list string that was last applied to SSL_CTX, so in the typical case that successive connections re-use the same cipherlist, additional NOOP calls to SSL_CTX_set_cipher_list() are avoided. -- Viktor. __ OpenSSL Project http://www.openssl.org User Support Mailing Listopenssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]