xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c (revision 60405de4d8688d96dd05157c28db3ade5c9bc234)
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 /* This function handles the call from C_DeriveKey for CKM_TLS_PRF */
380 CK_RV
381 derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param, soft_object_t *basekey_p)
382 {
383 
384 	if (param->pOutput == NULL || param->pulOutputLen == 0)
385 		return (CKR_BUFFER_TOO_SMALL);
386 
387 	(void) soft_tls_prf(OBJ_SEC_VALUE(basekey_p),
388 	    OBJ_SEC_VALUE_LEN(basekey_p), param->pLabel, param->ulLabelLen,
389 	    param->pSeed, param->ulSeedLen, NULL, 0, param->pOutput,
390 	    *param->pulOutputLen);
391 
392 	return (CKR_OK);
393 }
394 
395 
396 /*
397  * soft_ssl_master_key_derive()
398  *
399  * Arguments:
400  * . session_p
401  * . mech_p:	key derivation mechanism. the mechanism parameter carries the
402  *		client and master random from the Hello handshake messages.
403  * . basekey_p: The pre-master secret key.
404  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
405  *		created.
406  * . phKey:	store for handle to the derived key.
407  *
408  * Description:
409  *	Derive the SSL master secret from the pre-master secret, the client
410  *	and server random.
411  *	In SSL 3.0, master_secret =
412  *	    MD5(pre_master_secret + SHA('A' + pre_master_secret +
413  *	        ClientHello.random + ServerHello.random)) +
414  *	    MD5(pre_master_secret + SHA('BB' + pre_master_secret +
415  *	        ClientHello.random + ServerHello.random)) +
416  *	    MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
417  *	        ClientHello.random + ServerHello.random));
418  *
419  *	In TLS 1.0 (a.k.a. SSL 3.1), master_secret =
420  *	    PRF(pre_master_secret, "master secret",
421  *		ClientHello.random + ServerHello.random)
422  */
423 CK_RV
424 soft_ssl_master_key_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
425     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
426     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
427 {
428 	uchar_t	*pmsecret = OBJ_SEC_VALUE(basekey_p);
429 #ifdef	__sparcv9
430 	/* LINTED */
431 	uint_t pmlen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
432 #else	/* __sparcv9 */
433 	uint_t pmlen = OBJ_SEC_VALUE_LEN(basekey_p);
434 #endif	/* __sparcv9 */
435 	CK_SSL3_MASTER_KEY_DERIVE_PARAMS *mkd_params;
436 	CK_SSL3_RANDOM_DATA *random_data;
437 	CK_VERSION_PTR	pVersion;
438 	uchar_t	ssl_master_secret[48];
439 	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
440 	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
441 	CK_BBOOL true = TRUE;
442 	CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
443 	CK_ATTRIBUTE_PTR new_tmpl;
444 	CK_ULONG newattrcount;
445 	boolean_t new_tmpl_allocated = B_FALSE, is_tls = B_FALSE;
446 	ulong_t i;
447 	CK_RV rv = CKR_OK;
448 	uint_t ClientRandomLen, ServerRandomLen;
449 
450 	/* Check the validity of the mechanism's parameter */
451 
452 	mkd_params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter;
453 
454 	if (mkd_params == NULL ||
455 	    mech->ulParameterLen != sizeof (CK_SSL3_MASTER_KEY_DERIVE_PARAMS))
456 		return (CKR_MECHANISM_PARAM_INVALID);
457 
458 	pVersion = mkd_params->pVersion;
459 
460 	switch (mech->mechanism) {
461 	case CKM_TLS_MASTER_KEY_DERIVE:
462 		is_tls = B_TRUE;
463 	/* FALLTHRU */
464 	case CKM_SSL3_MASTER_KEY_DERIVE:
465 		/* Invalid pre-master key length. What else to return? */
466 		if (pmlen != 48)
467 			return (CKR_ARGUMENTS_BAD);
468 
469 		/* Get the SSL version number from the premaster secret */
470 		if (pVersion == NULL_PTR)
471 			return (CKR_MECHANISM_PARAM_INVALID);
472 
473 		bcopy(pmsecret, pVersion, sizeof (CK_VERSION));
474 
475 		break;
476 	case CKM_TLS_MASTER_KEY_DERIVE_DH:
477 		is_tls = B_TRUE;
478 	/* FALLTHRU */
479 	case CKM_SSL3_MASTER_KEY_DERIVE_DH:
480 		if (pVersion != NULL_PTR)
481 			return (CKR_MECHANISM_PARAM_INVALID);
482 	}
483 
484 	random_data = &mkd_params->RandomInfo;
485 #ifdef	__sparcv9
486 	/* LINTED */
487 	ClientRandomLen = (uint_t)random_data->ulClientRandomLen;
488 	/* LINTED */
489 	ServerRandomLen = (uint_t)random_data->ulServerRandomLen;
490 #else	/* __sparcv9 */
491 	ClientRandomLen = random_data->ulClientRandomLen;
492 	ServerRandomLen = random_data->ulServerRandomLen;
493 #endif	/* __sparcv9 */
494 
495 	if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
496 	    random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
497 		return (CKR_MECHANISM_PARAM_INVALID);
498 	}
499 
500 	/* Now the actual secret derivation */
501 	if (!is_tls) {
502 		soft_ssl3_churn(pmsecret, pmlen, random_data->pClientRandom,
503 		    ClientRandomLen, random_data->pServerRandom,
504 		    ServerRandomLen, 3, ssl_master_secret);
505 	} else {
506 		soft_tls_prf(pmsecret, pmlen, TLS_MASTER_SECRET_LABEL,
507 		    TLS_MASTER_SECRET_LABEL_LEN, random_data->pClientRandom,
508 		    ClientRandomLen, random_data->pServerRandom,
509 		    ServerRandomLen, ssl_master_secret, 48);
510 	}
511 
512 	/*
513 	 * The object creation attributes need to be in one contiguous
514 	 * array. In addition to the attrs from the application supplied
515 	 * pTemplates, We need to add the class, type, value, valuelen and
516 	 * CKA_DERIVE.
517 	 * In the most likely case, the application passes between zero and
518 	 * handful of attributes, We optimize for that case by allocating
519 	 * the new template on the stack. Oherwise we malloc() it.
520 	 */
521 
522 	newattrcount = ulAttributeCount + 4;
523 	if (newattrcount > MAX_DEFAULT_ATTRS) {
524 		new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
525 
526 		if (new_tmpl == NULL)
527 			return (CKR_HOST_MEMORY);
528 
529 		new_tmpl_allocated = B_TRUE;
530 	} else
531 		new_tmpl = obj_tmpl;
532 
533 	/*
534 	 * Fill in the new template.
535 	 * We put the attributes contributed by the mechanism first
536 	 * so that they override the application supplied ones.
537 	 */
538 	new_tmpl[0].type = CKA_CLASS;
539 	new_tmpl[0].pValue = &class;
540 	new_tmpl[0].ulValueLen = sizeof (class);
541 	new_tmpl[1].type = CKA_KEY_TYPE;
542 	new_tmpl[1].pValue = &keyType;
543 	new_tmpl[1].ulValueLen = sizeof (keyType);
544 	new_tmpl[2].type = CKA_DERIVE;
545 	new_tmpl[2].pValue = &true;
546 	new_tmpl[2].ulValueLen = sizeof (true);
547 	new_tmpl[3].type = CKA_VALUE;
548 	new_tmpl[3].pValue = ssl_master_secret;
549 	new_tmpl[3].ulValueLen = 48;
550 
551 	/* Any attributes left? */
552 	if (ulAttributeCount > 0) {
553 
554 		/* Validate the default class and type attributes */
555 		for (i = 0; i < ulAttributeCount; i++) {
556 			/* The caller is responsible for proper alignment */
557 			if ((pTemplate[i].type == CKA_CLASS) &&
558 			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) !=
559 			    CKO_SECRET_KEY)) {
560 				rv = CKR_TEMPLATE_INCONSISTENT;
561 				goto out;
562 			}
563 			if ((pTemplate[i].type == CKA_KEY_TYPE) &&
564 			    (*((CK_KEY_TYPE *)pTemplate[i].pValue) !=
565 			    CKK_GENERIC_SECRET)) {
566 				rv = CKR_TEMPLATE_INCONSISTENT;
567 				goto out;
568 			}
569 		}
570 		bcopy(pTemplate, &new_tmpl[4],
571 		    ulAttributeCount * sizeof (CK_ATTRIBUTE));
572 	}
573 
574 	rv = soft_add_derived_key(new_tmpl, newattrcount, phKey, sp, basekey_p);
575 out:
576 	if (new_tmpl_allocated)
577 		free(new_tmpl);
578 
579 	return (rv);
580 }
581 
582 /*
583  * soft_ssl3_key_and_mac_derive()
584  *
585  * Arguments:
586  * . session_p
587  * . mech_p:	key derivation mechanism. the mechanism parameter carries the
588  *		client and mastter random from the Hello handshake messages,
589  *		the specification of the key and IV sizes, and the location
590  * 		for the resulting keys and IVs.
591  * . basekey_p: The master secret key.
592  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
593  *		created.
594  *
595  * Description:
596  *	Derive the SSL key material (Client and server MAC secrets, symmetric
597  *	keys and IVs), from the master secret and the client
598  *	and server random.
599  *	First a keyblock is generated usining the following formula:
600  *	key_block =
601  *      	MD5(master_secret + SHA(`A' + master_secret +
602  *					ServerHello.random +
603  *					ClientHello.random)) +
604  *      	MD5(master_secret + SHA(`BB' + master_secret +
605  *					ServerHello.random +
606  *					ClientHello.random)) +
607  *      	MD5(master_secret + SHA(`CCC' + master_secret +
608  *					ServerHello.random +
609  *					ClientHello.random)) + [...];
610  *
611  *	In TLS 1.0 (a.k.a. SSL 3.1), key_block =
612  *	    PRF(master_secret, "key expansion",
613  *		ServerHello.random + ClientHello.random)
614  *
615  *	Then the keys materials are taken from the keyblock.
616  */
617 
618 CK_RV
619 soft_ssl_key_and_mac_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
620     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
621     CK_ULONG ulAttributeCount)
622 {
623 	uchar_t	*msecret = OBJ_SEC_VALUE(basekey_p);
624 #ifdef	__sparcv9
625 	/* LINTED */
626 	uint_t mslen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
627 #else	/* __sparcv9 */
628 	uint_t mslen = OBJ_SEC_VALUE_LEN(basekey_p);
629 #endif	/* __sparcv9 */
630 	CK_SSL3_KEY_MAT_PARAMS *km_params;
631 	CK_SSL3_RANDOM_DATA *random_data;
632 	CK_SSL3_KEY_MAT_OUT *kmo;
633 	uchar_t key_block[MAX_KEYBLOCK], *kb, *export_keys = NULL;
634 	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
635 	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
636 	CK_BBOOL true = TRUE;
637 	CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
638 	CK_ATTRIBUTE_PTR new_tmpl;
639 	ulong_t newattrcount, mac_key_bytes, secret_key_bytes, iv_bytes;
640 	uint_t size;
641 	int rounds;
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 		}
731 		/* so we won't allocate a key_block bigger than needed */
732 		iv_bytes = 0;
733 	}
734 
735 	/* Now the actual secret derivation */
736 
737 #ifdef	__sparcv9
738 	/* LINTED */
739 	size = (uint_t)((mac_key_bytes + secret_key_bytes + iv_bytes) * 2);
740 #else	/* __sparcv9 */
741 	size = (mac_key_bytes + secret_key_bytes + iv_bytes) * 2;
742 #endif	/* __sparcv9 */
743 
744 	/* Need to handle this better */
745 	if (size > MAX_KEYBLOCK)
746 		return (CKR_MECHANISM_PARAM_INVALID);
747 
748 	rounds = howmany(size, MD5_HASH_SIZE);
749 
750 	kb = key_block;
751 
752 	if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
753 		soft_ssl3_churn(msecret, mslen, random_data->pServerRandom,
754 		    ServerRandomLen, random_data->pClientRandom,
755 		    ClientRandomLen, rounds, kb);
756 	} else {
757 		soft_tls_prf(msecret, mslen, TLS_KEY_EXPANSION_LABEL,
758 		    TLS_KEY_EXPANSION_LABEL_LEN,
759 		    random_data->pServerRandom, ServerRandomLen,
760 		    random_data->pClientRandom, ClientRandomLen,
761 		    kb, size);
762 	}
763 
764 	/* Now create the objects */
765 
766 	kmo->hClientMacSecret = CK_INVALID_HANDLE;
767 	kmo->hServerMacSecret = CK_INVALID_HANDLE;
768 	kmo->hClientKey = CK_INVALID_HANDLE;
769 	kmo->hServerKey = CK_INVALID_HANDLE;
770 
771 	/* First the MAC secrets */
772 	if (mac_key_bytes > 0) {
773 		obj_tmpl[0].type = CKA_CLASS;
774 		obj_tmpl[0].pValue = &class;	/* CKO_SECRET_KEY */
775 		obj_tmpl[0].ulValueLen = sizeof (class);
776 		obj_tmpl[1].type = CKA_KEY_TYPE;
777 		obj_tmpl[1].pValue = &keyType;	/* CKK_GENERIC_SECRET */
778 		obj_tmpl[1].ulValueLen = sizeof (keyType);
779 		obj_tmpl[2].type = CKA_DERIVE;
780 		obj_tmpl[2].pValue = &true;
781 		obj_tmpl[2].ulValueLen = sizeof (true);
782 		obj_tmpl[3].type = CKA_SIGN;
783 		obj_tmpl[3].pValue = &true;
784 		obj_tmpl[3].ulValueLen = sizeof (true);
785 		obj_tmpl[4].type = CKA_VERIFY;
786 		obj_tmpl[4].pValue = &true;
787 		obj_tmpl[4].ulValueLen = sizeof (true);
788 		obj_tmpl[5].type = CKA_VALUE;
789 		obj_tmpl[5].pValue = kb;
790 		obj_tmpl[5].ulValueLen = mac_key_bytes;
791 
792 		rv = soft_add_derived_key(obj_tmpl, 6,
793 		    &(kmo->hClientMacSecret), sp, basekey_p);
794 
795 		if (rv != CKR_OK)
796 			goto out_err;
797 
798 		kb += mac_key_bytes;
799 
800 		obj_tmpl[5].pValue = kb;
801 		rv = soft_add_derived_key(obj_tmpl, 6,
802 		    &(kmo->hServerMacSecret), sp, basekey_p);
803 
804 		if (rv != CKR_OK)
805 			goto out_err;
806 
807 		kb += mac_key_bytes;
808 	}
809 
810 	/* Then the symmetric ciphers keys */
811 	if (secret_key_bytes > 0) {
812 
813 		newattrcount = ulAttributeCount + 5;
814 		if (newattrcount > MAX_DEFAULT_ATTRS) {
815 			new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
816 
817 			if (new_tmpl == NULL)
818 				return (CKR_HOST_MEMORY);
819 
820 			new_tmpl_allocated = B_TRUE;
821 		} else
822 			new_tmpl = obj_tmpl;
823 
824 		new_tmpl[0].type = CKA_CLASS;
825 		new_tmpl[0].pValue = &class;	/* CKO_SECRET_KEY */
826 		new_tmpl[0].ulValueLen = sizeof (class);
827 		/*
828 		 * The keyType comes from the application's template, and
829 		 * depends on the ciphersuite
830 		 */
831 		new_tmpl[1].type = CKA_DERIVE;
832 		new_tmpl[1].pValue = &true;
833 		new_tmpl[1].ulValueLen = sizeof (true);
834 		new_tmpl[2].type = CKA_ENCRYPT;
835 		new_tmpl[2].pValue = &true;
836 		new_tmpl[2].ulValueLen = sizeof (true);
837 		new_tmpl[3].type = CKA_DECRYPT;
838 		new_tmpl[3].pValue = &true;
839 		new_tmpl[3].ulValueLen = sizeof (true);
840 		new_tmpl[4].type = CKA_VALUE;
841 
842 		if (isExport) {
843 			if (secret_key_bytes > MD5_HASH_SIZE) {
844 				rv = CKR_MECHANISM_PARAM_INVALID;
845 				goto out_err;
846 			}
847 			if ((export_keys = malloc(2 * MD5_HASH_SIZE)) == NULL) {
848 				rv = CKR_HOST_MEMORY;
849 				goto out_err;
850 			}
851 #ifdef	__sparcv9
852 			/* LINTED */
853 			soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
854 #else	/* __sparcv9 */
855 			soft_ssl_weaken_key(mech, kb, secret_key_bytes,
856 #endif	/* __sparcv9 */
857 			    random_data->pClientRandom, ClientRandomLen,
858 			    random_data->pServerRandom, ServerRandomLen,
859 			    export_keys, B_TRUE);
860 			new_tmpl[4].pValue = export_keys;
861 			new_tmpl[4].ulValueLen = MD5_HASH_SIZE;
862 		} else {
863 			new_tmpl[4].pValue = kb;
864 			new_tmpl[4].ulValueLen = secret_key_bytes;
865 		}
866 
867 		if (ulAttributeCount > 0)
868 			bcopy(pTemplate, &new_tmpl[5],
869 			    ulAttributeCount * sizeof (CK_ATTRIBUTE));
870 
871 		rv = soft_add_derived_key(new_tmpl, newattrcount,
872 		    &(kmo->hClientKey), sp, basekey_p);
873 
874 		if (rv != CKR_OK)
875 			goto out_err;
876 
877 		kb += secret_key_bytes;
878 
879 		if (isExport) {
880 #ifdef	__sparcv9
881 			/* LINTED */
882 			soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
883 #else	/* __sparcv9 */
884 			soft_ssl_weaken_key(mech, kb, secret_key_bytes,
885 #endif	/* __sparcv9 */
886 			    random_data->pServerRandom, ServerRandomLen,
887 			    random_data->pClientRandom, ClientRandomLen,
888 			    export_keys + MD5_HASH_SIZE, B_FALSE);
889 			    new_tmpl[4].pValue = export_keys + MD5_HASH_SIZE;
890 		} else
891 			new_tmpl[4].pValue = kb;
892 
893 		rv = soft_add_derived_key(new_tmpl, newattrcount,
894 		    &(kmo->hServerKey), sp, basekey_p);
895 
896 		if (rv != CKR_OK)
897 			goto out_err;
898 
899 		kb += secret_key_bytes;
900 	}
901 
902 	/* Finally, the IVs */
903 	if (iv_bytes > 0) {
904 		bcopy(kb, kmo->pIVClient, iv_bytes);
905 		kb += iv_bytes;
906 		bcopy(kb, kmo->pIVServer, iv_bytes);
907 	}
908 
909 	if (new_tmpl_allocated)
910 		free(new_tmpl);
911 
912 	if (export_keys != NULL)
913 		free(export_keys);
914 
915 	return (rv);
916 
917 out_err:
918 	if (kmo->hClientMacSecret != CK_INVALID_HANDLE) {
919 		(void) soft_delete_derived_key(sp,
920 		    (soft_object_t *)(kmo->hClientMacSecret));
921 		kmo->hClientMacSecret = CK_INVALID_HANDLE;
922 	}
923 	if (kmo->hServerMacSecret != CK_INVALID_HANDLE) {
924 		(void) soft_delete_derived_key(sp,
925 		    (soft_object_t *)(kmo->hServerMacSecret));
926 		kmo->hServerMacSecret = CK_INVALID_HANDLE;
927 	}
928 	if (kmo->hClientKey != CK_INVALID_HANDLE) {
929 		(void) soft_delete_derived_key(sp,
930 		    (soft_object_t *)(kmo->hClientKey));
931 		kmo->hClientKey = CK_INVALID_HANDLE;
932 	}
933 	if (kmo->hServerKey != CK_INVALID_HANDLE) {
934 		(void) soft_delete_derived_key(sp,
935 		    (soft_object_t *)(kmo->hServerKey));
936 		kmo->hServerKey = CK_INVALID_HANDLE;
937 	}
938 
939 	if (new_tmpl_allocated)
940 		free(new_tmpl);
941 
942 	if (export_keys != NULL)
943 		free(export_keys);
944 
945 	return (rv);
946 }
947 
948 /*
949  * Add the derived key to the session, and, if it's a token object,
950  * write it to the token.
951  */
952 static CK_RV
953 soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount,
954     CK_OBJECT_HANDLE_PTR phKey, soft_session_t *sp, soft_object_t *basekey_p)
955 {
956 	CK_RV rv;
957 	soft_object_t *secret_key;
958 
959 	if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) {
960 		return (CKR_HOST_MEMORY);
961 	}
962 
963 	if (((rv = soft_build_secret_key_object(tmpl, attrcount, secret_key,
964 	    SOFT_CREATE_OBJ_INT, 0, (CK_KEY_TYPE)~0UL)) != CKR_OK) ||
965 	    ((rv = soft_pin_expired_check(secret_key)) != CKR_OK) ||
966 	    ((rv = soft_object_write_access_check(sp, secret_key)) != CKR_OK)) {
967 
968 		free(secret_key);
969 		return (rv);
970 	}
971 
972 	/* Set the sensitivity and extractability attributes as a needed */
973 	soft_derive_enforce_flags(basekey_p, secret_key);
974 
975 	/* Initialize the rest of stuffs in soft_object_t. */
976 	(void) pthread_mutex_init(&secret_key->object_mutex, NULL);
977 	secret_key->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
978 
979 	/* ... and, if it needs to persist, write on the token */
980 	if (IS_TOKEN_OBJECT(secret_key)) {
981 		secret_key->session_handle = (CK_SESSION_HANDLE)NULL;
982 		soft_add_token_object_to_slot(secret_key);
983 		rv = soft_put_object_to_keystore(secret_key);
984 		if (rv != CKR_OK) {
985 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
986 			return (rv);
987 		}
988 		*phKey = (CK_OBJECT_HANDLE)secret_key;
989 
990 		return (CKR_OK);
991 	}
992 
993 	/* Add the new object to the session's object list. */
994 	soft_add_object_to_session(secret_key, sp);
995 	secret_key->session_handle = (CK_SESSION_HANDLE)sp;
996 
997 	*phKey = (CK_OBJECT_HANDLE)secret_key;
998 
999 	return (rv);
1000 }
1001 
1002 /*
1003  * Delete the derived key from the session, and, if it's a token object,
1004  * remove it from the token.
1005  */
1006 static void
1007 soft_delete_derived_key(soft_session_t *sp, soft_object_t *key)
1008 {
1009 	/* session_handle is the creating session. It's NULL for token objs */
1010 
1011 	if (IS_TOKEN_OBJECT(key))
1012 		soft_delete_token_object(key, B_FALSE, B_FALSE);
1013 	else
1014 		soft_delete_object(sp, key, B_FALSE);
1015 }
1016 
1017 /*
1018  * soft_ssl_weaken_key()
1019  * Reduce the key length to an exportable size.
1020  * For SSL3.0:
1021  *	final_client_write_key = MD5(client_write_key +
1022  *                                ClientHello.random +
1023  *                                ServerHello.random);
1024  *	final_server_write_key = MD5(server_write_key +
1025  *                                ServerHello.random +
1026  *                                ClientHello.random);
1027  * For TLS1.0:
1028  *	final_client_write_key = PRF(SecurityParameters.client_write_key,
1029  *				    "client write key",
1030  *				    SecurityParameters.client_random +
1031  *				    SecurityParameters.server_random)[0..15];
1032  *	final_server_write_key = PRF(SecurityParameters.server_write_key,
1033  *				    "server write key",
1034  *				    SecurityParameters.client_random +
1035  *				    SecurityParameters.server_random)[0..15];
1036  */
1037 static void
1038 soft_ssl_weaken_key(CK_MECHANISM_PTR mech, uchar_t *secret, uint_t secretlen,
1039     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
1040     uchar_t *result, boolean_t isclient)
1041 {
1042 	MD5_CTX exp_md5_ctx;
1043 	uchar_t *label;
1044 	uint_t labellen;
1045 
1046 	if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
1047 		MD5Init(&exp_md5_ctx);
1048 		MD5Update(&exp_md5_ctx, secret, secretlen);
1049 		MD5Update(&exp_md5_ctx, rand1, rand1len);
1050 		MD5Update(&exp_md5_ctx, rand2, rand2len);
1051 		MD5Final(result, &exp_md5_ctx);
1052 	} else {
1053 		if (isclient) {
1054 			label = TLS_CLIENT_KEY_LABEL;
1055 			labellen = TLS_CLIENT_KEY_LABEL_LEN;
1056 		} else {
1057 			label = TLS_SERVER_KEY_LABEL;
1058 			labellen = TLS_SERVER_KEY_LABEL_LEN;
1059 		}
1060 		soft_tls_prf(secret, secretlen, label, labellen,
1061 		    rand1, rand1len, rand2, rand2len, result, 16);
1062 	}
1063 }
1064