summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Waldmann <tw@waldmann-edv.de>2023-02-19 21:06:54 +0100
committerThomas Waldmann <tw@waldmann-edv.de>2023-02-19 21:14:20 +0100
commitfea630027c6981094293deeeff9aa5a35fca9628 (patch)
tree04b48280f51d1af612e93d2fd2be1d2bddf98e7d
parent93a4bd61f81872a10e640c2b18575df60beb4be1 (diff)
assert_id: better be paranoid, fixes #7362
This makes borg2's new crypto do the same check as borg1's old crypto and makes sure that no chunks created by an evil borg client would go unnoticed.
-rw-r--r--src/borg/crypto/key.py18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py
index c31270cd5..01b08579d 100644
--- a/src/borg/crypto/key.py
+++ b/src/borg/crypto/key.py
@@ -840,11 +840,23 @@ class AEADKeyBase(KeyBase):
MAX_IV = 2**48 - 1
def assert_id(self, id, data):
- # note: assert_id(id, data) is not needed any more for the new AEAD crypto.
- # we put the id into AAD when storing the chunk, so it gets into the authentication tag computation.
+ # Comparing the id hash here would not be needed any more for the new AEAD crypto **IF** we
+ # could be sure that chunks were created by normal (not tampered, not evil) borg code:
+ # We put the id into AAD when storing the chunk, so it gets into the authentication tag computation.
# when decrypting, we provide the id we **want** as AAD for the auth tag verification, so
# decrypting only succeeds if we got the ciphertext we wrote **for that chunk id**.
- pass
+ # So, basically the **repository** can not cheat on us by giving us a different chunk.
+ #
+ # **BUT**, if chunks are created by tampered, evil borg code, the borg client code could put
+ # a wrong chunkid into AAD and then AEAD-encrypt-and-auth this and store it into the
+ # repository using this bad chunkid as key (violating the usual chunkid == id_hash(data)).
+ # Later, when reading such a bad chunk, AEAD-auth-and-decrypt would not notice any
+ # issue and decrypt successfully.
+ # Thus, to notice such evil borg activity, we must check for such violations here:
+ if id and id != Manifest.MANIFEST_ID:
+ id_computed = self.id_hash(data)
+ if not hmac.compare_digest(id_computed, id):
+ raise IntegrityError("Chunk %s: id verification failed" % bin_to_hex(id))
def encrypt(self, id, data):
# to encrypt new data in this session we use always self.cipher and self.sessionid