Просмотр исходного кода

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).
Ali Mohammad Pur 4 лет назад
Родитель
Сommit
a4e20a87d5

+ 2 - 2
Userland/Libraries/LibCrypto/Cipher/AES.h

@@ -37,9 +37,9 @@ public:
     virtual void overwrite(ReadonlyBytes) override;
     virtual void overwrite(ReadonlyBytes) override;
     virtual void overwrite(const u8* data, size_t size) override { overwrite({ data, size }); }
     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];
             m_data[i] ^= ivec[i];
     }
     }
 
 

+ 1 - 1
Userland/Libraries/LibCrypto/Cipher/Cipher.h

@@ -44,7 +44,7 @@ public:
     virtual void overwrite(ReadonlyBytes) = 0;
     virtual void overwrite(ReadonlyBytes) = 0;
     virtual void overwrite(const u8* data, size_t size) { overwrite({ data, size }); }
     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; }
     PaddingMode padding_mode() const { return m_padding_mode; }
     void set_padding_mode(PaddingMode mode) { m_padding_mode = mode; }
     void set_padding_mode(PaddingMode mode) { m_padding_mode = mode; }

+ 7 - 7
Userland/Libraries/LibCrypto/Cipher/Mode/CBC.h

@@ -47,7 +47,7 @@ public:
         // FIXME: We should have two of these encrypt/decrypt functions that
         // FIXME: We should have two of these encrypt/decrypt functions that
         //        we SFINAE out based on whether the Cipher mode needs an ivec
         //        we SFINAE out based on whether the Cipher mode needs an ivec
         VERIFY(!ivec.is_empty());
         VERIFY(!ivec.is_empty());
-        const auto* iv = ivec.data();
+        ReadonlyBytes iv = ivec;
 
 
         m_cipher_block.set_padding_mode(cipher.padding_mode());
         m_cipher_block.set_padding_mode(cipher.padding_mode());
         size_t offset { 0 };
         size_t offset { 0 };
@@ -59,7 +59,7 @@ public:
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             VERIFY(offset + block_size <= out.size());
             VERIFY(offset + block_size <= out.size());
             __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size);
             __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size);
-            iv = out.offset(offset);
+            iv = out.slice(offset);
             length -= block_size;
             length -= block_size;
             offset += block_size;
             offset += block_size;
         }
         }
@@ -70,11 +70,11 @@ public:
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             VERIFY(offset + block_size <= out.size());
             VERIFY(offset + block_size <= out.size());
             __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size);
             __builtin_memcpy(out.offset(offset), m_cipher_block.bytes().data(), block_size);
-            iv = out.offset(offset);
+            iv = out.slice(offset);
         }
         }
 
 
         if (ivec_out)
         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
     virtual void decrypt(ReadonlyBytes in, Bytes& out, ReadonlyBytes ivec = {}) override
@@ -86,7 +86,7 @@ public:
         auto& cipher = this->cipher();
         auto& cipher = this->cipher();
 
 
         VERIFY(!ivec.is_empty());
         VERIFY(!ivec.is_empty());
-        const auto* iv = ivec.data();
+        ReadonlyBytes iv = ivec;
 
 
         auto block_size = cipher.block_size();
         auto block_size = cipher.block_size();
 
 
@@ -98,8 +98,8 @@ public:
         size_t offset { 0 };
         size_t offset { 0 };
 
 
         while (length > 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);
             cipher.decrypt_block(m_cipher_block, m_cipher_block);
             m_cipher_block.apply_initialization_vector(iv);
             m_cipher_block.apply_initialization_vector(iv);
             auto decrypted = m_cipher_block.bytes();
             auto decrypted = m_cipher_block.bytes();

+ 1 - 1
Userland/Libraries/LibCrypto/Cipher/Mode/CTR.h

@@ -168,7 +168,7 @@ protected:
 
 
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             cipher.encrypt_block(m_cipher_block, m_cipher_block);
             if (in) {
             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);
             auto write_size = min(block_size, length);
 
 

+ 2 - 2
Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h

@@ -84,7 +84,7 @@ public:
             CTR<T>::encrypt(in, out, iv);
             CTR<T>::encrypt(in, out, iv);
 
 
         auto auth_tag = m_ghash->process(aad, out);
         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);
         block0.bytes().copy_to(tag);
     }
     }
 
 
@@ -103,7 +103,7 @@ public:
         CTR<T>::increment(iv);
         CTR<T>::increment(iv);
 
 
         auto auth_tag = m_ghash->process(aad, in);
         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 = [&] {
         auto test_consistency = [&] {
             if (block0.block_size() != tag.size() || __builtin_memcmp(block0.bytes().data(), tag.data(), tag.size()) != 0)
             if (block0.block_size() != tag.size() || __builtin_memcmp(block0.bytes().data(), tag.data(), tag.size()) != 0)