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