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 5d2b32306Smcpowers * Common Development and Distribution License (the "License"). 6d2b32306Smcpowers * 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 */ 21726fad2aSDina K Nimeh 227c478bd9Sstevel@tonic-gate /* 23726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * RSA provider for the Kernel Cryptographic Framework (KCF) 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/systm.h> 327c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 347c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 357c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h> 367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 377c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 387c478bd9Sstevel@tonic-gate #include <sys/md5.h> 397c478bd9Sstevel@tonic-gate #include <sys/sha1.h> 40b5a2d845SHai-May Chao #define _SHA2_IMPL 41f66d273dSizick #include <sys/sha2.h> 427c478bd9Sstevel@tonic-gate #include <sys/random.h> 4323c57df7Smcpowers #include <sys/crypto/impl.h> 44b5a2d845SHai-May Chao #include <sha1/sha1_impl.h> 45b5a2d845SHai-May Chao #include <sha2/sha2_impl.h> 46726fad2aSDina K Nimeh #include <padding/padding.h> 47b5a2d845SHai-May Chao #include <rsa/rsa_impl.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate extern struct mod_ops mod_cryptoops; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate static struct modlcrypto modlcrypto = { 557c478bd9Sstevel@tonic-gate &mod_cryptoops, 56d2b32306Smcpowers "RSA Kernel SW Provider" 577c478bd9Sstevel@tonic-gate }; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 607c478bd9Sstevel@tonic-gate MODREV_1, 617c478bd9Sstevel@tonic-gate (void *)&modlcrypto, 627c478bd9Sstevel@tonic-gate NULL 637c478bd9Sstevel@tonic-gate }; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * CSPI information (entry points, provider info, etc.) 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate typedef enum rsa_mech_type { 697c478bd9Sstevel@tonic-gate RSA_PKCS_MECH_INFO_TYPE, /* SUN_CKM_RSA_PKCS */ 707c478bd9Sstevel@tonic-gate RSA_X_509_MECH_INFO_TYPE, /* SUN_CKM_RSA_X_509 */ 717c478bd9Sstevel@tonic-gate MD5_RSA_PKCS_MECH_INFO_TYPE, /* SUN_MD5_RSA_PKCS */ 72f66d273dSizick SHA1_RSA_PKCS_MECH_INFO_TYPE, /* SUN_SHA1_RSA_PKCS */ 73f66d273dSizick SHA256_RSA_PKCS_MECH_INFO_TYPE, /* SUN_SHA256_RSA_PKCS */ 74f66d273dSizick SHA384_RSA_PKCS_MECH_INFO_TYPE, /* SUN_SHA384_RSA_PKCS */ 75f66d273dSizick SHA512_RSA_PKCS_MECH_INFO_TYPE /* SUN_SHA512_RSA_PKCS */ 767c478bd9Sstevel@tonic-gate } rsa_mech_type_t; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Context for RSA_PKCS and RSA_X_509 mechanisms. 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate typedef struct rsa_ctx { 827c478bd9Sstevel@tonic-gate rsa_mech_type_t mech_type; 837c478bd9Sstevel@tonic-gate crypto_key_t *key; 847c478bd9Sstevel@tonic-gate size_t keychunk_size; 857c478bd9Sstevel@tonic-gate } rsa_ctx_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 88f66d273dSizick * Context for MD5_RSA_PKCS and SHA*_RSA_PKCS mechanisms. 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate typedef struct digest_rsa_ctx { 917c478bd9Sstevel@tonic-gate rsa_mech_type_t mech_type; 927c478bd9Sstevel@tonic-gate crypto_key_t *key; 937c478bd9Sstevel@tonic-gate size_t keychunk_size; 947c478bd9Sstevel@tonic-gate union { 957c478bd9Sstevel@tonic-gate MD5_CTX md5ctx; 967c478bd9Sstevel@tonic-gate SHA1_CTX sha1ctx; 97f66d273dSizick SHA2_CTX sha2ctx; 987c478bd9Sstevel@tonic-gate } dctx_u; 997c478bd9Sstevel@tonic-gate } digest_rsa_ctx_t; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #define md5_ctx dctx_u.md5ctx 1027c478bd9Sstevel@tonic-gate #define sha1_ctx dctx_u.sha1ctx 103f66d273dSizick #define sha2_ctx dctx_u.sha2ctx 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Mechanism info structure passed to KCF during registration. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate static crypto_mech_info_t rsa_mech_info_tab[] = { 1097c478bd9Sstevel@tonic-gate /* RSA_PKCS */ 1107c478bd9Sstevel@tonic-gate {SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE, 1117c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1127c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC | 1137c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 1147c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC | 1157c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC | 1167c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC, 1177c478bd9Sstevel@tonic-gate RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* RSA_X_509 */ 1207c478bd9Sstevel@tonic-gate {SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE, 1217c478bd9Sstevel@tonic-gate CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC | 1227c478bd9Sstevel@tonic-gate CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC | 1237c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 1247c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC | 1257c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_SIGN_RECOVER_ATOMIC | 1267c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY_RECOVER | CRYPTO_FG_VERIFY_RECOVER_ATOMIC, 1277c478bd9Sstevel@tonic-gate RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* MD5_RSA_PKCS */ 1307c478bd9Sstevel@tonic-gate {SUN_CKM_MD5_RSA_PKCS, MD5_RSA_PKCS_MECH_INFO_TYPE, 1317c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 1327c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC, 1337c478bd9Sstevel@tonic-gate RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* SHA1_RSA_PKCS */ 1367c478bd9Sstevel@tonic-gate {SUN_CKM_SHA1_RSA_PKCS, SHA1_RSA_PKCS_MECH_INFO_TYPE, 1377c478bd9Sstevel@tonic-gate CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 1387c478bd9Sstevel@tonic-gate CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC, 139f66d273dSizick RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 140f66d273dSizick 141f66d273dSizick /* SHA256_RSA_PKCS */ 142f66d273dSizick {SUN_CKM_SHA256_RSA_PKCS, SHA256_RSA_PKCS_MECH_INFO_TYPE, 143f66d273dSizick CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 144f66d273dSizick CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC, 145f66d273dSizick RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 146f66d273dSizick 147f66d273dSizick /* SHA384_RSA_PKCS */ 148f66d273dSizick {SUN_CKM_SHA384_RSA_PKCS, SHA384_RSA_PKCS_MECH_INFO_TYPE, 149f66d273dSizick CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 150f66d273dSizick CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC, 151f66d273dSizick RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 152f66d273dSizick 153f66d273dSizick /* SHA512_RSA_PKCS */ 154f66d273dSizick {SUN_CKM_SHA512_RSA_PKCS, SHA512_RSA_PKCS_MECH_INFO_TYPE, 155f66d273dSizick CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC | 156f66d273dSizick CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC, 1577c478bd9Sstevel@tonic-gate RSA_MIN_KEY_LEN, RSA_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS} 158f66d273dSizick 1597c478bd9Sstevel@tonic-gate }; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate #define RSA_VALID_MECH(mech) \ 1627c478bd9Sstevel@tonic-gate (((mech)->cm_type == RSA_PKCS_MECH_INFO_TYPE || \ 1637c478bd9Sstevel@tonic-gate (mech)->cm_type == RSA_X_509_MECH_INFO_TYPE || \ 1647c478bd9Sstevel@tonic-gate (mech)->cm_type == MD5_RSA_PKCS_MECH_INFO_TYPE || \ 165f66d273dSizick (mech)->cm_type == SHA1_RSA_PKCS_MECH_INFO_TYPE || \ 166f66d273dSizick (mech)->cm_type == SHA256_RSA_PKCS_MECH_INFO_TYPE || \ 167f66d273dSizick (mech)->cm_type == SHA384_RSA_PKCS_MECH_INFO_TYPE || \ 168f66d273dSizick (mech)->cm_type == SHA512_RSA_PKCS_MECH_INFO_TYPE) ? 1 : 0) 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* operations are in-place if the output buffer is NULL */ 1717c478bd9Sstevel@tonic-gate #define RSA_ARG_INPLACE(input, output) \ 1727c478bd9Sstevel@tonic-gate if ((output) == NULL) \ 1737c478bd9Sstevel@tonic-gate (output) = (input); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate static void rsa_provider_status(crypto_provider_handle_t, uint_t *); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate static crypto_control_ops_t rsa_control_ops = { 1787c478bd9Sstevel@tonic-gate rsa_provider_status 1797c478bd9Sstevel@tonic-gate }; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate static int rsa_common_init(crypto_ctx_t *, crypto_mechanism_t *, 1827c478bd9Sstevel@tonic-gate crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 183726fad2aSDina K Nimeh static int rsaprov_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1847c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1857c478bd9Sstevel@tonic-gate static int rsa_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t, 1867c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 1877c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 188726fad2aSDina K Nimeh static int rsaprov_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1897c478bd9Sstevel@tonic-gate crypto_req_handle_t); 1907c478bd9Sstevel@tonic-gate static int rsa_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t, 1917c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 1927c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * The RSA mechanisms do not have multiple-part cipher operations. 1967c478bd9Sstevel@tonic-gate * So, the update and final routines are set to NULL. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate static crypto_cipher_ops_t rsa_cipher_ops = { 1997c478bd9Sstevel@tonic-gate rsa_common_init, 200726fad2aSDina K Nimeh rsaprov_encrypt, 2017c478bd9Sstevel@tonic-gate NULL, 2027c478bd9Sstevel@tonic-gate NULL, 2037c478bd9Sstevel@tonic-gate rsa_encrypt_atomic, 2047c478bd9Sstevel@tonic-gate rsa_common_init, 205726fad2aSDina K Nimeh rsaprov_decrypt, 2067c478bd9Sstevel@tonic-gate NULL, 2077c478bd9Sstevel@tonic-gate NULL, 2087c478bd9Sstevel@tonic-gate rsa_decrypt_atomic 2097c478bd9Sstevel@tonic-gate }; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static int rsa_sign_verify_common_init(crypto_ctx_t *, crypto_mechanism_t *, 2127c478bd9Sstevel@tonic-gate crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 213726fad2aSDina K Nimeh static int rsaprov_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 2147c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2157c478bd9Sstevel@tonic-gate static int rsa_sign_update(crypto_ctx_t *, crypto_data_t *, 2167c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2177c478bd9Sstevel@tonic-gate static int rsa_sign_final(crypto_ctx_t *, crypto_data_t *, 2187c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2197c478bd9Sstevel@tonic-gate static int rsa_sign_atomic(crypto_provider_handle_t, crypto_session_id_t, 2207c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 2217c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t, crypto_req_handle_t); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * We use the same routine for sign_init and sign_recover_init fields 2257c478bd9Sstevel@tonic-gate * as they do the same thing. Same holds for sign and sign_recover fields, 2267c478bd9Sstevel@tonic-gate * and sign_atomic and sign_recover_atomic fields. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate static crypto_sign_ops_t rsa_sign_ops = { 2297c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init, 230726fad2aSDina K Nimeh rsaprov_sign, 2317c478bd9Sstevel@tonic-gate rsa_sign_update, 2327c478bd9Sstevel@tonic-gate rsa_sign_final, 2337c478bd9Sstevel@tonic-gate rsa_sign_atomic, 2347c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init, 235726fad2aSDina K Nimeh rsaprov_sign, 2367c478bd9Sstevel@tonic-gate rsa_sign_atomic 2377c478bd9Sstevel@tonic-gate }; 2387c478bd9Sstevel@tonic-gate 239726fad2aSDina K Nimeh static int rsaprov_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 2407c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2417c478bd9Sstevel@tonic-gate static int rsa_verify_update(crypto_ctx_t *, crypto_data_t *, 2427c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2437c478bd9Sstevel@tonic-gate static int rsa_verify_final(crypto_ctx_t *, crypto_data_t *, 2447c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2457c478bd9Sstevel@tonic-gate static int rsa_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 2467c478bd9Sstevel@tonic-gate crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 2477c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 2487c478bd9Sstevel@tonic-gate static int rsa_verify_recover(crypto_ctx_t *, crypto_data_t *, 2497c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_req_handle_t); 2507c478bd9Sstevel@tonic-gate static int rsa_verify_recover_atomic(crypto_provider_handle_t, 2517c478bd9Sstevel@tonic-gate crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 2527c478bd9Sstevel@tonic-gate crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t, 2537c478bd9Sstevel@tonic-gate crypto_req_handle_t); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * We use the same routine (rsa_sign_verify_common_init) for verify_init 2577c478bd9Sstevel@tonic-gate * and verify_recover_init fields as they do the same thing. 2587c478bd9Sstevel@tonic-gate */ 2597c478bd9Sstevel@tonic-gate static crypto_verify_ops_t rsa_verify_ops = { 2607c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init, 261726fad2aSDina K Nimeh rsaprov_verify, 2627c478bd9Sstevel@tonic-gate rsa_verify_update, 2637c478bd9Sstevel@tonic-gate rsa_verify_final, 2647c478bd9Sstevel@tonic-gate rsa_verify_atomic, 2657c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init, 2667c478bd9Sstevel@tonic-gate rsa_verify_recover, 2677c478bd9Sstevel@tonic-gate rsa_verify_recover_atomic 2687c478bd9Sstevel@tonic-gate }; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate static int rsa_free_context(crypto_ctx_t *); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate static crypto_ctx_ops_t rsa_ctx_ops = { 2737c478bd9Sstevel@tonic-gate NULL, 2747c478bd9Sstevel@tonic-gate rsa_free_context 2757c478bd9Sstevel@tonic-gate }; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate static crypto_ops_t rsa_crypto_ops = { 2787c478bd9Sstevel@tonic-gate &rsa_control_ops, 2797c478bd9Sstevel@tonic-gate NULL, 2807c478bd9Sstevel@tonic-gate &rsa_cipher_ops, 2817c478bd9Sstevel@tonic-gate NULL, 2827c478bd9Sstevel@tonic-gate &rsa_sign_ops, 2837c478bd9Sstevel@tonic-gate &rsa_verify_ops, 2847c478bd9Sstevel@tonic-gate NULL, 2857c478bd9Sstevel@tonic-gate NULL, 2867c478bd9Sstevel@tonic-gate NULL, 2877c478bd9Sstevel@tonic-gate NULL, 2887c478bd9Sstevel@tonic-gate NULL, 2897c478bd9Sstevel@tonic-gate NULL, 2907c478bd9Sstevel@tonic-gate NULL, 29173556491SAnthony Scarpino &rsa_ctx_ops, 29273556491SAnthony Scarpino NULL, 29373556491SAnthony Scarpino NULL, 294*6ea3c060SGarrett D'Amore NULL, 2957c478bd9Sstevel@tonic-gate }; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate static crypto_provider_info_t rsa_prov_info = { 29873556491SAnthony Scarpino CRYPTO_SPI_VERSION_4, 2997c478bd9Sstevel@tonic-gate "RSA Software Provider", 3007c478bd9Sstevel@tonic-gate CRYPTO_SW_PROVIDER, 3017c478bd9Sstevel@tonic-gate {&modlinkage}, 3027c478bd9Sstevel@tonic-gate NULL, 3037c478bd9Sstevel@tonic-gate &rsa_crypto_ops, 3047c478bd9Sstevel@tonic-gate sizeof (rsa_mech_info_tab)/sizeof (crypto_mech_info_t), 3057c478bd9Sstevel@tonic-gate rsa_mech_info_tab 3067c478bd9Sstevel@tonic-gate }; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate static int rsa_encrypt_common(rsa_mech_type_t, crypto_key_t *, 309726fad2aSDina K Nimeh crypto_data_t *, crypto_data_t *); 3107c478bd9Sstevel@tonic-gate static int rsa_decrypt_common(rsa_mech_type_t, crypto_key_t *, 311726fad2aSDina K Nimeh crypto_data_t *, crypto_data_t *); 3127c478bd9Sstevel@tonic-gate static int rsa_sign_common(rsa_mech_type_t, crypto_key_t *, 313726fad2aSDina K Nimeh crypto_data_t *, crypto_data_t *); 3147c478bd9Sstevel@tonic-gate static int rsa_verify_common(rsa_mech_type_t, crypto_key_t *, 315726fad2aSDina K Nimeh crypto_data_t *, crypto_data_t *); 3167c478bd9Sstevel@tonic-gate static int compare_data(crypto_data_t *, uchar_t *); 3177c478bd9Sstevel@tonic-gate 318726fad2aSDina K Nimeh static int core_rsa_encrypt(crypto_key_t *, uchar_t *, int, uchar_t *, int); 319726fad2aSDina K Nimeh static int core_rsa_decrypt(crypto_key_t *, uchar_t *, int, uchar_t *); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate static crypto_kcf_provider_handle_t rsa_prov_handle = NULL; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate int 3247c478bd9Sstevel@tonic-gate _init(void) 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate int ret; 3277c478bd9Sstevel@tonic-gate 328d3b2efc7SAnthony Scarpino if ((ret = mod_install(&modlinkage)) != 0) 329d3b2efc7SAnthony Scarpino return (ret); 330d3b2efc7SAnthony Scarpino 331d3b2efc7SAnthony Scarpino /* Register with KCF. If the registration fails, remove the module. */ 332d3b2efc7SAnthony Scarpino if (crypto_register_provider(&rsa_prov_info, &rsa_prov_handle)) { 333d3b2efc7SAnthony Scarpino (void) mod_remove(&modlinkage); 3347c478bd9Sstevel@tonic-gate return (EACCES); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 337d3b2efc7SAnthony Scarpino return (0); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate int 3417c478bd9Sstevel@tonic-gate _fini(void) 3427c478bd9Sstevel@tonic-gate { 343d3b2efc7SAnthony Scarpino /* Unregister from KCF if module is registered */ 3447c478bd9Sstevel@tonic-gate if (rsa_prov_handle != NULL) { 345d3b2efc7SAnthony Scarpino if (crypto_unregister_provider(rsa_prov_handle)) 3467c478bd9Sstevel@tonic-gate return (EBUSY); 347d3b2efc7SAnthony Scarpino 3487c478bd9Sstevel@tonic-gate rsa_prov_handle = NULL; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate int 3557c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3617c478bd9Sstevel@tonic-gate static void 3627c478bd9Sstevel@tonic-gate rsa_provider_status(crypto_provider_handle_t provider, uint_t *status) 3637c478bd9Sstevel@tonic-gate { 3647c478bd9Sstevel@tonic-gate *status = CRYPTO_PROVIDER_READY; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate static int 3687c478bd9Sstevel@tonic-gate check_mech_and_key(crypto_mechanism_t *mechanism, crypto_key_t *key) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate uchar_t *modulus; 3737c478bd9Sstevel@tonic-gate ssize_t modulus_len; /* In bytes */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (!RSA_VALID_MECH(mechanism)) 3767c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * We only support RSA keys that are passed as a list of 3807c478bd9Sstevel@tonic-gate * object attributes. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate if (key->ck_format != CRYPTO_KEY_ATTR_LIST) { 3837c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_TYPE_INCONSISTENT); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 38623c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 3877c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 3887c478bd9Sstevel@tonic-gate return (rv); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate if (modulus_len < MIN_RSA_KEYLENGTH_IN_BYTES || 3917c478bd9Sstevel@tonic-gate modulus_len > MAX_RSA_KEYLENGTH_IN_BYTES) 3927c478bd9Sstevel@tonic-gate return (CRYPTO_KEY_SIZE_RANGE); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate return (rv); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate void 3987c478bd9Sstevel@tonic-gate kmemset(uint8_t *buf, char pattern, size_t len) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate int i = 0; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate while (i < len) 4037c478bd9Sstevel@tonic-gate buf[i++] = pattern; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * This function guarantees to return non-zero random numbers. 4087c478bd9Sstevel@tonic-gate * This is needed as the /dev/urandom kernel interface, 4097c478bd9Sstevel@tonic-gate * random_get_pseudo_bytes(), may return zeros. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate int 4127c478bd9Sstevel@tonic-gate knzero_random_generator(uint8_t *ran_out, size_t ran_len) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate int rv; 4157c478bd9Sstevel@tonic-gate size_t ebc = 0; /* count of extra bytes in extrarand */ 4167c478bd9Sstevel@tonic-gate size_t i = 0; 4177c478bd9Sstevel@tonic-gate uint8_t extrarand[32]; 4187c478bd9Sstevel@tonic-gate size_t extrarand_len; 4197c478bd9Sstevel@tonic-gate 420*6ea3c060SGarrett D'Amore if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0) 4217c478bd9Sstevel@tonic-gate return (rv); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * Walk through the returned random numbers pointed by ran_out, 4257c478bd9Sstevel@tonic-gate * and look for any random number which is zero. 4267c478bd9Sstevel@tonic-gate * If we find zero, call random_get_pseudo_bytes() to generate 4277c478bd9Sstevel@tonic-gate * another 32 random numbers pool. Replace any zeros in ran_out[] 4287c478bd9Sstevel@tonic-gate * from the random number in pool. 4297c478bd9Sstevel@tonic-gate */ 4307c478bd9Sstevel@tonic-gate while (i < ran_len) { 4317c478bd9Sstevel@tonic-gate if (ran_out[i] != 0) { 4327c478bd9Sstevel@tonic-gate i++; 4337c478bd9Sstevel@tonic-gate continue; 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Note that it is 'while' so we are guaranteed a 4387c478bd9Sstevel@tonic-gate * non-zero value on exit. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate if (ebc == 0) { 4417c478bd9Sstevel@tonic-gate /* refresh extrarand */ 4427c478bd9Sstevel@tonic-gate extrarand_len = sizeof (extrarand); 443*6ea3c060SGarrett D'Amore if ((rv = random_get_pseudo_bytes(extrarand, 4447c478bd9Sstevel@tonic-gate extrarand_len)) != 0) { 4457c478bd9Sstevel@tonic-gate return (rv); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate ebc = extrarand_len; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate /* Replace zero with byte from extrarand. */ 4517c478bd9Sstevel@tonic-gate -- ebc; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * The new random byte zero/non-zero will be checked in 4557c478bd9Sstevel@tonic-gate * the next pass through the loop. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate ran_out[i] = extrarand[ebc]; 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate static int 4647c478bd9Sstevel@tonic-gate compare_data(crypto_data_t *data, uchar_t *buf) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int len; 4677c478bd9Sstevel@tonic-gate uchar_t *dptr; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate len = data->cd_length; 4707c478bd9Sstevel@tonic-gate switch (data->cd_format) { 4717c478bd9Sstevel@tonic-gate case CRYPTO_DATA_RAW: 4727c478bd9Sstevel@tonic-gate dptr = (uchar_t *)(data->cd_raw.iov_base + 4737c478bd9Sstevel@tonic-gate data->cd_offset); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate return (bcmp(dptr, buf, len)); 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate case CRYPTO_DATA_UIO: 47823c57df7Smcpowers return (crypto_uio_data(data, buf, len, 47923c57df7Smcpowers COMPARE_TO_DATA, NULL, NULL)); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate case CRYPTO_DATA_MBLK: 48223c57df7Smcpowers return (crypto_mblk_data(data, buf, len, 48323c57df7Smcpowers COMPARE_TO_DATA, NULL, NULL)); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4907c478bd9Sstevel@tonic-gate static int 4917c478bd9Sstevel@tonic-gate rsa_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 4927c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t template, 4937c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate int rv; 4967c478bd9Sstevel@tonic-gate int kmflag; 4977c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 5007c478bd9Sstevel@tonic-gate return (rv); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Allocate a RSA context. 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate kmflag = crypto_kmflag(req); 5067c478bd9Sstevel@tonic-gate if ((ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag)) == NULL) 5077c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 5087c478bd9Sstevel@tonic-gate 50923c57df7Smcpowers if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size, 51023c57df7Smcpowers kmflag)) != CRYPTO_SUCCESS) { 5117c478bd9Sstevel@tonic-gate kmem_free(ctxp, sizeof (rsa_ctx_t)); 5127c478bd9Sstevel@tonic-gate return (rv); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate ctxp->mech_type = mechanism->cm_type; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate ctx->cc_provider_private = ctxp; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5227c478bd9Sstevel@tonic-gate static int 523726fad2aSDina K Nimeh rsaprov_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext, 5247c478bd9Sstevel@tonic-gate crypto_data_t *ciphertext, crypto_req_handle_t req) 5257c478bd9Sstevel@tonic-gate { 5267c478bd9Sstevel@tonic-gate int rv; 5277c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 5307c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate RSA_ARG_INPLACE(plaintext, ciphertext); 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Note on the KM_SLEEP flag passed to the routine below - 536726fad2aSDina K Nimeh * rsaprov_encrypt() is a single-part encryption routine which is 5377c478bd9Sstevel@tonic-gate * currently usable only by /dev/crypto. Since /dev/crypto calls are 5387c478bd9Sstevel@tonic-gate * always synchronous, we can safely pass KM_SLEEP here. 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate rv = rsa_encrypt_common(ctxp->mech_type, ctxp->key, plaintext, 541726fad2aSDina K Nimeh ciphertext); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 5447c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate return (rv); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5507c478bd9Sstevel@tonic-gate static int 5517c478bd9Sstevel@tonic-gate rsa_encrypt_atomic(crypto_provider_handle_t provider, 5527c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 5537c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext, 5547c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 5557c478bd9Sstevel@tonic-gate { 5567c478bd9Sstevel@tonic-gate int rv; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 5597c478bd9Sstevel@tonic-gate return (rv); 5607c478bd9Sstevel@tonic-gate RSA_ARG_INPLACE(plaintext, ciphertext); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate return (rsa_encrypt_common(mechanism->cm_type, key, plaintext, 563726fad2aSDina K Nimeh ciphertext)); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate static int 5677c478bd9Sstevel@tonic-gate rsa_free_context(crypto_ctx_t *ctx) 5687c478bd9Sstevel@tonic-gate { 5697c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp = ctx->cc_provider_private; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if (ctxp != NULL) { 5727c478bd9Sstevel@tonic-gate bzero(ctxp->key, ctxp->keychunk_size); 5737c478bd9Sstevel@tonic-gate kmem_free(ctxp->key, ctxp->keychunk_size); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate if (ctxp->mech_type == RSA_PKCS_MECH_INFO_TYPE || 5767c478bd9Sstevel@tonic-gate ctxp->mech_type == RSA_X_509_MECH_INFO_TYPE) 5777c478bd9Sstevel@tonic-gate kmem_free(ctxp, sizeof (rsa_ctx_t)); 5787c478bd9Sstevel@tonic-gate else 5797c478bd9Sstevel@tonic-gate kmem_free(ctxp, sizeof (digest_rsa_ctx_t)); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate ctx->cc_provider_private = NULL; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate static int 5887c478bd9Sstevel@tonic-gate rsa_encrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key, 589726fad2aSDina K Nimeh crypto_data_t *plaintext, crypto_data_t *ciphertext) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate int plen; 5947c478bd9Sstevel@tonic-gate uchar_t *ptptr; 5957c478bd9Sstevel@tonic-gate uchar_t *modulus; 5967c478bd9Sstevel@tonic-gate ssize_t modulus_len; 5977c478bd9Sstevel@tonic-gate uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 5987c478bd9Sstevel@tonic-gate uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 5997c478bd9Sstevel@tonic-gate uchar_t cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 6007c478bd9Sstevel@tonic-gate 60123c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 6027c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 6037c478bd9Sstevel@tonic-gate return (rv); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate plen = plaintext->cd_length; 6077c478bd9Sstevel@tonic-gate if (mech_type == RSA_PKCS_MECH_INFO_TYPE) { 6087c478bd9Sstevel@tonic-gate if (plen > (modulus_len - MIN_PKCS1_PADLEN)) 6097c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 6107c478bd9Sstevel@tonic-gate } else { 6117c478bd9Sstevel@tonic-gate if (plen > modulus_len) 6127c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * Output buf len must not be less than RSA modulus size. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate if (ciphertext->cd_length < modulus_len) { 6197c478bd9Sstevel@tonic-gate ciphertext->cd_length = modulus_len; 6207c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate ASSERT(plaintext->cd_length <= sizeof (tmp_data)); 62423c57df7Smcpowers if ((rv = crypto_get_input_data(plaintext, &ptptr, tmp_data)) 6257c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) 6267c478bd9Sstevel@tonic-gate return (rv); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate if (mech_type == RSA_PKCS_MECH_INFO_TYPE) { 629726fad2aSDina K Nimeh rv = pkcs1_encode(PKCS1_ENCRYPT, ptptr, plen, 6307c478bd9Sstevel@tonic-gate plain_data, modulus_len); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 6337c478bd9Sstevel@tonic-gate return (rv); 6347c478bd9Sstevel@tonic-gate } else { 6357c478bd9Sstevel@tonic-gate bzero(plain_data, modulus_len - plen); 6367c478bd9Sstevel@tonic-gate bcopy(ptptr, &plain_data[modulus_len - plen], plen); 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 639726fad2aSDina K Nimeh rv = core_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1); 6407c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 6417c478bd9Sstevel@tonic-gate /* copy out to ciphertext */ 64223c57df7Smcpowers if ((rv = crypto_put_output_data(cipher_data, 6437c478bd9Sstevel@tonic-gate ciphertext, modulus_len)) != CRYPTO_SUCCESS) 6447c478bd9Sstevel@tonic-gate return (rv); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate ciphertext->cd_length = modulus_len; 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate return (rv); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate static int 6537c478bd9Sstevel@tonic-gate core_rsa_encrypt(crypto_key_t *key, uchar_t *in, 654726fad2aSDina K Nimeh int in_len, uchar_t *out, int is_public) 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate int rv; 6577c478bd9Sstevel@tonic-gate uchar_t *expo, *modulus; 6587c478bd9Sstevel@tonic-gate ssize_t expo_len; 6597c478bd9Sstevel@tonic-gate ssize_t modulus_len; 660726fad2aSDina K Nimeh RSAbytekey k; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (is_public) { 66323c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_PUBLIC_EXPONENT, 66423c57df7Smcpowers &expo, &expo_len)) != CRYPTO_SUCCESS) 6657c478bd9Sstevel@tonic-gate return (rv); 6667c478bd9Sstevel@tonic-gate } else { 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * SUN_CKA_PRIVATE_EXPONENT is a required attribute for a 6697c478bd9Sstevel@tonic-gate * RSA secret key. See the comments in core_rsa_decrypt 6707c478bd9Sstevel@tonic-gate * routine which calls this routine with a private key. 6717c478bd9Sstevel@tonic-gate */ 67223c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_PRIVATE_EXPONENT, 67323c57df7Smcpowers &expo, &expo_len)) != CRYPTO_SUCCESS) 6747c478bd9Sstevel@tonic-gate return (rv); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 67723c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 6787c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 6797c478bd9Sstevel@tonic-gate return (rv); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 682726fad2aSDina K Nimeh k.modulus = modulus; 683726fad2aSDina K Nimeh k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len); 684726fad2aSDina K Nimeh k.pubexpo = expo; 685726fad2aSDina K Nimeh k.pubexpo_bytes = expo_len; 686726fad2aSDina K Nimeh k.rfunc = NULL; 6877c478bd9Sstevel@tonic-gate 688726fad2aSDina K Nimeh rv = rsa_encrypt(&k, in, in_len, out); 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate return (rv); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6947c478bd9Sstevel@tonic-gate static int 695726fad2aSDina K Nimeh rsaprov_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext, 6967c478bd9Sstevel@tonic-gate crypto_data_t *plaintext, crypto_req_handle_t req) 6977c478bd9Sstevel@tonic-gate { 6987c478bd9Sstevel@tonic-gate int rv; 6997c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 7027c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate RSA_ARG_INPLACE(ciphertext, plaintext); 7057c478bd9Sstevel@tonic-gate 706726fad2aSDina K Nimeh /* See the comments on KM_SLEEP flag in rsaprov_encrypt() */ 7077c478bd9Sstevel@tonic-gate rv = rsa_decrypt_common(ctxp->mech_type, ctxp->key, 708726fad2aSDina K Nimeh ciphertext, plaintext); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 7117c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate return (rv); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7177c478bd9Sstevel@tonic-gate static int 7187c478bd9Sstevel@tonic-gate rsa_decrypt_atomic(crypto_provider_handle_t provider, 7197c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 7207c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext, 7217c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t template, crypto_req_handle_t req) 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate int rv; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 7267c478bd9Sstevel@tonic-gate return (rv); 7277c478bd9Sstevel@tonic-gate RSA_ARG_INPLACE(ciphertext, plaintext); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate return (rsa_decrypt_common(mechanism->cm_type, key, ciphertext, 730726fad2aSDina K Nimeh plaintext)); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate static int 7347c478bd9Sstevel@tonic-gate rsa_decrypt_common(rsa_mech_type_t mech_type, crypto_key_t *key, 735726fad2aSDina K Nimeh crypto_data_t *ciphertext, crypto_data_t *plaintext) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 7387c478bd9Sstevel@tonic-gate 739726fad2aSDina K Nimeh size_t plain_len; 7407c478bd9Sstevel@tonic-gate uchar_t *ctptr; 7417c478bd9Sstevel@tonic-gate uchar_t *modulus; 7427c478bd9Sstevel@tonic-gate ssize_t modulus_len; 7437c478bd9Sstevel@tonic-gate uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 7447c478bd9Sstevel@tonic-gate uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 7457c478bd9Sstevel@tonic-gate 74623c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 7477c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 7487c478bd9Sstevel@tonic-gate return (rv); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* 7527c478bd9Sstevel@tonic-gate * Ciphertext length must be equal to RSA modulus size. 7537c478bd9Sstevel@tonic-gate */ 7547c478bd9Sstevel@tonic-gate if (ciphertext->cd_length != modulus_len) 7557c478bd9Sstevel@tonic-gate return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate ASSERT(ciphertext->cd_length <= sizeof (tmp_data)); 75823c57df7Smcpowers if ((rv = crypto_get_input_data(ciphertext, &ctptr, tmp_data)) 7597c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) 7607c478bd9Sstevel@tonic-gate return (rv); 7617c478bd9Sstevel@tonic-gate 762726fad2aSDina K Nimeh rv = core_rsa_decrypt(key, ctptr, modulus_len, plain_data); 7637c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 7647c478bd9Sstevel@tonic-gate plain_len = modulus_len; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate if (mech_type == RSA_PKCS_MECH_INFO_TYPE) { 7677c478bd9Sstevel@tonic-gate /* Strip off the PKCS block formatting data. */ 768726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_DECRYPT, plain_data, 7697c478bd9Sstevel@tonic-gate &plain_len); 7707c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 7717c478bd9Sstevel@tonic-gate return (rv); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate if (plain_len > plaintext->cd_length) { 7757c478bd9Sstevel@tonic-gate plaintext->cd_length = plain_len; 7767c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 77923c57df7Smcpowers if ((rv = crypto_put_output_data( 78023c57df7Smcpowers plain_data + modulus_len - plain_len, 7817c478bd9Sstevel@tonic-gate plaintext, plain_len)) != CRYPTO_SUCCESS) 7827c478bd9Sstevel@tonic-gate return (rv); 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate plaintext->cd_length = plain_len; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate return (rv); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate static int 791726fad2aSDina K Nimeh core_rsa_decrypt(crypto_key_t *key, uchar_t *in, int in_len, uchar_t *out) 7927c478bd9Sstevel@tonic-gate { 7937c478bd9Sstevel@tonic-gate int rv; 7947c478bd9Sstevel@tonic-gate uchar_t *modulus, *prime1, *prime2, *expo1, *expo2, *coef; 7957c478bd9Sstevel@tonic-gate ssize_t modulus_len; 7967c478bd9Sstevel@tonic-gate ssize_t prime1_len, prime2_len; 7977c478bd9Sstevel@tonic-gate ssize_t expo1_len, expo2_len, coef_len; 798726fad2aSDina K Nimeh RSAbytekey k; 7997c478bd9Sstevel@tonic-gate 80023c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 8017c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 8027c478bd9Sstevel@tonic-gate return (rv); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* 8067c478bd9Sstevel@tonic-gate * The following attributes are not required to be 8077c478bd9Sstevel@tonic-gate * present in a RSA secret key. If any of them is not present 8087c478bd9Sstevel@tonic-gate * we call the encrypt routine with a flag indicating use of 8097c478bd9Sstevel@tonic-gate * private exponent (d). Note that SUN_CKA_PRIVATE_EXPONENT is 8107c478bd9Sstevel@tonic-gate * a required attribute for a RSA secret key. 8117c478bd9Sstevel@tonic-gate */ 81223c57df7Smcpowers if ((crypto_get_key_attr(key, SUN_CKA_PRIME_1, &prime1, &prime1_len) 8137c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) || 81423c57df7Smcpowers (crypto_get_key_attr(key, SUN_CKA_PRIME_2, &prime2, &prime2_len) 8157c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) || 81623c57df7Smcpowers (crypto_get_key_attr(key, SUN_CKA_EXPONENT_1, &expo1, &expo1_len) 8177c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) || 81823c57df7Smcpowers (crypto_get_key_attr(key, SUN_CKA_EXPONENT_2, &expo2, &expo2_len) 8197c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) || 82023c57df7Smcpowers (crypto_get_key_attr(key, SUN_CKA_COEFFICIENT, &coef, &coef_len) 8217c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS)) { 822726fad2aSDina K Nimeh return (core_rsa_encrypt(key, in, in_len, out, 0)); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 825726fad2aSDina K Nimeh k.modulus = modulus; 826726fad2aSDina K Nimeh k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len); 827726fad2aSDina K Nimeh k.prime1 = prime1; 828726fad2aSDina K Nimeh k.prime1_bytes = prime1_len; 829726fad2aSDina K Nimeh k.prime2 = prime2; 830726fad2aSDina K Nimeh k.prime2_bytes = prime2_len; 831726fad2aSDina K Nimeh k.expo1 = expo1; 832726fad2aSDina K Nimeh k.expo1_bytes = expo1_len; 833726fad2aSDina K Nimeh k.expo2 = expo2; 834726fad2aSDina K Nimeh k.expo2_bytes = expo2_len; 835726fad2aSDina K Nimeh k.coeff = coef; 836726fad2aSDina K Nimeh k.coeff_bytes = coef_len; 837726fad2aSDina K Nimeh k.rfunc = NULL; 8387c478bd9Sstevel@tonic-gate 839726fad2aSDina K Nimeh rv = rsa_decrypt(&k, in, in_len, out); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate return (rv); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8457c478bd9Sstevel@tonic-gate static int 8467c478bd9Sstevel@tonic-gate rsa_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 8477c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 8487c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 8497c478bd9Sstevel@tonic-gate { 8507c478bd9Sstevel@tonic-gate int rv; 8517c478bd9Sstevel@tonic-gate int kmflag; 8527c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 8537c478bd9Sstevel@tonic-gate digest_rsa_ctx_t *dctxp; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 8567c478bd9Sstevel@tonic-gate return (rv); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Allocate a RSA context. 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate kmflag = crypto_kmflag(req); 8627c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 8637c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 8647c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 865f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 866f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 867f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 8687c478bd9Sstevel@tonic-gate dctxp = kmem_zalloc(sizeof (digest_rsa_ctx_t), kmflag); 8697c478bd9Sstevel@tonic-gate ctxp = (rsa_ctx_t *)dctxp; 8707c478bd9Sstevel@tonic-gate break; 8717c478bd9Sstevel@tonic-gate default: 8727c478bd9Sstevel@tonic-gate ctxp = kmem_zalloc(sizeof (rsa_ctx_t), kmflag); 8737c478bd9Sstevel@tonic-gate break; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (ctxp == NULL) 8777c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate ctxp->mech_type = mechanism->cm_type; 88023c57df7Smcpowers if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size, 88123c57df7Smcpowers kmflag)) != CRYPTO_SUCCESS) { 8827c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 8837c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 8847c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 885f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 886f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 887f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 8887c478bd9Sstevel@tonic-gate kmem_free(dctxp, sizeof (digest_rsa_ctx_t)); 8897c478bd9Sstevel@tonic-gate break; 8907c478bd9Sstevel@tonic-gate default: 8917c478bd9Sstevel@tonic-gate kmem_free(ctxp, sizeof (rsa_ctx_t)); 8927c478bd9Sstevel@tonic-gate break; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate return (rv); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate switch (mechanism->cm_type) { 8987c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 8997c478bd9Sstevel@tonic-gate MD5Init(&(dctxp->md5_ctx)); 9007c478bd9Sstevel@tonic-gate break; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 9037c478bd9Sstevel@tonic-gate SHA1Init(&(dctxp->sha1_ctx)); 9047c478bd9Sstevel@tonic-gate break; 905f66d273dSizick 906f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 907f66d273dSizick SHA2Init(SHA256, &(dctxp->sha2_ctx)); 908f66d273dSizick break; 909f66d273dSizick 910f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 911f66d273dSizick SHA2Init(SHA384, &(dctxp->sha2_ctx)); 912f66d273dSizick break; 913f66d273dSizick 914f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 915f66d273dSizick SHA2Init(SHA512, &(dctxp->sha2_ctx)); 916f66d273dSizick break; 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate ctx->cc_provider_private = ctxp; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate #define SHA1_DIGEST_SIZE 20 9257c478bd9Sstevel@tonic-gate #define MD5_DIGEST_SIZE 16 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate #define INIT_RAW_CRYPTO_DATA(data, base, len, cd_len) \ 9287c478bd9Sstevel@tonic-gate (data).cd_format = CRYPTO_DATA_RAW; \ 9297c478bd9Sstevel@tonic-gate (data).cd_offset = 0; \ 9307c478bd9Sstevel@tonic-gate (data).cd_raw.iov_base = (char *)base; \ 9317c478bd9Sstevel@tonic-gate (data).cd_raw.iov_len = len; \ 9327c478bd9Sstevel@tonic-gate (data).cd_length = cd_len; 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate static int 9357c478bd9Sstevel@tonic-gate rsa_digest_svrfy_common(digest_rsa_ctx_t *ctxp, crypto_data_t *data, 936726fad2aSDina K Nimeh crypto_data_t *signature, uchar_t flag) 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 9397c478bd9Sstevel@tonic-gate 940f66d273dSizick uchar_t digest[SHA512_DIGEST_LENGTH]; 9417c478bd9Sstevel@tonic-gate /* The der_data size is enough for MD5 also */ 942f66d273dSizick uchar_t der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len]; 9437c478bd9Sstevel@tonic-gate ulong_t der_data_len; 9447c478bd9Sstevel@tonic-gate crypto_data_t der_cd; 9457c478bd9Sstevel@tonic-gate rsa_mech_type_t mech_type; 9467c478bd9Sstevel@tonic-gate 94723c57df7Smcpowers ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY); 94823c57df7Smcpowers ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL)); 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate mech_type = ctxp->mech_type; 951f66d273dSizick if (mech_type == RSA_PKCS_MECH_INFO_TYPE || 952f66d273dSizick mech_type == RSA_X_509_MECH_INFO_TYPE) 9537c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* 9567c478bd9Sstevel@tonic-gate * We need to do the BUFFER_TOO_SMALL check before digesting 9577c478bd9Sstevel@tonic-gate * the data. No check is needed for verify as signature is not 9587c478bd9Sstevel@tonic-gate * an output argument for verify. 9597c478bd9Sstevel@tonic-gate */ 96023c57df7Smcpowers if (flag & CRYPTO_DO_SIGN) { 9617c478bd9Sstevel@tonic-gate uchar_t *modulus; 9627c478bd9Sstevel@tonic-gate ssize_t modulus_len; 9637c478bd9Sstevel@tonic-gate 96423c57df7Smcpowers if ((rv = crypto_get_key_attr(ctxp->key, SUN_CKA_MODULUS, 96523c57df7Smcpowers &modulus, &modulus_len)) != CRYPTO_SUCCESS) { 9667c478bd9Sstevel@tonic-gate return (rv); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate if (signature->cd_length < modulus_len) { 9707c478bd9Sstevel@tonic-gate signature->cd_length = modulus_len; 9717c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE) 97623c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->md5_ctx), 97723c57df7Smcpowers digest, MD5Update, MD5Final, flag | CRYPTO_DO_MD5); 978f66d273dSizick 979f66d273dSizick else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE) 98023c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), 98123c57df7Smcpowers digest, SHA1Update, SHA1Final, flag | CRYPTO_DO_SHA1); 982f66d273dSizick 983f66d273dSizick else 98423c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha2_ctx), 98523c57df7Smcpowers digest, SHA2Update, SHA2Final, flag | CRYPTO_DO_SHA2); 986f66d273dSizick 9877c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 9887c478bd9Sstevel@tonic-gate return (rv); 9897c478bd9Sstevel@tonic-gate 990f66d273dSizick 9917c478bd9Sstevel@tonic-gate /* 9927c478bd9Sstevel@tonic-gate * Prepare the DER encoding of the DigestInfo value as follows: 9937c478bd9Sstevel@tonic-gate * MD5: MD5_DER_PREFIX || H 9947c478bd9Sstevel@tonic-gate * SHA-1: SHA1_DER_PREFIX || H 9957c478bd9Sstevel@tonic-gate * 9967c478bd9Sstevel@tonic-gate * See rsa_impl.c for more details. 9977c478bd9Sstevel@tonic-gate */ 998f66d273dSizick switch (mech_type) { 999f66d273dSizick case MD5_RSA_PKCS_MECH_INFO_TYPE: 10007c478bd9Sstevel@tonic-gate bcopy(MD5_DER_PREFIX, der_data, MD5_DER_PREFIX_Len); 1001f66d273dSizick bcopy(digest, der_data + MD5_DER_PREFIX_Len, MD5_DIGEST_SIZE); 1002f66d273dSizick der_data_len = MD5_DER_PREFIX_Len + MD5_DIGEST_SIZE; 1003f66d273dSizick break; 1004f66d273dSizick 1005f66d273dSizick case SHA1_RSA_PKCS_MECH_INFO_TYPE: 10067c478bd9Sstevel@tonic-gate bcopy(SHA1_DER_PREFIX, der_data, SHA1_DER_PREFIX_Len); 1007f66d273dSizick bcopy(digest, der_data + SHA1_DER_PREFIX_Len, 1008f66d273dSizick SHA1_DIGEST_SIZE); 1009f66d273dSizick der_data_len = SHA1_DER_PREFIX_Len + SHA1_DIGEST_SIZE; 1010f66d273dSizick break; 1011f66d273dSizick 1012f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1013f66d273dSizick bcopy(SHA256_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len); 1014f66d273dSizick bcopy(digest, der_data + SHA2_DER_PREFIX_Len, 1015f66d273dSizick SHA256_DIGEST_LENGTH); 1016f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + SHA256_DIGEST_LENGTH; 1017f66d273dSizick break; 1018f66d273dSizick 1019f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1020f66d273dSizick bcopy(SHA384_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len); 1021f66d273dSizick bcopy(digest, der_data + SHA2_DER_PREFIX_Len, 1022f66d273dSizick SHA384_DIGEST_LENGTH); 1023f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + SHA384_DIGEST_LENGTH; 1024f66d273dSizick break; 1025f66d273dSizick 1026f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 1027f66d273dSizick bcopy(SHA512_DER_PREFIX, der_data, SHA2_DER_PREFIX_Len); 1028f66d273dSizick bcopy(digest, der_data + SHA2_DER_PREFIX_Len, 1029f66d273dSizick SHA512_DIGEST_LENGTH); 1030f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + SHA512_DIGEST_LENGTH; 1031f66d273dSizick break; 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate INIT_RAW_CRYPTO_DATA(der_cd, der_data, der_data_len, der_data_len); 10357c478bd9Sstevel@tonic-gate /* 10367c478bd9Sstevel@tonic-gate * Now, we are ready to sign or verify the DER_ENCODED data. 10377c478bd9Sstevel@tonic-gate */ 103823c57df7Smcpowers if (flag & CRYPTO_DO_SIGN) 10397c478bd9Sstevel@tonic-gate rv = rsa_sign_common(mech_type, ctxp->key, &der_cd, 1040726fad2aSDina K Nimeh signature); 10417c478bd9Sstevel@tonic-gate else 10427c478bd9Sstevel@tonic-gate rv = rsa_verify_common(mech_type, ctxp->key, &der_cd, 1043726fad2aSDina K Nimeh signature); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate return (rv); 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate static int 10497c478bd9Sstevel@tonic-gate rsa_sign_common(rsa_mech_type_t mech_type, crypto_key_t *key, 1050726fad2aSDina K Nimeh crypto_data_t *data, crypto_data_t *signature) 10517c478bd9Sstevel@tonic-gate { 10527c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate int dlen; 10557c478bd9Sstevel@tonic-gate uchar_t *dataptr, *modulus; 10567c478bd9Sstevel@tonic-gate ssize_t modulus_len; 10577c478bd9Sstevel@tonic-gate uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 10587c478bd9Sstevel@tonic-gate uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 10597c478bd9Sstevel@tonic-gate uchar_t signed_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 10607c478bd9Sstevel@tonic-gate 106123c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 10627c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 10637c478bd9Sstevel@tonic-gate return (rv); 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate dlen = data->cd_length; 10677c478bd9Sstevel@tonic-gate switch (mech_type) { 10687c478bd9Sstevel@tonic-gate case RSA_PKCS_MECH_INFO_TYPE: 10697c478bd9Sstevel@tonic-gate if (dlen > (modulus_len - MIN_PKCS1_PADLEN)) 10707c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 10717c478bd9Sstevel@tonic-gate break; 10727c478bd9Sstevel@tonic-gate case RSA_X_509_MECH_INFO_TYPE: 10737c478bd9Sstevel@tonic-gate if (dlen > modulus_len) 10747c478bd9Sstevel@tonic-gate return (CRYPTO_DATA_LEN_RANGE); 10757c478bd9Sstevel@tonic-gate break; 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate if (signature->cd_length < modulus_len) { 10797c478bd9Sstevel@tonic-gate signature->cd_length = modulus_len; 10807c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate ASSERT(data->cd_length <= sizeof (tmp_data)); 108423c57df7Smcpowers if ((rv = crypto_get_input_data(data, &dataptr, tmp_data)) 10857c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) 10867c478bd9Sstevel@tonic-gate return (rv); 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate switch (mech_type) { 10897c478bd9Sstevel@tonic-gate case RSA_PKCS_MECH_INFO_TYPE: 10907c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 10917c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 1092f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1093f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1094f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * Add PKCS padding to the input data to format a block 10977c478bd9Sstevel@tonic-gate * type "01" encryption block. 10987c478bd9Sstevel@tonic-gate */ 1099726fad2aSDina K Nimeh rv = pkcs1_encode(PKCS1_SIGN, dataptr, dlen, plain_data, 11007c478bd9Sstevel@tonic-gate modulus_len); 11017c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 11027c478bd9Sstevel@tonic-gate return (rv); 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate break; 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate case RSA_X_509_MECH_INFO_TYPE: 11077c478bd9Sstevel@tonic-gate bzero(plain_data, modulus_len - dlen); 11087c478bd9Sstevel@tonic-gate bcopy(dataptr, &plain_data[modulus_len - dlen], dlen); 11097c478bd9Sstevel@tonic-gate break; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 1112726fad2aSDina K Nimeh rv = core_rsa_decrypt(key, plain_data, modulus_len, signed_data); 11137c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 11147c478bd9Sstevel@tonic-gate /* copy out to signature */ 111523c57df7Smcpowers if ((rv = crypto_put_output_data(signed_data, 11167c478bd9Sstevel@tonic-gate signature, modulus_len)) != CRYPTO_SUCCESS) 11177c478bd9Sstevel@tonic-gate return (rv); 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate signature->cd_length = modulus_len; 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate return (rv); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11267c478bd9Sstevel@tonic-gate static int 1127726fad2aSDina K Nimeh rsaprov_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature, 11287c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 11297c478bd9Sstevel@tonic-gate { 11307c478bd9Sstevel@tonic-gate int rv; 11317c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 11347c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 11357c478bd9Sstevel@tonic-gate 1136726fad2aSDina K Nimeh /* See the comments on KM_SLEEP flag in rsaprov_encrypt() */ 11377c478bd9Sstevel@tonic-gate switch (ctxp->mech_type) { 11387c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 11397c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 1140f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1141f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1142f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 11437c478bd9Sstevel@tonic-gate rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data, 1144726fad2aSDina K Nimeh signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | 114523c57df7Smcpowers CRYPTO_DO_FINAL); 11467c478bd9Sstevel@tonic-gate break; 11477c478bd9Sstevel@tonic-gate default: 11487c478bd9Sstevel@tonic-gate rv = rsa_sign_common(ctxp->mech_type, ctxp->key, data, 1149726fad2aSDina K Nimeh signature); 11507c478bd9Sstevel@tonic-gate break; 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 11547c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate return (rv); 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11607c478bd9Sstevel@tonic-gate static int 11617c478bd9Sstevel@tonic-gate rsa_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 11627c478bd9Sstevel@tonic-gate { 11637c478bd9Sstevel@tonic-gate int rv; 11647c478bd9Sstevel@tonic-gate digest_rsa_ctx_t *ctxp; 11657c478bd9Sstevel@tonic-gate rsa_mech_type_t mech_type; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 11687c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 11697c478bd9Sstevel@tonic-gate mech_type = ctxp->mech_type; 11707c478bd9Sstevel@tonic-gate 1171f66d273dSizick if (mech_type == RSA_PKCS_MECH_INFO_TYPE || 1172f66d273dSizick mech_type == RSA_X_509_MECH_INFO_TYPE) 11737c478bd9Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID); 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if (mech_type == MD5_RSA_PKCS_MECH_INFO_TYPE) 117623c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->md5_ctx), 117723c57df7Smcpowers NULL, MD5Update, MD5Final, 117823c57df7Smcpowers CRYPTO_DO_MD5 | CRYPTO_DO_UPDATE); 1179f66d273dSizick 1180f66d273dSizick else if (mech_type == SHA1_RSA_PKCS_MECH_INFO_TYPE) 118123c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), 118223c57df7Smcpowers NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 | 118323c57df7Smcpowers CRYPTO_DO_UPDATE); 1184f66d273dSizick 1185f66d273dSizick else 118623c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha2_ctx), 118723c57df7Smcpowers NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 | 118823c57df7Smcpowers CRYPTO_DO_UPDATE); 1189f66d273dSizick 11907c478bd9Sstevel@tonic-gate return (rv); 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate 1193726fad2aSDina K Nimeh /* ARGSUSED2 */ 11947c478bd9Sstevel@tonic-gate static int 11957c478bd9Sstevel@tonic-gate rsa_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature, 11967c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 11977c478bd9Sstevel@tonic-gate { 11987c478bd9Sstevel@tonic-gate int rv; 11997c478bd9Sstevel@tonic-gate digest_rsa_ctx_t *ctxp; 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 12027c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate rv = rsa_digest_svrfy_common(ctxp, NULL, signature, 1205726fad2aSDina K Nimeh CRYPTO_DO_SIGN | CRYPTO_DO_FINAL); 12067c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 12077c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate return (rv); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* ARGSUSED */ 12137c478bd9Sstevel@tonic-gate static int 12147c478bd9Sstevel@tonic-gate rsa_sign_atomic(crypto_provider_handle_t provider, 12157c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 12167c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature, 12177c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 12187c478bd9Sstevel@tonic-gate { 12197c478bd9Sstevel@tonic-gate int rv; 12207c478bd9Sstevel@tonic-gate digest_rsa_ctx_t dctx; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 12237c478bd9Sstevel@tonic-gate return (rv); 12247c478bd9Sstevel@tonic-gate 1225f66d273dSizick if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE || 1226f66d273dSizick mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE) 12277c478bd9Sstevel@tonic-gate rv = rsa_sign_common(mechanism->cm_type, key, data, 1228726fad2aSDina K Nimeh signature); 1229f66d273dSizick 1230f66d273dSizick else { 1231f66d273dSizick dctx.mech_type = mechanism->cm_type; 1232f66d273dSizick dctx.key = key; 1233f66d273dSizick switch (mechanism->cm_type) { 1234f66d273dSizick case MD5_RSA_PKCS_MECH_INFO_TYPE: 1235f66d273dSizick MD5Init(&(dctx.md5_ctx)); 12367c478bd9Sstevel@tonic-gate break; 1237f66d273dSizick 1238f66d273dSizick case SHA1_RSA_PKCS_MECH_INFO_TYPE: 1239f66d273dSizick SHA1Init(&(dctx.sha1_ctx)); 1240f66d273dSizick break; 1241f66d273dSizick 1242f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1243f66d273dSizick SHA2Init(SHA256, &(dctx.sha2_ctx)); 1244f66d273dSizick break; 1245f66d273dSizick 1246f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1247f66d273dSizick SHA2Init(SHA384, &(dctx.sha2_ctx)); 1248f66d273dSizick break; 1249f66d273dSizick 1250f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 1251f66d273dSizick SHA2Init(SHA512, &(dctx.sha2_ctx)); 1252f66d273dSizick break; 1253f66d273dSizick } 1254f66d273dSizick 1255f66d273dSizick rv = rsa_digest_svrfy_common(&dctx, data, signature, 1256726fad2aSDina K Nimeh CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate return (rv); 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate static int 12637c478bd9Sstevel@tonic-gate rsa_verify_common(rsa_mech_type_t mech_type, crypto_key_t *key, 1264726fad2aSDina K Nimeh crypto_data_t *data, crypto_data_t *signature) 12657c478bd9Sstevel@tonic-gate { 12667c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate uchar_t *sigptr, *modulus; 12697c478bd9Sstevel@tonic-gate ssize_t modulus_len; 12707c478bd9Sstevel@tonic-gate uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 12717c478bd9Sstevel@tonic-gate uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 12727c478bd9Sstevel@tonic-gate 127323c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 12747c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 12757c478bd9Sstevel@tonic-gate return (rv); 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate if (signature->cd_length != modulus_len) 12797c478bd9Sstevel@tonic-gate return (CRYPTO_SIGNATURE_LEN_RANGE); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate ASSERT(signature->cd_length <= sizeof (tmp_data)); 128223c57df7Smcpowers if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data)) 12837c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) 12847c478bd9Sstevel@tonic-gate return (rv); 12857c478bd9Sstevel@tonic-gate 1286726fad2aSDina K Nimeh rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1); 12877c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 12887c478bd9Sstevel@tonic-gate return (rv); 12897c478bd9Sstevel@tonic-gate 1290f66d273dSizick if (mech_type == RSA_X_509_MECH_INFO_TYPE) { 1291f66d273dSizick if (compare_data(data, (plain_data + modulus_len 1292f66d273dSizick - data->cd_length)) != 0) 1293f66d273dSizick rv = CRYPTO_SIGNATURE_INVALID; 1294f66d273dSizick 1295f66d273dSizick } else { 1296726fad2aSDina K Nimeh size_t data_len = modulus_len; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * Strip off the encoded padding bytes in front of the 13007c478bd9Sstevel@tonic-gate * recovered data, then compare the recovered data with 13017c478bd9Sstevel@tonic-gate * the original data. 13027c478bd9Sstevel@tonic-gate */ 1303726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len); 13047c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 1305f66d273dSizick return (rv); 13067c478bd9Sstevel@tonic-gate 1307f66d273dSizick if (data_len != data->cd_length) 1308f66d273dSizick return (CRYPTO_SIGNATURE_LEN_RANGE); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate if (compare_data(data, (plain_data + modulus_len 13117c478bd9Sstevel@tonic-gate - data_len)) != 0) 13127c478bd9Sstevel@tonic-gate rv = CRYPTO_SIGNATURE_INVALID; 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate return (rv); 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate /* ARGSUSED */ 13197c478bd9Sstevel@tonic-gate static int 1320726fad2aSDina K Nimeh rsaprov_verify(crypto_ctx_t *ctx, crypto_data_t *data, 1321726fad2aSDina K Nimeh crypto_data_t *signature, crypto_req_handle_t req) 13227c478bd9Sstevel@tonic-gate { 13237c478bd9Sstevel@tonic-gate int rv; 13247c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 13277c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 13287c478bd9Sstevel@tonic-gate 1329726fad2aSDina K Nimeh /* See the comments on KM_SLEEP flag in rsaprov_encrypt() */ 13307c478bd9Sstevel@tonic-gate switch (ctxp->mech_type) { 13317c478bd9Sstevel@tonic-gate case MD5_RSA_PKCS_MECH_INFO_TYPE: 13327c478bd9Sstevel@tonic-gate case SHA1_RSA_PKCS_MECH_INFO_TYPE: 1333f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1334f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1335f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 13367c478bd9Sstevel@tonic-gate rv = rsa_digest_svrfy_common((digest_rsa_ctx_t *)ctxp, data, 1337726fad2aSDina K Nimeh signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | 133823c57df7Smcpowers CRYPTO_DO_FINAL); 13397c478bd9Sstevel@tonic-gate break; 13407c478bd9Sstevel@tonic-gate default: 13417c478bd9Sstevel@tonic-gate rv = rsa_verify_common(ctxp->mech_type, ctxp->key, data, 1342726fad2aSDina K Nimeh signature); 13437c478bd9Sstevel@tonic-gate break; 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 13477c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate return (rv); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate /* ARGSUSED */ 13537c478bd9Sstevel@tonic-gate static int 13547c478bd9Sstevel@tonic-gate rsa_verify_update(crypto_ctx_t *ctx, crypto_data_t *data, 13557c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 13567c478bd9Sstevel@tonic-gate { 13577c478bd9Sstevel@tonic-gate int rv; 13587c478bd9Sstevel@tonic-gate digest_rsa_ctx_t *ctxp; 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 13617c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 13627c478bd9Sstevel@tonic-gate 1363f66d273dSizick switch (ctxp->mech_type) { 13647c478bd9Sstevel@tonic-gate 1365f66d273dSizick case MD5_RSA_PKCS_MECH_INFO_TYPE: 136623c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->md5_ctx), 136723c57df7Smcpowers NULL, MD5Update, MD5Final, CRYPTO_DO_MD5 | 136823c57df7Smcpowers CRYPTO_DO_UPDATE); 1369f66d273dSizick break; 1370f66d273dSizick 1371f66d273dSizick case SHA1_RSA_PKCS_MECH_INFO_TYPE: 137223c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), 137323c57df7Smcpowers NULL, SHA1Update, SHA1Final, CRYPTO_DO_SHA1 | 137423c57df7Smcpowers CRYPTO_DO_UPDATE); 1375f66d273dSizick break; 1376f66d273dSizick 1377f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1378f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1379f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 138023c57df7Smcpowers rv = crypto_digest_data(data, &(ctxp->sha2_ctx), 138123c57df7Smcpowers NULL, SHA2Update, SHA2Final, CRYPTO_DO_SHA2 | 138223c57df7Smcpowers CRYPTO_DO_UPDATE); 1383f66d273dSizick break; 1384f66d273dSizick 1385f66d273dSizick default: 1386f66d273dSizick return (CRYPTO_MECHANISM_INVALID); 1387f66d273dSizick } 1388f66d273dSizick 13897c478bd9Sstevel@tonic-gate return (rv); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 1392726fad2aSDina K Nimeh /* ARGSUSED2 */ 13937c478bd9Sstevel@tonic-gate static int 13947c478bd9Sstevel@tonic-gate rsa_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature, 13957c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 13967c478bd9Sstevel@tonic-gate { 13977c478bd9Sstevel@tonic-gate int rv; 13987c478bd9Sstevel@tonic-gate digest_rsa_ctx_t *ctxp; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 14017c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate rv = rsa_digest_svrfy_common(ctxp, NULL, signature, 1404726fad2aSDina K Nimeh CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL); 14057c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 14067c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate return (rv); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14137c478bd9Sstevel@tonic-gate static int 14147c478bd9Sstevel@tonic-gate rsa_verify_atomic(crypto_provider_handle_t provider, 14157c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, 14167c478bd9Sstevel@tonic-gate crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *data, 14177c478bd9Sstevel@tonic-gate crypto_data_t *signature, crypto_spi_ctx_template_t ctx_template, 14187c478bd9Sstevel@tonic-gate crypto_req_handle_t req) 14197c478bd9Sstevel@tonic-gate { 14207c478bd9Sstevel@tonic-gate int rv; 14217c478bd9Sstevel@tonic-gate digest_rsa_ctx_t dctx; 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 14247c478bd9Sstevel@tonic-gate return (rv); 14257c478bd9Sstevel@tonic-gate 1426f66d273dSizick if (mechanism->cm_type == RSA_PKCS_MECH_INFO_TYPE || 1427f66d273dSizick mechanism->cm_type == RSA_X_509_MECH_INFO_TYPE) 1428f66d273dSizick rv = rsa_verify_common(mechanism->cm_type, key, data, 1429726fad2aSDina K Nimeh signature); 1430f66d273dSizick 1431f66d273dSizick else { 14327c478bd9Sstevel@tonic-gate dctx.mech_type = mechanism->cm_type; 14337c478bd9Sstevel@tonic-gate dctx.key = key; 1434f66d273dSizick 1435f66d273dSizick switch (mechanism->cm_type) { 1436f66d273dSizick case MD5_RSA_PKCS_MECH_INFO_TYPE: 14377c478bd9Sstevel@tonic-gate MD5Init(&(dctx.md5_ctx)); 1438f66d273dSizick break; 1439f66d273dSizick 1440f66d273dSizick case SHA1_RSA_PKCS_MECH_INFO_TYPE: 14417c478bd9Sstevel@tonic-gate SHA1Init(&(dctx.sha1_ctx)); 1442f66d273dSizick break; 1443f66d273dSizick 1444f66d273dSizick case SHA256_RSA_PKCS_MECH_INFO_TYPE: 1445f66d273dSizick SHA2Init(SHA256, &(dctx.sha2_ctx)); 1446f66d273dSizick break; 1447f66d273dSizick 1448f66d273dSizick case SHA384_RSA_PKCS_MECH_INFO_TYPE: 1449f66d273dSizick SHA2Init(SHA384, &(dctx.sha2_ctx)); 1450f66d273dSizick break; 1451f66d273dSizick 1452f66d273dSizick case SHA512_RSA_PKCS_MECH_INFO_TYPE: 1453f66d273dSizick SHA2Init(SHA512, &(dctx.sha2_ctx)); 1454f66d273dSizick break; 1455f66d273dSizick } 1456f66d273dSizick 1457726fad2aSDina K Nimeh rv = rsa_digest_svrfy_common(&dctx, data, signature, 145823c57df7Smcpowers CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate return (rv); 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate static int 14657c478bd9Sstevel@tonic-gate rsa_verify_recover_common(rsa_mech_type_t mech_type, crypto_key_t *key, 1466726fad2aSDina K Nimeh crypto_data_t *signature, crypto_data_t *data) 14677c478bd9Sstevel@tonic-gate { 14687c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 14697c478bd9Sstevel@tonic-gate 1470726fad2aSDina K Nimeh size_t data_len; 14717c478bd9Sstevel@tonic-gate uchar_t *sigptr, *modulus; 14727c478bd9Sstevel@tonic-gate ssize_t modulus_len; 14737c478bd9Sstevel@tonic-gate uchar_t plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 14747c478bd9Sstevel@tonic-gate uchar_t tmp_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 14757c478bd9Sstevel@tonic-gate 147623c57df7Smcpowers if ((rv = crypto_get_key_attr(key, SUN_CKA_MODULUS, &modulus, 14777c478bd9Sstevel@tonic-gate &modulus_len)) != CRYPTO_SUCCESS) { 14787c478bd9Sstevel@tonic-gate return (rv); 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate if (signature->cd_length != modulus_len) 14827c478bd9Sstevel@tonic-gate return (CRYPTO_SIGNATURE_LEN_RANGE); 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate ASSERT(signature->cd_length <= sizeof (tmp_data)); 148523c57df7Smcpowers if ((rv = crypto_get_input_data(signature, &sigptr, tmp_data)) 14867c478bd9Sstevel@tonic-gate != CRYPTO_SUCCESS) 14877c478bd9Sstevel@tonic-gate return (rv); 14887c478bd9Sstevel@tonic-gate 1489726fad2aSDina K Nimeh rv = core_rsa_encrypt(key, sigptr, modulus_len, plain_data, 1); 14907c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 14917c478bd9Sstevel@tonic-gate return (rv); 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate data_len = modulus_len; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate if (mech_type == RSA_PKCS_MECH_INFO_TYPE) { 14967c478bd9Sstevel@tonic-gate /* 14977c478bd9Sstevel@tonic-gate * Strip off the encoded padding bytes in front of the 14987c478bd9Sstevel@tonic-gate * recovered data, then compare the recovered data with 14997c478bd9Sstevel@tonic-gate * the original data. 15007c478bd9Sstevel@tonic-gate */ 1501726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len); 15027c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) 15037c478bd9Sstevel@tonic-gate return (rv); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate if (data->cd_length < data_len) { 15077c478bd9Sstevel@tonic-gate data->cd_length = data_len; 15087c478bd9Sstevel@tonic-gate return (CRYPTO_BUFFER_TOO_SMALL); 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 151123c57df7Smcpowers if ((rv = crypto_put_output_data(plain_data + modulus_len - data_len, 15127c478bd9Sstevel@tonic-gate data, data_len)) != CRYPTO_SUCCESS) 15137c478bd9Sstevel@tonic-gate return (rv); 15147c478bd9Sstevel@tonic-gate data->cd_length = data_len; 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate return (rv); 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15207c478bd9Sstevel@tonic-gate static int 15217c478bd9Sstevel@tonic-gate rsa_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature, 15227c478bd9Sstevel@tonic-gate crypto_data_t *data, crypto_req_handle_t req) 15237c478bd9Sstevel@tonic-gate { 15247c478bd9Sstevel@tonic-gate int rv; 15257c478bd9Sstevel@tonic-gate rsa_ctx_t *ctxp; 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate ASSERT(ctx->cc_provider_private != NULL); 15287c478bd9Sstevel@tonic-gate ctxp = ctx->cc_provider_private; 15297c478bd9Sstevel@tonic-gate 1530726fad2aSDina K Nimeh /* See the comments on KM_SLEEP flag in rsaprov_encrypt() */ 15317c478bd9Sstevel@tonic-gate rv = rsa_verify_recover_common(ctxp->mech_type, ctxp->key, 1532726fad2aSDina K Nimeh signature, data); 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate if (rv != CRYPTO_BUFFER_TOO_SMALL) 15357c478bd9Sstevel@tonic-gate (void) rsa_free_context(ctx); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate return (rv); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* ARGSUSED */ 15417c478bd9Sstevel@tonic-gate static int 15427c478bd9Sstevel@tonic-gate rsa_verify_recover_atomic(crypto_provider_handle_t provider, 15437c478bd9Sstevel@tonic-gate crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 15447c478bd9Sstevel@tonic-gate crypto_key_t *key, crypto_data_t *signature, crypto_data_t *data, 15457c478bd9Sstevel@tonic-gate crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 15467c478bd9Sstevel@tonic-gate { 15477c478bd9Sstevel@tonic-gate int rv; 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate if ((rv = check_mech_and_key(mechanism, key)) != CRYPTO_SUCCESS) 15507c478bd9Sstevel@tonic-gate return (rv); 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate return (rsa_verify_recover_common(mechanism->cm_type, key, 1553726fad2aSDina K Nimeh signature, data)); 15547c478bd9Sstevel@tonic-gate } 1555