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 560c58272Smarkfen * Common Development and Distribution License (the "License"). 660c58272Smarkfen * 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 */ 21*726fad2aSDina K Nimeh 227c478bd9Sstevel@tonic-gate /* 23*726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 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 "softDSA.h" 377c478bd9Sstevel@tonic-gate #include "softOps.h" 387c478bd9Sstevel@tonic-gate #include "softMAC.h" 397c478bd9Sstevel@tonic-gate #include "softCrypt.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * Allocate a DSA context for the active sign or verify operation. 437c478bd9Sstevel@tonic-gate * This function is called without the session lock held. 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate CK_RV 467c478bd9Sstevel@tonic-gate soft_dsa_sign_verify_init_common(soft_session_t *session_p, 477c478bd9Sstevel@tonic-gate CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 487c478bd9Sstevel@tonic-gate boolean_t sign) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate soft_dsa_ctx_t *dsa_ctx; 527c478bd9Sstevel@tonic-gate CK_MECHANISM digest_mech; 537c478bd9Sstevel@tonic-gate soft_object_t *tmp_key = NULL; 547c478bd9Sstevel@tonic-gate CK_RV rv; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (sign) { 577c478bd9Sstevel@tonic-gate if ((key_p->class != CKO_PRIVATE_KEY) || 587c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_DSA)) 597c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT); 607c478bd9Sstevel@tonic-gate } else { 617c478bd9Sstevel@tonic-gate if ((key_p->class != CKO_PUBLIC_KEY) || 627c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_DSA)) 637c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate if (pMechanism->mechanism == CKM_DSA_SHA1) { 677c478bd9Sstevel@tonic-gate digest_mech.mechanism = CKM_SHA_1; 687c478bd9Sstevel@tonic-gate rv = soft_digest_init_internal(session_p, &digest_mech); 697c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 707c478bd9Sstevel@tonic-gate return (rv); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate dsa_ctx = malloc(sizeof (soft_dsa_ctx_t)); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate if (dsa_ctx == NULL) { 767c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * Make a copy of the signature or verification key, and save it 817c478bd9Sstevel@tonic-gate * in the DSA crypto context since it will be used later for 827c478bd9Sstevel@tonic-gate * signing/verification. We don't want to hold any object reference 837c478bd9Sstevel@tonic-gate * on this original key while doing signing/verification. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&key_p->object_mutex); 867c478bd9Sstevel@tonic-gate rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, 877c478bd9Sstevel@tonic-gate NULL); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) || (tmp_key == NULL)) { 907c478bd9Sstevel@tonic-gate /* Most likely we ran out of space. */ 917c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 927c478bd9Sstevel@tonic-gate free(dsa_ctx); 937c478bd9Sstevel@tonic-gate return (rv); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* No need to hold the lock on the old object. */ 977c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&key_p->object_mutex); 987c478bd9Sstevel@tonic-gate dsa_ctx->key = tmp_key; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate if (sign) { 1037c478bd9Sstevel@tonic-gate session_p->sign.context = dsa_ctx; 1047c478bd9Sstevel@tonic-gate session_p->sign.mech.mechanism = pMechanism->mechanism; 1057c478bd9Sstevel@tonic-gate } else { 1067c478bd9Sstevel@tonic-gate session_p->verify.context = dsa_ctx; 1077c478bd9Sstevel@tonic-gate session_p->verify.mech.mechanism = pMechanism->mechanism; 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate return (CKR_OK); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 115b60f2a0bSfr41279 116*726fad2aSDina K Nimeh static CK_RV 117*726fad2aSDina K Nimeh local_dsa_sign(soft_object_t *key, CK_BYTE_PTR in, CK_ULONG inlen, 118*726fad2aSDina K Nimeh CK_BYTE_PTR out) 1197c478bd9Sstevel@tonic-gate { 120*726fad2aSDina K Nimeh CK_RV rv; 1217c478bd9Sstevel@tonic-gate uchar_t q[MAX_KEY_ATTR_BUFLEN]; 1227c478bd9Sstevel@tonic-gate uchar_t p[MAX_KEY_ATTR_BUFLEN]; 1237c478bd9Sstevel@tonic-gate uchar_t g[MAX_KEY_ATTR_BUFLEN]; 1247c478bd9Sstevel@tonic-gate uchar_t x[MAX_KEY_ATTR_BUFLEN]; 1257c478bd9Sstevel@tonic-gate uint_t qlen = sizeof (q); 1267c478bd9Sstevel@tonic-gate uint_t plen = sizeof (p); 1277c478bd9Sstevel@tonic-gate uint_t glen = sizeof (g); 1287c478bd9Sstevel@tonic-gate uint_t xlen = sizeof (x); 129*726fad2aSDina K Nimeh DSAbytekey k; 1307c478bd9Sstevel@tonic-gate 131*726fad2aSDina K Nimeh rv = soft_get_private_value(key, CKA_PRIME, p, &plen); 1327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1337c478bd9Sstevel@tonic-gate goto clean1; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 136*726fad2aSDina K Nimeh rv = soft_get_private_value(key, CKA_SUBPRIME, q, &qlen); 1377c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1387c478bd9Sstevel@tonic-gate goto clean1; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 141c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_BASE, g, &glen); 1427c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1437c478bd9Sstevel@tonic-gate goto clean1; 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 146c64d15a5Smcpowers rv = soft_get_private_value(key, CKA_VALUE, x, &xlen); 1477c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1487c478bd9Sstevel@tonic-gate goto clean1; 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 151*726fad2aSDina K Nimeh k.prime = p; 152*726fad2aSDina K Nimeh k.prime_bits = CRYPTO_BYTES2BITS(plen); 153*726fad2aSDina K Nimeh k.subprime = q; 154*726fad2aSDina K Nimeh k.subprime_bits = CRYPTO_BYTES2BITS(qlen); 155*726fad2aSDina K Nimeh k.base = g; 156*726fad2aSDina K Nimeh k.base_bytes = glen; 157*726fad2aSDina K Nimeh k.private_x_bits = CRYPTO_BYTES2BITS(xlen); 158*726fad2aSDina K Nimeh k.private_x = x; 159*726fad2aSDina K Nimeh k.rfunc = NULL; 1607c478bd9Sstevel@tonic-gate 161*726fad2aSDina K Nimeh rv = dsa_sign(&k, in, inlen, out); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate clean1: 1647c478bd9Sstevel@tonic-gate return (rv); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 167*726fad2aSDina K Nimeh static CK_RV 168*726fad2aSDina K Nimeh local_dsa_verify(soft_object_t *key, CK_BYTE_PTR data, CK_BYTE_PTR sig) 1697c478bd9Sstevel@tonic-gate { 170*726fad2aSDina K Nimeh CK_RV rv; 1717c478bd9Sstevel@tonic-gate uchar_t g[MAX_KEY_ATTR_BUFLEN]; 1727c478bd9Sstevel@tonic-gate uchar_t y[MAX_KEY_ATTR_BUFLEN]; 1737c478bd9Sstevel@tonic-gate uchar_t p[MAX_KEY_ATTR_BUFLEN]; 1747c478bd9Sstevel@tonic-gate uchar_t q[MAX_KEY_ATTR_BUFLEN]; 1757c478bd9Sstevel@tonic-gate uint_t glen = sizeof (g); 1767c478bd9Sstevel@tonic-gate uint_t ylen = sizeof (y); 1777c478bd9Sstevel@tonic-gate uint_t plen = sizeof (p); 1787c478bd9Sstevel@tonic-gate uint_t qlen = sizeof (q); 179*726fad2aSDina K Nimeh DSAbytekey k; 1807c478bd9Sstevel@tonic-gate 181*726fad2aSDina K Nimeh rv = soft_get_public_value(key, CKA_PRIME, p, &plen); 1827c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1837c478bd9Sstevel@tonic-gate goto clean1; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 186*726fad2aSDina K Nimeh rv = soft_get_public_value(key, CKA_SUBPRIME, q, &qlen); 1877c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1887c478bd9Sstevel@tonic-gate goto clean1; 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 191c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_BASE, g, &glen); 1927c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1937c478bd9Sstevel@tonic-gate goto clean1; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 196c64d15a5Smcpowers rv = soft_get_public_value(key, CKA_VALUE, y, &ylen); 1977c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1987c478bd9Sstevel@tonic-gate goto clean1; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 201*726fad2aSDina K Nimeh k.prime = p; 202*726fad2aSDina K Nimeh k.prime_bits = CRYPTO_BYTES2BITS(plen); 203*726fad2aSDina K Nimeh k.subprime = q; 204*726fad2aSDina K Nimeh k.subprime_bits = CRYPTO_BYTES2BITS(qlen); 205*726fad2aSDina K Nimeh k.base = g; 206*726fad2aSDina K Nimeh k.base_bytes = glen; 207*726fad2aSDina K Nimeh k.public_y_bits = CRYPTO_BYTES2BITS(ylen); 208*726fad2aSDina K Nimeh k.public_y = y; 209*726fad2aSDina K Nimeh k.rfunc = NULL; 2107c478bd9Sstevel@tonic-gate 211*726fad2aSDina K Nimeh rv = dsa_verify(&k, data, sig); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate clean1: 2147c478bd9Sstevel@tonic-gate return (rv); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate CK_RV 2197c478bd9Sstevel@tonic-gate soft_dsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 2207c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 2217c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulSignedLen, boolean_t Final) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 2257c478bd9Sstevel@tonic-gate CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 2267c478bd9Sstevel@tonic-gate CK_ULONG hash_len = SHA1_HASH_SIZE; 2277c478bd9Sstevel@tonic-gate soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 2287c478bd9Sstevel@tonic-gate soft_object_t *key = dsa_ctx->key; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* Check arguments before performing message digest. */ 2317c478bd9Sstevel@tonic-gate if (pSigned == NULL) { 2327c478bd9Sstevel@tonic-gate /* Application asks for the length of the output buffer. */ 2337c478bd9Sstevel@tonic-gate *pulSignedLen = DSA_SIGNATURE_LENGTH; 2347c478bd9Sstevel@tonic-gate goto clean1; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */ 2387c478bd9Sstevel@tonic-gate if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 2397c478bd9Sstevel@tonic-gate *pulSignedLen = DSA_SIGNATURE_LENGTH; 2407c478bd9Sstevel@tonic-gate rv = CKR_BUFFER_TOO_SMALL; 2417c478bd9Sstevel@tonic-gate goto clean1; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (Final) { 2457c478bd9Sstevel@tonic-gate rv = soft_digest_final(session_p, hash, &hash_len); 2467c478bd9Sstevel@tonic-gate } else { 2477c478bd9Sstevel@tonic-gate rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2517c478bd9Sstevel@tonic-gate /* free the signature key */ 2527c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 2537c478bd9Sstevel@tonic-gate free(key); 2547c478bd9Sstevel@tonic-gate goto clean_exit; 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * Now, we are ready to sign the data 2597c478bd9Sstevel@tonic-gate * soft_dsa_sign() will free the signature key. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate rv = soft_dsa_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate clean_exit: 2647c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2657c478bd9Sstevel@tonic-gate /* soft_digest_common() has freed the digest context */ 2667c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 2677c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate clean1: 2707c478bd9Sstevel@tonic-gate return (rv); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate CK_RV 2757c478bd9Sstevel@tonic-gate soft_dsa_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 2767c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 2777c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulSignedLen) 2787c478bd9Sstevel@tonic-gate { 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 2817c478bd9Sstevel@tonic-gate soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 2827c478bd9Sstevel@tonic-gate soft_object_t *key = dsa_ctx->key; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_DSA)) { 2857c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 2867c478bd9Sstevel@tonic-gate goto clean_exit; 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* Output length is always 40 bytes. */ 2907c478bd9Sstevel@tonic-gate if (pSigned == NULL) { 2917c478bd9Sstevel@tonic-gate /* Application asks for the length of the output buffer. */ 2927c478bd9Sstevel@tonic-gate *pulSignedLen = DSA_SIGNATURE_LENGTH; 2937c478bd9Sstevel@tonic-gate return (CKR_OK); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* Input data length needs to be 20 bytes. */ 297d288ba74SAnthony Scarpino if (ulDataLen != DSA_SUBPRIME_BYTES) { 2987c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 2997c478bd9Sstevel@tonic-gate goto clean_exit; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 3037c478bd9Sstevel@tonic-gate *pulSignedLen = DSA_SIGNATURE_LENGTH; 3047c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 307*726fad2aSDina K Nimeh rv = local_dsa_sign(key, pData, ulDataLen, pSigned); 3087c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 3097c478bd9Sstevel@tonic-gate *pulSignedLen = DSA_SIGNATURE_LENGTH; 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate clean_exit: 3137c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3147c478bd9Sstevel@tonic-gate free(session_p->sign.context); 3157c478bd9Sstevel@tonic-gate session_p->sign.context = NULL; 3167c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3177c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 3187c478bd9Sstevel@tonic-gate free(key); 3197c478bd9Sstevel@tonic-gate return (rv); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate CK_RV 3247c478bd9Sstevel@tonic-gate soft_dsa_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 3257c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 3267c478bd9Sstevel@tonic-gate CK_ULONG ulSignatureLen) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 3307c478bd9Sstevel@tonic-gate soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 3317c478bd9Sstevel@tonic-gate soft_object_t *key = dsa_ctx->key; 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_DSA)) { 3347c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 3357c478bd9Sstevel@tonic-gate goto clean_exit; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* Input data length needs to be 20 bytes. */ 339d288ba74SAnthony Scarpino if (ulDataLen != DSA_SUBPRIME_BYTES) { 3407c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE; 3417c478bd9Sstevel@tonic-gate goto clean_exit; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 344*726fad2aSDina K Nimeh /* The signature length is always 40 bytes. */ 345*726fad2aSDina K Nimeh if (ulSignatureLen != DSA_SIGNATURE_LENGTH) { 346*726fad2aSDina K Nimeh rv = CKR_SIGNATURE_LEN_RANGE; 347*726fad2aSDina K Nimeh goto clean_exit; 348*726fad2aSDina K Nimeh } 349*726fad2aSDina K Nimeh 350*726fad2aSDina K Nimeh rv = local_dsa_verify(key, pData, pSignature); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate clean_exit: 3537c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3547c478bd9Sstevel@tonic-gate free(session_p->verify.context); 3557c478bd9Sstevel@tonic-gate session_p->verify.context = NULL; 3567c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3577c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 3587c478bd9Sstevel@tonic-gate free(key); 3597c478bd9Sstevel@tonic-gate return (rv); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate CK_RV 3647c478bd9Sstevel@tonic-gate soft_dsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 3657c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 3667c478bd9Sstevel@tonic-gate CK_ULONG ulSignedLen, boolean_t Final) 3677c478bd9Sstevel@tonic-gate { 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate CK_RV rv; 3707c478bd9Sstevel@tonic-gate CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 3717c478bd9Sstevel@tonic-gate CK_ULONG hash_len = SHA1_HASH_SIZE; 3727c478bd9Sstevel@tonic-gate soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 3737c478bd9Sstevel@tonic-gate soft_object_t *key = dsa_ctx->key; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (Final) { 3767c478bd9Sstevel@tonic-gate rv = soft_digest_final(session_p, hash, &hash_len); 3777c478bd9Sstevel@tonic-gate } else { 3787c478bd9Sstevel@tonic-gate rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3827c478bd9Sstevel@tonic-gate /* free the verification key */ 3837c478bd9Sstevel@tonic-gate soft_cleanup_object(key); 3847c478bd9Sstevel@tonic-gate free(key); 3857c478bd9Sstevel@tonic-gate goto clean_exit; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * Now, we are ready to verify the data using signature. 3907c478bd9Sstevel@tonic-gate * soft_dsa_verify() will free the verification key. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate rv = soft_dsa_verify(session_p, hash, hash_len, 3937c478bd9Sstevel@tonic-gate pSigned, ulSignedLen); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate clean_exit: 3967c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3977c478bd9Sstevel@tonic-gate /* soft_digest_common() has freed the digest context */ 3987c478bd9Sstevel@tonic-gate session_p->digest.flags = 0; 3997c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 4007c478bd9Sstevel@tonic-gate return (rv); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate 404*726fad2aSDina K Nimeh static CK_RV 4057c478bd9Sstevel@tonic-gate soft_genDSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 4067c478bd9Sstevel@tonic-gate uchar_t *value, uint32_t value_len, boolean_t public) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 4107c478bd9Sstevel@tonic-gate biginteger_t *dst = NULL; 4117c478bd9Sstevel@tonic-gate biginteger_t src; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate switch (type) { 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate case CKA_VALUE: 4167c478bd9Sstevel@tonic-gate if (public) 4177c478bd9Sstevel@tonic-gate dst = OBJ_PUB_DSA_VALUE(key); 4187c478bd9Sstevel@tonic-gate else 4197c478bd9Sstevel@tonic-gate dst = OBJ_PRI_DSA_VALUE(key); 4207c478bd9Sstevel@tonic-gate break; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate case CKA_PRIME: 4237c478bd9Sstevel@tonic-gate if (public) 4247c478bd9Sstevel@tonic-gate dst = OBJ_PUB_DSA_PRIME(key); 4257c478bd9Sstevel@tonic-gate else 4267c478bd9Sstevel@tonic-gate dst = OBJ_PRI_DSA_PRIME(key); 4277c478bd9Sstevel@tonic-gate break; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate case CKA_SUBPRIME: 4307c478bd9Sstevel@tonic-gate if (public) 4317c478bd9Sstevel@tonic-gate dst = OBJ_PUB_DSA_SUBPRIME(key); 4327c478bd9Sstevel@tonic-gate else 4337c478bd9Sstevel@tonic-gate dst = OBJ_PRI_DSA_SUBPRIME(key); 4347c478bd9Sstevel@tonic-gate break; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate case CKA_BASE: 4377c478bd9Sstevel@tonic-gate if (public) 4387c478bd9Sstevel@tonic-gate dst = OBJ_PUB_DSA_BASE(key); 4397c478bd9Sstevel@tonic-gate else 4407c478bd9Sstevel@tonic-gate dst = OBJ_PRI_DSA_BASE(key); 4417c478bd9Sstevel@tonic-gate break; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 444*726fad2aSDina K Nimeh /* Note: removal of preceding 0x00 imitates similar code in RSA */ 445*726fad2aSDina K Nimeh while (value[0] == 0) { /* remove preceding 0x00 */ 446*726fad2aSDina K Nimeh value++; 447*726fad2aSDina K Nimeh value_len--; 4487c478bd9Sstevel@tonic-gate } 449*726fad2aSDina K Nimeh 450*726fad2aSDina K Nimeh if ((rv = dup_bigint_attr(&src, value, value_len)) != CKR_OK) 451*726fad2aSDina K Nimeh goto cleanexit; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* Copy the attribute in the key object. */ 4547c478bd9Sstevel@tonic-gate copy_bigint_attr(&src, dst); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate cleanexit: 4577c478bd9Sstevel@tonic-gate /* No need to free big_value because dst holds it now after copy. */ 4587c478bd9Sstevel@tonic-gate return (rv); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate CK_RV 4647c478bd9Sstevel@tonic-gate soft_dsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate CK_RV rv; 4677c478bd9Sstevel@tonic-gate uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 4687c478bd9Sstevel@tonic-gate uint32_t prime_len = sizeof (prime); 4697c478bd9Sstevel@tonic-gate uchar_t subprime[MAX_KEY_ATTR_BUFLEN]; 4707c478bd9Sstevel@tonic-gate uint32_t subprime_len = sizeof (subprime); 4717c478bd9Sstevel@tonic-gate uchar_t base[MAX_KEY_ATTR_BUFLEN]; 4727c478bd9Sstevel@tonic-gate uint32_t base_len = sizeof (base); 473*726fad2aSDina K Nimeh uchar_t pubvalue[MAX_KEY_ATTR_BUFLEN]; 474*726fad2aSDina K Nimeh uint32_t pubvalue_len = sizeof (pubvalue); 475*726fad2aSDina K Nimeh uchar_t privalue[DSA_SUBPRIME_BYTES]; 476*726fad2aSDina K Nimeh uint32_t privalue_len = sizeof (privalue); 477*726fad2aSDina K Nimeh DSAbytekey k; 47860c58272Smarkfen 4797c478bd9Sstevel@tonic-gate if ((pubkey == NULL) || (prikey == NULL)) { 4807c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* lookup prime, subprime and base */ 484c64d15a5Smcpowers rv = soft_get_public_value(pubkey, CKA_PRIME, prime, &prime_len); 4857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4867c478bd9Sstevel@tonic-gate rv = CKR_TEMPLATE_INCOMPLETE; 4877c478bd9Sstevel@tonic-gate goto cleanexit; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 490c64d15a5Smcpowers rv = soft_get_public_value(pubkey, CKA_SUBPRIME, subprime, 4917c478bd9Sstevel@tonic-gate &subprime_len); 4927c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4937c478bd9Sstevel@tonic-gate rv = CKR_TEMPLATE_INCOMPLETE; 4947c478bd9Sstevel@tonic-gate goto cleanexit; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 497c64d15a5Smcpowers rv = soft_get_public_value(pubkey, CKA_BASE, base, &base_len); 4987c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4997c478bd9Sstevel@tonic-gate rv = CKR_TEMPLATE_INCOMPLETE; 5007c478bd9Sstevel@tonic-gate goto cleanexit; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 503*726fad2aSDina K Nimeh /* Inputs to DSA key pair generation. */ 504*726fad2aSDina K Nimeh k.prime = prime; 505*726fad2aSDina K Nimeh k.prime_bits = CRYPTO_BYTES2BITS(prime_len); 506*726fad2aSDina K Nimeh k.subprime = subprime; 507*726fad2aSDina K Nimeh k.subprime_bits = CRYPTO_BYTES2BITS(subprime_len); 508*726fad2aSDina K Nimeh k.base = base; 509*726fad2aSDina K Nimeh k.base_bytes = base_len; 510*726fad2aSDina K Nimeh k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ? 511*726fad2aSDina K Nimeh pkcs11_get_random : pkcs11_get_urandom; 512*726fad2aSDina K Nimeh 513*726fad2aSDina K Nimeh /* Outputs from DSA key pair generation. */ 514*726fad2aSDina K Nimeh k.public_y = pubvalue; 515*726fad2aSDina K Nimeh k.public_y_bits = CRYPTO_BYTES2BITS(pubvalue_len); 516*726fad2aSDina K Nimeh k.private_x = privalue; 517*726fad2aSDina K Nimeh k.private_x_bits = CRYPTO_BYTES2BITS(privalue_len); 518*726fad2aSDina K Nimeh 519*726fad2aSDina K Nimeh rv = dsa_genkey_pair(&k); 520*726fad2aSDina K Nimeh 521*726fad2aSDina K Nimeh if (rv != CKR_OK) { 5227c478bd9Sstevel@tonic-gate goto cleanexit; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* Update attribute in public key. */ 5267c478bd9Sstevel@tonic-gate if ((rv = soft_genDSAkey_set_attribute(pubkey, CKA_VALUE, 527*726fad2aSDina K Nimeh pubvalue, CRYPTO_BITS2BYTES(k.public_y_bits), B_TRUE)) != CKR_OK) { 5287c478bd9Sstevel@tonic-gate goto cleanexit; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate /* Update attributes in private key. */ 5317c478bd9Sstevel@tonic-gate if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_PRIME, 532*726fad2aSDina K Nimeh prime, CRYPTO_BITS2BYTES(k.prime_bits), B_FALSE)) != CKR_OK) { 5337c478bd9Sstevel@tonic-gate goto cleanexit; 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 536*726fad2aSDina K Nimeh if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_SUBPRIME, subprime, 537*726fad2aSDina K Nimeh CRYPTO_BITS2BYTES(k.subprime_bits), B_FALSE)) != CKR_OK) { 5387c478bd9Sstevel@tonic-gate goto cleanexit; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_BASE, 542*726fad2aSDina K Nimeh base, k.base_bytes, B_FALSE)) != CKR_OK) { 5437c478bd9Sstevel@tonic-gate goto cleanexit; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 546*726fad2aSDina K Nimeh if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_VALUE, privalue, 547*726fad2aSDina K Nimeh CRYPTO_BITS2BYTES(k.private_x_bits), B_FALSE)) != CKR_OK) { 5487c478bd9Sstevel@tonic-gate goto cleanexit; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate cleanexit: 5527c478bd9Sstevel@tonic-gate return (rv); 5537c478bd9Sstevel@tonic-gate } 554