-
Notifications
You must be signed in to change notification settings - Fork 36.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add chacha20/poly1305 and chacha20poly1305_AEAD from openssh #14050
Add chacha20/poly1305 and chacha20poly1305_AEAD from openssh #14050
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Why not reuse the existing ChaCha20? |
@DesWurstes: see PR description (out of scope). |
Added benchmark for the AEAD (and for direct comparison also added the dbl-SHA (HASH) benchmark). My system reports (!we compare SSE4 SHA256 vs non-optimized chacha20):
|
fcfa804
to
90702f4
Compare
src/crypto/chachapoly_aead.cpp
Outdated
might try to eliminate "superfluous" memsets. If there's an easy way to | ||
detect memset_s, it would be better to use that. */ | ||
#if defined(_MSC_VER) | ||
SecureZeroMemory(ptr, len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems this should include windows.h
f42f6d5
to
ac477bc
Compare
src/crypto/chachapoly_aead.h
Outdated
uint8_t *dest, const uint8_t *src, uint32_t len, | ||
uint32_t aadlen, int is_encrypt); | ||
|
||
// extracts the LE 24bit (3byte) length from the AAD and puts it into a uint32_t (host endiannes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo found by codespell
: endiannes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
ac477bc
to
d415a02
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re out of scope "Combining with the existing ChaCha20 RNG": perhaps you can add some tests to show they're identical?
*/ | ||
|
||
static const struct chacha20_testvector chacha20_testvectors[] = { | ||
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be much easier to verify against the RFC document if you parse a hex string.
(p)[3] = (uint8_t)((v) >> 24); \ | ||
} while (0) | ||
|
||
void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove the poly1305_init, poly1305_update, poly1305_finish separation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which separation? I took Andrew Moons implementation found at https://github.com/openssh/openssh-portable/blob/90e51d672711c19a36573be1785caf35019ae7a8/poly1305.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see, in that case the source code URL at the top of the file is confusing; probably should add a link to Moons' implementation instead / in addition.
x->input[3] = U8TO32_LITTLE(constants + 12); | ||
} | ||
|
||
void chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can confirm this function in 09ec49ba31867187cecd631593d37bcc5f3ca72f is identical to the original at de624c626ea081929df000b09932dbc804eda51d, modulo some whitespace.
@Sjors The existing ChaCha20 implementation doesn't do the XORing and can therefore only be used for the RNG. |
Instead of those U8TOU32_LE macros you can use our own function (ReadLE32,
WriteLE32).
… |
@sipa: agree. Though as written in the PR description. I'd like to keep the code (extracted from openSSH) as identical as possible. I think (or hope) we can do refactoring after this has been merged. |
chacha_ivsetup(&ctx->header_ctx, (uint8_t *)&seqnr64, NULL); | ||
chacha_encrypt_bytes(&ctx->header_ctx, ciphertext, buf, 3); | ||
*len24_out = 0; | ||
*len24_out = buf[0] | (buf[1] << 8) | (buf[2] << 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a mistake? *len24_out
is assigned twice? *len24_out = 0;
should be removed? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if applying 3 time a uint_8t (24bits) the way its done here will guarantee to set the other 8 bits to 0. This is why I initialise with 0, then set bit 0 to 23. Could be that I'm wrong though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We wouldn't initialise before assignment if the RHS was an integer, right? :-)
buf[0] | (buf[1] << 8) | (buf[2] << 16)
evaluates to an integer.
But don't trust me – I'm just a fellow human.
Let's verify using our favourite C++ interpreter cling
:
$ cling
****************** CLING ******************
* Type C++ code and press enter to run it *
* Type .q to exit *
*******************************************
[cling]$ typeid(1).name()
(const char *) "i"
[cling]$ #include <cstdint>
[cling]$ uint8_t buf[3] = {1, 2, 3}
(uint8_t [3]) { '0x01', '0x02', '0x03' }
[cling]$ typeid(buf[0] | (buf[1] << 8) | (buf[2] << 16)).name()
(const char *) "i"
[cling]$ buf[0] | (buf[1] << 8) | (buf[2] << 16)
(int) 197121
:-)
src/test/crypto_tests.cpp
Outdated
assert(out_len == 255); | ||
chacha20poly1305_crypt(&aead_ctx, seqnr, plaintext_buf_new, ciphertext_buf, | ||
252, 3, 0); | ||
assert(memcmp(plaintext_buf, plaintext_buf_new, 252) == 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be assert(memcmp(plaintext_buf, plaintext_buf_new, 255) == 0);
or assert(memcmp(plaintext_buf, plaintext_buf_new, sizeof(plaintext_buf)) == 0);
?
src/crypto/chachapoly_aead.cpp
Outdated
uint32_t aadlen, int is_encrypt) { | ||
const uint8_t one[8] = {1, 0, 0, 0, 0, 0, 0, 0}; /* NB little-endian */ | ||
uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; | ||
int r = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a dead store :-)
Initialize to zero instead and remove the r = 0
below?
d415a02
to
e65a418
Compare
Fixed points reported by @practicalswift |
I'm afraid this PR doesn't compile when rebased on |
Partially superseded by #15512 (the ChaCha20 part) |
This adds ChaCha20 and Poly1305 and the openSSH form of the AEAD.
The implementations of ChaCha20 are from DJB himself and directly taken (unchanged as much as possible) from the openSSH source code: https://github.com/openssh/openssh-portable/blob/master/chacha.c
Poly1305 is written by Andrew Moon is also directly taken (unchanged as much as possible) from the openSSH source code: https://github.com/openssh/openssh-portable/blob/master/poly1305.c
The code for the ChaCha20/Poly1305@openssh AEAD is taken from https://github.com/openssh/openssh-portable/blob/master/cipher-chachapoly.c with minimal changes.
More details on the AEAD construction:
https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.chacha20poly1305
https://gist.github.com/jonasschnelli/c530ea8421b8d0e80c51486325587c52
Test vectors are taken from the RFC draft:
https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
Taking existing implementations should reduce risks of screwing up at the implementation level.
OUT OF SCOPE:
(can all be done later, after verification of the correctness)
This is a subset of #14032 and a pre-requirement for BIP151.