Home | History | Annotate | Download | only in ssl
      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2  * License, v. 2.0. If a copy of the MPL was not distributed with this
      3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 #include "ssl.h"
      5 #include "sslimpl.h"
      6 #include "sslproto.h"
      7 
      8 static const char *
      9 ssl_GetCompressionMethodName(SSLCompressionMethod compression)
     10 {
     11     switch (compression) {
     12     case ssl_compression_null:
     13 	return "NULL";
     14 #ifdef NSS_ENABLE_ZLIB
     15     case ssl_compression_deflate:
     16 	return "DEFLATE";
     17 #endif
     18     default:
     19 	return "???";
     20     }
     21 }
     22 
     23 SECStatus
     24 SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
     25 {
     26     sslSocket *      ss;
     27     SSLChannelInfo   inf;
     28     sslSessionID *   sid;
     29     PRBool           enoughFirstHsDone = PR_FALSE;
     30 
     31     if (!info || len < sizeof inf.length) {
     32 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
     33 	return SECFailure;
     34     }
     35 
     36     ss = ssl_FindSocket(fd);
     37     if (!ss) {
     38 	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo",
     39 		 SSL_GETPID(), fd));
     40 	return SECFailure;
     41     }
     42 
     43     memset(&inf, 0, sizeof inf);
     44     inf.length = PR_MIN(sizeof inf, len);
     45 
     46     if (ss->firstHsDone) {
     47 	enoughFirstHsDone = PR_TRUE;
     48     } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
     49 	       ssl3_CanFalseStart(ss)) {
     50 	enoughFirstHsDone = PR_TRUE;
     51     }
     52 
     53     if (ss->opt.useSecurity && enoughFirstHsDone) {
     54         sid = ss->sec.ci.sid;
     55 	inf.protocolVersion  = ss->version;
     56 	inf.authKeyBits      = ss->sec.authKeyBits;
     57 	inf.keaKeyBits       = ss->sec.keaKeyBits;
     58 	if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
     59 	    inf.cipherSuite           = ss->sec.cipherType | 0xff00;
     60 	    inf.compressionMethod     = ssl_compression_null;
     61 	    inf.compressionMethodName = "N/A";
     62 	} else if (ss->ssl3.initialized) { 	/* SSL3 and TLS */
     63 	    ssl_GetSpecReadLock(ss);
     64 	    /* XXX  The cipher suite should be in the specs and this
     65 	     * function should get it from cwSpec rather than from the "hs".
     66 	     * See bug 275744 comment 69 and bug 766137.
     67 	     */
     68 	    inf.cipherSuite           = ss->ssl3.hs.cipher_suite;
     69 	    inf.compressionMethod     = ss->ssl3.cwSpec->compression_method;
     70 	    ssl_ReleaseSpecReadLock(ss);
     71 	    inf.compressionMethodName =
     72 		ssl_GetCompressionMethodName(inf.compressionMethod);
     73 	}
     74 	if (sid) {
     75 	    inf.creationTime   = sid->creationTime;
     76 	    inf.lastAccessTime = sid->lastAccessTime;
     77 	    inf.expirationTime = sid->expirationTime;
     78 	    if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
     79 	        inf.sessionIDLength = SSL2_SESSIONID_BYTES;
     80 		memcpy(inf.sessionID, sid->u.ssl2.sessionID,
     81 		       SSL2_SESSIONID_BYTES);
     82 	    } else {
     83 		unsigned int sidLen = sid->u.ssl3.sessionIDLength;
     84 	        sidLen = PR_MIN(sidLen, sizeof inf.sessionID);
     85 	        inf.sessionIDLength = sidLen;
     86 		memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen);
     87 	    }
     88 	}
     89     }
     90 
     91     memcpy(info, &inf, inf.length);
     92 
     93     return SECSuccess;
     94 }
     95 
     96 
     97 #define CS(x) x, #x
     98 #define CK(x) x | 0xff00, #x
     99 
    100 #define S_DSA   "DSA", ssl_auth_dsa
    101 #define S_RSA	"RSA", ssl_auth_rsa
    102 #define S_KEA   "KEA", ssl_auth_kea
    103 #define S_ECDSA "ECDSA", ssl_auth_ecdsa
    104 
    105 #define K_DHE	"DHE", kt_dh
    106 #define K_RSA	"RSA", kt_rsa
    107 #define K_KEA	"KEA", kt_kea
    108 #define K_ECDH	"ECDH", kt_ecdh
    109 #define K_ECDHE	"ECDHE", kt_ecdh
    110 
    111 #define C_SEED 	"SEED", calg_seed
    112 #define C_CAMELLIA	"CAMELLIA", calg_camellia
    113 #define C_AES	"AES", calg_aes
    114 #define C_RC4	"RC4", calg_rc4
    115 #define C_RC2	"RC2", calg_rc2
    116 #define C_DES	"DES", calg_des
    117 #define C_3DES	"3DES", calg_3des
    118 #define C_NULL  "NULL", calg_null
    119 #define C_SJ 	"SKIPJACK", calg_sj
    120 
    121 #define B_256	256, 256, 256
    122 #define B_128	128, 128, 128
    123 #define B_3DES  192, 156, 112
    124 #define B_SJ     96,  80,  80
    125 #define B_DES    64,  56,  56
    126 #define B_56    128,  56,  56
    127 #define B_40    128,  40,  40
    128 #define B_0  	  0,   0,   0
    129 
    130 #define M_SHA256 "SHA256", ssl_hmac_sha256, 256
    131 #define M_SHA	"SHA1", ssl_mac_sha, 160
    132 #define M_MD5	"MD5",  ssl_mac_md5, 128
    133 
    134 static const SSLCipherSuiteInfo suiteInfo[] = {
    135 /* <------ Cipher suite --------------------> <auth> <KEA>  <bulk cipher> <MAC> <FIPS> */
    136 {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
    137 {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
    138 {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),   S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, },
    139 {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA),      S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, },
    140 {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA),      S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, },
    141 {0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA),     S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
    142 {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256),       S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0, },
    143 {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA),          S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0, },
    144 
    145 {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
    146 {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
    147 {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA),          S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
    148 {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256),   S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
    149 {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA),      S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
    150 {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA),      S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
    151 {0,CS(TLS_RSA_WITH_SEED_CBC_SHA),             S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, },
    152 {0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA),     S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
    153 {0,CS(SSL_RSA_WITH_RC4_128_SHA),              S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0, },
    154 {0,CS(SSL_RSA_WITH_RC4_128_MD5),              S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, },
    155 {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256),       S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0, },
    156 {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA),          S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0, },
    157 
    158 {0,CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA),     S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
    159 {0,CS(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA),     S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
    160 {0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA),    S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1, },
    161 {0,CS(SSL_RSA_WITH_3DES_EDE_CBC_SHA),         S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
    162 
    163 {0,CS(SSL_DHE_RSA_WITH_DES_CBC_SHA),          S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, },
    164 {0,CS(SSL_DHE_DSS_WITH_DES_CBC_SHA),          S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, },
    165 {0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA),         S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1, },
    166 {0,CS(SSL_RSA_WITH_DES_CBC_SHA),              S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0, },
    167 
    168 {0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA),    S_RSA, K_RSA, C_RC4, B_56,  M_SHA, 0, 1, 0, },
    169 {0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA),   S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0, },
    170 {0,CS(SSL_RSA_EXPORT_WITH_RC4_40_MD5),        S_RSA, K_RSA, C_RC4, B_40,  M_MD5, 0, 1, 0, },
    171 {0,CS(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5),    S_RSA, K_RSA, C_RC2, B_40,  M_MD5, 0, 1, 0, },
    172 {0,CS(TLS_RSA_WITH_NULL_SHA256),              S_RSA, K_RSA, C_NULL,B_0,   M_SHA256, 0, 1, 0, },
    173 {0,CS(SSL_RSA_WITH_NULL_SHA),                 S_RSA, K_RSA, C_NULL,B_0,   M_SHA, 0, 1, 0, },
    174 {0,CS(SSL_RSA_WITH_NULL_MD5),                 S_RSA, K_RSA, C_NULL,B_0,   M_MD5, 0, 1, 0, },
    175 
    176 #ifdef NSS_ENABLE_ECC
    177 /* ECC cipher suites */
    178 {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA),          S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
    179 {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA),       S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
    180 {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA),  S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
    181 {0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA),   S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, },
    182 {0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA),   S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, },
    183 
    184 {0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA),         S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, },
    185 {0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),      S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
    186 {0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
    187 {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),  S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, },
    188 {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
    189 {0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),  S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, },
    190 
    191 {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA),            S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
    192 {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA),         S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
    193 {0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA),    S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
    194 {0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA),     S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, },
    195 {0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA),     S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, },
    196 
    197 {0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA),           S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, },
    198 {0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA),        S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
    199 {0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),   S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
    200 {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),    S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, },
    201 {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
    202 {0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),    S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, },
    203 #endif /* NSS_ENABLE_ECC */
    204 
    205 /* SSL 2 table */
    206 {0,CK(SSL_CK_RC4_128_WITH_MD5),               S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, },
    207 {0,CK(SSL_CK_RC2_128_CBC_WITH_MD5),           S_RSA, K_RSA, C_RC2, B_128, M_MD5, 0, 0, 0, },
    208 {0,CK(SSL_CK_DES_192_EDE3_CBC_WITH_MD5),      S_RSA, K_RSA, C_3DES,B_3DES,M_MD5, 0, 0, 0, },
    209 {0,CK(SSL_CK_DES_64_CBC_WITH_MD5),            S_RSA, K_RSA, C_DES, B_DES, M_MD5, 0, 0, 0, },
    210 {0,CK(SSL_CK_RC4_128_EXPORT40_WITH_MD5),      S_RSA, K_RSA, C_RC4, B_40,  M_MD5, 0, 1, 0, },
    211 {0,CK(SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5),  S_RSA, K_RSA, C_RC2, B_40,  M_MD5, 0, 1, 0, }
    212 };
    213 
    214 #define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0]))
    215 
    216 
    217 SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
    218                                  SSLCipherSuiteInfo *info, PRUintn len)
    219 {
    220     unsigned int i;
    221 
    222     len = PR_MIN(len, sizeof suiteInfo[0]);
    223     if (!info || len < sizeof suiteInfo[0].length) {
    224 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    225     	return SECFailure;
    226     }
    227     for (i = 0; i < NUM_SUITEINFOS; i++) {
    228     	if (suiteInfo[i].cipherSuite == cipherSuite) {
    229 	    memcpy(info, &suiteInfo[i], len);
    230 	    info->length = len;
    231 	    return SECSuccess;
    232 	}
    233     }
    234     PORT_SetError(SEC_ERROR_INVALID_ARGS);
    235     return SECFailure;
    236 }
    237 
    238 /* This function might be a candidate to be public.
    239  * Disables all export ciphers in the default set of enabled ciphers.
    240  */
    241 SECStatus
    242 SSL_DisableDefaultExportCipherSuites(void)
    243 {
    244     const SSLCipherSuiteInfo * pInfo = suiteInfo;
    245     unsigned int i;
    246     SECStatus rv;
    247 
    248     for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
    249     	if (pInfo->isExportable) {
    250 	    rv = SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE);
    251 	    PORT_Assert(rv == SECSuccess);
    252 	}
    253     }
    254     return SECSuccess;
    255 }
    256 
    257 /* This function might be a candidate to be public,
    258  * except that it takes an sslSocket pointer as an argument.
    259  * A Public version would take a PRFileDesc pointer.
    260  * Disables all export ciphers in the default set of enabled ciphers.
    261  */
    262 SECStatus
    263 SSL_DisableExportCipherSuites(PRFileDesc * fd)
    264 {
    265     const SSLCipherSuiteInfo * pInfo = suiteInfo;
    266     unsigned int i;
    267     SECStatus rv;
    268 
    269     for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
    270     	if (pInfo->isExportable) {
    271 	    rv = SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE);
    272 	    PORT_Assert(rv == SECSuccess);
    273 	}
    274     }
    275     return SECSuccess;
    276 }
    277 
    278 /* Tells us if the named suite is exportable
    279  * returns false for unknown suites.
    280  */
    281 PRBool
    282 SSL_IsExportCipherSuite(PRUint16 cipherSuite)
    283 {
    284     unsigned int i;
    285     for (i = 0; i < NUM_SUITEINFOS; i++) {
    286     	if (suiteInfo[i].cipherSuite == cipherSuite) {
    287 	    return (PRBool)(suiteInfo[i].isExportable);
    288 	}
    289     }
    290     return PR_FALSE;
    291 }
    292 
    293 SECItem*
    294 SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
    295 {
    296     SECItem *sniName = NULL;
    297     sslSocket *ss;
    298     char *name = NULL;
    299 
    300     ss = ssl_FindSocket(fd);
    301     if (!ss) {
    302 	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
    303 		 SSL_GETPID(), fd));
    304 	return NULL;
    305     }
    306 
    307     if (ss->sec.isServer) {
    308         if (ss->version > SSL_LIBRARY_VERSION_3_0 &&
    309             ss->ssl3.initialized) { /* TLS */
    310             SECItem *crsName;
    311             ssl_GetSpecReadLock(ss); /*********************************/
    312             crsName = &ss->ssl3.cwSpec->srvVirtName;
    313             if (crsName->data) {
    314                 sniName = SECITEM_DupItem(crsName);
    315             }
    316             ssl_ReleaseSpecReadLock(ss); /*----------------------------*/
    317         }
    318         return sniName;
    319     }
    320     name = SSL_RevealURL(fd);
    321     if (name) {
    322         sniName = PORT_ZNew(SECItem);
    323         if (!sniName) {
    324             PORT_Free(name);
    325             return NULL;
    326         }
    327         sniName->data = (void*)name;
    328         sniName->len  = PORT_Strlen(name);
    329     }
    330     return sniName;
    331 }
    332 
    333 SECStatus
    334 SSL_ExportKeyingMaterial(PRFileDesc *fd,
    335                          const char *label, unsigned int labelLen,
    336                          PRBool hasContext,
    337                          const unsigned char *context, unsigned int contextLen,
    338                          unsigned char *out, unsigned int outLen)
    339 {
    340     sslSocket *ss;
    341     unsigned char *val = NULL;
    342     unsigned int valLen, i;
    343     SECStatus rv = SECFailure;
    344 
    345     ss = ssl_FindSocket(fd);
    346     if (!ss) {
    347 	SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
    348 		 SSL_GETPID(), fd));
    349 	return SECFailure;
    350     }
    351 
    352     ssl_GetRecvBufLock(ss);
    353     ssl_GetSSL3HandshakeLock(ss);
    354 
    355     if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
    356 	PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
    357 	ssl_ReleaseSSL3HandshakeLock(ss);
    358 	ssl_ReleaseRecvBufLock(ss);
    359 	return SECFailure;
    360     }
    361 
    362     /* construct PRF arguments */
    363     valLen = SSL3_RANDOM_LENGTH * 2;
    364     if (hasContext) {
    365 	valLen += 2 /* PRUint16 length */ + contextLen;
    366     }
    367     val = PORT_Alloc(valLen);
    368     if (!val) {
    369 	ssl_ReleaseSSL3HandshakeLock(ss);
    370 	ssl_ReleaseRecvBufLock(ss);
    371 	return SECFailure;
    372     }
    373     i = 0;
    374 
    375     PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
    376     i += SSL3_RANDOM_LENGTH;
    377     PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
    378     i += SSL3_RANDOM_LENGTH;
    379 
    380     if (hasContext) {
    381 	val[i++] = contextLen >> 8;
    382 	val[i++] = contextLen;
    383 	PORT_Memcpy(val + i, context, contextLen);
    384 	i += contextLen;
    385     }
    386     PORT_Assert(i == valLen);
    387 
    388     /* Allow TLS keying material to be exported sooner, when the master
    389      * secret is available and we have sent ChangeCipherSpec.
    390      */
    391     ssl_GetSpecReadLock(ss);
    392     if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) {
    393 	PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
    394 	rv = SECFailure;
    395     } else {
    396 	rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val,
    397 					 valLen, out, outLen);
    398     }
    399     ssl_ReleaseSpecReadLock(ss);
    400     ssl_ReleaseSSL3HandshakeLock(ss);
    401     ssl_ReleaseRecvBufLock(ss);
    402 
    403     PORT_ZFree(val, valLen);
    404     return rv;
    405 }
    406