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