1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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/param.h> 29 #include <sys/malloc.h> 30 31 #include <opencrypto/cryptodev.h> 32 #include <opencrypto/gmac.h> 33 34 #include <crypto/openssl/ossl.h> 35 #include <crypto/openssl/ossl_aes_gcm.h> 36 #include <crypto/openssl/ossl_cipher.h> 37 38 #if defined(__amd64__) || defined(__i386__) 39 #include <crypto/openssl/ossl_x86.h> 40 #elif defined (__aarch64__) 41 #include <crypto/openssl/ossl_aarch64.h> 42 #endif 43 44 static ossl_cipher_process_t ossl_aes_cbc; 45 static ossl_cipher_process_t ossl_aes_gcm; 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 struct ossl_cipher ossl_cipher_aes_gcm = { 59 .type = CRYPTO_AES_NIST_GCM_16, 60 .blocksize = 1, 61 .ivsize = AES_GCM_IV_LEN, 62 63 /* Filled during initialization based on CPU caps. */ 64 .set_encrypt_key = NULL, 65 .set_decrypt_key = NULL, 66 .process = ossl_aes_gcm, 67 }; 68 69 static int 70 ossl_aes_cbc(struct ossl_session_cipher *s, struct cryptop *crp, 71 const struct crypto_session_params *csp) 72 { 73 struct crypto_buffer_cursor cc_in, cc_out; 74 unsigned char block[EALG_MAX_BLOCK_LEN]; 75 unsigned char iv[EALG_MAX_BLOCK_LEN]; 76 const unsigned char *in, *inseg; 77 unsigned char *out, *outseg; 78 size_t plen, seglen, inlen, outlen; 79 struct ossl_cipher_context key; 80 struct ossl_cipher *cipher; 81 int blocklen, error; 82 bool encrypt; 83 84 cipher = s->cipher; 85 encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 86 plen = crp->crp_payload_length; 87 blocklen = cipher->blocksize; 88 89 if (plen % blocklen) 90 return (EINVAL); 91 92 if (crp->crp_cipher_key != NULL) { 93 if (encrypt) 94 error = cipher->set_encrypt_key(crp->crp_cipher_key, 95 8 * csp->csp_cipher_klen, &key); 96 else 97 error = cipher->set_decrypt_key(crp->crp_cipher_key, 98 8 * csp->csp_cipher_klen, &key); 99 if (error) 100 return (error); 101 } else { 102 if (encrypt) 103 key = s->enc_ctx; 104 else 105 key = s->dec_ctx; 106 } 107 108 crypto_read_iv(crp, iv); 109 110 /* Derived from ossl_chacha20.c */ 111 crypto_cursor_init(&cc_in, &crp->crp_buf); 112 crypto_cursor_advance(&cc_in, crp->crp_payload_start); 113 inseg = crypto_cursor_segment(&cc_in, &inlen); 114 if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 115 crypto_cursor_init(&cc_out, &crp->crp_obuf); 116 crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 117 } else { 118 cc_out = cc_in; 119 } 120 outseg = crypto_cursor_segment(&cc_out, &outlen); 121 122 while (plen >= blocklen) { 123 if (inlen < blocklen) { 124 crypto_cursor_copydata(&cc_in, blocklen, block); 125 in = block; 126 inlen = blocklen; 127 } else { 128 in = inseg; 129 } 130 if (outlen < blocklen) { 131 out = block; 132 outlen = blocklen; 133 } else { 134 out = outseg; 135 } 136 137 /* Figure out how many blocks we can encrypt/decrypt at once. */ 138 seglen = rounddown(MIN(plen, MIN(inlen, outlen)), blocklen); 139 140 AES_CBC_ENCRYPT(in, out, seglen, &key, iv, encrypt); 141 142 if (out == block) { 143 crypto_cursor_copyback(&cc_out, blocklen, block); 144 outseg = crypto_cursor_segment(&cc_out, &outlen); 145 } else { 146 crypto_cursor_advance(&cc_out, seglen); 147 outseg += seglen; 148 outlen -= seglen; 149 } 150 if (in == block) { 151 inseg = crypto_cursor_segment(&cc_in, &inlen); 152 } else { 153 crypto_cursor_advance(&cc_in, seglen); 154 inseg += seglen; 155 inlen -= seglen; 156 } 157 plen -= seglen; 158 } 159 160 explicit_bzero(block, sizeof(block)); 161 explicit_bzero(iv, sizeof(iv)); 162 explicit_bzero(&key, sizeof(key)); 163 return (0); 164 } 165 166 static int 167 ossl_aes_gcm(struct ossl_session_cipher *s, struct cryptop *crp, 168 const struct crypto_session_params *csp) 169 { 170 struct ossl_gcm_context ctx; 171 struct crypto_buffer_cursor cc_in, cc_out; 172 unsigned char iv[AES_BLOCK_LEN], tag[AES_BLOCK_LEN]; 173 const unsigned char *inseg; 174 unsigned char *outseg; 175 size_t inlen, outlen, seglen; 176 int error; 177 bool encrypt; 178 179 encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 180 181 if (crp->crp_cipher_key != NULL) { 182 if (encrypt) 183 error = s->cipher->set_encrypt_key(crp->crp_cipher_key, 184 8 * csp->csp_cipher_klen, 185 (struct ossl_cipher_context *)&ctx); 186 else 187 error = s->cipher->set_decrypt_key(crp->crp_cipher_key, 188 8 * csp->csp_cipher_klen, 189 (struct ossl_cipher_context *)&ctx); 190 if (error) 191 return (error); 192 } else if (encrypt) { 193 memcpy(&ctx, &s->enc_ctx, sizeof(struct ossl_gcm_context)); 194 } else { 195 memcpy(&ctx, &s->dec_ctx, sizeof(struct ossl_gcm_context)); 196 } 197 198 crypto_read_iv(crp, iv); 199 ctx.ops->setiv(&ctx, iv, csp->csp_ivlen); 200 201 if (crp->crp_aad != NULL) { 202 if (ctx.ops->aad(&ctx, crp->crp_aad, crp->crp_aad_length) != 0) 203 return (EINVAL); 204 } else { 205 crypto_cursor_init(&cc_in, &crp->crp_buf); 206 crypto_cursor_advance(&cc_in, crp->crp_aad_start); 207 for (size_t alen = crp->crp_aad_length; alen > 0; 208 alen -= seglen) { 209 inseg = crypto_cursor_segment(&cc_in, &inlen); 210 seglen = MIN(alen, inlen); 211 if (ctx.ops->aad(&ctx, inseg, seglen) != 0) 212 return (EINVAL); 213 crypto_cursor_advance(&cc_in, seglen); 214 } 215 } 216 217 crypto_cursor_init(&cc_in, &crp->crp_buf); 218 crypto_cursor_advance(&cc_in, crp->crp_payload_start); 219 if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 220 crypto_cursor_init(&cc_out, &crp->crp_obuf); 221 crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 222 } else { 223 cc_out = cc_in; 224 } 225 226 for (size_t plen = crp->crp_payload_length; plen > 0; plen -= seglen) { 227 inseg = crypto_cursor_segment(&cc_in, &inlen); 228 outseg = crypto_cursor_segment(&cc_out, &outlen); 229 seglen = MIN(plen, MIN(inlen, outlen)); 230 231 if (encrypt) { 232 if (ctx.ops->encrypt(&ctx, inseg, outseg, seglen) != 0) 233 return (EINVAL); 234 } else { 235 if (ctx.ops->decrypt(&ctx, inseg, outseg, seglen) != 0) 236 return (EINVAL); 237 } 238 239 crypto_cursor_advance(&cc_in, seglen); 240 crypto_cursor_advance(&cc_out, seglen); 241 } 242 243 error = 0; 244 if (encrypt) { 245 ctx.ops->tag(&ctx, tag, GMAC_DIGEST_LEN); 246 crypto_copyback(crp, crp->crp_digest_start, GMAC_DIGEST_LEN, 247 tag); 248 } else { 249 crypto_copydata(crp, crp->crp_digest_start, GMAC_DIGEST_LEN, 250 tag); 251 if (ctx.ops->finish(&ctx, tag, GMAC_DIGEST_LEN) != 0) 252 error = EBADMSG; 253 } 254 255 explicit_bzero(iv, sizeof(iv)); 256 explicit_bzero(tag, sizeof(tag)); 257 explicit_bzero(&ctx, sizeof(ctx)); 258 259 return (error); 260 } 261