From a4e20a87d5e66b06ca39bdcc0d4dd5c273a9eb46 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Fri, 14 May 2021 09:32:24 +0430 Subject: [PATCH] LibCrypto: Do not assume that the passed in IV is as long as a block Just take ReadonlyBytes instead of a raw pointer. Fixes #7072 (tested with the ASAN build fixed by #7060). --- Userland/Libraries/LibCrypto/Cipher/AES.h | 4 ++-- Userland/Libraries/LibCrypto/Cipher/Cipher.h | 2 +- Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h | 14 +++++++------- Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h | 2 +- Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Userland/Libraries/LibCrypto/Cipher/AES.h b/Userland/Libraries/LibCrypto/Cipher/AES.h index 236c3bbe63..e92b168615 100644 --- a/Userland/Libraries/LibCrypto/Cipher/AES.h +++ b/Userland/Libraries/LibCrypto/Cipher/AES.h @@ -37,9 +37,9 @@ public: virtual void overwrite(ReadonlyBytes) override; virtual void overwrite(const u8* data, size_t size) override { overwrite({ data, size }); } - virtual void apply_initialization_vector(const u8* ivec) override + virtual void apply_initialization_vector(ReadonlyBytes ivec) override { - for (size_t i = 0; i < block_size(); ++i) + for (size_t i = 0; i < min(block_size(), ivec.size()); ++i) m_data[i] ^= ivec[i]; } diff --git a/Userland/Libraries/LibCrypto/Cipher/Cipher.h b/Userland/Libraries/LibCrypto/Cipher/Cipher.h index 01739ab603..436ff6e2f2 100644 --- a/Userland/Libraries/LibCrypto/Cipher/Cipher.h +++ b/Userland/Libraries/LibCrypto/Cipher/Cipher.h @@ -44,7 +44,7 @@ public: virtual void overwrite(ReadonlyBytes) = 0; virtual void overwrite(const u8* data, size_t size) { overwrite({ data, size }); } - virtual void apply_initialization_vector(const u8* ivec) = 0; + virtual void apply_initialization_vector(ReadonlyBytes ivec) = 0; PaddingMode padding_mode() const { return m_padding_mode; } void set_padding_mode(PaddingMode mode) { m_padding_mode = mode; } diff --git a/Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h b/Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h index de2aa876f6..4bf5065bdc 100644 --- a/Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h +++ b/Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h @@ -47,7 +47,7 @@ public: // FIXME: We should have two of these encrypt/decrypt functions that // we SFINAE out based on whether the Cipher mode needs an ivec VERIFY(!ivec.is_empty()); - const auto* iv = ivec.data(); + ReadonlyBytes iv = ivec; m_cipher_block.set_padding_mode(cipher.padding_mode()); size_t offset { 0 }; @@ -59,7 +59,7 @@ public: cipher.encrypt_block(m_cipher_block, m_cipher_block); VERIFY(offset + block_size <= out.size()); __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size); - iv = out.offset(offset); + iv = out.slice(offset); length -= block_size; offset += block_size; } @@ -70,11 +70,11 @@ public: cipher.encrypt_block(m_cipher_block, m_cipher_block); VERIFY(offset + block_size <= out.size()); __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size); - iv = out.offset(offset); + iv = out.slice(offset); } if (ivec_out) - __builtin_memcpy(ivec_out->data(), iv, min(IV_length(), ivec_out->size())); + __builtin_memcpy(ivec_out->data(), iv.data(), min(IV_length(), ivec_out->size())); } virtual void decrypt(ReadonlyBytes in, Bytes& out, ReadonlyBytes ivec = {}) override @@ -86,7 +86,7 @@ public: auto& cipher = this->cipher(); VERIFY(!ivec.is_empty()); - const auto* iv = ivec.data(); + ReadonlyBytes iv = ivec; auto block_size = cipher.block_size(); @@ -98,8 +98,8 @@ public: size_t offset { 0 }; while (length > 0) { - auto* slice = in.offset(offset); - m_cipher_block.overwrite(slice, block_size); + auto slice = in.slice(offset); + m_cipher_block.overwrite(slice.data(), block_size); cipher.decrypt_block(m_cipher_block, m_cipher_block); m_cipher_block.apply_initialization_vector(iv); auto decrypted = m_cipher_block.bytes(); diff --git a/Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h b/Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h index 249bb142ca..dc02a175e1 100644 --- a/Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h +++ b/Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h @@ -168,7 +168,7 @@ protected: cipher.encrypt_block(m_cipher_block, m_cipher_block); if (in) { - m_cipher_block.apply_initialization_vector(in->data() + offset); + m_cipher_block.apply_initialization_vector(in->slice(offset)); } auto write_size = min(block_size, length); diff --git a/Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h b/Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h index 30773cba90..0f5610ae63 100644 --- a/Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h +++ b/Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h @@ -84,7 +84,7 @@ public: CTR::encrypt(in, out, iv); auto auth_tag = m_ghash->process(aad, out); - block0.apply_initialization_vector(auth_tag.data); + block0.apply_initialization_vector({ auth_tag.data, array_size(auth_tag.data) }); block0.bytes().copy_to(tag); } @@ -103,7 +103,7 @@ public: CTR::increment(iv); auto auth_tag = m_ghash->process(aad, in); - block0.apply_initialization_vector(auth_tag.data); + block0.apply_initialization_vector({ auth_tag.data, array_size(auth_tag.data) }); auto test_consistency = [&] { if (block0.block_size() != tag.size() || __builtin_memcmp(block0.bytes().data(), tag.data(), tag.size()) != 0)