10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52530Spwernau * Common Development and Distribution License (the "License").
62530Spwernau * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12856SZdenek.Kotala@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * AES provider for the Kernel Cryptographic Framework (KCF)
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/systm.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <sys/cmn_err.h>
330Sstevel@tonic-gate #include <sys/ddi.h>
340Sstevel@tonic-gate #include <sys/crypto/common.h>
357188Smcpowers #include <sys/crypto/impl.h>
360Sstevel@tonic-gate #include <sys/crypto/spi.h>
370Sstevel@tonic-gate #include <sys/sysmacros.h>
380Sstevel@tonic-gate #include <sys/strsun.h>
397188Smcpowers #include <modes/modes.h>
4010500SHai-May.Chao@Sun.COM #define _AES_FIPS_POST
4110500SHai-May.Chao@Sun.COM #define _AES_IMPL
427188Smcpowers #include <aes/aes_impl.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate extern struct mod_ops mod_cryptoops;
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * Module linkage information for the kernel.
480Sstevel@tonic-gate */
490Sstevel@tonic-gate static struct modlcrypto modlcrypto = {
500Sstevel@tonic-gate &mod_cryptoops,
515072Smcpowers "AES Kernel SW Provider"
520Sstevel@tonic-gate };
530Sstevel@tonic-gate
540Sstevel@tonic-gate static struct modlinkage modlinkage = {
550Sstevel@tonic-gate MODREV_1,
560Sstevel@tonic-gate (void *)&modlcrypto,
570Sstevel@tonic-gate NULL
580Sstevel@tonic-gate };
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * The following definitions are to keep EXPORT_SRC happy.
620Sstevel@tonic-gate */
632530Spwernau #ifndef AES_MIN_KEY_BYTES
642530Spwernau #define AES_MIN_KEY_BYTES 0
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate
672530Spwernau #ifndef AES_MAX_KEY_BYTES
682530Spwernau #define AES_MAX_KEY_BYTES 0
690Sstevel@tonic-gate #endif
700Sstevel@tonic-gate
710Sstevel@tonic-gate /*
720Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration.
730Sstevel@tonic-gate */
740Sstevel@tonic-gate static crypto_mech_info_t aes_mech_info_tab[] = {
750Sstevel@tonic-gate /* AES_ECB */
760Sstevel@tonic-gate {SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
770Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
780Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
792530Spwernau AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
800Sstevel@tonic-gate /* AES_CBC */
810Sstevel@tonic-gate {SUN_CKM_AES_CBC, AES_CBC_MECH_INFO_TYPE,
820Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
830Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
842530Spwernau AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
85904Smcpowers /* AES_CTR */
86904Smcpowers {SUN_CKM_AES_CTR, AES_CTR_MECH_INFO_TYPE,
87904Smcpowers CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
88904Smcpowers CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
894486Sktung AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
904486Sktung /* AES_CCM */
914486Sktung {SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
924486Sktung CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
934486Sktung CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
948005SMark.Powers@Sun.COM AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
958005SMark.Powers@Sun.COM /* AES_GCM */
968005SMark.Powers@Sun.COM {SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
978005SMark.Powers@Sun.COM CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
988005SMark.Powers@Sun.COM CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
999339SMark.Powers@Sun.COM AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
1009339SMark.Powers@Sun.COM /* AES_GMAC */
1019339SMark.Powers@Sun.COM {SUN_CKM_AES_GMAC, AES_GMAC_MECH_INFO_TYPE,
1029339SMark.Powers@Sun.COM CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
1039339SMark.Powers@Sun.COM CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
1049339SMark.Powers@Sun.COM CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
1059339SMark.Powers@Sun.COM CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
1069339SMark.Powers@Sun.COM CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
1072530Spwernau AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES}
1080Sstevel@tonic-gate };
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */
1110Sstevel@tonic-gate #define AES_ARG_INPLACE(input, output) \
1120Sstevel@tonic-gate if ((output) == NULL) \
1130Sstevel@tonic-gate (output) = (input);
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate static void aes_provider_status(crypto_provider_handle_t, uint_t *);
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate static crypto_control_ops_t aes_control_ops = {
1180Sstevel@tonic-gate aes_provider_status
1190Sstevel@tonic-gate };
1200Sstevel@tonic-gate
1214486Sktung static int aes_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
1224486Sktung crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1234486Sktung static int aes_decrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
1240Sstevel@tonic-gate crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1254486Sktung static int aes_common_init(crypto_ctx_t *, crypto_mechanism_t *,
1264486Sktung crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t, boolean_t);
1270Sstevel@tonic-gate static int aes_common_init_ctx(aes_ctx_t *, crypto_spi_ctx_template_t *,
1284486Sktung crypto_mechanism_t *, crypto_key_t *, int, boolean_t);
1290Sstevel@tonic-gate static int aes_encrypt_final(crypto_ctx_t *, crypto_data_t *,
1300Sstevel@tonic-gate crypto_req_handle_t);
1310Sstevel@tonic-gate static int aes_decrypt_final(crypto_ctx_t *, crypto_data_t *,
1320Sstevel@tonic-gate crypto_req_handle_t);
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate static int aes_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1350Sstevel@tonic-gate crypto_req_handle_t);
1360Sstevel@tonic-gate static int aes_encrypt_update(crypto_ctx_t *, crypto_data_t *,
1370Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t);
1380Sstevel@tonic-gate static int aes_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1390Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1400Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate static int aes_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1430Sstevel@tonic-gate crypto_req_handle_t);
1440Sstevel@tonic-gate static int aes_decrypt_update(crypto_ctx_t *, crypto_data_t *,
1450Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t);
1460Sstevel@tonic-gate static int aes_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
1470Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
1480Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate static crypto_cipher_ops_t aes_cipher_ops = {
1514486Sktung aes_encrypt_init,
1520Sstevel@tonic-gate aes_encrypt,
1530Sstevel@tonic-gate aes_encrypt_update,
1540Sstevel@tonic-gate aes_encrypt_final,
1550Sstevel@tonic-gate aes_encrypt_atomic,
1564486Sktung aes_decrypt_init,
1570Sstevel@tonic-gate aes_decrypt,
1580Sstevel@tonic-gate aes_decrypt_update,
1590Sstevel@tonic-gate aes_decrypt_final,
1600Sstevel@tonic-gate aes_decrypt_atomic
1610Sstevel@tonic-gate };
1620Sstevel@tonic-gate
1639339SMark.Powers@Sun.COM static int aes_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
1649339SMark.Powers@Sun.COM crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
1659339SMark.Powers@Sun.COM crypto_spi_ctx_template_t, crypto_req_handle_t);
1669339SMark.Powers@Sun.COM static int aes_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
1679339SMark.Powers@Sun.COM crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
1689339SMark.Powers@Sun.COM crypto_spi_ctx_template_t, crypto_req_handle_t);
1699339SMark.Powers@Sun.COM
1709339SMark.Powers@Sun.COM static crypto_mac_ops_t aes_mac_ops = {
1719339SMark.Powers@Sun.COM NULL,
1729339SMark.Powers@Sun.COM NULL,
1739339SMark.Powers@Sun.COM NULL,
1749339SMark.Powers@Sun.COM NULL,
1759339SMark.Powers@Sun.COM aes_mac_atomic,
1769339SMark.Powers@Sun.COM aes_mac_verify_atomic
1779339SMark.Powers@Sun.COM };
1789339SMark.Powers@Sun.COM
1790Sstevel@tonic-gate static int aes_create_ctx_template(crypto_provider_handle_t,
1800Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
1810Sstevel@tonic-gate size_t *, crypto_req_handle_t);
1820Sstevel@tonic-gate static int aes_free_context(crypto_ctx_t *);
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate static crypto_ctx_ops_t aes_ctx_ops = {
1850Sstevel@tonic-gate aes_create_ctx_template,
1860Sstevel@tonic-gate aes_free_context
1870Sstevel@tonic-gate };
1880Sstevel@tonic-gate
18910732SAnthony.Scarpino@Sun.COM static void aes_POST(int *);
19010732SAnthony.Scarpino@Sun.COM
19110732SAnthony.Scarpino@Sun.COM static crypto_fips140_ops_t aes_fips140_ops = {
19210732SAnthony.Scarpino@Sun.COM aes_POST
19310732SAnthony.Scarpino@Sun.COM };
19410732SAnthony.Scarpino@Sun.COM
1950Sstevel@tonic-gate static crypto_ops_t aes_crypto_ops = {
1960Sstevel@tonic-gate &aes_control_ops,
1970Sstevel@tonic-gate NULL,
1980Sstevel@tonic-gate &aes_cipher_ops,
1999339SMark.Powers@Sun.COM &aes_mac_ops,
2000Sstevel@tonic-gate NULL,
2010Sstevel@tonic-gate NULL,
2020Sstevel@tonic-gate NULL,
2030Sstevel@tonic-gate NULL,
2040Sstevel@tonic-gate NULL,
2050Sstevel@tonic-gate NULL,
2060Sstevel@tonic-gate NULL,
2070Sstevel@tonic-gate NULL,
2080Sstevel@tonic-gate NULL,
20910732SAnthony.Scarpino@Sun.COM &aes_ctx_ops,
21010732SAnthony.Scarpino@Sun.COM NULL,
21110732SAnthony.Scarpino@Sun.COM NULL,
21210732SAnthony.Scarpino@Sun.COM &aes_fips140_ops
2130Sstevel@tonic-gate };
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate static crypto_provider_info_t aes_prov_info = {
21610732SAnthony.Scarpino@Sun.COM CRYPTO_SPI_VERSION_4,
2170Sstevel@tonic-gate "AES Software Provider",
2180Sstevel@tonic-gate CRYPTO_SW_PROVIDER,
2190Sstevel@tonic-gate {&modlinkage},
2200Sstevel@tonic-gate NULL,
2210Sstevel@tonic-gate &aes_crypto_ops,
2220Sstevel@tonic-gate sizeof (aes_mech_info_tab)/sizeof (crypto_mech_info_t),
2230Sstevel@tonic-gate aes_mech_info_tab
2240Sstevel@tonic-gate };
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate static crypto_kcf_provider_handle_t aes_prov_handle = NULL;
2279339SMark.Powers@Sun.COM static crypto_data_t null_crypto_data = { CRYPTO_DATA_RAW };
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate int
_init(void)2300Sstevel@tonic-gate _init(void)
2310Sstevel@tonic-gate {
2320Sstevel@tonic-gate int ret;
2330Sstevel@tonic-gate
23411751SAnthony.Scarpino@Sun.COM if ((ret = mod_install(&modlinkage)) != 0)
23511751SAnthony.Scarpino@Sun.COM return (ret);
23611751SAnthony.Scarpino@Sun.COM
23711751SAnthony.Scarpino@Sun.COM /* Register with KCF. If the registration fails, remove the module. */
23811751SAnthony.Scarpino@Sun.COM if (crypto_register_provider(&aes_prov_info, &aes_prov_handle)) {
23911751SAnthony.Scarpino@Sun.COM (void) mod_remove(&modlinkage);
2400Sstevel@tonic-gate return (EACCES);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
24311751SAnthony.Scarpino@Sun.COM return (0);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate int
_fini(void)2470Sstevel@tonic-gate _fini(void)
2480Sstevel@tonic-gate {
24911751SAnthony.Scarpino@Sun.COM /* Unregister from KCF if module is registered */
2500Sstevel@tonic-gate if (aes_prov_handle != NULL) {
25111751SAnthony.Scarpino@Sun.COM if (crypto_unregister_provider(aes_prov_handle))
2520Sstevel@tonic-gate return (EBUSY);
25311751SAnthony.Scarpino@Sun.COM
2540Sstevel@tonic-gate aes_prov_handle = NULL;
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate return (mod_remove(&modlinkage));
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2610Sstevel@tonic-gate _info(struct modinfo *modinfop)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate
267991Smcpowers static int
aes_check_mech_param(crypto_mechanism_t * mechanism,aes_ctx_t ** ctx,int kmflag)2687188Smcpowers aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx, int kmflag)
269991Smcpowers {
2707188Smcpowers void *p = NULL;
2719339SMark.Powers@Sun.COM boolean_t param_required = B_TRUE;
2729339SMark.Powers@Sun.COM size_t param_len;
2739339SMark.Powers@Sun.COM void *(*alloc_fun)(int);
274991Smcpowers int rv = CRYPTO_SUCCESS;
275991Smcpowers
276991Smcpowers switch (mechanism->cm_type) {
277991Smcpowers case AES_ECB_MECH_INFO_TYPE:
2789339SMark.Powers@Sun.COM param_required = B_FALSE;
2799339SMark.Powers@Sun.COM alloc_fun = ecb_alloc_ctx;
280991Smcpowers break;
281991Smcpowers case AES_CBC_MECH_INFO_TYPE:
2829339SMark.Powers@Sun.COM param_len = AES_BLOCK_LEN;
2839339SMark.Powers@Sun.COM alloc_fun = cbc_alloc_ctx;
284991Smcpowers break;
285991Smcpowers case AES_CTR_MECH_INFO_TYPE:
2869339SMark.Powers@Sun.COM param_len = sizeof (CK_AES_CTR_PARAMS);
2879339SMark.Powers@Sun.COM alloc_fun = ctr_alloc_ctx;
288991Smcpowers break;
2894486Sktung case AES_CCM_MECH_INFO_TYPE:
2909339SMark.Powers@Sun.COM param_len = sizeof (CK_AES_CCM_PARAMS);
2919339SMark.Powers@Sun.COM alloc_fun = ccm_alloc_ctx;
2924486Sktung break;
2938005SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
2949339SMark.Powers@Sun.COM param_len = sizeof (CK_AES_GCM_PARAMS);
2959339SMark.Powers@Sun.COM alloc_fun = gcm_alloc_ctx;
2969339SMark.Powers@Sun.COM break;
2979339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
2989339SMark.Powers@Sun.COM param_len = sizeof (CK_AES_GMAC_PARAMS);
2999339SMark.Powers@Sun.COM alloc_fun = gmac_alloc_ctx;
3008005SMark.Powers@Sun.COM break;
301991Smcpowers default:
302991Smcpowers rv = CRYPTO_MECHANISM_INVALID;
303*12856SZdenek.Kotala@Sun.COM return (rv);
304991Smcpowers }
3059339SMark.Powers@Sun.COM if (param_required && mechanism->cm_param != NULL &&
3069339SMark.Powers@Sun.COM mechanism->cm_param_len != param_len) {
3079339SMark.Powers@Sun.COM rv = CRYPTO_MECHANISM_PARAM_INVALID;
3089339SMark.Powers@Sun.COM }
3099339SMark.Powers@Sun.COM if (ctx != NULL) {
3109339SMark.Powers@Sun.COM p = (alloc_fun)(kmflag);
3117188Smcpowers *ctx = p;
3129339SMark.Powers@Sun.COM }
313991Smcpowers return (rv);
314991Smcpowers }
315991Smcpowers
3161010Smcpowers /* EXPORT DELETE START */
3171010Smcpowers
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate * Initialize key schedules for AES
3200Sstevel@tonic-gate */
3210Sstevel@tonic-gate static int
init_keysched(crypto_key_t * key,void * newbie)3220Sstevel@tonic-gate init_keysched(crypto_key_t *key, void *newbie)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * Only keys by value are supported by this module.
3260Sstevel@tonic-gate */
3270Sstevel@tonic-gate switch (key->ck_format) {
3280Sstevel@tonic-gate case CRYPTO_KEY_RAW:
3290Sstevel@tonic-gate if (key->ck_length < AES_MINBITS ||
3300Sstevel@tonic-gate key->ck_length > AES_MAXBITS) {
3310Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /* key length must be either 128, 192, or 256 */
3350Sstevel@tonic-gate if ((key->ck_length & 63) != 0)
3360Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE);
3370Sstevel@tonic-gate break;
3380Sstevel@tonic-gate default:
3390Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT);
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate aes_init_keysched(key->ck_data, key->ck_length, newbie);
3430Sstevel@tonic-gate return (CRYPTO_SUCCESS);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate /* EXPORT DELETE END */
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /*
3490Sstevel@tonic-gate * KCF software provider control entry points.
3500Sstevel@tonic-gate */
3510Sstevel@tonic-gate /* ARGSUSED */
3520Sstevel@tonic-gate static void
aes_provider_status(crypto_provider_handle_t provider,uint_t * status)3530Sstevel@tonic-gate aes_provider_status(crypto_provider_handle_t provider, uint_t *status)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY;
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3584486Sktung static int
aes_encrypt_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req)3594486Sktung aes_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3604486Sktung crypto_key_t *key, crypto_spi_ctx_template_t template,
3614486Sktung crypto_req_handle_t req) {
3624486Sktung return (aes_common_init(ctx, mechanism, key, template, req, B_TRUE));
3634486Sktung }
3644486Sktung
3654486Sktung static int
aes_decrypt_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req)3664486Sktung aes_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3674486Sktung crypto_key_t *key, crypto_spi_ctx_template_t template,
3684486Sktung crypto_req_handle_t req) {
3694486Sktung return (aes_common_init(ctx, mechanism, key, template, req, B_FALSE));
3704486Sktung }
3714486Sktung
3724486Sktung
3734486Sktung
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate * KCF software provider encrypt entry points.
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate static int
aes_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t template,crypto_req_handle_t req,boolean_t is_encrypt_init)3780Sstevel@tonic-gate aes_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3790Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t template,
3804486Sktung crypto_req_handle_t req, boolean_t is_encrypt_init)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /* EXPORT DELETE START */
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate aes_ctx_t *aes_ctx;
3860Sstevel@tonic-gate int rv;
3870Sstevel@tonic-gate int kmflag;
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate * Only keys by value are supported by this module.
3910Sstevel@tonic-gate */
3920Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) {
3930Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate
3967188Smcpowers kmflag = crypto_kmflag(req);
3977188Smcpowers if ((rv = aes_check_mech_param(mechanism, &aes_ctx, kmflag))
3987188Smcpowers != CRYPTO_SUCCESS)
399991Smcpowers return (rv);
4000Sstevel@tonic-gate
4014486Sktung rv = aes_common_init_ctx(aes_ctx, template, mechanism, key, kmflag,
4024486Sktung is_encrypt_init);
4030Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) {
4047188Smcpowers crypto_free_mode_ctx(aes_ctx);
4050Sstevel@tonic-gate return (rv);
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate ctx->cc_provider_private = aes_ctx;
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate /* EXPORT DELETE END */
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate return (CRYPTO_SUCCESS);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate
4157188Smcpowers static void
aes_copy_block64(uint8_t * in,uint64_t * out)4167188Smcpowers aes_copy_block64(uint8_t *in, uint64_t *out)
4170Sstevel@tonic-gate {
4187188Smcpowers if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
4197188Smcpowers /* LINTED: pointer alignment */
4207188Smcpowers out[0] = *(uint64_t *)&in[0];
4217188Smcpowers /* LINTED: pointer alignment */
4227188Smcpowers out[1] = *(uint64_t *)&in[8];
4237188Smcpowers } else {
4247188Smcpowers uint8_t *iv8 = (uint8_t *)&out[0];
4250Sstevel@tonic-gate
4267188Smcpowers AES_COPY_BLOCK(in, iv8);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate
4309392Sopensolaris@drydog.com
4310Sstevel@tonic-gate static int
aes_encrypt(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)4320Sstevel@tonic-gate aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
4330Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate int ret = CRYPTO_FAILED;
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /* EXPORT DELETE START */
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate aes_ctx_t *aes_ctx;
4404486Sktung size_t saved_length, saved_offset, length_needed;
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
4430Sstevel@tonic-gate aes_ctx = ctx->cc_provider_private;
4440Sstevel@tonic-gate
445904Smcpowers /*
446904Smcpowers * For block ciphers, plaintext must be a multiple of AES block size.
447904Smcpowers * This test is only valid for ciphers whose blocksize is a power of 2.
448904Smcpowers */
4499339SMark.Powers@Sun.COM if (((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE))
4509339SMark.Powers@Sun.COM == 0) && (plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
451904Smcpowers return (CRYPTO_DATA_LEN_RANGE);
452904Smcpowers
4530Sstevel@tonic-gate AES_ARG_INPLACE(plaintext, ciphertext);
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate * We need to just return the length needed to store the output.
4570Sstevel@tonic-gate * We should not destroy the context for the following case.
4580Sstevel@tonic-gate */
4599339SMark.Powers@Sun.COM switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
4609339SMark.Powers@Sun.COM case CCM_MODE:
4617188Smcpowers length_needed = plaintext->cd_length + aes_ctx->ac_mac_len;
4629339SMark.Powers@Sun.COM break;
4639339SMark.Powers@Sun.COM case GCM_MODE:
4648195SMark.Powers@Sun.COM length_needed = plaintext->cd_length + aes_ctx->ac_tag_len;
4659339SMark.Powers@Sun.COM break;
4669339SMark.Powers@Sun.COM case GMAC_MODE:
4679339SMark.Powers@Sun.COM if (plaintext->cd_length != 0)
4689339SMark.Powers@Sun.COM return (CRYPTO_ARGUMENTS_BAD);
4699339SMark.Powers@Sun.COM
4709339SMark.Powers@Sun.COM length_needed = aes_ctx->ac_tag_len;
4719339SMark.Powers@Sun.COM break;
4729339SMark.Powers@Sun.COM default:
4734486Sktung length_needed = plaintext->cd_length;
4744486Sktung }
4754486Sktung
4764486Sktung if (ciphertext->cd_length < length_needed) {
4774486Sktung ciphertext->cd_length = length_needed;
4780Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4814486Sktung saved_length = ciphertext->cd_length;
4824486Sktung saved_offset = ciphertext->cd_offset;
4834486Sktung
4840Sstevel@tonic-gate /*
4850Sstevel@tonic-gate * Do an update on the specified input data.
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate ret = aes_encrypt_update(ctx, plaintext, ciphertext, req);
4884486Sktung if (ret != CRYPTO_SUCCESS) {
4894486Sktung return (ret);
4904486Sktung }
4914486Sktung
4924486Sktung /*
4934486Sktung * For CCM mode, aes_ccm_encrypt_final() will take care of any
4944486Sktung * left-over unprocessed data, and compute the MAC
4954486Sktung */
4967188Smcpowers if (aes_ctx->ac_flags & CCM_MODE) {
4974486Sktung /*
4988005SMark.Powers@Sun.COM * ccm_encrypt_final() will compute the MAC and append
4994486Sktung * it to existing ciphertext. So, need to adjust the left over
5004486Sktung * length value accordingly
5014486Sktung */
5024486Sktung
5034486Sktung /* order of following 2 lines MUST not be reversed */
5044486Sktung ciphertext->cd_offset = ciphertext->cd_length;
5054486Sktung ciphertext->cd_length = saved_length - ciphertext->cd_length;
5067188Smcpowers ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, ciphertext,
5077188Smcpowers AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
5084486Sktung if (ret != CRYPTO_SUCCESS) {
5094486Sktung return (ret);
5104486Sktung }
5114486Sktung
5124486Sktung if (plaintext != ciphertext) {
5134486Sktung ciphertext->cd_length =
5144486Sktung ciphertext->cd_offset - saved_offset;
5154486Sktung }
5164486Sktung ciphertext->cd_offset = saved_offset;
5179339SMark.Powers@Sun.COM } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
5188005SMark.Powers@Sun.COM /*
5198005SMark.Powers@Sun.COM * gcm_encrypt_final() will compute the MAC and append
5208005SMark.Powers@Sun.COM * it to existing ciphertext. So, need to adjust the left over
5218005SMark.Powers@Sun.COM * length value accordingly
5228005SMark.Powers@Sun.COM */
5238005SMark.Powers@Sun.COM
5248005SMark.Powers@Sun.COM /* order of following 2 lines MUST not be reversed */
5258005SMark.Powers@Sun.COM ciphertext->cd_offset = ciphertext->cd_length;
5268005SMark.Powers@Sun.COM ciphertext->cd_length = saved_length - ciphertext->cd_length;
5278005SMark.Powers@Sun.COM ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, ciphertext,
5288005SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
5298005SMark.Powers@Sun.COM aes_xor_block);
5308005SMark.Powers@Sun.COM if (ret != CRYPTO_SUCCESS) {
5318005SMark.Powers@Sun.COM return (ret);
5328005SMark.Powers@Sun.COM }
5338005SMark.Powers@Sun.COM
5348005SMark.Powers@Sun.COM if (plaintext != ciphertext) {
5358005SMark.Powers@Sun.COM ciphertext->cd_length =
5368005SMark.Powers@Sun.COM ciphertext->cd_offset - saved_offset;
5378005SMark.Powers@Sun.COM }
5388005SMark.Powers@Sun.COM ciphertext->cd_offset = saved_offset;
5394486Sktung }
5404486Sktung
5410Sstevel@tonic-gate ASSERT(aes_ctx->ac_remainder_len == 0);
5420Sstevel@tonic-gate (void) aes_free_context(ctx);
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate /* EXPORT DELETE END */
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate return (ret);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5499392Sopensolaris@drydog.com
5500Sstevel@tonic-gate static int
aes_decrypt(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)5510Sstevel@tonic-gate aes_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
5520Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req)
5530Sstevel@tonic-gate {
5540Sstevel@tonic-gate int ret = CRYPTO_FAILED;
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate /* EXPORT DELETE START */
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate aes_ctx_t *aes_ctx;
5594486Sktung off_t saved_offset;
5609339SMark.Powers@Sun.COM size_t saved_length, length_needed;
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
5630Sstevel@tonic-gate aes_ctx = ctx->cc_provider_private;
5640Sstevel@tonic-gate
565904Smcpowers /*
5664486Sktung * For block ciphers, plaintext must be a multiple of AES block size.
567904Smcpowers * This test is only valid for ciphers whose blocksize is a power of 2.
568904Smcpowers */
5699339SMark.Powers@Sun.COM if (((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE))
5709339SMark.Powers@Sun.COM == 0) && (ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0) {
5714558Sktung return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
5724558Sktung }
573904Smcpowers
5740Sstevel@tonic-gate AES_ARG_INPLACE(ciphertext, plaintext);
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate /*
5779339SMark.Powers@Sun.COM * Return length needed to store the output.
5789339SMark.Powers@Sun.COM * Do not destroy context when plaintext buffer is too small.
5794486Sktung *
5809339SMark.Powers@Sun.COM * CCM: plaintext is MAC len smaller than cipher text
5819339SMark.Powers@Sun.COM * GCM: plaintext is TAG len smaller than cipher text
5829339SMark.Powers@Sun.COM * GMAC: plaintext length must be zero
5830Sstevel@tonic-gate */
5849339SMark.Powers@Sun.COM switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
5859339SMark.Powers@Sun.COM case CCM_MODE:
5869339SMark.Powers@Sun.COM length_needed = aes_ctx->ac_processed_data_len;
5879339SMark.Powers@Sun.COM break;
5889339SMark.Powers@Sun.COM case GCM_MODE:
5899339SMark.Powers@Sun.COM length_needed = ciphertext->cd_length - aes_ctx->ac_tag_len;
5909339SMark.Powers@Sun.COM break;
5919339SMark.Powers@Sun.COM case GMAC_MODE:
5929339SMark.Powers@Sun.COM if (plaintext->cd_length != 0)
5939339SMark.Powers@Sun.COM return (CRYPTO_ARGUMENTS_BAD);
5948005SMark.Powers@Sun.COM
5959339SMark.Powers@Sun.COM length_needed = 0;
5969339SMark.Powers@Sun.COM break;
5979339SMark.Powers@Sun.COM default:
5989339SMark.Powers@Sun.COM length_needed = ciphertext->cd_length;
5999339SMark.Powers@Sun.COM }
6009339SMark.Powers@Sun.COM
6019339SMark.Powers@Sun.COM if (plaintext->cd_length < length_needed) {
6029339SMark.Powers@Sun.COM plaintext->cd_length = length_needed;
6030Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6069339SMark.Powers@Sun.COM saved_offset = plaintext->cd_offset;
6079339SMark.Powers@Sun.COM saved_length = plaintext->cd_length;
6089339SMark.Powers@Sun.COM
6090Sstevel@tonic-gate /*
6100Sstevel@tonic-gate * Do an update on the specified input data.
6110Sstevel@tonic-gate */
6120Sstevel@tonic-gate ret = aes_decrypt_update(ctx, ciphertext, plaintext, req);
6134486Sktung if (ret != CRYPTO_SUCCESS) {
6144486Sktung goto cleanup;
6154486Sktung }
6164486Sktung
6177188Smcpowers if (aes_ctx->ac_flags & CCM_MODE) {
6187188Smcpowers ASSERT(aes_ctx->ac_processed_data_len == aes_ctx->ac_data_len);
6197188Smcpowers ASSERT(aes_ctx->ac_processed_mac_len == aes_ctx->ac_mac_len);
6204486Sktung
6214486Sktung /* order of following 2 lines MUST not be reversed */
6224486Sktung plaintext->cd_offset = plaintext->cd_length;
6234486Sktung plaintext->cd_length = saved_length - plaintext->cd_length;
6244486Sktung
6257188Smcpowers ret = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, plaintext,
6267188Smcpowers AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
6277188Smcpowers aes_xor_block);
6284486Sktung if (ret == CRYPTO_SUCCESS) {
6294486Sktung if (plaintext != ciphertext) {
6304486Sktung plaintext->cd_length =
6314486Sktung plaintext->cd_offset - saved_offset;
6324486Sktung }
6334486Sktung } else {
6344486Sktung plaintext->cd_length = saved_length;
6354486Sktung }
6364486Sktung
6374486Sktung plaintext->cd_offset = saved_offset;
6389339SMark.Powers@Sun.COM } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
6398005SMark.Powers@Sun.COM /* order of following 2 lines MUST not be reversed */
6408005SMark.Powers@Sun.COM plaintext->cd_offset = plaintext->cd_length;
6418005SMark.Powers@Sun.COM plaintext->cd_length = saved_length - plaintext->cd_length;
6428005SMark.Powers@Sun.COM
6438005SMark.Powers@Sun.COM ret = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, plaintext,
6448005SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
6458005SMark.Powers@Sun.COM if (ret == CRYPTO_SUCCESS) {
6468005SMark.Powers@Sun.COM if (plaintext != ciphertext) {
6478005SMark.Powers@Sun.COM plaintext->cd_length =
6488005SMark.Powers@Sun.COM plaintext->cd_offset - saved_offset;
6498005SMark.Powers@Sun.COM }
6508005SMark.Powers@Sun.COM } else {
6518005SMark.Powers@Sun.COM plaintext->cd_length = saved_length;
6528005SMark.Powers@Sun.COM }
6538005SMark.Powers@Sun.COM
6548005SMark.Powers@Sun.COM plaintext->cd_offset = saved_offset;
6554486Sktung }
6564486Sktung
6570Sstevel@tonic-gate ASSERT(aes_ctx->ac_remainder_len == 0);
6584486Sktung
6594486Sktung cleanup:
6600Sstevel@tonic-gate (void) aes_free_context(ctx);
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate /* EXPORT DELETE END */
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate return (ret);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate
6679392Sopensolaris@drydog.com
6680Sstevel@tonic-gate /* ARGSUSED */
6690Sstevel@tonic-gate static int
aes_encrypt_update(crypto_ctx_t * ctx,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_req_handle_t req)6700Sstevel@tonic-gate aes_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
6710Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req)
6720Sstevel@tonic-gate {
6730Sstevel@tonic-gate off_t saved_offset;
6740Sstevel@tonic-gate size_t saved_length, out_len;
6750Sstevel@tonic-gate int ret = CRYPTO_SUCCESS;
676904Smcpowers aes_ctx_t *aes_ctx;
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
6797188Smcpowers aes_ctx = ctx->cc_provider_private;
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate AES_ARG_INPLACE(plaintext, ciphertext);
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate /* compute number of bytes that will hold the ciphertext */
6847188Smcpowers out_len = aes_ctx->ac_remainder_len;
6850Sstevel@tonic-gate out_len += plaintext->cd_length;
6860Sstevel@tonic-gate out_len &= ~(AES_BLOCK_LEN - 1);
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate /* return length needed to store the output */
6890Sstevel@tonic-gate if (ciphertext->cd_length < out_len) {
6900Sstevel@tonic-gate ciphertext->cd_length = out_len;
6910Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate saved_offset = ciphertext->cd_offset;
6950Sstevel@tonic-gate saved_length = ciphertext->cd_length;
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate /*
6980Sstevel@tonic-gate * Do the AES update on the specified input data.
6990Sstevel@tonic-gate */
7000Sstevel@tonic-gate switch (plaintext->cd_format) {
7010Sstevel@tonic-gate case CRYPTO_DATA_RAW:
7027188Smcpowers ret = crypto_update_iov(ctx->cc_provider_private,
7037188Smcpowers plaintext, ciphertext, aes_encrypt_contiguous_blocks,
7047188Smcpowers aes_copy_block64);
7050Sstevel@tonic-gate break;
7060Sstevel@tonic-gate case CRYPTO_DATA_UIO:
7077188Smcpowers ret = crypto_update_uio(ctx->cc_provider_private,
7087188Smcpowers plaintext, ciphertext, aes_encrypt_contiguous_blocks,
7097188Smcpowers aes_copy_block64);
7100Sstevel@tonic-gate break;
7110Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
7127188Smcpowers ret = crypto_update_mp(ctx->cc_provider_private,
7137188Smcpowers plaintext, ciphertext, aes_encrypt_contiguous_blocks,
7147188Smcpowers aes_copy_block64);
7150Sstevel@tonic-gate break;
7160Sstevel@tonic-gate default:
7170Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate
720904Smcpowers /*
721904Smcpowers * Since AES counter mode is a stream cipher, we call
7227188Smcpowers * ctr_mode_final() to pick up any remaining bytes.
723904Smcpowers * It is an internal function that does not destroy
724904Smcpowers * the context like *normal* final routines.
725904Smcpowers */
7267188Smcpowers if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
7277188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)aes_ctx,
7287188Smcpowers ciphertext, aes_encrypt_block);
729904Smcpowers }
730904Smcpowers
7310Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
7320Sstevel@tonic-gate if (plaintext != ciphertext)
7330Sstevel@tonic-gate ciphertext->cd_length =
7340Sstevel@tonic-gate ciphertext->cd_offset - saved_offset;
7350Sstevel@tonic-gate } else {
7360Sstevel@tonic-gate ciphertext->cd_length = saved_length;
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate ciphertext->cd_offset = saved_offset;
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate return (ret);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate
7439392Sopensolaris@drydog.com
7440Sstevel@tonic-gate static int
aes_decrypt_update(crypto_ctx_t * ctx,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_req_handle_t req)7450Sstevel@tonic-gate aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
7460Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req)
7470Sstevel@tonic-gate {
7480Sstevel@tonic-gate off_t saved_offset;
7490Sstevel@tonic-gate size_t saved_length, out_len;
7500Sstevel@tonic-gate int ret = CRYPTO_SUCCESS;
751904Smcpowers aes_ctx_t *aes_ctx;
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
7547188Smcpowers aes_ctx = ctx->cc_provider_private;
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate AES_ARG_INPLACE(ciphertext, plaintext);
7570Sstevel@tonic-gate
7588005SMark.Powers@Sun.COM /*
7598005SMark.Powers@Sun.COM * Compute number of bytes that will hold the plaintext.
7609339SMark.Powers@Sun.COM * This is not necessary for CCM, GCM, and GMAC since these
7619339SMark.Powers@Sun.COM * mechanisms never return plaintext for update operations.
7628005SMark.Powers@Sun.COM */
7639339SMark.Powers@Sun.COM if ((aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
7648005SMark.Powers@Sun.COM out_len = aes_ctx->ac_remainder_len;
7658005SMark.Powers@Sun.COM out_len += ciphertext->cd_length;
7668005SMark.Powers@Sun.COM out_len &= ~(AES_BLOCK_LEN - 1);
7670Sstevel@tonic-gate
7688005SMark.Powers@Sun.COM /* return length needed to store the output */
7698005SMark.Powers@Sun.COM if (plaintext->cd_length < out_len) {
7708005SMark.Powers@Sun.COM plaintext->cd_length = out_len;
7718005SMark.Powers@Sun.COM return (CRYPTO_BUFFER_TOO_SMALL);
7728005SMark.Powers@Sun.COM }
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate saved_offset = plaintext->cd_offset;
7760Sstevel@tonic-gate saved_length = plaintext->cd_length;
7770Sstevel@tonic-gate
7789339SMark.Powers@Sun.COM if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE))
7798005SMark.Powers@Sun.COM gcm_set_kmflag((gcm_ctx_t *)aes_ctx, crypto_kmflag(req));
7808005SMark.Powers@Sun.COM
7810Sstevel@tonic-gate /*
7820Sstevel@tonic-gate * Do the AES update on the specified input data.
7830Sstevel@tonic-gate */
7840Sstevel@tonic-gate switch (ciphertext->cd_format) {
7850Sstevel@tonic-gate case CRYPTO_DATA_RAW:
7867188Smcpowers ret = crypto_update_iov(ctx->cc_provider_private,
7877188Smcpowers ciphertext, plaintext, aes_decrypt_contiguous_blocks,
7887188Smcpowers aes_copy_block64);
7890Sstevel@tonic-gate break;
7900Sstevel@tonic-gate case CRYPTO_DATA_UIO:
7917188Smcpowers ret = crypto_update_uio(ctx->cc_provider_private,
7927188Smcpowers ciphertext, plaintext, aes_decrypt_contiguous_blocks,
7937188Smcpowers aes_copy_block64);
7940Sstevel@tonic-gate break;
7950Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
7967188Smcpowers ret = crypto_update_mp(ctx->cc_provider_private,
7977188Smcpowers ciphertext, plaintext, aes_decrypt_contiguous_blocks,
7987188Smcpowers aes_copy_block64);
7990Sstevel@tonic-gate break;
8000Sstevel@tonic-gate default:
8010Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate
804904Smcpowers /*
805904Smcpowers * Since AES counter mode is a stream cipher, we call
8067188Smcpowers * ctr_mode_final() to pick up any remaining bytes.
807904Smcpowers * It is an internal function that does not destroy
808904Smcpowers * the context like *normal* final routines.
809904Smcpowers */
8107188Smcpowers if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
8117188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, plaintext,
8127188Smcpowers aes_encrypt_block);
8137188Smcpowers if (ret == CRYPTO_DATA_LEN_RANGE)
8147188Smcpowers ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
815904Smcpowers }
816904Smcpowers
8170Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) {
8180Sstevel@tonic-gate if (ciphertext != plaintext)
8190Sstevel@tonic-gate plaintext->cd_length =
8200Sstevel@tonic-gate plaintext->cd_offset - saved_offset;
8210Sstevel@tonic-gate } else {
8220Sstevel@tonic-gate plaintext->cd_length = saved_length;
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate plaintext->cd_offset = saved_offset;
8250Sstevel@tonic-gate
826904Smcpowers
8270Sstevel@tonic-gate return (ret);
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate /* ARGSUSED */
8310Sstevel@tonic-gate static int
aes_encrypt_final(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)8320Sstevel@tonic-gate aes_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
8330Sstevel@tonic-gate crypto_req_handle_t req)
8340Sstevel@tonic-gate {
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate /* EXPORT DELETE START */
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate aes_ctx_t *aes_ctx;
839904Smcpowers int ret;
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
8420Sstevel@tonic-gate aes_ctx = ctx->cc_provider_private;
8430Sstevel@tonic-gate
844904Smcpowers if (data->cd_format != CRYPTO_DATA_RAW &&
845904Smcpowers data->cd_format != CRYPTO_DATA_UIO &&
846904Smcpowers data->cd_format != CRYPTO_DATA_MBLK) {
847904Smcpowers return (CRYPTO_ARGUMENTS_BAD);
848904Smcpowers }
849904Smcpowers
8507188Smcpowers if (aes_ctx->ac_flags & CTR_MODE) {
8514486Sktung if (aes_ctx->ac_remainder_len > 0) {
8527188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
8537188Smcpowers aes_encrypt_block);
854904Smcpowers if (ret != CRYPTO_SUCCESS)
855904Smcpowers return (ret);
856904Smcpowers }
8577188Smcpowers } else if (aes_ctx->ac_flags & CCM_MODE) {
8587188Smcpowers ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, data,
8597188Smcpowers AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
8604486Sktung if (ret != CRYPTO_SUCCESS) {
8614486Sktung return (ret);
8624486Sktung }
8639339SMark.Powers@Sun.COM } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
8648005SMark.Powers@Sun.COM size_t saved_offset = data->cd_offset;
8658005SMark.Powers@Sun.COM
8668005SMark.Powers@Sun.COM ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, data,
8678005SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
8688005SMark.Powers@Sun.COM aes_xor_block);
8698005SMark.Powers@Sun.COM if (ret != CRYPTO_SUCCESS) {
8708005SMark.Powers@Sun.COM return (ret);
8718005SMark.Powers@Sun.COM }
8728005SMark.Powers@Sun.COM data->cd_length = data->cd_offset - saved_offset;
8738005SMark.Powers@Sun.COM data->cd_offset = saved_offset;
8744486Sktung } else {
8754486Sktung /*
8764486Sktung * There must be no unprocessed plaintext.
8774486Sktung * This happens if the length of the last data is
8784486Sktung * not a multiple of the AES block length.
8794486Sktung */
8804486Sktung if (aes_ctx->ac_remainder_len > 0) {
8814486Sktung return (CRYPTO_DATA_LEN_RANGE);
8824486Sktung }
8834558Sktung data->cd_length = 0;
884904Smcpowers }
885904Smcpowers
8860Sstevel@tonic-gate (void) aes_free_context(ctx);
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate /* EXPORT DELETE END */
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate return (CRYPTO_SUCCESS);
8910Sstevel@tonic-gate }
8920Sstevel@tonic-gate
8930Sstevel@tonic-gate /* ARGSUSED */
8940Sstevel@tonic-gate static int
aes_decrypt_final(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)8950Sstevel@tonic-gate aes_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
8960Sstevel@tonic-gate crypto_req_handle_t req)
8970Sstevel@tonic-gate {
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate /* EXPORT DELETE START */
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate aes_ctx_t *aes_ctx;
902904Smcpowers int ret;
9034486Sktung off_t saved_offset;
9044486Sktung size_t saved_length;
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL);
9070Sstevel@tonic-gate aes_ctx = ctx->cc_provider_private;
9080Sstevel@tonic-gate
909904Smcpowers if (data->cd_format != CRYPTO_DATA_RAW &&
910904Smcpowers data->cd_format != CRYPTO_DATA_UIO &&
911904Smcpowers data->cd_format != CRYPTO_DATA_MBLK) {
912904Smcpowers return (CRYPTO_ARGUMENTS_BAD);
913904Smcpowers }
914904Smcpowers
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate * There must be no unprocessed ciphertext.
9170Sstevel@tonic-gate * This happens if the length of the last ciphertext is
9180Sstevel@tonic-gate * not a multiple of the AES block length.
9190Sstevel@tonic-gate */
920904Smcpowers if (aes_ctx->ac_remainder_len > 0) {
9217188Smcpowers if ((aes_ctx->ac_flags & CTR_MODE) == 0)
922904Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
923904Smcpowers else {
9247188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
9257188Smcpowers aes_encrypt_block);
9267188Smcpowers if (ret == CRYPTO_DATA_LEN_RANGE)
9277188Smcpowers ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
928904Smcpowers if (ret != CRYPTO_SUCCESS)
929904Smcpowers return (ret);
930904Smcpowers }
931904Smcpowers }
932904Smcpowers
9337188Smcpowers if (aes_ctx->ac_flags & CCM_MODE) {
9344486Sktung /*
9354486Sktung * This is where all the plaintext is returned, make sure
9364486Sktung * the plaintext buffer is big enough
9374486Sktung */
9387188Smcpowers size_t pt_len = aes_ctx->ac_data_len;
9394486Sktung if (data->cd_length < pt_len) {
9404486Sktung data->cd_length = pt_len;
9414486Sktung return (CRYPTO_BUFFER_TOO_SMALL);
9424486Sktung }
9434486Sktung
9447188Smcpowers ASSERT(aes_ctx->ac_processed_data_len == pt_len);
9457188Smcpowers ASSERT(aes_ctx->ac_processed_mac_len == aes_ctx->ac_mac_len);
9464486Sktung saved_offset = data->cd_offset;
9474486Sktung saved_length = data->cd_length;
9487188Smcpowers ret = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, data,
9497188Smcpowers AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
9507188Smcpowers aes_xor_block);
9514486Sktung if (ret == CRYPTO_SUCCESS) {
9524486Sktung data->cd_length = data->cd_offset - saved_offset;
9534486Sktung } else {
9544486Sktung data->cd_length = saved_length;
9554486Sktung }
9564486Sktung
9574486Sktung data->cd_offset = saved_offset;
9584486Sktung if (ret != CRYPTO_SUCCESS) {
9594486Sktung return (ret);
9604486Sktung }
9619339SMark.Powers@Sun.COM } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
9628005SMark.Powers@Sun.COM /*
9638005SMark.Powers@Sun.COM * This is where all the plaintext is returned, make sure
9648005SMark.Powers@Sun.COM * the plaintext buffer is big enough
9658005SMark.Powers@Sun.COM */
9668005SMark.Powers@Sun.COM gcm_ctx_t *ctx = (gcm_ctx_t *)aes_ctx;
9678005SMark.Powers@Sun.COM size_t pt_len = ctx->gcm_processed_data_len - ctx->gcm_tag_len;
9688005SMark.Powers@Sun.COM
9698005SMark.Powers@Sun.COM if (data->cd_length < pt_len) {
9708005SMark.Powers@Sun.COM data->cd_length = pt_len;
9718005SMark.Powers@Sun.COM return (CRYPTO_BUFFER_TOO_SMALL);
9728005SMark.Powers@Sun.COM }
9738005SMark.Powers@Sun.COM
9748005SMark.Powers@Sun.COM saved_offset = data->cd_offset;
9758005SMark.Powers@Sun.COM saved_length = data->cd_length;
9768005SMark.Powers@Sun.COM ret = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, data,
9778005SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
9788005SMark.Powers@Sun.COM if (ret == CRYPTO_SUCCESS) {
9798005SMark.Powers@Sun.COM data->cd_length = data->cd_offset - saved_offset;
9808005SMark.Powers@Sun.COM } else {
9818005SMark.Powers@Sun.COM data->cd_length = saved_length;
9828005SMark.Powers@Sun.COM }
9838005SMark.Powers@Sun.COM
9848005SMark.Powers@Sun.COM data->cd_offset = saved_offset;
9858005SMark.Powers@Sun.COM if (ret != CRYPTO_SUCCESS) {
9868005SMark.Powers@Sun.COM return (ret);
9878005SMark.Powers@Sun.COM }
9884486Sktung }
9894486Sktung
9904486Sktung
9919339SMark.Powers@Sun.COM if ((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
992904Smcpowers data->cd_length = 0;
9934558Sktung }
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate (void) aes_free_context(ctx);
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /* EXPORT DELETE END */
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate return (CRYPTO_SUCCESS);
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate /* ARGSUSED */
10030Sstevel@tonic-gate static int
aes_encrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * plaintext,crypto_data_t * ciphertext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)10040Sstevel@tonic-gate aes_encrypt_atomic(crypto_provider_handle_t provider,
10050Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
10060Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
10070Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req)
10080Sstevel@tonic-gate {
10090Sstevel@tonic-gate aes_ctx_t aes_ctx; /* on the stack */
10100Sstevel@tonic-gate off_t saved_offset;
10110Sstevel@tonic-gate size_t saved_length;
10128195SMark.Powers@Sun.COM size_t length_needed;
10130Sstevel@tonic-gate int ret;
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate AES_ARG_INPLACE(plaintext, ciphertext);
10160Sstevel@tonic-gate
10178195SMark.Powers@Sun.COM /*
10189339SMark.Powers@Sun.COM * CTR, CCM, GCM, and GMAC modes do not require that plaintext
10198195SMark.Powers@Sun.COM * be a multiple of AES block size.
10208195SMark.Powers@Sun.COM */
10218195SMark.Powers@Sun.COM switch (mechanism->cm_type) {
10228195SMark.Powers@Sun.COM case AES_CTR_MECH_INFO_TYPE:
10238195SMark.Powers@Sun.COM case AES_CCM_MECH_INFO_TYPE:
10248195SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
10259339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
10268195SMark.Powers@Sun.COM break;
10278195SMark.Powers@Sun.COM default:
1028904Smcpowers if ((plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
1029904Smcpowers return (CRYPTO_DATA_LEN_RANGE);
1030904Smcpowers }
10310Sstevel@tonic-gate
10327188Smcpowers if ((ret = aes_check_mech_param(mechanism, NULL, 0)) != CRYPTO_SUCCESS)
1033991Smcpowers return (ret);
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate bzero(&aes_ctx, sizeof (aes_ctx_t));
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
10384486Sktung crypto_kmflag(req), B_TRUE);
10390Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS)
10400Sstevel@tonic-gate return (ret);
10410Sstevel@tonic-gate
10428195SMark.Powers@Sun.COM switch (mechanism->cm_type) {
10438195SMark.Powers@Sun.COM case AES_CCM_MECH_INFO_TYPE:
10448195SMark.Powers@Sun.COM length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
10458195SMark.Powers@Sun.COM break;
10469339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
10479339SMark.Powers@Sun.COM if (plaintext->cd_length != 0)
10489339SMark.Powers@Sun.COM return (CRYPTO_ARGUMENTS_BAD);
10499339SMark.Powers@Sun.COM /* FALLTHRU */
10508195SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
10518195SMark.Powers@Sun.COM length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
10528195SMark.Powers@Sun.COM break;
10538195SMark.Powers@Sun.COM default:
10548195SMark.Powers@Sun.COM length_needed = plaintext->cd_length;
10554486Sktung }
10564486Sktung
10578195SMark.Powers@Sun.COM /* return size of buffer needed to store output */
10588195SMark.Powers@Sun.COM if (ciphertext->cd_length < length_needed) {
10598195SMark.Powers@Sun.COM ciphertext->cd_length = length_needed;
10608195SMark.Powers@Sun.COM ret = CRYPTO_BUFFER_TOO_SMALL;
10618195SMark.Powers@Sun.COM goto out;
10628195SMark.Powers@Sun.COM }
10634486Sktung
10640Sstevel@tonic-gate saved_offset = ciphertext->cd_offset;
10650Sstevel@tonic-gate saved_length = ciphertext->cd_length;
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /*
10680Sstevel@tonic-gate * Do an update on the specified input data.
10690Sstevel@tonic-gate */
10700Sstevel@tonic-gate switch (plaintext->cd_format) {
10710Sstevel@tonic-gate case CRYPTO_DATA_RAW:
10727188Smcpowers ret = crypto_update_iov(&aes_ctx, plaintext, ciphertext,
10737188Smcpowers aes_encrypt_contiguous_blocks, aes_copy_block64);
10740Sstevel@tonic-gate break;
10750Sstevel@tonic-gate case CRYPTO_DATA_UIO:
10767188Smcpowers ret = crypto_update_uio(&aes_ctx, plaintext, ciphertext,
10777188Smcpowers aes_encrypt_contiguous_blocks, aes_copy_block64);
10780Sstevel@tonic-gate break;
10790Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
10807188Smcpowers ret = crypto_update_mp(&aes_ctx, plaintext, ciphertext,
10817188Smcpowers aes_encrypt_contiguous_blocks, aes_copy_block64);
10820Sstevel@tonic-gate break;
10830Sstevel@tonic-gate default:
10840Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate
1087904Smcpowers if (ret == CRYPTO_SUCCESS) {
10884486Sktung if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
10897188Smcpowers ret = ccm_encrypt_final((ccm_ctx_t *)&aes_ctx,
10907188Smcpowers ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
10917188Smcpowers aes_xor_block);
10924486Sktung if (ret != CRYPTO_SUCCESS)
10934486Sktung goto out;
1094904Smcpowers ASSERT(aes_ctx.ac_remainder_len == 0);
10959339SMark.Powers@Sun.COM } else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
10969339SMark.Powers@Sun.COM mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
10978005SMark.Powers@Sun.COM ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
10988005SMark.Powers@Sun.COM ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
10998005SMark.Powers@Sun.COM aes_copy_block, aes_xor_block);
11008005SMark.Powers@Sun.COM if (ret != CRYPTO_SUCCESS)
11018005SMark.Powers@Sun.COM goto out;
11028005SMark.Powers@Sun.COM ASSERT(aes_ctx.ac_remainder_len == 0);
11034486Sktung } else if (mechanism->cm_type == AES_CTR_MECH_INFO_TYPE) {
1104904Smcpowers if (aes_ctx.ac_remainder_len > 0) {
11057188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
11067188Smcpowers ciphertext, aes_encrypt_block);
1107904Smcpowers if (ret != CRYPTO_SUCCESS)
1108904Smcpowers goto out;
1109904Smcpowers }
11104486Sktung } else {
11114486Sktung ASSERT(aes_ctx.ac_remainder_len == 0);
11124486Sktung }
11134486Sktung
11144486Sktung if (plaintext != ciphertext) {
11154486Sktung ciphertext->cd_length =
11164486Sktung ciphertext->cd_offset - saved_offset;
1117904Smcpowers }
1118904Smcpowers } else {
1119904Smcpowers ciphertext->cd_length = saved_length;
1120904Smcpowers }
1121904Smcpowers ciphertext->cd_offset = saved_offset;
1122904Smcpowers
1123904Smcpowers out:
11247188Smcpowers if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
11250Sstevel@tonic-gate bzero(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
11260Sstevel@tonic-gate kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate return (ret);
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate /* ARGSUSED */
11330Sstevel@tonic-gate static int
aes_decrypt_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * ciphertext,crypto_data_t * plaintext,crypto_spi_ctx_template_t template,crypto_req_handle_t req)11340Sstevel@tonic-gate aes_decrypt_atomic(crypto_provider_handle_t provider,
11350Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
11360Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
11370Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate aes_ctx_t aes_ctx; /* on the stack */
11400Sstevel@tonic-gate off_t saved_offset;
11410Sstevel@tonic-gate size_t saved_length;
11428195SMark.Powers@Sun.COM size_t length_needed;
11430Sstevel@tonic-gate int ret;
11440Sstevel@tonic-gate
11450Sstevel@tonic-gate AES_ARG_INPLACE(ciphertext, plaintext);
11460Sstevel@tonic-gate
11474486Sktung /*
11489339SMark.Powers@Sun.COM * CCM, GCM, CTR, and GMAC modes do not require that ciphertext
11498195SMark.Powers@Sun.COM * be a multiple of AES block size.
11504486Sktung */
11518195SMark.Powers@Sun.COM switch (mechanism->cm_type) {
11528195SMark.Powers@Sun.COM case AES_CTR_MECH_INFO_TYPE:
11538195SMark.Powers@Sun.COM case AES_CCM_MECH_INFO_TYPE:
11548195SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
11559339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
11568195SMark.Powers@Sun.COM break;
11578195SMark.Powers@Sun.COM default:
11588195SMark.Powers@Sun.COM if ((ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
11598195SMark.Powers@Sun.COM return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate
11627188Smcpowers if ((ret = aes_check_mech_param(mechanism, NULL, 0)) != CRYPTO_SUCCESS)
1163991Smcpowers return (ret);
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate bzero(&aes_ctx, sizeof (aes_ctx_t));
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate ret = aes_common_init_ctx(&aes_ctx, template, mechanism, key,
11684486Sktung crypto_kmflag(req), B_FALSE);
11690Sstevel@tonic-gate if (ret != CRYPTO_SUCCESS)
11700Sstevel@tonic-gate return (ret);
11710Sstevel@tonic-gate
11728195SMark.Powers@Sun.COM switch (mechanism->cm_type) {
11738195SMark.Powers@Sun.COM case AES_CCM_MECH_INFO_TYPE:
11748195SMark.Powers@Sun.COM length_needed = aes_ctx.ac_data_len;
11758195SMark.Powers@Sun.COM break;
11768195SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
11778195SMark.Powers@Sun.COM length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
11788195SMark.Powers@Sun.COM break;
11799339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
11809339SMark.Powers@Sun.COM if (plaintext->cd_length != 0)
11819339SMark.Powers@Sun.COM return (CRYPTO_ARGUMENTS_BAD);
11829339SMark.Powers@Sun.COM length_needed = 0;
11839339SMark.Powers@Sun.COM break;
11848195SMark.Powers@Sun.COM default:
11858195SMark.Powers@Sun.COM length_needed = ciphertext->cd_length;
11868195SMark.Powers@Sun.COM }
11878195SMark.Powers@Sun.COM
11888195SMark.Powers@Sun.COM /* return size of buffer needed to store output */
11898195SMark.Powers@Sun.COM if (plaintext->cd_length < length_needed) {
11908195SMark.Powers@Sun.COM plaintext->cd_length = length_needed;
11918195SMark.Powers@Sun.COM ret = CRYPTO_BUFFER_TOO_SMALL;
11928195SMark.Powers@Sun.COM goto out;
11934486Sktung }
11944486Sktung
11950Sstevel@tonic-gate saved_offset = plaintext->cd_offset;
11960Sstevel@tonic-gate saved_length = plaintext->cd_length;
11970Sstevel@tonic-gate
11989339SMark.Powers@Sun.COM if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
11999339SMark.Powers@Sun.COM mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE)
12008005SMark.Powers@Sun.COM gcm_set_kmflag((gcm_ctx_t *)&aes_ctx, crypto_kmflag(req));
12018005SMark.Powers@Sun.COM
12020Sstevel@tonic-gate /*
12030Sstevel@tonic-gate * Do an update on the specified input data.
12040Sstevel@tonic-gate */
12050Sstevel@tonic-gate switch (ciphertext->cd_format) {
12060Sstevel@tonic-gate case CRYPTO_DATA_RAW:
12077188Smcpowers ret = crypto_update_iov(&aes_ctx, ciphertext, plaintext,
12087188Smcpowers aes_decrypt_contiguous_blocks, aes_copy_block64);
12090Sstevel@tonic-gate break;
12100Sstevel@tonic-gate case CRYPTO_DATA_UIO:
12117188Smcpowers ret = crypto_update_uio(&aes_ctx, ciphertext, plaintext,
12127188Smcpowers aes_decrypt_contiguous_blocks, aes_copy_block64);
12130Sstevel@tonic-gate break;
12140Sstevel@tonic-gate case CRYPTO_DATA_MBLK:
12157188Smcpowers ret = crypto_update_mp(&aes_ctx, ciphertext, plaintext,
12167188Smcpowers aes_decrypt_contiguous_blocks, aes_copy_block64);
12170Sstevel@tonic-gate break;
12180Sstevel@tonic-gate default:
12190Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD;
12200Sstevel@tonic-gate }
12210Sstevel@tonic-gate
1222904Smcpowers if (ret == CRYPTO_SUCCESS) {
12234486Sktung if (mechanism->cm_type == AES_CCM_MECH_INFO_TYPE) {
12247188Smcpowers ASSERT(aes_ctx.ac_processed_data_len
12257188Smcpowers == aes_ctx.ac_data_len);
12267188Smcpowers ASSERT(aes_ctx.ac_processed_mac_len
12277188Smcpowers == aes_ctx.ac_mac_len);
12287188Smcpowers ret = ccm_decrypt_final((ccm_ctx_t *)&aes_ctx,
12297188Smcpowers plaintext, AES_BLOCK_LEN, aes_encrypt_block,
12307188Smcpowers aes_copy_block, aes_xor_block);
12314486Sktung ASSERT(aes_ctx.ac_remainder_len == 0);
12324486Sktung if ((ret == CRYPTO_SUCCESS) &&
12334486Sktung (ciphertext != plaintext)) {
12344486Sktung plaintext->cd_length =
12354486Sktung plaintext->cd_offset - saved_offset;
12364486Sktung } else {
12374486Sktung plaintext->cd_length = saved_length;
12384486Sktung }
12399339SMark.Powers@Sun.COM } else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
12409339SMark.Powers@Sun.COM mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
12418005SMark.Powers@Sun.COM ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
12428005SMark.Powers@Sun.COM plaintext, AES_BLOCK_LEN, aes_encrypt_block,
12438005SMark.Powers@Sun.COM aes_xor_block);
12448005SMark.Powers@Sun.COM ASSERT(aes_ctx.ac_remainder_len == 0);
12458005SMark.Powers@Sun.COM if ((ret == CRYPTO_SUCCESS) &&
12468005SMark.Powers@Sun.COM (ciphertext != plaintext)) {
12478005SMark.Powers@Sun.COM plaintext->cd_length =
12488005SMark.Powers@Sun.COM plaintext->cd_offset - saved_offset;
12498005SMark.Powers@Sun.COM } else {
12508005SMark.Powers@Sun.COM plaintext->cd_length = saved_length;
12518005SMark.Powers@Sun.COM }
12524486Sktung } else if (mechanism->cm_type != AES_CTR_MECH_INFO_TYPE) {
1253904Smcpowers ASSERT(aes_ctx.ac_remainder_len == 0);
1254904Smcpowers if (ciphertext != plaintext)
1255904Smcpowers plaintext->cd_length =
1256904Smcpowers plaintext->cd_offset - saved_offset;
1257904Smcpowers } else {
1258904Smcpowers if (aes_ctx.ac_remainder_len > 0) {
12597188Smcpowers ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
12607188Smcpowers plaintext, aes_encrypt_block);
12617188Smcpowers if (ret == CRYPTO_DATA_LEN_RANGE)
12627188Smcpowers ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
1263904Smcpowers if (ret != CRYPTO_SUCCESS)
1264904Smcpowers goto out;
1265904Smcpowers }
1266904Smcpowers if (ciphertext != plaintext)
1267904Smcpowers plaintext->cd_length =
1268904Smcpowers plaintext->cd_offset - saved_offset;
1269904Smcpowers }
1270904Smcpowers } else {
1271904Smcpowers plaintext->cd_length = saved_length;
1272904Smcpowers }
1273904Smcpowers plaintext->cd_offset = saved_offset;
1274904Smcpowers
1275904Smcpowers out:
12767188Smcpowers if (aes_ctx.ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
12770Sstevel@tonic-gate bzero(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
12780Sstevel@tonic-gate kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12817188Smcpowers if (aes_ctx.ac_flags & CCM_MODE) {
12827188Smcpowers if (aes_ctx.ac_pt_buf != NULL) {
12837188Smcpowers kmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
12847188Smcpowers }
12859339SMark.Powers@Sun.COM } else if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
12868005SMark.Powers@Sun.COM if (((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf != NULL) {
12878005SMark.Powers@Sun.COM kmem_free(((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf,
12888005SMark.Powers@Sun.COM ((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf_len);
12898005SMark.Powers@Sun.COM }
12904486Sktung }
12914486Sktung
12920Sstevel@tonic-gate return (ret);
12930Sstevel@tonic-gate }
12940Sstevel@tonic-gate
12950Sstevel@tonic-gate /*
12960Sstevel@tonic-gate * KCF software provider context template entry points.
12970Sstevel@tonic-gate */
12980Sstevel@tonic-gate /* ARGSUSED */
12990Sstevel@tonic-gate static int
aes_create_ctx_template(crypto_provider_handle_t provider,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t * tmpl,size_t * tmpl_size,crypto_req_handle_t req)13000Sstevel@tonic-gate aes_create_ctx_template(crypto_provider_handle_t provider,
13010Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key,
13020Sstevel@tonic-gate crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
13030Sstevel@tonic-gate {
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate /* EXPORT DELETE START */
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate void *keysched;
13080Sstevel@tonic-gate size_t size;
13090Sstevel@tonic-gate int rv;
13100Sstevel@tonic-gate
1311991Smcpowers if (mechanism->cm_type != AES_ECB_MECH_INFO_TYPE &&
1312991Smcpowers mechanism->cm_type != AES_CBC_MECH_INFO_TYPE &&
13134486Sktung mechanism->cm_type != AES_CTR_MECH_INFO_TYPE &&
13149339SMark.Powers@Sun.COM mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
13159339SMark.Powers@Sun.COM mechanism->cm_type != AES_GCM_MECH_INFO_TYPE &&
13169339SMark.Powers@Sun.COM mechanism->cm_type != AES_GMAC_MECH_INFO_TYPE)
13170Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate if ((keysched = aes_alloc_keysched(&size,
13200Sstevel@tonic-gate crypto_kmflag(req))) == NULL) {
13210Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY);
13220Sstevel@tonic-gate }
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate /*
13250Sstevel@tonic-gate * Initialize key schedule. Key length information is stored
13260Sstevel@tonic-gate * in the key.
13270Sstevel@tonic-gate */
13280Sstevel@tonic-gate if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
13290Sstevel@tonic-gate bzero(keysched, size);
13300Sstevel@tonic-gate kmem_free(keysched, size);
13310Sstevel@tonic-gate return (rv);
13320Sstevel@tonic-gate }
13330Sstevel@tonic-gate
13340Sstevel@tonic-gate *tmpl = keysched;
13350Sstevel@tonic-gate *tmpl_size = size;
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate /* EXPORT DELETE END */
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate return (CRYPTO_SUCCESS);
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate
13429392Sopensolaris@drydog.com
13430Sstevel@tonic-gate static int
aes_free_context(crypto_ctx_t * ctx)13440Sstevel@tonic-gate aes_free_context(crypto_ctx_t *ctx)
13450Sstevel@tonic-gate {
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate /* EXPORT DELETE START */
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate aes_ctx_t *aes_ctx = ctx->cc_provider_private;
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate if (aes_ctx != NULL) {
13527188Smcpowers if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
13530Sstevel@tonic-gate ASSERT(aes_ctx->ac_keysched_len != 0);
13540Sstevel@tonic-gate bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
13550Sstevel@tonic-gate kmem_free(aes_ctx->ac_keysched,
13560Sstevel@tonic-gate aes_ctx->ac_keysched_len);
13570Sstevel@tonic-gate }
13587188Smcpowers crypto_free_mode_ctx(aes_ctx);
13590Sstevel@tonic-gate ctx->cc_provider_private = NULL;
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate
13620Sstevel@tonic-gate /* EXPORT DELETE END */
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate return (CRYPTO_SUCCESS);
13650Sstevel@tonic-gate }
13660Sstevel@tonic-gate
13679392Sopensolaris@drydog.com
13680Sstevel@tonic-gate 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)13690Sstevel@tonic-gate aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
13704486Sktung crypto_mechanism_t *mechanism, crypto_key_t *key, int kmflag,
13714486Sktung boolean_t is_encrypt_init)
13720Sstevel@tonic-gate {
13730Sstevel@tonic-gate int rv = CRYPTO_SUCCESS;
13740Sstevel@tonic-gate
13750Sstevel@tonic-gate /* EXPORT DELETE START */
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate void *keysched;
13780Sstevel@tonic-gate size_t size;
1379904Smcpowers
1380904Smcpowers if (template == NULL) {
1381904Smcpowers if ((keysched = aes_alloc_keysched(&size, kmflag)) == NULL)
1382904Smcpowers return (CRYPTO_HOST_MEMORY);
1383904Smcpowers /*
1384904Smcpowers * Initialize key schedule.
1385904Smcpowers * Key length is stored in the key.
1386904Smcpowers */
13874486Sktung if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
1388904Smcpowers kmem_free(keysched, size);
13894486Sktung return (rv);
13904486Sktung }
1391904Smcpowers
13927188Smcpowers aes_ctx->ac_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
1393904Smcpowers aes_ctx->ac_keysched_len = size;
1394904Smcpowers } else {
1395904Smcpowers keysched = template;
13960Sstevel@tonic-gate }
13970Sstevel@tonic-gate aes_ctx->ac_keysched = keysched;
13980Sstevel@tonic-gate
13997188Smcpowers switch (mechanism->cm_type) {
14007188Smcpowers case AES_CBC_MECH_INFO_TYPE:
14017188Smcpowers rv = cbc_init_ctx((cbc_ctx_t *)aes_ctx, mechanism->cm_param,
14027188Smcpowers mechanism->cm_param_len, AES_BLOCK_LEN, aes_copy_block64);
14037188Smcpowers break;
14047188Smcpowers case AES_CTR_MECH_INFO_TYPE: {
14057188Smcpowers CK_AES_CTR_PARAMS *pp;
14067188Smcpowers
14077188Smcpowers if (mechanism->cm_param == NULL ||
14087188Smcpowers mechanism->cm_param_len != sizeof (CK_AES_CTR_PARAMS)) {
14094486Sktung return (CRYPTO_MECHANISM_PARAM_INVALID);
14104486Sktung }
14119392Sopensolaris@drydog.com pp = (CK_AES_CTR_PARAMS *)(void *)mechanism->cm_param;
14127188Smcpowers rv = ctr_init_ctx((ctr_ctx_t *)aes_ctx, pp->ulCounterBits,
14137188Smcpowers pp->cb, aes_copy_block);
14147188Smcpowers break;
14157188Smcpowers }
14167188Smcpowers case AES_CCM_MECH_INFO_TYPE:
14177188Smcpowers if (mechanism->cm_param == NULL ||
14187188Smcpowers mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
14197188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID);
14207188Smcpowers }
14217188Smcpowers rv = ccm_init_ctx((ccm_ctx_t *)aes_ctx, mechanism->cm_param,
14227188Smcpowers kmflag, is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
14237188Smcpowers aes_xor_block);
14247188Smcpowers break;
14258005SMark.Powers@Sun.COM case AES_GCM_MECH_INFO_TYPE:
14268005SMark.Powers@Sun.COM if (mechanism->cm_param == NULL ||
14278005SMark.Powers@Sun.COM mechanism->cm_param_len != sizeof (CK_AES_GCM_PARAMS)) {
14288005SMark.Powers@Sun.COM return (CRYPTO_MECHANISM_PARAM_INVALID);
14298005SMark.Powers@Sun.COM }
14308005SMark.Powers@Sun.COM rv = gcm_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
14318005SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
14328005SMark.Powers@Sun.COM aes_xor_block);
14338005SMark.Powers@Sun.COM break;
14349339SMark.Powers@Sun.COM case AES_GMAC_MECH_INFO_TYPE:
14359339SMark.Powers@Sun.COM if (mechanism->cm_param == NULL ||
14369339SMark.Powers@Sun.COM mechanism->cm_param_len != sizeof (CK_AES_GMAC_PARAMS)) {
14379339SMark.Powers@Sun.COM return (CRYPTO_MECHANISM_PARAM_INVALID);
14389339SMark.Powers@Sun.COM }
14399339SMark.Powers@Sun.COM rv = gmac_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
14409339SMark.Powers@Sun.COM AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
14419339SMark.Powers@Sun.COM aes_xor_block);
14429339SMark.Powers@Sun.COM break;
14437188Smcpowers case AES_ECB_MECH_INFO_TYPE:
14447188Smcpowers aes_ctx->ac_flags |= ECB_MODE;
14457188Smcpowers }
14467188Smcpowers
14477188Smcpowers if (rv != CRYPTO_SUCCESS) {
14487188Smcpowers if (aes_ctx->ac_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
14497188Smcpowers bzero(keysched, size);
14507188Smcpowers kmem_free(keysched, size);
14514486Sktung }
14524486Sktung }
14534486Sktung
14540Sstevel@tonic-gate /* EXPORT DELETE END */
14550Sstevel@tonic-gate
14560Sstevel@tonic-gate return (rv);
14570Sstevel@tonic-gate }
14589339SMark.Powers@Sun.COM
14599339SMark.Powers@Sun.COM static int
process_gmac_mech(crypto_mechanism_t * mech,crypto_data_t * data,CK_AES_GCM_PARAMS * gcm_params)14609339SMark.Powers@Sun.COM process_gmac_mech(crypto_mechanism_t *mech, crypto_data_t *data,
14619339SMark.Powers@Sun.COM CK_AES_GCM_PARAMS *gcm_params)
14629339SMark.Powers@Sun.COM {
14639339SMark.Powers@Sun.COM /* LINTED: pointer alignment */
14649339SMark.Powers@Sun.COM CK_AES_GMAC_PARAMS *params = (CK_AES_GMAC_PARAMS *)mech->cm_param;
14659339SMark.Powers@Sun.COM
14669339SMark.Powers@Sun.COM if (mech->cm_type != AES_GMAC_MECH_INFO_TYPE)
14679339SMark.Powers@Sun.COM return (CRYPTO_MECHANISM_INVALID);
14689339SMark.Powers@Sun.COM
14699339SMark.Powers@Sun.COM if (mech->cm_param_len != sizeof (CK_AES_GMAC_PARAMS))
14709339SMark.Powers@Sun.COM return (CRYPTO_MECHANISM_PARAM_INVALID);
14719339SMark.Powers@Sun.COM
14729339SMark.Powers@Sun.COM if (params->pIv == NULL)
14739339SMark.Powers@Sun.COM return (CRYPTO_MECHANISM_PARAM_INVALID);
14749339SMark.Powers@Sun.COM
14759339SMark.Powers@Sun.COM gcm_params->pIv = params->pIv;
14769339SMark.Powers@Sun.COM gcm_params->ulIvLen = AES_GMAC_IV_LEN;
14779339SMark.Powers@Sun.COM gcm_params->ulTagBits = AES_GMAC_TAG_BITS;
14789339SMark.Powers@Sun.COM
14799339SMark.Powers@Sun.COM if (data == NULL)
14809339SMark.Powers@Sun.COM return (CRYPTO_SUCCESS);
14819339SMark.Powers@Sun.COM
14829339SMark.Powers@Sun.COM if (data->cd_format != CRYPTO_DATA_RAW)
14839339SMark.Powers@Sun.COM return (CRYPTO_ARGUMENTS_BAD);
14849339SMark.Powers@Sun.COM
14859339SMark.Powers@Sun.COM gcm_params->pAAD = (uchar_t *)data->cd_raw.iov_base;
14869339SMark.Powers@Sun.COM gcm_params->ulAADLen = data->cd_length;
14879339SMark.Powers@Sun.COM return (CRYPTO_SUCCESS);
14889339SMark.Powers@Sun.COM }
14899339SMark.Powers@Sun.COM
14909339SMark.Powers@Sun.COM static int
aes_mac_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t template,crypto_req_handle_t req)14919339SMark.Powers@Sun.COM aes_mac_atomic(crypto_provider_handle_t provider,
14929339SMark.Powers@Sun.COM crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
14939339SMark.Powers@Sun.COM crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
14949339SMark.Powers@Sun.COM crypto_spi_ctx_template_t template, crypto_req_handle_t req)
14959339SMark.Powers@Sun.COM {
14969339SMark.Powers@Sun.COM CK_AES_GCM_PARAMS gcm_params;
14979339SMark.Powers@Sun.COM crypto_mechanism_t gcm_mech;
14989339SMark.Powers@Sun.COM int rv;
14999339SMark.Powers@Sun.COM
15009339SMark.Powers@Sun.COM if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
15019339SMark.Powers@Sun.COM != CRYPTO_SUCCESS)
15029339SMark.Powers@Sun.COM return (rv);
15039339SMark.Powers@Sun.COM
15049339SMark.Powers@Sun.COM gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
15059339SMark.Powers@Sun.COM gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
15069339SMark.Powers@Sun.COM gcm_mech.cm_param = (char *)&gcm_params;
15079339SMark.Powers@Sun.COM
15089339SMark.Powers@Sun.COM return (aes_encrypt_atomic(provider, session_id, &gcm_mech,
15099339SMark.Powers@Sun.COM key, &null_crypto_data, mac, template, req));
15109339SMark.Powers@Sun.COM }
15119339SMark.Powers@Sun.COM
15129339SMark.Powers@Sun.COM static int
aes_mac_verify_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t template,crypto_req_handle_t req)15139339SMark.Powers@Sun.COM aes_mac_verify_atomic(crypto_provider_handle_t provider,
15149339SMark.Powers@Sun.COM crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
15159339SMark.Powers@Sun.COM crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
15169339SMark.Powers@Sun.COM crypto_spi_ctx_template_t template, crypto_req_handle_t req)
15179339SMark.Powers@Sun.COM {
15189339SMark.Powers@Sun.COM CK_AES_GCM_PARAMS gcm_params;
15199339SMark.Powers@Sun.COM crypto_mechanism_t gcm_mech;
15209339SMark.Powers@Sun.COM int rv;
15219339SMark.Powers@Sun.COM
15229339SMark.Powers@Sun.COM if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
15239339SMark.Powers@Sun.COM != CRYPTO_SUCCESS)
15249339SMark.Powers@Sun.COM return (rv);
15259339SMark.Powers@Sun.COM
15269339SMark.Powers@Sun.COM gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
15279339SMark.Powers@Sun.COM gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
15289339SMark.Powers@Sun.COM gcm_mech.cm_param = (char *)&gcm_params;
15299339SMark.Powers@Sun.COM
15309339SMark.Powers@Sun.COM return (aes_decrypt_atomic(provider, session_id, &gcm_mech,
15319339SMark.Powers@Sun.COM key, mac, &null_crypto_data, template, req));
15329339SMark.Powers@Sun.COM }
153310500SHai-May.Chao@Sun.COM
153410500SHai-May.Chao@Sun.COM /*
153510500SHai-May.Chao@Sun.COM * AES Power-Up Self-Test
153610500SHai-May.Chao@Sun.COM */
153710500SHai-May.Chao@Sun.COM void
aes_POST(int * rc)153810500SHai-May.Chao@Sun.COM aes_POST(int *rc)
153910500SHai-May.Chao@Sun.COM {
154010500SHai-May.Chao@Sun.COM
154110500SHai-May.Chao@Sun.COM int ret;
154210500SHai-May.Chao@Sun.COM
154310500SHai-May.Chao@Sun.COM /* AES Power-Up Self-Test for 128-bit key. */
154410500SHai-May.Chao@Sun.COM ret = fips_aes_post(FIPS_AES_128_KEY_SIZE);
154510500SHai-May.Chao@Sun.COM
154610500SHai-May.Chao@Sun.COM if (ret != CRYPTO_SUCCESS)
154710500SHai-May.Chao@Sun.COM goto out;
154810500SHai-May.Chao@Sun.COM
154910500SHai-May.Chao@Sun.COM /* AES Power-Up Self-Test for 192-bit key. */
155010500SHai-May.Chao@Sun.COM ret = fips_aes_post(FIPS_AES_192_KEY_SIZE);
155110500SHai-May.Chao@Sun.COM
155210500SHai-May.Chao@Sun.COM if (ret != CRYPTO_SUCCESS)
155310500SHai-May.Chao@Sun.COM goto out;
155410500SHai-May.Chao@Sun.COM
155510500SHai-May.Chao@Sun.COM /* AES Power-Up Self-Test for 256-bit key. */
155610500SHai-May.Chao@Sun.COM ret = fips_aes_post(FIPS_AES_256_KEY_SIZE);
155710500SHai-May.Chao@Sun.COM
155810500SHai-May.Chao@Sun.COM out:
155910500SHai-May.Chao@Sun.COM *rc = ret;
156010500SHai-May.Chao@Sun.COM
156110500SHai-May.Chao@Sun.COM }
1562