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