diff options
Diffstat (limited to 'crypto/poly1305/poly1305_test.cc')
-rw-r--r-- | crypto/poly1305/poly1305_test.cc | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/crypto/poly1305/poly1305_test.cc b/crypto/poly1305/poly1305_test.cc index cae30a42..2c25e93b 100644 --- a/crypto/poly1305/poly1305_test.cc +++ b/crypto/poly1305/poly1305_test.cc @@ -24,6 +24,54 @@ #include "../test/file_test.h" +static bool TestSIMD(FileTest *t, unsigned excess, + const std::vector<uint8_t> &key, + const std::vector<uint8_t> &in, + const std::vector<uint8_t> &mac) { + poly1305_state state; + CRYPTO_poly1305_init(&state, key.data()); + + size_t done = 0; + + // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade + // on-demand. Stress the upgrade path. + size_t todo = 16; + if (todo > in.size()) { + todo = in.size(); + } + CRYPTO_poly1305_update(&state, in.data(), todo); + done += todo; + + for (;;) { + // Feed 128 + |excess| bytes to test SIMD mode. + if (done + 128 + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess); + done += 128 + excess; + + // Feed |excess| bytes to ensure SIMD mode can handle short inputs. + if (done + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, excess); + done += excess; + } + + // Consume the remainder and finish. + CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done); + + // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output. + alignas(16) uint8_t out[16]; + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { + t->PrintLine("SIMD pattern %u failed.", excess); + return false; + } + + return true; +} + static bool TestPoly1305(FileTest *t, void *arg) { std::vector<uint8_t> key, in, mac; if (!t->GetBytes(&key, "Key") || @@ -54,11 +102,20 @@ static bool TestPoly1305(FileTest *t, void *arg) { CRYPTO_poly1305_update(&state, &in[i], 1); } CRYPTO_poly1305_finish(&state, out); - if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) { + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { t->PrintLine("Streaming Poly1305 failed."); return false; } + // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of + // four blocks, so test up to three blocks of excess. + if (!TestSIMD(t, 0, key, in, mac) || + !TestSIMD(t, 16, key, in, mac) || + !TestSIMD(t, 32, key, in, mac) || + !TestSIMD(t, 48, key, in, mac)) { + return false; + } + return true; } |