From: Adam Langley Date: Wed, 6 Feb 2013 15:50:42 +0000 (+0000) Subject: Fix for EXP-RC2-CBC-MD5 X-Git-Tag: OpenSSL_0_9_8za~85 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6351adecb4726476def5f5ad904a7d2e63480d53;p=oweals%2Fopenssl.git Fix for EXP-RC2-CBC-MD5 MD5 should use little endian order. Fortunately the only ciphersuite affected is EXP-RC2-CBC-MD5 (TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5) which is a rarely used export grade ciphersuite. (cherry picked from commit ee463921ed94572b97a5e1fa8c4d88a27099347e) --- diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 2ab7bfb60a..ad695ae133 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -317,16 +317,24 @@ void ssl3_cbc_copy_mac(unsigned char* out, #endif } +/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. */ +#define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + /* These functions serialize the state of a hash and thus perform the standard * "final" operation without adding the padding and length that such a function * typically does. */ static void tls1_md5_final_raw(void* ctx, unsigned char *md_out) { MD5_CTX *md5 = ctx; - l2n(md5->A, md_out); - l2n(md5->B, md_out); - l2n(md5->C, md_out); - l2n(md5->D, md_out); + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); } static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) @@ -446,6 +454,7 @@ void ssl3_cbc_digest_record( /* mdLengthSize is the number of bytes in the length field that terminates * the hash. */ unsigned md_length_size = 8; + char length_is_big_endian = 1; /* This is a, hopefully redundant, check that allows us to forget about * many possible overflows later in this function. */ @@ -459,6 +468,7 @@ void ssl3_cbc_digest_record( md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; md_size = 16; sslv3_pad_length = 48; + length_is_big_endian = 0; break; case NID_sha1: SHA1_Init((SHA_CTX*)md_state.c); @@ -599,11 +609,22 @@ void ssl3_cbc_digest_record( md_transform(md_state.c, hmac_pad); } - memset(length_bytes,0,md_length_size-4); - length_bytes[md_length_size-4] = (unsigned char)(bits>>24); - length_bytes[md_length_size-3] = (unsigned char)(bits>>16); - length_bytes[md_length_size-2] = (unsigned char)(bits>>8); - length_bytes[md_length_size-1] = (unsigned char)bits; + if (length_is_big_endian) + { + memset(length_bytes,0,md_length_size-4); + length_bytes[md_length_size-4] = (unsigned char)(bits>>24); + length_bytes[md_length_size-3] = (unsigned char)(bits>>16); + length_bytes[md_length_size-2] = (unsigned char)(bits>>8); + length_bytes[md_length_size-1] = (unsigned char)bits; + } + else + { + memset(length_bytes,0,md_length_size); + length_bytes[md_length_size-5] = (unsigned char)(bits>>24); + length_bytes[md_length_size-6] = (unsigned char)(bits>>16); + length_bytes[md_length_size-7] = (unsigned char)(bits>>8); + length_bytes[md_length_size-8] = (unsigned char)bits; + } if (k > 0) { diff --git a/test/testssl b/test/testssl index 8ac90ae5ee..4c7584a95c 100644 --- a/test/testssl +++ b/test/testssl @@ -119,6 +119,23 @@ $ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 echo test sslv2/sslv3 with both client and server authentication via BIO pair and app verify $ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 +echo "Testing ciphersuites" +for protocol in SSLv3; do + echo "Testing ciphersuites for $protocol" + for cipher in `../util/shlib_wrap.sh ../apps/openssl ciphers "RSA+$protocol" | tr ':' ' '`; do + echo "Testing $cipher" + prot="" + if [ $protocol == "SSLv3" ] ; then + prot="-ssl3" + fi + $ssltest -cipher $cipher $prot + if [ $? -ne 0 ] ; then + echo "Failed $cipher" + exit 1 + fi + done +done + ############################################################################# if ../util/shlib_wrap.sh ../apps/openssl no-dh; then