xref: /freebsd/sys/contrib/openzfs/module/icp/io/aes.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2eda14cbcSMatt Macy /*
3eda14cbcSMatt Macy  * CDDL HEADER START
4eda14cbcSMatt Macy  *
5eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
6eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
7eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
8eda14cbcSMatt Macy  *
9eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
11eda14cbcSMatt Macy  * See the License for the specific language governing permissions
12eda14cbcSMatt Macy  * and limitations under the License.
13eda14cbcSMatt Macy  *
14eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
15eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
17eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
18eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
19eda14cbcSMatt Macy  *
20eda14cbcSMatt Macy  * CDDL HEADER END
21eda14cbcSMatt Macy  */
22eda14cbcSMatt Macy /*
23eda14cbcSMatt Macy  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24eda14cbcSMatt Macy  */
25eda14cbcSMatt Macy 
26eda14cbcSMatt Macy /*
27eda14cbcSMatt Macy  * AES provider for the Kernel Cryptographic Framework (KCF)
28eda14cbcSMatt Macy  */
29eda14cbcSMatt Macy 
30eda14cbcSMatt Macy #include <sys/zfs_context.h>
31eda14cbcSMatt Macy #include <sys/crypto/common.h>
32eda14cbcSMatt Macy #include <sys/crypto/impl.h>
33eda14cbcSMatt Macy #include <sys/crypto/spi.h>
34eda14cbcSMatt Macy #include <sys/crypto/icp.h>
35eda14cbcSMatt Macy #include <modes/modes.h>
36eda14cbcSMatt Macy #define	_AES_IMPL
37eda14cbcSMatt Macy #include <aes/aes_impl.h>
38eda14cbcSMatt Macy #include <modes/gcm_impl.h>
39eda14cbcSMatt Macy 
40eda14cbcSMatt Macy /*
41eda14cbcSMatt Macy  * Mechanism info structure passed to KCF during registration.
42eda14cbcSMatt Macy  */
43e92ffd9bSMartin Matuska static const crypto_mech_info_t aes_mech_info_tab[] = {
44eda14cbcSMatt Macy 	/* AES_CCM */
45eda14cbcSMatt Macy 	{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
4675e1fea6SMartin Matuska 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC},
47eda14cbcSMatt Macy 	/* AES_GCM */
48eda14cbcSMatt Macy 	{SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
4975e1fea6SMartin Matuska 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC},
50eda14cbcSMatt Macy };
51eda14cbcSMatt Macy 
52eda14cbcSMatt Macy static int aes_common_init_ctx(aes_ctx_t *, crypto_spi_ctx_template_t *,
53eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, int, boolean_t);
54eda14cbcSMatt Macy 
55c03c5b1cSMartin Matuska static int aes_encrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
56c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
57eda14cbcSMatt Macy 
58c03c5b1cSMartin Matuska static int aes_decrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
59c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
60eda14cbcSMatt Macy 
61e92ffd9bSMartin Matuska static const crypto_cipher_ops_t aes_cipher_ops = {
62eda14cbcSMatt Macy 	.encrypt_atomic = aes_encrypt_atomic,
63eda14cbcSMatt Macy 	.decrypt_atomic = aes_decrypt_atomic
64eda14cbcSMatt Macy };
65eda14cbcSMatt Macy 
66c03c5b1cSMartin Matuska static int aes_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
67c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *, size_t *);
68eda14cbcSMatt Macy static int aes_free_context(crypto_ctx_t *);
69eda14cbcSMatt Macy 
70e92ffd9bSMartin Matuska static const crypto_ctx_ops_t aes_ctx_ops = {
71eda14cbcSMatt Macy 	.create_ctx_template = aes_create_ctx_template,
72eda14cbcSMatt Macy 	.free_context = aes_free_context
73eda14cbcSMatt Macy };
74eda14cbcSMatt Macy 
75c03c5b1cSMartin Matuska static const crypto_ops_t aes_crypto_ops = {
76eda14cbcSMatt Macy 	&aes_cipher_ops,
7775e1fea6SMartin Matuska 	NULL,
78c03c5b1cSMartin Matuska 	&aes_ctx_ops,
79c03c5b1cSMartin Matuska };
80eda14cbcSMatt Macy 
81c03c5b1cSMartin Matuska static const crypto_provider_info_t aes_prov_info = {
82eda14cbcSMatt Macy 	"AES Software Provider",
83eda14cbcSMatt Macy 	&aes_crypto_ops,
84eda14cbcSMatt Macy 	sizeof (aes_mech_info_tab) / sizeof (crypto_mech_info_t),
85eda14cbcSMatt Macy 	aes_mech_info_tab
86c03c5b1cSMartin Matuska };
87eda14cbcSMatt Macy 
88eda14cbcSMatt Macy static crypto_kcf_provider_handle_t aes_prov_handle = 0;
89eda14cbcSMatt Macy 
90eda14cbcSMatt Macy int
aes_mod_init(void)91eda14cbcSMatt Macy aes_mod_init(void)
92eda14cbcSMatt Macy {
93eda14cbcSMatt Macy 	/* Determine the fastest available implementation. */
94eda14cbcSMatt Macy 	aes_impl_init();
95eda14cbcSMatt Macy 	gcm_impl_init();
96eda14cbcSMatt Macy 
97eda14cbcSMatt Macy 	/* Register with KCF.  If the registration fails, remove the module. */
98e92ffd9bSMartin Matuska 	if (crypto_register_provider(&aes_prov_info, &aes_prov_handle))
99eda14cbcSMatt Macy 		return (EACCES);
100eda14cbcSMatt Macy 
101eda14cbcSMatt Macy 	return (0);
102eda14cbcSMatt Macy }
103eda14cbcSMatt Macy 
104eda14cbcSMatt Macy int
aes_mod_fini(void)105eda14cbcSMatt Macy aes_mod_fini(void)
106eda14cbcSMatt Macy {
107eda14cbcSMatt Macy 	/* Unregister from KCF if module is registered */
108eda14cbcSMatt Macy 	if (aes_prov_handle != 0) {
109eda14cbcSMatt Macy 		if (crypto_unregister_provider(aes_prov_handle))
110eda14cbcSMatt Macy 			return (EBUSY);
111eda14cbcSMatt Macy 
112eda14cbcSMatt Macy 		aes_prov_handle = 0;
113eda14cbcSMatt Macy 	}
114eda14cbcSMatt Macy 
115e92ffd9bSMartin Matuska 	return (0);
116eda14cbcSMatt Macy }
117eda14cbcSMatt Macy 
118eda14cbcSMatt Macy static int
aes_check_mech_param(crypto_mechanism_t * mechanism,aes_ctx_t ** ctx)119c03c5b1cSMartin Matuska aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
120eda14cbcSMatt Macy {
121eda14cbcSMatt Macy 	void *p = NULL;
122eda14cbcSMatt Macy 	boolean_t param_required = B_TRUE;
123eda14cbcSMatt Macy 	size_t param_len;
124eda14cbcSMatt Macy 	void *(*alloc_fun)(int);
125eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
126eda14cbcSMatt Macy 
127eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
128eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
129eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_CCM_PARAMS);
130eda14cbcSMatt Macy 		alloc_fun = ccm_alloc_ctx;
131eda14cbcSMatt Macy 		break;
132eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
133eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_GCM_PARAMS);
134eda14cbcSMatt Macy 		alloc_fun = gcm_alloc_ctx;
135eda14cbcSMatt Macy 		break;
136eda14cbcSMatt Macy 	default:
13775e1fea6SMartin Matuska 		__builtin_unreachable();
138eda14cbcSMatt Macy 	}
139eda14cbcSMatt Macy 	if (param_required && mechanism->cm_param != NULL &&
140eda14cbcSMatt Macy 	    mechanism->cm_param_len != param_len) {
141eda14cbcSMatt Macy 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
142eda14cbcSMatt Macy 	}
143eda14cbcSMatt Macy 	if (ctx != NULL) {
144c03c5b1cSMartin Matuska 		p = (alloc_fun)(KM_SLEEP);
145eda14cbcSMatt Macy 		*ctx = p;
146eda14cbcSMatt Macy 	}
147eda14cbcSMatt Macy 	return (rv);
148eda14cbcSMatt Macy }
149eda14cbcSMatt Macy 
150eda14cbcSMatt Macy /*
151eda14cbcSMatt Macy  * Initialize key schedules for AES
152eda14cbcSMatt Macy  */
153eda14cbcSMatt Macy static int
init_keysched(crypto_key_t * key,void * newbie)154eda14cbcSMatt Macy init_keysched(crypto_key_t *key, void *newbie)
155eda14cbcSMatt Macy {
156eda14cbcSMatt Macy 	if (key->ck_length < AES_MINBITS ||
157eda14cbcSMatt Macy 	    key->ck_length > AES_MAXBITS) {
158eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
159eda14cbcSMatt Macy 	}
160eda14cbcSMatt Macy 
161eda14cbcSMatt Macy 	/* key length must be either 128, 192, or 256 */
162eda14cbcSMatt Macy 	if ((key->ck_length & 63) != 0)
163eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
164eda14cbcSMatt Macy 
165eda14cbcSMatt Macy 	aes_init_keysched(key->ck_data, key->ck_length, newbie);
166eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
167eda14cbcSMatt Macy }
168eda14cbcSMatt Macy 
169eda14cbcSMatt Macy /*
170eda14cbcSMatt Macy  * KCF software provider encrypt entry points.
171eda14cbcSMatt Macy  */
172eda14cbcSMatt Macy static int
aes_encrypt_atomic(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_spi_ctx_template_t template)173c03c5b1cSMartin Matuska aes_encrypt_atomic(crypto_mechanism_t *mechanism,
174eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
175c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
176eda14cbcSMatt Macy {
177aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
178eda14cbcSMatt Macy 	off_t saved_offset;
179eda14cbcSMatt Macy 	size_t saved_length;
180eda14cbcSMatt Macy 	size_t length_needed;
181eda14cbcSMatt Macy 	int ret;
182eda14cbcSMatt Macy 
183aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
184aca928a5SMartin Matuska 
185eda14cbcSMatt Macy 	ASSERT(ciphertext != NULL);
186eda14cbcSMatt Macy 
187c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
188eda14cbcSMatt Macy 		return (ret);
189eda14cbcSMatt Macy 
190eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
191c03c5b1cSMartin Matuska 	    KM_SLEEP, B_TRUE);
192eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
193eda14cbcSMatt Macy 		return (ret);
194eda14cbcSMatt Macy 
195eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
196eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
197eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
198eda14cbcSMatt Macy 		break;
199eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
200eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
201eda14cbcSMatt Macy 		break;
202eda14cbcSMatt Macy 	default:
20375e1fea6SMartin Matuska 		__builtin_unreachable();
204eda14cbcSMatt Macy 	}
205eda14cbcSMatt Macy 
206eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
207eda14cbcSMatt Macy 	if (ciphertext->cd_length < length_needed) {
208eda14cbcSMatt Macy 		ciphertext->cd_length = length_needed;
209eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
210eda14cbcSMatt Macy 		goto out;
211eda14cbcSMatt Macy 	}
212eda14cbcSMatt Macy 
213eda14cbcSMatt Macy 	saved_offset = ciphertext->cd_offset;
214eda14cbcSMatt Macy 	saved_length = ciphertext->cd_length;
215eda14cbcSMatt Macy 
216eda14cbcSMatt Macy 	/*
217eda14cbcSMatt Macy 	 * Do an update on the specified input data.
218eda14cbcSMatt Macy 	 */
219eda14cbcSMatt Macy 	switch (plaintext->cd_format) {
220eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
221eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, plaintext, ciphertext,
222c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
223eda14cbcSMatt Macy 		break;
224eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
225eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, plaintext, ciphertext,
226c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
227eda14cbcSMatt Macy 		break;
228eda14cbcSMatt Macy 	default:
229eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
230eda14cbcSMatt Macy 	}
231eda14cbcSMatt Macy 
232eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
233eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
234eda14cbcSMatt Macy 			ret = ccm_encrypt_final((ccm_ctx_t *)&aes_ctx,
235eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
236eda14cbcSMatt Macy 			    aes_xor_block);
237eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
238eda14cbcSMatt Macy 				goto out;
239eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
24075e1fea6SMartin Matuska 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
241eda14cbcSMatt Macy 			ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
242eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
243eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
244eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
245eda14cbcSMatt Macy 				goto out;
246eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
247eda14cbcSMatt Macy 		} else {
248eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
249eda14cbcSMatt Macy 		}
250eda14cbcSMatt Macy 
251eda14cbcSMatt Macy 		if (plaintext != ciphertext) {
252eda14cbcSMatt Macy 			ciphertext->cd_length =
253eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
254eda14cbcSMatt Macy 		}
255eda14cbcSMatt Macy 	} else {
256eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length;
257eda14cbcSMatt Macy 	}
258eda14cbcSMatt Macy 	ciphertext->cd_offset = saved_offset;
259eda14cbcSMatt Macy 
260eda14cbcSMatt Macy out:
261eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
262da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
263eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
264eda14cbcSMatt Macy 	}
26575e1fea6SMartin Matuska 	if (aes_ctx.ac_flags & GCM_MODE) {
2662a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
2677877fdebSMatt Macy 	}
268eda14cbcSMatt Macy 	return (ret);
269eda14cbcSMatt Macy }
270eda14cbcSMatt Macy 
271eda14cbcSMatt Macy static int
aes_decrypt_atomic(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_spi_ctx_template_t template)272c03c5b1cSMartin Matuska aes_decrypt_atomic(crypto_mechanism_t *mechanism,
273eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
274c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
275eda14cbcSMatt Macy {
276aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
277eda14cbcSMatt Macy 	off_t saved_offset;
278eda14cbcSMatt Macy 	size_t saved_length;
279eda14cbcSMatt Macy 	size_t length_needed;
280eda14cbcSMatt Macy 	int ret;
281eda14cbcSMatt Macy 
282aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
283aca928a5SMartin Matuska 
284eda14cbcSMatt Macy 	ASSERT(plaintext != NULL);
285eda14cbcSMatt Macy 
286c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
287eda14cbcSMatt Macy 		return (ret);
288eda14cbcSMatt Macy 
289eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
290c03c5b1cSMartin Matuska 	    KM_SLEEP, B_FALSE);
291eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
292eda14cbcSMatt Macy 		return (ret);
293eda14cbcSMatt Macy 
294eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
295eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
296eda14cbcSMatt Macy 		length_needed = aes_ctx.ac_data_len;
297eda14cbcSMatt Macy 		break;
298eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
299eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
300eda14cbcSMatt Macy 		break;
301eda14cbcSMatt Macy 	default:
30275e1fea6SMartin Matuska 		__builtin_unreachable();
303eda14cbcSMatt Macy 	}
304eda14cbcSMatt Macy 
305eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
306eda14cbcSMatt Macy 	if (plaintext->cd_length < length_needed) {
307eda14cbcSMatt Macy 		plaintext->cd_length = length_needed;
308eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
309eda14cbcSMatt Macy 		goto out;
310eda14cbcSMatt Macy 	}
311eda14cbcSMatt Macy 
312eda14cbcSMatt Macy 	saved_offset = plaintext->cd_offset;
313eda14cbcSMatt Macy 	saved_length = plaintext->cd_length;
314eda14cbcSMatt Macy 
315eda14cbcSMatt Macy 	/*
316eda14cbcSMatt Macy 	 * Do an update on the specified input data.
317eda14cbcSMatt Macy 	 */
318eda14cbcSMatt Macy 	switch (ciphertext->cd_format) {
319eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
320eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, ciphertext, plaintext,
321c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
322eda14cbcSMatt Macy 		break;
323eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
324eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, ciphertext, plaintext,
325c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
326eda14cbcSMatt Macy 		break;
327eda14cbcSMatt Macy 	default:
328eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
329eda14cbcSMatt Macy 	}
330eda14cbcSMatt Macy 
331eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
332eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
333eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_data_len
334eda14cbcSMatt Macy 			    == aes_ctx.ac_data_len);
335eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_mac_len
336eda14cbcSMatt Macy 			    == aes_ctx.ac_mac_len);
337eda14cbcSMatt Macy 			ret = ccm_decrypt_final((ccm_ctx_t *)&aes_ctx,
338eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
339eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
340eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
341eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
342eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
343eda14cbcSMatt Macy 				plaintext->cd_length =
344eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
345eda14cbcSMatt Macy 			} else {
346eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
347eda14cbcSMatt Macy 			}
34875e1fea6SMartin Matuska 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
349eda14cbcSMatt Macy 			ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
350eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
351eda14cbcSMatt Macy 			    aes_xor_block);
352eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
353eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
354eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
355eda14cbcSMatt Macy 				plaintext->cd_length =
356eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
357eda14cbcSMatt Macy 			} else {
358eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
359eda14cbcSMatt Macy 			}
36075e1fea6SMartin Matuska 		} else
36175e1fea6SMartin Matuska 			__builtin_unreachable();
362eda14cbcSMatt Macy 	} else {
363eda14cbcSMatt Macy 		plaintext->cd_length = saved_length;
364eda14cbcSMatt Macy 	}
365eda14cbcSMatt Macy 	plaintext->cd_offset = saved_offset;
366eda14cbcSMatt Macy 
367eda14cbcSMatt Macy out:
368eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
369da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
370eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
371eda14cbcSMatt Macy 	}
372eda14cbcSMatt Macy 
373eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & CCM_MODE) {
374eda14cbcSMatt Macy 		if (aes_ctx.ac_pt_buf != NULL) {
375eda14cbcSMatt Macy 			vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
376eda14cbcSMatt Macy 		}
37775e1fea6SMartin Matuska 	} else if (aes_ctx.ac_flags & GCM_MODE) {
3782a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
379eda14cbcSMatt Macy 	}
380eda14cbcSMatt Macy 
381eda14cbcSMatt Macy 	return (ret);
382eda14cbcSMatt Macy }
383eda14cbcSMatt Macy 
384eda14cbcSMatt Macy /*
385eda14cbcSMatt Macy  * KCF software provider context template entry points.
386eda14cbcSMatt Macy  */
387eda14cbcSMatt Macy static int
aes_create_ctx_template(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t * tmpl,size_t * tmpl_size)388c03c5b1cSMartin Matuska aes_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
389c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size)
390eda14cbcSMatt Macy {
391eda14cbcSMatt Macy 	void *keysched;
392eda14cbcSMatt Macy 	size_t size;
393eda14cbcSMatt Macy 	int rv;
394eda14cbcSMatt Macy 
39575e1fea6SMartin Matuska 	if (mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
39675e1fea6SMartin Matuska 	    mechanism->cm_type != AES_GCM_MECH_INFO_TYPE)
397eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
398eda14cbcSMatt Macy 
399c03c5b1cSMartin Matuska 	if ((keysched = aes_alloc_keysched(&size, KM_SLEEP)) == NULL) {
400eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
401eda14cbcSMatt Macy 	}
402eda14cbcSMatt Macy 
403eda14cbcSMatt Macy 	/*
404eda14cbcSMatt Macy 	 * Initialize key schedule.  Key length information is stored
405eda14cbcSMatt Macy 	 * in the key.
406eda14cbcSMatt Macy 	 */
407eda14cbcSMatt Macy 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
408da5137abSMartin Matuska 		memset(keysched, 0, size);
409eda14cbcSMatt Macy 		kmem_free(keysched, size);
410eda14cbcSMatt Macy 		return (rv);
411eda14cbcSMatt Macy 	}
412eda14cbcSMatt Macy 
413eda14cbcSMatt Macy 	*tmpl = keysched;
414eda14cbcSMatt Macy 	*tmpl_size = size;
415eda14cbcSMatt Macy 
416eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
417eda14cbcSMatt Macy }
418eda14cbcSMatt Macy 
419eda14cbcSMatt Macy 
420eda14cbcSMatt Macy static int
aes_free_context(crypto_ctx_t * ctx)421eda14cbcSMatt Macy aes_free_context(crypto_ctx_t *ctx)
422eda14cbcSMatt Macy {
423eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx = ctx->cc_provider_private;
424eda14cbcSMatt Macy 
425eda14cbcSMatt Macy 	if (aes_ctx != NULL) {
426eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
427eda14cbcSMatt Macy 			ASSERT(aes_ctx->ac_keysched_len != 0);
428da5137abSMartin Matuska 			memset(aes_ctx->ac_keysched, 0,
429da5137abSMartin Matuska 			    aes_ctx->ac_keysched_len);
430eda14cbcSMatt Macy 			kmem_free(aes_ctx->ac_keysched,
431eda14cbcSMatt Macy 			    aes_ctx->ac_keysched_len);
432eda14cbcSMatt Macy 		}
433eda14cbcSMatt Macy 		crypto_free_mode_ctx(aes_ctx);
434eda14cbcSMatt Macy 		ctx->cc_provider_private = NULL;
435eda14cbcSMatt Macy 	}
436eda14cbcSMatt Macy 
437eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
438eda14cbcSMatt Macy }
439eda14cbcSMatt Macy 
440eda14cbcSMatt Macy 
441eda14cbcSMatt Macy static int
aes_common_init_ctx(aes_ctx_t * aes_ctx,crypto_spi_ctx_template_t * template,crypto_mechanism_t * mechanism,crypto_key_t * key,int kmflag,boolean_t is_encrypt_init)442eda14cbcSMatt Macy aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
443eda14cbcSMatt Macy     crypto_mechanism_t *mechanism, crypto_key_t *key, int kmflag,
444eda14cbcSMatt Macy     boolean_t is_encrypt_init)
445eda14cbcSMatt Macy {
446eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
447eda14cbcSMatt Macy 	void *keysched;
448eda14cbcSMatt Macy 	size_t size = 0;
449eda14cbcSMatt Macy 
450eda14cbcSMatt Macy 	if (template == NULL) {
451eda14cbcSMatt Macy 		if ((keysched = aes_alloc_keysched(&size, kmflag)) == NULL)
452eda14cbcSMatt Macy 			return (CRYPTO_HOST_MEMORY);
453eda14cbcSMatt Macy 		/*
454eda14cbcSMatt Macy 		 * Initialize key schedule.
455eda14cbcSMatt Macy 		 * Key length is stored in the key.
456eda14cbcSMatt Macy 		 */
457eda14cbcSMatt Macy 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
458eda14cbcSMatt Macy 			kmem_free(keysched, size);
459eda14cbcSMatt Macy 			return (rv);
460eda14cbcSMatt Macy 		}
461eda14cbcSMatt Macy 
462eda14cbcSMatt Macy 		aes_ctx->ac_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
463eda14cbcSMatt Macy 		aes_ctx->ac_keysched_len = size;
464eda14cbcSMatt Macy 	} else {
465eda14cbcSMatt Macy 		keysched = template;
466eda14cbcSMatt Macy 	}
467eda14cbcSMatt Macy 	aes_ctx->ac_keysched = keysched;
468eda14cbcSMatt Macy 
469eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
470eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
471eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
472eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
473eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
474eda14cbcSMatt Macy 		}
475eda14cbcSMatt Macy 		rv = ccm_init_ctx((ccm_ctx_t *)aes_ctx, mechanism->cm_param,
476eda14cbcSMatt Macy 		    kmflag, is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
477eda14cbcSMatt Macy 		    aes_xor_block);
478eda14cbcSMatt Macy 		break;
479eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
480eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
481eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_GCM_PARAMS)) {
482eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
483eda14cbcSMatt Macy 		}
484eda14cbcSMatt Macy 		rv = gcm_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
485eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
486eda14cbcSMatt Macy 		    aes_xor_block);
487eda14cbcSMatt Macy 		break;
488eda14cbcSMatt Macy 	}
489eda14cbcSMatt Macy 
490eda14cbcSMatt Macy 	if (rv != CRYPTO_SUCCESS) {
491eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
492da5137abSMartin Matuska 			memset(keysched, 0, size);
493eda14cbcSMatt Macy 			kmem_free(keysched, size);
494eda14cbcSMatt Macy 		}
495eda14cbcSMatt Macy 	}
496eda14cbcSMatt Macy 
497eda14cbcSMatt Macy 	return (rv);
498eda14cbcSMatt Macy }
499