diff --git a/krypto/src/tests/integration/conftest.py b/krypto/src/tests/integration/conftest.py index f63010c3f..df0a8801a 100644 --- a/krypto/src/tests/integration/conftest.py +++ b/krypto/src/tests/integration/conftest.py @@ -56,9 +56,20 @@ def definition_dir(krypto_kompile: Callable[..., Path]) -> Path: module TEST imports BOOL + imports BYTES + imports INT + imports K-EQUAL + imports STRING imports KRYPTO syntax Pgm ::= Bool | Bytes | String | G1Point | G2Point configuration $PGM:Pgm + + // Passes the same Bytes term to Blake2Compress and to the check that + // follows it, so that a hook mutating its argument in place is observable. + syntax Bool ::= blake2NoAlias ( Bytes ) [function] + | blake2NoAliasAux ( String , Bytes ) [function] + rule blake2NoAlias(B) => blake2NoAliasAux(Blake2Compress(B), B) + rule blake2NoAliasAux(OUT, B) => lengthString(OUT) ==Int 128 andBool B ==K padRightBytes(b"", 213, 0) endmodule """ return krypto_kompile(definition=definition, main_module='TEST', syntax_module='TEST') diff --git a/krypto/src/tests/integration/test_hooks.py b/krypto/src/tests/integration/test_hooks.py index 8306732a2..6e22282b8 100644 --- a/krypto/src/tests/integration/test_hooks.py +++ b/krypto/src/tests/integration/test_hooks.py @@ -51,6 +51,11 @@ f"Blake2Compress({hex2bytes(213 * '00')})", '"08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"', ), + ( + 'Blake2CompressNoAliasing', + f"blake2NoAlias({hex2bytes(213 * '00')})", + 'true', + ), ( 'Keccak256raw', 'Keccak256raw(b"foo")', diff --git a/plugin-c/crypto.cpp b/plugin-c/crypto.cpp index 7584c599b..1d6d2133b 100644 --- a/plugin-c/crypto.cpp +++ b/plugin-c/crypto.cpp @@ -192,7 +192,10 @@ struct string *hook_KRYPTO_blake2compress(struct string *params) { } unsigned char *data = (unsigned char *)params->data; uint32_t rounds = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; - uint64_t *h = (uint64_t *)&data[4]; + // blake2b_compress updates h in place; params aliases the caller's Bytes, + // which the hook must not mutate, so compress a copy of the state. + uint64_t h[8]; + memcpy(h, &data[4], sizeof(h)); uint64_t *m = (uint64_t *)&data[68]; uint64_t *t = (uint64_t *)&data[196]; unsigned char f = data[212];