xref: /freebsd/sys/crypto/openssl/ossl_aes.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
1197ff4c3SKornel Duleba /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3197ff4c3SKornel Duleba  *
4197ff4c3SKornel Duleba  * Copyright (c) 2021 Stormshield.
5197ff4c3SKornel Duleba  * Copyright (c) 2021 Semihalf.
6197ff4c3SKornel Duleba  *
7197ff4c3SKornel Duleba  * Redistribution and use in source and binary forms, with or without
8197ff4c3SKornel Duleba  * modification, are permitted provided that the following conditions
9197ff4c3SKornel Duleba  * are met:
10197ff4c3SKornel Duleba  * 1. Redistributions of source code must retain the above copyright
11197ff4c3SKornel Duleba  *    notice, this list of conditions and the following disclaimer.
12197ff4c3SKornel Duleba  * 2. Redistributions in binary form must reproduce the above copyright
13197ff4c3SKornel Duleba  *    notice, this list of conditions and the following disclaimer in the
14197ff4c3SKornel Duleba  *    documentation and/or other materials provided with the distribution.
15197ff4c3SKornel Duleba  *
16197ff4c3SKornel Duleba  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17197ff4c3SKornel Duleba  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18197ff4c3SKornel Duleba  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19197ff4c3SKornel Duleba  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20197ff4c3SKornel Duleba  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21197ff4c3SKornel Duleba  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22197ff4c3SKornel Duleba  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23197ff4c3SKornel Duleba  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24197ff4c3SKornel Duleba  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25197ff4c3SKornel Duleba  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26197ff4c3SKornel Duleba  */
27197ff4c3SKornel Duleba 
28197ff4c3SKornel Duleba #include <sys/cdefs.h>
29197ff4c3SKornel Duleba __FBSDID("$FreeBSD$");
30197ff4c3SKornel Duleba 
31197ff4c3SKornel Duleba #include <sys/param.h>
32197ff4c3SKornel Duleba #include <sys/malloc.h>
33197ff4c3SKornel Duleba 
34197ff4c3SKornel Duleba #include <opencrypto/cryptodev.h>
35197ff4c3SKornel Duleba 
36197ff4c3SKornel Duleba #include <crypto/openssl/ossl.h>
37197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h>
38197ff4c3SKornel Duleba 
39197ff4c3SKornel Duleba #if defined(__amd64__) || defined(__i386__)
40197ff4c3SKornel Duleba #include <crypto/openssl/ossl_x86.h>
41197ff4c3SKornel Duleba #elif defined (__aarch64__)
42197ff4c3SKornel Duleba #include <crypto/openssl/ossl_aarch64.h>
43197ff4c3SKornel Duleba #endif
44197ff4c3SKornel Duleba 
45197ff4c3SKornel Duleba static ossl_cipher_process_t ossl_aes_cbc;
46197ff4c3SKornel Duleba 
47197ff4c3SKornel Duleba struct ossl_cipher ossl_cipher_aes_cbc = {
48197ff4c3SKornel Duleba 	.type = CRYPTO_AES_CBC,
49197ff4c3SKornel Duleba 	.blocksize = AES_BLOCK_LEN,
50197ff4c3SKornel Duleba 	.ivsize = AES_BLOCK_LEN,
51197ff4c3SKornel Duleba 
52197ff4c3SKornel Duleba 	/* Filled during initialization based on CPU caps. */
53197ff4c3SKornel Duleba 	.set_encrypt_key = NULL,
54197ff4c3SKornel Duleba 	.set_decrypt_key = NULL,
55197ff4c3SKornel Duleba 	.process = ossl_aes_cbc
56197ff4c3SKornel Duleba };
57197ff4c3SKornel Duleba 
58197ff4c3SKornel Duleba static int
59197ff4c3SKornel Duleba ossl_aes_cbc(struct ossl_session_cipher *s, struct cryptop *crp,
60197ff4c3SKornel Duleba     const struct crypto_session_params *csp)
61197ff4c3SKornel Duleba {
62197ff4c3SKornel Duleba 	struct crypto_buffer_cursor cc_in, cc_out;
63197ff4c3SKornel Duleba 	unsigned char block[EALG_MAX_BLOCK_LEN];
64197ff4c3SKornel Duleba 	unsigned char iv[EALG_MAX_BLOCK_LEN];
65197ff4c3SKornel Duleba 	const unsigned char *in, *inseg;
66197ff4c3SKornel Duleba 	unsigned char *out, *outseg;
67197ff4c3SKornel Duleba 	size_t plen, seglen, inlen, outlen;
68197ff4c3SKornel Duleba 	struct ossl_cipher_context key;
69197ff4c3SKornel Duleba 	struct ossl_cipher *cipher;
70197ff4c3SKornel Duleba 	int blocklen, error;
71197ff4c3SKornel Duleba 	bool encrypt;
72197ff4c3SKornel Duleba 
73197ff4c3SKornel Duleba 	cipher = s->cipher;
74197ff4c3SKornel Duleba 	encrypt = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
75197ff4c3SKornel Duleba 	plen = crp->crp_payload_length;
76197ff4c3SKornel Duleba 	blocklen = cipher->blocksize;
77197ff4c3SKornel Duleba 
78197ff4c3SKornel Duleba 	if (plen % blocklen)
79197ff4c3SKornel Duleba 		return (EINVAL);
80197ff4c3SKornel Duleba 
81197ff4c3SKornel Duleba 	if (crp->crp_cipher_key != NULL) {
82197ff4c3SKornel Duleba 		if (encrypt)
83197ff4c3SKornel Duleba 			error = cipher->set_encrypt_key(crp->crp_cipher_key,
84197ff4c3SKornel Duleba 			    8 * csp->csp_cipher_klen, &key);
85197ff4c3SKornel Duleba 		else
86197ff4c3SKornel Duleba 			error = cipher->set_decrypt_key(crp->crp_cipher_key,
87197ff4c3SKornel Duleba 			    8 * csp->csp_cipher_klen, &key);
88197ff4c3SKornel Duleba 		if (error)
89197ff4c3SKornel Duleba 			return (error);
90197ff4c3SKornel Duleba 	} else {
91197ff4c3SKornel Duleba 		if (encrypt)
92197ff4c3SKornel Duleba 			key = s->enc_ctx;
93197ff4c3SKornel Duleba 		else
94197ff4c3SKornel Duleba 			key = s->dec_ctx;
95197ff4c3SKornel Duleba 	}
96197ff4c3SKornel Duleba 
97197ff4c3SKornel Duleba 	crypto_read_iv(crp, iv);
98197ff4c3SKornel Duleba 
99197ff4c3SKornel Duleba 	/* Derived from ossl_chacha20.c */
100197ff4c3SKornel Duleba 	crypto_cursor_init(&cc_in, &crp->crp_buf);
101197ff4c3SKornel Duleba 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
102197ff4c3SKornel Duleba 	inseg = crypto_cursor_segment(&cc_in, &inlen);
103197ff4c3SKornel Duleba 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
104197ff4c3SKornel Duleba 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
105197ff4c3SKornel Duleba 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
106197ff4c3SKornel Duleba 	} else {
107197ff4c3SKornel Duleba 		cc_out = cc_in;
108197ff4c3SKornel Duleba 	}
109197ff4c3SKornel Duleba 	outseg = crypto_cursor_segment(&cc_out, &outlen);
110197ff4c3SKornel Duleba 
111197ff4c3SKornel Duleba 	while (plen >= blocklen) {
112197ff4c3SKornel Duleba 		if (inlen < blocklen) {
113197ff4c3SKornel Duleba 			crypto_cursor_copydata(&cc_in, blocklen, block);
114197ff4c3SKornel Duleba 			in = block;
115197ff4c3SKornel Duleba 			inlen = blocklen;
116197ff4c3SKornel Duleba 		} else {
117197ff4c3SKornel Duleba 			in = inseg;
118197ff4c3SKornel Duleba 		}
119197ff4c3SKornel Duleba 		if (outlen < blocklen) {
120197ff4c3SKornel Duleba 			out = block;
121197ff4c3SKornel Duleba 			outlen = blocklen;
122197ff4c3SKornel Duleba 		} else {
123197ff4c3SKornel Duleba 			out = outseg;
124197ff4c3SKornel Duleba 		}
125197ff4c3SKornel Duleba 
126197ff4c3SKornel Duleba 		/* Figure out how many blocks we can encrypt/decrypt at once. */
127197ff4c3SKornel Duleba 		seglen = rounddown(MIN(plen, MIN(inlen, outlen)), blocklen);
128197ff4c3SKornel Duleba 
129197ff4c3SKornel Duleba 		AES_CBC_ENCRYPT(in, out, seglen, &key, iv, encrypt);
130197ff4c3SKornel Duleba 
131197ff4c3SKornel Duleba 		if (out == block) {
132197ff4c3SKornel Duleba 			crypto_cursor_copyback(&cc_out, blocklen, block);
133197ff4c3SKornel Duleba 			outseg = crypto_cursor_segment(&cc_out, &outlen);
134197ff4c3SKornel Duleba 		} else {
135197ff4c3SKornel Duleba 			crypto_cursor_advance(&cc_out, seglen);
136197ff4c3SKornel Duleba 			outseg += seglen;
137197ff4c3SKornel Duleba 			outlen -= seglen;
138197ff4c3SKornel Duleba 		}
139197ff4c3SKornel Duleba 		if (in == block) {
140197ff4c3SKornel Duleba 			inseg = crypto_cursor_segment(&cc_in, &inlen);
141197ff4c3SKornel Duleba 		} else {
142197ff4c3SKornel Duleba 			crypto_cursor_advance(&cc_in, seglen);
143197ff4c3SKornel Duleba 			inseg += seglen;
144197ff4c3SKornel Duleba 			inlen -= seglen;
145197ff4c3SKornel Duleba 		}
146197ff4c3SKornel Duleba 		plen -= seglen;
147197ff4c3SKornel Duleba 	}
148197ff4c3SKornel Duleba 
149197ff4c3SKornel Duleba 	explicit_bzero(block, sizeof(block));
150197ff4c3SKornel Duleba 	explicit_bzero(iv, sizeof(iv));
151197ff4c3SKornel Duleba 	explicit_bzero(&key, sizeof(key));
152197ff4c3SKornel Duleba 	return (0);
153197ff4c3SKornel Duleba }
154