192aecd1eSJohn Baldwin /*- 292aecd1eSJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 392aecd1eSJohn Baldwin * 492aecd1eSJohn Baldwin * Copyright (c) 2020 Netflix, Inc 592aecd1eSJohn Baldwin * 692aecd1eSJohn Baldwin * Redistribution and use in source and binary forms, with or without 792aecd1eSJohn Baldwin * modification, are permitted provided that the following conditions 892aecd1eSJohn Baldwin * are met: 992aecd1eSJohn Baldwin * 1. Redistributions of source code must retain the above copyright 1092aecd1eSJohn Baldwin * notice, this list of conditions and the following disclaimer, 1192aecd1eSJohn Baldwin * without modification. 1292aecd1eSJohn Baldwin * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1392aecd1eSJohn Baldwin * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1492aecd1eSJohn Baldwin * redistribution must be conditioned upon including a substantially 1592aecd1eSJohn Baldwin * similar Disclaimer requirement for further binary redistribution. 1692aecd1eSJohn Baldwin * 1792aecd1eSJohn Baldwin * NO WARRANTY 1892aecd1eSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1992aecd1eSJohn Baldwin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2092aecd1eSJohn Baldwin * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2192aecd1eSJohn Baldwin * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2292aecd1eSJohn Baldwin * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2392aecd1eSJohn Baldwin * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2492aecd1eSJohn Baldwin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2592aecd1eSJohn Baldwin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2692aecd1eSJohn Baldwin * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2792aecd1eSJohn Baldwin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2892aecd1eSJohn Baldwin * THE POSSIBILITY OF SUCH DAMAGES. 2992aecd1eSJohn Baldwin */ 3092aecd1eSJohn Baldwin 3192aecd1eSJohn Baldwin #include <sys/types.h> 3292aecd1eSJohn Baldwin #include <sys/endian.h> 3392aecd1eSJohn Baldwin #include <sys/malloc.h> 3492aecd1eSJohn Baldwin #include <sys/time.h> 3592aecd1eSJohn Baldwin 3692aecd1eSJohn Baldwin #include <opencrypto/cryptodev.h> 3792aecd1eSJohn Baldwin 3892aecd1eSJohn Baldwin #include <crypto/openssl/ossl.h> 3992aecd1eSJohn Baldwin #include <crypto/openssl/ossl_chacha.h> 4078991a93SJohn Baldwin #include <crypto/openssl/ossl_poly1305.h> 4192aecd1eSJohn Baldwin 4292aecd1eSJohn Baldwin int 4392aecd1eSJohn Baldwin ossl_chacha20(struct cryptop *crp, const struct crypto_session_params *csp) 4492aecd1eSJohn Baldwin { 4592aecd1eSJohn Baldwin _Alignas(8) unsigned int key[CHACHA_KEY_SIZE / 4]; 4692aecd1eSJohn Baldwin unsigned int counter[CHACHA_CTR_SIZE / 4]; 4792aecd1eSJohn Baldwin unsigned char block[CHACHA_BLK_SIZE]; 4892aecd1eSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 4992aecd1eSJohn Baldwin const unsigned char *in, *inseg, *cipher_key; 5092aecd1eSJohn Baldwin unsigned char *out, *outseg; 5192aecd1eSJohn Baldwin size_t resid, todo, inlen, outlen; 5292aecd1eSJohn Baldwin uint32_t next_counter; 5392aecd1eSJohn Baldwin u_int i; 5492aecd1eSJohn Baldwin 5592aecd1eSJohn Baldwin if (crp->crp_cipher_key != NULL) 5692aecd1eSJohn Baldwin cipher_key = crp->crp_cipher_key; 5792aecd1eSJohn Baldwin else 5892aecd1eSJohn Baldwin cipher_key = csp->csp_cipher_key; 5992aecd1eSJohn Baldwin for (i = 0; i < nitems(key); i++) 6092aecd1eSJohn Baldwin key[i] = CHACHA_U8TOU32(cipher_key + i * 4); 6192aecd1eSJohn Baldwin crypto_read_iv(crp, counter); 6292aecd1eSJohn Baldwin for (i = 0; i < nitems(counter); i++) 6392aecd1eSJohn Baldwin counter[i] = le32toh(counter[i]); 6492aecd1eSJohn Baldwin 6592aecd1eSJohn Baldwin resid = crp->crp_payload_length; 6692aecd1eSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 6792aecd1eSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 68*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 6992aecd1eSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 7092aecd1eSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 7192aecd1eSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 7292aecd1eSJohn Baldwin } else 7392aecd1eSJohn Baldwin cc_out = cc_in; 74*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 7592aecd1eSJohn Baldwin while (resid >= CHACHA_BLK_SIZE) { 7692aecd1eSJohn Baldwin if (inlen < CHACHA_BLK_SIZE) { 7792aecd1eSJohn Baldwin crypto_cursor_copydata(&cc_in, CHACHA_BLK_SIZE, block); 7892aecd1eSJohn Baldwin in = block; 7992aecd1eSJohn Baldwin inlen = CHACHA_BLK_SIZE; 8092aecd1eSJohn Baldwin } else 8192aecd1eSJohn Baldwin in = inseg; 8292aecd1eSJohn Baldwin if (outlen < CHACHA_BLK_SIZE) { 8392aecd1eSJohn Baldwin out = block; 8492aecd1eSJohn Baldwin outlen = CHACHA_BLK_SIZE; 8592aecd1eSJohn Baldwin } else 8692aecd1eSJohn Baldwin out = outseg; 8792aecd1eSJohn Baldwin 8892aecd1eSJohn Baldwin /* Figure out how many blocks we can encrypt/decrypt at once. */ 89d2e076c3SJohn Baldwin todo = rounddown(MIN(resid, MIN(inlen, outlen)), 90d2e076c3SJohn Baldwin CHACHA_BLK_SIZE); 9192aecd1eSJohn Baldwin 9292aecd1eSJohn Baldwin #ifdef __LP64__ 9392aecd1eSJohn Baldwin /* ChaCha20_ctr32() assumes length is <= 4GB. */ 9492aecd1eSJohn Baldwin todo = (uint32_t)todo; 9592aecd1eSJohn Baldwin #endif 9692aecd1eSJohn Baldwin 9792aecd1eSJohn Baldwin /* Truncate if the 32-bit counter would roll over. */ 9892aecd1eSJohn Baldwin next_counter = counter[0] + todo / CHACHA_BLK_SIZE; 9992aecd1eSJohn Baldwin if (next_counter < counter[0]) { 10092aecd1eSJohn Baldwin todo -= next_counter * CHACHA_BLK_SIZE; 10192aecd1eSJohn Baldwin next_counter = 0; 10292aecd1eSJohn Baldwin } 10392aecd1eSJohn Baldwin 10492aecd1eSJohn Baldwin ChaCha20_ctr32(out, in, todo, key, counter); 10592aecd1eSJohn Baldwin 10692aecd1eSJohn Baldwin counter[0] = next_counter; 10792aecd1eSJohn Baldwin if (counter[0] == 0) 10892aecd1eSJohn Baldwin counter[1]++; 10992aecd1eSJohn Baldwin 11092aecd1eSJohn Baldwin if (out == block) { 11192aecd1eSJohn Baldwin crypto_cursor_copyback(&cc_out, CHACHA_BLK_SIZE, block); 112*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 11392aecd1eSJohn Baldwin } else { 11492aecd1eSJohn Baldwin crypto_cursor_advance(&cc_out, todo); 11592aecd1eSJohn Baldwin outseg += todo; 11692aecd1eSJohn Baldwin outlen -= todo; 11792aecd1eSJohn Baldwin } 11892aecd1eSJohn Baldwin if (in == block) { 119*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 12092aecd1eSJohn Baldwin } else { 12192aecd1eSJohn Baldwin crypto_cursor_advance(&cc_in, todo); 12292aecd1eSJohn Baldwin inseg += todo; 12392aecd1eSJohn Baldwin inlen -= todo; 12492aecd1eSJohn Baldwin } 12592aecd1eSJohn Baldwin resid -= todo; 12692aecd1eSJohn Baldwin } 12792aecd1eSJohn Baldwin 12892aecd1eSJohn Baldwin if (resid > 0) { 12992aecd1eSJohn Baldwin memset(block, 0, sizeof(block)); 13092aecd1eSJohn Baldwin crypto_cursor_copydata(&cc_in, resid, block); 13192aecd1eSJohn Baldwin ChaCha20_ctr32(block, block, CHACHA_BLK_SIZE, key, counter); 13292aecd1eSJohn Baldwin crypto_cursor_copyback(&cc_out, resid, block); 13392aecd1eSJohn Baldwin } 13492aecd1eSJohn Baldwin 13592aecd1eSJohn Baldwin explicit_bzero(block, sizeof(block)); 13692aecd1eSJohn Baldwin explicit_bzero(counter, sizeof(counter)); 13792aecd1eSJohn Baldwin explicit_bzero(key, sizeof(key)); 13892aecd1eSJohn Baldwin return (0); 13992aecd1eSJohn Baldwin } 14078991a93SJohn Baldwin 14178991a93SJohn Baldwin int 14278991a93SJohn Baldwin ossl_chacha20_poly1305_encrypt(struct cryptop *crp, 14378991a93SJohn Baldwin const struct crypto_session_params *csp) 14478991a93SJohn Baldwin { 14578991a93SJohn Baldwin _Alignas(8) unsigned int key[CHACHA_KEY_SIZE / 4]; 14678991a93SJohn Baldwin unsigned int counter[CHACHA_CTR_SIZE / 4]; 14778991a93SJohn Baldwin _Alignas(8) unsigned char block[CHACHA_BLK_SIZE]; 14878991a93SJohn Baldwin unsigned char tag[POLY1305_HASH_LEN]; 14978991a93SJohn Baldwin POLY1305 auth_ctx; 15078991a93SJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 15178991a93SJohn Baldwin const unsigned char *in, *inseg, *cipher_key; 15278991a93SJohn Baldwin unsigned char *out, *outseg; 15378991a93SJohn Baldwin size_t resid, todo, inlen, outlen; 15478991a93SJohn Baldwin uint32_t next_counter; 15578991a93SJohn Baldwin u_int i; 15678991a93SJohn Baldwin 15778991a93SJohn Baldwin if (crp->crp_cipher_key != NULL) 15878991a93SJohn Baldwin cipher_key = crp->crp_cipher_key; 15978991a93SJohn Baldwin else 16078991a93SJohn Baldwin cipher_key = csp->csp_cipher_key; 16178991a93SJohn Baldwin for (i = 0; i < nitems(key); i++) 16278991a93SJohn Baldwin key[i] = CHACHA_U8TOU32(cipher_key + i * 4); 16378991a93SJohn Baldwin 16478991a93SJohn Baldwin crypto_read_iv(crp, counter + 1); 16578991a93SJohn Baldwin for (i = 1; i < nitems(counter); i++) 16678991a93SJohn Baldwin counter[i] = le32toh(counter[i]); 16778991a93SJohn Baldwin 16878991a93SJohn Baldwin /* Block 0 is used to generate the poly1305 key. */ 16978991a93SJohn Baldwin counter[0] = 0; 17078991a93SJohn Baldwin 17178991a93SJohn Baldwin memset(block, 0, sizeof(block)); 17278991a93SJohn Baldwin ChaCha20_ctr32(block, block, sizeof(block), key, counter); 17378991a93SJohn Baldwin Poly1305_Init(&auth_ctx, block); 17478991a93SJohn Baldwin 17578991a93SJohn Baldwin /* MAC the AAD. */ 17678991a93SJohn Baldwin if (crp->crp_aad != NULL) 17778991a93SJohn Baldwin Poly1305_Update(&auth_ctx, crp->crp_aad, crp->crp_aad_length); 17878991a93SJohn Baldwin else 17978991a93SJohn Baldwin crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 18078991a93SJohn Baldwin ossl_poly1305_update, &auth_ctx); 18178991a93SJohn Baldwin if (crp->crp_aad_length % 16 != 0) { 18278991a93SJohn Baldwin /* padding1 */ 18378991a93SJohn Baldwin memset(block, 0, 16); 18478991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, 18578991a93SJohn Baldwin 16 - crp->crp_aad_length % 16); 18678991a93SJohn Baldwin } 18778991a93SJohn Baldwin 18878991a93SJohn Baldwin /* Encryption starts with block 1. */ 18978991a93SJohn Baldwin counter[0] = 1; 19078991a93SJohn Baldwin 19178991a93SJohn Baldwin /* Do encryption with MAC */ 19278991a93SJohn Baldwin resid = crp->crp_payload_length; 19378991a93SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 19478991a93SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 195*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 19678991a93SJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 19778991a93SJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 19878991a93SJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 19978991a93SJohn Baldwin } else 20078991a93SJohn Baldwin cc_out = cc_in; 201*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 20278991a93SJohn Baldwin while (resid >= CHACHA_BLK_SIZE) { 20378991a93SJohn Baldwin if (inlen < CHACHA_BLK_SIZE) { 20478991a93SJohn Baldwin crypto_cursor_copydata(&cc_in, CHACHA_BLK_SIZE, block); 20578991a93SJohn Baldwin in = block; 20678991a93SJohn Baldwin inlen = CHACHA_BLK_SIZE; 20778991a93SJohn Baldwin } else 20878991a93SJohn Baldwin in = inseg; 20978991a93SJohn Baldwin if (outlen < CHACHA_BLK_SIZE) { 21078991a93SJohn Baldwin out = block; 21178991a93SJohn Baldwin outlen = CHACHA_BLK_SIZE; 21278991a93SJohn Baldwin } else 21378991a93SJohn Baldwin out = outseg; 21478991a93SJohn Baldwin 21578991a93SJohn Baldwin /* Figure out how many blocks we can encrypt/decrypt at once. */ 216d2e076c3SJohn Baldwin todo = rounddown(MIN(resid, MIN(inlen, outlen)), 217d2e076c3SJohn Baldwin CHACHA_BLK_SIZE); 21878991a93SJohn Baldwin 21978991a93SJohn Baldwin #ifdef __LP64__ 22078991a93SJohn Baldwin /* ChaCha20_ctr32() assumes length is <= 4GB. */ 22178991a93SJohn Baldwin todo = (uint32_t)todo; 22278991a93SJohn Baldwin #endif 22378991a93SJohn Baldwin 22478991a93SJohn Baldwin /* Truncate if the 32-bit counter would roll over. */ 22578991a93SJohn Baldwin next_counter = counter[0] + todo / CHACHA_BLK_SIZE; 22678991a93SJohn Baldwin if (next_counter < counter[0]) { 22778991a93SJohn Baldwin todo -= next_counter * CHACHA_BLK_SIZE; 22878991a93SJohn Baldwin next_counter = 0; 22978991a93SJohn Baldwin } 23078991a93SJohn Baldwin 23178991a93SJohn Baldwin ChaCha20_ctr32(out, in, todo, key, counter); 23278991a93SJohn Baldwin Poly1305_Update(&auth_ctx, out, todo); 23378991a93SJohn Baldwin 23478991a93SJohn Baldwin counter[0] = next_counter; 23578991a93SJohn Baldwin if (counter[0] == 0) 23678991a93SJohn Baldwin counter[1]++; 23778991a93SJohn Baldwin 23878991a93SJohn Baldwin if (out == block) { 23978991a93SJohn Baldwin crypto_cursor_copyback(&cc_out, CHACHA_BLK_SIZE, block); 240*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 24178991a93SJohn Baldwin } else { 24278991a93SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 24378991a93SJohn Baldwin outseg += todo; 24478991a93SJohn Baldwin outlen -= todo; 24578991a93SJohn Baldwin } 24678991a93SJohn Baldwin if (in == block) { 247*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 24878991a93SJohn Baldwin } else { 24978991a93SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 25078991a93SJohn Baldwin inseg += todo; 25178991a93SJohn Baldwin inlen -= todo; 25278991a93SJohn Baldwin } 25378991a93SJohn Baldwin resid -= todo; 25478991a93SJohn Baldwin } 25578991a93SJohn Baldwin 25678991a93SJohn Baldwin if (resid > 0) { 25778991a93SJohn Baldwin memset(block, 0, sizeof(block)); 25878991a93SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, block); 25978991a93SJohn Baldwin ChaCha20_ctr32(block, block, CHACHA_BLK_SIZE, key, counter); 26078991a93SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, block); 26178991a93SJohn Baldwin 26278991a93SJohn Baldwin /* padding2 */ 26378991a93SJohn Baldwin todo = roundup2(resid, 16); 26478991a93SJohn Baldwin memset(block + resid, 0, todo - resid); 26578991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, todo); 26678991a93SJohn Baldwin } 26778991a93SJohn Baldwin 26878991a93SJohn Baldwin /* lengths */ 26978991a93SJohn Baldwin le64enc(block, crp->crp_aad_length); 27078991a93SJohn Baldwin le64enc(block + 8, crp->crp_payload_length); 27178991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, sizeof(uint64_t) * 2); 27278991a93SJohn Baldwin 27378991a93SJohn Baldwin Poly1305_Final(&auth_ctx, tag); 27478991a93SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, csp->csp_auth_mlen == 0 ? 27578991a93SJohn Baldwin POLY1305_HASH_LEN : csp->csp_auth_mlen, tag); 27678991a93SJohn Baldwin 27778991a93SJohn Baldwin explicit_bzero(&auth_ctx, sizeof(auth_ctx)); 27878991a93SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 27978991a93SJohn Baldwin explicit_bzero(block, sizeof(block)); 28078991a93SJohn Baldwin explicit_bzero(counter, sizeof(counter)); 28178991a93SJohn Baldwin explicit_bzero(key, sizeof(key)); 28278991a93SJohn Baldwin return (0); 28378991a93SJohn Baldwin } 28478991a93SJohn Baldwin 28578991a93SJohn Baldwin 28678991a93SJohn Baldwin int 28778991a93SJohn Baldwin ossl_chacha20_poly1305_decrypt(struct cryptop *crp, 28878991a93SJohn Baldwin const struct crypto_session_params *csp) 28978991a93SJohn Baldwin { 29078991a93SJohn Baldwin _Alignas(8) unsigned int key[CHACHA_KEY_SIZE / 4]; 29178991a93SJohn Baldwin unsigned int counter[CHACHA_CTR_SIZE / 4]; 29278991a93SJohn Baldwin _Alignas(8) unsigned char block[CHACHA_BLK_SIZE]; 29378991a93SJohn Baldwin unsigned char tag[POLY1305_HASH_LEN], tag2[POLY1305_HASH_LEN]; 29478991a93SJohn Baldwin struct poly1305_context auth_ctx; 29578991a93SJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 29678991a93SJohn Baldwin const unsigned char *in, *inseg, *cipher_key; 29778991a93SJohn Baldwin unsigned char *out, *outseg; 29878991a93SJohn Baldwin size_t resid, todo, inlen, outlen; 29978991a93SJohn Baldwin uint32_t next_counter; 30078991a93SJohn Baldwin int error; 30178991a93SJohn Baldwin u_int i, mlen; 30278991a93SJohn Baldwin 30378991a93SJohn Baldwin if (crp->crp_cipher_key != NULL) 30478991a93SJohn Baldwin cipher_key = crp->crp_cipher_key; 30578991a93SJohn Baldwin else 30678991a93SJohn Baldwin cipher_key = csp->csp_cipher_key; 30778991a93SJohn Baldwin for (i = 0; i < nitems(key); i++) 30878991a93SJohn Baldwin key[i] = CHACHA_U8TOU32(cipher_key + i * 4); 30978991a93SJohn Baldwin 31078991a93SJohn Baldwin crypto_read_iv(crp, counter + 1); 31178991a93SJohn Baldwin for (i = 1; i < nitems(counter); i++) 31278991a93SJohn Baldwin counter[i] = le32toh(counter[i]); 31378991a93SJohn Baldwin 31478991a93SJohn Baldwin /* Block 0 is used to generate the poly1305 key. */ 31578991a93SJohn Baldwin counter[0] = 0; 31678991a93SJohn Baldwin 31778991a93SJohn Baldwin memset(block, 0, sizeof(block)); 31878991a93SJohn Baldwin ChaCha20_ctr32(block, block, sizeof(block), key, counter); 31978991a93SJohn Baldwin Poly1305_Init(&auth_ctx, block); 32078991a93SJohn Baldwin 32178991a93SJohn Baldwin /* MAC the AAD. */ 32278991a93SJohn Baldwin if (crp->crp_aad != NULL) 32378991a93SJohn Baldwin Poly1305_Update(&auth_ctx, crp->crp_aad, crp->crp_aad_length); 32478991a93SJohn Baldwin else 32578991a93SJohn Baldwin crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 32678991a93SJohn Baldwin ossl_poly1305_update, &auth_ctx); 32778991a93SJohn Baldwin if (crp->crp_aad_length % 16 != 0) { 32878991a93SJohn Baldwin /* padding1 */ 32978991a93SJohn Baldwin memset(block, 0, 16); 33078991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, 33178991a93SJohn Baldwin 16 - crp->crp_aad_length % 16); 33278991a93SJohn Baldwin } 33378991a93SJohn Baldwin 33478991a93SJohn Baldwin /* Mac the ciphertext. */ 33578991a93SJohn Baldwin crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, 33678991a93SJohn Baldwin ossl_poly1305_update, &auth_ctx); 33778991a93SJohn Baldwin if (crp->crp_payload_length % 16 != 0) { 33878991a93SJohn Baldwin /* padding2 */ 33978991a93SJohn Baldwin memset(block, 0, 16); 34078991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, 34178991a93SJohn Baldwin 16 - crp->crp_payload_length % 16); 34278991a93SJohn Baldwin } 34378991a93SJohn Baldwin 34478991a93SJohn Baldwin /* lengths */ 34578991a93SJohn Baldwin le64enc(block, crp->crp_aad_length); 34678991a93SJohn Baldwin le64enc(block + 8, crp->crp_payload_length); 34778991a93SJohn Baldwin Poly1305_Update(&auth_ctx, block, sizeof(uint64_t) * 2); 34878991a93SJohn Baldwin 34978991a93SJohn Baldwin Poly1305_Final(&auth_ctx, tag); 35078991a93SJohn Baldwin mlen = csp->csp_auth_mlen == 0 ? POLY1305_HASH_LEN : csp->csp_auth_mlen; 35178991a93SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, mlen, tag2); 35278991a93SJohn Baldwin if (timingsafe_bcmp(tag, tag2, mlen) != 0) { 35378991a93SJohn Baldwin error = EBADMSG; 35478991a93SJohn Baldwin goto out; 35578991a93SJohn Baldwin } 35678991a93SJohn Baldwin 35778991a93SJohn Baldwin /* Decryption starts with block 1. */ 35878991a93SJohn Baldwin counter[0] = 1; 35978991a93SJohn Baldwin 36078991a93SJohn Baldwin resid = crp->crp_payload_length; 36178991a93SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 36278991a93SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 363*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 36478991a93SJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 36578991a93SJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 36678991a93SJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 36778991a93SJohn Baldwin } else 36878991a93SJohn Baldwin cc_out = cc_in; 369*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 37078991a93SJohn Baldwin while (resid >= CHACHA_BLK_SIZE) { 37178991a93SJohn Baldwin if (inlen < CHACHA_BLK_SIZE) { 37278991a93SJohn Baldwin crypto_cursor_copydata(&cc_in, CHACHA_BLK_SIZE, block); 37378991a93SJohn Baldwin in = block; 37478991a93SJohn Baldwin inlen = CHACHA_BLK_SIZE; 37578991a93SJohn Baldwin } else 37678991a93SJohn Baldwin in = inseg; 37778991a93SJohn Baldwin if (outlen < CHACHA_BLK_SIZE) { 37878991a93SJohn Baldwin out = block; 37978991a93SJohn Baldwin outlen = CHACHA_BLK_SIZE; 38078991a93SJohn Baldwin } else 38178991a93SJohn Baldwin out = outseg; 38278991a93SJohn Baldwin 38378991a93SJohn Baldwin /* Figure out how many blocks we can encrypt/decrypt at once. */ 384d2e076c3SJohn Baldwin todo = rounddown(MIN(resid, MIN(inlen, outlen)), 385d2e076c3SJohn Baldwin CHACHA_BLK_SIZE); 38678991a93SJohn Baldwin 38778991a93SJohn Baldwin #ifdef __LP64__ 38878991a93SJohn Baldwin /* ChaCha20_ctr32() assumes length is <= 4GB. */ 38978991a93SJohn Baldwin todo = (uint32_t)todo; 39078991a93SJohn Baldwin #endif 39178991a93SJohn Baldwin 39278991a93SJohn Baldwin /* Truncate if the 32-bit counter would roll over. */ 39378991a93SJohn Baldwin next_counter = counter[0] + todo / CHACHA_BLK_SIZE; 39478991a93SJohn Baldwin if (next_counter < counter[0]) { 39578991a93SJohn Baldwin todo -= next_counter * CHACHA_BLK_SIZE; 39678991a93SJohn Baldwin next_counter = 0; 39778991a93SJohn Baldwin } 39878991a93SJohn Baldwin 39978991a93SJohn Baldwin ChaCha20_ctr32(out, in, todo, key, counter); 40078991a93SJohn Baldwin 40178991a93SJohn Baldwin counter[0] = next_counter; 40278991a93SJohn Baldwin if (counter[0] == 0) 40378991a93SJohn Baldwin counter[1]++; 40478991a93SJohn Baldwin 40578991a93SJohn Baldwin if (out == block) { 40678991a93SJohn Baldwin crypto_cursor_copyback(&cc_out, CHACHA_BLK_SIZE, block); 407*1c09320dSJohn Baldwin outseg = crypto_cursor_segment(&cc_out, &outlen); 40878991a93SJohn Baldwin } else { 40978991a93SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 41078991a93SJohn Baldwin outseg += todo; 41178991a93SJohn Baldwin outlen -= todo; 41278991a93SJohn Baldwin } 41378991a93SJohn Baldwin if (in == block) { 414*1c09320dSJohn Baldwin inseg = crypto_cursor_segment(&cc_in, &inlen); 41578991a93SJohn Baldwin } else { 41678991a93SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 41778991a93SJohn Baldwin inseg += todo; 41878991a93SJohn Baldwin inlen -= todo; 41978991a93SJohn Baldwin } 42078991a93SJohn Baldwin resid -= todo; 42178991a93SJohn Baldwin } 42278991a93SJohn Baldwin 42378991a93SJohn Baldwin if (resid > 0) { 42478991a93SJohn Baldwin memset(block, 0, sizeof(block)); 42578991a93SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, block); 42678991a93SJohn Baldwin ChaCha20_ctr32(block, block, CHACHA_BLK_SIZE, key, counter); 42778991a93SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, block); 42878991a93SJohn Baldwin } 42978991a93SJohn Baldwin 43078991a93SJohn Baldwin error = 0; 43178991a93SJohn Baldwin out: 43278991a93SJohn Baldwin explicit_bzero(&auth_ctx, sizeof(auth_ctx)); 43378991a93SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 43478991a93SJohn Baldwin explicit_bzero(block, sizeof(block)); 43578991a93SJohn Baldwin explicit_bzero(counter, sizeof(counter)); 43678991a93SJohn Baldwin explicit_bzero(key, sizeof(key)); 43778991a93SJohn Baldwin return (error); 43878991a93SJohn Baldwin } 439