ssl/s3_cbc.c: uint64_t portability fix.
[openssl.git] / ssl / s3_cbc.c
index e9b112c1b589510aff18ef39cace825b4529ce2b..fff5f24ebddd1919e058b99a14de66a15455617a 100644 (file)
@@ -53,8 +53,6 @@
  *
  */
 
-#include <stdint.h>
-
 #include "ssl_locl.h"
 
 #include <openssl/md5.h>
@@ -139,8 +137,7 @@ int tls1_cbc_remove_padding(const SSL* s,
                            unsigned mac_size)
        {
        unsigned padding_length, good, to_check, i;
-       const char has_explicit_iv =
-               s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION;
+       const char has_explicit_iv = s->version == DTLS1_VERSION;
        const unsigned overhead = 1 /* padding length byte */ +
                                  mac_size +
                                  (has_explicit_iv ? block_size : 0);
@@ -366,9 +363,13 @@ static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out)
 
 /* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
  * which ssl3_cbc_digest_record supports. */
-char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
+char ssl3_cbc_record_digest_supported(const EVP_MD *digest)
        {
-       switch (ctx->digest->type)
+#ifdef OPENSSL_FIPS
+       if (FIPS_mode())
+               return 0;
+#endif
+       switch (EVP_MD_type(digest))
                {
                case NID_md5:
                case NID_sha1:
@@ -402,7 +403,7 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
  * a padding byte and MAC. (If the padding was invalid, it might contain the
  * padding too. ) */
 void ssl3_cbc_digest_record(
-       const EVP_MD_CTX *ctx,
+       const EVP_MD *digest,
        unsigned char* md_out,
        size_t* md_out_size,
        const unsigned char header[13],
@@ -420,7 +421,7 @@ void ssl3_cbc_digest_record(
        unsigned sslv3_pad_length = 40, header_length, variance_blocks,
                 len, max_mac_bytes, num_blocks,
                 num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
-       uint64_t bits;
+       unsigned int bits;      /* at most 18 bits */
        unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
        /* hmac_pad is the masked HMAC key. */
        unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
@@ -436,7 +437,7 @@ void ssl3_cbc_digest_record(
         * many possible overflows later in this function. */
        OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024);
 
-       switch (ctx->digest->type)
+       switch (EVP_MD_type(digest))
                {
                case NID_md5:
                        MD5_Init((MD5_CTX*)md_state);
@@ -580,14 +581,11 @@ void ssl3_cbc_digest_record(
                md_transform(md_state, hmac_pad);
                }
 
-       j = 0;
-       if (md_length_size == 16)
-               {
-               memset(length_bytes, 0, 8);
-               j = 8;
-               }
-       for (i = 0; i < 8; i++)
-               length_bytes[i+j] = bits >> (8*(7-i));
+       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 (k > 0)
                {
@@ -670,7 +668,7 @@ void ssl3_cbc_digest_record(
                }
 
        EVP_MD_CTX_init(&md_ctx);
-       EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */);
+       EVP_DigestInit_ex(&md_ctx, digest, NULL /* engine */);
        if (is_sslv3)
                {
                /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
@@ -694,3 +692,50 @@ void ssl3_cbc_digest_record(
                *md_out_size = md_out_size_u;
        EVP_MD_CTX_cleanup(&md_ctx);
        }
+
+#ifdef OPENSSL_FIPS
+
+/* Due to the need to use EVP in FIPS mode we can't reimplement digests but
+ * we can ensure the number of blocks processed is equal for all cases
+ * by digesting additional data.
+ */
+
+void tls_fips_digest_extra(
+       const EVP_CIPHER_CTX *cipher_ctx, const EVP_MD *hash, HMAC_CTX *hctx,
+       const unsigned char *data, size_t data_len, size_t orig_len)
+       {
+       size_t block_size, digest_pad, blocks_data, blocks_orig;
+       if (EVP_CIPHER_CTX_mode(cipher_ctx) != EVP_CIPH_CBC_MODE)
+               return;
+       block_size = EVP_MD_block_size(hash);
+       /* We are in FIPS mode if we get this far so we know we have only SHA*
+        * digests and TLS to deal with.
+        * Minimum digest padding length is 17 for SHA384/SHA512 and 9
+        * otherwise.
+        * Additional header is 13 bytes. To get the number of digest blocks
+        * processed round up the amount of data plus padding to the nearest
+        * block length. Block length is 128 for SHA384/SHA512 and 64 otherwise.
+        * So we have:
+        * blocks = (payload_len + digest_pad + 13 + block_size - 1)/block_size
+        * equivalently:
+        * blocks = (payload_len + digest_pad + 12)/block_size + 1
+        * HMAC adds a constant overhead.
+        * We're ultimately only interested in differences so this becomes
+        * blocks = (payload_len + 29)/128
+        * for SHA384/SHA512 and
+        * blocks = (payload_len + 21)/64
+        * otherwise.
+        */
+       digest_pad = block_size == 64 ? 21 : 29;
+       blocks_orig = (orig_len + digest_pad)/block_size;
+       blocks_data = (data_len + digest_pad)/block_size;
+       /* MAC enough blocks to make up the difference between the original
+        * and actual lengths plus one extra block to ensure this is never a
+        * no op. The "data" pointer should always have enough space to
+        * perform this operation as it is large enough for a maximum
+        * length TLS buffer. 
+        */
+       HMAC_Update(hctx, data,
+                               (blocks_orig - blocks_data + 1) * block_size);
+       }
+#endif