17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5690caf98Sizick * Common Development and Distribution License (the "License"). 6690caf98Sizick * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate * 21436935a1SVladimir Kotal */ 22436935a1SVladimir Kotal /* 23d3b2efc7SAnthony Scarpino * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 327c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * des_crypt.c, DES encryption library routines 377c478bd9Sstevel@tonic-gate */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <sys/errno.h> 407c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <sys/systm.h> 437c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 447c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 457c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h> 467c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h> 477c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 487c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 497c478bd9Sstevel@tonic-gate #include <sys/note.h> 5023c57df7Smcpowers #include <modes/modes.h> 51*6ea3c060SGarrett D'Amore #define _DES_IMPL 5223c57df7Smcpowers #include <des/des_impl.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #include <sys/types.h> 557c478bd9Sstevel@tonic-gate #include <rpc/des_crypt.h> 567c478bd9Sstevel@tonic-gate #include <des/des.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #ifdef sun_hardware 597c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 607c478bd9Sstevel@tonic-gate #ifdef _KERNEL 617c478bd9Sstevel@tonic-gate #include <sys/conf.h> 627c478bd9Sstevel@tonic-gate static int g_desfd = -1; 637c478bd9Sstevel@tonic-gate #define getdesfd() (cdevsw[11].d_open(0, 0) ? -1 : 0) 647c478bd9Sstevel@tonic-gate #define ioctl(a, b, c) (cdevsw[11].d_ioctl(0, b, c, 0) ? -1 : 0) 657c478bd9Sstevel@tonic-gate #else 667c478bd9Sstevel@tonic-gate #define getdesfd() (open("/dev/des", 0, 0)) 677c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 687c478bd9Sstevel@tonic-gate #endif /* sun */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static int common_crypt(char *key, char *buf, size_t len, 717c478bd9Sstevel@tonic-gate unsigned int mode, struct desparams *desp); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate extern int _des_crypt(char *buf, size_t len, struct desparams *desp); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate extern struct mod_ops mod_cryptoops; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 817c478bd9Sstevel@tonic-gate &mod_miscops, 827c478bd9Sstevel@tonic-gate "des encryption", 837c478bd9Sstevel@tonic-gate }; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 867c478bd9Sstevel@tonic-gate &mod_cryptoops, 87d2b32306Smcpowers "DES Kernel SW Provider" 887c478bd9Sstevel@tonic-gate }; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 917c478bd9Sstevel@tonic-gate MODREV_1, 927c478bd9Sstevel@tonic-gate &modlmisc, 937c478bd9Sstevel@tonic-gate &modlcrypto, 947c478bd9Sstevel@tonic-gate NULL 957c478bd9Sstevel@tonic-gate }; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #define DES_MIN_KEY_LEN DES_MINBYTES 987c478bd9Sstevel@tonic-gate #define DES_MAX_KEY_LEN DES_MAXBYTES 99436935a1SVladimir Kotal #define DES3_MIN_KEY_LEN DES3_MAXBYTES /* no CKK_DES2 support */ 1007c478bd9Sstevel@tonic-gate #define DES3_MAX_KEY_LEN DES3_MAXBYTES 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate #ifndef DES_MIN_KEY_LEN 1037c478bd9Sstevel@tonic-gate #define DES_MIN_KEY_LEN 0 1047c478bd9Sstevel@tonic-gate #endif 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #ifndef DES_MAX_KEY_LEN 1077c478bd9Sstevel@tonic-gate #define DES_MAX_KEY_LEN 0 1087c478bd9Sstevel@tonic-gate #endif 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate #ifndef DES3_MIN_KEY_LEN 1117c478bd9Sstevel@tonic-gate #define DES3_MIN_KEY_LEN 0 1127c478bd9Sstevel@tonic-gate #endif 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate #ifndef DES3_MAX_KEY_LEN 1157c478bd9Sstevel@tonic-gate #define DES3_MAX_KEY_LEN 0 1167c478bd9Sstevel@tonic-gate #endif 1177c478bd9Sstevel@tonic-gate 118b5a2d845SHai-May Chao 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate static crypto_mech_info_t des_mech_info_tab[] = { 1237c478bd9Sstevel@tonic-gate /* DES_ECB */ 1247c478bd9Sstevel@tonic-gate {SUN_CKM_DES_ECB, DES_ECB_MECH_INFO_TYPE, 1257c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1267c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 1277c478bd9Sstevel@tonic-gate DES_MIN_KEY_LEN, DES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES}, 1287c478bd9Sstevel@tonic-gate /* DES_CBC */ 1297c478bd9Sstevel@tonic-gate {SUN_CKM_DES_CBC, DES_CBC_MECH_INFO_TYPE, 1307c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1317c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 1327c478bd9Sstevel@tonic-gate DES_MIN_KEY_LEN, DES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES}, 1337c478bd9Sstevel@tonic-gate /* DES3_ECB */ 1347c478bd9Sstevel@tonic-gate {SUN_CKM_DES3_ECB, DES3_ECB_MECH_INFO_TYPE, 1357c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1367c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 1377c478bd9Sstevel@tonic-gate DES3_MIN_KEY_LEN, DES3_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES}, 1387c478bd9Sstevel@tonic-gate /* DES3_CBC */ 1397c478bd9Sstevel@tonic-gate {SUN_CKM_DES3_CBC, DES3_CBC_MECH_INFO_TYPE, 1407c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1417c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC, 1427c478bd9Sstevel@tonic-gate DES3_MIN_KEY_LEN, DES3_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES} 1437c478bd9Sstevel@tonic-gate }; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */ 1467c478bd9Sstevel@tonic-gate #define DES_ARG_INPLACE(input, output) \ 1477c478bd9Sstevel@tonic-gate if ((output) == NULL) \ 1487c478bd9Sstevel@tonic-gate (output) = (input); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate static void des_provider_status(crypto_provider_handle_t, uint_t *); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate static crypto_control_ops_t des_control_ops = { 1537c478bd9Sstevel@tonic-gate des_provider_status 1547c478bd9Sstevel@tonic-gate }; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate static int 1577c478bd9Sstevel@tonic-gate des_common_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 1587c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 1597c478bd9Sstevel@tonic-gate static int des_common_init_ctx(des_ctx_t *, crypto_spi_ctx_template_t *, 1607c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, des_strength_t, int); 1617c478bd9Sstevel@tonic-gate static int des_encrypt_final(crypto_ctx_t *, crypto_data_t *, 1627c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1637c478bd9Sstevel@tonic-gate static int des_decrypt_final(crypto_ctx_t *, crypto_data_t *, 1647c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static int des_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1677c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1687c478bd9Sstevel@tonic-gate static int des_encrypt_update(crypto_ctx_t *, crypto_data_t *, 1697c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t); 1707c478bd9Sstevel@tonic-gate static int des_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t, 1717c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 1727c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate static int des_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1757c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1767c478bd9Sstevel@tonic-gate static int des_decrypt_update(crypto_ctx_t *, crypto_data_t *, 1777c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t); 1787c478bd9Sstevel@tonic-gate static int des_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t, 1797c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 1807c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate static crypto_cipher_ops_t des_cipher_ops = { 1837c478bd9Sstevel@tonic-gate des_common_init, 1847c478bd9Sstevel@tonic-gate des_encrypt, 1857c478bd9Sstevel@tonic-gate des_encrypt_update, 1867c478bd9Sstevel@tonic-gate des_encrypt_final, 1877c478bd9Sstevel@tonic-gate des_encrypt_atomic, 1887c478bd9Sstevel@tonic-gate des_common_init, 1897c478bd9Sstevel@tonic-gate des_decrypt, 1907c478bd9Sstevel@tonic-gate des_decrypt_update, 1917c478bd9Sstevel@tonic-gate des_decrypt_final, 1927c478bd9Sstevel@tonic-gate des_decrypt_atomic 1937c478bd9Sstevel@tonic-gate }; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate static int des_create_ctx_template(crypto_provider_handle_t, 1967c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 1977c478bd9Sstevel@tonic-gate size_t *, crypto_req_handle_t); 1987c478bd9Sstevel@tonic-gate static int des_free_context(crypto_ctx_t *); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate static crypto_ctx_ops_t des_ctx_ops = { 2017c478bd9Sstevel@tonic-gate des_create_ctx_template, 2027c478bd9Sstevel@tonic-gate des_free_context 2037c478bd9Sstevel@tonic-gate }; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate static int des_key_check(crypto_provider_handle_t, crypto_mechanism_t *, 2067c478bd9Sstevel@tonic-gate crypto_key_t *); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate static crypto_key_ops_t des_key_ops = { 2097c478bd9Sstevel@tonic-gate NULL, 2107c478bd9Sstevel@tonic-gate NULL, 2117c478bd9Sstevel@tonic-gate NULL, 2127c478bd9Sstevel@tonic-gate NULL, 2137c478bd9Sstevel@tonic-gate NULL, 2147c478bd9Sstevel@tonic-gate des_key_check 2157c478bd9Sstevel@tonic-gate }; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static crypto_ops_t des_crypto_ops = { 2187c478bd9Sstevel@tonic-gate &des_control_ops, 2197c478bd9Sstevel@tonic-gate NULL, 2207c478bd9Sstevel@tonic-gate &des_cipher_ops, 2217c478bd9Sstevel@tonic-gate NULL, 2227c478bd9Sstevel@tonic-gate NULL, 2237c478bd9Sstevel@tonic-gate NULL, 2247c478bd9Sstevel@tonic-gate NULL, 2257c478bd9Sstevel@tonic-gate NULL, 2267c478bd9Sstevel@tonic-gate NULL, 2277c478bd9Sstevel@tonic-gate NULL, 2287c478bd9Sstevel@tonic-gate NULL, 2297c478bd9Sstevel@tonic-gate &des_key_ops, 2307c478bd9Sstevel@tonic-gate NULL, 23173556491SAnthony Scarpino &des_ctx_ops, 23273556491SAnthony Scarpino NULL, 23373556491SAnthony Scarpino NULL, 234*6ea3c060SGarrett D'Amore NULL 2357c478bd9Sstevel@tonic-gate }; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate static crypto_provider_info_t des_prov_info = { 23873556491SAnthony Scarpino CRYPTO_SPI_VERSION_4, 2397c478bd9Sstevel@tonic-gate "DES Software Provider", 2407c478bd9Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 2417c478bd9Sstevel@tonic-gate {&modlinkage}, 2427c478bd9Sstevel@tonic-gate NULL, 2437c478bd9Sstevel@tonic-gate &des_crypto_ops, 2447c478bd9Sstevel@tonic-gate sizeof (des_mech_info_tab)/sizeof (crypto_mech_info_t), 2457c478bd9Sstevel@tonic-gate des_mech_info_tab 2467c478bd9Sstevel@tonic-gate }; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static crypto_kcf_provider_handle_t des_prov_handle = NULL; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate int 2517c478bd9Sstevel@tonic-gate _init(void) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate int ret; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) 2567c478bd9Sstevel@tonic-gate return (ret); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 259d3b2efc7SAnthony Scarpino * Register with KCF. If the registration fails, kcf will log an 2607c478bd9Sstevel@tonic-gate * error but do not uninstall the module, since the functionality 2617c478bd9Sstevel@tonic-gate * provided by misc/des should still be available. 262d3b2efc7SAnthony Scarpino * 2637c478bd9Sstevel@tonic-gate */ 264d3b2efc7SAnthony Scarpino (void) crypto_register_provider(&des_prov_info, &des_prov_handle); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate return (0); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate int 2717c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * Copy 8 bytes 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate #define COPY8(src, dst) { \ 2807c478bd9Sstevel@tonic-gate char *a = (char *)dst; \ 2817c478bd9Sstevel@tonic-gate char *b = (char *)src; \ 2827c478bd9Sstevel@tonic-gate *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ 2837c478bd9Sstevel@tonic-gate *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * Copy multiple of 8 bytes 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate #define DESCOPY(src, dst, len) { \ 2907c478bd9Sstevel@tonic-gate char *a = (char *)dst; \ 2917c478bd9Sstevel@tonic-gate char *b = (char *)src; \ 2927c478bd9Sstevel@tonic-gate int i; \ 2937c478bd9Sstevel@tonic-gate for (i = (size_t)len; i > 0; i -= 8) { \ 2947c478bd9Sstevel@tonic-gate *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ 2957c478bd9Sstevel@tonic-gate *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ 2967c478bd9Sstevel@tonic-gate } \ 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * CBC mode encryption 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3037c478bd9Sstevel@tonic-gate int 3047c478bd9Sstevel@tonic-gate cbc_crypt(char *key, char *buf, size_t len, unsigned int mode, char *ivec) 3057c478bd9Sstevel@tonic-gate { 3067c478bd9Sstevel@tonic-gate int err = 0; 3077c478bd9Sstevel@tonic-gate struct desparams dp; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate dp.des_mode = CBC; 3107c478bd9Sstevel@tonic-gate COPY8(ivec, dp.des_ivec); 3117c478bd9Sstevel@tonic-gate err = common_crypt(key, buf, len, mode, &dp); 3127c478bd9Sstevel@tonic-gate COPY8(dp.des_ivec, ivec); 3137c478bd9Sstevel@tonic-gate return (err); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * ECB mode encryption 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3217c478bd9Sstevel@tonic-gate int 3227c478bd9Sstevel@tonic-gate ecb_crypt(char *key, char *buf, size_t len, unsigned int mode) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate int err = 0; 3257c478bd9Sstevel@tonic-gate struct desparams dp; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate dp.des_mode = ECB; 3287c478bd9Sstevel@tonic-gate err = common_crypt(key, buf, len, mode, &dp); 3297c478bd9Sstevel@tonic-gate return (err); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * Common code to cbc_crypt() & ecb_crypt() 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate static int 3387c478bd9Sstevel@tonic-gate common_crypt(char *key, char *buf, size_t len, unsigned int mode, 3397c478bd9Sstevel@tonic-gate struct desparams *desp) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate int desdev; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if ((len % 8) != 0 || len > DES_MAXDATA) 3447c478bd9Sstevel@tonic-gate return (DESERR_BADPARAM); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate desp->des_dir = 3477c478bd9Sstevel@tonic-gate ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate desdev = mode & DES_DEVMASK; 3507c478bd9Sstevel@tonic-gate COPY8(key, desp->des_key); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate #ifdef sun_hardware 3537c478bd9Sstevel@tonic-gate if (desdev == DES_HW) { 3547c478bd9Sstevel@tonic-gate int res; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if (g_desfd < 0 && 3577c478bd9Sstevel@tonic-gate (g_desfd == -1 || (g_desfd = getdesfd()) < 0)) 3587c478bd9Sstevel@tonic-gate goto software; /* no hardware device */ 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * hardware 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate desp->des_len = len; 3647c478bd9Sstevel@tonic-gate if (len <= DES_QUICKLEN) { 3657c478bd9Sstevel@tonic-gate DESCOPY(buf, desp->des_data, len); 3667c478bd9Sstevel@tonic-gate res = ioctl(g_desfd, DESIOCQUICK, (char *)desp); 3677c478bd9Sstevel@tonic-gate DESCOPY(desp->des_data, buf, len); 3687c478bd9Sstevel@tonic-gate } else { 3697c478bd9Sstevel@tonic-gate desp->des_buf = (uchar_t *)buf; 3707c478bd9Sstevel@tonic-gate res = ioctl(g_desfd, DESIOCBLOCK, (char *)desp); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate return (res == 0 ? DESERR_NONE : DESERR_HWERROR); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate software: 3757c478bd9Sstevel@tonic-gate #endif 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * software 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate if (!_des_crypt(buf, len, desp)) 3807c478bd9Sstevel@tonic-gate return (DESERR_HWERROR); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate return (desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * Initialize key schedules for DES and DES3 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate static int 3897c478bd9Sstevel@tonic-gate init_keysched(crypto_key_t *key, void *newbie, des_strength_t strength) 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate uint8_t corrected_key[DES3_KEYSIZE]; 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * Only keys by value are supported by this module. 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate switch (key->ck_format) { 3977c478bd9Sstevel@tonic-gate case CRYPTO_KEY_RAW: 398436935a1SVladimir Kotal if (strength == DES && key->ck_length != DES_MAXBITS) 3997c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 400436935a1SVladimir Kotal if (strength == DES3 && key->ck_length != DES3_MAXBITS) 4017c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 4027c478bd9Sstevel@tonic-gate break; 4037c478bd9Sstevel@tonic-gate default: 4047c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Fix parity bits. 4097c478bd9Sstevel@tonic-gate * Initialize key schedule even if key is weak. 4107c478bd9Sstevel@tonic-gate */ 411690caf98Sizick if (key->ck_data == NULL) 412690caf98Sizick return (CRYPTO_ARGUMENTS_BAD); 4137c478bd9Sstevel@tonic-gate 414690caf98Sizick des_parity_fix(key->ck_data, strength, corrected_key); 4157c478bd9Sstevel@tonic-gate des_init_keysched(corrected_key, strength, newbie); 4167c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * KCF software provider control entry points. 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4237c478bd9Sstevel@tonic-gate static void 4247c478bd9Sstevel@tonic-gate des_provider_status(crypto_provider_handle_t provider, uint_t *status) 4257c478bd9Sstevel@tonic-gate { 4267c478bd9Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * KCF software provider encrypt entry points. 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate static int 4337c478bd9Sstevel@tonic-gate des_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 4347c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t template, 4357c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 4367c478bd9Sstevel@tonic-gate { 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate des_strength_t strength; 43923c57df7Smcpowers des_ctx_t *des_ctx = NULL; 4407c478bd9Sstevel@tonic-gate int rv; 4417c478bd9Sstevel@tonic-gate int kmflag; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Only keys by value are supported by this module. 4457c478bd9Sstevel@tonic-gate */ 4467c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) { 4477c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 45023c57df7Smcpowers kmflag = crypto_kmflag(req); 4517c478bd9Sstevel@tonic-gate /* Check mechanism type and parameter length */ 4527c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 4537c478bd9Sstevel@tonic-gate case DES_ECB_MECH_INFO_TYPE: 45423c57df7Smcpowers des_ctx = ecb_alloc_ctx(kmflag); 45523c57df7Smcpowers /* FALLTHRU */ 4567c478bd9Sstevel@tonic-gate case DES_CBC_MECH_INFO_TYPE: 4577c478bd9Sstevel@tonic-gate if (mechanism->cm_param != NULL && 4587c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 4597c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 460436935a1SVladimir Kotal if (key->ck_length != DES_MAXBITS) 4617c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 4627c478bd9Sstevel@tonic-gate strength = DES; 46323c57df7Smcpowers if (des_ctx == NULL) 46423c57df7Smcpowers des_ctx = cbc_alloc_ctx(kmflag); 4657c478bd9Sstevel@tonic-gate break; 4667c478bd9Sstevel@tonic-gate case DES3_ECB_MECH_INFO_TYPE: 46723c57df7Smcpowers des_ctx = ecb_alloc_ctx(kmflag); 46823c57df7Smcpowers /* FALLTHRU */ 4697c478bd9Sstevel@tonic-gate case DES3_CBC_MECH_INFO_TYPE: 4707c478bd9Sstevel@tonic-gate if (mechanism->cm_param != NULL && 4717c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 4727c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 473436935a1SVladimir Kotal if (key->ck_length != DES3_MAXBITS) 4747c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 4757c478bd9Sstevel@tonic-gate strength = DES3; 47623c57df7Smcpowers if (des_ctx == NULL) 47723c57df7Smcpowers des_ctx = cbc_alloc_ctx(kmflag); 4787c478bd9Sstevel@tonic-gate break; 4797c478bd9Sstevel@tonic-gate default: 4807c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate if ((rv = des_common_init_ctx(des_ctx, template, mechanism, key, 4847c478bd9Sstevel@tonic-gate strength, kmflag)) != CRYPTO_SUCCESS) { 48523c57df7Smcpowers crypto_free_mode_ctx(des_ctx); 4867c478bd9Sstevel@tonic-gate return (rv); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate ctx->cc_provider_private = des_ctx; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 49423c57df7Smcpowers static void 49523c57df7Smcpowers des_copy_block64(uint8_t *in, uint64_t *out) 4967c478bd9Sstevel@tonic-gate { 49723c57df7Smcpowers if (IS_P2ALIGNED(in, sizeof (uint64_t))) { 4987c478bd9Sstevel@tonic-gate /* LINTED: pointer alignment */ 49923c57df7Smcpowers out[0] = *(uint64_t *)&in[0]; 5007c478bd9Sstevel@tonic-gate } else { 5017c478bd9Sstevel@tonic-gate uint64_t tmp64; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN 50423c57df7Smcpowers tmp64 = (((uint64_t)in[0] << 56) | 50523c57df7Smcpowers ((uint64_t)in[1] << 48) | 50623c57df7Smcpowers ((uint64_t)in[2] << 40) | 50723c57df7Smcpowers ((uint64_t)in[3] << 32) | 50823c57df7Smcpowers ((uint64_t)in[4] << 24) | 50923c57df7Smcpowers ((uint64_t)in[5] << 16) | 51023c57df7Smcpowers ((uint64_t)in[6] << 8) | 51123c57df7Smcpowers (uint64_t)in[7]); 5127c478bd9Sstevel@tonic-gate #else 51323c57df7Smcpowers tmp64 = (((uint64_t)in[7] << 56) | 51423c57df7Smcpowers ((uint64_t)in[6] << 48) | 51523c57df7Smcpowers ((uint64_t)in[5] << 40) | 51623c57df7Smcpowers ((uint64_t)in[4] << 32) | 51723c57df7Smcpowers ((uint64_t)in[3] << 24) | 51823c57df7Smcpowers ((uint64_t)in[2] << 16) | 51923c57df7Smcpowers ((uint64_t)in[1] << 8) | 52023c57df7Smcpowers (uint64_t)in[0]); 5217c478bd9Sstevel@tonic-gate #endif /* _BIG_ENDIAN */ 5227c478bd9Sstevel@tonic-gate 52323c57df7Smcpowers out[0] = tmp64; 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5287c478bd9Sstevel@tonic-gate static int 5297c478bd9Sstevel@tonic-gate des_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 5307c478bd9Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate int ret; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx; 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* 5377c478bd9Sstevel@tonic-gate * Plaintext must be a multiple of the block size. 5387c478bd9Sstevel@tonic-gate * This test only works for non-padded mechanisms 5397c478bd9Sstevel@tonic-gate * when blocksize is 2^N. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate if ((plaintext->cd_length & (DES_BLOCK_LEN - 1)) != 0) 5427c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 5457c478bd9Sstevel@tonic-gate des_ctx = ctx->cc_provider_private; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(plaintext, ciphertext); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 5517c478bd9Sstevel@tonic-gate * We should not destroy the context for the following case. 5527c478bd9Sstevel@tonic-gate */ 5537c478bd9Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) { 5547c478bd9Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length; 5557c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * Do an update on the specified input data. 5607c478bd9Sstevel@tonic-gate */ 5617c478bd9Sstevel@tonic-gate ret = des_encrypt_update(ctx, plaintext, ciphertext, req); 5627c478bd9Sstevel@tonic-gate ASSERT(des_ctx->dc_remainder_len == 0); 5637c478bd9Sstevel@tonic-gate (void) des_free_context(ctx); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* LINTED */ 5667c478bd9Sstevel@tonic-gate return (ret); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5707c478bd9Sstevel@tonic-gate static int 5717c478bd9Sstevel@tonic-gate des_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 5727c478bd9Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req) 5737c478bd9Sstevel@tonic-gate { 5747c478bd9Sstevel@tonic-gate int ret; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * Ciphertext must be a multiple of the block size. 5807c478bd9Sstevel@tonic-gate * This test only works for non-padded mechanisms 5817c478bd9Sstevel@tonic-gate * when blocksize is 2^N. 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate if ((ciphertext->cd_length & (DES_BLOCK_LEN - 1)) != 0) 5847c478bd9Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 5877c478bd9Sstevel@tonic-gate des_ctx = ctx->cc_provider_private; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(ciphertext, plaintext); 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * We need to just return the length needed to store the output. 5937c478bd9Sstevel@tonic-gate * We should not destroy the context for the following case. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) { 5967c478bd9Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length; 5977c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate /* 6017c478bd9Sstevel@tonic-gate * Do an update on the specified input data. 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate ret = des_decrypt_update(ctx, ciphertext, plaintext, req); 6047c478bd9Sstevel@tonic-gate ASSERT(des_ctx->dc_remainder_len == 0); 6057c478bd9Sstevel@tonic-gate (void) des_free_context(ctx); 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate /* LINTED */ 6087c478bd9Sstevel@tonic-gate return (ret); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6127c478bd9Sstevel@tonic-gate static int 6137c478bd9Sstevel@tonic-gate des_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext, 6147c478bd9Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate off_t saved_offset; 6177c478bd9Sstevel@tonic-gate size_t saved_length, out_len; 6187c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(plaintext, ciphertext); 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* compute number of bytes that will hold the ciphertext */ 6257c478bd9Sstevel@tonic-gate out_len = ((des_ctx_t *)ctx->cc_provider_private)->dc_remainder_len; 6267c478bd9Sstevel@tonic-gate out_len += plaintext->cd_length; 6277c478bd9Sstevel@tonic-gate out_len &= ~(DES_BLOCK_LEN - 1); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* return length needed to store the output */ 6307c478bd9Sstevel@tonic-gate if (ciphertext->cd_length < out_len) { 6317c478bd9Sstevel@tonic-gate ciphertext->cd_length = out_len; 6327c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate saved_offset = ciphertext->cd_offset; 6367c478bd9Sstevel@tonic-gate saved_length = ciphertext->cd_length; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * Do the DES update on the specified input data. 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gate switch (plaintext->cd_format) { 6427c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 64323c57df7Smcpowers ret = crypto_update_iov(ctx->cc_provider_private, 64423c57df7Smcpowers plaintext, ciphertext, des_encrypt_contiguous_blocks, 64523c57df7Smcpowers des_copy_block64); 6467c478bd9Sstevel@tonic-gate break; 6477c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 64823c57df7Smcpowers ret = crypto_update_uio(ctx->cc_provider_private, 64923c57df7Smcpowers plaintext, ciphertext, des_encrypt_contiguous_blocks, 65023c57df7Smcpowers des_copy_block64); 6517c478bd9Sstevel@tonic-gate break; 6527c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 65323c57df7Smcpowers ret = crypto_update_mp(ctx->cc_provider_private, 65423c57df7Smcpowers plaintext, ciphertext, des_encrypt_contiguous_blocks, 65523c57df7Smcpowers des_copy_block64); 6567c478bd9Sstevel@tonic-gate break; 6577c478bd9Sstevel@tonic-gate default: 6587c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 6627c478bd9Sstevel@tonic-gate if (plaintext != ciphertext) 6637c478bd9Sstevel@tonic-gate ciphertext->cd_length = 6647c478bd9Sstevel@tonic-gate ciphertext->cd_offset - saved_offset; 6657c478bd9Sstevel@tonic-gate } else { 6667c478bd9Sstevel@tonic-gate ciphertext->cd_length = saved_length; 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate ciphertext->cd_offset = saved_offset; 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate return (ret); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6747c478bd9Sstevel@tonic-gate static int 6757c478bd9Sstevel@tonic-gate des_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 6767c478bd9Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req) 6777c478bd9Sstevel@tonic-gate { 6787c478bd9Sstevel@tonic-gate off_t saved_offset; 6797c478bd9Sstevel@tonic-gate size_t saved_length, out_len; 6807c478bd9Sstevel@tonic-gate int ret = CRYPTO_SUCCESS; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(ciphertext, plaintext); 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* compute number of bytes that will hold the plaintext */ 6877c478bd9Sstevel@tonic-gate out_len = ((des_ctx_t *)ctx->cc_provider_private)->dc_remainder_len; 6887c478bd9Sstevel@tonic-gate out_len += ciphertext->cd_length; 6897c478bd9Sstevel@tonic-gate out_len &= ~(DES_BLOCK_LEN - 1); 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* return length needed to store the output */ 6927c478bd9Sstevel@tonic-gate if (plaintext->cd_length < out_len) { 6937c478bd9Sstevel@tonic-gate plaintext->cd_length = out_len; 6947c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate saved_offset = plaintext->cd_offset; 6987c478bd9Sstevel@tonic-gate saved_length = plaintext->cd_length; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* 7017c478bd9Sstevel@tonic-gate * Do the DES update on the specified input data. 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate switch (ciphertext->cd_format) { 7047c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 70523c57df7Smcpowers ret = crypto_update_iov(ctx->cc_provider_private, 70623c57df7Smcpowers ciphertext, plaintext, des_decrypt_contiguous_blocks, 70723c57df7Smcpowers des_copy_block64); 7087c478bd9Sstevel@tonic-gate break; 7097c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 71023c57df7Smcpowers ret = crypto_update_uio(ctx->cc_provider_private, 71123c57df7Smcpowers ciphertext, plaintext, des_decrypt_contiguous_blocks, 71223c57df7Smcpowers des_copy_block64); 7137c478bd9Sstevel@tonic-gate break; 7147c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 71523c57df7Smcpowers ret = crypto_update_mp(ctx->cc_provider_private, 71623c57df7Smcpowers ciphertext, plaintext, des_decrypt_contiguous_blocks, 71723c57df7Smcpowers des_copy_block64); 7187c478bd9Sstevel@tonic-gate break; 7197c478bd9Sstevel@tonic-gate default: 7207c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 7247c478bd9Sstevel@tonic-gate if (ciphertext != plaintext) 7257c478bd9Sstevel@tonic-gate plaintext->cd_length = 7267c478bd9Sstevel@tonic-gate plaintext->cd_offset - saved_offset; 7277c478bd9Sstevel@tonic-gate } else { 7287c478bd9Sstevel@tonic-gate plaintext->cd_length = saved_length; 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate plaintext->cd_offset = saved_offset; 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate return (ret); 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7367c478bd9Sstevel@tonic-gate static int 7377c478bd9Sstevel@tonic-gate des_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 7387c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 7437c478bd9Sstevel@tonic-gate des_ctx = ctx->cc_provider_private; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* 7467c478bd9Sstevel@tonic-gate * There must be no unprocessed plaintext. 7477c478bd9Sstevel@tonic-gate * This happens if the length of the last data is 7487c478bd9Sstevel@tonic-gate * not a multiple of the DES block length. 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate if (des_ctx->dc_remainder_len > 0) 7517c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate (void) des_free_context(ctx); 7547c478bd9Sstevel@tonic-gate ciphertext->cd_length = 0; 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7607c478bd9Sstevel@tonic-gate static int 7617c478bd9Sstevel@tonic-gate des_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *plaintext, 7627c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 7677c478bd9Sstevel@tonic-gate des_ctx = ctx->cc_provider_private; 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate /* 7707c478bd9Sstevel@tonic-gate * There must be no unprocessed ciphertext. 7717c478bd9Sstevel@tonic-gate * This happens if the length of the last ciphertext is 7727c478bd9Sstevel@tonic-gate * not a multiple of the DES block length. 7737c478bd9Sstevel@tonic-gate */ 7747c478bd9Sstevel@tonic-gate if (des_ctx->dc_remainder_len > 0) 7757c478bd9Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate (void) des_free_context(ctx); 7787c478bd9Sstevel@tonic-gate plaintext->cd_length = 0; 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7847c478bd9Sstevel@tonic-gate static int 7857c478bd9Sstevel@tonic-gate des_encrypt_atomic(crypto_provider_handle_t provider, 7867c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 7877c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 7887c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate int ret; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate des_ctx_t des_ctx; /* on the stack */ 7937c478bd9Sstevel@tonic-gate des_strength_t strength; 7947c478bd9Sstevel@tonic-gate off_t saved_offset; 7957c478bd9Sstevel@tonic-gate size_t saved_length; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(plaintext, ciphertext); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* 8007c478bd9Sstevel@tonic-gate * Plaintext must be a multiple of the block size. 8017c478bd9Sstevel@tonic-gate * This test only works for non-padded mechanisms 8027c478bd9Sstevel@tonic-gate * when blocksize is 2^N. 8037c478bd9Sstevel@tonic-gate */ 8047c478bd9Sstevel@tonic-gate if ((plaintext->cd_length & (DES_BLOCK_LEN - 1)) != 0) 8057c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* return length needed to store the output */ 8087c478bd9Sstevel@tonic-gate if (ciphertext->cd_length < plaintext->cd_length) { 8097c478bd9Sstevel@tonic-gate ciphertext->cd_length = plaintext->cd_length; 8107c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* Check mechanism type and parameter length */ 8147c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 8157c478bd9Sstevel@tonic-gate case DES_ECB_MECH_INFO_TYPE: 8167c478bd9Sstevel@tonic-gate case DES_CBC_MECH_INFO_TYPE: 8177c478bd9Sstevel@tonic-gate if (mechanism->cm_param_len > 0 && 8187c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 8197c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 8207c478bd9Sstevel@tonic-gate if (key->ck_length != DES_MINBITS) 8217c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 8227c478bd9Sstevel@tonic-gate strength = DES; 8237c478bd9Sstevel@tonic-gate break; 8247c478bd9Sstevel@tonic-gate case DES3_ECB_MECH_INFO_TYPE: 8257c478bd9Sstevel@tonic-gate case DES3_CBC_MECH_INFO_TYPE: 8267c478bd9Sstevel@tonic-gate if (mechanism->cm_param_len > 0 && 8277c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 8287c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 829436935a1SVladimir Kotal if (key->ck_length != DES3_MAXBITS) 8307c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 8317c478bd9Sstevel@tonic-gate strength = DES3; 8327c478bd9Sstevel@tonic-gate break; 8337c478bd9Sstevel@tonic-gate default: 8347c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate bzero(&des_ctx, sizeof (des_ctx_t)); 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if ((ret = des_common_init_ctx(&des_ctx, template, mechanism, key, 8407c478bd9Sstevel@tonic-gate strength, crypto_kmflag(req))) != CRYPTO_SUCCESS) { 8417c478bd9Sstevel@tonic-gate return (ret); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate saved_offset = ciphertext->cd_offset; 8457c478bd9Sstevel@tonic-gate saved_length = ciphertext->cd_length; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate * Do the update on the specified input data. 8497c478bd9Sstevel@tonic-gate */ 8507c478bd9Sstevel@tonic-gate switch (plaintext->cd_format) { 8517c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 85223c57df7Smcpowers ret = crypto_update_iov(&des_ctx, plaintext, ciphertext, 85323c57df7Smcpowers des_encrypt_contiguous_blocks, des_copy_block64); 8547c478bd9Sstevel@tonic-gate break; 8557c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 85623c57df7Smcpowers ret = crypto_update_uio(&des_ctx, plaintext, ciphertext, 85723c57df7Smcpowers des_encrypt_contiguous_blocks, des_copy_block64); 8587c478bd9Sstevel@tonic-gate break; 8597c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 86023c57df7Smcpowers ret = crypto_update_mp(&des_ctx, plaintext, ciphertext, 86123c57df7Smcpowers des_encrypt_contiguous_blocks, des_copy_block64); 8627c478bd9Sstevel@tonic-gate break; 8637c478bd9Sstevel@tonic-gate default: 8647c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 86723c57df7Smcpowers if (des_ctx.dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 8687c478bd9Sstevel@tonic-gate bzero(des_ctx.dc_keysched, des_ctx.dc_keysched_len); 8697c478bd9Sstevel@tonic-gate kmem_free(des_ctx.dc_keysched, des_ctx.dc_keysched_len); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 8737c478bd9Sstevel@tonic-gate ASSERT(des_ctx.dc_remainder_len == 0); 8747c478bd9Sstevel@tonic-gate if (plaintext != ciphertext) 8757c478bd9Sstevel@tonic-gate ciphertext->cd_length = 8767c478bd9Sstevel@tonic-gate ciphertext->cd_offset - saved_offset; 8777c478bd9Sstevel@tonic-gate } else { 8787c478bd9Sstevel@tonic-gate ciphertext->cd_length = saved_length; 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate ciphertext->cd_offset = saved_offset; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* LINTED */ 8837c478bd9Sstevel@tonic-gate return (ret); 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8877c478bd9Sstevel@tonic-gate static int 8887c478bd9Sstevel@tonic-gate des_decrypt_atomic(crypto_provider_handle_t provider, 8897c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 8907c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 8917c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 8927c478bd9Sstevel@tonic-gate { 8937c478bd9Sstevel@tonic-gate int ret; 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate des_ctx_t des_ctx; /* on the stack */ 8967c478bd9Sstevel@tonic-gate des_strength_t strength; 8977c478bd9Sstevel@tonic-gate off_t saved_offset; 8987c478bd9Sstevel@tonic-gate size_t saved_length; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate DES_ARG_INPLACE(ciphertext, plaintext); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate /* 9037c478bd9Sstevel@tonic-gate * Ciphertext must be a multiple of the block size. 9047c478bd9Sstevel@tonic-gate * This test only works for non-padded mechanisms 9057c478bd9Sstevel@tonic-gate * when blocksize is 2^N. 9067c478bd9Sstevel@tonic-gate */ 9077c478bd9Sstevel@tonic-gate if ((ciphertext->cd_length & (DES_BLOCK_LEN - 1)) != 0) 9087c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate /* return length needed to store the output */ 9117c478bd9Sstevel@tonic-gate if (plaintext->cd_length < ciphertext->cd_length) { 9127c478bd9Sstevel@tonic-gate plaintext->cd_length = ciphertext->cd_length; 9137c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* Check mechanism type and parameter length */ 9177c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 9187c478bd9Sstevel@tonic-gate case DES_ECB_MECH_INFO_TYPE: 9197c478bd9Sstevel@tonic-gate case DES_CBC_MECH_INFO_TYPE: 9207c478bd9Sstevel@tonic-gate if (mechanism->cm_param_len > 0 && 9217c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 9227c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 9237c478bd9Sstevel@tonic-gate if (key->ck_length != DES_MINBITS) 9247c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 9257c478bd9Sstevel@tonic-gate strength = DES; 9267c478bd9Sstevel@tonic-gate break; 9277c478bd9Sstevel@tonic-gate case DES3_ECB_MECH_INFO_TYPE: 9287c478bd9Sstevel@tonic-gate case DES3_CBC_MECH_INFO_TYPE: 9297c478bd9Sstevel@tonic-gate if (mechanism->cm_param_len > 0 && 9307c478bd9Sstevel@tonic-gate mechanism->cm_param_len != DES_BLOCK_LEN) 9317c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_PARAM_INVALID); 932436935a1SVladimir Kotal if (key->ck_length != DES3_MAXBITS) 9337c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 9347c478bd9Sstevel@tonic-gate strength = DES3; 9357c478bd9Sstevel@tonic-gate break; 9367c478bd9Sstevel@tonic-gate default: 9377c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate bzero(&des_ctx, sizeof (des_ctx_t)); 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate if ((ret = des_common_init_ctx(&des_ctx, template, mechanism, key, 9437c478bd9Sstevel@tonic-gate strength, crypto_kmflag(req))) != CRYPTO_SUCCESS) { 9447c478bd9Sstevel@tonic-gate return (ret); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate saved_offset = plaintext->cd_offset; 9487c478bd9Sstevel@tonic-gate saved_length = plaintext->cd_length; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* 9517c478bd9Sstevel@tonic-gate * Do the update on the specified input data. 9527c478bd9Sstevel@tonic-gate */ 9537c478bd9Sstevel@tonic-gate switch (ciphertext->cd_format) { 9547c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 95523c57df7Smcpowers ret = crypto_update_iov(&des_ctx, ciphertext, plaintext, 95623c57df7Smcpowers des_decrypt_contiguous_blocks, des_copy_block64); 9577c478bd9Sstevel@tonic-gate break; 9587c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 95923c57df7Smcpowers ret = crypto_update_uio(&des_ctx, ciphertext, plaintext, 96023c57df7Smcpowers des_decrypt_contiguous_blocks, des_copy_block64); 9617c478bd9Sstevel@tonic-gate break; 9627c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 96323c57df7Smcpowers ret = crypto_update_mp(&des_ctx, ciphertext, plaintext, 96423c57df7Smcpowers des_decrypt_contiguous_blocks, des_copy_block64); 9657c478bd9Sstevel@tonic-gate break; 9667c478bd9Sstevel@tonic-gate default: 9677c478bd9Sstevel@tonic-gate ret = CRYPTO_ARGUMENTS_BAD; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 97023c57df7Smcpowers if (des_ctx.dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 9717c478bd9Sstevel@tonic-gate bzero(des_ctx.dc_keysched, des_ctx.dc_keysched_len); 9727c478bd9Sstevel@tonic-gate kmem_free(des_ctx.dc_keysched, des_ctx.dc_keysched_len); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if (ret == CRYPTO_SUCCESS) { 9767c478bd9Sstevel@tonic-gate ASSERT(des_ctx.dc_remainder_len == 0); 9777c478bd9Sstevel@tonic-gate if (ciphertext != plaintext) 9787c478bd9Sstevel@tonic-gate plaintext->cd_length = 9797c478bd9Sstevel@tonic-gate plaintext->cd_offset - saved_offset; 9807c478bd9Sstevel@tonic-gate } else { 9817c478bd9Sstevel@tonic-gate plaintext->cd_length = saved_length; 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate plaintext->cd_offset = saved_offset; 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* LINTED */ 9867c478bd9Sstevel@tonic-gate return (ret); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate /* 9907c478bd9Sstevel@tonic-gate * KCF software provider context template entry points. 9917c478bd9Sstevel@tonic-gate */ 9927c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9937c478bd9Sstevel@tonic-gate static int 9947c478bd9Sstevel@tonic-gate des_create_ctx_template(crypto_provider_handle_t provider, 9957c478bd9Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, 9967c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req) 9977c478bd9Sstevel@tonic-gate { 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate des_strength_t strength; 10007c478bd9Sstevel@tonic-gate void *keysched; 10017c478bd9Sstevel@tonic-gate size_t size; 10027c478bd9Sstevel@tonic-gate int rv; 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 10057c478bd9Sstevel@tonic-gate case DES_ECB_MECH_INFO_TYPE: 10067c478bd9Sstevel@tonic-gate strength = DES; 10077c478bd9Sstevel@tonic-gate break; 10087c478bd9Sstevel@tonic-gate case DES_CBC_MECH_INFO_TYPE: 10097c478bd9Sstevel@tonic-gate strength = DES; 10107c478bd9Sstevel@tonic-gate break; 10117c478bd9Sstevel@tonic-gate case DES3_ECB_MECH_INFO_TYPE: 10127c478bd9Sstevel@tonic-gate strength = DES3; 10137c478bd9Sstevel@tonic-gate break; 10147c478bd9Sstevel@tonic-gate case DES3_CBC_MECH_INFO_TYPE: 10157c478bd9Sstevel@tonic-gate strength = DES3; 10167c478bd9Sstevel@tonic-gate break; 10177c478bd9Sstevel@tonic-gate default: 10187c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if ((keysched = des_alloc_keysched(&size, strength, 10227c478bd9Sstevel@tonic-gate crypto_kmflag(req))) == NULL) { 10237c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * Initialize key schedule. Key length information is stored 10287c478bd9Sstevel@tonic-gate * in the key. 10297c478bd9Sstevel@tonic-gate */ 10307c478bd9Sstevel@tonic-gate if ((rv = init_keysched(key, keysched, strength)) != CRYPTO_SUCCESS) { 10317c478bd9Sstevel@tonic-gate bzero(keysched, size); 10327c478bd9Sstevel@tonic-gate kmem_free(keysched, size); 10337c478bd9Sstevel@tonic-gate return (rv); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate *tmpl = keysched; 10377c478bd9Sstevel@tonic-gate *tmpl_size = size; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10437c478bd9Sstevel@tonic-gate static int 10447c478bd9Sstevel@tonic-gate des_free_context(crypto_ctx_t *ctx) 10457c478bd9Sstevel@tonic-gate { 10467c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx = ctx->cc_provider_private; 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate if (des_ctx != NULL) { 104923c57df7Smcpowers if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 10507c478bd9Sstevel@tonic-gate ASSERT(des_ctx->dc_keysched_len != 0); 10517c478bd9Sstevel@tonic-gate bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len); 10527c478bd9Sstevel@tonic-gate kmem_free(des_ctx->dc_keysched, 10537c478bd9Sstevel@tonic-gate des_ctx->dc_keysched_len); 10547c478bd9Sstevel@tonic-gate } 105523c57df7Smcpowers crypto_free_mode_ctx(des_ctx); 10567c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate /* 10637c478bd9Sstevel@tonic-gate * Pass it to des_keycheck() which will 10647c478bd9Sstevel@tonic-gate * fix it (parity bits), and check if the fixed key is weak. 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10677c478bd9Sstevel@tonic-gate static int 10687c478bd9Sstevel@tonic-gate des_key_check(crypto_provider_handle_t pd, crypto_mechanism_t *mech, 10697c478bd9Sstevel@tonic-gate crypto_key_t *key) 10707c478bd9Sstevel@tonic-gate { 10717c478bd9Sstevel@tonic-gate int expectedkeylen; 10727c478bd9Sstevel@tonic-gate des_strength_t strength; 10737c478bd9Sstevel@tonic-gate uint8_t keydata[DES3_MAX_KEY_LEN]; 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if ((mech == NULL) || (key == NULL)) 10767c478bd9Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD); 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate switch (mech->cm_type) { 10797c478bd9Sstevel@tonic-gate case DES_ECB_MECH_INFO_TYPE: 10807c478bd9Sstevel@tonic-gate case DES_CBC_MECH_INFO_TYPE: 10817c478bd9Sstevel@tonic-gate expectedkeylen = DES_MINBITS; 10827c478bd9Sstevel@tonic-gate strength = DES; 10837c478bd9Sstevel@tonic-gate break; 10847c478bd9Sstevel@tonic-gate case DES3_ECB_MECH_INFO_TYPE: 10857c478bd9Sstevel@tonic-gate case DES3_CBC_MECH_INFO_TYPE: 1086436935a1SVladimir Kotal expectedkeylen = DES3_MAXBITS; 10877c478bd9Sstevel@tonic-gate strength = DES3; 10887c478bd9Sstevel@tonic-gate break; 10897c478bd9Sstevel@tonic-gate default: 10907c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_RAW) 10947c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate if (key->ck_length != expectedkeylen) 10977c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate bcopy(key->ck_data, keydata, CRYPTO_BITS2BYTES(expectedkeylen)); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate if (des_keycheck(keydata, strength, key->ck_data) == B_FALSE) 11027c478bd9Sstevel@tonic-gate return (CRYPTO_WEAK_KEY); 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11087c478bd9Sstevel@tonic-gate static int 11097c478bd9Sstevel@tonic-gate des_common_init_ctx(des_ctx_t *des_ctx, crypto_spi_ctx_template_t *template, 11107c478bd9Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, des_strength_t strength, 11117c478bd9Sstevel@tonic-gate int kmflag) 11127c478bd9Sstevel@tonic-gate { 11137c478bd9Sstevel@tonic-gate int rv = CRYPTO_SUCCESS; 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate void *keysched; 11167c478bd9Sstevel@tonic-gate size_t size; 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate if (template == NULL) { 11197c478bd9Sstevel@tonic-gate if ((keysched = des_alloc_keysched(&size, strength, 11207c478bd9Sstevel@tonic-gate kmflag)) == NULL) 11217c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 11227c478bd9Sstevel@tonic-gate /* 11237c478bd9Sstevel@tonic-gate * Initialize key schedule. 11247c478bd9Sstevel@tonic-gate * Key length is stored in the key. 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate if ((rv = init_keysched(key, keysched, 11277c478bd9Sstevel@tonic-gate strength)) != CRYPTO_SUCCESS) 11287c478bd9Sstevel@tonic-gate kmem_free(keysched, size); 11297c478bd9Sstevel@tonic-gate 113023c57df7Smcpowers des_ctx->dc_flags |= PROVIDER_OWNS_KEY_SCHEDULE; 11317c478bd9Sstevel@tonic-gate des_ctx->dc_keysched_len = size; 11327c478bd9Sstevel@tonic-gate } else { 11337c478bd9Sstevel@tonic-gate keysched = template; 11347c478bd9Sstevel@tonic-gate } 113523c57df7Smcpowers des_ctx->dc_keysched = keysched; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate if (strength == DES3) { 11387c478bd9Sstevel@tonic-gate des_ctx->dc_flags |= DES3_STRENGTH; 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 114123c57df7Smcpowers switch (mechanism->cm_type) { 114223c57df7Smcpowers case DES_CBC_MECH_INFO_TYPE: 114323c57df7Smcpowers case DES3_CBC_MECH_INFO_TYPE: 114423c57df7Smcpowers rv = cbc_init_ctx((cbc_ctx_t *)des_ctx, mechanism->cm_param, 114523c57df7Smcpowers mechanism->cm_param_len, DES_BLOCK_LEN, des_copy_block64); 114623c57df7Smcpowers break; 114723c57df7Smcpowers case DES_ECB_MECH_INFO_TYPE: 114823c57df7Smcpowers case DES3_ECB_MECH_INFO_TYPE: 114923c57df7Smcpowers des_ctx->dc_flags |= ECB_MODE; 11507c478bd9Sstevel@tonic-gate } 11517c478bd9Sstevel@tonic-gate 115223c57df7Smcpowers if (rv != CRYPTO_SUCCESS) { 115323c57df7Smcpowers if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) { 115423c57df7Smcpowers bzero(keysched, size); 115523c57df7Smcpowers kmem_free(keysched, size); 11567c478bd9Sstevel@tonic-gate } 115723c57df7Smcpowers } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate return (rv); 11607c478bd9Sstevel@tonic-gate } 1161