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