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