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 51c02caffSmcpowers * Common Development and Distribution License (the "License"). 61c02caffSmcpowers * 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*1f49a79aSZdenek Kotala * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <fcntl.h> 277c478bd9Sstevel@tonic-gate #include <strings.h> 287c478bd9Sstevel@tonic-gate #include <sys/stat.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/sha1.h> 317c478bd9Sstevel@tonic-gate #include <sys/md5.h> 327c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 337c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 347c478bd9Sstevel@tonic-gate #include "softGlobal.h" 357c478bd9Sstevel@tonic-gate #include "softKeys.h" 367c478bd9Sstevel@tonic-gate #include "softKeystore.h" 377c478bd9Sstevel@tonic-gate #include "softMAC.h" 387c478bd9Sstevel@tonic-gate #include "softObject.h" 397c478bd9Sstevel@tonic-gate #include "softSession.h" 407c478bd9Sstevel@tonic-gate #include "softSSL.h" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * This files contains the implementation of the following PKCS#11 447c478bd9Sstevel@tonic-gate * mechanisms needed by SSL: 457c478bd9Sstevel@tonic-gate * CKM_SSL3_MASTER_KEY_DERIVE 467c478bd9Sstevel@tonic-gate * CKM_SSL3_MASTER_KEY_DERIVE_DH 477c478bd9Sstevel@tonic-gate * CKM_SSL3_KEY_AND_DERIVE 487c478bd9Sstevel@tonic-gate * CKM_TLS_MASTER_KEY_DERIVE 497c478bd9Sstevel@tonic-gate * CKM_TLS_MASTER_KEY_DERIVE_DH 507c478bd9Sstevel@tonic-gate * CKM_TLS_KEY_AND_DERIVE 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * SSL refers to common functions between SSL v3.0 and SSL v3.1 (a.k.a TLS.) 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #define MAX_KEYBLOCK 160 /* should be plenty for all known cipherspecs */ 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #define MAX_DEFAULT_ATTRS 10 /* Enough for major applicarions */ 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static char *ssl3_const_vals[] = { 607c478bd9Sstevel@tonic-gate "A", 617c478bd9Sstevel@tonic-gate "BB", 627c478bd9Sstevel@tonic-gate "CCC", 637c478bd9Sstevel@tonic-gate "DDDD", 647c478bd9Sstevel@tonic-gate "EEEEE", 657c478bd9Sstevel@tonic-gate "FFFFFF", 667c478bd9Sstevel@tonic-gate "GGGGGGG", 677c478bd9Sstevel@tonic-gate "HHHHHHHH", 687c478bd9Sstevel@tonic-gate "IIIIIIIII", 697c478bd9Sstevel@tonic-gate "JJJJJJJJJJ", 707c478bd9Sstevel@tonic-gate }; 717c478bd9Sstevel@tonic-gate static uint_t ssl3_const_lens[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate static uchar_t TLS_MASTER_SECRET_LABEL[] = {"master secret"}; 747c478bd9Sstevel@tonic-gate #define TLS_MASTER_SECRET_LABEL_LEN 13 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static uchar_t TLS_KEY_EXPANSION_LABEL[] = {"key expansion"}; 777c478bd9Sstevel@tonic-gate #define TLS_KEY_EXPANSION_LABEL_LEN 13 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static uchar_t TLS_CLIENT_KEY_LABEL[] = {"client write key"}; 807c478bd9Sstevel@tonic-gate #define TLS_CLIENT_KEY_LABEL_LEN 16 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static uchar_t TLS_SERVER_KEY_LABEL[] = {"server write key"}; 837c478bd9Sstevel@tonic-gate #define TLS_SERVER_KEY_LABEL_LEN 16 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static uchar_t TLS_IV_BLOCK_LABEL[] = {"IV block"}; 867c478bd9Sstevel@tonic-gate #define TLS_IV_BLOCK_LABEL_LEN 8 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static void P_MD5(uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, uint_t, 897c478bd9Sstevel@tonic-gate uchar_t *, uint_t, uchar_t *, uint_t, boolean_t); 907c478bd9Sstevel@tonic-gate static void P_SHA1(uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, uint_t, 917c478bd9Sstevel@tonic-gate uchar_t *, uint_t, uchar_t *, uint_t, boolean_t); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static CK_RV soft_add_derived_key(CK_ATTRIBUTE_PTR, CK_ULONG, 947c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR, soft_session_t *, soft_object_t *); 957c478bd9Sstevel@tonic-gate static void soft_delete_derived_key(soft_session_t *, soft_object_t *); 967c478bd9Sstevel@tonic-gate static void soft_ssl_weaken_key(CK_MECHANISM_PTR, uchar_t *, uint_t, 977c478bd9Sstevel@tonic-gate uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, boolean_t); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * soft_ssl3_churn() 1017c478bd9Sstevel@tonic-gate * Called for derivation of the master secret from the pre-master secret, 1027c478bd9Sstevel@tonic-gate * and for the derivation of the key_block in an SSL3 handshake 1037c478bd9Sstevel@tonic-gate * result is assumed to be larger than rounds * MD5_HASH_SIZE. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate static void 1067c478bd9Sstevel@tonic-gate soft_ssl3_churn(uchar_t *secret, uint_t secretlen, uchar_t *rand1, 1077c478bd9Sstevel@tonic-gate uint_t rand1len, uchar_t *rand2, uint_t rand2len, int rounds, 1087c478bd9Sstevel@tonic-gate uchar_t *result) 1097c478bd9Sstevel@tonic-gate { 1107c478bd9Sstevel@tonic-gate SHA1_CTX sha1_ctx; 1117c478bd9Sstevel@tonic-gate MD5_CTX md5_ctx; 1127c478bd9Sstevel@tonic-gate uchar_t sha1_digest[SHA1_HASH_SIZE]; 1137c478bd9Sstevel@tonic-gate int i; 1147c478bd9Sstevel@tonic-gate uchar_t *ms = result; 1157c478bd9Sstevel@tonic-gate for (i = 0; i < rounds; i++) { 1167c478bd9Sstevel@tonic-gate SHA1Init(&sha1_ctx); 1177c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, (const uint8_t *)ssl3_const_vals[i], 1187c478bd9Sstevel@tonic-gate ssl3_const_lens[i]); 1197c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, secret, secretlen); 1207c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, rand1, rand1len); 1217c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, rand2, rand2len); 1227c478bd9Sstevel@tonic-gate SHA1Final(sha1_digest, &sha1_ctx); 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate MD5Init(&md5_ctx); 1257c478bd9Sstevel@tonic-gate MD5Update(&md5_ctx, secret, secretlen); 1267c478bd9Sstevel@tonic-gate MD5Update(&md5_ctx, sha1_digest, SHA1_HASH_SIZE); 1277c478bd9Sstevel@tonic-gate MD5Final(ms, &md5_ctx); 1287c478bd9Sstevel@tonic-gate ms += MD5_HASH_SIZE; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * This TLS generic Pseudo Random Function expands a triplet 1347c478bd9Sstevel@tonic-gate * {secret, label, seed} into any arbitrary length string of pseudo 1357c478bd9Sstevel@tonic-gate * random bytes. 1367c478bd9Sstevel@tonic-gate * Here, it is called for the derivation of the master secret from the 1377c478bd9Sstevel@tonic-gate * pre-master secret, and for the derivation of the key_block in a TLS 1387c478bd9Sstevel@tonic-gate * handshake 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate static void 1417c478bd9Sstevel@tonic-gate soft_tls_prf(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen, 1427c478bd9Sstevel@tonic-gate uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len, 1437c478bd9Sstevel@tonic-gate uchar_t *result, uint_t resultlen) 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate uchar_t *S1, *S2; 1467c478bd9Sstevel@tonic-gate uchar_t md5_digested_key[MD5_HASH_SIZE]; 1477c478bd9Sstevel@tonic-gate uchar_t sha1_digested_key[SHA1_HASH_SIZE]; 1487c478bd9Sstevel@tonic-gate uint_t L_S, L_S1, L_S2; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* secret is NULL for IV's in exportable ciphersuites */ 1517c478bd9Sstevel@tonic-gate if (secret == NULL) { 1527c478bd9Sstevel@tonic-gate L_S = 0; 1537c478bd9Sstevel@tonic-gate L_S2 = L_S1 = 0; 1547c478bd9Sstevel@tonic-gate S1 = NULL; 1557c478bd9Sstevel@tonic-gate S2 = NULL; 1567c478bd9Sstevel@tonic-gate goto do_P_HASH; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate L_S = roundup(secretlen, 2) / 2; 1607c478bd9Sstevel@tonic-gate L_S1 = L_S; 1617c478bd9Sstevel@tonic-gate L_S2 = L_S; 1627c478bd9Sstevel@tonic-gate S1 = secret; 1637c478bd9Sstevel@tonic-gate S2 = secret + (secretlen / 2); /* Possible overlap of S1 and S2. */ 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* Reduce the half secrets if bigger than the HASH's block size */ 1667c478bd9Sstevel@tonic-gate if (L_S > MD5_HMAC_BLOCK_SIZE) { 1677c478bd9Sstevel@tonic-gate MD5_CTX md5_ctx; 1687c478bd9Sstevel@tonic-gate SHA1_CTX sha1_ctx; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate MD5Init(&md5_ctx); 1717c478bd9Sstevel@tonic-gate MD5Update(&md5_ctx, S1, L_S); 1727c478bd9Sstevel@tonic-gate MD5Final(md5_digested_key, &md5_ctx); 1737c478bd9Sstevel@tonic-gate S1 = md5_digested_key; 1747c478bd9Sstevel@tonic-gate L_S1 = MD5_HASH_SIZE; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate SHA1Init(&sha1_ctx); 1777c478bd9Sstevel@tonic-gate SHA1Update(&sha1_ctx, S2, L_S); 1787c478bd9Sstevel@tonic-gate SHA1Final(sha1_digested_key, &sha1_ctx); 1797c478bd9Sstevel@tonic-gate S2 = sha1_digested_key; 1807c478bd9Sstevel@tonic-gate L_S2 = SHA1_HASH_SIZE; 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR 1857c478bd9Sstevel@tonic-gate * P_SHA-1(S2, label + seed); 1867c478bd9Sstevel@tonic-gate * the 'seed' here is rand1 + rand2 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate do_P_HASH: 1897c478bd9Sstevel@tonic-gate /* The first one writes directly to the result */ 1907c478bd9Sstevel@tonic-gate P_MD5(S1, L_S1, label, labellen, rand1, rand1len, rand2, rand2len, 1917c478bd9Sstevel@tonic-gate result, resultlen, B_FALSE); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* The second one XOR's with the result. */ 1947c478bd9Sstevel@tonic-gate P_SHA1(S2, L_S2, label, labellen, rand1, rand1len, rand2, rand2len, 1957c478bd9Sstevel@tonic-gate result, resultlen, B_TRUE); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * These two expansion routines are very similar. (they can merge one day). 2007c478bd9Sstevel@tonic-gate * They implement the P_HASH() function for MD5 and for SHA1, as defined in 2017c478bd9Sstevel@tonic-gate * RFC2246: 2027c478bd9Sstevel@tonic-gate * 2037c478bd9Sstevel@tonic-gate * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + 2047c478bd9Sstevel@tonic-gate * HMAC_hash(secret, A(2) + seed) + 2057c478bd9Sstevel@tonic-gate * HMAC_hash(secret, A(3) + seed) + ... 2067c478bd9Sstevel@tonic-gate * Where + indicates concatenation. 2077c478bd9Sstevel@tonic-gate * A() is defined as: 2087c478bd9Sstevel@tonic-gate * A(0) = seed 2097c478bd9Sstevel@tonic-gate * A(i) = HMAC_hash(secret, A(i-1)) 2107c478bd9Sstevel@tonic-gate * 2117c478bd9Sstevel@tonic-gate * The seed is the concatenation of 'babel', 'rand1', and 'rand2'. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate static void 2147c478bd9Sstevel@tonic-gate P_MD5(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen, 2157c478bd9Sstevel@tonic-gate uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len, 2167c478bd9Sstevel@tonic-gate uchar_t *result, uint_t resultlen, boolean_t xor_it) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate uint32_t md5_ipad[MD5_HMAC_INTS_PER_BLOCK]; 2197c478bd9Sstevel@tonic-gate uint32_t md5_opad[MD5_HMAC_INTS_PER_BLOCK]; 2207c478bd9Sstevel@tonic-gate uchar_t md5_hmac[MD5_HASH_SIZE]; 2217c478bd9Sstevel@tonic-gate uchar_t A[MD5_HASH_SIZE]; 2227c478bd9Sstevel@tonic-gate md5_hc_ctx_t md5_hmac_ctx; 2237c478bd9Sstevel@tonic-gate uchar_t *res, *cur; 2247c478bd9Sstevel@tonic-gate uint_t left = resultlen; 2257c478bd9Sstevel@tonic-gate int i; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* good compilers will leverage the aligment */ 2287c478bd9Sstevel@tonic-gate bzero(md5_ipad, MD5_HMAC_BLOCK_SIZE); 2297c478bd9Sstevel@tonic-gate bzero(md5_opad, MD5_HMAC_BLOCK_SIZE); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if (secretlen > 0) { 2327c478bd9Sstevel@tonic-gate bcopy(secret, md5_ipad, secretlen); 2337c478bd9Sstevel@tonic-gate bcopy(secret, md5_opad, secretlen); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* A(1) = HMAC_MD5(secret, rand1 + rand2) */ 2377c478bd9Sstevel@tonic-gate md5_hmac_ctx_init(&md5_hmac_ctx, md5_ipad, md5_opad); 2387c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, label, labellen); 2397c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand1, rand1len); 2407c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand2, rand2len); 2417c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, A); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (xor_it) { 2447c478bd9Sstevel@tonic-gate res = md5_hmac; 2457c478bd9Sstevel@tonic-gate cur = result; 2467c478bd9Sstevel@tonic-gate } else { 2477c478bd9Sstevel@tonic-gate res = result; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate while (left > 0) { 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Compute HMAC_MD5(secret, A(i) + seed); 2537c478bd9Sstevel@tonic-gate * The secret is already expanded in the ictx and octx, so 2547c478bd9Sstevel@tonic-gate * we can call the SOFT_MAC_INIT_CTX() directly. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate SOFT_MAC_INIT_CTX(MD5, &md5_hmac_ctx, md5_ipad, md5_opad, 2577c478bd9Sstevel@tonic-gate MD5_HMAC_BLOCK_SIZE); 2587c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, A, MD5_HASH_SIZE); 2597c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, label, labellen); 2607c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand1, rand1len); 2617c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand2, rand2len); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (left > MD5_HASH_SIZE) { 2647c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, res); 2657c478bd9Sstevel@tonic-gate if (xor_it) { 2667c478bd9Sstevel@tonic-gate for (i = 0; i < MD5_HASH_SIZE; i++) { 2677c478bd9Sstevel@tonic-gate *cur ^= res[i]; 2687c478bd9Sstevel@tonic-gate cur++; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate } else { 2717c478bd9Sstevel@tonic-gate res += MD5_HASH_SIZE; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate left -= MD5_HASH_SIZE; 2747c478bd9Sstevel@tonic-gate } else { 2757c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, md5_hmac); 2767c478bd9Sstevel@tonic-gate if (xor_it) { 2777c478bd9Sstevel@tonic-gate for (i = 0; i < left; i++) { 2787c478bd9Sstevel@tonic-gate *cur ^= md5_hmac[i]; 2797c478bd9Sstevel@tonic-gate cur++; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate } else { 2827c478bd9Sstevel@tonic-gate bcopy(md5_hmac, res, left); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate /* A(i) = HMAC_MD5(secret, A(i-1) */ 2877c478bd9Sstevel@tonic-gate SOFT_MAC_INIT_CTX(MD5, &md5_hmac_ctx, md5_ipad, md5_opad, 2887c478bd9Sstevel@tonic-gate MD5_HMAC_BLOCK_SIZE); 2897c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, A, MD5_HASH_SIZE); 2907c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, A); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate static void 2947c478bd9Sstevel@tonic-gate P_SHA1(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen, 2957c478bd9Sstevel@tonic-gate uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len, 2967c478bd9Sstevel@tonic-gate uchar_t *result, uint_t resultlen, boolean_t xor_it) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK]; 2997c478bd9Sstevel@tonic-gate uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK]; 3007c478bd9Sstevel@tonic-gate uchar_t sha1_hmac[SHA1_HASH_SIZE]; 3017c478bd9Sstevel@tonic-gate uchar_t A[SHA1_HASH_SIZE]; 3027c478bd9Sstevel@tonic-gate sha1_hc_ctx_t sha1_hmac_ctx; 3037c478bd9Sstevel@tonic-gate uchar_t *res, *cur; 3047c478bd9Sstevel@tonic-gate uint_t left = resultlen; 3057c478bd9Sstevel@tonic-gate int i; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* good compilers will leverage the aligment */ 3087c478bd9Sstevel@tonic-gate bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE); 3097c478bd9Sstevel@tonic-gate bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (secretlen > 0) { 3127c478bd9Sstevel@tonic-gate bcopy(secret, sha1_ipad, secretlen); 3137c478bd9Sstevel@tonic-gate bcopy(secret, sha1_opad, secretlen); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* A(1) = HMAC_SHA1(secret, rand1 + rand2) */ 3177c478bd9Sstevel@tonic-gate sha1_hmac_ctx_init(&sha1_hmac_ctx, sha1_ipad, sha1_opad); 3187c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, label, labellen); 3197c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand1, rand1len); 3207c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand2, rand2len); 3217c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, A); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if (xor_it) { 3247c478bd9Sstevel@tonic-gate res = sha1_hmac; 3257c478bd9Sstevel@tonic-gate cur = result; 3267c478bd9Sstevel@tonic-gate } else { 3277c478bd9Sstevel@tonic-gate res = result; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate while (left > 0) { 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * Compute HMAC_SHA1(secret, A(i) + seed); 3337c478bd9Sstevel@tonic-gate * The secret is already expanded in the ictx and octx, so 3347c478bd9Sstevel@tonic-gate * we can call the SOFT_MAC_INIT_CTX() directly. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate SOFT_MAC_INIT_CTX(SHA1, &sha1_hmac_ctx, 3377c478bd9Sstevel@tonic-gate (const uchar_t *)sha1_ipad, (const uchar_t *)sha1_opad, 3387c478bd9Sstevel@tonic-gate SHA1_HMAC_BLOCK_SIZE); 3397c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, A, SHA1_HASH_SIZE); 3407c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, label, labellen); 3417c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand1, rand1len); 3427c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand2, rand2len); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (left > SHA1_HASH_SIZE) { 3457c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, res); 3467c478bd9Sstevel@tonic-gate if (xor_it) { 3477c478bd9Sstevel@tonic-gate for (i = 0; i < SHA1_HASH_SIZE; i++) { 3487c478bd9Sstevel@tonic-gate *cur ^= res[i]; 3497c478bd9Sstevel@tonic-gate cur++; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate } else { 3527c478bd9Sstevel@tonic-gate res += SHA1_HASH_SIZE; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate left -= SHA1_HASH_SIZE; 3557c478bd9Sstevel@tonic-gate } else { 3567c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, sha1_hmac); 3577c478bd9Sstevel@tonic-gate if (xor_it) { 3587c478bd9Sstevel@tonic-gate for (i = 0; i < left; i++) { 3597c478bd9Sstevel@tonic-gate *cur ^= sha1_hmac[i]; 3607c478bd9Sstevel@tonic-gate cur++; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate } else { 3637c478bd9Sstevel@tonic-gate bcopy(sha1_hmac, res, left); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate /* A(i) = HMAC_SHA1(secret, A(i-1) */ 3687c478bd9Sstevel@tonic-gate SOFT_MAC_INIT_CTX(SHA1, &sha1_hmac_ctx, 3697c478bd9Sstevel@tonic-gate (const uchar_t *)sha1_ipad, (const uchar_t *)sha1_opad, 3707c478bd9Sstevel@tonic-gate SHA1_HMAC_BLOCK_SIZE); 3717c478bd9Sstevel@tonic-gate SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, A, SHA1_HASH_SIZE); 3727c478bd9Sstevel@tonic-gate SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, A); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate } 37560722cc8Sizick 37660722cc8Sizick /* This function handles the call from C_DeriveKey for CKM_TLS_PRF */ 37760722cc8Sizick CK_RV 37860722cc8Sizick derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param, soft_object_t *basekey_p) 37960722cc8Sizick { 38060722cc8Sizick 38160722cc8Sizick if (param->pOutput == NULL || param->pulOutputLen == 0) 38260722cc8Sizick return (CKR_BUFFER_TOO_SMALL); 38360722cc8Sizick 38460722cc8Sizick (void) soft_tls_prf(OBJ_SEC_VALUE(basekey_p), 38560722cc8Sizick OBJ_SEC_VALUE_LEN(basekey_p), param->pLabel, param->ulLabelLen, 38660722cc8Sizick param->pSeed, param->ulSeedLen, NULL, 0, param->pOutput, 38760722cc8Sizick *param->pulOutputLen); 38860722cc8Sizick 38960722cc8Sizick return (CKR_OK); 39060722cc8Sizick } 39160722cc8Sizick 39260722cc8Sizick 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * soft_ssl_master_key_derive() 3957c478bd9Sstevel@tonic-gate * 3967c478bd9Sstevel@tonic-gate * Arguments: 3977c478bd9Sstevel@tonic-gate * . session_p 3987c478bd9Sstevel@tonic-gate * . mech_p: key derivation mechanism. the mechanism parameter carries the 3997c478bd9Sstevel@tonic-gate * client and master random from the Hello handshake messages. 4007c478bd9Sstevel@tonic-gate * . basekey_p: The pre-master secret key. 4017c478bd9Sstevel@tonic-gate * . pTemplate & ulAttributeCount: Any extra attributes for the key to be 4027c478bd9Sstevel@tonic-gate * created. 4037c478bd9Sstevel@tonic-gate * . phKey: store for handle to the derived key. 4047c478bd9Sstevel@tonic-gate * 4057c478bd9Sstevel@tonic-gate * Description: 4067c478bd9Sstevel@tonic-gate * Derive the SSL master secret from the pre-master secret, the client 4077c478bd9Sstevel@tonic-gate * and server random. 4087c478bd9Sstevel@tonic-gate * In SSL 3.0, master_secret = 4097c478bd9Sstevel@tonic-gate * MD5(pre_master_secret + SHA('A' + pre_master_secret + 4107c478bd9Sstevel@tonic-gate * ClientHello.random + ServerHello.random)) + 4117c478bd9Sstevel@tonic-gate * MD5(pre_master_secret + SHA('BB' + pre_master_secret + 4127c478bd9Sstevel@tonic-gate * ClientHello.random + ServerHello.random)) + 4137c478bd9Sstevel@tonic-gate * MD5(pre_master_secret + SHA('CCC' + pre_master_secret + 4147c478bd9Sstevel@tonic-gate * ClientHello.random + ServerHello.random)); 4157c478bd9Sstevel@tonic-gate * 4167c478bd9Sstevel@tonic-gate * In TLS 1.0 (a.k.a. SSL 3.1), master_secret = 4177c478bd9Sstevel@tonic-gate * PRF(pre_master_secret, "master secret", 4187c478bd9Sstevel@tonic-gate * ClientHello.random + ServerHello.random) 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate CK_RV 4217c478bd9Sstevel@tonic-gate soft_ssl_master_key_derive(soft_session_t *sp, CK_MECHANISM_PTR mech, 4227c478bd9Sstevel@tonic-gate soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate, 4237c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate uchar_t *pmsecret = OBJ_SEC_VALUE(basekey_p); 4267c478bd9Sstevel@tonic-gate #ifdef __sparcv9 4277c478bd9Sstevel@tonic-gate /* LINTED */ 4287c478bd9Sstevel@tonic-gate uint_t pmlen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p); 4297c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 4307c478bd9Sstevel@tonic-gate uint_t pmlen = OBJ_SEC_VALUE_LEN(basekey_p); 4317c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 4327c478bd9Sstevel@tonic-gate CK_SSL3_MASTER_KEY_DERIVE_PARAMS *mkd_params; 4337c478bd9Sstevel@tonic-gate CK_SSL3_RANDOM_DATA *random_data; 4347c478bd9Sstevel@tonic-gate CK_VERSION_PTR pVersion; 4357c478bd9Sstevel@tonic-gate uchar_t ssl_master_secret[48]; 4367c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS class = CKO_SECRET_KEY; 4377c478bd9Sstevel@tonic-gate CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 4387c478bd9Sstevel@tonic-gate CK_BBOOL true = TRUE; 4397c478bd9Sstevel@tonic-gate CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS]; 4407c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR new_tmpl; 4417c478bd9Sstevel@tonic-gate CK_ULONG newattrcount; 4427c478bd9Sstevel@tonic-gate boolean_t new_tmpl_allocated = B_FALSE, is_tls = B_FALSE; 4437c478bd9Sstevel@tonic-gate ulong_t i; 4447c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 4457c478bd9Sstevel@tonic-gate uint_t ClientRandomLen, ServerRandomLen; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate /* Check the validity of the mechanism's parameter */ 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate mkd_params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if (mkd_params == NULL || 4527c478bd9Sstevel@tonic-gate mech->ulParameterLen != sizeof (CK_SSL3_MASTER_KEY_DERIVE_PARAMS)) 4537c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate pVersion = mkd_params->pVersion; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate switch (mech->mechanism) { 4587c478bd9Sstevel@tonic-gate case CKM_TLS_MASTER_KEY_DERIVE: 4597c478bd9Sstevel@tonic-gate is_tls = B_TRUE; 4607c478bd9Sstevel@tonic-gate /* FALLTHRU */ 4617c478bd9Sstevel@tonic-gate case CKM_SSL3_MASTER_KEY_DERIVE: 4627c478bd9Sstevel@tonic-gate /* Invalid pre-master key length. What else to return? */ 4637c478bd9Sstevel@tonic-gate if (pmlen != 48) 4647c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* Get the SSL version number from the premaster secret */ 4677c478bd9Sstevel@tonic-gate if (pVersion == NULL_PTR) 4687c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate bcopy(pmsecret, pVersion, sizeof (CK_VERSION)); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate case CKM_TLS_MASTER_KEY_DERIVE_DH: 4747c478bd9Sstevel@tonic-gate is_tls = B_TRUE; 4757c478bd9Sstevel@tonic-gate /* FALLTHRU */ 4767c478bd9Sstevel@tonic-gate case CKM_SSL3_MASTER_KEY_DERIVE_DH: 4777c478bd9Sstevel@tonic-gate if (pVersion != NULL_PTR) 4787c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate random_data = &mkd_params->RandomInfo; 4827c478bd9Sstevel@tonic-gate #ifdef __sparcv9 4837c478bd9Sstevel@tonic-gate /* LINTED */ 4847c478bd9Sstevel@tonic-gate ClientRandomLen = (uint_t)random_data->ulClientRandomLen; 4857c478bd9Sstevel@tonic-gate /* LINTED */ 4867c478bd9Sstevel@tonic-gate ServerRandomLen = (uint_t)random_data->ulServerRandomLen; 4877c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 4887c478bd9Sstevel@tonic-gate ClientRandomLen = random_data->ulClientRandomLen; 4897c478bd9Sstevel@tonic-gate ServerRandomLen = random_data->ulServerRandomLen; 4907c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 || 4937c478bd9Sstevel@tonic-gate random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) { 4947c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* Now the actual secret derivation */ 4987c478bd9Sstevel@tonic-gate if (!is_tls) { 4997c478bd9Sstevel@tonic-gate soft_ssl3_churn(pmsecret, pmlen, random_data->pClientRandom, 5007c478bd9Sstevel@tonic-gate ClientRandomLen, random_data->pServerRandom, 5017c478bd9Sstevel@tonic-gate ServerRandomLen, 3, ssl_master_secret); 5027c478bd9Sstevel@tonic-gate } else { 5037c478bd9Sstevel@tonic-gate soft_tls_prf(pmsecret, pmlen, TLS_MASTER_SECRET_LABEL, 5047c478bd9Sstevel@tonic-gate TLS_MASTER_SECRET_LABEL_LEN, random_data->pClientRandom, 5057c478bd9Sstevel@tonic-gate ClientRandomLen, random_data->pServerRandom, 5067c478bd9Sstevel@tonic-gate ServerRandomLen, ssl_master_secret, 48); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * The object creation attributes need to be in one contiguous 5117c478bd9Sstevel@tonic-gate * array. In addition to the attrs from the application supplied 5127c478bd9Sstevel@tonic-gate * pTemplates, We need to add the class, type, value, valuelen and 5137c478bd9Sstevel@tonic-gate * CKA_DERIVE. 5147c478bd9Sstevel@tonic-gate * In the most likely case, the application passes between zero and 5157c478bd9Sstevel@tonic-gate * handful of attributes, We optimize for that case by allocating 5167c478bd9Sstevel@tonic-gate * the new template on the stack. Oherwise we malloc() it. 5177c478bd9Sstevel@tonic-gate */ 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate newattrcount = ulAttributeCount + 4; 5207c478bd9Sstevel@tonic-gate if (newattrcount > MAX_DEFAULT_ATTRS) { 5217c478bd9Sstevel@tonic-gate new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (new_tmpl == NULL) 5247c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate new_tmpl_allocated = B_TRUE; 5277c478bd9Sstevel@tonic-gate } else 5287c478bd9Sstevel@tonic-gate new_tmpl = obj_tmpl; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * Fill in the new template. 5327c478bd9Sstevel@tonic-gate * We put the attributes contributed by the mechanism first 5337c478bd9Sstevel@tonic-gate * so that they override the application supplied ones. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate new_tmpl[0].type = CKA_CLASS; 5367c478bd9Sstevel@tonic-gate new_tmpl[0].pValue = &class; 5377c478bd9Sstevel@tonic-gate new_tmpl[0].ulValueLen = sizeof (class); 5387c478bd9Sstevel@tonic-gate new_tmpl[1].type = CKA_KEY_TYPE; 5397c478bd9Sstevel@tonic-gate new_tmpl[1].pValue = &keyType; 5407c478bd9Sstevel@tonic-gate new_tmpl[1].ulValueLen = sizeof (keyType); 5417c478bd9Sstevel@tonic-gate new_tmpl[2].type = CKA_DERIVE; 5427c478bd9Sstevel@tonic-gate new_tmpl[2].pValue = &true; 5437c478bd9Sstevel@tonic-gate new_tmpl[2].ulValueLen = sizeof (true); 5447c478bd9Sstevel@tonic-gate new_tmpl[3].type = CKA_VALUE; 5457c478bd9Sstevel@tonic-gate new_tmpl[3].pValue = ssl_master_secret; 5467c478bd9Sstevel@tonic-gate new_tmpl[3].ulValueLen = 48; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* Any attributes left? */ 5497c478bd9Sstevel@tonic-gate if (ulAttributeCount > 0) { 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /* Validate the default class and type attributes */ 5527c478bd9Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) { 5537c478bd9Sstevel@tonic-gate /* The caller is responsible for proper alignment */ 5547c478bd9Sstevel@tonic-gate if ((pTemplate[i].type == CKA_CLASS) && 5557c478bd9Sstevel@tonic-gate (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) != 5567c478bd9Sstevel@tonic-gate CKO_SECRET_KEY)) { 5577c478bd9Sstevel@tonic-gate rv = CKR_TEMPLATE_INCONSISTENT; 5587c478bd9Sstevel@tonic-gate goto out; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate if ((pTemplate[i].type == CKA_KEY_TYPE) && 5617c478bd9Sstevel@tonic-gate (*((CK_KEY_TYPE *)pTemplate[i].pValue) != 5627c478bd9Sstevel@tonic-gate CKK_GENERIC_SECRET)) { 5637c478bd9Sstevel@tonic-gate rv = CKR_TEMPLATE_INCONSISTENT; 5647c478bd9Sstevel@tonic-gate goto out; 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate bcopy(pTemplate, &new_tmpl[4], 5687c478bd9Sstevel@tonic-gate ulAttributeCount * sizeof (CK_ATTRIBUTE)); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate rv = soft_add_derived_key(new_tmpl, newattrcount, phKey, sp, basekey_p); 5727c478bd9Sstevel@tonic-gate out: 5737c478bd9Sstevel@tonic-gate if (new_tmpl_allocated) 5747c478bd9Sstevel@tonic-gate free(new_tmpl); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate return (rv); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * soft_ssl3_key_and_mac_derive() 5817c478bd9Sstevel@tonic-gate * 5827c478bd9Sstevel@tonic-gate * Arguments: 5837c478bd9Sstevel@tonic-gate * . session_p 5847c478bd9Sstevel@tonic-gate * . mech_p: key derivation mechanism. the mechanism parameter carries the 5857c478bd9Sstevel@tonic-gate * client and mastter random from the Hello handshake messages, 5867c478bd9Sstevel@tonic-gate * the specification of the key and IV sizes, and the location 5877c478bd9Sstevel@tonic-gate * for the resulting keys and IVs. 5887c478bd9Sstevel@tonic-gate * . basekey_p: The master secret key. 5897c478bd9Sstevel@tonic-gate * . pTemplate & ulAttributeCount: Any extra attributes for the key to be 5907c478bd9Sstevel@tonic-gate * created. 5917c478bd9Sstevel@tonic-gate * 5927c478bd9Sstevel@tonic-gate * Description: 5937c478bd9Sstevel@tonic-gate * Derive the SSL key material (Client and server MAC secrets, symmetric 5947c478bd9Sstevel@tonic-gate * keys and IVs), from the master secret and the client 5957c478bd9Sstevel@tonic-gate * and server random. 5967c478bd9Sstevel@tonic-gate * First a keyblock is generated usining the following formula: 5977c478bd9Sstevel@tonic-gate * key_block = 5987c478bd9Sstevel@tonic-gate * MD5(master_secret + SHA(`A' + master_secret + 5997c478bd9Sstevel@tonic-gate * ServerHello.random + 6007c478bd9Sstevel@tonic-gate * ClientHello.random)) + 6017c478bd9Sstevel@tonic-gate * MD5(master_secret + SHA(`BB' + master_secret + 6027c478bd9Sstevel@tonic-gate * ServerHello.random + 6037c478bd9Sstevel@tonic-gate * ClientHello.random)) + 6047c478bd9Sstevel@tonic-gate * MD5(master_secret + SHA(`CCC' + master_secret + 6057c478bd9Sstevel@tonic-gate * ServerHello.random + 6067c478bd9Sstevel@tonic-gate * ClientHello.random)) + [...]; 6077c478bd9Sstevel@tonic-gate * 6087c478bd9Sstevel@tonic-gate * In TLS 1.0 (a.k.a. SSL 3.1), key_block = 6097c478bd9Sstevel@tonic-gate * PRF(master_secret, "key expansion", 6107c478bd9Sstevel@tonic-gate * ServerHello.random + ClientHello.random) 6117c478bd9Sstevel@tonic-gate * 6127c478bd9Sstevel@tonic-gate * Then the keys materials are taken from the keyblock. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate CK_RV 6167c478bd9Sstevel@tonic-gate soft_ssl_key_and_mac_derive(soft_session_t *sp, CK_MECHANISM_PTR mech, 6177c478bd9Sstevel@tonic-gate soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate, 6187c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount) 6197c478bd9Sstevel@tonic-gate { 6207c478bd9Sstevel@tonic-gate uchar_t *msecret = OBJ_SEC_VALUE(basekey_p); 6217c478bd9Sstevel@tonic-gate #ifdef __sparcv9 6227c478bd9Sstevel@tonic-gate /* LINTED */ 6237c478bd9Sstevel@tonic-gate uint_t mslen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p); 6247c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 6257c478bd9Sstevel@tonic-gate uint_t mslen = OBJ_SEC_VALUE_LEN(basekey_p); 6267c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 6277c478bd9Sstevel@tonic-gate CK_SSL3_KEY_MAT_PARAMS *km_params; 6287c478bd9Sstevel@tonic-gate CK_SSL3_RANDOM_DATA *random_data; 6297c478bd9Sstevel@tonic-gate CK_SSL3_KEY_MAT_OUT *kmo; 6307c478bd9Sstevel@tonic-gate uchar_t key_block[MAX_KEYBLOCK], *kb, *export_keys = NULL; 6317c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS class = CKO_SECRET_KEY; 6327c478bd9Sstevel@tonic-gate CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 6337c478bd9Sstevel@tonic-gate CK_BBOOL true = TRUE; 6347c478bd9Sstevel@tonic-gate CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS]; 6357c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR new_tmpl; 6367c478bd9Sstevel@tonic-gate ulong_t newattrcount, mac_key_bytes, secret_key_bytes, iv_bytes; 6371c02caffSmcpowers ulong_t extra_attr_count; 6387c478bd9Sstevel@tonic-gate uint_t size; 6391c02caffSmcpowers int rounds, n = 0; 6407c478bd9Sstevel@tonic-gate boolean_t new_tmpl_allocated = B_FALSE, isExport; 6417c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 6427c478bd9Sstevel@tonic-gate uint_t ClientRandomLen, ServerRandomLen; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* Check the validity of the mechanism's parameter */ 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate km_params = (CK_SSL3_KEY_MAT_PARAMS *)mech->pParameter; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if (km_params == NULL || 6497c478bd9Sstevel@tonic-gate mech->ulParameterLen != sizeof (CK_SSL3_KEY_MAT_PARAMS) || 6507c478bd9Sstevel@tonic-gate (kmo = km_params->pReturnedKeyMaterial) == NULL) 6517c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate isExport = (km_params->bIsExport == TRUE); 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate random_data = &km_params->RandomInfo; 6567c478bd9Sstevel@tonic-gate #ifdef __sparcv9 6577c478bd9Sstevel@tonic-gate /* LINTED */ 6587c478bd9Sstevel@tonic-gate ClientRandomLen = (uint_t)random_data->ulClientRandomLen; 6597c478bd9Sstevel@tonic-gate /* LINTED */ 6607c478bd9Sstevel@tonic-gate ServerRandomLen = (uint_t)random_data->ulServerRandomLen; 6617c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 6627c478bd9Sstevel@tonic-gate ClientRandomLen = random_data->ulClientRandomLen; 6637c478bd9Sstevel@tonic-gate ServerRandomLen = random_data->ulServerRandomLen; 6647c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 || 6677c478bd9Sstevel@tonic-gate random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) { 6687c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate mac_key_bytes = km_params->ulMacSizeInBits / 8; 6727c478bd9Sstevel@tonic-gate secret_key_bytes = km_params->ulKeySizeInBits / 8; 6737c478bd9Sstevel@tonic-gate iv_bytes = km_params->ulIVSizeInBits / 8; 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate if ((iv_bytes > 0) && 6767c478bd9Sstevel@tonic-gate ((kmo->pIVClient == NULL) || (kmo->pIVServer == NULL))) 6777c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * For exportable ciphersuites, the IV's aren't taken from the 6817c478bd9Sstevel@tonic-gate * key block. They are directly derived from the client and 6827c478bd9Sstevel@tonic-gate * server random data. 6837c478bd9Sstevel@tonic-gate * For SSL3.0: 6847c478bd9Sstevel@tonic-gate * client_write_IV = MD5(ClientHello.random + ServerHello.random); 6857c478bd9Sstevel@tonic-gate * server_write_IV = MD5(ServerHello.random + ClientHello.random); 6867c478bd9Sstevel@tonic-gate * For TLS1.0: 6877c478bd9Sstevel@tonic-gate * iv_block = PRF("", "IV block", client_random + 6887c478bd9Sstevel@tonic-gate * server_random)[0..15] 6897c478bd9Sstevel@tonic-gate * client_write_IV = iv_block[0..7] 6907c478bd9Sstevel@tonic-gate * server_write_IV = iv_block[8..15] 6917c478bd9Sstevel@tonic-gate */ 6927c478bd9Sstevel@tonic-gate if ((isExport) && (iv_bytes > 0)) { 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) { 6957c478bd9Sstevel@tonic-gate MD5_CTX exp_md5_ctx; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate if (iv_bytes > MD5_HASH_SIZE) 6987c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate MD5Init(&exp_md5_ctx); 7017c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, random_data->pClientRandom, 7027c478bd9Sstevel@tonic-gate ClientRandomLen); 7037c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, random_data->pServerRandom, 7047c478bd9Sstevel@tonic-gate ServerRandomLen); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* there's room in key_block. use it */ 7077c478bd9Sstevel@tonic-gate MD5Final(key_block, &exp_md5_ctx); 7087c478bd9Sstevel@tonic-gate bcopy(key_block, kmo->pIVClient, iv_bytes); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate MD5Init(&exp_md5_ctx); 7117c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, random_data->pServerRandom, 7127c478bd9Sstevel@tonic-gate ServerRandomLen); 7137c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, random_data->pClientRandom, 7147c478bd9Sstevel@tonic-gate ClientRandomLen); 7157c478bd9Sstevel@tonic-gate MD5Final(key_block, &exp_md5_ctx); 7167c478bd9Sstevel@tonic-gate bcopy(key_block, kmo->pIVServer, iv_bytes); 7177c478bd9Sstevel@tonic-gate } else { 7187c478bd9Sstevel@tonic-gate uchar_t iv_block[16]; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (iv_bytes != 8) 7217c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate soft_tls_prf(NULL, 0, TLS_IV_BLOCK_LABEL, 7247c478bd9Sstevel@tonic-gate TLS_IV_BLOCK_LABEL_LEN, 7257c478bd9Sstevel@tonic-gate random_data->pClientRandom, ClientRandomLen, 7267c478bd9Sstevel@tonic-gate random_data->pServerRandom, ServerRandomLen, 7277c478bd9Sstevel@tonic-gate iv_block, 16); 7281c02caffSmcpowers bcopy(iv_block, kmo->pIVClient, 8); 7291c02caffSmcpowers bcopy(iv_block + 8, kmo->pIVServer, 8); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate /* so we won't allocate a key_block bigger than needed */ 7327c478bd9Sstevel@tonic-gate iv_bytes = 0; 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* Now the actual secret derivation */ 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate #ifdef __sparcv9 7387c478bd9Sstevel@tonic-gate /* LINTED */ 7397c478bd9Sstevel@tonic-gate size = (uint_t)((mac_key_bytes + secret_key_bytes + iv_bytes) * 2); 7407c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 7417c478bd9Sstevel@tonic-gate size = (mac_key_bytes + secret_key_bytes + iv_bytes) * 2; 7427c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* Need to handle this better */ 7457c478bd9Sstevel@tonic-gate if (size > MAX_KEYBLOCK) 7467c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate rounds = howmany(size, MD5_HASH_SIZE); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate kb = key_block; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) { 7537c478bd9Sstevel@tonic-gate soft_ssl3_churn(msecret, mslen, random_data->pServerRandom, 7547c478bd9Sstevel@tonic-gate ServerRandomLen, random_data->pClientRandom, 7557c478bd9Sstevel@tonic-gate ClientRandomLen, rounds, kb); 7567c478bd9Sstevel@tonic-gate } else { 7577c478bd9Sstevel@tonic-gate soft_tls_prf(msecret, mslen, TLS_KEY_EXPANSION_LABEL, 7587c478bd9Sstevel@tonic-gate TLS_KEY_EXPANSION_LABEL_LEN, 7597c478bd9Sstevel@tonic-gate random_data->pServerRandom, ServerRandomLen, 7607c478bd9Sstevel@tonic-gate random_data->pClientRandom, ClientRandomLen, 7617c478bd9Sstevel@tonic-gate kb, size); 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate /* Now create the objects */ 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate kmo->hClientMacSecret = CK_INVALID_HANDLE; 7677c478bd9Sstevel@tonic-gate kmo->hServerMacSecret = CK_INVALID_HANDLE; 7687c478bd9Sstevel@tonic-gate kmo->hClientKey = CK_INVALID_HANDLE; 7697c478bd9Sstevel@tonic-gate kmo->hServerKey = CK_INVALID_HANDLE; 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* First the MAC secrets */ 7727c478bd9Sstevel@tonic-gate if (mac_key_bytes > 0) { 7737c478bd9Sstevel@tonic-gate obj_tmpl[0].type = CKA_CLASS; 7747c478bd9Sstevel@tonic-gate obj_tmpl[0].pValue = &class; /* CKO_SECRET_KEY */ 7757c478bd9Sstevel@tonic-gate obj_tmpl[0].ulValueLen = sizeof (class); 7767c478bd9Sstevel@tonic-gate obj_tmpl[1].type = CKA_KEY_TYPE; 7777c478bd9Sstevel@tonic-gate obj_tmpl[1].pValue = &keyType; /* CKK_GENERIC_SECRET */ 7787c478bd9Sstevel@tonic-gate obj_tmpl[1].ulValueLen = sizeof (keyType); 7797c478bd9Sstevel@tonic-gate obj_tmpl[2].type = CKA_DERIVE; 7807c478bd9Sstevel@tonic-gate obj_tmpl[2].pValue = &true; 7817c478bd9Sstevel@tonic-gate obj_tmpl[2].ulValueLen = sizeof (true); 7827c478bd9Sstevel@tonic-gate obj_tmpl[3].type = CKA_SIGN; 7837c478bd9Sstevel@tonic-gate obj_tmpl[3].pValue = &true; 7847c478bd9Sstevel@tonic-gate obj_tmpl[3].ulValueLen = sizeof (true); 7857c478bd9Sstevel@tonic-gate obj_tmpl[4].type = CKA_VERIFY; 7867c478bd9Sstevel@tonic-gate obj_tmpl[4].pValue = &true; 7877c478bd9Sstevel@tonic-gate obj_tmpl[4].ulValueLen = sizeof (true); 7887c478bd9Sstevel@tonic-gate obj_tmpl[5].type = CKA_VALUE; 7897c478bd9Sstevel@tonic-gate obj_tmpl[5].pValue = kb; 7907c478bd9Sstevel@tonic-gate obj_tmpl[5].ulValueLen = mac_key_bytes; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate rv = soft_add_derived_key(obj_tmpl, 6, 7937c478bd9Sstevel@tonic-gate &(kmo->hClientMacSecret), sp, basekey_p); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 7967c478bd9Sstevel@tonic-gate goto out_err; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate kb += mac_key_bytes; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate obj_tmpl[5].pValue = kb; 8017c478bd9Sstevel@tonic-gate rv = soft_add_derived_key(obj_tmpl, 6, 8027c478bd9Sstevel@tonic-gate &(kmo->hServerMacSecret), sp, basekey_p); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 8057c478bd9Sstevel@tonic-gate goto out_err; 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate kb += mac_key_bytes; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* Then the symmetric ciphers keys */ 8117c478bd9Sstevel@tonic-gate 8121c02caffSmcpowers extra_attr_count = (secret_key_bytes == 0) ? 6 : 5; 8131c02caffSmcpowers newattrcount = ulAttributeCount + extra_attr_count; 8147c478bd9Sstevel@tonic-gate if (newattrcount > MAX_DEFAULT_ATTRS) { 8157c478bd9Sstevel@tonic-gate new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate if (new_tmpl == NULL) 8187c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate new_tmpl_allocated = B_TRUE; 8217c478bd9Sstevel@tonic-gate } else 8227c478bd9Sstevel@tonic-gate new_tmpl = obj_tmpl; 8237c478bd9Sstevel@tonic-gate 8241c02caffSmcpowers new_tmpl[n].type = CKA_CLASS; 8251c02caffSmcpowers new_tmpl[n].pValue = &class; /* CKO_SECRET_KEY */ 8261c02caffSmcpowers new_tmpl[n].ulValueLen = sizeof (class); 8271c02caffSmcpowers ++n; 8287c478bd9Sstevel@tonic-gate /* 8291c02caffSmcpowers * The keyType comes from the application's template, and depends 8301c02caffSmcpowers * on the ciphersuite. The only exception is authentication only 8311c02caffSmcpowers * ciphersuites which do not use cipher keys. 8327c478bd9Sstevel@tonic-gate */ 8331c02caffSmcpowers if (secret_key_bytes == 0) { 8341c02caffSmcpowers new_tmpl[n].type = CKA_KEY_TYPE; 8351c02caffSmcpowers new_tmpl[n].pValue = &keyType; /* CKK_GENERIC_SECRET */ 8361c02caffSmcpowers new_tmpl[n].ulValueLen = sizeof (keyType); 8371c02caffSmcpowers n++; 8381c02caffSmcpowers } 8391c02caffSmcpowers new_tmpl[n].type = CKA_DERIVE; 8401c02caffSmcpowers new_tmpl[n].pValue = &true; 8411c02caffSmcpowers new_tmpl[n].ulValueLen = sizeof (true); 8421c02caffSmcpowers n++; 8431c02caffSmcpowers new_tmpl[n].type = CKA_ENCRYPT; 8441c02caffSmcpowers new_tmpl[n].pValue = &true; 8451c02caffSmcpowers new_tmpl[n].ulValueLen = sizeof (true); 8461c02caffSmcpowers n++; 8471c02caffSmcpowers new_tmpl[n].type = CKA_DECRYPT; 8481c02caffSmcpowers new_tmpl[n].pValue = &true; 8491c02caffSmcpowers new_tmpl[n].ulValueLen = sizeof (true); 8501c02caffSmcpowers n++; 8511c02caffSmcpowers new_tmpl[n].type = CKA_VALUE; 8521c02caffSmcpowers new_tmpl[n].pValue = NULL; 8531c02caffSmcpowers new_tmpl[n].ulValueLen = 0; 8547c478bd9Sstevel@tonic-gate 8551c02caffSmcpowers if (secret_key_bytes > 0) { 8567c478bd9Sstevel@tonic-gate if (isExport) { 8577c478bd9Sstevel@tonic-gate if (secret_key_bytes > MD5_HASH_SIZE) { 8587c478bd9Sstevel@tonic-gate rv = CKR_MECHANISM_PARAM_INVALID; 8597c478bd9Sstevel@tonic-gate goto out_err; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate if ((export_keys = malloc(2 * MD5_HASH_SIZE)) == NULL) { 8627c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 8637c478bd9Sstevel@tonic-gate goto out_err; 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate #ifdef __sparcv9 8667c478bd9Sstevel@tonic-gate /* LINTED */ 8677c478bd9Sstevel@tonic-gate soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes, 8687c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 8697c478bd9Sstevel@tonic-gate soft_ssl_weaken_key(mech, kb, secret_key_bytes, 8707c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 8717c478bd9Sstevel@tonic-gate random_data->pClientRandom, ClientRandomLen, 8727c478bd9Sstevel@tonic-gate random_data->pServerRandom, ServerRandomLen, 8737c478bd9Sstevel@tonic-gate export_keys, B_TRUE); 8741c02caffSmcpowers new_tmpl[n].pValue = export_keys; 8751c02caffSmcpowers new_tmpl[n].ulValueLen = MD5_HASH_SIZE; 8767c478bd9Sstevel@tonic-gate } else { 8771c02caffSmcpowers new_tmpl[n].pValue = kb; 8781c02caffSmcpowers new_tmpl[n].ulValueLen = secret_key_bytes; 8791c02caffSmcpowers } 8800106fafcShaimay } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate if (ulAttributeCount > 0) 8831c02caffSmcpowers bcopy(pTemplate, &new_tmpl[extra_attr_count], 8847c478bd9Sstevel@tonic-gate ulAttributeCount * sizeof (CK_ATTRIBUTE)); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate rv = soft_add_derived_key(new_tmpl, newattrcount, 8877c478bd9Sstevel@tonic-gate &(kmo->hClientKey), sp, basekey_p); 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 8907c478bd9Sstevel@tonic-gate goto out_err; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate kb += secret_key_bytes; 8937c478bd9Sstevel@tonic-gate 8941c02caffSmcpowers if (secret_key_bytes > 0) { 8957c478bd9Sstevel@tonic-gate if (isExport) { 8967c478bd9Sstevel@tonic-gate #ifdef __sparcv9 8977c478bd9Sstevel@tonic-gate /* LINTED */ 8987c478bd9Sstevel@tonic-gate soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes, 8997c478bd9Sstevel@tonic-gate #else /* __sparcv9 */ 9007c478bd9Sstevel@tonic-gate soft_ssl_weaken_key(mech, kb, secret_key_bytes, 9017c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 9027c478bd9Sstevel@tonic-gate random_data->pServerRandom, ServerRandomLen, 9037c478bd9Sstevel@tonic-gate random_data->pClientRandom, ClientRandomLen, 9047c478bd9Sstevel@tonic-gate export_keys + MD5_HASH_SIZE, B_FALSE); 9051c02caffSmcpowers new_tmpl[n].pValue = export_keys + MD5_HASH_SIZE; 9067c478bd9Sstevel@tonic-gate } else 9071c02caffSmcpowers new_tmpl[n].pValue = kb; 9081c02caffSmcpowers } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate rv = soft_add_derived_key(new_tmpl, newattrcount, 9117c478bd9Sstevel@tonic-gate &(kmo->hServerKey), sp, basekey_p); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 9147c478bd9Sstevel@tonic-gate goto out_err; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate kb += secret_key_bytes; 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate /* Finally, the IVs */ 9197c478bd9Sstevel@tonic-gate if (iv_bytes > 0) { 9207c478bd9Sstevel@tonic-gate bcopy(kb, kmo->pIVClient, iv_bytes); 9217c478bd9Sstevel@tonic-gate kb += iv_bytes; 9227c478bd9Sstevel@tonic-gate bcopy(kb, kmo->pIVServer, iv_bytes); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (new_tmpl_allocated) 9267c478bd9Sstevel@tonic-gate free(new_tmpl); 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate if (export_keys != NULL) 9297c478bd9Sstevel@tonic-gate free(export_keys); 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate return (rv); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate out_err: 9347c478bd9Sstevel@tonic-gate if (kmo->hClientMacSecret != CK_INVALID_HANDLE) { 9357c478bd9Sstevel@tonic-gate (void) soft_delete_derived_key(sp, 9367c478bd9Sstevel@tonic-gate (soft_object_t *)(kmo->hClientMacSecret)); 9377c478bd9Sstevel@tonic-gate kmo->hClientMacSecret = CK_INVALID_HANDLE; 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate if (kmo->hServerMacSecret != CK_INVALID_HANDLE) { 9407c478bd9Sstevel@tonic-gate (void) soft_delete_derived_key(sp, 9417c478bd9Sstevel@tonic-gate (soft_object_t *)(kmo->hServerMacSecret)); 9427c478bd9Sstevel@tonic-gate kmo->hServerMacSecret = CK_INVALID_HANDLE; 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate if (kmo->hClientKey != CK_INVALID_HANDLE) { 9457c478bd9Sstevel@tonic-gate (void) soft_delete_derived_key(sp, 9467c478bd9Sstevel@tonic-gate (soft_object_t *)(kmo->hClientKey)); 9477c478bd9Sstevel@tonic-gate kmo->hClientKey = CK_INVALID_HANDLE; 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate if (kmo->hServerKey != CK_INVALID_HANDLE) { 9507c478bd9Sstevel@tonic-gate (void) soft_delete_derived_key(sp, 9517c478bd9Sstevel@tonic-gate (soft_object_t *)(kmo->hServerKey)); 9527c478bd9Sstevel@tonic-gate kmo->hServerKey = CK_INVALID_HANDLE; 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate if (new_tmpl_allocated) 9567c478bd9Sstevel@tonic-gate free(new_tmpl); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate if (export_keys != NULL) 9597c478bd9Sstevel@tonic-gate free(export_keys); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate return (rv); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * Add the derived key to the session, and, if it's a token object, 9667c478bd9Sstevel@tonic-gate * write it to the token. 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate static CK_RV 9697c478bd9Sstevel@tonic-gate soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount, 9707c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phKey, soft_session_t *sp, soft_object_t *basekey_p) 9717c478bd9Sstevel@tonic-gate { 9727c478bd9Sstevel@tonic-gate CK_RV rv; 9737c478bd9Sstevel@tonic-gate soft_object_t *secret_key; 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) { 9767c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate if (((rv = soft_build_secret_key_object(tmpl, attrcount, secret_key, 9807c478bd9Sstevel@tonic-gate SOFT_CREATE_OBJ_INT, 0, (CK_KEY_TYPE)~0UL)) != CKR_OK) || 9817c478bd9Sstevel@tonic-gate ((rv = soft_pin_expired_check(secret_key)) != CKR_OK) || 9827c478bd9Sstevel@tonic-gate ((rv = soft_object_write_access_check(sp, secret_key)) != CKR_OK)) { 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate free(secret_key); 9857c478bd9Sstevel@tonic-gate return (rv); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate /* Set the sensitivity and extractability attributes as a needed */ 9897c478bd9Sstevel@tonic-gate soft_derive_enforce_flags(basekey_p, secret_key); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* Initialize the rest of stuffs in soft_object_t. */ 9927c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&secret_key->object_mutex, NULL); 9937c478bd9Sstevel@tonic-gate secret_key->magic_marker = SOFTTOKEN_OBJECT_MAGIC; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate /* ... and, if it needs to persist, write on the token */ 9967c478bd9Sstevel@tonic-gate if (IS_TOKEN_OBJECT(secret_key)) { 9977c478bd9Sstevel@tonic-gate secret_key->session_handle = (CK_SESSION_HANDLE)NULL; 9987c478bd9Sstevel@tonic-gate soft_add_token_object_to_slot(secret_key); 9997c478bd9Sstevel@tonic-gate rv = soft_put_object_to_keystore(secret_key); 10007c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 10017c478bd9Sstevel@tonic-gate soft_delete_token_object(secret_key, B_FALSE, B_FALSE); 10027c478bd9Sstevel@tonic-gate return (rv); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)secret_key; 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate return (CKR_OK); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* Add the new object to the session's object list. */ 10107c478bd9Sstevel@tonic-gate soft_add_object_to_session(secret_key, sp); 10117c478bd9Sstevel@tonic-gate secret_key->session_handle = (CK_SESSION_HANDLE)sp; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)secret_key; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate return (rv); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate /* 10197c478bd9Sstevel@tonic-gate * Delete the derived key from the session, and, if it's a token object, 10207c478bd9Sstevel@tonic-gate * remove it from the token. 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate static void 10237c478bd9Sstevel@tonic-gate soft_delete_derived_key(soft_session_t *sp, soft_object_t *key) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate /* session_handle is the creating session. It's NULL for token objs */ 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate if (IS_TOKEN_OBJECT(key)) 10287c478bd9Sstevel@tonic-gate soft_delete_token_object(key, B_FALSE, B_FALSE); 10297c478bd9Sstevel@tonic-gate else 1030*1f49a79aSZdenek Kotala soft_delete_object(sp, key, B_FALSE, B_FALSE); 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate /* 10347c478bd9Sstevel@tonic-gate * soft_ssl_weaken_key() 10357c478bd9Sstevel@tonic-gate * Reduce the key length to an exportable size. 10367c478bd9Sstevel@tonic-gate * For SSL3.0: 10377c478bd9Sstevel@tonic-gate * final_client_write_key = MD5(client_write_key + 10387c478bd9Sstevel@tonic-gate * ClientHello.random + 10397c478bd9Sstevel@tonic-gate * ServerHello.random); 10407c478bd9Sstevel@tonic-gate * final_server_write_key = MD5(server_write_key + 10417c478bd9Sstevel@tonic-gate * ServerHello.random + 10427c478bd9Sstevel@tonic-gate * ClientHello.random); 10437c478bd9Sstevel@tonic-gate * For TLS1.0: 10447c478bd9Sstevel@tonic-gate * final_client_write_key = PRF(SecurityParameters.client_write_key, 10457c478bd9Sstevel@tonic-gate * "client write key", 10467c478bd9Sstevel@tonic-gate * SecurityParameters.client_random + 10477c478bd9Sstevel@tonic-gate * SecurityParameters.server_random)[0..15]; 10487c478bd9Sstevel@tonic-gate * final_server_write_key = PRF(SecurityParameters.server_write_key, 10497c478bd9Sstevel@tonic-gate * "server write key", 10507c478bd9Sstevel@tonic-gate * SecurityParameters.client_random + 10517c478bd9Sstevel@tonic-gate * SecurityParameters.server_random)[0..15]; 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate static void 10547c478bd9Sstevel@tonic-gate soft_ssl_weaken_key(CK_MECHANISM_PTR mech, uchar_t *secret, uint_t secretlen, 10557c478bd9Sstevel@tonic-gate uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len, 10567c478bd9Sstevel@tonic-gate uchar_t *result, boolean_t isclient) 10577c478bd9Sstevel@tonic-gate { 10587c478bd9Sstevel@tonic-gate MD5_CTX exp_md5_ctx; 10597c478bd9Sstevel@tonic-gate uchar_t *label; 10607c478bd9Sstevel@tonic-gate uint_t labellen; 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) { 10637c478bd9Sstevel@tonic-gate MD5Init(&exp_md5_ctx); 10647c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, secret, secretlen); 10657c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, rand1, rand1len); 10667c478bd9Sstevel@tonic-gate MD5Update(&exp_md5_ctx, rand2, rand2len); 10677c478bd9Sstevel@tonic-gate MD5Final(result, &exp_md5_ctx); 10687c478bd9Sstevel@tonic-gate } else { 10697c478bd9Sstevel@tonic-gate if (isclient) { 10707c478bd9Sstevel@tonic-gate label = TLS_CLIENT_KEY_LABEL; 10717c478bd9Sstevel@tonic-gate labellen = TLS_CLIENT_KEY_LABEL_LEN; 10721c02caffSmcpowers soft_tls_prf(secret, secretlen, label, labellen, 10731c02caffSmcpowers rand1, rand1len, rand2, rand2len, result, 16); 10747c478bd9Sstevel@tonic-gate } else { 10757c478bd9Sstevel@tonic-gate label = TLS_SERVER_KEY_LABEL; 10767c478bd9Sstevel@tonic-gate labellen = TLS_SERVER_KEY_LABEL_LEN; 10777c478bd9Sstevel@tonic-gate soft_tls_prf(secret, secretlen, label, labellen, 10781c02caffSmcpowers rand2, rand2len, rand1, rand1len, result, 16); 10791c02caffSmcpowers } 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate } 1082