1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  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"
  41 
  42 /*
  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
  51  *
  52  * SSL refers to common functions between SSL v3.0 and SSL v3.1 (a.k.a TLS.)
  53  */
  54 
  55 #define MAX_KEYBLOCK    160     /* should be plenty for all known cipherspecs */
  56 
  57 #define MAX_DEFAULT_ATTRS       10      /* Enough for major applicarions */
  58 
  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",
  70 };
  71 static  uint_t ssl3_const_lens[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  72 
  73 static uchar_t TLS_MASTER_SECRET_LABEL[] = {"master secret"};
  74 #define TLS_MASTER_SECRET_LABEL_LEN     13
  75 
  76 static uchar_t TLS_KEY_EXPANSION_LABEL[] = {"key expansion"};
  77 #define TLS_KEY_EXPANSION_LABEL_LEN     13
  78 
  79 static uchar_t TLS_CLIENT_KEY_LABEL[] = {"client write key"};
  80 #define TLS_CLIENT_KEY_LABEL_LEN        16
  81 
  82 static uchar_t TLS_SERVER_KEY_LABEL[] = {"server write key"};
  83 #define TLS_SERVER_KEY_LABEL_LEN        16
  84 
  85 static uchar_t TLS_IV_BLOCK_LABEL[] = {"IV block"};
  86 #define TLS_IV_BLOCK_LABEL_LEN  8
  87 
  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);
  92 
  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);
  98 
  99 /*
 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.
 104  */
 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)
 109 {
 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);
 123 
 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;
 129         }
 130 }
 131 
 132 /*
 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
 139  */
 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)
 144 {
 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;
 149 
 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;
 157         }
 158 
 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. */
 164 
 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;
 169 
 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;
 175 
 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;
 181         }
 182 
 183         /*
 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
 187          */
 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);
 192 
 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);
 196 }
 197 
 198 /*
 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:
 202  *
 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))
 210  *
 211  * The seed is the concatenation of 'babel', 'rand1', and 'rand2'.
 212  */
 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)
 217 {
 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;
 226 
 227         /* good compilers will leverage the aligment */
 228         bzero(md5_ipad, MD5_HMAC_BLOCK_SIZE);
 229         bzero(md5_opad, MD5_HMAC_BLOCK_SIZE);
 230 
 231         if (secretlen > 0) {
 232                 bcopy(secret, md5_ipad, secretlen);
 233                 bcopy(secret, md5_opad, secretlen);
 234         }
 235 
 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);
 242 
 243         if (xor_it) {
 244                 res = md5_hmac;
 245                 cur = result;
 246         } else {
 247                 res = result;
 248         }
 249 
 250         while (left > 0) {
 251                 /*
 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.
 255                  */
 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);
 262 
 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++;
 269                                 }
 270                         } else {
 271                                 res += MD5_HASH_SIZE;
 272                         }
 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++;
 280                                 }
 281                         } else {
 282                                 bcopy(md5_hmac, res, left);
 283                         }
 284                         break;
 285                 }
 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);
 291         }
 292 }
 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)
 297 {
 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;
 306 
 307         /* good compilers will leverage the aligment */
 308         bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
 309         bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
 310 
 311         if (secretlen > 0) {
 312                 bcopy(secret, sha1_ipad, secretlen);
 313                 bcopy(secret, sha1_opad, secretlen);
 314         }
 315 
 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);
 322 
 323         if (xor_it) {
 324                 res = sha1_hmac;
 325                 cur = result;
 326         } else {
 327                 res = result;
 328         }
 329 
 330         while (left > 0) {
 331                 /*
 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.
 335                  */
 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);
 343 
 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++;
 350                                 }
 351                         } else {
 352                                 res += SHA1_HASH_SIZE;
 353                         }
 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++;
 361                                 }
 362                         } else {
 363                                 bcopy(sha1_hmac, res, left);
 364                         }
 365                         break;
 366                 }
 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);
 373         }
 374 }
 375 
 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)
 379 {
 380 
 381         if (param->pOutput == NULL || param->pulOutputLen == 0)
 382                 return (CKR_BUFFER_TOO_SMALL);
 383 
 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);
 388 
 389         return (CKR_OK);
 390 }
 391 
 392 
 393 /*
 394  * soft_ssl_master_key_derive()
 395  *
 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.
 404  *
 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));
 415  *
 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)
 419  */
 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)
 424 {
 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;
 446 
 447         /* Check the validity of the mechanism's parameter */
 448 
 449         mkd_params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter;
 450 
 451         if (mkd_params == NULL ||
 452             mech->ulParameterLen != sizeof (CK_SSL3_MASTER_KEY_DERIVE_PARAMS))
 453                 return (CKR_MECHANISM_PARAM_INVALID);
 454 
 455         pVersion = mkd_params->pVersion;
 456 
 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);
 465 
 466                 /* Get the SSL version number from the premaster secret */
 467                 if (pVersion == NULL_PTR)
 468                         return (CKR_MECHANISM_PARAM_INVALID);
 469 
 470                 bcopy(pmsecret, pVersion, sizeof (CK_VERSION));
 471 
 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);
 479         }
 480 
 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 */
 491 
 492         if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
 493             random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
 494                 return (CKR_MECHANISM_PARAM_INVALID);
 495         }
 496 
 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);
 507         }
 508 
 509         /*
 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.
 517          */
 518 
 519         newattrcount = ulAttributeCount + 4;
 520         if (newattrcount > MAX_DEFAULT_ATTRS) {
 521                 new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
 522 
 523                 if (new_tmpl == NULL)
 524                         return (CKR_HOST_MEMORY);
 525 
 526                 new_tmpl_allocated = B_TRUE;
 527         } else
 528                 new_tmpl = obj_tmpl;
 529 
 530         /*
 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.
 534          */
 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;
 547 
 548         /* Any attributes left? */
 549         if (ulAttributeCount > 0) {
 550 
 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;
 559                         }
 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;
 565                         }
 566                 }
 567                 bcopy(pTemplate, &new_tmpl[4],
 568                     ulAttributeCount * sizeof (CK_ATTRIBUTE));
 569         }
 570 
 571         rv = soft_add_derived_key(new_tmpl, newattrcount, phKey, sp, basekey_p);
 572 out:
 573         if (new_tmpl_allocated)
 574                 free(new_tmpl);
 575 
 576         return (rv);
 577 }
 578 
 579 /*
 580  * soft_ssl3_key_and_mac_derive()
 581  *
 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.
 591  *
 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)) + [...];
 607  *
 608  *      In TLS 1.0 (a.k.a. SSL 3.1), key_block =
 609  *          PRF(master_secret, "key expansion",
 610  *              ServerHello.random + ClientHello.random)
 611  *
 612  *      Then the keys materials are taken from the keyblock.
 613  */
 614 
 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)
 619 {
 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;
 643 
 644         /* Check the validity of the mechanism's parameter */
 645 
 646         km_params = (CK_SSL3_KEY_MAT_PARAMS *)mech->pParameter;
 647 
 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);
 652 
 653         isExport = (km_params->bIsExport == TRUE);
 654 
 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 */
 665 
 666         if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
 667             random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
 668                 return (CKR_MECHANISM_PARAM_INVALID);
 669         }
 670 
 671         mac_key_bytes = km_params->ulMacSizeInBits / 8;
 672         secret_key_bytes = km_params->ulKeySizeInBits / 8;
 673         iv_bytes = km_params->ulIVSizeInBits / 8;
 674 
 675         if ((iv_bytes > 0) &&
 676             ((kmo->pIVClient == NULL) || (kmo->pIVServer == NULL)))
 677                 return (CKR_MECHANISM_PARAM_INVALID);
 678 
 679         /*
 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]
 691          */
 692         if ((isExport) && (iv_bytes > 0)) {
 693 
 694                 if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
 695                         MD5_CTX exp_md5_ctx;
 696 
 697                         if (iv_bytes > MD5_HASH_SIZE)
 698                                 return (CKR_MECHANISM_PARAM_INVALID);
 699 
 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);
 705 
 706                         /* there's room in key_block. use it */
 707                         MD5Final(key_block, &exp_md5_ctx);
 708                         bcopy(key_block, kmo->pIVClient, iv_bytes);
 709 
 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];
 719 
 720                         if (iv_bytes != 8)
 721                                 return (CKR_MECHANISM_PARAM_INVALID);
 722 
 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);
 730                 }
 731                 /* so we won't allocate a key_block bigger than needed */
 732                 iv_bytes = 0;
 733         }
 734 
 735         /* Now the actual secret derivation */
 736 
 737 #ifdef  __sparcv9
 738         /* LINTED */
 739         size = (uint_t)((mac_key_bytes + secret_key_bytes + iv_bytes) * 2);
 740 #else   /* __sparcv9 */
 741         size = (mac_key_bytes + secret_key_bytes + iv_bytes) * 2;
 742 #endif  /* __sparcv9 */
 743 
 744         /* Need to handle this better */
 745         if (size > MAX_KEYBLOCK)
 746                 return (CKR_MECHANISM_PARAM_INVALID);
 747 
 748         rounds = howmany(size, MD5_HASH_SIZE);
 749 
 750         kb = key_block;
 751 
 752         if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
 753                 soft_ssl3_churn(msecret, mslen, random_data->pServerRandom,
 754                     ServerRandomLen, random_data->pClientRandom,
 755                     ClientRandomLen, rounds, kb);
 756         } else {
 757                 soft_tls_prf(msecret, mslen, TLS_KEY_EXPANSION_LABEL,
 758                     TLS_KEY_EXPANSION_LABEL_LEN,
 759                     random_data->pServerRandom, ServerRandomLen,
 760                     random_data->pClientRandom, ClientRandomLen,
 761                     kb, size);
 762         }
 763 
 764         /* Now create the objects */
 765 
 766         kmo->hClientMacSecret = CK_INVALID_HANDLE;
 767         kmo->hServerMacSecret = CK_INVALID_HANDLE;
 768         kmo->hClientKey = CK_INVALID_HANDLE;
 769         kmo->hServerKey = CK_INVALID_HANDLE;
 770 
 771         /* First the MAC secrets */
 772         if (mac_key_bytes > 0) {
 773                 obj_tmpl[0].type = CKA_CLASS;
 774                 obj_tmpl[0].pValue = &class;        /* CKO_SECRET_KEY */
 775                 obj_tmpl[0].ulValueLen = sizeof (class);
 776                 obj_tmpl[1].type = CKA_KEY_TYPE;
 777                 obj_tmpl[1].pValue = &keyType;      /* CKK_GENERIC_SECRET */
 778                 obj_tmpl[1].ulValueLen = sizeof (keyType);
 779                 obj_tmpl[2].type = CKA_DERIVE;
 780                 obj_tmpl[2].pValue = &true;
 781                 obj_tmpl[2].ulValueLen = sizeof (true);
 782                 obj_tmpl[3].type = CKA_SIGN;
 783                 obj_tmpl[3].pValue = &true;
 784                 obj_tmpl[3].ulValueLen = sizeof (true);
 785                 obj_tmpl[4].type = CKA_VERIFY;
 786                 obj_tmpl[4].pValue = &true;
 787                 obj_tmpl[4].ulValueLen = sizeof (true);
 788                 obj_tmpl[5].type = CKA_VALUE;
 789                 obj_tmpl[5].pValue = kb;
 790                 obj_tmpl[5].ulValueLen = mac_key_bytes;
 791 
 792                 rv = soft_add_derived_key(obj_tmpl, 6,
 793                     &(kmo->hClientMacSecret), sp, basekey_p);
 794 
 795                 if (rv != CKR_OK)
 796                         goto out_err;
 797 
 798                 kb += mac_key_bytes;
 799 
 800                 obj_tmpl[5].pValue = kb;
 801                 rv = soft_add_derived_key(obj_tmpl, 6,
 802                     &(kmo->hServerMacSecret), sp, basekey_p);
 803 
 804                 if (rv != CKR_OK)
 805                         goto out_err;
 806 
 807                 kb += mac_key_bytes;
 808         }
 809 
 810         /* Then the symmetric ciphers keys */
 811 
 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);
 816 
 817                 if (new_tmpl == NULL)
 818                         return (CKR_HOST_MEMORY);
 819 
 820                 new_tmpl_allocated = B_TRUE;
 821         } else
 822                 new_tmpl = obj_tmpl;
 823 
 824         new_tmpl[n].type = CKA_CLASS;
 825         new_tmpl[n].pValue = &class;        /* CKO_SECRET_KEY */
 826         new_tmpl[n].ulValueLen = sizeof (class);
 827         ++n;
 828         /*
 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.
 832          */
 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++;
 838         }
 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;
 854 
 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;
 860                         }
 861                         if ((export_keys = malloc(2 * MD5_HASH_SIZE)) == NULL) {
 862                                 rv = CKR_HOST_MEMORY;
 863                                 goto out_err;
 864                         }
 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;
 879                 }
 880         }
 881 
 882         if (ulAttributeCount > 0)
 883                 bcopy(pTemplate, &new_tmpl[extra_attr_count],
 884                     ulAttributeCount * sizeof (CK_ATTRIBUTE));
 885 
 886         rv = soft_add_derived_key(new_tmpl, newattrcount,
 887             &(kmo->hClientKey), sp, basekey_p);
 888 
 889         if (rv != CKR_OK)
 890                 goto out_err;
 891 
 892         kb += secret_key_bytes;
 893 
 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;
 908         }
 909 
 910         rv = soft_add_derived_key(new_tmpl, newattrcount,
 911             &(kmo->hServerKey), sp, basekey_p);
 912 
 913         if (rv != CKR_OK)
 914                 goto out_err;
 915 
 916         kb += secret_key_bytes;
 917 
 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);
 923         }
 924 
 925         if (new_tmpl_allocated)
 926                 free(new_tmpl);
 927 
 928         if (export_keys != NULL)
 929                 free(export_keys);
 930 
 931         return (rv);
 932 
 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;
 938         }
 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;
 943         }
 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;
 948         }
 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;
 953         }
 954 
 955         if (new_tmpl_allocated)
 956                 free(new_tmpl);
 957 
 958         if (export_keys != NULL)
 959                 free(export_keys);
 960 
 961         return (rv);
 962 }
 963 
 964 /*
 965  * Add the derived key to the session, and, if it's a token object,
 966  * write it to the token.
 967  */
 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)
 971 {
 972         CK_RV rv;
 973         soft_object_t *secret_key;
 974 
 975         if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) {
 976                 return (CKR_HOST_MEMORY);
 977         }
 978 
 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)) {
 983 
 984                 free(secret_key);
 985                 return (rv);
 986         }
 987 
 988         /* Set the sensitivity and extractability attributes as a needed */
 989         soft_derive_enforce_flags(basekey_p, secret_key);
 990 
 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;
 994 
 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);
1003                 }
1004                 *phKey = (CK_OBJECT_HANDLE)secret_key;
1005 
1006                 return (CKR_OK);
1007         }
1008 
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;
1012 
1013         *phKey = (CK_OBJECT_HANDLE)secret_key;
1014 
1015         return (rv);
1016 }
1017 
1018 /*
1019  * Delete the derived key from the session, and, if it's a token object,
1020  * remove it from the token.
1021  */
1022 static void
1023 soft_delete_derived_key(soft_session_t *sp, soft_object_t *key)
1024 {
1025         /* session_handle is the creating session. It's NULL for token objs */
1026 
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);
1031 }
1032 
1033 /*
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];
1052  */
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)
1057 {
1058         MD5_CTX exp_md5_ctx;
1059         uchar_t *label;
1060         uint_t labellen;
1061 
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);
1079                 }
1080         }
1081 }