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 5b60f2a0bSfr41279 * Common Development and Distribution License (the "License"). 6b60f2a0bSfr41279 * 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 */ 217c478bd9Sstevel@tonic-gate 22*726fad2aSDina K Nimeh /* 23*726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24*726fad2aSDina K Nimeh */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <pthread.h> 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 32*726fad2aSDina K Nimeh #include <cryptoutil.h> 337c478bd9Sstevel@tonic-gate #include "softGlobal.h" 347c478bd9Sstevel@tonic-gate #include "softSession.h" 357c478bd9Sstevel@tonic-gate #include "softObject.h" 367c478bd9Sstevel@tonic-gate #include "softOps.h" 377c478bd9Sstevel@tonic-gate #include "softRSA.h" 387c478bd9Sstevel@tonic-gate #include "softMAC.h" 397c478bd9Sstevel@tonic-gate #include "softCrypt.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate CK_RV 427c478bd9Sstevel@tonic-gate soft_rsa_encrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len, 437c478bd9Sstevel@tonic-gate CK_BYTE_PTR out, int realpublic) 447c478bd9Sstevel@tonic-gate { 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate uchar_t expo[MAX_KEY_ATTR_BUFLEN]; 497c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 507c478bd9Sstevel@tonic-gate uint32_t expo_len = sizeof (expo); 517c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 52*726fad2aSDina K Nimeh RSAbytekey k; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate if (realpublic) { 55c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_PUBLIC_EXPONENT, expo, 567c478bd9Sstevel@tonic-gate &expo_len); 577c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 587c478bd9Sstevel@tonic-gate goto clean1; 597c478bd9Sstevel@tonic-gate } 607c478bd9Sstevel@tonic-gate } else { 61c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_PRIVATE_EXPONENT, expo, 627c478bd9Sstevel@tonic-gate &expo_len); 637c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 647c478bd9Sstevel@tonic-gate goto clean1; 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate } 677c478bd9Sstevel@tonic-gate 68c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len); 697c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 707c478bd9Sstevel@tonic-gate goto clean1; 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 73*726fad2aSDina K Nimeh k.modulus = modulus; 74*726fad2aSDina K Nimeh k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len); 75*726fad2aSDina K Nimeh k.pubexpo = expo; 76*726fad2aSDina K Nimeh k.pubexpo_bytes = expo_len; 77*726fad2aSDina K Nimeh k.rfunc = NULL; 787c478bd9Sstevel@tonic-gate 79*726fad2aSDina K Nimeh rv = rsa_encrypt(&k, in, in_len, out); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate clean1: 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate return (rv); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate CK_RV 887c478bd9Sstevel@tonic-gate soft_rsa_decrypt(soft_object_t *key, CK_BYTE_PTR in, uint32_t in_len, 897c478bd9Sstevel@tonic-gate CK_BYTE_PTR out) 907c478bd9Sstevel@tonic-gate { 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 957c478bd9Sstevel@tonic-gate uchar_t prime1[MAX_KEY_ATTR_BUFLEN]; 967c478bd9Sstevel@tonic-gate uchar_t prime2[MAX_KEY_ATTR_BUFLEN]; 977c478bd9Sstevel@tonic-gate uchar_t expo1[MAX_KEY_ATTR_BUFLEN]; 987c478bd9Sstevel@tonic-gate uchar_t expo2[MAX_KEY_ATTR_BUFLEN]; 997c478bd9Sstevel@tonic-gate uchar_t coef[MAX_KEY_ATTR_BUFLEN]; 1007c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 1017c478bd9Sstevel@tonic-gate uint32_t prime1_len = sizeof (prime1); 1027c478bd9Sstevel@tonic-gate uint32_t prime2_len = sizeof (prime2); 1037c478bd9Sstevel@tonic-gate uint32_t expo1_len = sizeof (expo1); 1047c478bd9Sstevel@tonic-gate uint32_t expo2_len = sizeof (expo2); 1057c478bd9Sstevel@tonic-gate uint32_t coef_len = sizeof (coef); 106*726fad2aSDina K Nimeh RSAbytekey k; 1077c478bd9Sstevel@tonic-gate 108c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len); 1097c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1107c478bd9Sstevel@tonic-gate goto clean1; 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 113c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_PRIME_1, prime1, &prime1_len); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate if ((prime1_len == 0) && (rv == CKR_OK)) { 1167c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, in, in_len, out, 0); 1177c478bd9Sstevel@tonic-gate goto clean1; 1187c478bd9Sstevel@tonic-gate } else { 1197c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1207c478bd9Sstevel@tonic-gate goto clean1; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 123c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_PRIME_2, prime2, &prime2_len); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate if ((prime2_len == 0) && (rv == CKR_OK)) { 1267c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, in, in_len, out, 0); 1277c478bd9Sstevel@tonic-gate goto clean1; 1287c478bd9Sstevel@tonic-gate } else { 1297c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1307c478bd9Sstevel@tonic-gate goto clean1; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 133c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_EXPONENT_1, expo1, &expo1_len); 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if ((expo1_len == 0) && (rv == CKR_OK)) { 1367c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, in, in_len, out, 0); 1377c478bd9Sstevel@tonic-gate goto clean1; 1387c478bd9Sstevel@tonic-gate } else { 1397c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1407c478bd9Sstevel@tonic-gate goto clean1; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 143c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_EXPONENT_2, expo2, &expo2_len); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate if ((expo2_len == 0) && (rv == CKR_OK)) { 1467c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, in, in_len, out, 0); 1477c478bd9Sstevel@tonic-gate goto clean1; 1487c478bd9Sstevel@tonic-gate } else { 1497c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1507c478bd9Sstevel@tonic-gate goto clean1; 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 153c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_COEFFICIENT, coef, &coef_len); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate if ((coef_len == 0) && (rv == CKR_OK)) { 1567c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, in, in_len, out, 0); 1577c478bd9Sstevel@tonic-gate goto clean1; 1587c478bd9Sstevel@tonic-gate } else { 1597c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1607c478bd9Sstevel@tonic-gate goto clean1; 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 163*726fad2aSDina K Nimeh k.modulus = modulus; 164*726fad2aSDina K Nimeh k.modulus_bits = CRYPTO_BYTES2BITS(modulus_len); 165*726fad2aSDina K Nimeh k.prime1 = prime1; 166*726fad2aSDina K Nimeh k.prime1_bytes = prime1_len; 167*726fad2aSDina K Nimeh k.prime2 = prime2; 168*726fad2aSDina K Nimeh k.prime2_bytes = prime2_len; 169*726fad2aSDina K Nimeh k.expo1 = expo1; 170*726fad2aSDina K Nimeh k.expo1_bytes = expo1_len; 171*726fad2aSDina K Nimeh k.expo2 = expo2; 172*726fad2aSDina K Nimeh k.expo2_bytes = expo2_len; 173*726fad2aSDina K Nimeh k.coeff = coef; 174*726fad2aSDina K Nimeh k.coeff_bytes = coef_len; 175*726fad2aSDina K Nimeh k.rfunc = NULL; 1767c478bd9Sstevel@tonic-gate 177*726fad2aSDina K Nimeh rv = rsa_decrypt(&k, in, in_len, out); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate clean1: 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate return (rv); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Allocate a RSA context for the active encryption or decryption operation. 1867c478bd9Sstevel@tonic-gate * This function is called without the session lock held. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate CK_RV 1897c478bd9Sstevel@tonic-gate soft_rsa_crypt_init_common(soft_session_t *session_p, 1907c478bd9Sstevel@tonic-gate CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 1917c478bd9Sstevel@tonic-gate boolean_t encrypt) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx; 1957c478bd9Sstevel@tonic-gate soft_object_t *tmp_key = NULL; 1967c478bd9Sstevel@tonic-gate CK_RV rv; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate rsa_ctx = calloc(1, sizeof (soft_rsa_ctx_t)); 1997c478bd9Sstevel@tonic-gate if (rsa_ctx == NULL) { 2007c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Make a copy of the encryption or decryption key, and save it 2057c478bd9Sstevel@tonic-gate * in the RSA crypto context since it will be used later for 2067c478bd9Sstevel@tonic-gate * encryption/decryption. We don't want to hold any object reference 2077c478bd9Sstevel@tonic-gate * on this original key while doing encryption/decryption. 2087c478bd9Sstevel@tonic-gate */ 2097c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&key_p->object_mutex); 2107c478bd9Sstevel@tonic-gate rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, 2117c478bd9Sstevel@tonic-gate NULL); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) || (tmp_key == NULL)) { 2147c478bd9Sstevel@tonic-gate /* Most likely we ran out of space. */ 2157c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 2167c478bd9Sstevel@tonic-gate free(rsa_ctx); 2177c478bd9Sstevel@tonic-gate return (rv); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* No need to hold the lock on the old object. */ 2217c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 2227c478bd9Sstevel@tonic-gate rsa_ctx->key = tmp_key; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2257c478bd9Sstevel@tonic-gate if (encrypt) { 2267c478bd9Sstevel@tonic-gate /* Called by C_EncryptInit. */ 2277c478bd9Sstevel@tonic-gate session_p->encrypt.context = rsa_ctx; 2287c478bd9Sstevel@tonic-gate session_p->encrypt.mech.mechanism = pMechanism->mechanism; 2297c478bd9Sstevel@tonic-gate } else { 2307c478bd9Sstevel@tonic-gate /* Called by C_DecryptInit. */ 2317c478bd9Sstevel@tonic-gate session_p->decrypt.context = rsa_ctx; 2327c478bd9Sstevel@tonic-gate session_p->decrypt.mech.mechanism = pMechanism->mechanism; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate return (CKR_OK); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate CK_RV 2407c478bd9Sstevel@tonic-gate soft_rsa_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData, 2417c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, 2427c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism) 2437c478bd9Sstevel@tonic-gate { 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->encrypt.context; 2467c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 2477c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 2487c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 2497c478bd9Sstevel@tonic-gate CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 2507c478bd9Sstevel@tonic-gate CK_BYTE cipher_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 2517c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 2527c478bd9Sstevel@tonic-gate 253c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len); 2547c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2557c478bd9Sstevel@tonic-gate goto clean_exit; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (pEncrypted == NULL) { 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Application asks for the length of the output buffer 2617c478bd9Sstevel@tonic-gate * to hold the ciphertext. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate *pulEncryptedLen = modulus_len; 2647c478bd9Sstevel@tonic-gate rv = CKR_OK; 2657c478bd9Sstevel@tonic-gate goto clean1; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate if (mechanism == CKM_RSA_PKCS) { 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * Input data length needs to be <= 2717c478bd9Sstevel@tonic-gate * modulus length-MIN_PKCS1_PADLEN. 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) { 2747c478bd9Sstevel@tonic-gate *pulEncryptedLen = modulus_len; 2757c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 2767c478bd9Sstevel@tonic-gate goto clean_exit; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate } else { 2797c478bd9Sstevel@tonic-gate /* Input data length needs to be <= modulus length. */ 2807c478bd9Sstevel@tonic-gate if (ulDataLen > (CK_ULONG)modulus_len) { 2817c478bd9Sstevel@tonic-gate *pulEncryptedLen = modulus_len; 2827c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 2837c478bd9Sstevel@tonic-gate goto clean_exit; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 2887c478bd9Sstevel@tonic-gate if (*pulEncryptedLen < (CK_ULONG)modulus_len) { 2897c478bd9Sstevel@tonic-gate *pulEncryptedLen = modulus_len; 2907c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 2917c478bd9Sstevel@tonic-gate goto clean1; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (mechanism == CKM_RSA_PKCS) { 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Add PKCS padding to the input data to format a block 2977c478bd9Sstevel@tonic-gate * type "02" encryption block. 2987c478bd9Sstevel@tonic-gate */ 299*726fad2aSDina K Nimeh rv = pkcs1_encode(PKCS1_ENCRYPT, pData, ulDataLen, plain_data, 3007c478bd9Sstevel@tonic-gate modulus_len); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3037c478bd9Sstevel@tonic-gate goto clean_exit; 3047c478bd9Sstevel@tonic-gate } else { 3057c478bd9Sstevel@tonic-gate /* Pad zeros for the leading bytes of the input data. */ 3067c478bd9Sstevel@tonic-gate (void) memset(plain_data, 0x0, modulus_len - ulDataLen); 3077c478bd9Sstevel@tonic-gate (void) memcpy(&plain_data[modulus_len - ulDataLen], pData, 3087c478bd9Sstevel@tonic-gate ulDataLen); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, plain_data, modulus_len, cipher_data, 1); 3127c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 3137c478bd9Sstevel@tonic-gate (void) memcpy(pEncrypted, cipher_data, modulus_len); 3147c478bd9Sstevel@tonic-gate *pulEncryptedLen = modulus_len; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate clean_exit: 3187c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3197c478bd9Sstevel@tonic-gate free(session_p->encrypt.context); 3207c478bd9Sstevel@tonic-gate session_p->encrypt.context = NULL; 3217c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3227c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 3237c478bd9Sstevel@tonic-gate free(key); 3247c478bd9Sstevel@tonic-gate clean1: 3257c478bd9Sstevel@tonic-gate return (rv); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate CK_RV 3307c478bd9Sstevel@tonic-gate soft_rsa_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 3317c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 3327c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism) 3337c478bd9Sstevel@tonic-gate { 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->decrypt.context; 3367c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 3377c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 3387c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 3397c478bd9Sstevel@tonic-gate CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 3407c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 3417c478bd9Sstevel@tonic-gate 342c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len); 3437c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3447c478bd9Sstevel@tonic-gate goto clean_exit; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate if (ulEncryptedLen != (CK_ULONG)modulus_len) { 3487c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 3497c478bd9Sstevel@tonic-gate goto clean_exit; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate if (pData == NULL) { 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Application asks for the length of the output buffer 3557c478bd9Sstevel@tonic-gate * to hold the recovered data. 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 3587c478bd9Sstevel@tonic-gate rv = CKR_OK; 3597c478bd9Sstevel@tonic-gate goto clean1; 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (mechanism == CKM_RSA_X_509) { 3637c478bd9Sstevel@tonic-gate if (*pulDataLen < (CK_ULONG)modulus_len) { 3647c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 3657c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 3667c478bd9Sstevel@tonic-gate goto clean1; 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate rv = soft_rsa_decrypt(key, pEncrypted, modulus_len, plain_data); 3717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3727c478bd9Sstevel@tonic-gate goto clean_exit; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (mechanism == CKM_RSA_PKCS) { 376*726fad2aSDina K Nimeh size_t plain_len = modulus_len; 377*726fad2aSDina K Nimeh size_t num_padding; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* Strip off the PKCS block formatting data. */ 380*726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_DECRYPT, plain_data, &plain_len); 3817c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3827c478bd9Sstevel@tonic-gate goto clean_exit; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate num_padding = modulus_len - plain_len; 3857c478bd9Sstevel@tonic-gate if (ulEncryptedLen - num_padding > *pulDataLen) { 3867c478bd9Sstevel@tonic-gate *pulDataLen = plain_len; 3877c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 3887c478bd9Sstevel@tonic-gate goto clean1; 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate (void) memcpy(pData, &plain_data[num_padding], plain_len); 3927c478bd9Sstevel@tonic-gate *pulDataLen = plain_len; 3937c478bd9Sstevel@tonic-gate } else { 3947c478bd9Sstevel@tonic-gate (void) memcpy(pData, plain_data, modulus_len); 3957c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate clean_exit: 3997c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 4007c478bd9Sstevel@tonic-gate free(session_p->decrypt.context); 4017c478bd9Sstevel@tonic-gate session_p->decrypt.context = NULL; 4027c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 4037c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 4047c478bd9Sstevel@tonic-gate free(key); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate clean1: 4077c478bd9Sstevel@tonic-gate return (rv); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * Allocate a RSA context for the active sign or verify operation. 4127c478bd9Sstevel@tonic-gate * This function is called without the session lock held. 4137c478bd9Sstevel@tonic-gate */ 4147c478bd9Sstevel@tonic-gate CK_RV 4157c478bd9Sstevel@tonic-gate soft_rsa_sign_verify_init_common(soft_session_t *session_p, 4167c478bd9Sstevel@tonic-gate CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 4177c478bd9Sstevel@tonic-gate boolean_t sign) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 4207c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx; 4217c478bd9Sstevel@tonic-gate CK_MECHANISM digest_mech; 4227c478bd9Sstevel@tonic-gate soft_object_t *tmp_key = NULL; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate if (sign) { 4257c478bd9Sstevel@tonic-gate if ((key_p->class != CKO_PRIVATE_KEY) || 4267c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_RSA)) 4277c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT); 4287c478bd9Sstevel@tonic-gate } else { 4297c478bd9Sstevel@tonic-gate if ((key_p->class != CKO_PUBLIC_KEY) || 4307c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_RSA)) 4317c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate switch (pMechanism->mechanism) { 4357c478bd9Sstevel@tonic-gate case CKM_MD5_RSA_PKCS: 4367c478bd9Sstevel@tonic-gate digest_mech.mechanism = CKM_MD5; 4377c478bd9Sstevel@tonic-gate rv = soft_digest_init_internal(session_p, &digest_mech); 4387c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4397c478bd9Sstevel@tonic-gate return (rv); 4407c478bd9Sstevel@tonic-gate break; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate case CKM_SHA1_RSA_PKCS: 4437c478bd9Sstevel@tonic-gate digest_mech.mechanism = CKM_SHA_1; 44460722cc8Sizick digest_mech.pParameter = pMechanism->pParameter; 44560722cc8Sizick digest_mech.ulParameterLen = pMechanism->ulParameterLen; 4467c478bd9Sstevel@tonic-gate rv = soft_digest_init_internal(session_p, &digest_mech); 4477c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4487c478bd9Sstevel@tonic-gate return (rv); 4497c478bd9Sstevel@tonic-gate break; 450f66d273dSizick 451f66d273dSizick case CKM_SHA256_RSA_PKCS: 452f66d273dSizick digest_mech.mechanism = CKM_SHA256; 453f66d273dSizick rv = soft_digest_init_internal(session_p, &digest_mech); 454f66d273dSizick if (rv != CKR_OK) 455f66d273dSizick return (rv); 456f66d273dSizick break; 457f66d273dSizick 458f66d273dSizick case CKM_SHA384_RSA_PKCS: 459f66d273dSizick digest_mech.mechanism = CKM_SHA384; 460f66d273dSizick rv = soft_digest_init_internal(session_p, &digest_mech); 461f66d273dSizick if (rv != CKR_OK) 462f66d273dSizick return (rv); 463f66d273dSizick break; 464f66d273dSizick 465f66d273dSizick case CKM_SHA512_RSA_PKCS: 466f66d273dSizick digest_mech.mechanism = CKM_SHA512; 467f66d273dSizick rv = soft_digest_init_internal(session_p, &digest_mech); 468f66d273dSizick if (rv != CKR_OK) 469f66d273dSizick return (rv); 470f66d273dSizick break; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate rsa_ctx = malloc(sizeof (soft_rsa_ctx_t)); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (rsa_ctx == NULL) { 4767c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 4777c478bd9Sstevel@tonic-gate goto clean_exit; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&key_p->object_mutex); 4817c478bd9Sstevel@tonic-gate rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, 4827c478bd9Sstevel@tonic-gate NULL); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) || (tmp_key == NULL)) { 4857c478bd9Sstevel@tonic-gate /* Most likely we ran out of space. */ 4867c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 4877c478bd9Sstevel@tonic-gate free(rsa_ctx); 4887c478bd9Sstevel@tonic-gate goto clean_exit; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* No need to hold the lock on the old object. */ 4927c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 4937c478bd9Sstevel@tonic-gate rsa_ctx->key = tmp_key; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if (sign) { 4987c478bd9Sstevel@tonic-gate session_p->sign.context = rsa_ctx; 4997c478bd9Sstevel@tonic-gate session_p->sign.mech.mechanism = pMechanism->mechanism; 5007c478bd9Sstevel@tonic-gate } else { 5017c478bd9Sstevel@tonic-gate session_p->verify.context = rsa_ctx; 5027c478bd9Sstevel@tonic-gate session_p->verify.mech.mechanism = pMechanism->mechanism; 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate return (CKR_OK); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate clean_exit: 5107c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 5117c478bd9Sstevel@tonic-gate if (session_p->digest.context != NULL) { 5127c478bd9Sstevel@tonic-gate free(session_p->digest.context); 5137c478bd9Sstevel@tonic-gate session_p->digest.context = NULL; 5147c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 5177c478bd9Sstevel@tonic-gate return (rv); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate CK_RV 5237c478bd9Sstevel@tonic-gate soft_rsa_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 5247c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 5257c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism) 5267c478bd9Sstevel@tonic-gate { 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 5297c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->sign.context; 5307c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 5317c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 5327c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 5337c478bd9Sstevel@tonic-gate CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 5347c478bd9Sstevel@tonic-gate CK_BYTE signed_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 5357c478bd9Sstevel@tonic-gate 536c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len); 5377c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5387c478bd9Sstevel@tonic-gate goto clean_exit; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if (pSigned == NULL) { 5427c478bd9Sstevel@tonic-gate /* Application asks for the length of the output buffer. */ 5437c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 5447c478bd9Sstevel@tonic-gate rv = CKR_OK; 5457c478bd9Sstevel@tonic-gate goto clean1; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate switch (mechanism) { 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS: 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * Input data length needs to be <= 5547c478bd9Sstevel@tonic-gate * modulus length-MIN_PKCS1_PADLEN. 5557c478bd9Sstevel@tonic-gate */ 5567c478bd9Sstevel@tonic-gate if (ulDataLen > ((CK_ULONG)modulus_len - MIN_PKCS1_PADLEN)) { 5577c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 5587c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 5597c478bd9Sstevel@tonic-gate goto clean_exit; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate break; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate case CKM_RSA_X_509: 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* Input data length needs to be <= modulus length. */ 5667c478bd9Sstevel@tonic-gate if (ulDataLen > (CK_ULONG)modulus_len) { 5677c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 5687c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 5697c478bd9Sstevel@tonic-gate goto clean_exit; 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate break; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 5757c478bd9Sstevel@tonic-gate if (*pulSignedLen < (CK_ULONG)modulus_len) { 5767c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 5777c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 5787c478bd9Sstevel@tonic-gate goto clean1; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate switch (mechanism) { 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS: 5847c478bd9Sstevel@tonic-gate case CKM_MD5_RSA_PKCS: 5857c478bd9Sstevel@tonic-gate case CKM_SHA1_RSA_PKCS: 586f66d273dSizick case CKM_SHA256_RSA_PKCS: 587f66d273dSizick case CKM_SHA384_RSA_PKCS: 588f66d273dSizick case CKM_SHA512_RSA_PKCS: 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Add PKCS padding to the input data to format a block 5917c478bd9Sstevel@tonic-gate * type "01" encryption block. 5927c478bd9Sstevel@tonic-gate */ 593*726fad2aSDina K Nimeh rv = pkcs1_encode(PKCS1_SIGN, pData, ulDataLen, plain_data, 5947c478bd9Sstevel@tonic-gate modulus_len); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5977c478bd9Sstevel@tonic-gate goto clean_exit; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate case CKM_RSA_X_509: 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate /* Pad zeros for the leading bytes of the input data. */ 6047c478bd9Sstevel@tonic-gate (void) memset(plain_data, 0x0, modulus_len - ulDataLen); 6057c478bd9Sstevel@tonic-gate (void) memcpy(&plain_data[modulus_len - ulDataLen], pData, 6067c478bd9Sstevel@tonic-gate ulDataLen); 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Perform RSA encryption with the signer's RSA private key 6127c478bd9Sstevel@tonic-gate * for signature process. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate rv = soft_rsa_decrypt(key, plain_data, modulus_len, signed_data); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 6177c478bd9Sstevel@tonic-gate (void) memcpy(pSigned, signed_data, modulus_len); 6187c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate clean_exit: 6227c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 6237c478bd9Sstevel@tonic-gate free(session_p->sign.context); 6247c478bd9Sstevel@tonic-gate session_p->sign.context = NULL; 6257c478bd9Sstevel@tonic-gate if (session_p->digest.context != NULL) { 6267c478bd9Sstevel@tonic-gate free(session_p->digest.context); 6277c478bd9Sstevel@tonic-gate session_p->digest.context = NULL; 6287c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 6317c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 6327c478bd9Sstevel@tonic-gate free(key); 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate clean1: 6357c478bd9Sstevel@tonic-gate return (rv); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate CK_RV 6407c478bd9Sstevel@tonic-gate soft_rsa_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 6417c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 6427c478bd9Sstevel@tonic-gate CK_ULONG ulSignatureLen, CK_MECHANISM_TYPE mechanism) 6437c478bd9Sstevel@tonic-gate { 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 6467c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->verify.context; 6477c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 6487c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 6497c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 6507c478bd9Sstevel@tonic-gate CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 6517c478bd9Sstevel@tonic-gate 652c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len); 6537c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6547c478bd9Sstevel@tonic-gate goto clean_exit; 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 657*726fad2aSDina K Nimeh if (ulDataLen == 0) { 658*726fad2aSDina K Nimeh rv = CKR_DATA_LEN_RANGE; 659*726fad2aSDina K Nimeh goto clean_exit; 660*726fad2aSDina K Nimeh } 661*726fad2aSDina K Nimeh 6627c478bd9Sstevel@tonic-gate if (ulSignatureLen != (CK_ULONG)modulus_len) { 6637c478bd9Sstevel@tonic-gate rv = CKR_SIGNATURE_LEN_RANGE; 6647c478bd9Sstevel@tonic-gate goto clean_exit; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * Perform RSA decryption with the signer's RSA public key 6697c478bd9Sstevel@tonic-gate * for verification process. 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1); 6727c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 6737c478bd9Sstevel@tonic-gate switch (mechanism) { 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS: 6767c478bd9Sstevel@tonic-gate case CKM_MD5_RSA_PKCS: 6777c478bd9Sstevel@tonic-gate case CKM_SHA1_RSA_PKCS: 678f66d273dSizick case CKM_SHA256_RSA_PKCS: 679f66d273dSizick case CKM_SHA384_RSA_PKCS: 680f66d273dSizick case CKM_SHA512_RSA_PKCS: 6817c478bd9Sstevel@tonic-gate { 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * Strip off the encoded padding bytes in front of the 6847c478bd9Sstevel@tonic-gate * recovered data, then compare the recovered data with 6857c478bd9Sstevel@tonic-gate * the original data. 6867c478bd9Sstevel@tonic-gate */ 687*726fad2aSDina K Nimeh size_t data_len = modulus_len; 6887c478bd9Sstevel@tonic-gate 689*726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len); 6907c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6917c478bd9Sstevel@tonic-gate goto clean_exit; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if ((CK_ULONG)data_len != ulDataLen) { 695*726fad2aSDina K Nimeh rv = CKR_DATA_LEN_RANGE; 6967c478bd9Sstevel@tonic-gate goto clean_exit; 6977c478bd9Sstevel@tonic-gate } else if (memcmp(pData, 6987c478bd9Sstevel@tonic-gate &plain_data[modulus_len - data_len], 6997c478bd9Sstevel@tonic-gate ulDataLen) != 0) { 7007c478bd9Sstevel@tonic-gate rv = CKR_SIGNATURE_INVALID; 7017c478bd9Sstevel@tonic-gate goto clean_exit; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate case CKM_RSA_X_509: 7077c478bd9Sstevel@tonic-gate /* 7087c478bd9Sstevel@tonic-gate * Strip off the encoded padding bytes in front of the 7097c478bd9Sstevel@tonic-gate * recovered plain_data, then compare the input data 7107c478bd9Sstevel@tonic-gate * with the recovered data. 7117c478bd9Sstevel@tonic-gate */ 7127c478bd9Sstevel@tonic-gate if (memcmp(pData, 7137c478bd9Sstevel@tonic-gate plain_data + ulSignatureLen - ulDataLen, 7147c478bd9Sstevel@tonic-gate ulDataLen) != 0) { 7157c478bd9Sstevel@tonic-gate rv = CKR_SIGNATURE_INVALID; 7167c478bd9Sstevel@tonic-gate goto clean_exit; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate break; 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if (rv == CKR_DATA_LEN_RANGE) { 7237c478bd9Sstevel@tonic-gate if ((mechanism == CKM_MD5_RSA_PKCS) || 724f66d273dSizick (mechanism == CKM_SHA1_RSA_PKCS) || 725f66d273dSizick (mechanism == CKM_SHA256_RSA_PKCS) || 726f66d273dSizick (mechanism == CKM_SHA384_RSA_PKCS) || 727f66d273dSizick (mechanism == CKM_SHA512_RSA_PKCS)) 7287c478bd9Sstevel@tonic-gate rv = CKR_SIGNATURE_INVALID; 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate clean_exit: 7327c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 7337c478bd9Sstevel@tonic-gate free(session_p->verify.context); 7347c478bd9Sstevel@tonic-gate session_p->verify.context = NULL; 7357c478bd9Sstevel@tonic-gate if (session_p->digest.context != NULL) { 7367c478bd9Sstevel@tonic-gate free(session_p->digest.context); 7377c478bd9Sstevel@tonic-gate session_p->digest.context = NULL; 7387c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 7417c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 7427c478bd9Sstevel@tonic-gate free(key); 7437c478bd9Sstevel@tonic-gate return (rv); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate CK_RV 747*726fad2aSDina K Nimeh soft_genRSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 748*726fad2aSDina K Nimeh uchar_t *buf, uint32_t buflen, boolean_t public) 7497c478bd9Sstevel@tonic-gate { 7507c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 7517c478bd9Sstevel@tonic-gate biginteger_t *dst = NULL; 7527c478bd9Sstevel@tonic-gate biginteger_t src; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate switch (type) { 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate case CKA_MODULUS: 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (public) 7597c478bd9Sstevel@tonic-gate dst = OBJ_PUB_RSA_MOD(key); 7607c478bd9Sstevel@tonic-gate else 7617c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_MOD(key); 7627c478bd9Sstevel@tonic-gate break; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate case CKA_PUBLIC_EXPONENT: 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate if (public) 7677c478bd9Sstevel@tonic-gate dst = OBJ_PUB_RSA_PUBEXPO(key); 7687c478bd9Sstevel@tonic-gate else 7697c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_PUBEXPO(key); 7707c478bd9Sstevel@tonic-gate break; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate case CKA_PRIVATE_EXPONENT: 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_PRIEXPO(key); 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate case CKA_PRIME_1: 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_PRIME1(key); 7807c478bd9Sstevel@tonic-gate break; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate case CKA_PRIME_2: 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_PRIME2(key); 7857c478bd9Sstevel@tonic-gate break; 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate case CKA_EXPONENT_1: 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_EXPO1(key); 7907c478bd9Sstevel@tonic-gate break; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate case CKA_EXPONENT_2: 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_EXPO2(key); 7957c478bd9Sstevel@tonic-gate break; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate case CKA_COEFFICIENT: 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate dst = OBJ_PRI_RSA_COEF(key); 8007c478bd9Sstevel@tonic-gate break; 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 803*726fad2aSDina K Nimeh /* Note: no explanation found for why this is needed */ 8047c478bd9Sstevel@tonic-gate while (buf[0] == 0) { /* remove proceeding 0x00 */ 8057c478bd9Sstevel@tonic-gate buf++; 8067c478bd9Sstevel@tonic-gate buflen--; 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 809*726fad2aSDina K Nimeh if ((rv = dup_bigint_attr(&src, buf, buflen)) != CKR_OK) 8107c478bd9Sstevel@tonic-gate goto cleanexit; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* Copy the attribute in the key object. */ 8137c478bd9Sstevel@tonic-gate copy_bigint_attr(&src, dst); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate cleanexit: 8167c478bd9Sstevel@tonic-gate return (rv); 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate CK_RV 8227c478bd9Sstevel@tonic-gate soft_rsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 825*726fad2aSDina K Nimeh CK_ATTRIBUTE template; 826*726fad2aSDina K Nimeh uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 8277c478bd9Sstevel@tonic-gate uint32_t modulus_len; 8287c478bd9Sstevel@tonic-gate uchar_t pub_expo[MAX_KEY_ATTR_BUFLEN]; 8297c478bd9Sstevel@tonic-gate uint32_t pub_expo_len = sizeof (pub_expo); 830*726fad2aSDina K Nimeh uchar_t private_exponent[MAX_KEY_ATTR_BUFLEN]; 831*726fad2aSDina K Nimeh uint32_t private_exponent_len = sizeof (private_exponent); 832*726fad2aSDina K Nimeh uchar_t prime1[MAX_KEY_ATTR_BUFLEN]; 833*726fad2aSDina K Nimeh uint32_t prime1_len = sizeof (prime1); 834*726fad2aSDina K Nimeh uchar_t prime2[MAX_KEY_ATTR_BUFLEN]; 835*726fad2aSDina K Nimeh uint32_t prime2_len = sizeof (prime2); 836*726fad2aSDina K Nimeh uchar_t exponent1[MAX_KEY_ATTR_BUFLEN]; 837*726fad2aSDina K Nimeh uint32_t exponent1_len = sizeof (exponent1); 838*726fad2aSDina K Nimeh uchar_t exponent2[MAX_KEY_ATTR_BUFLEN]; 839*726fad2aSDina K Nimeh uint32_t exponent2_len = sizeof (exponent2); 840*726fad2aSDina K Nimeh uchar_t coefficient[MAX_KEY_ATTR_BUFLEN]; 841*726fad2aSDina K Nimeh uint32_t coefficient_len = sizeof (coefficient); 842*726fad2aSDina K Nimeh RSAbytekey k; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate if ((pubkey == NULL) || (prikey == NULL)) { 8457c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate template.pValue = malloc(sizeof (CK_ULONG)); 8497c478bd9Sstevel@tonic-gate if (template.pValue == NULL) { 8507c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate template.ulValueLen = sizeof (CK_ULONG); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate rv = get_ulong_attr_from_object(OBJ_PUB_RSA_MOD_BITS(pubkey), 8557c478bd9Sstevel@tonic-gate &template); 8567c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 857*726fad2aSDina K Nimeh free(template.pValue); 8587c478bd9Sstevel@tonic-gate goto clean0; 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate #ifdef __sparcv9 8627c478bd9Sstevel@tonic-gate /* LINTED */ 8637c478bd9Sstevel@tonic-gate modulus_len = (uint32_t)(*((CK_ULONG *)(template.pValue))); 8647c478bd9Sstevel@tonic-gate #else /* !__sparcv9 */ 8657c478bd9Sstevel@tonic-gate modulus_len = *((CK_ULONG *)(template.pValue)); 8667c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 8677c478bd9Sstevel@tonic-gate 868*726fad2aSDina K Nimeh free(template.pValue); 8697c478bd9Sstevel@tonic-gate 870c64d15a5Smcpowers rv = soft_get_public_value(pubkey, CKA_PUBLIC_EXPONENT, pub_expo, 8717c478bd9Sstevel@tonic-gate &pub_expo_len); 8727c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8737c478bd9Sstevel@tonic-gate goto clean0; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 876*726fad2aSDina K Nimeh /* Inputs to RSA key pair generation */ 877*726fad2aSDina K Nimeh k.modulus_bits = modulus_len; /* save modulus len in bits */ 878*726fad2aSDina K Nimeh modulus_len = CRYPTO_BITS2BYTES(modulus_len); /* convert to bytes */ 879*726fad2aSDina K Nimeh k.modulus = modulus; 880*726fad2aSDina K Nimeh k.pubexpo = pub_expo; 881*726fad2aSDina K Nimeh k.pubexpo_bytes = pub_expo_len; 882*726fad2aSDina K Nimeh k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ? 883*726fad2aSDina K Nimeh pkcs11_get_random : pkcs11_get_urandom; 884*726fad2aSDina K Nimeh 885*726fad2aSDina K Nimeh /* Outputs from RSA key pair generation */ 886*726fad2aSDina K Nimeh k.privexpo = private_exponent; 887*726fad2aSDina K Nimeh k.privexpo_bytes = private_exponent_len; 888*726fad2aSDina K Nimeh k.prime1 = prime1; 889*726fad2aSDina K Nimeh k.prime1_bytes = prime1_len; 890*726fad2aSDina K Nimeh k.prime2 = prime2; 891*726fad2aSDina K Nimeh k.prime2_bytes = prime2_len; 892*726fad2aSDina K Nimeh k.expo1 = exponent1; 893*726fad2aSDina K Nimeh k.expo1_bytes = exponent1_len; 894*726fad2aSDina K Nimeh k.expo2 = exponent2; 895*726fad2aSDina K Nimeh k.expo2_bytes = exponent2_len; 896*726fad2aSDina K Nimeh k.coeff = coefficient; 897*726fad2aSDina K Nimeh k.coeff_bytes = coefficient_len; 898*726fad2aSDina K Nimeh 899*726fad2aSDina K Nimeh rv = rsa_genkey_pair(&k); 900*726fad2aSDina K Nimeh 901*726fad2aSDina K Nimeh if (rv != CKR_OK) { 9027c478bd9Sstevel@tonic-gate goto clean0; 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate /* 9067c478bd9Sstevel@tonic-gate * Add modulus in public template, and add all eight key fields 9077c478bd9Sstevel@tonic-gate * in private template. 9087c478bd9Sstevel@tonic-gate */ 909*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(pubkey, CKA_MODULUS, 910*726fad2aSDina K Nimeh modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_TRUE)) != CKR_OK) { 911*726fad2aSDina K Nimeh goto clean0; 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 914*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_MODULUS, 915*726fad2aSDina K Nimeh modulus, CRYPTO_BITS2BYTES(k.modulus_bits), B_FALSE)) != CKR_OK) { 916*726fad2aSDina K Nimeh goto clean0; 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 919*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIVATE_EXPONENT, 920*726fad2aSDina K Nimeh private_exponent, k.privexpo_bytes, B_FALSE)) != CKR_OK) { 921*726fad2aSDina K Nimeh goto clean0; 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 924*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PUBLIC_EXPONENT, 925*726fad2aSDina K Nimeh pub_expo, k.pubexpo_bytes, B_FALSE)) != CKR_OK) { 926*726fad2aSDina K Nimeh goto clean0; 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate 929*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_1, 930*726fad2aSDina K Nimeh prime1, k.prime1_bytes, B_FALSE)) != CKR_OK) { 931*726fad2aSDina K Nimeh goto clean0; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 934*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_PRIME_2, 935*726fad2aSDina K Nimeh prime2, k.prime2_bytes, B_FALSE)) != CKR_OK) { 936*726fad2aSDina K Nimeh goto clean0; 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 939*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_1, 940*726fad2aSDina K Nimeh exponent1, k.expo1_bytes, B_FALSE)) != CKR_OK) { 941*726fad2aSDina K Nimeh goto clean0; 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate 944*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_EXPONENT_2, 945*726fad2aSDina K Nimeh exponent2, k.expo2_bytes, B_FALSE)) != CKR_OK) { 946*726fad2aSDina K Nimeh goto clean0; 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 949*726fad2aSDina K Nimeh if ((rv = soft_genRSAkey_set_attribute(prikey, CKA_COEFFICIENT, 950*726fad2aSDina K Nimeh coefficient, k.coeff_bytes, B_FALSE)) != CKR_OK) { 951*726fad2aSDina K Nimeh goto clean0; 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate clean0: 9557c478bd9Sstevel@tonic-gate return (rv); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 95860722cc8Sizick 95960722cc8Sizick CK_ULONG 96060722cc8Sizick get_rsa_sha1_prefix(CK_MECHANISM_PTR mech, CK_BYTE_PTR *prefix) { 96160722cc8Sizick if (mech->pParameter == NULL) { 96260722cc8Sizick *prefix = (CK_BYTE *)SHA1_DER_PREFIX; 96360722cc8Sizick return (SHA1_DER_PREFIX_Len); 96460722cc8Sizick } 96560722cc8Sizick 96660722cc8Sizick *prefix = (CK_BYTE *)SHA1_DER_PREFIX_OID; 96760722cc8Sizick return (SHA1_DER_PREFIX_OID_Len); 96860722cc8Sizick } 96960722cc8Sizick 9707c478bd9Sstevel@tonic-gate CK_RV 9717c478bd9Sstevel@tonic-gate soft_rsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 9727c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 9737c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final) 9747c478bd9Sstevel@tonic-gate { 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 977f66d273dSizick CK_BYTE hash[SHA512_DIGEST_LENGTH]; /* space enough for all mechs */ 978f66d273dSizick CK_ULONG hash_len = SHA512_DIGEST_LENGTH; 979f66d273dSizick /* space enough for all mechs */ 980f66d273dSizick CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len]; 9817c478bd9Sstevel@tonic-gate CK_ULONG der_data_len; 9827c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->sign.context; 9837c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 9847c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 9857c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 98660722cc8Sizick CK_ULONG der_len; 98760722cc8Sizick CK_BYTE_PTR der_prefix; 9887c478bd9Sstevel@tonic-gate 989c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_MODULUS, modulus, &modulus_len); 9907c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 9917c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 9927c478bd9Sstevel@tonic-gate free(session_p->digest.context); 9937c478bd9Sstevel@tonic-gate session_p->digest.context = NULL; 9947c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 9957c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 9967c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 9977c478bd9Sstevel@tonic-gate free(key); 9987c478bd9Sstevel@tonic-gate goto clean1; 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate /* Check arguments before performing message digest. */ 10027c478bd9Sstevel@tonic-gate if (pSigned == NULL) { 10037c478bd9Sstevel@tonic-gate /* Application asks for the length of the output buffer. */ 10047c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 10057c478bd9Sstevel@tonic-gate rv = CKR_OK; 10067c478bd9Sstevel@tonic-gate goto clean1; 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 10107c478bd9Sstevel@tonic-gate if (*pulSignedLen < (CK_ULONG)modulus_len) { 10117c478bd9Sstevel@tonic-gate *pulSignedLen = modulus_len; 10127c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 10137c478bd9Sstevel@tonic-gate goto clean1; 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate if (Final) { 10177c478bd9Sstevel@tonic-gate rv = soft_digest_final(session_p, hash, &hash_len); 10187c478bd9Sstevel@tonic-gate } else { 10197c478bd9Sstevel@tonic-gate rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 10237c478bd9Sstevel@tonic-gate /* free the signature key */ 10247c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 10257c478bd9Sstevel@tonic-gate free(key); 10267c478bd9Sstevel@tonic-gate goto clean_exit; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate /* 103060722cc8Sizick * Prepare the DER encoding of the DigestInfo value by setting it to: 103160722cc8Sizick * <MECH>_DER_PREFIX || H 10327c478bd9Sstevel@tonic-gate * 10337c478bd9Sstevel@tonic-gate * See rsa_impl.c for more details. 10347c478bd9Sstevel@tonic-gate */ 1035f66d273dSizick switch (session_p->digest.mech.mechanism) { 1036f66d273dSizick case CKM_MD5: 10377c478bd9Sstevel@tonic-gate (void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len); 10387c478bd9Sstevel@tonic-gate (void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len); 10397c478bd9Sstevel@tonic-gate der_data_len = MD5_DER_PREFIX_Len + hash_len; 1040f66d273dSizick break; 1041f66d273dSizick case CKM_SHA_1: 104260722cc8Sizick der_len = get_rsa_sha1_prefix(&(session_p->digest.mech), 104360722cc8Sizick &der_prefix); 104460722cc8Sizick (void) memcpy(der_data, der_prefix, der_len); 104560722cc8Sizick (void) memcpy(der_data + der_len, hash, hash_len); 104660722cc8Sizick der_data_len = der_len + hash_len; 1047f66d273dSizick break; 1048f66d273dSizick case CKM_SHA256: 1049f66d273dSizick (void) memcpy(der_data, SHA256_DER_PREFIX, 1050f66d273dSizick SHA2_DER_PREFIX_Len); 1051f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1052f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1053f66d273dSizick break; 1054f66d273dSizick case CKM_SHA384: 1055f66d273dSizick (void) memcpy(der_data, SHA384_DER_PREFIX, 1056f66d273dSizick SHA2_DER_PREFIX_Len); 1057f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1058f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1059f66d273dSizick break; 1060f66d273dSizick case CKM_SHA512: 1061f66d273dSizick (void) memcpy(der_data, SHA512_DER_PREFIX, 1062f66d273dSizick SHA2_DER_PREFIX_Len); 1063f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1064f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1065f66d273dSizick break; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * Now, we are ready to sign the DER_ENCODED data 10707c478bd9Sstevel@tonic-gate * soft_rsa_sign_common() will free the signature key. 10717c478bd9Sstevel@tonic-gate */ 10727c478bd9Sstevel@tonic-gate rv = soft_rsa_sign_common(session_p, der_data, der_data_len, 10737c478bd9Sstevel@tonic-gate pSigned, pulSignedLen, mechanism); 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate clean_exit: 10767c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 10777c478bd9Sstevel@tonic-gate /* soft_digest_common() has freed the digest context */ 10787c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 10797c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate clean1: 10827c478bd9Sstevel@tonic-gate return (rv); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate CK_RV 10877c478bd9Sstevel@tonic-gate soft_rsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 10887c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 10897c478bd9Sstevel@tonic-gate CK_ULONG ulSignedLen, CK_MECHANISM_TYPE mechanism, boolean_t Final) 10907c478bd9Sstevel@tonic-gate { 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1093f66d273dSizick CK_BYTE hash[SHA512_DIGEST_LENGTH]; /* space for all mechs */ 1094f66d273dSizick CK_ULONG hash_len = SHA512_DIGEST_LENGTH; 1095f66d273dSizick CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len]; 10967c478bd9Sstevel@tonic-gate CK_ULONG der_data_len; 10977c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->verify.context; 10987c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 109960722cc8Sizick CK_ULONG der_len; 110060722cc8Sizick CK_BYTE_PTR der_prefix; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate if (Final) { 11037c478bd9Sstevel@tonic-gate rv = soft_digest_final(session_p, hash, &hash_len); 11047c478bd9Sstevel@tonic-gate } else { 11057c478bd9Sstevel@tonic-gate rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 11097c478bd9Sstevel@tonic-gate /* free the verification key */ 11107c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 11117c478bd9Sstevel@tonic-gate free(key); 11127c478bd9Sstevel@tonic-gate goto clean_exit; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate /* 11167c478bd9Sstevel@tonic-gate * Prepare the DER encoding of the DigestInfo value as follows: 11177c478bd9Sstevel@tonic-gate * MD5: MD5_DER_PREFIX || H 11187c478bd9Sstevel@tonic-gate * SHA-1: SHA1_DER_PREFIX || H 1119f66d273dSizick * SHA2: SHA2_DER_PREFIX || H 11207c478bd9Sstevel@tonic-gate * 11217c478bd9Sstevel@tonic-gate * See rsa_impl.c for more details. 11227c478bd9Sstevel@tonic-gate */ 1123f66d273dSizick switch (session_p->digest.mech.mechanism) { 1124f66d273dSizick case CKM_MD5: 11257c478bd9Sstevel@tonic-gate (void) memcpy(der_data, MD5_DER_PREFIX, MD5_DER_PREFIX_Len); 11267c478bd9Sstevel@tonic-gate (void) memcpy(der_data + MD5_DER_PREFIX_Len, hash, hash_len); 11277c478bd9Sstevel@tonic-gate der_data_len = MD5_DER_PREFIX_Len + hash_len; 1128f66d273dSizick break; 1129f66d273dSizick case CKM_SHA_1: 113060722cc8Sizick der_len = get_rsa_sha1_prefix(&(session_p->digest.mech), 113160722cc8Sizick &der_prefix); 113260722cc8Sizick (void) memcpy(der_data, der_prefix, der_len); 113360722cc8Sizick (void) memcpy(der_data + der_len, hash, hash_len); 113460722cc8Sizick der_data_len = der_len + hash_len; 1135f66d273dSizick break; 1136f66d273dSizick case CKM_SHA256: 1137f66d273dSizick (void) memcpy(der_data, SHA256_DER_PREFIX, 1138f66d273dSizick SHA2_DER_PREFIX_Len); 1139f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1140f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1141f66d273dSizick break; 1142f66d273dSizick case CKM_SHA384: 1143f66d273dSizick (void) memcpy(der_data, SHA384_DER_PREFIX, 1144f66d273dSizick SHA2_DER_PREFIX_Len); 1145f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1146f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1147f66d273dSizick break; 1148f66d273dSizick case CKM_SHA512: 1149f66d273dSizick (void) memcpy(der_data, SHA512_DER_PREFIX, 1150f66d273dSizick SHA2_DER_PREFIX_Len); 1151f66d273dSizick (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len); 1152f66d273dSizick der_data_len = SHA2_DER_PREFIX_Len + hash_len; 1153f66d273dSizick break; 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate /* 11577c478bd9Sstevel@tonic-gate * Now, we are ready to verify the DER_ENCODED data using signature. 11587c478bd9Sstevel@tonic-gate * soft_rsa_verify_common() will free the verification key. 11597c478bd9Sstevel@tonic-gate */ 11607c478bd9Sstevel@tonic-gate rv = soft_rsa_verify_common(session_p, der_data, der_data_len, 11617c478bd9Sstevel@tonic-gate pSigned, ulSignedLen, mechanism); 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate clean_exit: 11647c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 11657c478bd9Sstevel@tonic-gate /* soft_digest_common() has freed the digest context */ 11667c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 11677c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate return (rv); 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate CK_RV 11757c478bd9Sstevel@tonic-gate soft_rsa_verify_recover(soft_session_t *session_p, CK_BYTE_PTR pSignature, 11767c478bd9Sstevel@tonic-gate CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 11777c478bd9Sstevel@tonic-gate { 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 11807c478bd9Sstevel@tonic-gate soft_rsa_ctx_t *rsa_ctx = session_p->verify.context; 11817c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->verify.mech.mechanism; 11827c478bd9Sstevel@tonic-gate soft_object_t *key = rsa_ctx->key; 11837c478bd9Sstevel@tonic-gate uchar_t modulus[MAX_KEY_ATTR_BUFLEN]; 11847c478bd9Sstevel@tonic-gate uint32_t modulus_len = sizeof (modulus); 11857c478bd9Sstevel@tonic-gate CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES]; 11867c478bd9Sstevel@tonic-gate 1187c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_MODULUS, modulus, &modulus_len); 11887c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 11897c478bd9Sstevel@tonic-gate goto clean_exit; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate if (ulSignatureLen != (CK_ULONG)modulus_len) { 11937c478bd9Sstevel@tonic-gate rv = CKR_SIGNATURE_LEN_RANGE; 11947c478bd9Sstevel@tonic-gate goto clean_exit; 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate /* 11987c478bd9Sstevel@tonic-gate * Perform RSA decryption with the signer's RSA public key 11997c478bd9Sstevel@tonic-gate * for verification process. 12007c478bd9Sstevel@tonic-gate */ 12017c478bd9Sstevel@tonic-gate rv = soft_rsa_encrypt(key, pSignature, modulus_len, plain_data, 1); 12027c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 12037c478bd9Sstevel@tonic-gate switch (mechanism) { 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS: 12067c478bd9Sstevel@tonic-gate { 12077c478bd9Sstevel@tonic-gate /* 12087c478bd9Sstevel@tonic-gate * Strip off the encoded padding bytes in front of the 12097c478bd9Sstevel@tonic-gate * recovered data. 12107c478bd9Sstevel@tonic-gate */ 1211*726fad2aSDina K Nimeh size_t data_len = modulus_len; 12127c478bd9Sstevel@tonic-gate 1213*726fad2aSDina K Nimeh rv = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len); 12147c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 12157c478bd9Sstevel@tonic-gate goto clean_exit; 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* 12197c478bd9Sstevel@tonic-gate * If application asks for the length of the output 12207c478bd9Sstevel@tonic-gate * buffer? 12217c478bd9Sstevel@tonic-gate */ 12227c478bd9Sstevel@tonic-gate if (pData == NULL) { 12237c478bd9Sstevel@tonic-gate *pulDataLen = data_len; 12247c478bd9Sstevel@tonic-gate rv = CKR_OK; 12257c478bd9Sstevel@tonic-gate goto clean1; 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 12297c478bd9Sstevel@tonic-gate if (*pulDataLen < (CK_ULONG)data_len) { 12307c478bd9Sstevel@tonic-gate *pulDataLen = data_len; 12317c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 12327c478bd9Sstevel@tonic-gate goto clean1; 12337c478bd9Sstevel@tonic-gate } 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate (void) memcpy(pData, 12367c478bd9Sstevel@tonic-gate &plain_data[modulus_len - data_len], data_len); 12377c478bd9Sstevel@tonic-gate *pulDataLen = data_len; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate break; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate case CKM_RSA_X_509: 12437c478bd9Sstevel@tonic-gate /* 12447c478bd9Sstevel@tonic-gate * If application asks for the length of the output 12457c478bd9Sstevel@tonic-gate * buffer? 12467c478bd9Sstevel@tonic-gate */ 12477c478bd9Sstevel@tonic-gate if (pData == NULL) { 12487c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 12497c478bd9Sstevel@tonic-gate rv = CKR_OK; 12507c478bd9Sstevel@tonic-gate goto clean1; 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 12547c478bd9Sstevel@tonic-gate if (*pulDataLen < (CK_ULONG)modulus_len) { 12557c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 12567c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 12577c478bd9Sstevel@tonic-gate goto clean1; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate (void) memcpy(pData, plain_data, modulus_len); 12617c478bd9Sstevel@tonic-gate *pulDataLen = modulus_len; 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate break; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate clean_exit: 12687c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 12697c478bd9Sstevel@tonic-gate free(session_p->verify.context); 12707c478bd9Sstevel@tonic-gate session_p->verify.context = NULL; 12717c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 12727c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 12737c478bd9Sstevel@tonic-gate free(key); 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate clean1: 12767c478bd9Sstevel@tonic-gate return (rv); 12777c478bd9Sstevel@tonic-gate } 1278