1*197ff4c3SKornel Duleba /*- 2*197ff4c3SKornel Duleba * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*197ff4c3SKornel Duleba * 4*197ff4c3SKornel Duleba * Copyright (c) 2021 Stormshield. 5*197ff4c3SKornel Duleba * Copyright (c) 2021 Semihalf. 6*197ff4c3SKornel Duleba * 7*197ff4c3SKornel Duleba * Redistribution and use in source and binary forms, with or without 8*197ff4c3SKornel Duleba * modification, are permitted provided that the following conditions 9*197ff4c3SKornel Duleba * are met: 10*197ff4c3SKornel Duleba * 1. Redistributions of source code must retain the above copyright 11*197ff4c3SKornel Duleba * notice, this list of conditions and the following disclaimer. 12*197ff4c3SKornel Duleba * 2. Redistributions in binary form must reproduce the above copyright 13*197ff4c3SKornel Duleba * notice, this list of conditions and the following disclaimer in the 14*197ff4c3SKornel Duleba * documentation and/or other materials provided with the distribution. 15*197ff4c3SKornel Duleba * 16*197ff4c3SKornel Duleba * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*197ff4c3SKornel Duleba * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*197ff4c3SKornel Duleba * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*197ff4c3SKornel Duleba * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*197ff4c3SKornel Duleba * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*197ff4c3SKornel Duleba * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*197ff4c3SKornel Duleba * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*197ff4c3SKornel Duleba * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*197ff4c3SKornel Duleba * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*197ff4c3SKornel Duleba * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*197ff4c3SKornel Duleba */ 27*197ff4c3SKornel Duleba 28*197ff4c3SKornel Duleba #include <sys/cdefs.h> 29*197ff4c3SKornel Duleba __FBSDID("$FreeBSD$"); 30*197ff4c3SKornel Duleba 31*197ff4c3SKornel Duleba #include <sys/param.h> 32*197ff4c3SKornel Duleba #include <sys/malloc.h> 33*197ff4c3SKornel Duleba 34*197ff4c3SKornel Duleba #include <opencrypto/cryptodev.h> 35*197ff4c3SKornel Duleba 36*197ff4c3SKornel Duleba #include <crypto/openssl/ossl.h> 37*197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h> 38*197ff4c3SKornel Duleba 39*197ff4c3SKornel Duleba #if defined(__amd64__) || defined(__i386__) 40*197ff4c3SKornel Duleba #include <crypto/openssl/ossl_x86.h> 41*197ff4c3SKornel Duleba #elif defined (__aarch64__) 42*197ff4c3SKornel Duleba #include <crypto/openssl/ossl_aarch64.h> 43*197ff4c3SKornel Duleba #endif 44*197ff4c3SKornel Duleba 45*197ff4c3SKornel Duleba static ossl_cipher_process_t ossl_aes_cbc; 46*197ff4c3SKornel Duleba 47*197ff4c3SKornel Duleba struct ossl_cipher ossl_cipher_aes_cbc = { 48*197ff4c3SKornel Duleba .type = CRYPTO_AES_CBC, 49*197ff4c3SKornel Duleba .blocksize = AES_BLOCK_LEN, 50*197ff4c3SKornel Duleba .ivsize = AES_BLOCK_LEN, 51*197ff4c3SKornel Duleba 52*197ff4c3SKornel Duleba /* Filled during initialization based on CPU caps. */ 53*197ff4c3SKornel Duleba .set_encrypt_key = NULL, 54*197ff4c3SKornel Duleba .set_decrypt_key = NULL, 55*197ff4c3SKornel Duleba .process = ossl_aes_cbc 56*197ff4c3SKornel Duleba }; 57*197ff4c3SKornel Duleba 58*197ff4c3SKornel Duleba static int 59*197ff4c3SKornel Duleba ossl_aes_cbc(struct ossl_session_cipher *s, struct cryptop *crp, 60*197ff4c3SKornel Duleba const struct crypto_session_params *csp) 61*197ff4c3SKornel Duleba { 62*197ff4c3SKornel Duleba struct crypto_buffer_cursor cc_in, cc_out; 63*197ff4c3SKornel Duleba unsigned char block[EALG_MAX_BLOCK_LEN]; 64*197ff4c3SKornel Duleba unsigned char iv[EALG_MAX_BLOCK_LEN]; 65*197ff4c3SKornel Duleba const unsigned char *in, *inseg; 66*197ff4c3SKornel Duleba unsigned char *out, *outseg; 67*197ff4c3SKornel Duleba size_t plen, seglen, inlen, outlen; 68*197ff4c3SKornel Duleba struct ossl_cipher_context key; 69*197ff4c3SKornel Duleba struct ossl_cipher *cipher; 70*197ff4c3SKornel Duleba int blocklen, error; 71*197ff4c3SKornel Duleba bool encrypt; 72*197ff4c3SKornel Duleba 73*197ff4c3SKornel Duleba cipher = s->cipher; 74*197ff4c3SKornel Duleba encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 75*197ff4c3SKornel Duleba plen = crp->crp_payload_length; 76*197ff4c3SKornel Duleba blocklen = cipher->blocksize; 77*197ff4c3SKornel Duleba 78*197ff4c3SKornel Duleba if (plen % blocklen) 79*197ff4c3SKornel Duleba return (EINVAL); 80*197ff4c3SKornel Duleba 81*197ff4c3SKornel Duleba if (crp->crp_cipher_key != NULL) { 82*197ff4c3SKornel Duleba if (encrypt) 83*197ff4c3SKornel Duleba error = cipher->set_encrypt_key(crp->crp_cipher_key, 84*197ff4c3SKornel Duleba 8 * csp->csp_cipher_klen, &key); 85*197ff4c3SKornel Duleba else 86*197ff4c3SKornel Duleba error = cipher->set_decrypt_key(crp->crp_cipher_key, 87*197ff4c3SKornel Duleba 8 * csp->csp_cipher_klen, &key); 88*197ff4c3SKornel Duleba if (error) 89*197ff4c3SKornel Duleba return (error); 90*197ff4c3SKornel Duleba } else { 91*197ff4c3SKornel Duleba if (encrypt) 92*197ff4c3SKornel Duleba key = s->enc_ctx; 93*197ff4c3SKornel Duleba else 94*197ff4c3SKornel Duleba key = s->dec_ctx; 95*197ff4c3SKornel Duleba } 96*197ff4c3SKornel Duleba 97*197ff4c3SKornel Duleba crypto_read_iv(crp, iv); 98*197ff4c3SKornel Duleba 99*197ff4c3SKornel Duleba /* Derived from ossl_chacha20.c */ 100*197ff4c3SKornel Duleba crypto_cursor_init(&cc_in, &crp->crp_buf); 101*197ff4c3SKornel Duleba crypto_cursor_advance(&cc_in, crp->crp_payload_start); 102*197ff4c3SKornel Duleba inseg = crypto_cursor_segment(&cc_in, &inlen); 103*197ff4c3SKornel Duleba if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 104*197ff4c3SKornel Duleba crypto_cursor_init(&cc_out, &crp->crp_obuf); 105*197ff4c3SKornel Duleba crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 106*197ff4c3SKornel Duleba } else { 107*197ff4c3SKornel Duleba cc_out = cc_in; 108*197ff4c3SKornel Duleba } 109*197ff4c3SKornel Duleba outseg = crypto_cursor_segment(&cc_out, &outlen); 110*197ff4c3SKornel Duleba 111*197ff4c3SKornel Duleba while (plen >= blocklen) { 112*197ff4c3SKornel Duleba if (inlen < blocklen) { 113*197ff4c3SKornel Duleba crypto_cursor_copydata(&cc_in, blocklen, block); 114*197ff4c3SKornel Duleba in = block; 115*197ff4c3SKornel Duleba inlen = blocklen; 116*197ff4c3SKornel Duleba } else { 117*197ff4c3SKornel Duleba in = inseg; 118*197ff4c3SKornel Duleba } 119*197ff4c3SKornel Duleba if (outlen < blocklen) { 120*197ff4c3SKornel Duleba out = block; 121*197ff4c3SKornel Duleba outlen = blocklen; 122*197ff4c3SKornel Duleba } else { 123*197ff4c3SKornel Duleba out = outseg; 124*197ff4c3SKornel Duleba } 125*197ff4c3SKornel Duleba 126*197ff4c3SKornel Duleba /* Figure out how many blocks we can encrypt/decrypt at once. */ 127*197ff4c3SKornel Duleba seglen = rounddown(MIN(plen, MIN(inlen, outlen)), blocklen); 128*197ff4c3SKornel Duleba 129*197ff4c3SKornel Duleba AES_CBC_ENCRYPT(in, out, seglen, &key, iv, encrypt); 130*197ff4c3SKornel Duleba 131*197ff4c3SKornel Duleba if (out == block) { 132*197ff4c3SKornel Duleba crypto_cursor_copyback(&cc_out, blocklen, block); 133*197ff4c3SKornel Duleba outseg = crypto_cursor_segment(&cc_out, &outlen); 134*197ff4c3SKornel Duleba } else { 135*197ff4c3SKornel Duleba crypto_cursor_advance(&cc_out, seglen); 136*197ff4c3SKornel Duleba outseg += seglen; 137*197ff4c3SKornel Duleba outlen -= seglen; 138*197ff4c3SKornel Duleba } 139*197ff4c3SKornel Duleba if (in == block) { 140*197ff4c3SKornel Duleba inseg = crypto_cursor_segment(&cc_in, &inlen); 141*197ff4c3SKornel Duleba } else { 142*197ff4c3SKornel Duleba crypto_cursor_advance(&cc_in, seglen); 143*197ff4c3SKornel Duleba inseg += seglen; 144*197ff4c3SKornel Duleba inlen -= seglen; 145*197ff4c3SKornel Duleba } 146*197ff4c3SKornel Duleba plen -= seglen; 147*197ff4c3SKornel Duleba } 148*197ff4c3SKornel Duleba 149*197ff4c3SKornel Duleba explicit_bzero(block, sizeof(block)); 150*197ff4c3SKornel Duleba explicit_bzero(iv, sizeof(iv)); 151*197ff4c3SKornel Duleba explicit_bzero(&key, sizeof(key)); 152*197ff4c3SKornel Duleba return (0); 153*197ff4c3SKornel Duleba } 154