xref: /freebsd/sys/contrib/openzfs/module/icp/io/aes.c (revision aca928a50a42f00f344df934005b09dbcb4e2f77)
1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23eda14cbcSMatt Macy  */
24eda14cbcSMatt Macy 
25eda14cbcSMatt Macy /*
26eda14cbcSMatt Macy  * AES provider for the Kernel Cryptographic Framework (KCF)
27eda14cbcSMatt Macy  */
28eda14cbcSMatt Macy 
29eda14cbcSMatt Macy #include <sys/zfs_context.h>
30eda14cbcSMatt Macy #include <sys/crypto/common.h>
31eda14cbcSMatt Macy #include <sys/crypto/impl.h>
32eda14cbcSMatt Macy #include <sys/crypto/spi.h>
33eda14cbcSMatt Macy #include <sys/crypto/icp.h>
34eda14cbcSMatt Macy #include <modes/modes.h>
35eda14cbcSMatt Macy #define	_AES_IMPL
36eda14cbcSMatt Macy #include <aes/aes_impl.h>
37eda14cbcSMatt Macy #include <modes/gcm_impl.h>
38eda14cbcSMatt Macy 
39eda14cbcSMatt Macy /*
40eda14cbcSMatt Macy  * Mechanism info structure passed to KCF during registration.
41eda14cbcSMatt Macy  */
42e92ffd9bSMartin Matuska static const crypto_mech_info_t aes_mech_info_tab[] = {
43eda14cbcSMatt Macy 	/* AES_ECB */
44eda14cbcSMatt Macy 	{SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
45eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
46c03c5b1cSMartin Matuska 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
47eda14cbcSMatt Macy 	/* AES_CBC */
48eda14cbcSMatt Macy 	{SUN_CKM_AES_CBC, AES_CBC_MECH_INFO_TYPE,
49eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
50c03c5b1cSMartin Matuska 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
51eda14cbcSMatt Macy 	/* AES_CTR */
52eda14cbcSMatt Macy 	{SUN_CKM_AES_CTR, AES_CTR_MECH_INFO_TYPE,
53eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
54c03c5b1cSMartin Matuska 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
55eda14cbcSMatt Macy 	/* AES_CCM */
56eda14cbcSMatt Macy 	{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
57eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
58c03c5b1cSMartin Matuska 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
59eda14cbcSMatt Macy 	/* AES_GCM */
60eda14cbcSMatt Macy 	{SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
61eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
62c03c5b1cSMartin Matuska 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
63eda14cbcSMatt Macy 	/* AES_GMAC */
64eda14cbcSMatt Macy 	{SUN_CKM_AES_GMAC, AES_GMAC_MECH_INFO_TYPE,
65eda14cbcSMatt Macy 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
66eda14cbcSMatt Macy 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
67c03c5b1cSMartin Matuska 	    CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
68eda14cbcSMatt Macy };
69eda14cbcSMatt Macy 
70eda14cbcSMatt Macy static int aes_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
71c03c5b1cSMartin Matuska     crypto_key_t *, crypto_spi_ctx_template_t);
72eda14cbcSMatt Macy static int aes_decrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
73c03c5b1cSMartin Matuska     crypto_key_t *, crypto_spi_ctx_template_t);
74eda14cbcSMatt Macy static int aes_common_init(crypto_ctx_t *, crypto_mechanism_t *,
75c03c5b1cSMartin Matuska     crypto_key_t *, crypto_spi_ctx_template_t, boolean_t);
76eda14cbcSMatt Macy static int aes_common_init_ctx(aes_ctx_t *, crypto_spi_ctx_template_t *,
77eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, int, boolean_t);
78c03c5b1cSMartin Matuska static int aes_encrypt_final(crypto_ctx_t *, crypto_data_t *);
79c03c5b1cSMartin Matuska static int aes_decrypt_final(crypto_ctx_t *, crypto_data_t *);
80eda14cbcSMatt Macy 
81c03c5b1cSMartin Matuska static int aes_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *);
82eda14cbcSMatt Macy static int aes_encrypt_update(crypto_ctx_t *, crypto_data_t *,
83c03c5b1cSMartin Matuska     crypto_data_t *);
84c03c5b1cSMartin Matuska static int aes_encrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
85c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
86eda14cbcSMatt Macy 
87c03c5b1cSMartin Matuska static int aes_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *);
88eda14cbcSMatt Macy static int aes_decrypt_update(crypto_ctx_t *, crypto_data_t *,
89c03c5b1cSMartin Matuska     crypto_data_t *);
90c03c5b1cSMartin Matuska static int aes_decrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
91c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
92eda14cbcSMatt Macy 
93e92ffd9bSMartin Matuska static const crypto_cipher_ops_t aes_cipher_ops = {
94eda14cbcSMatt Macy 	.encrypt_init = aes_encrypt_init,
95eda14cbcSMatt Macy 	.encrypt = aes_encrypt,
96eda14cbcSMatt Macy 	.encrypt_update = aes_encrypt_update,
97eda14cbcSMatt Macy 	.encrypt_final = aes_encrypt_final,
98eda14cbcSMatt Macy 	.encrypt_atomic = aes_encrypt_atomic,
99eda14cbcSMatt Macy 	.decrypt_init = aes_decrypt_init,
100eda14cbcSMatt Macy 	.decrypt = aes_decrypt,
101eda14cbcSMatt Macy 	.decrypt_update = aes_decrypt_update,
102eda14cbcSMatt Macy 	.decrypt_final = aes_decrypt_final,
103eda14cbcSMatt Macy 	.decrypt_atomic = aes_decrypt_atomic
104eda14cbcSMatt Macy };
105eda14cbcSMatt Macy 
106c03c5b1cSMartin Matuska static int aes_mac_atomic(crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
107c03c5b1cSMartin Matuska     crypto_data_t *, crypto_spi_ctx_template_t);
108c03c5b1cSMartin Matuska static int aes_mac_verify_atomic(crypto_mechanism_t *, crypto_key_t *,
109c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
110eda14cbcSMatt Macy 
111e92ffd9bSMartin Matuska static const crypto_mac_ops_t aes_mac_ops = {
112eda14cbcSMatt Macy 	.mac_init = NULL,
113eda14cbcSMatt Macy 	.mac = NULL,
114eda14cbcSMatt Macy 	.mac_update = NULL,
115eda14cbcSMatt Macy 	.mac_final = NULL,
116eda14cbcSMatt Macy 	.mac_atomic = aes_mac_atomic,
117eda14cbcSMatt Macy 	.mac_verify_atomic = aes_mac_verify_atomic
118eda14cbcSMatt Macy };
119eda14cbcSMatt Macy 
120c03c5b1cSMartin Matuska static int aes_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
121c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *, size_t *);
122eda14cbcSMatt Macy static int aes_free_context(crypto_ctx_t *);
123eda14cbcSMatt Macy 
124e92ffd9bSMartin Matuska static const crypto_ctx_ops_t aes_ctx_ops = {
125eda14cbcSMatt Macy 	.create_ctx_template = aes_create_ctx_template,
126eda14cbcSMatt Macy 	.free_context = aes_free_context
127eda14cbcSMatt Macy };
128eda14cbcSMatt Macy 
129c03c5b1cSMartin Matuska static const crypto_ops_t aes_crypto_ops = {
130eda14cbcSMatt Macy 	NULL,
131eda14cbcSMatt Macy 	&aes_cipher_ops,
132eda14cbcSMatt Macy 	&aes_mac_ops,
133c03c5b1cSMartin Matuska 	&aes_ctx_ops,
134c03c5b1cSMartin Matuska };
135eda14cbcSMatt Macy 
136c03c5b1cSMartin Matuska static const crypto_provider_info_t aes_prov_info = {
137eda14cbcSMatt Macy 	"AES Software Provider",
138eda14cbcSMatt Macy 	&aes_crypto_ops,
139eda14cbcSMatt Macy 	sizeof (aes_mech_info_tab) / sizeof (crypto_mech_info_t),
140eda14cbcSMatt Macy 	aes_mech_info_tab
141c03c5b1cSMartin Matuska };
142eda14cbcSMatt Macy 
143eda14cbcSMatt Macy static crypto_kcf_provider_handle_t aes_prov_handle = 0;
144eda14cbcSMatt Macy static crypto_data_t null_crypto_data = { CRYPTO_DATA_RAW };
145eda14cbcSMatt Macy 
146eda14cbcSMatt Macy int
147eda14cbcSMatt Macy aes_mod_init(void)
148eda14cbcSMatt Macy {
149eda14cbcSMatt Macy 	/* Determine the fastest available implementation. */
150eda14cbcSMatt Macy 	aes_impl_init();
151eda14cbcSMatt Macy 	gcm_impl_init();
152eda14cbcSMatt Macy 
153eda14cbcSMatt Macy 	/* Register with KCF.  If the registration fails, remove the module. */
154e92ffd9bSMartin Matuska 	if (crypto_register_provider(&aes_prov_info, &aes_prov_handle))
155eda14cbcSMatt Macy 		return (EACCES);
156eda14cbcSMatt Macy 
157eda14cbcSMatt Macy 	return (0);
158eda14cbcSMatt Macy }
159eda14cbcSMatt Macy 
160eda14cbcSMatt Macy int
161eda14cbcSMatt Macy aes_mod_fini(void)
162eda14cbcSMatt Macy {
163eda14cbcSMatt Macy 	/* Unregister from KCF if module is registered */
164eda14cbcSMatt Macy 	if (aes_prov_handle != 0) {
165eda14cbcSMatt Macy 		if (crypto_unregister_provider(aes_prov_handle))
166eda14cbcSMatt Macy 			return (EBUSY);
167eda14cbcSMatt Macy 
168eda14cbcSMatt Macy 		aes_prov_handle = 0;
169eda14cbcSMatt Macy 	}
170eda14cbcSMatt Macy 
171e92ffd9bSMartin Matuska 	return (0);
172eda14cbcSMatt Macy }
173eda14cbcSMatt Macy 
174eda14cbcSMatt Macy static int
175c03c5b1cSMartin Matuska aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
176eda14cbcSMatt Macy {
177eda14cbcSMatt Macy 	void *p = NULL;
178eda14cbcSMatt Macy 	boolean_t param_required = B_TRUE;
179eda14cbcSMatt Macy 	size_t param_len;
180eda14cbcSMatt Macy 	void *(*alloc_fun)(int);
181eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
182eda14cbcSMatt Macy 
183eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
184eda14cbcSMatt Macy 	case AES_ECB_MECH_INFO_TYPE:
185eda14cbcSMatt Macy 		param_required = B_FALSE;
186eda14cbcSMatt Macy 		alloc_fun = ecb_alloc_ctx;
187eda14cbcSMatt Macy 		break;
188eda14cbcSMatt Macy 	case AES_CBC_MECH_INFO_TYPE:
189eda14cbcSMatt Macy 		param_len = AES_BLOCK_LEN;
190eda14cbcSMatt Macy 		alloc_fun = cbc_alloc_ctx;
191eda14cbcSMatt Macy 		break;
192eda14cbcSMatt Macy 	case AES_CTR_MECH_INFO_TYPE:
193eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_CTR_PARAMS);
194eda14cbcSMatt Macy 		alloc_fun = ctr_alloc_ctx;
195eda14cbcSMatt Macy 		break;
196eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
197eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_CCM_PARAMS);
198eda14cbcSMatt Macy 		alloc_fun = ccm_alloc_ctx;
199eda14cbcSMatt Macy 		break;
200eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
201eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_GCM_PARAMS);
202eda14cbcSMatt Macy 		alloc_fun = gcm_alloc_ctx;
203eda14cbcSMatt Macy 		break;
204eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
205eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_GMAC_PARAMS);
206eda14cbcSMatt Macy 		alloc_fun = gmac_alloc_ctx;
207eda14cbcSMatt Macy 		break;
208eda14cbcSMatt Macy 	default:
209eda14cbcSMatt Macy 		rv = CRYPTO_MECHANISM_INVALID;
210eda14cbcSMatt Macy 		return (rv);
211eda14cbcSMatt Macy 	}
212eda14cbcSMatt Macy 	if (param_required && mechanism->cm_param != NULL &&
213eda14cbcSMatt Macy 	    mechanism->cm_param_len != param_len) {
214eda14cbcSMatt Macy 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
215eda14cbcSMatt Macy 	}
216eda14cbcSMatt Macy 	if (ctx != NULL) {
217c03c5b1cSMartin Matuska 		p = (alloc_fun)(KM_SLEEP);
218eda14cbcSMatt Macy 		*ctx = p;
219eda14cbcSMatt Macy 	}
220eda14cbcSMatt Macy 	return (rv);
221eda14cbcSMatt Macy }
222eda14cbcSMatt Macy 
223eda14cbcSMatt Macy /*
224eda14cbcSMatt Macy  * Initialize key schedules for AES
225eda14cbcSMatt Macy  */
226eda14cbcSMatt Macy static int
227eda14cbcSMatt Macy init_keysched(crypto_key_t *key, void *newbie)
228eda14cbcSMatt Macy {
229eda14cbcSMatt Macy 	if (key->ck_length < AES_MINBITS ||
230eda14cbcSMatt Macy 	    key->ck_length > AES_MAXBITS) {
231eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
232eda14cbcSMatt Macy 	}
233eda14cbcSMatt Macy 
234eda14cbcSMatt Macy 	/* key length must be either 128, 192, or 256 */
235eda14cbcSMatt Macy 	if ((key->ck_length & 63) != 0)
236eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
237eda14cbcSMatt Macy 
238eda14cbcSMatt Macy 	aes_init_keysched(key->ck_data, key->ck_length, newbie);
239eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
240eda14cbcSMatt Macy }
241eda14cbcSMatt Macy 
242eda14cbcSMatt Macy static int
243eda14cbcSMatt Macy aes_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
244c03c5b1cSMartin Matuska     crypto_key_t *key, crypto_spi_ctx_template_t template)
245eda14cbcSMatt Macy {
246c03c5b1cSMartin Matuska 	return (aes_common_init(ctx, mechanism, key, template, B_TRUE));
247eda14cbcSMatt Macy }
248eda14cbcSMatt Macy 
249eda14cbcSMatt Macy static int
250eda14cbcSMatt Macy aes_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
251c03c5b1cSMartin Matuska     crypto_key_t *key, crypto_spi_ctx_template_t template)
252eda14cbcSMatt Macy {
253c03c5b1cSMartin Matuska 	return (aes_common_init(ctx, mechanism, key, template, B_FALSE));
254eda14cbcSMatt Macy }
255eda14cbcSMatt Macy 
256eda14cbcSMatt Macy 
257eda14cbcSMatt Macy 
258eda14cbcSMatt Macy /*
259eda14cbcSMatt Macy  * KCF software provider encrypt entry points.
260eda14cbcSMatt Macy  */
261eda14cbcSMatt Macy static int
262eda14cbcSMatt Macy aes_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
263eda14cbcSMatt Macy     crypto_key_t *key, crypto_spi_ctx_template_t template,
264c03c5b1cSMartin Matuska     boolean_t is_encrypt_init)
265eda14cbcSMatt Macy {
266eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
267eda14cbcSMatt Macy 	int rv;
268eda14cbcSMatt Macy 
269c03c5b1cSMartin Matuska 	if ((rv = aes_check_mech_param(mechanism, &aes_ctx))
270eda14cbcSMatt Macy 	    != CRYPTO_SUCCESS)
271eda14cbcSMatt Macy 		return (rv);
272eda14cbcSMatt Macy 
273c03c5b1cSMartin Matuska 	rv = aes_common_init_ctx(aes_ctx, template, mechanism, key, KM_SLEEP,
274eda14cbcSMatt Macy 	    is_encrypt_init);
275eda14cbcSMatt Macy 	if (rv != CRYPTO_SUCCESS) {
276eda14cbcSMatt Macy 		crypto_free_mode_ctx(aes_ctx);
277eda14cbcSMatt Macy 		return (rv);
278eda14cbcSMatt Macy 	}
279eda14cbcSMatt Macy 
280eda14cbcSMatt Macy 	ctx->cc_provider_private = aes_ctx;
281eda14cbcSMatt Macy 
282eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
283eda14cbcSMatt Macy }
284eda14cbcSMatt Macy 
285eda14cbcSMatt Macy static void
286eda14cbcSMatt Macy aes_copy_block64(uint8_t *in, uint64_t *out)
287eda14cbcSMatt Macy {
288eda14cbcSMatt Macy 	if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
289eda14cbcSMatt Macy 		/* LINTED: pointer alignment */
290eda14cbcSMatt Macy 		out[0] = *(uint64_t *)&in[0];
291eda14cbcSMatt Macy 		/* LINTED: pointer alignment */
292eda14cbcSMatt Macy 		out[1] = *(uint64_t *)&in[8];
293eda14cbcSMatt Macy 	} else {
294eda14cbcSMatt Macy 		uint8_t *iv8 = (uint8_t *)&out[0];
295eda14cbcSMatt Macy 
296eda14cbcSMatt Macy 		AES_COPY_BLOCK(in, iv8);
297eda14cbcSMatt Macy 	}
298eda14cbcSMatt Macy }
299eda14cbcSMatt Macy 
300eda14cbcSMatt Macy 
301eda14cbcSMatt Macy static int
302eda14cbcSMatt Macy aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
303c03c5b1cSMartin Matuska     crypto_data_t *ciphertext)
304eda14cbcSMatt Macy {
305eda14cbcSMatt Macy 	int ret = CRYPTO_FAILED;
306eda14cbcSMatt Macy 
307eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
308eda14cbcSMatt Macy 	size_t saved_length, saved_offset, length_needed;
309eda14cbcSMatt Macy 
310eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
311eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
312eda14cbcSMatt Macy 
313eda14cbcSMatt Macy 	/*
314eda14cbcSMatt Macy 	 * For block ciphers, plaintext must be a multiple of AES block size.
315eda14cbcSMatt Macy 	 * This test is only valid for ciphers whose blocksize is a power of 2.
316eda14cbcSMatt Macy 	 */
317eda14cbcSMatt Macy 	if (((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE))
318eda14cbcSMatt Macy 	    == 0) && (plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
319eda14cbcSMatt Macy 		return (CRYPTO_DATA_LEN_RANGE);
320eda14cbcSMatt Macy 
321eda14cbcSMatt Macy 	ASSERT(ciphertext != NULL);
322eda14cbcSMatt Macy 
323eda14cbcSMatt Macy 	/*
324eda14cbcSMatt Macy 	 * We need to just return the length needed to store the output.
325eda14cbcSMatt Macy 	 * We should not destroy the context for the following case.
326eda14cbcSMatt Macy 	 */
327eda14cbcSMatt Macy 	switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
328eda14cbcSMatt Macy 	case CCM_MODE:
329eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx->ac_mac_len;
330eda14cbcSMatt Macy 		break;
331eda14cbcSMatt Macy 	case GCM_MODE:
332eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx->ac_tag_len;
333eda14cbcSMatt Macy 		break;
334eda14cbcSMatt Macy 	case GMAC_MODE:
335eda14cbcSMatt Macy 		if (plaintext->cd_length != 0)
336eda14cbcSMatt Macy 			return (CRYPTO_ARGUMENTS_BAD);
337eda14cbcSMatt Macy 
338eda14cbcSMatt Macy 		length_needed = aes_ctx->ac_tag_len;
339eda14cbcSMatt Macy 		break;
340eda14cbcSMatt Macy 	default:
341eda14cbcSMatt Macy 		length_needed = plaintext->cd_length;
342eda14cbcSMatt Macy 	}
343eda14cbcSMatt Macy 
344eda14cbcSMatt Macy 	if (ciphertext->cd_length < length_needed) {
345eda14cbcSMatt Macy 		ciphertext->cd_length = length_needed;
346eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
347eda14cbcSMatt Macy 	}
348eda14cbcSMatt Macy 
349eda14cbcSMatt Macy 	saved_length = ciphertext->cd_length;
350eda14cbcSMatt Macy 	saved_offset = ciphertext->cd_offset;
351eda14cbcSMatt Macy 
352eda14cbcSMatt Macy 	/*
353eda14cbcSMatt Macy 	 * Do an update on the specified input data.
354eda14cbcSMatt Macy 	 */
355c03c5b1cSMartin Matuska 	ret = aes_encrypt_update(ctx, plaintext, ciphertext);
356eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS) {
357eda14cbcSMatt Macy 		return (ret);
358eda14cbcSMatt Macy 	}
359eda14cbcSMatt Macy 
360eda14cbcSMatt Macy 	/*
361eda14cbcSMatt Macy 	 * For CCM mode, aes_ccm_encrypt_final() will take care of any
362eda14cbcSMatt Macy 	 * left-over unprocessed data, and compute the MAC
363eda14cbcSMatt Macy 	 */
364eda14cbcSMatt Macy 	if (aes_ctx->ac_flags & CCM_MODE) {
365eda14cbcSMatt Macy 		/*
366eda14cbcSMatt Macy 		 * ccm_encrypt_final() will compute the MAC and append
367eda14cbcSMatt Macy 		 * it to existing ciphertext. So, need to adjust the left over
368eda14cbcSMatt Macy 		 * length value accordingly
369eda14cbcSMatt Macy 		 */
370eda14cbcSMatt Macy 
371eda14cbcSMatt Macy 		/* order of following 2 lines MUST not be reversed */
372eda14cbcSMatt Macy 		ciphertext->cd_offset = ciphertext->cd_length;
373eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length - ciphertext->cd_length;
374eda14cbcSMatt Macy 		ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, ciphertext,
375eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
376eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
377eda14cbcSMatt Macy 			return (ret);
378eda14cbcSMatt Macy 		}
379eda14cbcSMatt Macy 
380eda14cbcSMatt Macy 		if (plaintext != ciphertext) {
381eda14cbcSMatt Macy 			ciphertext->cd_length =
382eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
383eda14cbcSMatt Macy 		}
384eda14cbcSMatt Macy 		ciphertext->cd_offset = saved_offset;
385eda14cbcSMatt Macy 	} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
386eda14cbcSMatt Macy 		/*
387eda14cbcSMatt Macy 		 * gcm_encrypt_final() will compute the MAC and append
388eda14cbcSMatt Macy 		 * it to existing ciphertext. So, need to adjust the left over
389eda14cbcSMatt Macy 		 * length value accordingly
390eda14cbcSMatt Macy 		 */
391eda14cbcSMatt Macy 
392eda14cbcSMatt Macy 		/* order of following 2 lines MUST not be reversed */
393eda14cbcSMatt Macy 		ciphertext->cd_offset = ciphertext->cd_length;
394eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length - ciphertext->cd_length;
395eda14cbcSMatt Macy 		ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, ciphertext,
396eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
397eda14cbcSMatt Macy 		    aes_xor_block);
398eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
399eda14cbcSMatt Macy 			return (ret);
400eda14cbcSMatt Macy 		}
401eda14cbcSMatt Macy 
402eda14cbcSMatt Macy 		if (plaintext != ciphertext) {
403eda14cbcSMatt Macy 			ciphertext->cd_length =
404eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
405eda14cbcSMatt Macy 		}
406eda14cbcSMatt Macy 		ciphertext->cd_offset = saved_offset;
407eda14cbcSMatt Macy 	}
408eda14cbcSMatt Macy 
409eda14cbcSMatt Macy 	ASSERT(aes_ctx->ac_remainder_len == 0);
410eda14cbcSMatt Macy 	(void) aes_free_context(ctx);
411eda14cbcSMatt Macy 
412eda14cbcSMatt Macy 	return (ret);
413eda14cbcSMatt Macy }
414eda14cbcSMatt Macy 
415eda14cbcSMatt Macy 
416eda14cbcSMatt Macy static int
417eda14cbcSMatt Macy aes_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
418c03c5b1cSMartin Matuska     crypto_data_t *plaintext)
419eda14cbcSMatt Macy {
420eda14cbcSMatt Macy 	int ret = CRYPTO_FAILED;
421eda14cbcSMatt Macy 
422eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
423eda14cbcSMatt Macy 	off_t saved_offset;
424eda14cbcSMatt Macy 	size_t saved_length, length_needed;
425eda14cbcSMatt Macy 
426eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
427eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
428eda14cbcSMatt Macy 
429eda14cbcSMatt Macy 	/*
430eda14cbcSMatt Macy 	 * For block ciphers, plaintext must be a multiple of AES block size.
431eda14cbcSMatt Macy 	 * This test is only valid for ciphers whose blocksize is a power of 2.
432eda14cbcSMatt Macy 	 */
433eda14cbcSMatt Macy 	if (((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE))
434eda14cbcSMatt Macy 	    == 0) && (ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0) {
435eda14cbcSMatt Macy 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
436eda14cbcSMatt Macy 	}
437eda14cbcSMatt Macy 
438eda14cbcSMatt Macy 	ASSERT(plaintext != NULL);
439eda14cbcSMatt Macy 
440eda14cbcSMatt Macy 	/*
441eda14cbcSMatt Macy 	 * Return length needed to store the output.
442eda14cbcSMatt Macy 	 * Do not destroy context when plaintext buffer is too small.
443eda14cbcSMatt Macy 	 *
444eda14cbcSMatt Macy 	 * CCM:  plaintext is MAC len smaller than cipher text
445eda14cbcSMatt Macy 	 * GCM:  plaintext is TAG len smaller than cipher text
446eda14cbcSMatt Macy 	 * GMAC: plaintext length must be zero
447eda14cbcSMatt Macy 	 */
448eda14cbcSMatt Macy 	switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
449eda14cbcSMatt Macy 	case CCM_MODE:
450eda14cbcSMatt Macy 		length_needed = aes_ctx->ac_processed_data_len;
451eda14cbcSMatt Macy 		break;
452eda14cbcSMatt Macy 	case GCM_MODE:
453eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length - aes_ctx->ac_tag_len;
454eda14cbcSMatt Macy 		break;
455eda14cbcSMatt Macy 	case GMAC_MODE:
456eda14cbcSMatt Macy 		if (plaintext->cd_length != 0)
457eda14cbcSMatt Macy 			return (CRYPTO_ARGUMENTS_BAD);
458eda14cbcSMatt Macy 
459eda14cbcSMatt Macy 		length_needed = 0;
460eda14cbcSMatt Macy 		break;
461eda14cbcSMatt Macy 	default:
462eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length;
463eda14cbcSMatt Macy 	}
464eda14cbcSMatt Macy 
465eda14cbcSMatt Macy 	if (plaintext->cd_length < length_needed) {
466eda14cbcSMatt Macy 		plaintext->cd_length = length_needed;
467eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
468eda14cbcSMatt Macy 	}
469eda14cbcSMatt Macy 
470eda14cbcSMatt Macy 	saved_offset = plaintext->cd_offset;
471eda14cbcSMatt Macy 	saved_length = plaintext->cd_length;
472eda14cbcSMatt Macy 
473eda14cbcSMatt Macy 	/*
474eda14cbcSMatt Macy 	 * Do an update on the specified input data.
475eda14cbcSMatt Macy 	 */
476c03c5b1cSMartin Matuska 	ret = aes_decrypt_update(ctx, ciphertext, plaintext);
477eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS) {
478eda14cbcSMatt Macy 		goto cleanup;
479eda14cbcSMatt Macy 	}
480eda14cbcSMatt Macy 
481eda14cbcSMatt Macy 	if (aes_ctx->ac_flags & CCM_MODE) {
482eda14cbcSMatt Macy 		ASSERT(aes_ctx->ac_processed_data_len == aes_ctx->ac_data_len);
483eda14cbcSMatt Macy 		ASSERT(aes_ctx->ac_processed_mac_len == aes_ctx->ac_mac_len);
484eda14cbcSMatt Macy 
485eda14cbcSMatt Macy 		/* order of following 2 lines MUST not be reversed */
486eda14cbcSMatt Macy 		plaintext->cd_offset = plaintext->cd_length;
487eda14cbcSMatt Macy 		plaintext->cd_length = saved_length - plaintext->cd_length;
488eda14cbcSMatt Macy 
489eda14cbcSMatt Macy 		ret = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, plaintext,
490eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
491eda14cbcSMatt Macy 		    aes_xor_block);
492eda14cbcSMatt Macy 		if (ret == CRYPTO_SUCCESS) {
493eda14cbcSMatt Macy 			if (plaintext != ciphertext) {
494eda14cbcSMatt Macy 				plaintext->cd_length =
495eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
496eda14cbcSMatt Macy 			}
497eda14cbcSMatt Macy 		} else {
498eda14cbcSMatt Macy 			plaintext->cd_length = saved_length;
499eda14cbcSMatt Macy 		}
500eda14cbcSMatt Macy 
501eda14cbcSMatt Macy 		plaintext->cd_offset = saved_offset;
502eda14cbcSMatt Macy 	} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
503eda14cbcSMatt Macy 		/* order of following 2 lines MUST not be reversed */
504eda14cbcSMatt Macy 		plaintext->cd_offset = plaintext->cd_length;
505eda14cbcSMatt Macy 		plaintext->cd_length = saved_length - plaintext->cd_length;
506eda14cbcSMatt Macy 
507eda14cbcSMatt Macy 		ret = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, plaintext,
508eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
509eda14cbcSMatt Macy 		if (ret == CRYPTO_SUCCESS) {
510eda14cbcSMatt Macy 			if (plaintext != ciphertext) {
511eda14cbcSMatt Macy 				plaintext->cd_length =
512eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
513eda14cbcSMatt Macy 			}
514eda14cbcSMatt Macy 		} else {
515eda14cbcSMatt Macy 			plaintext->cd_length = saved_length;
516eda14cbcSMatt Macy 		}
517eda14cbcSMatt Macy 
518eda14cbcSMatt Macy 		plaintext->cd_offset = saved_offset;
519eda14cbcSMatt Macy 	}
520eda14cbcSMatt Macy 
521eda14cbcSMatt Macy 	ASSERT(aes_ctx->ac_remainder_len == 0);
522eda14cbcSMatt Macy 
523eda14cbcSMatt Macy cleanup:
524eda14cbcSMatt Macy 	(void) aes_free_context(ctx);
525eda14cbcSMatt Macy 
526eda14cbcSMatt Macy 	return (ret);
527eda14cbcSMatt Macy }
528eda14cbcSMatt Macy 
529eda14cbcSMatt Macy 
530eda14cbcSMatt Macy static int
531eda14cbcSMatt Macy aes_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
532c03c5b1cSMartin Matuska     crypto_data_t *ciphertext)
533eda14cbcSMatt Macy {
534eda14cbcSMatt Macy 	off_t saved_offset;
535eda14cbcSMatt Macy 	size_t saved_length, out_len;
536eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
537eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
538eda14cbcSMatt Macy 
539eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
540eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
541eda14cbcSMatt Macy 
542eda14cbcSMatt Macy 	ASSERT(ciphertext != NULL);
543eda14cbcSMatt Macy 
544eda14cbcSMatt Macy 	/* compute number of bytes that will hold the ciphertext */
545eda14cbcSMatt Macy 	out_len = aes_ctx->ac_remainder_len;
546eda14cbcSMatt Macy 	out_len += plaintext->cd_length;
547eda14cbcSMatt Macy 	out_len &= ~(AES_BLOCK_LEN - 1);
548eda14cbcSMatt Macy 
549eda14cbcSMatt Macy 	/* return length needed to store the output */
550eda14cbcSMatt Macy 	if (ciphertext->cd_length < out_len) {
551eda14cbcSMatt Macy 		ciphertext->cd_length = out_len;
552eda14cbcSMatt Macy 		return (CRYPTO_BUFFER_TOO_SMALL);
553eda14cbcSMatt Macy 	}
554eda14cbcSMatt Macy 
555eda14cbcSMatt Macy 	saved_offset = ciphertext->cd_offset;
556eda14cbcSMatt Macy 	saved_length = ciphertext->cd_length;
557eda14cbcSMatt Macy 
558eda14cbcSMatt Macy 	/*
559eda14cbcSMatt Macy 	 * Do the AES update on the specified input data.
560eda14cbcSMatt Macy 	 */
561eda14cbcSMatt Macy 	switch (plaintext->cd_format) {
562eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
563eda14cbcSMatt Macy 		ret = crypto_update_iov(ctx->cc_provider_private,
564c03c5b1cSMartin Matuska 		    plaintext, ciphertext, aes_encrypt_contiguous_blocks);
565eda14cbcSMatt Macy 		break;
566eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
567eda14cbcSMatt Macy 		ret = crypto_update_uio(ctx->cc_provider_private,
568c03c5b1cSMartin Matuska 		    plaintext, ciphertext, aes_encrypt_contiguous_blocks);
569eda14cbcSMatt Macy 		break;
570eda14cbcSMatt Macy 	default:
571eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
572eda14cbcSMatt Macy 	}
573eda14cbcSMatt Macy 
574eda14cbcSMatt Macy 	/*
575eda14cbcSMatt Macy 	 * Since AES counter mode is a stream cipher, we call
576eda14cbcSMatt Macy 	 * ctr_mode_final() to pick up any remaining bytes.
577eda14cbcSMatt Macy 	 * It is an internal function that does not destroy
578eda14cbcSMatt Macy 	 * the context like *normal* final routines.
579eda14cbcSMatt Macy 	 */
580eda14cbcSMatt Macy 	if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
581eda14cbcSMatt Macy 		ret = ctr_mode_final((ctr_ctx_t *)aes_ctx,
582eda14cbcSMatt Macy 		    ciphertext, aes_encrypt_block);
583eda14cbcSMatt Macy 	}
584eda14cbcSMatt Macy 
585eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
586eda14cbcSMatt Macy 		if (plaintext != ciphertext)
587eda14cbcSMatt Macy 			ciphertext->cd_length =
588eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
589eda14cbcSMatt Macy 	} else {
590eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length;
591eda14cbcSMatt Macy 	}
592eda14cbcSMatt Macy 	ciphertext->cd_offset = saved_offset;
593eda14cbcSMatt Macy 
594eda14cbcSMatt Macy 	return (ret);
595eda14cbcSMatt Macy }
596eda14cbcSMatt Macy 
597eda14cbcSMatt Macy 
598eda14cbcSMatt Macy static int
599eda14cbcSMatt Macy aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
600c03c5b1cSMartin Matuska     crypto_data_t *plaintext)
601eda14cbcSMatt Macy {
602eda14cbcSMatt Macy 	off_t saved_offset;
603eda14cbcSMatt Macy 	size_t saved_length, out_len;
604eda14cbcSMatt Macy 	int ret = CRYPTO_SUCCESS;
605eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
606eda14cbcSMatt Macy 
607eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
608eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
609eda14cbcSMatt Macy 
610eda14cbcSMatt Macy 	ASSERT(plaintext != NULL);
611eda14cbcSMatt Macy 
612eda14cbcSMatt Macy 	/*
613eda14cbcSMatt Macy 	 * Compute number of bytes that will hold the plaintext.
614eda14cbcSMatt Macy 	 * This is not necessary for CCM, GCM, and GMAC since these
615eda14cbcSMatt Macy 	 * mechanisms never return plaintext for update operations.
616eda14cbcSMatt Macy 	 */
617eda14cbcSMatt Macy 	if ((aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
618eda14cbcSMatt Macy 		out_len = aes_ctx->ac_remainder_len;
619eda14cbcSMatt Macy 		out_len += ciphertext->cd_length;
620eda14cbcSMatt Macy 		out_len &= ~(AES_BLOCK_LEN - 1);
621eda14cbcSMatt Macy 
622eda14cbcSMatt Macy 		/* return length needed to store the output */
623eda14cbcSMatt Macy 		if (plaintext->cd_length < out_len) {
624eda14cbcSMatt Macy 			plaintext->cd_length = out_len;
625eda14cbcSMatt Macy 			return (CRYPTO_BUFFER_TOO_SMALL);
626eda14cbcSMatt Macy 		}
627eda14cbcSMatt Macy 	}
628eda14cbcSMatt Macy 
629eda14cbcSMatt Macy 	saved_offset = plaintext->cd_offset;
630eda14cbcSMatt Macy 	saved_length = plaintext->cd_length;
631eda14cbcSMatt Macy 
632eda14cbcSMatt Macy 	/*
633eda14cbcSMatt Macy 	 * Do the AES update on the specified input data.
634eda14cbcSMatt Macy 	 */
635eda14cbcSMatt Macy 	switch (ciphertext->cd_format) {
636eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
637eda14cbcSMatt Macy 		ret = crypto_update_iov(ctx->cc_provider_private,
638c03c5b1cSMartin Matuska 		    ciphertext, plaintext, aes_decrypt_contiguous_blocks);
639eda14cbcSMatt Macy 		break;
640eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
641eda14cbcSMatt Macy 		ret = crypto_update_uio(ctx->cc_provider_private,
642c03c5b1cSMartin Matuska 		    ciphertext, plaintext, aes_decrypt_contiguous_blocks);
643eda14cbcSMatt Macy 		break;
644eda14cbcSMatt Macy 	default:
645eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
646eda14cbcSMatt Macy 	}
647eda14cbcSMatt Macy 
648eda14cbcSMatt Macy 	/*
649eda14cbcSMatt Macy 	 * Since AES counter mode is a stream cipher, we call
650eda14cbcSMatt Macy 	 * ctr_mode_final() to pick up any remaining bytes.
651eda14cbcSMatt Macy 	 * It is an internal function that does not destroy
652eda14cbcSMatt Macy 	 * the context like *normal* final routines.
653eda14cbcSMatt Macy 	 */
654eda14cbcSMatt Macy 	if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
655eda14cbcSMatt Macy 		ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, plaintext,
656eda14cbcSMatt Macy 		    aes_encrypt_block);
657eda14cbcSMatt Macy 		if (ret == CRYPTO_DATA_LEN_RANGE)
658eda14cbcSMatt Macy 			ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
659eda14cbcSMatt Macy 	}
660eda14cbcSMatt Macy 
661eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
662eda14cbcSMatt Macy 		if (ciphertext != plaintext)
663eda14cbcSMatt Macy 			plaintext->cd_length =
664eda14cbcSMatt Macy 			    plaintext->cd_offset - saved_offset;
665eda14cbcSMatt Macy 	} else {
666eda14cbcSMatt Macy 		plaintext->cd_length = saved_length;
667eda14cbcSMatt Macy 	}
668eda14cbcSMatt Macy 	plaintext->cd_offset = saved_offset;
669eda14cbcSMatt Macy 
670eda14cbcSMatt Macy 
671eda14cbcSMatt Macy 	return (ret);
672eda14cbcSMatt Macy }
673eda14cbcSMatt Macy 
674eda14cbcSMatt Macy static int
675c03c5b1cSMartin Matuska aes_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
676eda14cbcSMatt Macy {
677eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
678eda14cbcSMatt Macy 	int ret;
679eda14cbcSMatt Macy 
680eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
681eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
682eda14cbcSMatt Macy 
683eda14cbcSMatt Macy 	if (data->cd_format != CRYPTO_DATA_RAW &&
684eda14cbcSMatt Macy 	    data->cd_format != CRYPTO_DATA_UIO) {
685eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
686eda14cbcSMatt Macy 	}
687eda14cbcSMatt Macy 
688eda14cbcSMatt Macy 	if (aes_ctx->ac_flags & CTR_MODE) {
689eda14cbcSMatt Macy 		if (aes_ctx->ac_remainder_len > 0) {
690eda14cbcSMatt Macy 			ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
691eda14cbcSMatt Macy 			    aes_encrypt_block);
692eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
693eda14cbcSMatt Macy 				return (ret);
694eda14cbcSMatt Macy 		}
695eda14cbcSMatt Macy 	} else if (aes_ctx->ac_flags & CCM_MODE) {
696eda14cbcSMatt Macy 		ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, data,
697eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
698eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
699eda14cbcSMatt Macy 			return (ret);
700eda14cbcSMatt Macy 		}
701eda14cbcSMatt Macy 	} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
702eda14cbcSMatt Macy 		size_t saved_offset = data->cd_offset;
703eda14cbcSMatt Macy 
704eda14cbcSMatt Macy 		ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, data,
705eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
706eda14cbcSMatt Macy 		    aes_xor_block);
707eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
708eda14cbcSMatt Macy 			return (ret);
709eda14cbcSMatt Macy 		}
710eda14cbcSMatt Macy 		data->cd_length = data->cd_offset - saved_offset;
711eda14cbcSMatt Macy 		data->cd_offset = saved_offset;
712eda14cbcSMatt Macy 	} else {
713eda14cbcSMatt Macy 		/*
714eda14cbcSMatt Macy 		 * There must be no unprocessed plaintext.
715eda14cbcSMatt Macy 		 * This happens if the length of the last data is
716eda14cbcSMatt Macy 		 * not a multiple of the AES block length.
717eda14cbcSMatt Macy 		 */
718eda14cbcSMatt Macy 		if (aes_ctx->ac_remainder_len > 0) {
719eda14cbcSMatt Macy 			return (CRYPTO_DATA_LEN_RANGE);
720eda14cbcSMatt Macy 		}
721eda14cbcSMatt Macy 		data->cd_length = 0;
722eda14cbcSMatt Macy 	}
723eda14cbcSMatt Macy 
724eda14cbcSMatt Macy 	(void) aes_free_context(ctx);
725eda14cbcSMatt Macy 
726eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
727eda14cbcSMatt Macy }
728eda14cbcSMatt Macy 
729eda14cbcSMatt Macy static int
730c03c5b1cSMartin Matuska aes_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
731eda14cbcSMatt Macy {
732eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx;
733eda14cbcSMatt Macy 	int ret;
734eda14cbcSMatt Macy 	off_t saved_offset;
735eda14cbcSMatt Macy 	size_t saved_length;
736eda14cbcSMatt Macy 
737eda14cbcSMatt Macy 	ASSERT(ctx->cc_provider_private != NULL);
738eda14cbcSMatt Macy 	aes_ctx = ctx->cc_provider_private;
739eda14cbcSMatt Macy 
740eda14cbcSMatt Macy 	if (data->cd_format != CRYPTO_DATA_RAW &&
741eda14cbcSMatt Macy 	    data->cd_format != CRYPTO_DATA_UIO) {
742eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
743eda14cbcSMatt Macy 	}
744eda14cbcSMatt Macy 
745eda14cbcSMatt Macy 	/*
746eda14cbcSMatt Macy 	 * There must be no unprocessed ciphertext.
747eda14cbcSMatt Macy 	 * This happens if the length of the last ciphertext is
748eda14cbcSMatt Macy 	 * not a multiple of the AES block length.
749eda14cbcSMatt Macy 	 */
750eda14cbcSMatt Macy 	if (aes_ctx->ac_remainder_len > 0) {
751eda14cbcSMatt Macy 		if ((aes_ctx->ac_flags & CTR_MODE) == 0)
752eda14cbcSMatt Macy 			return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
753eda14cbcSMatt Macy 		else {
754eda14cbcSMatt Macy 			ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
755eda14cbcSMatt Macy 			    aes_encrypt_block);
756eda14cbcSMatt Macy 			if (ret == CRYPTO_DATA_LEN_RANGE)
757eda14cbcSMatt Macy 				ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
758eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
759eda14cbcSMatt Macy 				return (ret);
760eda14cbcSMatt Macy 		}
761eda14cbcSMatt Macy 	}
762eda14cbcSMatt Macy 
763eda14cbcSMatt Macy 	if (aes_ctx->ac_flags & CCM_MODE) {
764eda14cbcSMatt Macy 		/*
765eda14cbcSMatt Macy 		 * This is where all the plaintext is returned, make sure
766eda14cbcSMatt Macy 		 * the plaintext buffer is big enough
767eda14cbcSMatt Macy 		 */
768eda14cbcSMatt Macy 		size_t pt_len = aes_ctx->ac_data_len;
769eda14cbcSMatt Macy 		if (data->cd_length < pt_len) {
770eda14cbcSMatt Macy 			data->cd_length = pt_len;
771eda14cbcSMatt Macy 			return (CRYPTO_BUFFER_TOO_SMALL);
772eda14cbcSMatt Macy 		}
773eda14cbcSMatt Macy 
774eda14cbcSMatt Macy 		ASSERT(aes_ctx->ac_processed_data_len == pt_len);
775eda14cbcSMatt Macy 		ASSERT(aes_ctx->ac_processed_mac_len == aes_ctx->ac_mac_len);
776eda14cbcSMatt Macy 		saved_offset = data->cd_offset;
777eda14cbcSMatt Macy 		saved_length = data->cd_length;
778eda14cbcSMatt Macy 		ret = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, data,
779eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
780eda14cbcSMatt Macy 		    aes_xor_block);
781eda14cbcSMatt Macy 		if (ret == CRYPTO_SUCCESS) {
782eda14cbcSMatt Macy 			data->cd_length = data->cd_offset - saved_offset;
783eda14cbcSMatt Macy 		} else {
784eda14cbcSMatt Macy 			data->cd_length = saved_length;
785eda14cbcSMatt Macy 		}
786eda14cbcSMatt Macy 
787eda14cbcSMatt Macy 		data->cd_offset = saved_offset;
788eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
789eda14cbcSMatt Macy 			return (ret);
790eda14cbcSMatt Macy 		}
791eda14cbcSMatt Macy 	} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
792eda14cbcSMatt Macy 		/*
793eda14cbcSMatt Macy 		 * This is where all the plaintext is returned, make sure
794eda14cbcSMatt Macy 		 * the plaintext buffer is big enough
795eda14cbcSMatt Macy 		 */
796eda14cbcSMatt Macy 		gcm_ctx_t *ctx = (gcm_ctx_t *)aes_ctx;
797eda14cbcSMatt Macy 		size_t pt_len = ctx->gcm_processed_data_len - ctx->gcm_tag_len;
798eda14cbcSMatt Macy 
799eda14cbcSMatt Macy 		if (data->cd_length < pt_len) {
800eda14cbcSMatt Macy 			data->cd_length = pt_len;
801eda14cbcSMatt Macy 			return (CRYPTO_BUFFER_TOO_SMALL);
802eda14cbcSMatt Macy 		}
803eda14cbcSMatt Macy 
804eda14cbcSMatt Macy 		saved_offset = data->cd_offset;
805eda14cbcSMatt Macy 		saved_length = data->cd_length;
806eda14cbcSMatt Macy 		ret = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, data,
807eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
808eda14cbcSMatt Macy 		if (ret == CRYPTO_SUCCESS) {
809eda14cbcSMatt Macy 			data->cd_length = data->cd_offset - saved_offset;
810eda14cbcSMatt Macy 		} else {
811eda14cbcSMatt Macy 			data->cd_length = saved_length;
812eda14cbcSMatt Macy 		}
813eda14cbcSMatt Macy 
814eda14cbcSMatt Macy 		data->cd_offset = saved_offset;
815eda14cbcSMatt Macy 		if (ret != CRYPTO_SUCCESS) {
816eda14cbcSMatt Macy 			return (ret);
817eda14cbcSMatt Macy 		}
818eda14cbcSMatt Macy 	}
819eda14cbcSMatt Macy 
820eda14cbcSMatt Macy 
821eda14cbcSMatt Macy 	if ((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
822eda14cbcSMatt Macy 		data->cd_length = 0;
823eda14cbcSMatt Macy 	}
824eda14cbcSMatt Macy 
825eda14cbcSMatt Macy 	(void) aes_free_context(ctx);
826eda14cbcSMatt Macy 
827eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
828eda14cbcSMatt Macy }
829eda14cbcSMatt Macy 
830eda14cbcSMatt Macy static int
831c03c5b1cSMartin Matuska aes_encrypt_atomic(crypto_mechanism_t *mechanism,
832eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
833c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
834eda14cbcSMatt Macy {
835*aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
836eda14cbcSMatt Macy 	off_t saved_offset;
837eda14cbcSMatt Macy 	size_t saved_length;
838eda14cbcSMatt Macy 	size_t length_needed;
839eda14cbcSMatt Macy 	int ret;
840eda14cbcSMatt Macy 
841*aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
842*aca928a5SMartin Matuska 
843eda14cbcSMatt Macy 	ASSERT(ciphertext != NULL);
844eda14cbcSMatt Macy 
845eda14cbcSMatt Macy 	/*
846eda14cbcSMatt Macy 	 * CTR, CCM, GCM, and GMAC modes do not require that plaintext
847eda14cbcSMatt Macy 	 * be a multiple of AES block size.
848eda14cbcSMatt Macy 	 */
849eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
850eda14cbcSMatt Macy 	case AES_CTR_MECH_INFO_TYPE:
851eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
852eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
853eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
854eda14cbcSMatt Macy 		break;
855eda14cbcSMatt Macy 	default:
856eda14cbcSMatt Macy 		if ((plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
857eda14cbcSMatt Macy 			return (CRYPTO_DATA_LEN_RANGE);
858eda14cbcSMatt Macy 	}
859eda14cbcSMatt Macy 
860c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
861eda14cbcSMatt Macy 		return (ret);
862eda14cbcSMatt Macy 
863eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
864c03c5b1cSMartin Matuska 	    KM_SLEEP, B_TRUE);
865eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
866eda14cbcSMatt Macy 		return (ret);
867eda14cbcSMatt Macy 
868eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
869eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
870eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
871eda14cbcSMatt Macy 		break;
872eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
873eda14cbcSMatt Macy 		if (plaintext->cd_length != 0)
874eda14cbcSMatt Macy 			return (CRYPTO_ARGUMENTS_BAD);
875c03c5b1cSMartin Matuska 		zfs_fallthrough;
876eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
877eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
878eda14cbcSMatt Macy 		break;
879eda14cbcSMatt Macy 	default:
880eda14cbcSMatt Macy 		length_needed = plaintext->cd_length;
881eda14cbcSMatt Macy 	}
882eda14cbcSMatt Macy 
883eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
884eda14cbcSMatt Macy 	if (ciphertext->cd_length < length_needed) {
885eda14cbcSMatt Macy 		ciphertext->cd_length = length_needed;
886eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
887eda14cbcSMatt Macy 		goto out;
888eda14cbcSMatt Macy 	}
889eda14cbcSMatt Macy 
890eda14cbcSMatt Macy 	saved_offset = ciphertext->cd_offset;
891eda14cbcSMatt Macy 	saved_length = ciphertext->cd_length;
892eda14cbcSMatt Macy 
893eda14cbcSMatt Macy 	/*
894eda14cbcSMatt Macy 	 * Do an update on the specified input data.
895eda14cbcSMatt Macy 	 */
896eda14cbcSMatt Macy 	switch (plaintext->cd_format) {
897eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
898eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, plaintext, ciphertext,
899c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
900eda14cbcSMatt Macy 		break;
901eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
902eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, plaintext, ciphertext,
903c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
904eda14cbcSMatt Macy 		break;
905eda14cbcSMatt Macy 	default:
906eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
907eda14cbcSMatt Macy 	}
908eda14cbcSMatt Macy 
909eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
910eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
911eda14cbcSMatt Macy 			ret = ccm_encrypt_final((ccm_ctx_t *)&aes_ctx,
912eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
913eda14cbcSMatt Macy 			    aes_xor_block);
914eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
915eda14cbcSMatt Macy 				goto out;
916eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
917eda14cbcSMatt Macy 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
918eda14cbcSMatt Macy 		    mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
919eda14cbcSMatt Macy 			ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
920eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
921eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
922eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
923eda14cbcSMatt Macy 				goto out;
924eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
925eda14cbcSMatt Macy 		} else if (mechanism->cm_type == AES_CTR_MECH_INFO_TYPE) {
926eda14cbcSMatt Macy 			if (aes_ctx.ac_remainder_len > 0) {
927eda14cbcSMatt Macy 				ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
928eda14cbcSMatt Macy 				    ciphertext, aes_encrypt_block);
929eda14cbcSMatt Macy 				if (ret != CRYPTO_SUCCESS)
930eda14cbcSMatt Macy 					goto out;
931eda14cbcSMatt Macy 			}
932eda14cbcSMatt Macy 		} else {
933eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
934eda14cbcSMatt Macy 		}
935eda14cbcSMatt Macy 
936eda14cbcSMatt Macy 		if (plaintext != ciphertext) {
937eda14cbcSMatt Macy 			ciphertext->cd_length =
938eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
939eda14cbcSMatt Macy 		}
940eda14cbcSMatt Macy 	} else {
941eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length;
942eda14cbcSMatt Macy 	}
943eda14cbcSMatt Macy 	ciphertext->cd_offset = saved_offset;
944eda14cbcSMatt Macy 
945eda14cbcSMatt Macy out:
946eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
947da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
948eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
949eda14cbcSMatt Macy 	}
9502a58b312SMartin Matuska 	if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
9512a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
9527877fdebSMatt Macy 	}
953eda14cbcSMatt Macy 	return (ret);
954eda14cbcSMatt Macy }
955eda14cbcSMatt Macy 
956eda14cbcSMatt Macy static int
957c03c5b1cSMartin Matuska aes_decrypt_atomic(crypto_mechanism_t *mechanism,
958eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
959c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
960eda14cbcSMatt Macy {
961*aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
962eda14cbcSMatt Macy 	off_t saved_offset;
963eda14cbcSMatt Macy 	size_t saved_length;
964eda14cbcSMatt Macy 	size_t length_needed;
965eda14cbcSMatt Macy 	int ret;
966eda14cbcSMatt Macy 
967*aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
968*aca928a5SMartin Matuska 
969eda14cbcSMatt Macy 	ASSERT(plaintext != NULL);
970eda14cbcSMatt Macy 
971eda14cbcSMatt Macy 	/*
972eda14cbcSMatt Macy 	 * CCM, GCM, CTR, and GMAC modes do not require that ciphertext
973eda14cbcSMatt Macy 	 * be a multiple of AES block size.
974eda14cbcSMatt Macy 	 */
975eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
976eda14cbcSMatt Macy 	case AES_CTR_MECH_INFO_TYPE:
977eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
978eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
979eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
980eda14cbcSMatt Macy 		break;
981eda14cbcSMatt Macy 	default:
982eda14cbcSMatt Macy 		if ((ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
983eda14cbcSMatt Macy 			return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
984eda14cbcSMatt Macy 	}
985eda14cbcSMatt Macy 
986c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
987eda14cbcSMatt Macy 		return (ret);
988eda14cbcSMatt Macy 
989eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
990c03c5b1cSMartin Matuska 	    KM_SLEEP, B_FALSE);
991eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
992eda14cbcSMatt Macy 		return (ret);
993eda14cbcSMatt Macy 
994eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
995eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
996eda14cbcSMatt Macy 		length_needed = aes_ctx.ac_data_len;
997eda14cbcSMatt Macy 		break;
998eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
999eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
1000eda14cbcSMatt Macy 		break;
1001eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
1002eda14cbcSMatt Macy 		if (plaintext->cd_length != 0)
1003eda14cbcSMatt Macy 			return (CRYPTO_ARGUMENTS_BAD);
1004eda14cbcSMatt Macy 		length_needed = 0;
1005eda14cbcSMatt Macy 		break;
1006eda14cbcSMatt Macy 	default:
1007eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length;
1008eda14cbcSMatt Macy 	}
1009eda14cbcSMatt Macy 
1010eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
1011eda14cbcSMatt Macy 	if (plaintext->cd_length < length_needed) {
1012eda14cbcSMatt Macy 		plaintext->cd_length = length_needed;
1013eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
1014eda14cbcSMatt Macy 		goto out;
1015eda14cbcSMatt Macy 	}
1016eda14cbcSMatt Macy 
1017eda14cbcSMatt Macy 	saved_offset = plaintext->cd_offset;
1018eda14cbcSMatt Macy 	saved_length = plaintext->cd_length;
1019eda14cbcSMatt Macy 
1020eda14cbcSMatt Macy 	/*
1021eda14cbcSMatt Macy 	 * Do an update on the specified input data.
1022eda14cbcSMatt Macy 	 */
1023eda14cbcSMatt Macy 	switch (ciphertext->cd_format) {
1024eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
1025eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, ciphertext, plaintext,
1026c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
1027eda14cbcSMatt Macy 		break;
1028eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
1029eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, ciphertext, plaintext,
1030c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
1031eda14cbcSMatt Macy 		break;
1032eda14cbcSMatt Macy 	default:
1033eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
1034eda14cbcSMatt Macy 	}
1035eda14cbcSMatt Macy 
1036eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
1037eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
1038eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_data_len
1039eda14cbcSMatt Macy 			    == aes_ctx.ac_data_len);
1040eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_mac_len
1041eda14cbcSMatt Macy 			    == aes_ctx.ac_mac_len);
1042eda14cbcSMatt Macy 			ret = ccm_decrypt_final((ccm_ctx_t *)&aes_ctx,
1043eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
1044eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
1045eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
1046eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
1047eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
1048eda14cbcSMatt Macy 				plaintext->cd_length =
1049eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
1050eda14cbcSMatt Macy 			} else {
1051eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
1052eda14cbcSMatt Macy 			}
1053eda14cbcSMatt Macy 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
1054eda14cbcSMatt Macy 		    mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
1055eda14cbcSMatt Macy 			ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
1056eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
1057eda14cbcSMatt Macy 			    aes_xor_block);
1058eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
1059eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
1060eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
1061eda14cbcSMatt Macy 				plaintext->cd_length =
1062eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
1063eda14cbcSMatt Macy 			} else {
1064eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
1065eda14cbcSMatt Macy 			}
1066eda14cbcSMatt Macy 		} else if (mechanism->cm_type != AES_CTR_MECH_INFO_TYPE) {
1067eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
1068eda14cbcSMatt Macy 			if (ciphertext != plaintext)
1069eda14cbcSMatt Macy 				plaintext->cd_length =
1070eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
1071eda14cbcSMatt Macy 		} else {
1072eda14cbcSMatt Macy 			if (aes_ctx.ac_remainder_len > 0) {
1073eda14cbcSMatt Macy 				ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
1074eda14cbcSMatt Macy 				    plaintext, aes_encrypt_block);
1075eda14cbcSMatt Macy 				if (ret == CRYPTO_DATA_LEN_RANGE)
1076eda14cbcSMatt Macy 					ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
1077eda14cbcSMatt Macy 				if (ret != CRYPTO_SUCCESS)
1078eda14cbcSMatt Macy 					goto out;
1079eda14cbcSMatt Macy 			}
1080eda14cbcSMatt Macy 			if (ciphertext != plaintext)
1081eda14cbcSMatt Macy 				plaintext->cd_length =
1082eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
1083eda14cbcSMatt Macy 		}
1084eda14cbcSMatt Macy 	} else {
1085eda14cbcSMatt Macy 		plaintext->cd_length = saved_length;
1086eda14cbcSMatt Macy 	}
1087eda14cbcSMatt Macy 	plaintext->cd_offset = saved_offset;
1088eda14cbcSMatt Macy 
1089eda14cbcSMatt Macy out:
1090eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
1091da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
1092eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
1093eda14cbcSMatt Macy 	}
1094eda14cbcSMatt Macy 
1095eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & CCM_MODE) {
1096eda14cbcSMatt Macy 		if (aes_ctx.ac_pt_buf != NULL) {
1097eda14cbcSMatt Macy 			vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
1098eda14cbcSMatt Macy 		}
1099eda14cbcSMatt Macy 	} else if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
11002a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
1101eda14cbcSMatt Macy 	}
1102eda14cbcSMatt Macy 
1103eda14cbcSMatt Macy 	return (ret);
1104eda14cbcSMatt Macy }
1105eda14cbcSMatt Macy 
1106eda14cbcSMatt Macy /*
1107eda14cbcSMatt Macy  * KCF software provider context template entry points.
1108eda14cbcSMatt Macy  */
1109eda14cbcSMatt Macy static int
1110c03c5b1cSMartin Matuska aes_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
1111c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size)
1112eda14cbcSMatt Macy {
1113eda14cbcSMatt Macy 	void *keysched;
1114eda14cbcSMatt Macy 	size_t size;
1115eda14cbcSMatt Macy 	int rv;
1116eda14cbcSMatt Macy 
1117eda14cbcSMatt Macy 	if (mechanism->cm_type != AES_ECB_MECH_INFO_TYPE &&
1118eda14cbcSMatt Macy 	    mechanism->cm_type != AES_CBC_MECH_INFO_TYPE &&
1119eda14cbcSMatt Macy 	    mechanism->cm_type != AES_CTR_MECH_INFO_TYPE &&
1120eda14cbcSMatt Macy 	    mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
1121eda14cbcSMatt Macy 	    mechanism->cm_type != AES_GCM_MECH_INFO_TYPE &&
1122eda14cbcSMatt Macy 	    mechanism->cm_type != AES_GMAC_MECH_INFO_TYPE)
1123eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
1124eda14cbcSMatt Macy 
1125c03c5b1cSMartin Matuska 	if ((keysched = aes_alloc_keysched(&size, KM_SLEEP)) == NULL) {
1126eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
1127eda14cbcSMatt Macy 	}
1128eda14cbcSMatt Macy 
1129eda14cbcSMatt Macy 	/*
1130eda14cbcSMatt Macy 	 * Initialize key schedule.  Key length information is stored
1131eda14cbcSMatt Macy 	 * in the key.
1132eda14cbcSMatt Macy 	 */
1133eda14cbcSMatt Macy 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
1134da5137abSMartin Matuska 		memset(keysched, 0, size);
1135eda14cbcSMatt Macy 		kmem_free(keysched, size);
1136eda14cbcSMatt Macy 		return (rv);
1137eda14cbcSMatt Macy 	}
1138eda14cbcSMatt Macy 
1139eda14cbcSMatt Macy 	*tmpl = keysched;
1140eda14cbcSMatt Macy 	*tmpl_size = size;
1141eda14cbcSMatt Macy 
1142eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
1143eda14cbcSMatt Macy }
1144eda14cbcSMatt Macy 
1145eda14cbcSMatt Macy 
1146eda14cbcSMatt Macy static int
1147eda14cbcSMatt Macy aes_free_context(crypto_ctx_t *ctx)
1148eda14cbcSMatt Macy {
1149eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx = ctx->cc_provider_private;
1150eda14cbcSMatt Macy 
1151eda14cbcSMatt Macy 	if (aes_ctx != NULL) {
1152eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
1153eda14cbcSMatt Macy 			ASSERT(aes_ctx->ac_keysched_len != 0);
1154da5137abSMartin Matuska 			memset(aes_ctx->ac_keysched, 0,
1155da5137abSMartin Matuska 			    aes_ctx->ac_keysched_len);
1156eda14cbcSMatt Macy 			kmem_free(aes_ctx->ac_keysched,
1157eda14cbcSMatt Macy 			    aes_ctx->ac_keysched_len);
1158eda14cbcSMatt Macy 		}
1159eda14cbcSMatt Macy 		crypto_free_mode_ctx(aes_ctx);
1160eda14cbcSMatt Macy 		ctx->cc_provider_private = NULL;
1161eda14cbcSMatt Macy 	}
1162eda14cbcSMatt Macy 
1163eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
1164eda14cbcSMatt Macy }
1165eda14cbcSMatt Macy 
1166eda14cbcSMatt Macy 
1167eda14cbcSMatt Macy static int
1168eda14cbcSMatt Macy aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
1169eda14cbcSMatt Macy     crypto_mechanism_t *mechanism, crypto_key_t *key, int kmflag,
1170eda14cbcSMatt Macy     boolean_t is_encrypt_init)
1171eda14cbcSMatt Macy {
1172eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
1173eda14cbcSMatt Macy 	void *keysched;
1174eda14cbcSMatt Macy 	size_t size = 0;
1175eda14cbcSMatt Macy 
1176eda14cbcSMatt Macy 	if (template == NULL) {
1177eda14cbcSMatt Macy 		if ((keysched = aes_alloc_keysched(&size, kmflag)) == NULL)
1178eda14cbcSMatt Macy 			return (CRYPTO_HOST_MEMORY);
1179eda14cbcSMatt Macy 		/*
1180eda14cbcSMatt Macy 		 * Initialize key schedule.
1181eda14cbcSMatt Macy 		 * Key length is stored in the key.
1182eda14cbcSMatt Macy 		 */
1183eda14cbcSMatt Macy 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
1184eda14cbcSMatt Macy 			kmem_free(keysched, size);
1185eda14cbcSMatt Macy 			return (rv);
1186eda14cbcSMatt Macy 		}
1187eda14cbcSMatt Macy 
1188eda14cbcSMatt Macy 		aes_ctx->ac_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
1189eda14cbcSMatt Macy 		aes_ctx->ac_keysched_len = size;
1190eda14cbcSMatt Macy 	} else {
1191eda14cbcSMatt Macy 		keysched = template;
1192eda14cbcSMatt Macy 	}
1193eda14cbcSMatt Macy 	aes_ctx->ac_keysched = keysched;
1194eda14cbcSMatt Macy 
1195eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
1196eda14cbcSMatt Macy 	case AES_CBC_MECH_INFO_TYPE:
1197eda14cbcSMatt Macy 		rv = cbc_init_ctx((cbc_ctx_t *)aes_ctx, mechanism->cm_param,
1198eda14cbcSMatt Macy 		    mechanism->cm_param_len, AES_BLOCK_LEN, aes_copy_block64);
1199eda14cbcSMatt Macy 		break;
1200eda14cbcSMatt Macy 	case AES_CTR_MECH_INFO_TYPE: {
1201eda14cbcSMatt Macy 		CK_AES_CTR_PARAMS *pp;
1202eda14cbcSMatt Macy 
1203eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1204eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_CTR_PARAMS)) {
1205eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
1206eda14cbcSMatt Macy 		}
1207eda14cbcSMatt Macy 		pp = (CK_AES_CTR_PARAMS *)(void *)mechanism->cm_param;
1208eda14cbcSMatt Macy 		rv = ctr_init_ctx((ctr_ctx_t *)aes_ctx, pp->ulCounterBits,
1209eda14cbcSMatt Macy 		    pp->cb, aes_copy_block);
1210eda14cbcSMatt Macy 		break;
1211eda14cbcSMatt Macy 	}
1212eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
1213eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1214eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
1215eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
1216eda14cbcSMatt Macy 		}
1217eda14cbcSMatt Macy 		rv = ccm_init_ctx((ccm_ctx_t *)aes_ctx, mechanism->cm_param,
1218eda14cbcSMatt Macy 		    kmflag, is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
1219eda14cbcSMatt Macy 		    aes_xor_block);
1220eda14cbcSMatt Macy 		break;
1221eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
1222eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1223eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_GCM_PARAMS)) {
1224eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
1225eda14cbcSMatt Macy 		}
1226eda14cbcSMatt Macy 		rv = gcm_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
1227eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
1228eda14cbcSMatt Macy 		    aes_xor_block);
1229eda14cbcSMatt Macy 		break;
1230eda14cbcSMatt Macy 	case AES_GMAC_MECH_INFO_TYPE:
1231eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
1232eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_GMAC_PARAMS)) {
1233eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
1234eda14cbcSMatt Macy 		}
1235eda14cbcSMatt Macy 		rv = gmac_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
1236eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
1237eda14cbcSMatt Macy 		    aes_xor_block);
1238eda14cbcSMatt Macy 		break;
1239eda14cbcSMatt Macy 	case AES_ECB_MECH_INFO_TYPE:
1240eda14cbcSMatt Macy 		aes_ctx->ac_flags |= ECB_MODE;
1241eda14cbcSMatt Macy 	}
1242eda14cbcSMatt Macy 
1243eda14cbcSMatt Macy 	if (rv != CRYPTO_SUCCESS) {
1244eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
1245da5137abSMartin Matuska 			memset(keysched, 0, size);
1246eda14cbcSMatt Macy 			kmem_free(keysched, size);
1247eda14cbcSMatt Macy 		}
1248eda14cbcSMatt Macy 	}
1249eda14cbcSMatt Macy 
1250eda14cbcSMatt Macy 	return (rv);
1251eda14cbcSMatt Macy }
1252eda14cbcSMatt Macy 
1253eda14cbcSMatt Macy static int
1254eda14cbcSMatt Macy process_gmac_mech(crypto_mechanism_t *mech, crypto_data_t *data,
1255eda14cbcSMatt Macy     CK_AES_GCM_PARAMS *gcm_params)
1256eda14cbcSMatt Macy {
1257eda14cbcSMatt Macy 	/* LINTED: pointer alignment */
1258eda14cbcSMatt Macy 	CK_AES_GMAC_PARAMS *params = (CK_AES_GMAC_PARAMS *)mech->cm_param;
1259eda14cbcSMatt Macy 
1260eda14cbcSMatt Macy 	if (mech->cm_type != AES_GMAC_MECH_INFO_TYPE)
1261eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
1262eda14cbcSMatt Macy 
1263eda14cbcSMatt Macy 	if (mech->cm_param_len != sizeof (CK_AES_GMAC_PARAMS))
1264eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_PARAM_INVALID);
1265eda14cbcSMatt Macy 
1266eda14cbcSMatt Macy 	if (params->pIv == NULL)
1267eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_PARAM_INVALID);
1268eda14cbcSMatt Macy 
1269eda14cbcSMatt Macy 	gcm_params->pIv = params->pIv;
1270eda14cbcSMatt Macy 	gcm_params->ulIvLen = AES_GMAC_IV_LEN;
1271eda14cbcSMatt Macy 	gcm_params->ulTagBits = AES_GMAC_TAG_BITS;
1272eda14cbcSMatt Macy 
1273eda14cbcSMatt Macy 	if (data == NULL)
1274eda14cbcSMatt Macy 		return (CRYPTO_SUCCESS);
1275eda14cbcSMatt Macy 
1276eda14cbcSMatt Macy 	if (data->cd_format != CRYPTO_DATA_RAW)
1277eda14cbcSMatt Macy 		return (CRYPTO_ARGUMENTS_BAD);
1278eda14cbcSMatt Macy 
1279eda14cbcSMatt Macy 	gcm_params->pAAD = (uchar_t *)data->cd_raw.iov_base;
1280eda14cbcSMatt Macy 	gcm_params->ulAADLen = data->cd_length;
1281eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
1282eda14cbcSMatt Macy }
1283eda14cbcSMatt Macy 
1284eda14cbcSMatt Macy static int
1285c03c5b1cSMartin Matuska aes_mac_atomic(crypto_mechanism_t *mechanism,
1286eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1287c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
1288eda14cbcSMatt Macy {
1289eda14cbcSMatt Macy 	CK_AES_GCM_PARAMS gcm_params;
1290eda14cbcSMatt Macy 	crypto_mechanism_t gcm_mech;
1291eda14cbcSMatt Macy 	int rv;
1292eda14cbcSMatt Macy 
1293eda14cbcSMatt Macy 	if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
1294eda14cbcSMatt Macy 	    != CRYPTO_SUCCESS)
1295eda14cbcSMatt Macy 		return (rv);
1296eda14cbcSMatt Macy 
1297eda14cbcSMatt Macy 	gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
1298eda14cbcSMatt Macy 	gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
1299eda14cbcSMatt Macy 	gcm_mech.cm_param = (char *)&gcm_params;
1300eda14cbcSMatt Macy 
1301c03c5b1cSMartin Matuska 	return (aes_encrypt_atomic(&gcm_mech,
1302c03c5b1cSMartin Matuska 	    key, &null_crypto_data, mac, template));
1303eda14cbcSMatt Macy }
1304eda14cbcSMatt Macy 
1305eda14cbcSMatt Macy static int
1306c03c5b1cSMartin Matuska aes_mac_verify_atomic(crypto_mechanism_t *mechanism, crypto_key_t *key,
1307c03c5b1cSMartin Matuska     crypto_data_t *data, crypto_data_t *mac, crypto_spi_ctx_template_t template)
1308eda14cbcSMatt Macy {
1309eda14cbcSMatt Macy 	CK_AES_GCM_PARAMS gcm_params;
1310eda14cbcSMatt Macy 	crypto_mechanism_t gcm_mech;
1311eda14cbcSMatt Macy 	int rv;
1312eda14cbcSMatt Macy 
1313eda14cbcSMatt Macy 	if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
1314eda14cbcSMatt Macy 	    != CRYPTO_SUCCESS)
1315eda14cbcSMatt Macy 		return (rv);
1316eda14cbcSMatt Macy 
1317eda14cbcSMatt Macy 	gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
1318eda14cbcSMatt Macy 	gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
1319eda14cbcSMatt Macy 	gcm_mech.cm_param = (char *)&gcm_params;
1320eda14cbcSMatt Macy 
1321c03c5b1cSMartin Matuska 	return (aes_decrypt_atomic(&gcm_mech,
1322c03c5b1cSMartin Matuska 	    key, mac, &null_crypto_data, template));
1323eda14cbcSMatt Macy }
1324