Skip to content

Commit 2084060

Browse files
committed
Merge #15519: Add Poly1305 implementation
e9d5e97 Poly1305: tolerate the intentional unsigned wraparound in poly1305.cpp (Jonas Schnelli) b34bf30 Add Poly1305 bench (Jonas Schnelli) 03be7f4 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
2 parents e14cd04 + e9d5e97 commit 2084060

File tree

7 files changed

+285
-0
lines changed

7 files changed

+285
-0
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
346346
crypto/hmac_sha256.h \
347347
crypto/hmac_sha512.cpp \
348348
crypto/hmac_sha512.h \
349+
crypto/poly1305.h \
350+
crypto/poly1305.cpp \
349351
crypto/ripemd160.cpp \
350352
crypto/ripemd160.h \
351353
crypto/sha1.cpp \

src/Makefile.bench.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ bench_bench_bitcoin_SOURCES = \
3131
bench/base58.cpp \
3232
bench/bech32.cpp \
3333
bench/lockedpool.cpp \
34+
bench/poly1305.cpp \
3435
bench/prevector.cpp
3536

3637
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)

src/bench/poly1305.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <iostream>
6+
7+
#include <bench/bench.h>
8+
#include <crypto/poly1305.h>
9+
10+
/* Number of bytes to process per iteration */
11+
static constexpr uint64_t BUFFER_SIZE_TINY = 64;
12+
static constexpr uint64_t BUFFER_SIZE_SMALL = 256;
13+
static constexpr uint64_t BUFFER_SIZE_LARGE = 1024*1024;
14+
15+
static void POLY1305(benchmark::State& state, size_t buffersize)
16+
{
17+
std::vector<unsigned char> tag(POLY1305_TAGLEN, 0);
18+
std::vector<unsigned char> key(POLY1305_KEYLEN, 0);
19+
std::vector<unsigned char> in(buffersize, 0);
20+
while (state.KeepRunning())
21+
poly1305_auth(tag.data(), in.data(), in.size(), key.data());
22+
}
23+
24+
static void POLY1305_64BYTES(benchmark::State& state)
25+
{
26+
POLY1305(state, BUFFER_SIZE_TINY);
27+
}
28+
29+
static void POLY1305_256BYTES(benchmark::State& state)
30+
{
31+
POLY1305(state, BUFFER_SIZE_SMALL);
32+
}
33+
34+
static void POLY1305_1MB(benchmark::State& state)
35+
{
36+
POLY1305(state, BUFFER_SIZE_LARGE);
37+
}
38+
39+
BENCHMARK(POLY1305_64BYTES, 500000);
40+
BENCHMARK(POLY1305_256BYTES, 250000);
41+
BENCHMARK(POLY1305_1MB, 340);

