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