ossl: Don't encryt/decrypt too much data for chacha20.

The loops for Chacha20 and Chacha20+Poly1305 which encrypted/decrypted
full blocks of data used the minimum of the input and output segment
lengths to determine the size of the next chunk ('todo') to pass to
Chacha20_ctr32().  However, the input and output segments could extend
past the end of the ciphertext region into the tag (e.g.  if a "plain"
single mbuf contained an entire TLS record).  If the length of the tag
plus the length of the last partial block together were at least as
large as a full Chacha20 block (64 bytes), then an extra block was
encrypted/decrypted overlapping with the tag.  Fix this by also
capping the amount of data to encrypt/decrypt by the amount of
remaining data in the ciphertext region ('resid').

Reported by:	gallatin
Reviewed by:	cem, gallatin, markj
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D29517
This commit is contained in:
John Baldwin 2021-04-01 15:42:18 -07:00
parent 4e6c2a1ee9
commit d2e076c37b

View File

@ -88,7 +88,8 @@ ossl_chacha20(struct cryptop *crp, const struct crypto_session_params *csp)
out = outseg; out = outseg;
/* Figure out how many blocks we can encrypt/decrypt at once. */ /* Figure out how many blocks we can encrypt/decrypt at once. */
todo = rounddown(MIN(inlen, outlen), CHACHA_BLK_SIZE); todo = rounddown(MIN(resid, MIN(inlen, outlen)),
CHACHA_BLK_SIZE);
#ifdef __LP64__ #ifdef __LP64__
/* ChaCha20_ctr32() assumes length is <= 4GB. */ /* ChaCha20_ctr32() assumes length is <= 4GB. */
@ -218,7 +219,8 @@ ossl_chacha20_poly1305_encrypt(struct cryptop *crp,
out = outseg; out = outseg;
/* Figure out how many blocks we can encrypt/decrypt at once. */ /* Figure out how many blocks we can encrypt/decrypt at once. */
todo = rounddown(MIN(inlen, outlen), CHACHA_BLK_SIZE); todo = rounddown(MIN(resid, MIN(inlen, outlen)),
CHACHA_BLK_SIZE);
#ifdef __LP64__ #ifdef __LP64__
/* ChaCha20_ctr32() assumes length is <= 4GB. */ /* ChaCha20_ctr32() assumes length is <= 4GB. */
@ -389,7 +391,8 @@ ossl_chacha20_poly1305_decrypt(struct cryptop *crp,
out = outseg; out = outseg;
/* Figure out how many blocks we can encrypt/decrypt at once. */ /* Figure out how many blocks we can encrypt/decrypt at once. */
todo = rounddown(MIN(inlen, outlen), CHACHA_BLK_SIZE); todo = rounddown(MIN(resid, MIN(inlen, outlen)),
CHACHA_BLK_SIZE);
#ifdef __LP64__ #ifdef __LP64__
/* ChaCha20_ctr32() assumes length is <= 4GB. */ /* ChaCha20_ctr32() assumes length is <= 4GB. */