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