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