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  * Copyright 2018, Joyent, Inc.
  25  */
  26 
  27 #include <fcntl.h>
  28 #include <strings.h>
  29 #include <sys/stat.h>
  30 #include <sys/types.h>
  31 #include <sys/sha1.h>
  32 #include <sys/md5.h>
  33 #include <sys/sysmacros.h>
  34 #include <security/cryptoki.h>
  35 #include "softGlobal.h"
  36 #include "softKeys.h"
  37 #include "softKeystore.h"
  38 #include "softMAC.h"
  39 #include "softObject.h"
  40 #include "softSession.h"
  41 #include "softSSL.h"
  42 
  43 /*
  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
  52  *
  53  * SSL refers to common functions between SSL v3.0 and SSL v3.1 (a.k.a TLS.)
  54  */
  55 
  56 #define MAX_KEYBLOCK    160     /* should be plenty for all known cipherspecs */
  57 
  58 #define MAX_DEFAULT_ATTRS       10      /* Enough for major applicarions */
  59 
  60 static  char *ssl3_const_vals[] = {
  61         "A",
  62         "BB",
  63         "CCC",
  64         "DDDD",
  65         "EEEEE",
  66         "FFFFFF",
  67         "GGGGGGG",
  68         "HHHHHHHH",
  69         "IIIIIIIII",
  70         "JJJJJJJJJJ",
  71 };
  72 static  uint_t ssl3_const_lens[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  73 
  74 static uchar_t TLS_MASTER_SECRET_LABEL[] = {"master secret"};
  75 #define TLS_MASTER_SECRET_LABEL_LEN     13
  76 
  77 static uchar_t TLS_KEY_EXPANSION_LABEL[] = {"key expansion"};
  78 #define TLS_KEY_EXPANSION_LABEL_LEN     13
  79 
  80 static uchar_t TLS_CLIENT_KEY_LABEL[] = {"client write key"};
  81 #define TLS_CLIENT_KEY_LABEL_LEN        16
  82 
  83 static uchar_t TLS_SERVER_KEY_LABEL[] = {"server write key"};
  84 #define TLS_SERVER_KEY_LABEL_LEN        16
  85 
  86 static uchar_t TLS_IV_BLOCK_LABEL[] = {"IV block"};
  87 #define TLS_IV_BLOCK_LABEL_LEN  8
  88 
  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);
  93 
  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);
  99 
 100 /*
 101  * soft_ssl3_churn()
 102  * Called for derivation of the master secret from the pre-master secret,
 103  * and for the derivation of the key_block in an SSL3 handshake
 104  * result is assumed to be larger than rounds * MD5_HASH_SIZE.
 105  */
 106 static void
 107 soft_ssl3_churn(uchar_t *secret, uint_t secretlen, uchar_t *rand1,
 108     uint_t rand1len, uchar_t *rand2, uint_t rand2len, int rounds,
 109     uchar_t *result)
 110 {
 111         SHA1_CTX sha1_ctx;
 112         MD5_CTX md5_ctx;
 113         uchar_t sha1_digest[SHA1_HASH_SIZE];
 114         int i;
 115         uchar_t *ms = result;
 116         for (i = 0; i < rounds; i++) {
 117                 SHA1Init(&sha1_ctx);
 118                 SHA1Update(&sha1_ctx, (const uint8_t *)ssl3_const_vals[i],
 119                     ssl3_const_lens[i]);
 120                 SHA1Update(&sha1_ctx, secret, secretlen);
 121                 SHA1Update(&sha1_ctx, rand1, rand1len);
 122                 SHA1Update(&sha1_ctx, rand2, rand2len);
 123                 SHA1Final(sha1_digest, &sha1_ctx);
 124 
 125                 MD5Init(&md5_ctx);
 126                 MD5Update(&md5_ctx, secret, secretlen);
 127                 MD5Update(&md5_ctx, sha1_digest, SHA1_HASH_SIZE);
 128                 MD5Final(ms, &md5_ctx);
 129                 ms += MD5_HASH_SIZE;
 130         }
 131 }
 132 
 133 /*
 134  * This TLS generic Pseudo Random Function expands a triplet
 135  * {secret, label, seed} into any arbitrary length string of pseudo
 136  * random bytes.
 137  * Here, it is called for the derivation of the master secret from the
 138  * pre-master secret, and for the derivation of the key_block in a TLS
 139  * handshake
 140  */
 141 static void
 142 soft_tls_prf(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
 143     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
 144     uchar_t *result, uint_t resultlen)
 145 {
 146         uchar_t *S1, *S2;
 147         uchar_t md5_digested_key[MD5_HASH_SIZE];
 148         uchar_t sha1_digested_key[SHA1_HASH_SIZE];
 149         uint_t L_S, L_S1, L_S2;
 150 
 151         /* secret is NULL for IV's in exportable ciphersuites */
 152         if (secret == NULL) {
 153                 L_S = 0;
 154                 L_S2 = L_S1 = 0;
 155                 S1 = NULL;
 156                 S2 = NULL;
 157                 goto do_P_HASH;
 158         }
 159 
 160         L_S = roundup(secretlen, 2) / 2;
 161         L_S1 = L_S;
 162         L_S2 = L_S;
 163         S1 = secret;
 164         S2 = secret + (secretlen / 2);  /* Possible overlap of S1 and S2. */
 165 
 166         /* Reduce the half secrets if bigger than the HASH's block size */
 167         if (L_S > MD5_HMAC_BLOCK_SIZE) {
 168                 MD5_CTX md5_ctx;
 169                 SHA1_CTX sha1_ctx;
 170 
 171                 MD5Init(&md5_ctx);
 172                 MD5Update(&md5_ctx, S1, L_S);
 173                 MD5Final(md5_digested_key, &md5_ctx);
 174                 S1 = md5_digested_key;
 175                 L_S1 = MD5_HASH_SIZE;
 176 
 177                 SHA1Init(&sha1_ctx);
 178                 SHA1Update(&sha1_ctx, S2, L_S);
 179                 SHA1Final(sha1_digested_key, &sha1_ctx);
 180                 S2 = sha1_digested_key;
 181                 L_S2 = SHA1_HASH_SIZE;
 182         }
 183 
 184         /*
 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
 188          */
 189 do_P_HASH:
 190         /* The first one writes directly to the result */
 191         P_MD5(S1, L_S1, label, labellen, rand1, rand1len, rand2, rand2len,
 192             result, resultlen, B_FALSE);
 193 
 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);
 197 }
 198 
 199 /*
 200  * These two expansion routines are very similar. (they can merge one day).
 201  * They implement the P_HASH() function for MD5 and for SHA1, as defined in
 202  * RFC2246:
 203  *
 204  *      P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
 205  *                              HMAC_hash(secret, A(2) + seed) +
 206  *                              HMAC_hash(secret, A(3) + seed) + ...
 207  * Where + indicates concatenation.
 208  * A() is defined as:
 209  *      A(0) = seed
 210  *      A(i) = HMAC_hash(secret, A(i-1))
 211  *
 212  * The seed is the concatenation of 'babel', 'rand1', and 'rand2'.
 213  */
 214 static void
 215 P_MD5(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
 216     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
 217     uchar_t *result, uint_t resultlen, boolean_t xor_it)
 218 {
 219         uint32_t md5_ipad[MD5_HMAC_INTS_PER_BLOCK];
 220         uint32_t md5_opad[MD5_HMAC_INTS_PER_BLOCK];
 221         uchar_t md5_hmac[MD5_HASH_SIZE];
 222         uchar_t A[MD5_HASH_SIZE];
 223         md5_hc_ctx_t md5_hmac_ctx;
 224         uchar_t *res, *cur;
 225         uint_t left = resultlen;
 226         int i;
 227 
 228         /* good compilers will leverage the aligment */
 229         bzero(md5_ipad, MD5_HMAC_BLOCK_SIZE);
 230         bzero(md5_opad, MD5_HMAC_BLOCK_SIZE);
 231 
 232         if (secretlen > 0) {
 233                 bcopy(secret, md5_ipad, secretlen);
 234                 bcopy(secret, md5_opad, secretlen);
 235         }
 236 
 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);
 243 
 244         if (xor_it) {
 245                 res = md5_hmac;
 246                 cur = result;
 247         } else {
 248                 res = result;
 249         }
 250 
 251         while (left > 0) {
 252                 /*
 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.
 256                  */
 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);
 263 
 264                 if (left > MD5_HASH_SIZE) {
 265                         SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, res);
 266                         if (xor_it) {
 267                                 for (i = 0; i < MD5_HASH_SIZE; i++) {
 268                                         *cur ^= res[i];
 269                                         cur++;
 270                                 }
 271                         } else {
 272                                 res += MD5_HASH_SIZE;
 273                         }
 274                         left -= MD5_HASH_SIZE;
 275                 } else {
 276                         SOFT_MAC_FINAL(MD5, &md5_hmac_ctx, md5_hmac);
 277                         if (xor_it) {
 278                                 for (i = 0; i < left; i++) {
 279                                         *cur ^= md5_hmac[i];
 280                                         cur++;
 281                                 }
 282                         } else {
 283                                 bcopy(md5_hmac, res, left);
 284                         }
 285                         break;
 286                 }
 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);
 292         }
 293 }
 294 static void
 295 P_SHA1(uchar_t *secret, uint_t secretlen, uchar_t *label, uint_t labellen,
 296     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
 297     uchar_t *result, uint_t resultlen, boolean_t xor_it)
 298 {
 299         uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK];
 300         uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK];
 301         uchar_t sha1_hmac[SHA1_HASH_SIZE];
 302         uchar_t A[SHA1_HASH_SIZE];
 303         sha1_hc_ctx_t sha1_hmac_ctx;
 304         uchar_t *res, *cur;
 305         uint_t left = resultlen;
 306         int i;
 307 
 308         /* good compilers will leverage the aligment */
 309         bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
 310         bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
 311 
 312         if (secretlen > 0) {
 313                 bcopy(secret, sha1_ipad, secretlen);
 314                 bcopy(secret, sha1_opad, secretlen);
 315         }
 316 
 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);
 323 
 324         if (xor_it) {
 325                 res = sha1_hmac;
 326                 cur = result;
 327         } else {
 328                 res = result;
 329         }
 330 
 331         while (left > 0) {
 332                 /*
 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.
 336                  */
 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);
 344 
 345                 if (left > SHA1_HASH_SIZE) {
 346                         SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, res);
 347                         if (xor_it) {
 348                                 for (i = 0; i < SHA1_HASH_SIZE; i++) {
 349                                         *cur ^= res[i];
 350                                         cur++;
 351                                 }
 352                         } else {
 353                                 res += SHA1_HASH_SIZE;
 354                         }
 355                         left -= SHA1_HASH_SIZE;
 356                 } else {
 357                         SOFT_MAC_FINAL(SHA1, &sha1_hmac_ctx, sha1_hmac);
 358                         if (xor_it) {
 359                                 for (i = 0; i < left; i++) {
 360                                         *cur ^= sha1_hmac[i];
 361                                         cur++;
 362                                 }
 363                         } else {
 364                                 bcopy(sha1_hmac, res, left);
 365                         }
 366                         break;
 367                 }
 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);
 374         }
 375 }
 376 
 377 /* This function handles the call from C_DeriveKey for CKM_TLS_PRF */
 378 CK_RV
 379 derive_tls_prf(CK_TLS_PRF_PARAMS_PTR param, soft_object_t *basekey_p)
 380 {
 381 
 382         if (param->pOutput == NULL || param->pulOutputLen == 0)
 383                 return (CKR_BUFFER_TOO_SMALL);
 384 
 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);
 389 
 390         return (CKR_OK);
 391 }
 392 
 393 
 394 /*
 395  * soft_ssl_master_key_derive()
 396  *
 397  * Arguments:
 398  * . session_p
 399  * . mech_p:    key derivation mechanism. the mechanism parameter carries the
 400  *              client and master random from the Hello handshake messages.
 401  * . basekey_p: The pre-master secret key.
 402  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
 403  *              created.
 404  * . phKey:     store for handle to the derived key.
 405  *
 406  * Description:
 407  *      Derive the SSL master secret from the pre-master secret, the client
 408  *      and server random.
 409  *      In SSL 3.0, master_secret =
 410  *          MD5(pre_master_secret + SHA('A' + pre_master_secret +
 411  *              ClientHello.random + ServerHello.random)) +
 412  *          MD5(pre_master_secret + SHA('BB' + pre_master_secret +
 413  *              ClientHello.random + ServerHello.random)) +
 414  *          MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
 415  *              ClientHello.random + ServerHello.random));
 416  *
 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)
 420  */
 421 CK_RV
 422 soft_ssl_master_key_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
 423     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
 424     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
 425 {
 426         uchar_t *pmsecret = OBJ_SEC_VALUE(basekey_p);
 427 #ifdef  __sparcv9
 428         /* LINTED */
 429         uint_t pmlen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
 430 #else   /* __sparcv9 */
 431         uint_t pmlen = OBJ_SEC_VALUE_LEN(basekey_p);
 432 #endif  /* __sparcv9 */
 433         CK_SSL3_MASTER_KEY_DERIVE_PARAMS *mkd_params;
 434         CK_SSL3_RANDOM_DATA *random_data;
 435         CK_VERSION_PTR  pVersion;
 436         uchar_t ssl_master_secret[48];
 437         CK_OBJECT_CLASS class = CKO_SECRET_KEY;
 438         CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
 439         CK_BBOOL true = TRUE;
 440         CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
 441         CK_ATTRIBUTE_PTR new_tmpl;
 442         CK_ULONG newattrcount;
 443         boolean_t new_tmpl_allocated = B_FALSE, is_tls = B_FALSE;
 444         ulong_t i;
 445         CK_RV rv = CKR_OK;
 446         uint_t ClientRandomLen, ServerRandomLen;
 447 
 448         /* Check the validity of the mechanism's parameter */
 449 
 450         mkd_params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter;
 451 
 452         if (mkd_params == NULL ||
 453             mech->ulParameterLen != sizeof (CK_SSL3_MASTER_KEY_DERIVE_PARAMS))
 454                 return (CKR_MECHANISM_PARAM_INVALID);
 455 
 456         pVersion = mkd_params->pVersion;
 457 
 458         switch (mech->mechanism) {
 459         case CKM_TLS_MASTER_KEY_DERIVE:
 460                 is_tls = B_TRUE;
 461         /* FALLTHRU */
 462         case CKM_SSL3_MASTER_KEY_DERIVE:
 463                 /* Invalid pre-master key length. What else to return? */
 464                 if (pmlen != 48)
 465                         return (CKR_ARGUMENTS_BAD);
 466 
 467                 /* Get the SSL version number from the premaster secret */
 468                 if (pVersion == NULL_PTR)
 469                         return (CKR_MECHANISM_PARAM_INVALID);
 470 
 471                 bcopy(pmsecret, pVersion, sizeof (CK_VERSION));
 472 
 473                 break;
 474         case CKM_TLS_MASTER_KEY_DERIVE_DH:
 475                 is_tls = B_TRUE;
 476         /* FALLTHRU */
 477         case CKM_SSL3_MASTER_KEY_DERIVE_DH:
 478                 if (pVersion != NULL_PTR)
 479                         return (CKR_MECHANISM_PARAM_INVALID);
 480         }
 481 
 482         random_data = &mkd_params->RandomInfo;
 483 #ifdef  __sparcv9
 484         /* LINTED */
 485         ClientRandomLen = (uint_t)random_data->ulClientRandomLen;
 486         /* LINTED */
 487         ServerRandomLen = (uint_t)random_data->ulServerRandomLen;
 488 #else   /* __sparcv9 */
 489         ClientRandomLen = random_data->ulClientRandomLen;
 490         ServerRandomLen = random_data->ulServerRandomLen;
 491 #endif  /* __sparcv9 */
 492 
 493         if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
 494             random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
 495                 return (CKR_MECHANISM_PARAM_INVALID);
 496         }
 497 
 498         /* Now the actual secret derivation */
 499         if (!is_tls) {
 500                 soft_ssl3_churn(pmsecret, pmlen, random_data->pClientRandom,
 501                     ClientRandomLen, random_data->pServerRandom,
 502                     ServerRandomLen, 3, ssl_master_secret);
 503         } else {
 504                 soft_tls_prf(pmsecret, pmlen, TLS_MASTER_SECRET_LABEL,
 505                     TLS_MASTER_SECRET_LABEL_LEN, random_data->pClientRandom,
 506                     ClientRandomLen, random_data->pServerRandom,
 507                     ServerRandomLen, ssl_master_secret, 48);
 508         }
 509 
 510         /*
 511          * The object creation attributes need to be in one contiguous
 512          * array. In addition to the attrs from the application supplied
 513          * pTemplates, We need to add the class, type, value, valuelen and
 514          * CKA_DERIVE.
 515          * In the most likely case, the application passes between zero and
 516          * handful of attributes, We optimize for that case by allocating
 517          * the new template on the stack. Oherwise we malloc() it.
 518          */
 519 
 520         newattrcount = ulAttributeCount + 4;
 521         if (newattrcount > MAX_DEFAULT_ATTRS) {
 522                 new_tmpl = malloc(sizeof (CK_ATTRIBUTE) * newattrcount);
 523 
 524                 if (new_tmpl == NULL)
 525                         return (CKR_HOST_MEMORY);
 526 
 527                 new_tmpl_allocated = B_TRUE;
 528         } else
 529                 new_tmpl = obj_tmpl;
 530 
 531         /*
 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.
 535          */
 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;
 548 
 549         /* Any attributes left? */
 550         if (ulAttributeCount > 0) {
 551 
 552                 /* Validate the default class and type attributes */
 553                 for (i = 0; i < ulAttributeCount; i++) {
 554                         /* The caller is responsible for proper alignment */
 555                         if ((pTemplate[i].type == CKA_CLASS) &&
 556                             (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) !=
 557                             CKO_SECRET_KEY)) {
 558                                 rv = CKR_TEMPLATE_INCONSISTENT;
 559                                 goto out;
 560                         }
 561                         if ((pTemplate[i].type == CKA_KEY_TYPE) &&
 562                             (*((CK_KEY_TYPE *)pTemplate[i].pValue) !=
 563                             CKK_GENERIC_SECRET)) {
 564                                 rv = CKR_TEMPLATE_INCONSISTENT;
 565                                 goto out;
 566                         }
 567                 }
 568                 bcopy(pTemplate, &new_tmpl[4],
 569                     ulAttributeCount * sizeof (CK_ATTRIBUTE));
 570         }
 571 
 572         rv = soft_add_derived_key(new_tmpl, newattrcount, phKey, sp, basekey_p);
 573 out:
 574         if (new_tmpl_allocated)
 575                 free(new_tmpl);
 576 
 577         return (rv);
 578 }
 579 
 580 /*
 581  * soft_ssl3_key_and_mac_derive()
 582  *
 583  * Arguments:
 584  * . session_p
 585  * . mech_p:    key derivation mechanism. the mechanism parameter carries the
 586  *              client and mastter random from the Hello handshake messages,
 587  *              the specification of the key and IV sizes, and the location
 588  *              for the resulting keys and IVs.
 589  * . basekey_p: The master secret key.
 590  * . pTemplate & ulAttributeCount: Any extra attributes for the key to be
 591  *              created.
 592  *
 593  * Description:
 594  *      Derive the SSL key material (Client and server MAC secrets, symmetric
 595  *      keys and IVs), from the master secret and the client
 596  *      and server random.
 597  *      First a keyblock is generated usining the following formula:
 598  *      key_block =
 599  *              MD5(master_secret + SHA(`A' + master_secret +
 600  *                                      ServerHello.random +
 601  *                                      ClientHello.random)) +
 602  *              MD5(master_secret + SHA(`BB' + master_secret +
 603  *                                      ServerHello.random +
 604  *                                      ClientHello.random)) +
 605  *              MD5(master_secret + SHA(`CCC' + master_secret +
 606  *                                      ServerHello.random +
 607  *                                      ClientHello.random)) + [...];
 608  *
 609  *      In TLS 1.0 (a.k.a. SSL 3.1), key_block =
 610  *          PRF(master_secret, "key expansion",
 611  *              ServerHello.random + ClientHello.random)
 612  *
 613  *      Then the keys materials are taken from the keyblock.
 614  */
 615 
 616 CK_RV
 617 soft_ssl_key_and_mac_derive(soft_session_t *sp, CK_MECHANISM_PTR mech,
 618     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
 619     CK_ULONG ulAttributeCount)
 620 {
 621         uchar_t *msecret = OBJ_SEC_VALUE(basekey_p);
 622 #ifdef  __sparcv9
 623         /* LINTED */
 624         uint_t mslen = (uint_t)OBJ_SEC_VALUE_LEN(basekey_p);
 625 #else   /* __sparcv9 */
 626         uint_t mslen = OBJ_SEC_VALUE_LEN(basekey_p);
 627 #endif  /* __sparcv9 */
 628         CK_SSL3_KEY_MAT_PARAMS *km_params;
 629         CK_SSL3_RANDOM_DATA *random_data;
 630         CK_SSL3_KEY_MAT_OUT *kmo;
 631         uchar_t key_block[MAX_KEYBLOCK], *kb, *export_keys = NULL;
 632         CK_OBJECT_CLASS class = CKO_SECRET_KEY;
 633         CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
 634         CK_BBOOL true = TRUE;
 635         CK_ATTRIBUTE obj_tmpl[MAX_DEFAULT_ATTRS];
 636         CK_ATTRIBUTE_PTR new_tmpl;
 637         ulong_t newattrcount, mac_key_bytes, secret_key_bytes, iv_bytes;
 638         ulong_t extra_attr_count;
 639         uint_t size;
 640         int rounds, n = 0;
 641         boolean_t new_tmpl_allocated = B_FALSE, isExport;
 642         CK_RV rv = CKR_OK;
 643         uint_t ClientRandomLen, ServerRandomLen;
 644 
 645         /* Check the validity of the mechanism's parameter */
 646 
 647         km_params = (CK_SSL3_KEY_MAT_PARAMS *)mech->pParameter;
 648 
 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);
 653 
 654         isExport = (km_params->bIsExport == TRUE);
 655 
 656         random_data = &km_params->RandomInfo;
 657 #ifdef  __sparcv9
 658         /* LINTED */
 659         ClientRandomLen = (uint_t)random_data->ulClientRandomLen;
 660         /* LINTED */
 661         ServerRandomLen = (uint_t)random_data->ulServerRandomLen;
 662 #else   /* __sparcv9 */
 663         ClientRandomLen = random_data->ulClientRandomLen;
 664         ServerRandomLen = random_data->ulServerRandomLen;
 665 #endif  /* __sparcv9 */
 666 
 667         if (random_data->pClientRandom == NULL_PTR || ClientRandomLen == 0 ||
 668             random_data->pServerRandom == NULL_PTR || ServerRandomLen == 0) {
 669                 return (CKR_MECHANISM_PARAM_INVALID);
 670         }
 671 
 672         mac_key_bytes = km_params->ulMacSizeInBits / 8;
 673         secret_key_bytes = km_params->ulKeySizeInBits / 8;
 674         iv_bytes = km_params->ulIVSizeInBits / 8;
 675 
 676         if ((iv_bytes > 0) &&
 677             ((kmo->pIVClient == NULL) || (kmo->pIVServer == NULL)))
 678                 return (CKR_MECHANISM_PARAM_INVALID);
 679 
 680         /*
 681          * For exportable ciphersuites, the IV's aren't taken from the
 682          * key block. They are directly derived from the client and
 683          * server random data.
 684          * For SSL3.0:
 685          *      client_write_IV = MD5(ClientHello.random + ServerHello.random);
 686          *      server_write_IV = MD5(ServerHello.random + ClientHello.random);
 687          * For TLS1.0:
 688          *      iv_block = PRF("", "IV block", client_random +
 689          *                      server_random)[0..15]
 690          *      client_write_IV = iv_block[0..7]
 691          *      server_write_IV = iv_block[8..15]
 692          */
 693         if ((isExport) && (iv_bytes > 0)) {
 694 
 695                 if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
 696                         MD5_CTX exp_md5_ctx;
 697 
 698                         if (iv_bytes > MD5_HASH_SIZE)
 699                                 return (CKR_MECHANISM_PARAM_INVALID);
 700 
 701                         MD5Init(&exp_md5_ctx);
 702                         MD5Update(&exp_md5_ctx, random_data->pClientRandom,
 703                             ClientRandomLen);
 704                         MD5Update(&exp_md5_ctx, random_data->pServerRandom,
 705                             ServerRandomLen);
 706 
 707                         /* there's room in key_block. use it */
 708                         MD5Final(key_block, &exp_md5_ctx);
 709                         bcopy(key_block, kmo->pIVClient, iv_bytes);
 710 
 711                         MD5Init(&exp_md5_ctx);
 712                         MD5Update(&exp_md5_ctx, random_data->pServerRandom,
 713                             ServerRandomLen);
 714                         MD5Update(&exp_md5_ctx, random_data->pClientRandom,
 715                             ClientRandomLen);
 716                         MD5Final(key_block, &exp_md5_ctx);
 717                         bcopy(key_block, kmo->pIVServer, iv_bytes);
 718                 } else {
 719                         uchar_t iv_block[16];
 720 
 721                         if (iv_bytes != 8)
 722                                 return (CKR_MECHANISM_PARAM_INVALID);
 723 
 724                         soft_tls_prf(NULL, 0, TLS_IV_BLOCK_LABEL,
 725                             TLS_IV_BLOCK_LABEL_LEN,
 726                             random_data->pClientRandom, ClientRandomLen,
 727                             random_data->pServerRandom, ServerRandomLen,
 728                             iv_block, 16);
 729                         bcopy(iv_block, kmo->pIVClient, 8);
 730                         bcopy(iv_block + 8, kmo->pIVServer, 8);
 731                 }
 732                 /* so we won't allocate a key_block bigger than needed */
 733                 iv_bytes = 0;
 734         }
 735 
 736         /* Now the actual secret derivation */
 737 
 738 #ifdef  __sparcv9
 739         /* LINTED */
 740         size = (uint_t)((mac_key_bytes + secret_key_bytes + iv_bytes) * 2);
 741 #else   /* __sparcv9 */
 742         size = (mac_key_bytes + secret_key_bytes + iv_bytes) * 2;
 743 #endif  /* __sparcv9 */
 744 
 745         /* Need to handle this better */
 746         if (size > MAX_KEYBLOCK)
 747                 return (CKR_MECHANISM_PARAM_INVALID);
 748 
 749         rounds = howmany(size, MD5_HASH_SIZE);
 750 
 751         kb = key_block;
 752 
 753         if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
 754                 soft_ssl3_churn(msecret, mslen, random_data->pServerRandom,
 755                     ServerRandomLen, random_data->pClientRandom,
 756                     ClientRandomLen, rounds, kb);
 757         } else {
 758                 soft_tls_prf(msecret, mslen, TLS_KEY_EXPANSION_LABEL,
 759                     TLS_KEY_EXPANSION_LABEL_LEN,
 760                     random_data->pServerRandom, ServerRandomLen,
 761                     random_data->pClientRandom, ClientRandomLen,
 762                     kb, size);
 763         }
 764 
 765         /* Now create the objects */
 766 
 767         kmo->hClientMacSecret = CK_INVALID_HANDLE;
 768         kmo->hServerMacSecret = CK_INVALID_HANDLE;
 769         kmo->hClientKey = CK_INVALID_HANDLE;
 770         kmo->hServerKey = CK_INVALID_HANDLE;
 771 
 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;
 792 
 793                 rv = soft_add_derived_key(obj_tmpl, 6,
 794                     &(kmo->hClientMacSecret), sp, basekey_p);
 795 
 796                 if (rv != CKR_OK)
 797                         goto out_err;
 798 
 799                 kb += mac_key_bytes;
 800 
 801                 obj_tmpl[5].pValue = kb;
 802                 rv = soft_add_derived_key(obj_tmpl, 6,
 803                     &(kmo->hServerMacSecret), sp, basekey_p);
 804 
 805                 if (rv != CKR_OK)
 806                         goto out_err;
 807 
 808                 kb += mac_key_bytes;
 809         }
 810 
 811         /* Then the symmetric ciphers keys */
 812 
 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);
 817 
 818                 if (new_tmpl == NULL)
 819                         return (CKR_HOST_MEMORY);
 820 
 821                 new_tmpl_allocated = B_TRUE;
 822         } else
 823                 new_tmpl = obj_tmpl;
 824 
 825         new_tmpl[n].type = CKA_CLASS;
 826         new_tmpl[n].pValue = &class;        /* CKO_SECRET_KEY */
 827         new_tmpl[n].ulValueLen = sizeof (class);
 828         ++n;
 829         /*
 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.
 833          */
 834         if (secret_key_bytes == 0) {
 835                 new_tmpl[n].type = CKA_KEY_TYPE;
 836                 new_tmpl[n].pValue = &keyType;      /* CKK_GENERIC_SECRET */
 837                 new_tmpl[n].ulValueLen = sizeof (keyType);
 838                 n++;
 839         }
 840         new_tmpl[n].type = CKA_DERIVE;
 841         new_tmpl[n].pValue = &true;
 842         new_tmpl[n].ulValueLen = sizeof (true);
 843         n++;
 844         new_tmpl[n].type = CKA_ENCRYPT;
 845         new_tmpl[n].pValue = &true;
 846         new_tmpl[n].ulValueLen = sizeof (true);
 847         n++;
 848         new_tmpl[n].type = CKA_DECRYPT;
 849         new_tmpl[n].pValue = &true;
 850         new_tmpl[n].ulValueLen = sizeof (true);
 851         n++;
 852         new_tmpl[n].type = CKA_VALUE;
 853         new_tmpl[n].pValue = NULL;
 854         new_tmpl[n].ulValueLen = 0;
 855 
 856         if (secret_key_bytes > 0) {
 857                 if (isExport) {
 858                         if (secret_key_bytes > MD5_HASH_SIZE) {
 859                                 rv = CKR_MECHANISM_PARAM_INVALID;
 860                                 goto out_err;
 861                         }
 862                         if ((export_keys = malloc(2 * MD5_HASH_SIZE)) == NULL) {
 863                                 rv = CKR_HOST_MEMORY;
 864                                 goto out_err;
 865                         }
 866 #ifdef  __sparcv9
 867                         /* LINTED */
 868                         soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
 869 #else   /* __sparcv9 */
 870                         soft_ssl_weaken_key(mech, kb, secret_key_bytes,
 871 #endif  /* __sparcv9 */
 872                             random_data->pClientRandom, ClientRandomLen,
 873                             random_data->pServerRandom, ServerRandomLen,
 874                             export_keys, B_TRUE);
 875                         new_tmpl[n].pValue = export_keys;
 876                         new_tmpl[n].ulValueLen = MD5_HASH_SIZE;
 877                 } else {
 878                         new_tmpl[n].pValue = kb;
 879                         new_tmpl[n].ulValueLen = secret_key_bytes;
 880                 }
 881         }
 882 
 883         if (ulAttributeCount > 0)
 884                 bcopy(pTemplate, &new_tmpl[extra_attr_count],
 885                     ulAttributeCount * sizeof (CK_ATTRIBUTE));
 886 
 887         rv = soft_add_derived_key(new_tmpl, newattrcount,
 888             &(kmo->hClientKey), sp, basekey_p);
 889 
 890         if (rv != CKR_OK)
 891                 goto out_err;
 892 
 893         kb += secret_key_bytes;
 894 
 895         if (secret_key_bytes > 0) {
 896                 if (isExport) {
 897 #ifdef  __sparcv9
 898                         /* LINTED */
 899                         soft_ssl_weaken_key(mech, kb, (uint_t)secret_key_bytes,
 900 #else   /* __sparcv9 */
 901                         soft_ssl_weaken_key(mech, kb, secret_key_bytes,
 902 #endif  /* __sparcv9 */
 903                             random_data->pServerRandom, ServerRandomLen,
 904                             random_data->pClientRandom, ClientRandomLen,
 905                             export_keys + MD5_HASH_SIZE, B_FALSE);
 906                         new_tmpl[n].pValue = export_keys + MD5_HASH_SIZE;
 907                 } else
 908                         new_tmpl[n].pValue = kb;
 909         }
 910 
 911         rv = soft_add_derived_key(new_tmpl, newattrcount,
 912             &(kmo->hServerKey), sp, basekey_p);
 913 
 914         if (rv != CKR_OK)
 915                 goto out_err;
 916 
 917         kb += secret_key_bytes;
 918 
 919         /* Finally, the IVs */
 920         if (iv_bytes > 0) {
 921                 bcopy(kb, kmo->pIVClient, iv_bytes);
 922                 kb += iv_bytes;
 923                 bcopy(kb, kmo->pIVServer, iv_bytes);
 924         }
 925 
 926         if (new_tmpl_allocated)
 927                 free(new_tmpl);
 928 
 929         freezero(export_keys, 2 * MD5_HASH_SIZE);
 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         freezero(export_keys, 2 * MD5_HASH_SIZE);
 959 
 960         return (rv);
 961 }
 962 
 963 /*
 964  * Add the derived key to the session, and, if it's a token object,
 965  * write it to the token.
 966  */
 967 static CK_RV
 968 soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount,
 969     CK_OBJECT_HANDLE_PTR phKey, soft_session_t *sp, soft_object_t *basekey_p)
 970 {
 971         CK_RV rv;
 972         soft_object_t *secret_key;
 973 
 974         if ((secret_key = calloc(1, sizeof (soft_object_t))) == NULL) {
 975                 return (CKR_HOST_MEMORY);
 976         }
 977 
 978         if (((rv = soft_build_secret_key_object(tmpl, attrcount, secret_key,
 979             SOFT_CREATE_OBJ_INT, 0, (CK_KEY_TYPE)~0UL)) != CKR_OK) ||
 980             ((rv = soft_pin_expired_check(secret_key)) != CKR_OK) ||
 981             ((rv = soft_object_write_access_check(sp, secret_key)) != CKR_OK)) {
 982 
 983                 free(secret_key);
 984                 return (rv);
 985         }
 986 
 987         /* Set the sensitivity and extractability attributes as a needed */
 988         soft_derive_enforce_flags(basekey_p, secret_key);
 989 
 990         /* Initialize the rest of stuffs in soft_object_t. */
 991         (void) pthread_mutex_init(&secret_key->object_mutex, NULL);
 992         secret_key->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
 993 
 994         /* ... and, if it needs to persist, write on the token */
 995         if (IS_TOKEN_OBJECT(secret_key)) {
 996                 secret_key->session_handle = (CK_SESSION_HANDLE)NULL;
 997                 soft_add_token_object_to_slot(secret_key);
 998                 rv = soft_put_object_to_keystore(secret_key);
 999                 if (rv != CKR_OK) {
1000                         soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
1001                         return (rv);
1002                 }
1003                 *phKey = (CK_OBJECT_HANDLE)secret_key;
1004 
1005                 return (CKR_OK);
1006         }
1007 
1008         /* Add the new object to the session's object list. */
1009         soft_add_object_to_session(secret_key, sp);
1010         secret_key->session_handle = (CK_SESSION_HANDLE)sp;
1011 
1012         *phKey = (CK_OBJECT_HANDLE)secret_key;
1013 
1014         return (rv);
1015 }
1016 
1017 /*
1018  * Delete the derived key from the session, and, if it's a token object,
1019  * remove it from the token.
1020  */
1021 static void
1022 soft_delete_derived_key(soft_session_t *sp, soft_object_t *key)
1023 {
1024         /* session_handle is the creating session. It's NULL for token objs */
1025 
1026         if (IS_TOKEN_OBJECT(key))
1027                 soft_delete_token_object(key, B_FALSE, B_FALSE);
1028         else
1029                 soft_delete_object(sp, key, B_FALSE, B_FALSE);
1030 }
1031 
1032 /*
1033  * soft_ssl_weaken_key()
1034  * Reduce the key length to an exportable size.
1035  * For SSL3.0:
1036  *      final_client_write_key = MD5(client_write_key +
1037  *                                ClientHello.random +
1038  *                                ServerHello.random);
1039  *      final_server_write_key = MD5(server_write_key +
1040  *                                ServerHello.random +
1041  *                                ClientHello.random);
1042  * For TLS1.0:
1043  *      final_client_write_key = PRF(SecurityParameters.client_write_key,
1044  *                                  "client write key",
1045  *                                  SecurityParameters.client_random +
1046  *                                  SecurityParameters.server_random)[0..15];
1047  *      final_server_write_key = PRF(SecurityParameters.server_write_key,
1048  *                                  "server write key",
1049  *                                  SecurityParameters.client_random +
1050  *                                  SecurityParameters.server_random)[0..15];
1051  */
1052 static void
1053 soft_ssl_weaken_key(CK_MECHANISM_PTR mech, uchar_t *secret, uint_t secretlen,
1054     uchar_t *rand1, uint_t rand1len, uchar_t *rand2, uint_t rand2len,
1055     uchar_t *result, boolean_t isclient)
1056 {
1057         MD5_CTX exp_md5_ctx;
1058         uchar_t *label;
1059         uint_t labellen;
1060 
1061         if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE) {
1062                 MD5Init(&exp_md5_ctx);
1063                 MD5Update(&exp_md5_ctx, secret, secretlen);
1064                 MD5Update(&exp_md5_ctx, rand1, rand1len);
1065                 MD5Update(&exp_md5_ctx, rand2, rand2len);
1066                 MD5Final(result, &exp_md5_ctx);
1067         } else {
1068                 if (isclient) {
1069                         label = TLS_CLIENT_KEY_LABEL;
1070                         labellen = TLS_CLIENT_KEY_LABEL_LEN;
1071                         soft_tls_prf(secret, secretlen, label, labellen,
1072                             rand1, rand1len, rand2, rand2len, result, 16);
1073                 } else {
1074                         label = TLS_SERVER_KEY_LABEL;
1075                         labellen = TLS_SERVER_KEY_LABEL_LEN;
1076                         soft_tls_prf(secret, secretlen, label, labellen,
1077                             rand2, rand2len, rand1, rand1len, result, 16);
1078                 }
1079         }
1080 }