1diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2--- a/nss/lib/ssl/ssl3con.c 2014-01-17 17:55:01.518095989 -0800 3+++ b/nss/lib/ssl/ssl3con.c 2014-01-17 17:55:19.158389328 -0800 4@@ -7199,6 +7199,85 @@ done: 5 return rv; 6 } 7 8+/* 9+ * attempt to restart the handshake after asynchronously handling 10+ * a request for the client's certificate. 11+ * 12+ * inputs: 13+ * cert Client cert chosen by application. 14+ * Note: ssl takes this reference, and does not bump the 15+ * reference count. The caller should drop its reference 16+ * without calling CERT_DestroyCert after calling this function. 17+ * 18+ * key Private key associated with cert. This function takes 19+ * ownership of the private key, so the caller should drop its 20+ * reference without destroying the private key after this 21+ * function returns. 22+ * 23+ * certChain DER-encoded certs, client cert and its signers. 24+ * Note: ssl takes this reference, and does not copy the chain. 25+ * The caller should drop its reference without destroying the 26+ * chain. SSL will free the chain when it is done with it. 27+ * 28+ * Return value: XXX 29+ * 30+ * XXX This code only works on the initial handshake on a connection, XXX 31+ * It does not work on a subsequent handshake (redo). 32+ * 33+ * Caller holds 1stHandshakeLock. 34+ */ 35+SECStatus 36+ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, 37+ CERTCertificate * cert, 38+ SECKEYPrivateKey * key, 39+ CERTCertificateList *certChain) 40+{ 41+ SECStatus rv = SECSuccess; 42+ 43+ /* XXX This code only works on the initial handshake on a connection, 44+ ** XXX It does not work on a subsequent handshake (redo). 45+ */ 46+ if (ss->handshake != 0) { 47+ ss->handshake = ssl_GatherRecord1stHandshake; 48+ ss->ssl3.clientCertificate = cert; 49+ ss->ssl3.clientPrivateKey = key; 50+ ss->ssl3.clientCertChain = certChain; 51+ if (!cert || !key || !certChain) { 52+ /* we are missing the key, cert, or cert chain */ 53+ if (ss->ssl3.clientCertificate) { 54+ CERT_DestroyCertificate(ss->ssl3.clientCertificate); 55+ ss->ssl3.clientCertificate = NULL; 56+ } 57+ if (ss->ssl3.clientPrivateKey) { 58+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); 59+ ss->ssl3.clientPrivateKey = NULL; 60+ } 61+ if (ss->ssl3.clientCertChain != NULL) { 62+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain); 63+ ss->ssl3.clientCertChain = NULL; 64+ } 65+ if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { 66+ ss->ssl3.sendEmptyCert = PR_TRUE; 67+ } else { 68+ (void)SSL3_SendAlert(ss, alert_warning, no_certificate); 69+ } 70+ } 71+ } else { 72+ if (cert) { 73+ CERT_DestroyCertificate(cert); 74+ } 75+ if (key) { 76+ SECKEY_DestroyPrivateKey(key); 77+ } 78+ if (certChain) { 79+ CERT_DestroyCertificateList(certChain); 80+ } 81+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 82+ rv = SECFailure; 83+ } 84+ return rv; 85+} 86+ 87 static SECStatus 88 ssl3_CheckFalseStart(sslSocket *ss) 89 { 90diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h 91--- a/nss/lib/ssl/ssl.h 2014-01-17 17:55:01.538096321 -0800 92+++ b/nss/lib/ssl/ssl.h 2014-01-17 17:55:19.158389328 -0800 93@@ -399,6 +399,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake( 94 SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, 95 PRIntervalTime timeout); 96 97+SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd, 98+ CERTCertificate *cert, 99+ SECKEYPrivateKey *key, 100+ CERTCertificateList *certChain); 101+ 102 /* 103 ** Query security status of socket. *on is set to one if security is 104 ** enabled. *keySize will contain the stream key size used. *issuer will 105diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 106--- a/nss/lib/ssl/sslimpl.h 2014-01-17 17:55:01.538096321 -0800 107+++ b/nss/lib/ssl/sslimpl.h 2014-01-17 17:55:19.158389328 -0800 108@@ -1588,16 +1588,17 @@ extern SECStatus ssl3_MasterKeyDeriveBy 109 /* These functions are called from secnav, even though they're "private". */ 110 111 extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error); 112-extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss, 113- CERTCertificate *cert, 114- SECKEYPrivateKey *key, 115- CERTCertificateList *certChain); 116 extern sslSocket *ssl_FindSocket(PRFileDesc *fd); 117 extern void ssl_FreeSocket(struct sslSocketStr *ssl); 118 extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, 119 SSL3AlertDescription desc); 120 extern SECStatus ssl3_DecodeError(sslSocket *ss); 121 122+extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, 123+ CERTCertificate * cert, 124+ SECKEYPrivateKey * key, 125+ CERTCertificateList *certChain); 126+ 127 extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error); 128 129 /* 130diff -pu a/nss/lib/ssl/sslsecur.c b/nss/lib/ssl/sslsecur.c 131--- a/nss/lib/ssl/sslsecur.c 2014-01-17 17:49:26.072517368 -0800 132+++ b/nss/lib/ssl/sslsecur.c 2014-01-17 17:55:19.158389328 -0800 133@@ -1518,17 +1518,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERT 134 return SECSuccess; 135 } 136 137-/* DO NOT USE. This function was exported in ssl.def with the wrong signature; 138- * this implementation exists to maintain link-time compatibility. 139+/* 140+ * attempt to restart the handshake after asynchronously handling 141+ * a request for the client's certificate. 142+ * 143+ * inputs: 144+ * cert Client cert chosen by application. 145+ * Note: ssl takes this reference, and does not bump the 146+ * reference count. The caller should drop its reference 147+ * without calling CERT_DestroyCertificate after calling this 148+ * function. 149+ * 150+ * key Private key associated with cert. This function takes 151+ * ownership of the private key, so the caller should drop its 152+ * reference without destroying the private key after this 153+ * function returns. 154+ * 155+ * certChain Chain of signers for cert. 156+ * Note: ssl takes this reference, and does not copy the chain. 157+ * The caller should drop its reference without destroying the 158+ * chain. SSL will free the chain when it is done with it. 159+ * 160+ * Return value: XXX 161+ * 162+ * XXX This code only works on the initial handshake on a connection, XXX 163+ * It does not work on a subsequent handshake (redo). 164 */ 165-int 166-SSL_RestartHandshakeAfterCertReq(sslSocket * ss, 167+SECStatus 168+SSL_RestartHandshakeAfterCertReq(PRFileDesc * fd, 169 CERTCertificate * cert, 170 SECKEYPrivateKey * key, 171 CERTCertificateList *certChain) 172 { 173- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 174- return -1; 175+ sslSocket * ss = ssl_FindSocket(fd); 176+ SECStatus ret; 177+ 178+ if (!ss) { 179+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq", 180+ SSL_GETPID(), fd)); 181+ if (cert) { 182+ CERT_DestroyCertificate(cert); 183+ } 184+ if (key) { 185+ SECKEY_DestroyPrivateKey(key); 186+ } 187+ if (certChain) { 188+ CERT_DestroyCertificateList(certChain); 189+ } 190+ return SECFailure; 191+ } 192+ 193+ ssl_Get1stHandshakeLock(ss); /************************************/ 194+ 195+ if (ss->version >= SSL_LIBRARY_VERSION_3_0) { 196+ ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain); 197+ } else { 198+ if (certChain != NULL) { 199+ CERT_DestroyCertificateList(certChain); 200+ } 201+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); 202+ ret = SECFailure; 203+ } 204+ 205+ ssl_Release1stHandshakeLock(ss); /************************************/ 206+ return ret; 207 } 208 209 /* DO NOT USE. This function was exported in ssl.def with the wrong signature; 210