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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2018, Joyent, Inc.
30 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <security/cryptoki.h>
35 #include "softGlobal.h"
37 #include "softKeystore.h"
39 #include "softObject.h"
40 #include "softSession.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
[] = {
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
);
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.
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
,
113 uchar_t sha1_digest
[SHA1_HASH_SIZE
];
115 uchar_t
*ms
= result
;
116 for (i
= 0; i
< rounds
; i
++) {
118 SHA1Update(&sha1_ctx
, (const uint8_t *)ssl3_const_vals
[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
);
126 MD5Update(&md5_ctx
, secret
, secretlen
);
127 MD5Update(&md5_ctx
, sha1_digest
, SHA1_HASH_SIZE
);
128 MD5Final(ms
, &md5_ctx
);
134 * This TLS generic Pseudo Random Function expands a triplet
135 * {secret, label, seed} into any arbitrary length string of pseudo
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
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
)
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
) {
160 L_S
= roundup(secretlen
, 2) / 2;
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
) {
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
;
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
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
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.
210 * A(i) = HMAC_hash(secret, A(i-1))
212 * The seed is the concatenation of 'babel', 'rand1', and 'rand2'.
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
;
225 uint_t left
= resultlen
;
228 /* good compilers will leverage the aligment */
229 bzero(md5_ipad
, MD5_HMAC_BLOCK_SIZE
);
230 bzero(md5_opad
, MD5_HMAC_BLOCK_SIZE
);
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
);
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
);
267 for (i
= 0; i
< MD5_HASH_SIZE
; i
++) {
272 res
+= MD5_HASH_SIZE
;
274 left
-= MD5_HASH_SIZE
;
276 SOFT_MAC_FINAL(MD5
, &md5_hmac_ctx
, md5_hmac
);
278 for (i
= 0; i
< left
; i
++) {
283 bcopy(md5_hmac
, res
, left
);
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
);
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
;
305 uint_t left
= resultlen
;
308 /* good compilers will leverage the aligment */
309 bzero(sha1_ipad
, SHA1_HMAC_BLOCK_SIZE
);
310 bzero(sha1_opad
, SHA1_HMAC_BLOCK_SIZE
);
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
);
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
);
348 for (i
= 0; i
< SHA1_HASH_SIZE
; i
++) {
353 res
+= SHA1_HASH_SIZE
;
355 left
-= SHA1_HASH_SIZE
;
357 SOFT_MAC_FINAL(SHA1
, &sha1_hmac_ctx
, sha1_hmac
);
359 for (i
= 0; i
< left
; i
++) {
360 *cur
^= sha1_hmac
[i
];
364 bcopy(sha1_hmac
, res
, left
);
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 */
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
);
395 * soft_ssl_master_key_derive()
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
404 * . phKey: store for handle to the derived key.
407 * Derive the SSL master secret from the pre-master secret, the client
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)
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
);
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
;
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
:
462 case CKM_SSL3_MASTER_KEY_DERIVE
:
463 /* Invalid pre-master key length. What else to return? */
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
));
474 case CKM_TLS_MASTER_KEY_DERIVE_DH
:
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
;
485 ClientRandomLen
= (uint_t
)random_data
->ulClientRandomLen
;
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 */
500 soft_ssl3_churn(pmsecret
, pmlen
, random_data
->pClientRandom
,
501 ClientRandomLen
, random_data
->pServerRandom
,
502 ServerRandomLen
, 3, ssl_master_secret
);
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
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
;
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
) !=
558 rv
= CKR_TEMPLATE_INCONSISTENT
;
561 if ((pTemplate
[i
].type
== CKA_KEY_TYPE
) &&
562 (*((CK_KEY_TYPE
*)pTemplate
[i
].pValue
) !=
563 CKK_GENERIC_SECRET
)) {
564 rv
= CKR_TEMPLATE_INCONSISTENT
;
568 bcopy(pTemplate
, &new_tmpl
[4],
569 ulAttributeCount
* sizeof (CK_ATTRIBUTE
));
572 rv
= soft_add_derived_key(new_tmpl
, newattrcount
, phKey
, sp
, basekey_p
);
574 if (new_tmpl_allocated
)
581 * soft_ssl3_key_and_mac_derive()
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
594 * Derive the SSL key material (Client and server MAC secrets, symmetric
595 * keys and IVs), from the master secret and the client
597 * First a keyblock is generated usining the following formula:
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.
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
);
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
;
641 boolean_t new_tmpl_allocated
= B_FALSE
, isExport
;
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
;
659 ClientRandomLen
= (uint_t
)random_data
->ulClientRandomLen
;
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.
685 * client_write_IV = MD5(ClientHello.random + ServerHello.random);
686 * server_write_IV = MD5(ServerHello.random + ClientHello.random);
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
) {
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
,
704 MD5Update(&exp_md5_ctx
, random_data
->pServerRandom
,
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
,
714 MD5Update(&exp_md5_ctx
, random_data
->pClientRandom
,
716 MD5Final(key_block
, &exp_md5_ctx
);
717 bcopy(key_block
, kmo
->pIVServer
, iv_bytes
);
719 uchar_t iv_block
[16];
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
,
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 */
736 /* Now the actual secret derivation */
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
);
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
);
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
,
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
);
801 obj_tmpl
[5].pValue
= kb
;
802 rv
= soft_add_derived_key(obj_tmpl
, 6,
803 &(kmo
->hServerMacSecret
), sp
, basekey_p
);
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
;
825 new_tmpl
[n
].type
= CKA_CLASS
;
826 new_tmpl
[n
].pValue
= &class; /* CKO_SECRET_KEY */
827 new_tmpl
[n
].ulValueLen
= sizeof (class);
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
);
840 new_tmpl
[n
].type
= CKA_DERIVE
;
841 new_tmpl
[n
].pValue
= &true;
842 new_tmpl
[n
].ulValueLen
= sizeof (true);
844 new_tmpl
[n
].type
= CKA_ENCRYPT
;
845 new_tmpl
[n
].pValue
= &true;
846 new_tmpl
[n
].ulValueLen
= sizeof (true);
848 new_tmpl
[n
].type
= CKA_DECRYPT
;
849 new_tmpl
[n
].pValue
= &true;
850 new_tmpl
[n
].ulValueLen
= sizeof (true);
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) {
858 if (secret_key_bytes
> MD5_HASH_SIZE
) {
859 rv
= CKR_MECHANISM_PARAM_INVALID
;
862 if ((export_keys
= malloc(2 * MD5_HASH_SIZE
)) == NULL
) {
863 rv
= CKR_HOST_MEMORY
;
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
;
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
);
896 kb
+= secret_key_bytes
;
898 if (secret_key_bytes
> 0) {
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
;
914 new_tmpl
[n
].pValue
= kb
;
917 rv
= soft_add_derived_key(new_tmpl
, newattrcount
,
918 &(kmo
->hServerKey
), sp
, basekey_p
);
923 kb
+= secret_key_bytes
;
925 /* Finally, the IVs */
927 bcopy(kb
, kmo
->pIVClient
, iv_bytes
);
929 bcopy(kb
, kmo
->pIVServer
, iv_bytes
);
932 if (new_tmpl_allocated
)
935 freezero(export_keys
, 2 * MD5_HASH_SIZE
);
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
)
964 freezero(export_keys
, 2 * MD5_HASH_SIZE
);
970 * Add the derived key to the session, and, if it's a token object,
971 * write it to the token.
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
)
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
)) {
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
);
1006 soft_delete_token_object(secret_key
, B_FALSE
, B_FALSE
);
1009 *phKey
= (CK_OBJECT_HANDLE
)secret_key
;
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
;
1024 * Delete the derived key from the session, and, if it's a token object,
1025 * remove it from the token.
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
);
1035 soft_delete_object(sp
, key
, B_FALSE
, B_FALSE
);
1039 * soft_ssl_weaken_key()
1040 * Reduce the key length to an exportable size.
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);
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];
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
;
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
);
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);
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);