1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2020 Joyent, Inc.
26 */
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
soft_ssl3_churn(uchar_t * secret,uint_t secretlen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,int rounds,uchar_t * result)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
soft_tls_prf(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen)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
P_MD5(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen,boolean_t xor_it)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
P_SHA1(uchar_t * secret,uint_t secretlen,uchar_t * label,uint_t labellen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,uint_t resultlen,boolean_t xor_it)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
derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param,soft_object_t * basekey_p)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
soft_ssl_master_key_derive(soft_session_t * sp,CK_MECHANISM_PTR mech,soft_object_t * basekey_p,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)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
soft_ssl_key_and_mac_derive(soft_session_t * sp,CK_MECHANISM_PTR mech,soft_object_t * basekey_p,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount)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 random_data->pClientRandom, ClientRandomLen,
871 random_data->pServerRandom, ServerRandomLen,
872 export_keys, B_TRUE);
873 #else /* __sparcv9 */
874 soft_ssl_weaken_key(mech, kb, secret_key_bytes,
875 random_data->pClientRandom, ClientRandomLen,
876 random_data->pServerRandom, ServerRandomLen,
877 export_keys, B_TRUE);
878 #endif /* __sparcv9 */
879 new_tmpl[n].pValue = export_keys;
880 new_tmpl[n].ulValueLen = MD5_HASH_SIZE;
881 } else {
882 new_tmpl[n].pValue = kb;
883 new_tmpl[n].ulValueLen = secret_key_bytes;
884 }
885 }
886
887 if (ulAttributeCount > 0)
888 bcopy(pTemplate, &new_tmpl[extra_attr_count],
889 ulAttributeCount * sizeof (CK_ATTRIBUTE));
890
891 rv = soft_add_derived_key(new_tmpl, newattrcount,
892 &(kmo->hClientKey), sp, basekey_p);
893
894 if (rv != CKR_OK)
895 goto out_err;
896
897 kb += secret_key_bytes;
898
899 if (secret_key_bytes > 0) {
900 if (isExport) {
901 #ifdef __sparcv9
902 /* LINTED */
903 soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
904 random_data->pServerRandom, ServerRandomLen,
905 random_data->pClientRandom, ClientRandomLen,
906 export_keys + MD5_HASH_SIZE, B_FALSE);
907 #else /* __sparcv9 */
908 soft_ssl_weaken_key(mech, kb, secret_key_bytes,
909 random_data->pServerRandom, ServerRandomLen,
910 random_data->pClientRandom, ClientRandomLen,
911 export_keys + MD5_HASH_SIZE, B_FALSE);
912 #endif /* __sparcv9 */
913 new_tmpl[n].pValue = export_keys + MD5_HASH_SIZE;
914 } else
915 new_tmpl[n].pValue = kb;
916 }
917
918 rv = soft_add_derived_key(new_tmpl, newattrcount,
919 &(kmo->hServerKey), sp, basekey_p);
920
921 if (rv != CKR_OK)
922 goto out_err;
923
924 kb += secret_key_bytes;
925
926 /* Finally, the IVs */
927 if (iv_bytes > 0) {
928 bcopy(kb, kmo->pIVClient, iv_bytes);
929 kb += iv_bytes;
930 bcopy(kb, kmo->pIVServer, iv_bytes);
931 }
932
933 if (new_tmpl_allocated)
934 free(new_tmpl);
935
936 freezero(export_keys, 2 * MD5_HASH_SIZE);
937
938 return (rv);
939
940 out_err:
941 if (kmo->hClientMacSecret != CK_INVALID_HANDLE) {
942 (void) soft_delete_derived_key(sp,
943 (soft_object_t *)(kmo->hClientMacSecret));
944 kmo->hClientMacSecret = CK_INVALID_HANDLE;
945 }
946 if (kmo->hServerMacSecret != CK_INVALID_HANDLE) {
947 (void) soft_delete_derived_key(sp,
948 (soft_object_t *)(kmo->hServerMacSecret));
949 kmo->hServerMacSecret = CK_INVALID_HANDLE;
950 }
951 if (kmo->hClientKey != CK_INVALID_HANDLE) {
952 (void) soft_delete_derived_key(sp,
953 (soft_object_t *)(kmo->hClientKey));
954 kmo->hClientKey = CK_INVALID_HANDLE;
955 }
956 if (kmo->hServerKey != CK_INVALID_HANDLE) {
957 (void) soft_delete_derived_key(sp,
958 (soft_object_t *)(kmo->hServerKey));
959 kmo->hServerKey = CK_INVALID_HANDLE;
960 }
961
962 if (new_tmpl_allocated)
963 free(new_tmpl);
964
965 freezero(export_keys, 2 * MD5_HASH_SIZE);
966
967 return (rv);
968 }
969
970 /*
971 * Add the derived key to the session, and, if it's a token object,
972 * write it to the token.
973 */
974 static CK_RV
soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl,CK_ULONG attrcount,CK_OBJECT_HANDLE_PTR phKey,soft_session_t * sp,soft_object_t * basekey_p)975 soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount,
976 CK_OBJECT_HANDLE_PTR phKey, soft_session_t *sp, soft_object_t *basekey_p)
977 {
978 CK_RV rv;
979 soft_object_t *secret_key;
980
981 if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) {
982 return (CKR_HOST_MEMORY);
983 }
984
985 if (((rv = soft_build_secret_key_object(tmpl, attrcount, secret_key,
986 SOFT_CREATE_OBJ_INT, 0, (CK_KEY_TYPE)~0UL)) != CKR_OK) ||
987 ((rv = soft_pin_expired_check(secret_key)) != CKR_OK) ||
988 ((rv = soft_object_write_access_check(sp, secret_key)) != CKR_OK)) {
989
990 free(secret_key);
991 return (rv);
992 }
993
994 /* Set the sensitivity and extractability attributes as a needed */
995 soft_derive_enforce_flags(basekey_p, secret_key);
996
997 /* Initialize the rest of stuffs in soft_object_t. */
998 (void) pthread_mutex_init(&secret_key->object_mutex, NULL);
999 secret_key->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
1000
1001 /* ... and, if it needs to persist, write on the token */
1002 if (IS_TOKEN_OBJECT(secret_key)) {
1003 secret_key->session_handle = CK_INVALID_HANDLE;
1004 soft_add_token_object_to_slot(secret_key);
1005 rv = soft_put_object_to_keystore(secret_key);
1006 if (rv != CKR_OK) {
1007 soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
1008 return (rv);
1009 }
1010 *phKey = set_objecthandle(secret_key);
1011
1012 return (CKR_OK);
1013 }
1014
1015 /* Add the new object to the session's object list. */
1016 soft_add_object_to_session(secret_key, sp);
1017 secret_key->session_handle = sp->handle;
1018
1019 *phKey = set_objecthandle(secret_key);
1020
1021 return (rv);
1022 }
1023
1024 /*
1025 * Delete the derived key from the session, and, if it's a token object,
1026 * remove it from the token.
1027 */
1028 static void
soft_delete_derived_key(soft_session_t * sp,soft_object_t * key)1029 soft_delete_derived_key(soft_session_t *sp, soft_object_t *key)
1030 {
1031 /* session_handle is the creating session. It's NULL for token objs */
1032
1033 if (IS_TOKEN_OBJECT(key))
1034 soft_delete_token_object(key, B_FALSE, B_FALSE);
1035 else
1036 soft_delete_object(sp, key, B_FALSE, B_FALSE);
1037 }
1038
1039 /*
1040 * soft_ssl_weaken_key()
1041 * Reduce the key length to an exportable size.
1042 * For SSL3.0:
1043 * final_client_write_key = MD5(client_write_key +
1044 * ClientHello.random +
1045 * ServerHello.random);
1046 * final_server_write_key = MD5(server_write_key +
1047 * ServerHello.random +
1048 * ClientHello.random);
1049 * For TLS1.0:
1050 * final_client_write_key = PRF(SecurityParameters.client_write_key,
1051 * "client write key",
1052 * SecurityParameters.client_random +
1053 * SecurityParameters.server_random)[0..15];
1054 * final_server_write_key = PRF(SecurityParameters.server_write_key,
1055 * "server write key",
1056 * SecurityParameters.client_random +
1057 * SecurityParameters.server_random)[0..15];
1058 */
1059 static void
soft_ssl_weaken_key(CK_MECHANISM_PTR mech,uchar_t * secret,uint_t secretlen,uchar_t * rand1,uint_t rand1len,uchar_t * rand2,uint_t rand2len,uchar_t * result,boolean_t isclient)1060 soft_ssl_weaken_key(CK_MECHANISM_PTR mech, uchar_t *secret, uint_t secretlen,
1061 uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
1062 uchar_t *result, boolean_t isclient)
1063 {
1064 MD5_CTX exp_md5_ctx;
1065 uchar_t *label;
1066 uint_t labellen;
1067
1068 if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
1069 MD5Init(&exp_md5_ctx);
1070 MD5Update(&exp_md5_ctx, secret, secretlen);
1071 MD5Update(&exp_md5_ctx, rand1, rand1len);
1072 MD5Update(&exp_md5_ctx, rand2, rand2len);
1073 MD5Final(result, &exp_md5_ctx);
1074 } else {
1075 if (isclient) {
1076 label = TLS_CLIENT_KEY_LABEL;
1077 labellen = TLS_CLIENT_KEY_LABEL_LEN;
1078 soft_tls_prf(secret, secretlen, label, labellen,
1079 rand1, rand1len, rand2, rand2len, result, 16);
1080 } else {
1081 label = TLS_SERVER_KEY_LABEL;
1082 labellen = TLS_SERVER_KEY_LABEL_LEN;
1083 soft_tls_prf(secret, secretlen, label, labellen,
1084 rand2, rand2len, rand1, rand1len, result, 16);
1085 }
1086 }
1087 }
1088