Skip to content

Commit 306157a

Browse files
committed
Merge #27993: Make poly1305 support incremental computation + modernize
4e5c933 Switch all callers from poly1305_auth to Poly1305 class (Pieter Wuille) 8871f7d tests: add more Poly1305 test vectors (Pieter Wuille) 40e6c5b crypto: add Poly1305 class with std::byte Span interface (Pieter Wuille) 50269b3 crypto: switch poly1305 to incremental implementation (Pieter Wuille) Pull request description: Our current Poly1305 code (src/crypto/poly1305.*) only supports computing the entire tag in one go (the `poly1305_auth` function takes a key and message, and outputs the tag). However, the RFC8439 authenticated encryption (as used in BIP324, see #27634) scheme makes use of Poly1305 in a way where the message consists of 3 different pieces: * The additionally authenticated data (AAD), padded to 16 bytes. * The ciphertext, padded to 16 bytes. * The length of the AAD and the length of the ciphertext, together another 16 bytes. Implementing RFC8439 using the existing `poly1305_auth` function requires creating a temporary copy with all these pieces of data concatenated just for the purpose of computing the tag (the approach used in #25361). This PR replaces the poly1305 code with new code from https://github.com/floodyberry/poly1305-donna (with minor adjustments to make it match our coding style and use our utility functions, documented in the commit) which supports incremental operation, and then adds a C++ wrapper interface using std::byte Spans around it, and adds tests that incremental and all-at-once computation match. ACKs for top commit: achow101: ACK 4e5c933 theStack: ACK 4e5c933 stratospher: tested ACK 4e5c933. Tree-SHA512: df6e9a2a4a38a480f9e4360d3e3def5311673a727a4a85b008a084cf6843b260dc82cec7c73e1cecaaccbf10f3521a0ae7dba388b65d0b086770f7fbc5223e2a
2 parents d09c8bc + 4e5c933 commit 306157a

8 files changed

+392
-154
lines changed

src/bench/chacha_poly_aead.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ static ChaCha20Poly1305AEAD aead(k1, 32, k2, 32);
2323

2424
static void CHACHA20_POLY1305_AEAD(benchmark::Bench& bench, size_t buffersize, bool include_decryption)
2525
{
26-
std::vector<unsigned char> in(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + POLY1305_TAGLEN, 0);
27-
std::vector<unsigned char> out(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + POLY1305_TAGLEN, 0);
26+
std::vector<unsigned char> in(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
27+
std::vector<unsigned char> out(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
2828
uint64_t seqnr_payload = 0;
2929
uint64_t seqnr_aad = 0;
3030
int aad_pos = 0;

src/bench/poly1305.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@
66
#include <bench/bench.h>
77
#include <crypto/poly1305.h>
88

9+
#include <span.h>
10+
911
/* Number of bytes to process per iteration */
1012
static constexpr uint64_t BUFFER_SIZE_TINY = 64;
1113
static constexpr uint64_t BUFFER_SIZE_SMALL = 256;
1214
static constexpr uint64_t BUFFER_SIZE_LARGE = 1024*1024;
1315

1416
static void POLY1305(benchmark::Bench& bench, size_t buffersize)
1517
{
16-
std::vector<unsigned char> tag(POLY1305_TAGLEN, 0);
17-
std::vector<unsigned char> key(POLY1305_KEYLEN, 0);
18-
std::vector<unsigned char> in(buffersize, 0);
18+
std::vector<std::byte> tag(Poly1305::TAGLEN, {});
19+
std::vector<std::byte> key(Poly1305::KEYLEN, {});
20+
std::vector<std::byte> in(buffersize, {});
1921
bench.batch(in.size()).unit("byte").run([&] {
20-
poly1305_auth(tag.data(), in.data(), in.size(), key.data());
22+
Poly1305{key}.Update(in).Finalize(tag);
2123
});
2224
}
2325

src/crypto/chacha_poly_aead.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ bool ChaCha20Poly1305AEAD::Crypt(uint64_t seqnr_payload, uint64_t seqnr_aad, int
5050
// check buffer boundaries
5151
if (
5252
// if we encrypt, make sure the source contains at least the expected AAD and the destination has at least space for the source + MAC
53-
(is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN || dest_len < src_len + POLY1305_TAGLEN)) ||
53+
(is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN || dest_len < src_len + Poly1305::TAGLEN)) ||
5454
// if we decrypt, make sure the source contains at least the expected AAD+MAC and the destination has at least space for the source - MAC
55-
(!is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN + POLY1305_TAGLEN || dest_len < src_len - POLY1305_TAGLEN))) {
55+
(!is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN || dest_len < src_len - Poly1305::TAGLEN))) {
5656
return false;
5757
}
5858

59-
unsigned char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
59+
unsigned char expected_tag[Poly1305::TAGLEN], poly_key[Poly1305::KEYLEN];
6060
memset(poly_key, 0, sizeof(poly_key));
6161

6262
// block counter 0 for the poly1305 key
@@ -67,18 +67,20 @@ bool ChaCha20Poly1305AEAD::Crypt(uint64_t seqnr_payload, uint64_t seqnr_aad, int
6767

6868
// if decrypting, verify the tag prior to decryption
6969
if (!is_encrypt) {
70-
const unsigned char* tag = src + src_len - POLY1305_TAGLEN;
71-
poly1305_auth(expected_tag, src, src_len - POLY1305_TAGLEN, poly_key);
70+
const unsigned char* tag = src + src_len - Poly1305::TAGLEN;
71+
Poly1305{MakeByteSpan(poly_key)}
72+
.Update(AsBytes(Span{src, src_len - Poly1305::TAGLEN}))
73+
.Finalize(MakeWritableByteSpan(expected_tag));
7274

7375
// constant time compare the calculated MAC with the provided MAC
74-
if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
76+
if (timingsafe_bcmp(expected_tag, tag, Poly1305::TAGLEN) != 0) {
7577
memory_cleanse(expected_tag, sizeof(expected_tag));
7678
memory_cleanse(poly_key, sizeof(poly_key));
7779
return false;
7880
}
7981
memory_cleanse(expected_tag, sizeof(expected_tag));
8082
// MAC has been successfully verified, make sure we don't convert it in decryption
81-
src_len -= POLY1305_TAGLEN;
83+
src_len -= Poly1305::TAGLEN;
8284
}
8385

8486
// calculate and cache the next 64byte keystream block if requested sequence number is not yet the cache
@@ -99,7 +101,9 @@ bool ChaCha20Poly1305AEAD::Crypt(uint64_t seqnr_payload, uint64_t seqnr_aad, int
99101
// If encrypting, calculate and append tag
100102
if (is_encrypt) {
101103
// the poly1305 tag expands over the AAD (3 bytes length) & encrypted payload
102-
poly1305_auth(dest + src_len, dest, src_len, poly_key);
104+
Poly1305{MakeByteSpan(poly_key)}
105+
.Update(AsBytes(Span{dest, src_len}))
106+
.Finalize(AsWritableBytes(Span{dest + src_len, Poly1305::TAGLEN}));
103107
}
104108

105109
// cleanse no longer required MAC and polykey

0 commit comments

Comments
 (0)