xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c (revision 1f49a79a97c031bfe0722e2e812dd0e192355be5)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <fcntl.h>
27 #include <strings.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/sha1.h>
31 #include <sys/md5.h>
32 #include <sys/sysmacros.h>
33 #include <security/cryptoki.h>
34 #include "softGlobal.h"
35 #include "softKeys.h"
36 #include "softKeystore.h"
37 #include "softMAC.h"
38 #include "softObject.h"
39 #include "softSession.h"
40 #include "softSSL.h"
41 
42 /*
43  * This files contains the implementation of the following PKCS#11
44  * mechanisms needed by SSL:
45  * CKM_SSL3_MASTER_KEY_DERIVE
46  * CKM_SSL3_MASTER_KEY_DERIVE_DH
47  * CKM_SSL3_KEY_AND_DERIVE
48  * CKM_TLS_MASTER_KEY_DERIVE
49  * CKM_TLS_MASTER_KEY_DERIVE_DH
50  * CKM_TLS_KEY_AND_DERIVE
51  *
52  * SSL refers to common functions between SSL v3.0 and SSL v3.1 (a.k.a TLS.)
53  */
54 
55 #define	MAX_KEYBLOCK	160	/* should be plenty for all known cipherspecs */
56 
57 #define	MAX_DEFAULT_ATTRS	10	/* Enough for major applicarions */
58 
59 static	char *ssl3_const_vals[] = {
60 	"A",
61 	"BB",
62 	"CCC",
63 	"DDDD",
64 	"EEEEE",
65 	"FFFFFF",
66 	"GGGGGGG",
67 	"HHHHHHHH",
68 	"IIIIIIIII",
69 	"JJJJJJJJJJ",
70 };
71 static	uint_t ssl3_const_lens[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
72 
73 static uchar_t TLS_MASTER_SECRET_LABEL[] = {"master secret"};
74 #define	TLS_MASTER_SECRET_LABEL_LEN	13
75 
76 static uchar_t TLS_KEY_EXPANSION_LABEL[] = {"key expansion"};
77 #define	TLS_KEY_EXPANSION_LABEL_LEN	13
78 
79 static uchar_t TLS_CLIENT_KEY_LABEL[] = {"client write key"};
80 #define	TLS_CLIENT_KEY_LABEL_LEN	16
81 
82 static uchar_t TLS_SERVER_KEY_LABEL[] = {"server write key"};
83 #define	TLS_SERVER_KEY_LABEL_LEN	16
84 
85 static uchar_t TLS_IV_BLOCK_LABEL[] = {"IV block"};
86 #define	TLS_IV_BLOCK_LABEL_LEN	8
87 
88 static void P_MD5(uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, uint_t,
89     uchar_t *, uint_t, uchar_t *, uint_t, boolean_t);
90 static void P_SHA1(uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, uint_t,
91     uchar_t *, uint_t, uchar_t *, uint_t, boolean_t);
92 
93 static CK_RV soft_add_derived_key(CK_ATTRIBUTE_PTR, CK_ULONG,
94     CK_OBJECT_HANDLE_PTR, soft_session_t *, soft_object_t *);
95 static void soft_delete_derived_key(soft_session_t *, soft_object_t *);
96 static void soft_ssl_weaken_key(CK_MECHANISM_PTR, uchar_t *, uint_t,
97     uchar_t *, uint_t, uchar_t *, uint_t, uchar_t *, boolean_t);
98 
99 /*
100  * soft_ssl3_churn()
101  * Called for derivation of the master secret from the pre-master secret,
102  * and for the derivation of the key_block in an SSL3 handshake
103  * result is assumed to be larger than rounds * MD5_HASH_SIZE.
104  */
105 static void
soft_ssl3_churn(uchar_t * secret,uint_t secretlen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,int rounds,uchar_t * result)106 soft_ssl3_churn(uchar_t *secret, uint_t secretlen, uchar_t *rand1,
107     uint_t rand1len, uchar_t *rand2, uint_t rand2len, int rounds,
108     uchar_t *result)
109 {
110 	SHA1_CTX sha1_ctx;
111 	MD5_CTX	md5_ctx;
112 	uchar_t sha1_digest[SHA1_HASH_SIZE];
113 	int i;
114 	uchar_t *ms = result;
115 	for (i = 0; i < rounds; i++) {
116 		SHA1Init(&sha1_ctx);
117 		SHA1Update(&sha1_ctx, (const uint8_t *)ssl3_const_vals[i],
118 		    ssl3_const_lens[i]);
119 		SHA1Update(&sha1_ctx, secret, secretlen);
120 		SHA1Update(&sha1_ctx, rand1, rand1len);
121 		SHA1Update(&sha1_ctx, rand2, rand2len);
122 		SHA1Final(sha1_digest, &sha1_ctx);
123 
124 		MD5Init(&md5_ctx);
125 		MD5Update(&md5_ctx, secret, secretlen);
126 		MD5Update(&md5_ctx, sha1_digest, SHA1_HASH_SIZE);
127 		MD5Final(ms, &md5_ctx);
128 		ms += MD5_HASH_SIZE;
129 	}
130 }
131 
132 /*
133  * This TLS generic Pseudo Random Function expands a triplet
134  * {secret, label, seed} into any arbitrary length string of pseudo
135  * random bytes.
136  * Here, it is called for the derivation of the master secret from the
137  * pre-master secret, and for the derivation of the key_block in a TLS
138  * handshake
139  */
140 static void
soft_tls_prf(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen)141 soft_tls_prf(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
142     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
143     uchar_t *result, uint_t resultlen)
144 {
145 	uchar_t *S1, *S2;
146 	uchar_t md5_digested_key[MD5_HASH_SIZE];
147 	uchar_t sha1_digested_key[SHA1_HASH_SIZE];
148 	uint_t L_S, L_S1, L_S2;
149 
150 	/* secret is NULL for IV's in exportable ciphersuites */
151 	if (secret == NULL) {
152 		L_S = 0;
153 		L_S2 = L_S1 = 0;
154 		S1 = NULL;
155 		S2 = NULL;
156 		goto do_P_HASH;
157 	}
158 
159 	L_S = roundup(secretlen, 2) / 2;
160 	L_S1 = L_S;
161 	L_S2 = L_S;
162 	S1 = secret;
163 	S2 = secret + (secretlen / 2);	/* Possible overlap of S1 and S2. */
164 
165 	/* Reduce the half secrets if bigger than the HASH's block size */
166 	if (L_S > MD5_HMAC_BLOCK_SIZE) {
167 		MD5_CTX	md5_ctx;
168 		SHA1_CTX sha1_ctx;
169 
170 		MD5Init(&md5_ctx);
171 		MD5Update(&md5_ctx, S1, L_S);
172 		MD5Final(md5_digested_key, &md5_ctx);
173 		S1 = md5_digested_key;
174 		L_S1 = MD5_HASH_SIZE;
175 
176 		SHA1Init(&sha1_ctx);
177 		SHA1Update(&sha1_ctx, S2, L_S);
178 		SHA1Final(sha1_digested_key, &sha1_ctx);
179 		S2 = sha1_digested_key;
180 		L_S2 = SHA1_HASH_SIZE;
181 	}
182 
183 	/*
184 	 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
185 	 *				P_SHA-1(S2, label + seed);
186 	 * the 'seed' here is rand1 + rand2
187 	 */
188 do_P_HASH:
189 	/* The first one writes directly to the result */
190 	P_MD5(S1, L_S1, label, labellen, rand1, rand1len, rand2, rand2len,
191 	    result, resultlen, B_FALSE);
192 
193 	/* The second one XOR's with the result. */
194 	P_SHA1(S2, L_S2, label, labellen, rand1, rand1len, rand2, rand2len,
195 	    result, resultlen, B_TRUE);
196 }
197 
198 /*
199  * These two expansion routines are very similar. (they can merge one day).
200  * They implement the P_HASH() function for MD5 and for SHA1, as defined in
201  * RFC2246:
202  *
203  *	P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
204  *				HMAC_hash(secret, A(2) + seed) +
205  *				HMAC_hash(secret, A(3) + seed) + ...
206  * Where + indicates concatenation.
207  * A() is defined as:
208  *	A(0) = seed
209  *	A(i) = HMAC_hash(secret, A(i-1))
210  *
211  * The seed is the concatenation of 'babel', 'rand1', and 'rand2'.
212  */
213 static void
P_MD5(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen,boolean_t xor_it)214 P_MD5(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
215     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
216     uchar_t *result, uint_t resultlen, boolean_t xor_it)
217 {
218 	uint32_t md5_ipad[MD5_HMAC_INTS_PER_BLOCK];
219 	uint32_t md5_opad[MD5_HMAC_INTS_PER_BLOCK];
220 	uchar_t	md5_hmac[MD5_HASH_SIZE];
221 	uchar_t	A[MD5_HASH_SIZE];
222 	md5_hc_ctx_t md5_hmac_ctx;
223 	uchar_t *res, *cur;
224 	uint_t left = resultlen;
225 	int i;
226 
227 	/* good compilers will leverage the aligment */
228 	bzero(md5_ipad, MD5_HMAC_BLOCK_SIZE);
229 	bzero(md5_opad, MD5_HMAC_BLOCK_SIZE);
230 
231 	if (secretlen > 0) {
232 		bcopy(secret, md5_ipad, secretlen);
233 		bcopy(secret, md5_opad, secretlen);
234 	}
235 
236 	/* A(1) = HMAC_MD5(secret, rand1 + rand2) */
237 	md5_hmac_ctx_init(&md5_hmac_ctx, md5_ipad, md5_opad);
238 	SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, label, labellen);
239 	SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand1, rand1len);
240 	SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand2, rand2len);
241 	SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, A);
242 
243 	if (xor_it) {
244 		res = md5_hmac;
245 		cur = result;
246 	} else {
247 		res = result;
248 	}
249 
250 	while (left > 0) {
251 		/*
252 		 * Compute HMAC_MD5(secret, A(i) + seed);
253 		 * The secret is already expanded in the ictx and octx, so
254 		 * we can call the SOFT_MAC_INIT_CTX() directly.
255 		 */
256 		SOFT_MAC_INIT_CTX(MD5, &md5_hmac_ctx, md5_ipad, md5_opad,
257 		    MD5_HMAC_BLOCK_SIZE);
258 		SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, A, MD5_HASH_SIZE);
259 		SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, label, labellen);
260 		SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand1, rand1len);
261 		SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, rand2, rand2len);
262 
263 		if (left > MD5_HASH_SIZE) {
264 			SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, res);
265 			if (xor_it) {
266 				for (i = 0; i < MD5_HASH_SIZE; i++) {
267 					*cur ^= res[i];
268 					cur++;
269 				}
270 			} else {
271 				res += MD5_HASH_SIZE;
272 			}
273 			left -= MD5_HASH_SIZE;
274 		} else {
275 			SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, md5_hmac);
276 			if (xor_it) {
277 				for (i = 0; i < left; i++) {
278 					*cur ^= md5_hmac[i];
279 					cur++;
280 				}
281 			} else {
282 				bcopy(md5_hmac, res, left);
283 			}
284 			break;
285 		}
286 		/* A(i) = HMAC_MD5(secret, A(i-1) */
287 		SOFT_MAC_INIT_CTX(MD5, &md5_hmac_ctx, md5_ipad, md5_opad,
288 		    MD5_HMAC_BLOCK_SIZE);
289 		SOFT_MAC_UPDATE(MD5, &md5_hmac_ctx, A, MD5_HASH_SIZE);
290 		SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, A);
291 	}
292 }
293 static void
P_SHA1(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen,boolean_t xor_it)294 P_SHA1(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
295     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
296     uchar_t *result, uint_t resultlen, boolean_t xor_it)
297 {
298 	uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK];
299 	uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK];
300 	uchar_t	sha1_hmac[SHA1_HASH_SIZE];
301 	uchar_t	A[SHA1_HASH_SIZE];
302 	sha1_hc_ctx_t sha1_hmac_ctx;
303 	uchar_t *res, *cur;
304 	uint_t left = resultlen;
305 	int i;
306 
307 	/* good compilers will leverage the aligment */
308 	bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
309 	bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
310 
311 	if (secretlen > 0) {
312 		bcopy(secret, sha1_ipad, secretlen);
313 		bcopy(secret, sha1_opad, secretlen);
314 	}
315 
316 	/* A(1) = HMAC_SHA1(secret, rand1 + rand2) */
317 	sha1_hmac_ctx_init(&sha1_hmac_ctx, sha1_ipad, sha1_opad);
318 	SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, label, labellen);
319 	SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand1, rand1len);
320 	SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand2, rand2len);
321 	SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, A);
322 
323 	if (xor_it) {
324 		res = sha1_hmac;
325 		cur = result;
326 	} else {
327 		res = result;
328 	}
329 
330 	while (left > 0) {
331 		/*
332 		 * Compute HMAC_SHA1(secret, A(i) + seed);
333 		 * The secret is already expanded in the ictx and octx, so
334 		 * we can call the SOFT_MAC_INIT_CTX() directly.
335 		 */
336 		SOFT_MAC_INIT_CTX(SHA1, &sha1_hmac_ctx,
337 		    (const uchar_t *)sha1_ipad, (const uchar_t *)sha1_opad,
338 		    SHA1_HMAC_BLOCK_SIZE);
339 		SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, A, SHA1_HASH_SIZE);
340 		SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, label, labellen);
341 		SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand1, rand1len);
342 		SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, rand2, rand2len);
343 
344 		if (left > SHA1_HASH_SIZE) {
345 			SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, res);
346 			if (xor_it) {
347 				for (i = 0; i < SHA1_HASH_SIZE; i++) {
348 					*cur ^= res[i];
349 					cur++;
350 				}
351 			} else {
352 				res += SHA1_HASH_SIZE;
353 			}
354 			left -= SHA1_HASH_SIZE;
355 		} else {
356 			SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, sha1_hmac);
357 			if (xor_it) {
358 				for (i = 0; i < left; i++) {
359 					*cur ^= sha1_hmac[i];
360 					cur++;
361 				}
362 			} else {
363 				bcopy(sha1_hmac, res, left);
364 			}
365 			break;
366 		}
367 		/* A(i) = HMAC_SHA1(secret, A(i-1) */
368 		SOFT_MAC_INIT_CTX(SHA1, &sha1_hmac_ctx,
369 		    (const uchar_t *)sha1_ipad, (const uchar_t *)sha1_opad,
370 		    SHA1_HMAC_BLOCK_SIZE);
371 		SOFT_MAC_UPDATE(SHA1, &sha1_hmac_ctx, A, SHA1_HASH_SIZE);
372 		SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, A);
373 	}
374 }
375 
376 /* This function handles the call from C_DeriveKey for CKM_TLS_PRF */
377 CK_RV
derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param,soft_object_t * basekey_p)378 derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param, soft_object_t *basekey_p)
379 {
380 
381 	if (param->pOutput == NULL || param->pulOutputLen == 0)
382 		return (CKR_BUFFER_TOO_SMALL);
383 
384 	(void) soft_tls_prf(OBJ_SEC_VALUE(basekey_p),
385 	    OBJ_SEC_VALUE_LEN(basekey_p), param->pLabel, param->ulLabelLen,
386 	    param->pSeed, param->ulSeedLen, NULL, 0, param->pOutput,
387 	    *param->pulOutputLen);
388 
389 	return (CKR_OK);
390 }
391 
392 
393 /*
394  * soft_ssl_master_key_derive()
395  *
396  * Arguments:
397  * . session_p
398  * . mech_p:	key derivation mechanism. the mechanism parameter carries the
399  *		client and master random from the Hello handshake messages.
400  * . basekey_p: The pre-master secret key.
401  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
402  *		created.
403  * . phKey:	store for handle to the derived key.
404  *
405  * Description:
406  *	Derive the SSL master secret from the pre-master secret, the client
407  *	and server random.
408  *	In SSL 3.0, master_secret =
409  *	    MD5(pre_master_secret + SHA('A' + pre_master_secret +
410  *	        ClientHello.random + ServerHello.random)) +
411  *	    MD5(pre_master_secret + SHA('BB' + pre_master_secret +
412  *	        ClientHello.random + ServerHello.random)) +
413  *	    MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
414  *	        ClientHello.random + ServerHello.random));
415  *
416  *	In TLS 1.0 (a.k.a. SSL 3.1), master_secret =
417  *	    PRF(pre_master_secret, "master secret",
418  *		ClientHello.random + ServerHello.random)
419  */
420 CK_RV
soft_ssl_master_key_derive(soft_session_t * sp,CK_MECHANISM_PTR mech,soft_object_t * basekey_p,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)421 soft_ssl_master_key_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
422     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
423     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
424 {
425 	uchar_t	*pmsecret = OBJ_SEC_VALUE(basekey_p);
426 #ifdef	__sparcv9
427 	/* LINTED */
428 	uint_t pmlen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
429 #else	/* __sparcv9 */
430 	uint_t pmlen = OBJ_SEC_VALUE_LEN(basekey_p);
431 #endif	/* __sparcv9 */
432 	CK_SSL3_MASTER_KEY_DERIVE_PARAMS *mkd_params;
433 	CK_SSL3_RANDOM_DATA *random_data;
434 	CK_VERSION_PTR	pVersion;
435 	uchar_t	ssl_master_secret[48];
436 	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
437 	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
438 	CK_BBOOL true = TRUE;
439 	CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
440 	CK_ATTRIBUTE_PTR new_tmpl;
441 	CK_ULONG newattrcount;
442 	boolean_t new_tmpl_allocated = B_FALSE, is_tls = B_FALSE;
443 	ulong_t i;
444 	CK_RV rv = CKR_OK;
445 	uint_t ClientRandomLen, ServerRandomLen;
446 
447 	/* Check the validity of the mechanism's parameter */
448 
449 	mkd_params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter;
450 
451 	if (mkd_params == NULL ||
452 	    mech->ulParameterLen != sizeof (CK_SSL3_MASTER_KEY_DERIVE_PARAMS))
453 		return (CKR_MECHANISM_PARAM_INVALID);
454 
455 	pVersion = mkd_params->pVersion;
456 
457 	switch (mech->mechanism) {
458 	case CKM_TLS_MASTER_KEY_DERIVE:
459 		is_tls = B_TRUE;
460 	/* FALLTHRU */
461 	case CKM_SSL3_MASTER_KEY_DERIVE:
462 		/* Invalid pre-master key length. What else to return? */
463 		if (pmlen != 48)
464 			return (CKR_ARGUMENTS_BAD);
465 
466 		/* Get the SSL version number from the premaster secret */
467 		if (pVersion == NULL_PTR)
468 			return (CKR_MECHANISM_PARAM_INVALID);
469 
470 		bcopy(pmsecret, pVersion, sizeof (CK_VERSION));
471 
472 		break;
473 	case CKM_TLS_MASTER_KEY_DERIVE_DH:
474 		is_tls = B_TRUE;
475 	/* FALLTHRU */
476 	case CKM_SSL3_MASTER_KEY_DERIVE_DH:
477 		if (pVersion != NULL_PTR)
478 			return (CKR_MECHANISM_PARAM_INVALID);
479 	}
480 
481 	random_data = &mkd_params->RandomInfo;
482 #ifdef	__sparcv9
483 	/* LINTED */
484 	ClientRandomLen = (uint_t)random_data->ulClientRandomLen;
485 	/* LINTED */
486 	ServerRandomLen = (uint_t)random_data->ulServerRandomLen;
487 #else	/* __sparcv9 */
488 	ClientRandomLen = random_data->ulClientRandomLen;
489 	ServerRandomLen = random_data->ulServerRandomLen;
490 #endif	/* __sparcv9 */
491 
492 	if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
493 	    random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
494 		return (CKR_MECHANISM_PARAM_INVALID);
495 	}
496 
497 	/* Now the actual secret derivation */
498 	if (!is_tls) {
499 		soft_ssl3_churn(pmsecret, pmlen, random_data->pClientRandom,
500 		    ClientRandomLen, random_data->pServerRandom,
501 		    ServerRandomLen, 3, ssl_master_secret);
502 	} else {
503 		soft_tls_prf(pmsecret, pmlen, TLS_MASTER_SECRET_LABEL,
504 		    TLS_MASTER_SECRET_LABEL_LEN, random_data->pClientRandom,
505 		    ClientRandomLen, random_data->pServerRandom,
506 		    ServerRandomLen, ssl_master_secret, 48);
507 	}
508 
509 	/*
510 	 * The object creation attributes need to be in one contiguous
511 	 * array. In addition to the attrs from the application supplied
512 	 * pTemplates, We need to add the class, type, value, valuelen and
513 	 * CKA_DERIVE.
514 	 * In the most likely case, the application passes between zero and
515 	 * handful of attributes, We optimize for that case by allocating
516 	 * the new template on the stack. Oherwise we malloc() it.
517 	 */
518 
519 	newattrcount = ulAttributeCount + 4;
520 	if (newattrcount > MAX_DEFAULT_ATTRS) {
521 		new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
522 
523 		if (new_tmpl == NULL)
524 			return (CKR_HOST_MEMORY);
525 
526 		new_tmpl_allocated = B_TRUE;
527 	} else
528 		new_tmpl = obj_tmpl;
529 
530 	/*
531 	 * Fill in the new template.
532 	 * We put the attributes contributed by the mechanism first
533 	 * so that they override the application supplied ones.
534 	 */
535 	new_tmpl[0].type = CKA_CLASS;
536 	new_tmpl[0].pValue = &class;
537 	new_tmpl[0].ulValueLen = sizeof (class);
538 	new_tmpl[1].type = CKA_KEY_TYPE;
539 	new_tmpl[1].pValue = &keyType;
540 	new_tmpl[1].ulValueLen = sizeof (keyType);
541 	new_tmpl[2].type = CKA_DERIVE;
542 	new_tmpl[2].pValue = &true;
543 	new_tmpl[2].ulValueLen = sizeof (true);
544 	new_tmpl[3].type = CKA_VALUE;
545 	new_tmpl[3].pValue = ssl_master_secret;
546 	new_tmpl[3].ulValueLen = 48;
547 
548 	/* Any attributes left? */
549 	if (ulAttributeCount > 0) {
550 
551 		/* Validate the default class and type attributes */
552 		for (i = 0; i < ulAttributeCount; i++) {
553 			/* The caller is responsible for proper alignment */
554 			if ((pTemplate[i].type == CKA_CLASS) &&
555 			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) !=
556 			    CKO_SECRET_KEY)) {
557 				rv = CKR_TEMPLATE_INCONSISTENT;
558 				goto out;
559 			}
560 			if ((pTemplate[i].type == CKA_KEY_TYPE) &&
561 			    (*((CK_KEY_TYPE *)pTemplate[i].pValue) !=
562 			    CKK_GENERIC_SECRET)) {
563 				rv = CKR_TEMPLATE_INCONSISTENT;
564 				goto out;
565 			}
566 		}
567 		bcopy(pTemplate, &new_tmpl[4],
568 		    ulAttributeCount * sizeof (CK_ATTRIBUTE));
569 	}
570 
571 	rv = soft_add_derived_key(new_tmpl, newattrcount, phKey, sp, basekey_p);
572 out:
573 	if (new_tmpl_allocated)
574 		free(new_tmpl);
575 
576 	return (rv);
577 }
578 
579 /*
580  * soft_ssl3_key_and_mac_derive()
581  *
582  * Arguments:
583  * . session_p
584  * . mech_p:	key derivation mechanism. the mechanism parameter carries the
585  *		client and mastter random from the Hello handshake messages,
586  *		the specification of the key and IV sizes, and the location
587  * 		for the resulting keys and IVs.
588  * . basekey_p: The master secret key.
589  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
590  *		created.
591  *
592  * Description:
593  *	Derive the SSL key material (Client and server MAC secrets, symmetric
594  *	keys and IVs), from the master secret and the client
595  *	and server random.
596  *	First a keyblock is generated usining the following formula:
597  *	key_block =
598  *      	MD5(master_secret + SHA(`A' + master_secret +
599  *					ServerHello.random +
600  *					ClientHello.random)) +
601  *      	MD5(master_secret + SHA(`BB' + master_secret +
602  *					ServerHello.random +
603  *					ClientHello.random)) +
604  *      	MD5(master_secret + SHA(`CCC' + master_secret +
605  *					ServerHello.random +
606  *					ClientHello.random)) + [...];
607  *
608  *	In TLS 1.0 (a.k.a. SSL 3.1), key_block =
609  *	    PRF(master_secret, "key expansion",
610  *		ServerHello.random + ClientHello.random)
611  *
612  *	Then the keys materials are taken from the keyblock.
613  */
614 
615 CK_RV
soft_ssl_key_and_mac_derive(soft_session_t * sp,CK_MECHANISM_PTR mech,soft_object_t * basekey_p,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount)616 soft_ssl_key_and_mac_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
617     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
618     CK_ULONG ulAttributeCount)
619 {
620 	uchar_t	*msecret = OBJ_SEC_VALUE(basekey_p);
621 #ifdef	__sparcv9
622 	/* LINTED */
623 	uint_t mslen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
624 #else	/* __sparcv9 */
625 	uint_t mslen = OBJ_SEC_VALUE_LEN(basekey_p);
626 #endif	/* __sparcv9 */
627 	CK_SSL3_KEY_MAT_PARAMS *km_params;
628 	CK_SSL3_RANDOM_DATA *random_data;
629 	CK_SSL3_KEY_MAT_OUT *kmo;
630 	uchar_t key_block[MAX_KEYBLOCK], *kb, *export_keys = NULL;
631 	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
632 	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
633 	CK_BBOOL true = TRUE;
634 	CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
635 	CK_ATTRIBUTE_PTR new_tmpl;
636 	ulong_t newattrcount, mac_key_bytes, secret_key_bytes, iv_bytes;
637 	ulong_t extra_attr_count;
638 	uint_t size;
639 	int rounds, n = 0;
640 	boolean_t new_tmpl_allocated = B_FALSE, isExport;
641 	CK_RV rv = CKR_OK;
642 	uint_t ClientRandomLen, ServerRandomLen;
643 
644 	/* Check the validity of the mechanism's parameter */
645 
646 	km_params = (CK_SSL3_KEY_MAT_PARAMS *)mech->pParameter;
647 
648 	if (km_params == NULL ||
649 	    mech->ulParameterLen != sizeof (CK_SSL3_KEY_MAT_PARAMS) ||
650 	    (kmo = km_params->pReturnedKeyMaterial) == NULL)
651 		return (CKR_MECHANISM_PARAM_INVALID);
652 
653 	isExport = (km_params->bIsExport == TRUE);
654 
655 	random_data = &km_params->RandomInfo;
656 #ifdef	__sparcv9
657 	/* LINTED */
658 	ClientRandomLen = (uint_t)random_data->ulClientRandomLen;
659 	/* LINTED */
660 	ServerRandomLen = (uint_t)random_data->ulServerRandomLen;
661 #else	/* __sparcv9 */
662 	ClientRandomLen = random_data->ulClientRandomLen;
663 	ServerRandomLen = random_data->ulServerRandomLen;
664 #endif	/* __sparcv9 */
665 
666 	if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
667 	    random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
668 		return (CKR_MECHANISM_PARAM_INVALID);
669 	}
670 
671 	mac_key_bytes = km_params->ulMacSizeInBits / 8;
672 	secret_key_bytes = km_params->ulKeySizeInBits / 8;
673 	iv_bytes = km_params->ulIVSizeInBits / 8;
674 
675 	if ((iv_bytes > 0) &&
676 	    ((kmo->pIVClient == NULL) || (kmo->pIVServer == NULL)))
677 		return (CKR_MECHANISM_PARAM_INVALID);
678 
679 	/*
680 	 * For exportable ciphersuites, the IV's aren't taken from the
681 	 * key block. They are directly derived from the client and
682 	 * server random data.
683 	 * For SSL3.0:
684 	 *	client_write_IV = MD5(ClientHello.random + ServerHello.random);
685 	 *	server_write_IV = MD5(ServerHello.random + ClientHello.random);
686 	 * For TLS1.0:
687 	 *	iv_block = PRF("", "IV block", client_random +
688 	 *			server_random)[0..15]
689 	 *	client_write_IV = iv_block[0..7]
690 	 *	server_write_IV = iv_block[8..15]
691 	 */
692 	if ((isExport) && (iv_bytes > 0)) {
693 
694 		if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
695 			MD5_CTX	exp_md5_ctx;
696 
697 			if (iv_bytes > MD5_HASH_SIZE)
698 				return (CKR_MECHANISM_PARAM_INVALID);
699 
700 			MD5Init(&exp_md5_ctx);
701 			MD5Update(&exp_md5_ctx, random_data->pClientRandom,
702 			    ClientRandomLen);
703 			MD5Update(&exp_md5_ctx, random_data->pServerRandom,
704 			    ServerRandomLen);
705 
706 			/* there's room in key_block. use it */
707 			MD5Final(key_block, &exp_md5_ctx);
708 			bcopy(key_block, kmo->pIVClient, iv_bytes);
709 
710 			MD5Init(&exp_md5_ctx);
711 			MD5Update(&exp_md5_ctx, random_data->pServerRandom,
712 			    ServerRandomLen);
713 			MD5Update(&exp_md5_ctx, random_data->pClientRandom,
714 			    ClientRandomLen);
715 			MD5Final(key_block, &exp_md5_ctx);
716 			bcopy(key_block, kmo->pIVServer, iv_bytes);
717 		} else {
718 			uchar_t	iv_block[16];
719 
720 			if (iv_bytes != 8)
721 				return (CKR_MECHANISM_PARAM_INVALID);
722 
723 			soft_tls_prf(NULL, 0, TLS_IV_BLOCK_LABEL,
724 			    TLS_IV_BLOCK_LABEL_LEN,
725 			    random_data->pClientRandom, ClientRandomLen,
726 			    random_data->pServerRandom, ServerRandomLen,
727 			    iv_block, 16);
728 			bcopy(iv_block, kmo->pIVClient, 8);
729 			bcopy(iv_block + 8, kmo->pIVServer, 8);
730 		}
731 		/* so we won't allocate a key_block bigger than needed */
732 		iv_bytes = 0;
733 	}
734 
735 	/* Now the actual secret derivation */
736 
737 #ifdef	__sparcv9
738 	/* LINTED */
739 	size = (uint_t)((mac_key_bytes + secret_key_bytes + iv_bytes) * 2);
740 #else	/* __sparcv9 */
741 	size = (mac_key_bytes + secret_key_bytes + iv_bytes) * 2;
742 #endif	/* __sparcv9 */
743 
744 	/* Need to handle this better */
745 	if (size > MAX_KEYBLOCK)
746 		return (CKR_MECHANISM_PARAM_INVALID);
747 
748 	rounds = howmany(size, MD5_HASH_SIZE);
749 
750 	kb = key_block;
751 
752 	if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
753 		soft_ssl3_churn(msecret, mslen, random_data->pServerRandom,
754 		    ServerRandomLen, random_data->pClientRandom,
755 		    ClientRandomLen, rounds, kb);
756 	} else {
757 		soft_tls_prf(msecret, mslen, TLS_KEY_EXPANSION_LABEL,
758 		    TLS_KEY_EXPANSION_LABEL_LEN,
759 		    random_data->pServerRandom, ServerRandomLen,
760 		    random_data->pClientRandom, ClientRandomLen,
761 		    kb, size);
762 	}
763 
764 	/* Now create the objects */
765 
766 	kmo->hClientMacSecret = CK_INVALID_HANDLE;
767 	kmo->hServerMacSecret = CK_INVALID_HANDLE;
768 	kmo->hClientKey = CK_INVALID_HANDLE;
769 	kmo->hServerKey = CK_INVALID_HANDLE;
770 
771 	/* First the MAC secrets */
772 	if (mac_key_bytes > 0) {
773 		obj_tmpl[0].type = CKA_CLASS;
774 		obj_tmpl[0].pValue = &class;	/* CKO_SECRET_KEY */
775 		obj_tmpl[0].ulValueLen = sizeof (class);
776 		obj_tmpl[1].type = CKA_KEY_TYPE;
777 		obj_tmpl[1].pValue = &keyType;	/* CKK_GENERIC_SECRET */
778 		obj_tmpl[1].ulValueLen = sizeof (keyType);
779 		obj_tmpl[2].type = CKA_DERIVE;
780 		obj_tmpl[2].pValue = &true;
781 		obj_tmpl[2].ulValueLen = sizeof (true);
782 		obj_tmpl[3].type = CKA_SIGN;
783 		obj_tmpl[3].pValue = &true;
784 		obj_tmpl[3].ulValueLen = sizeof (true);
785 		obj_tmpl[4].type = CKA_VERIFY;
786 		obj_tmpl[4].pValue = &true;
787 		obj_tmpl[4].ulValueLen = sizeof (true);
788 		obj_tmpl[5].type = CKA_VALUE;
789 		obj_tmpl[5].pValue = kb;
790 		obj_tmpl[5].ulValueLen = mac_key_bytes;
791 
792 		rv = soft_add_derived_key(obj_tmpl, 6,
793 		    &(kmo->hClientMacSecret), sp, basekey_p);
794 
795 		if (rv != CKR_OK)
796 			goto out_err;
797 
798 		kb += mac_key_bytes;
799 
800 		obj_tmpl[5].pValue = kb;
801 		rv = soft_add_derived_key(obj_tmpl, 6,
802 		    &(kmo->hServerMacSecret), sp, basekey_p);
803 
804 		if (rv != CKR_OK)
805 			goto out_err;
806 
807 		kb += mac_key_bytes;
808 	}
809 
810 	/* Then the symmetric ciphers keys */
811 
812 	extra_attr_count = (secret_key_bytes == 0) ? 6 : 5;
813 	newattrcount = ulAttributeCount + extra_attr_count;
814 	if (newattrcount > MAX_DEFAULT_ATTRS) {
815 		new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
816 
817 		if (new_tmpl == NULL)
818 			return (CKR_HOST_MEMORY);
819 
820 		new_tmpl_allocated = B_TRUE;
821 	} else
822 		new_tmpl = obj_tmpl;
823 
824 	new_tmpl[n].type = CKA_CLASS;
825 	new_tmpl[n].pValue = &class;	/* CKO_SECRET_KEY */
826 	new_tmpl[n].ulValueLen = sizeof (class);
827 	++n;
828 	/*
829 	 * The keyType comes from the application's template, and depends
830 	 * on the ciphersuite. The only exception is authentication only
831 	 * ciphersuites which do not use cipher keys.
832 	 */
833 	if (secret_key_bytes == 0) {
834 		new_tmpl[n].type = CKA_KEY_TYPE;
835 		new_tmpl[n].pValue = &keyType;	/* CKK_GENERIC_SECRET */
836 		new_tmpl[n].ulValueLen = sizeof (keyType);
837 		n++;
838 	}
839 	new_tmpl[n].type = CKA_DERIVE;
840 	new_tmpl[n].pValue = &true;
841 	new_tmpl[n].ulValueLen = sizeof (true);
842 	n++;
843 	new_tmpl[n].type = CKA_ENCRYPT;
844 	new_tmpl[n].pValue = &true;
845 	new_tmpl[n].ulValueLen = sizeof (true);
846 	n++;
847 	new_tmpl[n].type = CKA_DECRYPT;
848 	new_tmpl[n].pValue = &true;
849 	new_tmpl[n].ulValueLen = sizeof (true);
850 	n++;
851 	new_tmpl[n].type = CKA_VALUE;
852 	new_tmpl[n].pValue = NULL;
853 	new_tmpl[n].ulValueLen = 0;
854 
855 	if (secret_key_bytes > 0) {
856 		if (isExport) {
857 			if (secret_key_bytes > MD5_HASH_SIZE) {
858 				rv = CKR_MECHANISM_PARAM_INVALID;
859 				goto out_err;
860 			}
861 			if ((export_keys = malloc(2 * MD5_HASH_SIZE)) == NULL) {
862 				rv = CKR_HOST_MEMORY;
863 				goto out_err;
864 			}
865 #ifdef	__sparcv9
866 			/* LINTED */
867 			soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
868 #else	/* __sparcv9 */
869 			soft_ssl_weaken_key(mech, kb, secret_key_bytes,
870 #endif	/* __sparcv9 */
871 			    random_data->pClientRandom, ClientRandomLen,
872 			    random_data->pServerRandom, ServerRandomLen,
873 			    export_keys, B_TRUE);
874 			new_tmpl[n].pValue = export_keys;
875 			new_tmpl[n].ulValueLen = MD5_HASH_SIZE;
876 		} else {
877 			new_tmpl[n].pValue = kb;
878 			new_tmpl[n].ulValueLen = secret_key_bytes;
879 		}
880 	}
881 
882 	if (ulAttributeCount > 0)
883 		bcopy(pTemplate, &new_tmpl[extra_attr_count],
884 		    ulAttributeCount * sizeof (CK_ATTRIBUTE));
885 
886 	rv = soft_add_derived_key(new_tmpl, newattrcount,
887 	    &(kmo->hClientKey), sp, basekey_p);
888 
889 	if (rv != CKR_OK)
890 		goto out_err;
891 
892 	kb += secret_key_bytes;
893 
894 	if (secret_key_bytes > 0) {
895 		if (isExport) {
896 #ifdef	__sparcv9
897 			/* LINTED */
898 			soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
899 #else	/* __sparcv9 */
900 			soft_ssl_weaken_key(mech, kb, secret_key_bytes,
901 #endif	/* __sparcv9 */
902 			    random_data->pServerRandom, ServerRandomLen,
903 			    random_data->pClientRandom, ClientRandomLen,
904 			    export_keys + MD5_HASH_SIZE, B_FALSE);
905 			new_tmpl[n].pValue = export_keys + MD5_HASH_SIZE;
906 		} else
907 			new_tmpl[n].pValue = kb;
908 	}
909 
910 	rv = soft_add_derived_key(new_tmpl, newattrcount,
911 	    &(kmo->hServerKey), sp, basekey_p);
912 
913 	if (rv != CKR_OK)
914 		goto out_err;
915 
916 	kb += secret_key_bytes;
917 
918 	/* Finally, the IVs */
919 	if (iv_bytes > 0) {
920 		bcopy(kb, kmo->pIVClient, iv_bytes);
921 		kb += iv_bytes;
922 		bcopy(kb, kmo->pIVServer, iv_bytes);
923 	}
924 
925 	if (new_tmpl_allocated)
926 		free(new_tmpl);
927 
928 	if (export_keys != NULL)
929 		free(export_keys);
930 
931 	return (rv);
932 
933 out_err:
934 	if (kmo->hClientMacSecret != CK_INVALID_HANDLE) {
935 		(void) soft_delete_derived_key(sp,
936 		    (soft_object_t *)(kmo->hClientMacSecret));
937 		kmo->hClientMacSecret = CK_INVALID_HANDLE;
938 	}
939 	if (kmo->hServerMacSecret != CK_INVALID_HANDLE) {
940 		(void) soft_delete_derived_key(sp,
941 		    (soft_object_t *)(kmo->hServerMacSecret));
942 		kmo->hServerMacSecret = CK_INVALID_HANDLE;
943 	}
944 	if (kmo->hClientKey != CK_INVALID_HANDLE) {
945 		(void) soft_delete_derived_key(sp,
946 		    (soft_object_t *)(kmo->hClientKey));
947 		kmo->hClientKey = CK_INVALID_HANDLE;
948 	}
949 	if (kmo->hServerKey != CK_INVALID_HANDLE) {
950 		(void) soft_delete_derived_key(sp,
951 		    (soft_object_t *)(kmo->hServerKey));
952 		kmo->hServerKey = CK_INVALID_HANDLE;
953 	}
954 
955 	if (new_tmpl_allocated)
956 		free(new_tmpl);
957 
958 	if (export_keys != NULL)
959 		free(export_keys);
960 
961 	return (rv);
962 }
963 
964 /*
965  * Add the derived key to the session, and, if it's a token object,
966  * write it to the token.
967  */
968 static CK_RV
soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl,CK_ULONG attrcount,CK_OBJECT_HANDLE_PTR phKey,soft_session_t * sp,soft_object_t * basekey_p)969 soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount,
970     CK_OBJECT_HANDLE_PTR phKey, soft_session_t *sp, soft_object_t *basekey_p)
971 {
972 	CK_RV rv;
973 	soft_object_t *secret_key;
974 
975 	if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) {
976 		return (CKR_HOST_MEMORY);
977 	}
978 
979 	if (((rv = soft_build_secret_key_object(tmpl, attrcount, secret_key,
980 	    SOFT_CREATE_OBJ_INT, 0, (CK_KEY_TYPE)~0UL)) != CKR_OK) ||
981 	    ((rv = soft_pin_expired_check(secret_key)) != CKR_OK) ||
982 	    ((rv = soft_object_write_access_check(sp, secret_key)) != CKR_OK)) {
983 
984 		free(secret_key);
985 		return (rv);
986 	}
987 
988 	/* Set the sensitivity and extractability attributes as a needed */
989 	soft_derive_enforce_flags(basekey_p, secret_key);
990 
991 	/* Initialize the rest of stuffs in soft_object_t. */
992 	(void) pthread_mutex_init(&secret_key->object_mutex, NULL);
993 	secret_key->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
994 
995 	/* ... and, if it needs to persist, write on the token */
996 	if (IS_TOKEN_OBJECT(secret_key)) {
997 		secret_key->session_handle = (CK_SESSION_HANDLE)NULL;
998 		soft_add_token_object_to_slot(secret_key);
999 		rv = soft_put_object_to_keystore(secret_key);
1000 		if (rv != CKR_OK) {
1001 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
1002 			return (rv);
1003 		}
1004 		*phKey = (CK_OBJECT_HANDLE)secret_key;
1005 
1006 		return (CKR_OK);
1007 	}
1008 
1009 	/* Add the new object to the session's object list. */
1010 	soft_add_object_to_session(secret_key, sp);
1011 	secret_key->session_handle = (CK_SESSION_HANDLE)sp;
1012 
1013 	*phKey = (CK_OBJECT_HANDLE)secret_key;
1014 
1015 	return (rv);
1016 }
1017 
1018 /*
1019  * Delete the derived key from the session, and, if it's a token object,
1020  * remove it from the token.
1021  */
1022 static void
soft_delete_derived_key(soft_session_t * sp,soft_object_t * key)1023 soft_delete_derived_key(soft_session_t *sp, soft_object_t *key)
1024 {
1025 	/* session_handle is the creating session. It's NULL for token objs */
1026 
1027 	if (IS_TOKEN_OBJECT(key))
1028 		soft_delete_token_object(key, B_FALSE, B_FALSE);
1029 	else
1030 		soft_delete_object(sp, key, B_FALSE, B_FALSE);
1031 }
1032 
1033 /*
1034  * soft_ssl_weaken_key()
1035  * Reduce the key length to an exportable size.
1036  * For SSL3.0:
1037  *	final_client_write_key = MD5(client_write_key +
1038  *                                ClientHello.random +
1039  *                                ServerHello.random);
1040  *	final_server_write_key = MD5(server_write_key +
1041  *                                ServerHello.random +
1042  *                                ClientHello.random);
1043  * For TLS1.0:
1044  *	final_client_write_key = PRF(SecurityParameters.client_write_key,
1045  *				    "client write key",
1046  *				    SecurityParameters.client_random +
1047  *				    SecurityParameters.server_random)[0..15];
1048  *	final_server_write_key = PRF(SecurityParameters.server_write_key,
1049  *				    "server write key",
1050  *				    SecurityParameters.client_random +
1051  *				    SecurityParameters.server_random)[0..15];
1052  */
1053 static void
soft_ssl_weaken_key(CK_MECHANISM_PTR mech,uchar_t * secret,uint_t secretlen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,boolean_t isclient)1054 soft_ssl_weaken_key(CK_MECHANISM_PTR mech, uchar_t *secret, uint_t secretlen,
1055     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
1056     uchar_t *result, boolean_t isclient)
1057 {
1058 	MD5_CTX exp_md5_ctx;
1059 	uchar_t *label;
1060 	uint_t labellen;
1061 
1062 	if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
1063 		MD5Init(&exp_md5_ctx);
1064 		MD5Update(&exp_md5_ctx, secret, secretlen);
1065 		MD5Update(&exp_md5_ctx, rand1, rand1len);
1066 		MD5Update(&exp_md5_ctx, rand2, rand2len);
1067 		MD5Final(result, &exp_md5_ctx);
1068 	} else {
1069 		if (isclient) {
1070 			label = TLS_CLIENT_KEY_LABEL;
1071 			labellen = TLS_CLIENT_KEY_LABEL_LEN;
1072 			soft_tls_prf(secret, secretlen, label, labellen,
1073 			    rand1, rand1len, rand2, rand2len, result, 16);
1074 		} else {
1075 			label = TLS_SERVER_KEY_LABEL;
1076 			labellen = TLS_SERVER_KEY_LABEL_LEN;
1077 			soft_tls_prf(secret, secretlen, label, labellen,
1078 			    rand2, rand2len, rand1, rand1len, result, 16);
1079 		}
1080 	}
1081 }
1082