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