validate data lengths against value in header
[python-delta-tar] / testing / test_crypto.py
index 7efb195..dc652e2 100644 (file)
@@ -480,6 +480,66 @@ class AESGCMTest (CryptoLayerTest):
         for i in range (16): encobj (1 << i)
 
 
+    def test_crypto_aes_gcm_dec_length_cap (self):
+        """
+        The decryptor must reject headers with an object size that exceeds
+        the PDTCRYPT maximum. Longer files split into multiple objects.
+        """
+        password        = str (os.urandom (42))
+        meta            = faux_hdr()
+        meta ["ctsize"] = crypto.PDTCRYPT_MAX_OBJ_SIZE + 1
+        ok, header      = crypto.hdr_make (meta)
+
+        assert ok
+
+        # Set up decryption with bogus header.
+        decryptor = crypto.Decrypt (password=password, fixedparts=[])
+
+        with self.assertRaises (crypto.InvalidHeader):
+            decryptor.next (header)
+
+
+    def test_crypto_aes_gcm_dec_length_mismatch (self):
+        """
+        Catch attempts at decrypting more data than what was stated in the
+        header.
+        """
+        cnksiz         = 1 << 10
+        orig_pt        = fill_mod (1 << 14)
+        password       = str (os.urandom (42))
+        encryptor      = crypto.Encrypt (TEST_VERSION,
+                                         TEST_PARAMVERSION,
+                                         password=password,
+                                         nacl=TEST_STATIC_NACL)
+        header_dummy   = encryptor.next (TEST_DUMMY_FILENAME)
+
+        off = 0
+        ct = b""
+        while off < len (orig_pt):
+            upto = min (off + cnksiz, len (orig_pt))
+            _n, cnk = encryptor.process (orig_pt [off:upto])
+            ct += cnk
+            off += cnksiz
+        cnk, header, fixed = encryptor.done (header_dummy)
+        ct += cnk
+
+        decryptor = crypto.Decrypt (password=password, fixedparts=fixed)
+
+        decryptor.next (header)
+        off = 0
+        pt  = b""
+        while off < len (orig_pt):
+            upto = min (off + cnksiz, len (orig_pt))
+            cnk  = decryptor.process (ct [off:upto])
+            pt += cnk
+            off += cnksiz
+
+        with self.assertRaises (crypto.CiphertextTooLong):
+            # Try and decrypt one byte more than was encrypted.
+            # This must be caught in crypto.py.
+            _ = decryptor.process (ct [0:1])
+
+
     def test_crypto_aes_gcm_dec_multicnk (self):
         cnksiz         = 1 << 10
         orig_pt        = fill_mod (1 << 14)