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