src/crypto/poly1305.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright (c) 2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
// Based on the public domain implementation by Andrew Moon
6+
// poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
7+
8+
#include <crypto/common.h>
9+
#include <crypto/poly1305.h>
10+
11+
#include <string.h>
12+
13+
#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
14+
15+
void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
16+
uint32_t t0,t1,t2,t3;
17+
uint32_t h0,h1,h2,h3,h4;
18+
uint32_t r0,r1,r2,r3,r4;
19+
uint32_t s1,s2,s3,s4;
20+
uint32_t b, nb;
21+
size_t j;
22+
uint64_t t[5];
23+
uint64_t f0,f1,f2,f3;
24+
uint64_t g0,g1,g2,g3,g4;
25+
uint64_t c;
26+
unsigned char mp[16];
27+
28+
/* clamp key */
29+
t0 = ReadLE32(key+0);
30+
t1 = ReadLE32(key+4);
31+
t2 = ReadLE32(key+8);
32+
t3 = ReadLE32(key+12);
33+
34+
/* precompute multipliers */
35+
r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
36+
r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
37+
r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
38+
r3 = t2 & 0x3f03fff; t3 >>= 8;
39+
r4 = t3 & 0x00fffff;
40+
41+
s1 = r1 * 5;
42+
s2 = r2 * 5;
43+
s3 = r3 * 5;
44+
s4 = r4 * 5;
45+
46+
/* init state */
47+
h0 = 0;
48+
h1 = 0;
49+
h2 = 0;
50+
h3 = 0;
51+
h4 = 0;
52+
53+
/* full blocks */
54+
if (inlen < 16) goto poly1305_donna_atmost15bytes;
55+
poly1305_donna_16bytes:
56+
m += 16;
57+
inlen -= 16;
58+
59+
t0 = ReadLE32(m-16);
60+
t1 = ReadLE32(m-12);
61+
t2 = ReadLE32(m-8);
62+
t3 = ReadLE32(m-4);
63+
64+
h0 += t0 & 0x3ffffff;
65+
h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
66+
h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
67+
h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
68+
h4 += (t3 >> 8) | (1 << 24);
69+
70+
71+
poly1305_donna_mul:
72+
t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
73+
t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
74+
t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
75+
t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
76+
t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
77+
78+
h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26);
79+
t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
80+
t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
81+
t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
82+
t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
83+
h0 += b * 5;
84+
85+
if (inlen >= 16) goto poly1305_donna_16bytes;
86+
87+
/* final bytes */
88+
poly1305_donna_atmost15bytes:
89+
if (!inlen) goto poly1305_donna_finish;
90+
91+
for (j = 0; j < inlen; j++) mp[j] = m[j];
92+
mp[j++] = 1;
93+
for (; j < 16; j++) mp[j] = 0;
94+
inlen = 0;
95+
96+
t0 = ReadLE32(mp+0);
97+
t1 = ReadLE32(mp+4);
98+
t2 = ReadLE32(mp+8);
99+
t3 = ReadLE32(mp+12);
100+
101+
h0 += t0 & 0x3ffffff;
102+
h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
103+
h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
104+
h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
105+
h4 += (t3 >> 8);
106+
107+
goto poly1305_donna_mul;
108+
109+
poly1305_donna_finish:
110+
b = h0 >> 26; h0 = h0 & 0x3ffffff;
111+
h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
112+
h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
113+
h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
114+
h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
115+
h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
116+
h1 += b;
117+
118+
g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
119+
g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
120+
g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
121+
g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
122+
g4 = h4 + b - (1 << 26);
123+
124+
b = (g4 >> 31) - 1;
125+
nb = ~b;
126+
h0 = (h0 & nb) | (g0 & b);
127+
h1 = (h1 & nb) | (g1 & b);
128+
h2 = (h2 & nb) | (g2 & b);
129+
h3 = (h3 & nb) | (g3 & b);
130+
h4 = (h4 & nb) | (g4 & b);
131+
132+
f0 = ((h0 ) | (h1 << 26)) + (uint64_t)ReadLE32(&key[16]);
133+
f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)ReadLE32(&key[20]);
134+
f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)ReadLE32(&key[24]);
135+
f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)ReadLE32(&key[28]);
136+
137+
WriteLE32(&out[ 0], f0); f1 += (f0 >> 32);
138+
WriteLE32(&out[ 4], f1); f2 += (f1 >> 32);
139+
WriteLE32(&out[ 8], f2); f3 += (f2 >> 32);
140+
WriteLE32(&out[12], f3);
141+
}

src/crypto/poly1305.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_CRYPTO_POLY1305_H
6+
#define BITCOIN_CRYPTO_POLY1305_H
7+
8+
#include <stdint.h>
9+
#include <stdlib.h>
10+
11+
#define POLY1305_KEYLEN 32
12+
#define POLY1305_TAGLEN 16
13+
14+
void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen,
15+
const unsigned char key[POLY1305_KEYLEN]);
16+
17+
#endif // BITCOIN_CRYPTO_POLY1305_H

src/test/crypto_tests.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <crypto/aes.h>
66
#include <crypto/chacha20.h>
7+
#include <crypto/poly1305.h>
78
#include <crypto/ripemd160.h>
89
#include <crypto/sha1.h>
910
#include <crypto/sha256.h>
@@ -200,6 +201,17 @@ static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t see
200201
BOOST_CHECK(out == outres);
201202
}
202203

