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