1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 --- a/nss/lib/ssl/ssl3con.c 2013-07-31 12:44:31.987362835 -0700 3 +++ b/nss/lib/ssl/ssl3con.c 2013-07-31 12:44:50.987642452 -0700 4 @@ -6756,6 +6756,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 PRBool 88 ssl3_CanFalseStart(sslSocket *ss) { 89 PRBool rv; 90 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h 91 --- a/nss/lib/ssl/ssl.h 2013-07-31 12:44:31.987362835 -0700 92 +++ b/nss/lib/ssl/ssl.h 2013-07-31 12:44:50.987642452 -0700 93 @@ -366,6 +366,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 105 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 106 --- a/nss/lib/ssl/sslimpl.h 2013-07-31 12:44:31.997362988 -0700 107 +++ b/nss/lib/ssl/sslimpl.h 2013-07-31 12:44:50.987642452 -0700 108 @@ -1513,16 +1513,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 /* 130 diff -pu a/nss/lib/ssl/sslsecur.c b/nss/lib/ssl/sslsecur.c 131 --- a/nss/lib/ssl/sslsecur.c 2013-07-31 12:28:39.283413269 -0700 132 +++ b/nss/lib/ssl/sslsecur.c 2013-07-31 12:44:50.987642452 -0700 133 @@ -1436,17 +1436,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