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