def _update(self, buf): self.acc += buf n = len(buf) # Copy to the heap to help ASan copy = FFI.new("char[]", n) FFI.memmove(copy, buf, n) self.update(copy, n)
def test_public_params_derive(bits, key): length = FFI.sizeof("struct umash_params") umash_key = b"Do not use UMASH VS adversaries." if key is not None: umash_key = key nonce = struct.pack("<Q", bits) expected = FFI.new("struct umash_params[1]") salsa_bytes = Salsa20.new(umash_key, nonce).encrypt(b"\x00" * length) FFI.memmove(expected, salsa_bytes, length) assert C.umash_params_prepare(expected) actual = FFI.new("struct umash_params[1]") if key is None: C.umash_params_derive(actual, bits, FFI.NULL) else: buf = FFI.new("char[]", len(key)) FFI.memmove(buf, key, len(key)) C.umash_params_derive(actual, bits, buf) # The values should all be the same. assert length % 8 == 0 for i in range(length // 8): assert FFI.cast("uint64_t *", actual)[i] == FFI.cast("uint64_t *", expected)[i]
def test_vec_to_u64(data): """Make sure we expand to a uint64 correctly.""" n_bytes = len(data) # Copy to a malloc-ed buffer to help ASan. buf = FFI.new("char[]", n_bytes) FFI.memmove(buf, data, n_bytes) assert C.vec_to_u64(buf, n_bytes) == vec_to_u64(data)
def test_umash_short(seed, key, data): """Compare umash_short with the reference.""" expected = umash(UmashKey(poly=0, oh=key), seed, data) n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].oh[i] = param assert C.umash_short(params[0].oh, seed, block, n_bytes) == expected
def assert_idempotent(params): """Asserts that calling `umash_params_prepare` on something that was successfully prepared is idempotent. """ size = FFI.sizeof("struct umash_params") copy = FFI.new("struct umash_params[1]") FFI.memmove(copy, params, size) assert C.umash_params_prepare(copy) == True # The copy should still be the same as params. assert size % 8 == 0 for i in range(size // 8): assert FFI.cast("uint64_t *", params)[i] == FFI.cast("uint64_t *", copy)[i]
def test_public_umash_full_shifted(seed, multiplier, key, data): """Compare umash_full(which=1) with the reference.""" expected = umash(UmashKey(poly=multiplier, oh=key), seed, data) n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) params = FFI.new("struct umash_params[1]") params[0].poly[1][0] = (multiplier**2) % FIELD params[0].poly[1][1] = multiplier for i, param in enumerate(key): params[0].oh[i + C.UMASH_OH_TOEPLITZ_SHIFT] = param assert C.umash_full(params, seed, 1, block, n_bytes) == expected
def test_public_umash_full(seed, multiplier, key, data): """Compare umash_full with the reference.""" expected = umash(UmashKey(poly=multiplier, ph=key), seed, data) n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) params = FFI.new("struct umash_params[1]") params[0].poly[0][0] = (multiplier ** 2) % FIELD params[0].poly[0][1] = multiplier for i, param in enumerate(key): params[0].ph[i] = param assert C.umash_full(params, seed, 0, block, n_bytes) == expected
def test_umash_medium(seed, multiplier, key, data): """Compare umash_medium with the reference.""" expected = umash(UmashKey(poly=multiplier, ph=key), seed, data) n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) poly = FFI.new("uint64_t[2]") poly[0] = (multiplier**2) % FIELD poly[1] = multiplier params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].ph[i] = param assert C.umash_medium(poly, params[0].ph, seed, block, n_bytes) == expected
def test_ph_one_block(seed, key, data): """Compare PH compression for full blocks.""" expected = ph_compress_one_block(key, seed, split_block(data)) # Copy to exactly-sized malloced buffers to help ASan. block = FFI.new("char[]", BLOCK_SIZE) FFI.memmove(block, data, BLOCK_SIZE) params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].ph[i] = param actual = C.ph_one_block(params[0].ph, seed, block) assert expected == actual.bits[0] + (actual.bits[1] << 64), ( actual.bits[0], actual.bits[1], )
def test_umash_long_repeat(seed, multiplier, key, data): """Compare umash_long on repeated strings with the reference.""" expected = umash(UmashKey(poly=multiplier, oh=key), seed, data, secondary=False) note(len(data)) n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) poly = FFI.new("uint64_t[2]") poly[0] = (multiplier ** 2) % FIELD poly[1] = multiplier params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].oh[i] = param assert C.umash_long(poly, params[0].oh, seed, block, n_bytes) == expected
def test_ph_tail_large(seed, key, data): """Compare PH compression for the last block, when it has enough data to fully contain the last 16-byte chunk.""" expected = ph_compress_one_block(key, seed, split_block(data)) n_bytes = len(data) # Copy to exactly-sized malloced buffers to help ASan. block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].ph[i] = param actual = C.ph_last_block(params[0].ph, seed, block, n_bytes) assert expected == actual.bits[0] + (actual.bits[1] << 64), ( actual.bits[0], actual.bits[1], )
def test_oh_one_block(tag, key, data): """Compare OH compression for full blocks.""" # The C-side implicit accepts the high half of the tag, and leaves # the low half zeroed out. expected = oh_compress_one_block(key, split_block(data), tag << 64) # Copy to exactly-sized malloced buffers to help ASan. block = FFI.new("char[]", BLOCK_SIZE) FFI.memmove(block, data, BLOCK_SIZE) params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].oh[i] = param actual = C.oh_one_block(params[0].oh, tag, block) assert expected == actual.bits[0] + (actual.bits[1] << 64), ( actual.bits[0], actual.bits[1], )
def test_public_umash_fprint(seed, multipliers, key, data): """Compare umash_fprint with two calls to the reference.""" expected = [ umash(UmashKey(poly=multipliers[0], oh=key[:-4]), seed, data), umash(UmashKey(poly=multipliers[1], oh=key[4:]), seed, data), ] n_bytes = len(data) block = FFI.new("char[]", n_bytes) FFI.memmove(block, data, n_bytes) params = FFI.new("struct umash_params[1]") for i, multiplier in enumerate(multipliers): params[0].poly[i][0] = (multiplier**2) % FIELD params[0].poly[i][1] = multiplier for i, param in enumerate(key): params[0].oh[i] = param actual = C.umash_fprint(params, seed, block, n_bytes) assert [actual.hash[0], actual.hash[1]] == expected
def test_ph_tail_short(seed, key, prefix, data): """Compare PH compression for the last block, when we must steal some data from the previous chunk.""" expected = ph_compress_one_block( key, seed, split_block(prefix * (C.UMASH_PH_PARAM_COUNT // 2) + data) ) offset = len(prefix) n_bytes = len(data) # Copy to exactly-sized malloced buffers to help ASan. block = FFI.new("char[]", offset + n_bytes) FFI.memmove(block, prefix + data, offset + n_bytes) params = FFI.new("struct umash_params[1]") for i, param in enumerate(key): params[0].ph[i] = param actual = C.ph_last_block(params[0].ph, seed, block + offset, n_bytes) assert expected == actual.bits[0] + (actual.bits[1] << 64), ( actual.bits[0], actual.bits[1], )