Commit d91d9acc authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Timing fix mitigation for FIPS mode.

We have to use EVP in FIPS mode so we can only partially mitigate
timing differences.

Make an extra call to EVP_DigestSignUpdate to hash additonal blocks
to cover any timing differences caused by removal of padding.
(cherry picked from commit b908e88e)
parent 820988a0
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -368,6 +368,10 @@ static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out)
 * which ssl3_cbc_digest_record supports. */
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
	{
#ifdef OPENSSL_FIPS
	if (FIPS_mode())
		return 0;
#endif
	switch (ctx->digest->type)
		{
		case NID_md5:
@@ -694,3 +698,50 @@ void ssl3_cbc_digest_record(
		*md_out_size = md_out_size_u;
	EVP_MD_CTX_cleanup(&md_ctx);
	}

#ifndef 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, EVP_MD_CTX *mac_ctx,
	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_CTX_block_size(mac_ctx);
	/* 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. 
	 */
	EVP_DigestSignUpdate(mac_ctx, data,
				(blocks_orig - blocks_data + 1) * block_size);
	}
#endif
+4 −0
Original line number Diff line number Diff line
@@ -1299,4 +1299,8 @@ void ssl3_cbc_digest_record(
	unsigned mac_secret_length,
	char is_sslv3);

void tls_fips_digest_extra(
	const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx,
	const unsigned char *data, size_t data_len, size_t orig_len);

#endif
+7 −0
Original line number Diff line number Diff line
@@ -1049,6 +1049,13 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
		EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
		t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
		OPENSSL_assert(t > 0);
#ifdef OPENSSL_FIPS
		if (!send && FIPS_mode())
			tls_fips_digest_extra(
	    				ssl->enc_read_ctx,
					mac_ctx, rec->input,
					rec->length, rec->orig_len);
#endif
		}
		
	if (!stream_mac)