diff options
author | Adam Langley <agl@chromium.org> | 2013-02-06 16:05:40 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2013-02-08 10:40:13 +0100 |
commit | 0462eedf5ee2273647010955a92d962ce109c6af (patch) | |
tree | 0bf72facf5c59c2c966b1153f823e3c0414b9353 /ssl/s3_cbc.c | |
parent | 82425f2c281be4b71b400ce22612d487d8085fec (diff) |
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 f306b87d766e6ecf30824635c7c395b67cff9dbc)
Diffstat (limited to 'ssl/s3_cbc.c')
-rw-r--r-- | ssl/s3_cbc.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 3c2c16539d..ce77acd3d4 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -328,16 +328,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) @@ -457,6 +465,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. */ @@ -470,6 +479,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); @@ -610,11 +620,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) { |