xref: /freebsd/sys/crypto/openssl/ossl_aes.c (revision 81ad6265)
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