204+
static void TestPoly1305(const std::string &hexmessage, const std::string &hexkey, const std::string& hextag)
205+
{
206+
std::vector<unsigned char> key = ParseHex(hexkey);
207+
std::vector<unsigned char> m = ParseHex(hexmessage);
208+
std::vector<unsigned char> tag = ParseHex(hextag);
209+
std::vector<unsigned char> tagres;
210+
tagres.resize(POLY1305_TAGLEN);
211+
poly1305_auth(tagres.data(), m.data(), m.size(), key.data());
212+
BOOST_CHECK(tag == tagres);
213+
}
214+
203215
static std::string LongTestString() {
204216
std::string ret;
205217
for (int i=0; i<200000; i++) {
@@ -524,6 +536,76 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector)
524536
"fab78c9");
525537
}
526538

539+
BOOST_AUTO_TEST_CASE(poly1305_testvector)
540+
{
541+
// RFC 7539, section 2.5.2.
542+
TestPoly1305("43727970746f6772617068696320466f72756d2052657365617263682047726f7570",
543+
"85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
544+
"a8061dc1305136c6c22b8baf0c0127a9");
545+
546+
// RFC 7539, section A.3.
547+
TestPoly1305("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
548+
"000000000000000000000000000",
549+
"0000000000000000000000000000000000000000000000000000000000000000",
550+
"00000000000000000000000000000000");
551+
552+
TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
553+
"5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
554+
"726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
555+
"520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
556+
"4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
557+
"56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
558+
"6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
559+
"768696368206172652061646472657373656420746f",
560+
"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
561+
"36e5f6b5c5e06070f0efca96227a863e");
562+
563+
TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
564+
"5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
565+
"726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
566+
"520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
567+
"4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
568+
"56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
569+
"6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
570+
"768696368206172652061646472657373656420746f",
571+
"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
572+
"f3477e7cd95417af89a6b8794c310cf0");
573+
574+
TestPoly1305("2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e6420676"
575+
"96d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e"
576+
"6420746865206d6f6d65207261746873206f757467726162652e",
577+
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
578+
"4541669a7eaaee61e708dc7cbcc5eb62");
579+
580+
TestPoly1305("ffffffffffffffffffffffffffffffff",
581+
"0200000000000000000000000000000000000000000000000000000000000000",
582+
"03000000000000000000000000000000");
583+
584+
TestPoly1305("02000000000000000000000000000000",
585+
"02000000000000000000000000000000ffffffffffffffffffffffffffffffff",
586+
"03000000000000000000000000000000");
587+
588+
TestPoly1305("fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000",
589+
"0100000000000000000000000000000000000000000000000000000000000000",
590+
"05000000000000000000000000000000");
591+
592+
TestPoly1305("fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101",
593+
"0100000000000000000000000000000000000000000000000000000000000000",
594+
"00000000000000000000000000000000");
595+
596+
TestPoly1305("fdffffffffffffffffffffffffffffff",
597+
"0200000000000000000000000000000000000000000000000000000000000000",
598+
"faffffffffffffffffffffffffffffff");
599+
600+
TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000",
601+
"0100000000000000040000000000000000000000000000000000000000000000",
602+
"14000000000000005500000000000000");
603+
604+
TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000",
605+
"0100000000000000040000000000000000000000000000000000000000000000",
606+
"13000000000000000000000000000000");
607+
}
608+
527609
BOOST_AUTO_TEST_CASE(countbits_tests)
528610
{
529611
FastRandomContext ctx;

test/sanitizer_suppressions/ubsan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ unsigned-integer-overflow:coded_stream.h
1515
unsigned-integer-overflow:core_write.cpp
1616
unsigned-integer-overflow:crypto/chacha20.cpp
1717
unsigned-integer-overflow:crypto/ctaes/ctaes.c
18+
unsigned-integer-overflow:crypto/poly1305.cpp
1819
unsigned-integer-overflow:crypto/ripemd160.cpp
1920
unsigned-integer-overflow:crypto/sha1.cpp
2021
unsigned-integer-overflow:crypto/sha256.cpp

0 commit comments

Comments
 (0)