Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
Subject: Re: OpenSSL 3DES inner chaining?
From: Eric Murray (ericmlne.com)
Date: Mon Oct 09 2000 - 19:04:22 CDT

On Mon, Oct 09, 2000 at 09:00:21PM -0000, lcs Mixmaster Remailer wrote:
> The OpenSSL implementation of triple DES in CBC mode appears to use
> inner chaining. This is from cbc3_enc.c:
> /* HAS BUGS? DON'T USE - this is only present for use in des.c */
> void des_3cbc_encrypt(des_cblock *input, des_cblock *output, long length,
> des_key_schedule ks1, des_key_schedule ks2, des_cblock *iv1,
> des_cblock *iv2, int enc)
> {
> int off=((int)length-1)/8;
> long l8=((length+7)/8)*8;
> des_cblock niv1,niv2;
> if (enc == DES_ENCRYPT)
> {
> des_cbc_encrypt(input,output,length,ks1,iv1,enc);
> if (length >= sizeof(des_cblock))
> memcpy(niv1,output[off],sizeof(des_cblock));
> des_cbc_encrypt(output,output,l8,ks2,iv1,!enc);
> des_cbc_encrypt(output,output,l8,ks1,iv2, enc);
> if (length >= sizeof(des_cblock))
> memcpy(niv2,output[off],sizeof(des_cblock));
> }
> else
> {
> if (length >= sizeof(des_cblock))
> memcpy(niv2,input[off],sizeof(des_cblock));
> des_cbc_encrypt(input,output,l8,ks1,iv2,enc);
> des_cbc_encrypt(output,output,l8,ks2,iv1,!enc);
> if (length >= sizeof(des_cblock))
> memcpy(niv1,output[off],sizeof(des_cblock));
> des_cbc_encrypt(output,output,length,ks1,iv1, enc);
> }
> memcpy(*iv1,niv1,sizeof(des_cblock));
> memcpy(*iv2,niv2,sizeof(des_cblock));
> }
> Note that there is no looping at this level; the entire message is CBC
> encrypted, decrypted, and encrypted again.
> Biham has shown that inner chaining weakens 3DES. Outer chaining is
> generally preferred. SSL uses outer chaining. How can OpenSSL be
> compatible if it is doing inner chaining? Is the code above not used?

It looks like it's used only in the DES package, and not in SSL/TLS.

The doc file ssleay.txt says:

< void des_3cbc_encrypt(
< des_cblock *input,
< des_cblock *output,
< long length,
< des_key_schedule sk1,
< des_key_schedule sk2,
< des_cblock *ivec1,
< des_cblock *ivec2,
< int enc);
< This function is flawed, do not use it. I have left it in the
< library because it is used in my des(1) program and will function
< correctly when used by des(1). If I removed the function, people
< could end up unable to decrypt files.
< This routine implements outer triple cbc encryption using 2 ks and
< 2 ivec's. Use des_ede2_cbc_encrypt() instead.
< void des_ede3_cbc_encrypt(
< des_cblock *input,
< des_cblock *output,
< long length,
< des_key_schedule ks1,
< des_key_schedule ks2,
< des_key_schedule ks3,
< des_cblock *ivec,
< int enc);
< This function implements outer triple CBC DES encryption with 3
< keys. What this means is that each 'DES' operation
< inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))).
< Again, this is cbc mode so an ivec is requires.
< This mode is used by SSL.
< There is also a des_ede2_cbc_encrypt() that only uses 2
< des_key_schedule's, the first being reused for the final
< encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES
< is used by the RSAref library.

I did a quick grep and found des_ede3_cbc_encrypt() in a bunch of
ssl-related files, and des_3cbc_encrypt only in a couple des files.
Which is what the comment at the top of the code you forwarded says...
although I don't fault you for not trusting it.

I don't have time now to check fully (and tracing the code to figure out
what cipher's being used in Openssl is non-trivial) but I think that it's ok.

  Eric Murray http://www.lne.com/ericm  ericm at lne.com  PGP keyid:E03F65E5
                     Consulting Security Architect