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