xref: /freebsd-src/sys/contrib/openzfs/module/icp/io/aes.c (revision 75e1fea68aaa613a20dfdcd0c59dd403aca02c49)
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_CCM */
44eda14cbcSMatt Macy 	{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
45*75e1fea6SMartin Matuska 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC},
46eda14cbcSMatt Macy 	/* AES_GCM */
47eda14cbcSMatt Macy 	{SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
48*75e1fea6SMartin Matuska 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC},
49eda14cbcSMatt Macy };
50eda14cbcSMatt Macy 
51eda14cbcSMatt Macy static int aes_common_init_ctx(aes_ctx_t *, crypto_spi_ctx_template_t *,
52eda14cbcSMatt Macy     crypto_mechanism_t *, crypto_key_t *, int, boolean_t);
53eda14cbcSMatt Macy 
54c03c5b1cSMartin Matuska static int aes_encrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
55c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
56eda14cbcSMatt Macy 
57c03c5b1cSMartin Matuska static int aes_decrypt_atomic(crypto_mechanism_t *, crypto_key_t *,
58c03c5b1cSMartin Matuska     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
59eda14cbcSMatt Macy 
60e92ffd9bSMartin Matuska static const crypto_cipher_ops_t aes_cipher_ops = {
61eda14cbcSMatt Macy 	.encrypt_atomic = aes_encrypt_atomic,
62eda14cbcSMatt Macy 	.decrypt_atomic = aes_decrypt_atomic
63eda14cbcSMatt Macy };
64eda14cbcSMatt Macy 
65c03c5b1cSMartin Matuska static int aes_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
66c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *, size_t *);
67eda14cbcSMatt Macy static int aes_free_context(crypto_ctx_t *);
68eda14cbcSMatt Macy 
69e92ffd9bSMartin Matuska static const crypto_ctx_ops_t aes_ctx_ops = {
70eda14cbcSMatt Macy 	.create_ctx_template = aes_create_ctx_template,
71eda14cbcSMatt Macy 	.free_context = aes_free_context
72eda14cbcSMatt Macy };
73eda14cbcSMatt Macy 
74c03c5b1cSMartin Matuska static const crypto_ops_t aes_crypto_ops = {
75eda14cbcSMatt Macy 	&aes_cipher_ops,
76*75e1fea6SMartin Matuska 	NULL,
77c03c5b1cSMartin Matuska 	&aes_ctx_ops,
78c03c5b1cSMartin Matuska };
79eda14cbcSMatt Macy 
80c03c5b1cSMartin Matuska static const crypto_provider_info_t aes_prov_info = {
81eda14cbcSMatt Macy 	"AES Software Provider",
82eda14cbcSMatt Macy 	&aes_crypto_ops,
83eda14cbcSMatt Macy 	sizeof (aes_mech_info_tab) / sizeof (crypto_mech_info_t),
84eda14cbcSMatt Macy 	aes_mech_info_tab
85c03c5b1cSMartin Matuska };
86eda14cbcSMatt Macy 
87eda14cbcSMatt Macy static crypto_kcf_provider_handle_t aes_prov_handle = 0;
88eda14cbcSMatt Macy 
89eda14cbcSMatt Macy int
90eda14cbcSMatt Macy aes_mod_init(void)
91eda14cbcSMatt Macy {
92eda14cbcSMatt Macy 	/* Determine the fastest available implementation. */
93eda14cbcSMatt Macy 	aes_impl_init();
94eda14cbcSMatt Macy 	gcm_impl_init();
95eda14cbcSMatt Macy 
96eda14cbcSMatt Macy 	/* Register with KCF.  If the registration fails, remove the module. */
97e92ffd9bSMartin Matuska 	if (crypto_register_provider(&aes_prov_info, &aes_prov_handle))
98eda14cbcSMatt Macy 		return (EACCES);
99eda14cbcSMatt Macy 
100eda14cbcSMatt Macy 	return (0);
101eda14cbcSMatt Macy }
102eda14cbcSMatt Macy 
103eda14cbcSMatt Macy int
104eda14cbcSMatt Macy aes_mod_fini(void)
105eda14cbcSMatt Macy {
106eda14cbcSMatt Macy 	/* Unregister from KCF if module is registered */
107eda14cbcSMatt Macy 	if (aes_prov_handle != 0) {
108eda14cbcSMatt Macy 		if (crypto_unregister_provider(aes_prov_handle))
109eda14cbcSMatt Macy 			return (EBUSY);
110eda14cbcSMatt Macy 
111eda14cbcSMatt Macy 		aes_prov_handle = 0;
112eda14cbcSMatt Macy 	}
113eda14cbcSMatt Macy 
114e92ffd9bSMartin Matuska 	return (0);
115eda14cbcSMatt Macy }
116eda14cbcSMatt Macy 
117eda14cbcSMatt Macy static int
118c03c5b1cSMartin Matuska aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
119eda14cbcSMatt Macy {
120eda14cbcSMatt Macy 	void *p = NULL;
121eda14cbcSMatt Macy 	boolean_t param_required = B_TRUE;
122eda14cbcSMatt Macy 	size_t param_len;
123eda14cbcSMatt Macy 	void *(*alloc_fun)(int);
124eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
125eda14cbcSMatt Macy 
126eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
127eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
128eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_CCM_PARAMS);
129eda14cbcSMatt Macy 		alloc_fun = ccm_alloc_ctx;
130eda14cbcSMatt Macy 		break;
131eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
132eda14cbcSMatt Macy 		param_len = sizeof (CK_AES_GCM_PARAMS);
133eda14cbcSMatt Macy 		alloc_fun = gcm_alloc_ctx;
134eda14cbcSMatt Macy 		break;
135eda14cbcSMatt Macy 	default:
136*75e1fea6SMartin Matuska 		__builtin_unreachable();
137eda14cbcSMatt Macy 	}
138eda14cbcSMatt Macy 	if (param_required && mechanism->cm_param != NULL &&
139eda14cbcSMatt Macy 	    mechanism->cm_param_len != param_len) {
140eda14cbcSMatt Macy 		rv = CRYPTO_MECHANISM_PARAM_INVALID;
141eda14cbcSMatt Macy 	}
142eda14cbcSMatt Macy 	if (ctx != NULL) {
143c03c5b1cSMartin Matuska 		p = (alloc_fun)(KM_SLEEP);
144eda14cbcSMatt Macy 		*ctx = p;
145eda14cbcSMatt Macy 	}
146eda14cbcSMatt Macy 	return (rv);
147eda14cbcSMatt Macy }
148eda14cbcSMatt Macy 
149eda14cbcSMatt Macy /*
150eda14cbcSMatt Macy  * Initialize key schedules for AES
151eda14cbcSMatt Macy  */
152eda14cbcSMatt Macy static int
153eda14cbcSMatt Macy init_keysched(crypto_key_t *key, void *newbie)
154eda14cbcSMatt Macy {
155eda14cbcSMatt Macy 	if (key->ck_length < AES_MINBITS ||
156eda14cbcSMatt Macy 	    key->ck_length > AES_MAXBITS) {
157eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
158eda14cbcSMatt Macy 	}
159eda14cbcSMatt Macy 
160eda14cbcSMatt Macy 	/* key length must be either 128, 192, or 256 */
161eda14cbcSMatt Macy 	if ((key->ck_length & 63) != 0)
162eda14cbcSMatt Macy 		return (CRYPTO_KEY_SIZE_RANGE);
163eda14cbcSMatt Macy 
164eda14cbcSMatt Macy 	aes_init_keysched(key->ck_data, key->ck_length, newbie);
165eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
166eda14cbcSMatt Macy }
167eda14cbcSMatt Macy 
168eda14cbcSMatt Macy /*
169eda14cbcSMatt Macy  * KCF software provider encrypt entry points.
170eda14cbcSMatt Macy  */
171eda14cbcSMatt Macy static int
172c03c5b1cSMartin Matuska aes_encrypt_atomic(crypto_mechanism_t *mechanism,
173eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
174c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
175eda14cbcSMatt Macy {
176aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
177eda14cbcSMatt Macy 	off_t saved_offset;
178eda14cbcSMatt Macy 	size_t saved_length;
179eda14cbcSMatt Macy 	size_t length_needed;
180eda14cbcSMatt Macy 	int ret;
181eda14cbcSMatt Macy 
182aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
183aca928a5SMartin Matuska 
184eda14cbcSMatt Macy 	ASSERT(ciphertext != NULL);
185eda14cbcSMatt Macy 
186c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
187eda14cbcSMatt Macy 		return (ret);
188eda14cbcSMatt Macy 
189eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
190c03c5b1cSMartin Matuska 	    KM_SLEEP, B_TRUE);
191eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
192eda14cbcSMatt Macy 		return (ret);
193eda14cbcSMatt Macy 
194eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
195eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
196eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
197eda14cbcSMatt Macy 		break;
198eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
199eda14cbcSMatt Macy 		length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
200eda14cbcSMatt Macy 		break;
201eda14cbcSMatt Macy 	default:
202*75e1fea6SMartin Matuska 		__builtin_unreachable();
203eda14cbcSMatt Macy 	}
204eda14cbcSMatt Macy 
205eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
206eda14cbcSMatt Macy 	if (ciphertext->cd_length < length_needed) {
207eda14cbcSMatt Macy 		ciphertext->cd_length = length_needed;
208eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
209eda14cbcSMatt Macy 		goto out;
210eda14cbcSMatt Macy 	}
211eda14cbcSMatt Macy 
212eda14cbcSMatt Macy 	saved_offset = ciphertext->cd_offset;
213eda14cbcSMatt Macy 	saved_length = ciphertext->cd_length;
214eda14cbcSMatt Macy 
215eda14cbcSMatt Macy 	/*
216eda14cbcSMatt Macy 	 * Do an update on the specified input data.
217eda14cbcSMatt Macy 	 */
218eda14cbcSMatt Macy 	switch (plaintext->cd_format) {
219eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
220eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, plaintext, ciphertext,
221c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
222eda14cbcSMatt Macy 		break;
223eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
224eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, plaintext, ciphertext,
225c03c5b1cSMartin Matuska 		    aes_encrypt_contiguous_blocks);
226eda14cbcSMatt Macy 		break;
227eda14cbcSMatt Macy 	default:
228eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
229eda14cbcSMatt Macy 	}
230eda14cbcSMatt Macy 
231eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
232eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
233eda14cbcSMatt Macy 			ret = ccm_encrypt_final((ccm_ctx_t *)&aes_ctx,
234eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
235eda14cbcSMatt Macy 			    aes_xor_block);
236eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
237eda14cbcSMatt Macy 				goto out;
238eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
239*75e1fea6SMartin Matuska 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
240eda14cbcSMatt Macy 			ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
241eda14cbcSMatt Macy 			    ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
242eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
243eda14cbcSMatt Macy 			if (ret != CRYPTO_SUCCESS)
244eda14cbcSMatt Macy 				goto out;
245eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
246eda14cbcSMatt Macy 		} else {
247eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
248eda14cbcSMatt Macy 		}
249eda14cbcSMatt Macy 
250eda14cbcSMatt Macy 		if (plaintext != ciphertext) {
251eda14cbcSMatt Macy 			ciphertext->cd_length =
252eda14cbcSMatt Macy 			    ciphertext->cd_offset - saved_offset;
253eda14cbcSMatt Macy 		}
254eda14cbcSMatt Macy 	} else {
255eda14cbcSMatt Macy 		ciphertext->cd_length = saved_length;
256eda14cbcSMatt Macy 	}
257eda14cbcSMatt Macy 	ciphertext->cd_offset = saved_offset;
258eda14cbcSMatt Macy 
259eda14cbcSMatt Macy out:
260eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
261da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
262eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
263eda14cbcSMatt Macy 	}
264*75e1fea6SMartin Matuska 	if (aes_ctx.ac_flags & GCM_MODE) {
2652a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
2667877fdebSMatt Macy 	}
267eda14cbcSMatt Macy 	return (ret);
268eda14cbcSMatt Macy }
269eda14cbcSMatt Macy 
270eda14cbcSMatt Macy static int
271c03c5b1cSMartin Matuska aes_decrypt_atomic(crypto_mechanism_t *mechanism,
272eda14cbcSMatt Macy     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
273c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t template)
274eda14cbcSMatt Macy {
275aca928a5SMartin Matuska 	aes_ctx_t aes_ctx;
276eda14cbcSMatt Macy 	off_t saved_offset;
277eda14cbcSMatt Macy 	size_t saved_length;
278eda14cbcSMatt Macy 	size_t length_needed;
279eda14cbcSMatt Macy 	int ret;
280eda14cbcSMatt Macy 
281aca928a5SMartin Matuska 	memset(&aes_ctx, 0, sizeof (aes_ctx_t));
282aca928a5SMartin Matuska 
283eda14cbcSMatt Macy 	ASSERT(plaintext != NULL);
284eda14cbcSMatt Macy 
285c03c5b1cSMartin Matuska 	if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
286eda14cbcSMatt Macy 		return (ret);
287eda14cbcSMatt Macy 
288eda14cbcSMatt Macy 	ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
289c03c5b1cSMartin Matuska 	    KM_SLEEP, B_FALSE);
290eda14cbcSMatt Macy 	if (ret != CRYPTO_SUCCESS)
291eda14cbcSMatt Macy 		return (ret);
292eda14cbcSMatt Macy 
293eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
294eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
295eda14cbcSMatt Macy 		length_needed = aes_ctx.ac_data_len;
296eda14cbcSMatt Macy 		break;
297eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
298eda14cbcSMatt Macy 		length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
299eda14cbcSMatt Macy 		break;
300eda14cbcSMatt Macy 	default:
301*75e1fea6SMartin Matuska 		__builtin_unreachable();
302eda14cbcSMatt Macy 	}
303eda14cbcSMatt Macy 
304eda14cbcSMatt Macy 	/* return size of buffer needed to store output */
305eda14cbcSMatt Macy 	if (plaintext->cd_length < length_needed) {
306eda14cbcSMatt Macy 		plaintext->cd_length = length_needed;
307eda14cbcSMatt Macy 		ret = CRYPTO_BUFFER_TOO_SMALL;
308eda14cbcSMatt Macy 		goto out;
309eda14cbcSMatt Macy 	}
310eda14cbcSMatt Macy 
311eda14cbcSMatt Macy 	saved_offset = plaintext->cd_offset;
312eda14cbcSMatt Macy 	saved_length = plaintext->cd_length;
313eda14cbcSMatt Macy 
314eda14cbcSMatt Macy 	/*
315eda14cbcSMatt Macy 	 * Do an update on the specified input data.
316eda14cbcSMatt Macy 	 */
317eda14cbcSMatt Macy 	switch (ciphertext->cd_format) {
318eda14cbcSMatt Macy 	case CRYPTO_DATA_RAW:
319eda14cbcSMatt Macy 		ret = crypto_update_iov(&aes_ctx, ciphertext, plaintext,
320c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
321eda14cbcSMatt Macy 		break;
322eda14cbcSMatt Macy 	case CRYPTO_DATA_UIO:
323eda14cbcSMatt Macy 		ret = crypto_update_uio(&aes_ctx, ciphertext, plaintext,
324c03c5b1cSMartin Matuska 		    aes_decrypt_contiguous_blocks);
325eda14cbcSMatt Macy 		break;
326eda14cbcSMatt Macy 	default:
327eda14cbcSMatt Macy 		ret = CRYPTO_ARGUMENTS_BAD;
328eda14cbcSMatt Macy 	}
329eda14cbcSMatt Macy 
330eda14cbcSMatt Macy 	if (ret == CRYPTO_SUCCESS) {
331eda14cbcSMatt Macy 		if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
332eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_data_len
333eda14cbcSMatt Macy 			    == aes_ctx.ac_data_len);
334eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_processed_mac_len
335eda14cbcSMatt Macy 			    == aes_ctx.ac_mac_len);
336eda14cbcSMatt Macy 			ret = ccm_decrypt_final((ccm_ctx_t *)&aes_ctx,
337eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
338eda14cbcSMatt Macy 			    aes_copy_block, aes_xor_block);
339eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
340eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
341eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
342eda14cbcSMatt Macy 				plaintext->cd_length =
343eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
344eda14cbcSMatt Macy 			} else {
345eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
346eda14cbcSMatt Macy 			}
347*75e1fea6SMartin Matuska 		} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
348eda14cbcSMatt Macy 			ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
349eda14cbcSMatt Macy 			    plaintext, AES_BLOCK_LEN, aes_encrypt_block,
350eda14cbcSMatt Macy 			    aes_xor_block);
351eda14cbcSMatt Macy 			ASSERT(aes_ctx.ac_remainder_len == 0);
352eda14cbcSMatt Macy 			if ((ret == CRYPTO_SUCCESS) &&
353eda14cbcSMatt Macy 			    (ciphertext != plaintext)) {
354eda14cbcSMatt Macy 				plaintext->cd_length =
355eda14cbcSMatt Macy 				    plaintext->cd_offset - saved_offset;
356eda14cbcSMatt Macy 			} else {
357eda14cbcSMatt Macy 				plaintext->cd_length = saved_length;
358eda14cbcSMatt Macy 			}
359*75e1fea6SMartin Matuska 		} else
360*75e1fea6SMartin Matuska 			__builtin_unreachable();
361eda14cbcSMatt Macy 	} else {
362eda14cbcSMatt Macy 		plaintext->cd_length = saved_length;
363eda14cbcSMatt Macy 	}
364eda14cbcSMatt Macy 	plaintext->cd_offset = saved_offset;
365eda14cbcSMatt Macy 
366eda14cbcSMatt Macy out:
367eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
368da5137abSMartin Matuska 		memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
369eda14cbcSMatt Macy 		kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
370eda14cbcSMatt Macy 	}
371eda14cbcSMatt Macy 
372eda14cbcSMatt Macy 	if (aes_ctx.ac_flags & CCM_MODE) {
373eda14cbcSMatt Macy 		if (aes_ctx.ac_pt_buf != NULL) {
374eda14cbcSMatt Macy 			vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
375eda14cbcSMatt Macy 		}
376*75e1fea6SMartin Matuska 	} else if (aes_ctx.ac_flags & GCM_MODE) {
3772a58b312SMartin Matuska 		gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
378eda14cbcSMatt Macy 	}
379eda14cbcSMatt Macy 
380eda14cbcSMatt Macy 	return (ret);
381eda14cbcSMatt Macy }
382eda14cbcSMatt Macy 
383eda14cbcSMatt Macy /*
384eda14cbcSMatt Macy  * KCF software provider context template entry points.
385eda14cbcSMatt Macy  */
386eda14cbcSMatt Macy static int
387c03c5b1cSMartin Matuska aes_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
388c03c5b1cSMartin Matuska     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size)
389eda14cbcSMatt Macy {
390eda14cbcSMatt Macy 	void *keysched;
391eda14cbcSMatt Macy 	size_t size;
392eda14cbcSMatt Macy 	int rv;
393eda14cbcSMatt Macy 
394*75e1fea6SMartin Matuska 	if (mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
395*75e1fea6SMartin Matuska 	    mechanism->cm_type != AES_GCM_MECH_INFO_TYPE)
396eda14cbcSMatt Macy 		return (CRYPTO_MECHANISM_INVALID);
397eda14cbcSMatt Macy 
398c03c5b1cSMartin Matuska 	if ((keysched = aes_alloc_keysched(&size, KM_SLEEP)) == NULL) {
399eda14cbcSMatt Macy 		return (CRYPTO_HOST_MEMORY);
400eda14cbcSMatt Macy 	}
401eda14cbcSMatt Macy 
402eda14cbcSMatt Macy 	/*
403eda14cbcSMatt Macy 	 * Initialize key schedule.  Key length information is stored
404eda14cbcSMatt Macy 	 * in the key.
405eda14cbcSMatt Macy 	 */
406eda14cbcSMatt Macy 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
407da5137abSMartin Matuska 		memset(keysched, 0, size);
408eda14cbcSMatt Macy 		kmem_free(keysched, size);
409eda14cbcSMatt Macy 		return (rv);
410eda14cbcSMatt Macy 	}
411eda14cbcSMatt Macy 
412eda14cbcSMatt Macy 	*tmpl = keysched;
413eda14cbcSMatt Macy 	*tmpl_size = size;
414eda14cbcSMatt Macy 
415eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
416eda14cbcSMatt Macy }
417eda14cbcSMatt Macy 
418eda14cbcSMatt Macy 
419eda14cbcSMatt Macy static int
420eda14cbcSMatt Macy aes_free_context(crypto_ctx_t *ctx)
421eda14cbcSMatt Macy {
422eda14cbcSMatt Macy 	aes_ctx_t *aes_ctx = ctx->cc_provider_private;
423eda14cbcSMatt Macy 
424eda14cbcSMatt Macy 	if (aes_ctx != NULL) {
425eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
426eda14cbcSMatt Macy 			ASSERT(aes_ctx->ac_keysched_len != 0);
427da5137abSMartin Matuska 			memset(aes_ctx->ac_keysched, 0,
428da5137abSMartin Matuska 			    aes_ctx->ac_keysched_len);
429eda14cbcSMatt Macy 			kmem_free(aes_ctx->ac_keysched,
430eda14cbcSMatt Macy 			    aes_ctx->ac_keysched_len);
431eda14cbcSMatt Macy 		}
432eda14cbcSMatt Macy 		crypto_free_mode_ctx(aes_ctx);
433eda14cbcSMatt Macy 		ctx->cc_provider_private = NULL;
434eda14cbcSMatt Macy 	}
435eda14cbcSMatt Macy 
436eda14cbcSMatt Macy 	return (CRYPTO_SUCCESS);
437eda14cbcSMatt Macy }
438eda14cbcSMatt Macy 
439eda14cbcSMatt Macy 
440eda14cbcSMatt Macy static int
441eda14cbcSMatt Macy aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
442eda14cbcSMatt Macy     crypto_mechanism_t *mechanism, crypto_key_t *key, int kmflag,
443eda14cbcSMatt Macy     boolean_t is_encrypt_init)
444eda14cbcSMatt Macy {
445eda14cbcSMatt Macy 	int rv = CRYPTO_SUCCESS;
446eda14cbcSMatt Macy 	void *keysched;
447eda14cbcSMatt Macy 	size_t size = 0;
448eda14cbcSMatt Macy 
449eda14cbcSMatt Macy 	if (template == NULL) {
450eda14cbcSMatt Macy 		if ((keysched = aes_alloc_keysched(&size, kmflag)) == NULL)
451eda14cbcSMatt Macy 			return (CRYPTO_HOST_MEMORY);
452eda14cbcSMatt Macy 		/*
453eda14cbcSMatt Macy 		 * Initialize key schedule.
454eda14cbcSMatt Macy 		 * Key length is stored in the key.
455eda14cbcSMatt Macy 		 */
456eda14cbcSMatt Macy 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
457eda14cbcSMatt Macy 			kmem_free(keysched, size);
458eda14cbcSMatt Macy 			return (rv);
459eda14cbcSMatt Macy 		}
460eda14cbcSMatt Macy 
461eda14cbcSMatt Macy 		aes_ctx->ac_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
462eda14cbcSMatt Macy 		aes_ctx->ac_keysched_len = size;
463eda14cbcSMatt Macy 	} else {
464eda14cbcSMatt Macy 		keysched = template;
465eda14cbcSMatt Macy 	}
466eda14cbcSMatt Macy 	aes_ctx->ac_keysched = keysched;
467eda14cbcSMatt Macy 
468eda14cbcSMatt Macy 	switch (mechanism->cm_type) {
469eda14cbcSMatt Macy 	case AES_CCM_MECH_INFO_TYPE:
470eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
471eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
472eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
473eda14cbcSMatt Macy 		}
474eda14cbcSMatt Macy 		rv = ccm_init_ctx((ccm_ctx_t *)aes_ctx, mechanism->cm_param,
475eda14cbcSMatt Macy 		    kmflag, is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
476eda14cbcSMatt Macy 		    aes_xor_block);
477eda14cbcSMatt Macy 		break;
478eda14cbcSMatt Macy 	case AES_GCM_MECH_INFO_TYPE:
479eda14cbcSMatt Macy 		if (mechanism->cm_param == NULL ||
480eda14cbcSMatt Macy 		    mechanism->cm_param_len != sizeof (CK_AES_GCM_PARAMS)) {
481eda14cbcSMatt Macy 			return (CRYPTO_MECHANISM_PARAM_INVALID);
482eda14cbcSMatt Macy 		}
483eda14cbcSMatt Macy 		rv = gcm_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
484eda14cbcSMatt Macy 		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
485eda14cbcSMatt Macy 		    aes_xor_block);
486eda14cbcSMatt Macy 		break;
487eda14cbcSMatt Macy 	}
488eda14cbcSMatt Macy 
489eda14cbcSMatt Macy 	if (rv != CRYPTO_SUCCESS) {
490eda14cbcSMatt Macy 		if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
491da5137abSMartin Matuska 			memset(keysched, 0, size);
492eda14cbcSMatt Macy 			kmem_free(keysched, size);
493eda14cbcSMatt Macy 		}
494eda14cbcSMatt Macy 	}
495eda14cbcSMatt Macy 
496eda14cbcSMatt Macy 	return (rv);
497eda14cbcSMatt Macy }
498