Merge #15519: Add Poly1305 implementation
e9d5e97561
Poly1305: tolerate the intentional unsigned wraparound in poly1305.cpp (Jonas Schnelli)b34bf302f2
Add Poly1305 bench (Jonas Schnelli)03be7f48fa
Add Poly1305 implementation (Jonas Schnelli) Pull request description: This adds a currently unused Poly1305 implementation including test vectors from RFC7539. Required for BIP151 (and related to #15512). Tree-SHA512: f8c1ad2f686b980a7498ca50c517e2348ac7b1fe550565156f6c2b20faf764978e4fa6b5b1c3777a16e7a12e2eca3fb57a59be9c788b00d4358ee80f2959edb1
This commit is contained in:
commit
208406038c
7 changed files with 285 additions and 0 deletions
|
@ -346,6 +346,8 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
|
|||
crypto/hmac_sha256.h \
|
||||
crypto/hmac_sha512.cpp \
|
||||
crypto/hmac_sha512.h \
|
||||
crypto/poly1305.h \
|
||||
crypto/poly1305.cpp \
|
||||
crypto/ripemd160.cpp \
|
||||
crypto/ripemd160.h \
|
||||
crypto/sha1.cpp \
|
||||
|
|
|
@ -31,6 +31,7 @@ bench_bench_bitcoin_SOURCES = \
|
|||
bench/base58.cpp \
|
||||
bench/bech32.cpp \
|
||||
bench/lockedpool.cpp \
|
||||
bench/poly1305.cpp \
|
||||
bench/prevector.cpp
|
||||
|
||||
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
|
||||
|
|
41
src/bench/poly1305.cpp
Normal file
41
src/bench/poly1305.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <bench/bench.h>
|
||||
#include <crypto/poly1305.h>
|
||||
|
||||
/* Number of bytes to process per iteration */
|
||||
static constexpr uint64_t BUFFER_SIZE_TINY = 64;
|
||||
static constexpr uint64_t BUFFER_SIZE_SMALL = 256;
|
||||
static constexpr uint64_t BUFFER_SIZE_LARGE = 1024*1024;
|
||||
|
||||
static void POLY1305(benchmark::State& state, size_t buffersize)
|
||||
{
|
||||
std::vector<unsigned char> tag(POLY1305_TAGLEN, 0);
|
||||
std::vector<unsigned char> key(POLY1305_KEYLEN, 0);
|
||||
std::vector<unsigned char> in(buffersize, 0);
|
||||
while (state.KeepRunning())
|
||||
poly1305_auth(tag.data(), in.data(), in.size(), key.data());
|
||||
}
|
||||
|
||||
static void POLY1305_64BYTES(benchmark::State& state)
|
||||
{
|
||||
POLY1305(state, BUFFER_SIZE_TINY);
|
||||
}
|
||||
|
||||
static void POLY1305_256BYTES(benchmark::State& state)
|
||||
{
|
||||
POLY1305(state, BUFFER_SIZE_SMALL);
|
||||
}
|
||||
|
||||
static void POLY1305_1MB(benchmark::State& state)
|
||||
{
|
||||
POLY1305(state, BUFFER_SIZE_LARGE);
|
||||
}
|
||||
|
||||
BENCHMARK(POLY1305_64BYTES, 500000);
|
||||
BENCHMARK(POLY1305_256BYTES, 250000);
|
||||
BENCHMARK(POLY1305_1MB, 340);
|
141
src/crypto/poly1305.cpp
Normal file
141
src/crypto/poly1305.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) 2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
// Based on the public domain implementation by Andrew Moon
|
||||
// poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
|
||||
|
||||
#include <crypto/common.h>
|
||||
#include <crypto/poly1305.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
|
||||
|
||||
void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
|
||||
uint32_t t0,t1,t2,t3;
|
||||
uint32_t h0,h1,h2,h3,h4;
|
||||
uint32_t r0,r1,r2,r3,r4;
|
||||
uint32_t s1,s2,s3,s4;
|
||||
uint32_t b, nb;
|
||||
size_t j;
|
||||
uint64_t t[5];
|
||||
uint64_t f0,f1,f2,f3;
|
||||
uint64_t g0,g1,g2,g3,g4;
|
||||
uint64_t c;
|
||||
unsigned char mp[16];
|
||||
|
||||
/* clamp key */
|
||||
t0 = ReadLE32(key+0);
|
||||
t1 = ReadLE32(key+4);
|
||||
t2 = ReadLE32(key+8);
|
||||
t3 = ReadLE32(key+12);
|
||||
|
||||
/* precompute multipliers */
|
||||
r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
|
||||
r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
|
||||
r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
|
||||
r3 = t2 & 0x3f03fff; t3 >>= 8;
|
||||
r4 = t3 & 0x00fffff;
|
||||
|
||||
s1 = r1 * 5;
|
||||
s2 = r2 * 5;
|
||||
s3 = r3 * 5;
|
||||
s4 = r4 * 5;
|
||||
|
||||
/* init state */
|
||||
h0 = 0;
|
||||
h1 = 0;
|
||||
h2 = 0;
|
||||
h3 = 0;
|
||||
h4 = 0;
|
||||
|
||||
/* full blocks */
|
||||
if (inlen < 16) goto poly1305_donna_atmost15bytes;
|
||||
poly1305_donna_16bytes:
|
||||
m += 16;
|
||||
inlen -= 16;
|
||||
|
||||
t0 = ReadLE32(m-16);
|
||||
t1 = ReadLE32(m-12);
|
||||
t2 = ReadLE32(m-8);
|
||||
t3 = ReadLE32(m-4);
|
||||
|
||||
h0 += t0 & 0x3ffffff;
|
||||
h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
|
||||
h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
|
||||
h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
|
||||
h4 += (t3 >> 8) | (1 << 24);
|
||||
|
||||
|
||||
poly1305_donna_mul:
|
||||
t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
|
||||
t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
|
||||
t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
|
||||
t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
|
||||
t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
|
||||
|
||||
h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26);
|
||||
t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
|
||||
t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
|
||||
t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
|
||||
t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
|
||||
h0 += b * 5;
|
||||
|
||||
if (inlen >= 16) goto poly1305_donna_16bytes;
|
||||
|
||||
/* final bytes */
|
||||
poly1305_donna_atmost15bytes:
|
||||
if (!inlen) goto poly1305_donna_finish;
|
||||
|
||||
for (j = 0; j < inlen; j++) mp[j] = m[j];
|
||||
mp[j++] = 1;
|
||||
for (; j < 16; j++) mp[j] = 0;
|
||||
inlen = 0;
|
||||
|
||||
t0 = ReadLE32(mp+0);
|
||||
t1 = ReadLE32(mp+4);
|
||||
t2 = ReadLE32(mp+8);
|
||||
t3 = ReadLE32(mp+12);
|
||||
|
||||
h0 += t0 & 0x3ffffff;
|
||||
h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
|
||||
h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
|
||||
h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
|
||||
h4 += (t3 >> 8);
|
||||
|
||||
goto poly1305_donna_mul;
|
||||
|
||||
poly1305_donna_finish:
|
||||
b = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += b;
|
||||
|
||||
g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
|
||||
g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
|
||||
g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
|
||||
g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
|
||||
g4 = h4 + b - (1 << 26);
|
||||
|
||||
b = (g4 >> 31) - 1;
|
||||
nb = ~b;
|
||||
h0 = (h0 & nb) | (g0 & b);
|
||||
h1 = (h1 & nb) | (g1 & b);
|
||||
h2 = (h2 & nb) | (g2 & b);
|
||||
h3 = (h3 & nb) | (g3 & b);
|
||||
h4 = (h4 & nb) | (g4 & b);
|
||||
|
||||
f0 = ((h0 ) | (h1 << 26)) + (uint64_t)ReadLE32(&key[16]);
|
||||
f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)ReadLE32(&key[20]);
|
||||
f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)ReadLE32(&key[24]);
|
||||
f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)ReadLE32(&key[28]);
|
||||
|
||||
WriteLE32(&out[ 0], f0); f1 += (f0 >> 32);
|
||||
WriteLE32(&out[ 4], f1); f2 += (f1 >> 32);
|
||||
WriteLE32(&out[ 8], f2); f3 += (f2 >> 32);
|
||||
WriteLE32(&out[12], f3);
|
||||
}
|
17
src/crypto/poly1305.h
Normal file
17
src/crypto/poly1305.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_POLY1305_H
|
||||
#define BITCOIN_CRYPTO_POLY1305_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define POLY1305_KEYLEN 32
|
||||
#define POLY1305_TAGLEN 16
|
||||
|
||||
void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen,
|
||||
const unsigned char key[POLY1305_KEYLEN]);
|
||||
|
||||
#endif // BITCOIN_CRYPTO_POLY1305_H
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/chacha20.h>
|
||||
#include <crypto/poly1305.h>
|
||||
#include <crypto/ripemd160.h>
|
||||
#include <crypto/sha1.h>
|
||||
#include <crypto/sha256.h>
|
||||
|
@ -200,6 +201,17 @@ static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t see
|
|||
BOOST_CHECK(out == outres);
|
||||
}
|
||||
|
||||
static void TestPoly1305(const std::string &hexmessage, const std::string &hexkey, const std::string& hextag)
|
||||
{
|
||||
std::vector<unsigned char> key = ParseHex(hexkey);
|
||||
std::vector<unsigned char> m = ParseHex(hexmessage);
|
||||
std::vector<unsigned char> tag = ParseHex(hextag);
|
||||
std::vector<unsigned char> tagres;
|
||||
tagres.resize(POLY1305_TAGLEN);
|
||||
poly1305_auth(tagres.data(), m.data(), m.size(), key.data());
|
||||
BOOST_CHECK(tag == tagres);
|
||||
}
|
||||
|
||||
static std::string LongTestString() {
|
||||
std::string ret;
|
||||
for (int i=0; i<200000; i++) {
|
||||
|
@ -524,6 +536,76 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector)
|
|||
"fab78c9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(poly1305_testvector)
|
||||
{
|
||||
// RFC 7539, section 2.5.2.
|
||||
TestPoly1305("43727970746f6772617068696320466f72756d2052657365617263682047726f7570",
|
||||
"85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
|
||||
"a8061dc1305136c6c22b8baf0c0127a9");
|
||||
|
||||
// RFC 7539, section A.3.
|
||||
TestPoly1305("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000");
|
||||
|
||||
TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
|
||||
"5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
|
||||
"726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
|
||||
"520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
|
||||
"4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
|
||||
"56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
|
||||
"6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
|
||||
"768696368206172652061646472657373656420746f",
|
||||
"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
|
||||
"36e5f6b5c5e06070f0efca96227a863e");
|
||||
|
||||
TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
|
||||
"5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
|
||||
"726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
|
||||
"520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
|
||||
"4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
|
||||
"56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
|
||||
"6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
|
||||
"768696368206172652061646472657373656420746f",
|
||||
"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
|
||||
"f3477e7cd95417af89a6b8794c310cf0");
|
||||
|
||||
TestPoly1305("2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e6420676"
|
||||
"96d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e"
|
||||
"6420746865206d6f6d65207261746873206f757467726162652e",
|
||||
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
|
||||
"4541669a7eaaee61e708dc7cbcc5eb62");
|
||||
|
||||
TestPoly1305("ffffffffffffffffffffffffffffffff",
|
||||
"0200000000000000000000000000000000000000000000000000000000000000",
|
||||
"03000000000000000000000000000000");
|
||||
|
||||
TestPoly1305("02000000000000000000000000000000",
|
||||
"02000000000000000000000000000000ffffffffffffffffffffffffffffffff",
|
||||
"03000000000000000000000000000000");
|
||||
|
||||
TestPoly1305("fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000",
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"05000000000000000000000000000000");
|
||||
|
||||
TestPoly1305("fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101",
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000");
|
||||
|
||||
TestPoly1305("fdffffffffffffffffffffffffffffff",
|
||||
"0200000000000000000000000000000000000000000000000000000000000000",
|
||||
"faffffffffffffffffffffffffffffff");
|
||||
|
||||
TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000",
|
||||
"0100000000000000040000000000000000000000000000000000000000000000",
|
||||
"14000000000000005500000000000000");
|
||||
|
||||
TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000",
|
||||
"0100000000000000040000000000000000000000000000000000000000000000",
|
||||
"13000000000000000000000000000000");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(countbits_tests)
|
||||
{
|
||||
FastRandomContext ctx;
|
||||
|
|
|
@ -15,6 +15,7 @@ unsigned-integer-overflow:coded_stream.h
|
|||
unsigned-integer-overflow:core_write.cpp
|
||||
unsigned-integer-overflow:crypto/chacha20.cpp
|
||||
unsigned-integer-overflow:crypto/ctaes/ctaes.c
|
||||
unsigned-integer-overflow:crypto/poly1305.cpp
|
||||
unsigned-integer-overflow:crypto/ripemd160.cpp
|
||||
unsigned-integer-overflow:crypto/sha1.cpp
|
||||
unsigned-integer-overflow:crypto/sha256.cpp
|
||||
|
|
Loading…
Reference in a new issue