Fix for EXP-RC2-CBC-MD5
authorAdam Langley <agl@chromium.org>
Wed, 6 Feb 2013 15:50:42 +0000 (15:50 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 6 Feb 2013 16:12:49 +0000 (16:12 +0000)
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)

ssl/s3_cbc.c
test/testssl

index 2ab7bfb60a5632de169ee47b87702d3bd130e19a..ad695ae1332520487885c16e767c0ed759a431be 100644 (file)
@@ -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)
                {
index 8ac90ae5eec37a76ef0ffa9001b8582a85708b43..4c7584a95c2cdd8a31a53f01c91b7916fe0d8ed4 100644 (file)
@@ -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