ALL vs DEFAULT or how to properly order anonymous ciphers?

2007-02-17 Thread Victor Duchovni

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?

2007-02-19 Thread Bodo Moeller
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?

2007-02-19 Thread Victor Duchovni
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?

2007-02-19 Thread Victor Duchovni
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?

2007-02-20 Thread Bodo Moeller
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?

2007-02-20 Thread Bodo Moeller
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?

2007-02-20 Thread Bodo Moeller
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?

2007-02-20 Thread Victor Duchovni
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]