security/nss/lib/ssl/sslsecur.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Various SSL functions.
michael@0 3 *
michael@0 4 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7 #include "cert.h"
michael@0 8 #include "secitem.h"
michael@0 9 #include "keyhi.h"
michael@0 10 #include "ssl.h"
michael@0 11 #include "sslimpl.h"
michael@0 12 #include "sslproto.h"
michael@0 13 #include "secoid.h" /* for SECOID_GetALgorithmTag */
michael@0 14 #include "pk11func.h" /* for PK11_GenerateRandom */
michael@0 15 #include "nss.h" /* for NSS_RegisterShutdown */
michael@0 16 #include "prinit.h" /* for PR_CallOnceWithArg */
michael@0 17
michael@0 18 #define MAX_BLOCK_CYPHER_SIZE 32
michael@0 19
michael@0 20 #define TEST_FOR_FAILURE /* reminder */
michael@0 21 #define SET_ERROR_CODE /* reminder */
michael@0 22
michael@0 23 /* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
michael@0 24 *
michael@0 25 * Currently, the list of functions called through ss->handshake is:
michael@0 26 *
michael@0 27 * In sslsocks.c:
michael@0 28 * SocksGatherRecord
michael@0 29 * SocksHandleReply
michael@0 30 * SocksStartGather
michael@0 31 *
michael@0 32 * In sslcon.c:
michael@0 33 * ssl_GatherRecord1stHandshake
michael@0 34 * ssl2_HandleClientSessionKeyMessage
michael@0 35 * ssl2_HandleMessage
michael@0 36 * ssl2_HandleVerifyMessage
michael@0 37 * ssl2_BeginClientHandshake
michael@0 38 * ssl2_BeginServerHandshake
michael@0 39 * ssl2_HandleClientHelloMessage
michael@0 40 * ssl2_HandleServerHelloMessage
michael@0 41 *
michael@0 42 * The ss->handshake function returns SECWouldBlock under these conditions:
michael@0 43 * 1. ssl_GatherRecord1stHandshake called ssl2_GatherData which read in
michael@0 44 * the beginning of an SSL v3 hello message and returned SECWouldBlock
michael@0 45 * to switch to SSL v3 handshake processing.
michael@0 46 *
michael@0 47 * 2. ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
michael@0 48 * v2 client hello msg, and called ssl3_HandleV2ClientHello which
michael@0 49 * returned SECWouldBlock.
michael@0 50 *
michael@0 51 * 3. SECWouldBlock was returned by one of the callback functions, via
michael@0 52 * one of these paths:
michael@0 53 * - ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
michael@0 54 * ss->getClientAuthData()
michael@0 55 *
michael@0 56 * - ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
michael@0 57 *
michael@0 58 * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
michael@0 59 * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
michael@0 60 * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
michael@0 61 * ss->handleBadCert()
michael@0 62 *
michael@0 63 * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
michael@0 64 * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
michael@0 65 * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
michael@0 66 * ss->getClientAuthData()
michael@0 67 *
michael@0 68 * Called from: SSL_ForceHandshake (below),
michael@0 69 * ssl_SecureRecv (below) and
michael@0 70 * ssl_SecureSend (below)
michael@0 71 * from: WaitForResponse in sslsocks.c
michael@0 72 * ssl_SocksRecv in sslsocks.c
michael@0 73 * ssl_SocksSend in sslsocks.c
michael@0 74 *
michael@0 75 * Caller must hold the (write) handshakeLock.
michael@0 76 */
michael@0 77 int
michael@0 78 ssl_Do1stHandshake(sslSocket *ss)
michael@0 79 {
michael@0 80 int rv = SECSuccess;
michael@0 81 int loopCount = 0;
michael@0 82
michael@0 83 do {
michael@0 84 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
michael@0 85 PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
michael@0 86 PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
michael@0 87 PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
michael@0 88
michael@0 89 if (ss->handshake == 0) {
michael@0 90 /* Previous handshake finished. Switch to next one */
michael@0 91 ss->handshake = ss->nextHandshake;
michael@0 92 ss->nextHandshake = 0;
michael@0 93 }
michael@0 94 if (ss->handshake == 0) {
michael@0 95 /* Previous handshake finished. Switch to security handshake */
michael@0 96 ss->handshake = ss->securityHandshake;
michael@0 97 ss->securityHandshake = 0;
michael@0 98 }
michael@0 99 if (ss->handshake == 0) {
michael@0 100 /* for v3 this is done in ssl3_FinishHandshake */
michael@0 101 if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
michael@0 102 ssl_GetRecvBufLock(ss);
michael@0 103 ss->gs.recordLen = 0;
michael@0 104 ssl_FinishHandshake(ss);
michael@0 105 ssl_ReleaseRecvBufLock(ss);
michael@0 106 }
michael@0 107 break;
michael@0 108 }
michael@0 109 rv = (*ss->handshake)(ss);
michael@0 110 ++loopCount;
michael@0 111 /* This code must continue to loop on SECWouldBlock,
michael@0 112 * or any positive value. See XXX_1 comments.
michael@0 113 */
michael@0 114 } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */
michael@0 115
michael@0 116 PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
michael@0 117 PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
michael@0 118 PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
michael@0 119
michael@0 120 if (rv == SECWouldBlock) {
michael@0 121 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 122 rv = SECFailure;
michael@0 123 }
michael@0 124 return rv;
michael@0 125 }
michael@0 126
michael@0 127 void
michael@0 128 ssl_FinishHandshake(sslSocket *ss)
michael@0 129 {
michael@0 130 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
michael@0 131 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
michael@0 132
michael@0 133 SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
michael@0 134
michael@0 135 ss->firstHsDone = PR_TRUE;
michael@0 136 ss->enoughFirstHsDone = PR_TRUE;
michael@0 137 ss->gs.writeOffset = 0;
michael@0 138 ss->gs.readOffset = 0;
michael@0 139
michael@0 140 if (ss->handshakeCallback) {
michael@0 141 (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
michael@0 142 }
michael@0 143 }
michael@0 144
michael@0 145 /*
michael@0 146 * Handshake function that blocks. Used to force a
michael@0 147 * retry on a connection on the next read/write.
michael@0 148 */
michael@0 149 static SECStatus
michael@0 150 ssl3_AlwaysBlock(sslSocket *ss)
michael@0 151 {
michael@0 152 PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */
michael@0 153 return SECWouldBlock;
michael@0 154 }
michael@0 155
michael@0 156 /*
michael@0 157 * set the initial handshake state machine to block
michael@0 158 */
michael@0 159 void
michael@0 160 ssl3_SetAlwaysBlock(sslSocket *ss)
michael@0 161 {
michael@0 162 if (!ss->firstHsDone) {
michael@0 163 ss->handshake = ssl3_AlwaysBlock;
michael@0 164 ss->nextHandshake = 0;
michael@0 165 }
michael@0 166 }
michael@0 167
michael@0 168 static SECStatus
michael@0 169 ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout)
michael@0 170 {
michael@0 171 sslSocket *ss;
michael@0 172
michael@0 173 ss = ssl_FindSocket(fd);
michael@0 174 if (!ss) {
michael@0 175 SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd));
michael@0 176 return SECFailure;
michael@0 177 }
michael@0 178 SSL_LOCK_READER(ss);
michael@0 179 ss->rTimeout = timeout;
michael@0 180 if (ss->opt.fdx) {
michael@0 181 SSL_LOCK_WRITER(ss);
michael@0 182 }
michael@0 183 ss->wTimeout = timeout;
michael@0 184 if (ss->opt.fdx) {
michael@0 185 SSL_UNLOCK_WRITER(ss);
michael@0 186 }
michael@0 187 SSL_UNLOCK_READER(ss);
michael@0 188 return SECSuccess;
michael@0 189 }
michael@0 190
michael@0 191 /* Acquires and releases HandshakeLock.
michael@0 192 */
michael@0 193 SECStatus
michael@0 194 SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
michael@0 195 {
michael@0 196 sslSocket *ss;
michael@0 197 SECStatus status;
michael@0 198 PRNetAddr addr;
michael@0 199
michael@0 200 ss = ssl_FindSocket(s);
michael@0 201 if (!ss) {
michael@0 202 SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
michael@0 203 return SECFailure;
michael@0 204 }
michael@0 205
michael@0 206 /* Don't waste my time */
michael@0 207 if (!ss->opt.useSecurity)
michael@0 208 return SECSuccess;
michael@0 209
michael@0 210 SSL_LOCK_READER(ss);
michael@0 211 SSL_LOCK_WRITER(ss);
michael@0 212
michael@0 213 /* Reset handshake state */
michael@0 214 ssl_Get1stHandshakeLock(ss);
michael@0 215
michael@0 216 ss->firstHsDone = PR_FALSE;
michael@0 217 ss->enoughFirstHsDone = PR_FALSE;
michael@0 218 if ( asServer ) {
michael@0 219 ss->handshake = ssl2_BeginServerHandshake;
michael@0 220 ss->handshaking = sslHandshakingAsServer;
michael@0 221 } else {
michael@0 222 ss->handshake = ssl2_BeginClientHandshake;
michael@0 223 ss->handshaking = sslHandshakingAsClient;
michael@0 224 }
michael@0 225 ss->nextHandshake = 0;
michael@0 226 ss->securityHandshake = 0;
michael@0 227
michael@0 228 ssl_GetRecvBufLock(ss);
michael@0 229 status = ssl_InitGather(&ss->gs);
michael@0 230 ssl_ReleaseRecvBufLock(ss);
michael@0 231
michael@0 232 ssl_GetSSL3HandshakeLock(ss);
michael@0 233 ss->ssl3.hs.canFalseStart = PR_FALSE;
michael@0 234 ss->ssl3.hs.restartTarget = NULL;
michael@0 235
michael@0 236 /*
michael@0 237 ** Blow away old security state and get a fresh setup.
michael@0 238 */
michael@0 239 ssl_GetXmitBufLock(ss);
michael@0 240 ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
michael@0 241 status = ssl_CreateSecurityInfo(ss);
michael@0 242 ssl_ReleaseXmitBufLock(ss);
michael@0 243
michael@0 244 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 245 ssl_Release1stHandshakeLock(ss);
michael@0 246
michael@0 247 if (!ss->TCPconnected)
michael@0 248 ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
michael@0 249
michael@0 250 SSL_UNLOCK_WRITER(ss);
michael@0 251 SSL_UNLOCK_READER(ss);
michael@0 252
michael@0 253 return status;
michael@0 254 }
michael@0 255
michael@0 256 /* For SSLv2, does nothing but return an error.
michael@0 257 ** For SSLv3, flushes SID cache entry (if requested),
michael@0 258 ** and then starts new client hello or hello request.
michael@0 259 ** Acquires and releases HandshakeLock.
michael@0 260 */
michael@0 261 SECStatus
michael@0 262 SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
michael@0 263 {
michael@0 264 sslSocket *ss;
michael@0 265 SECStatus rv;
michael@0 266
michael@0 267 ss = ssl_FindSocket(fd);
michael@0 268 if (!ss) {
michael@0 269 SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd));
michael@0 270 return SECFailure;
michael@0 271 }
michael@0 272
michael@0 273 if (!ss->opt.useSecurity)
michael@0 274 return SECSuccess;
michael@0 275
michael@0 276 ssl_Get1stHandshakeLock(ss);
michael@0 277
michael@0 278 /* SSL v2 protocol does not support subsequent handshakes. */
michael@0 279 if (ss->version < SSL_LIBRARY_VERSION_3_0) {
michael@0 280 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
michael@0 281 rv = SECFailure;
michael@0 282 } else {
michael@0 283 ssl_GetSSL3HandshakeLock(ss);
michael@0 284 rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */
michael@0 285 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 286 }
michael@0 287
michael@0 288 ssl_Release1stHandshakeLock(ss);
michael@0 289
michael@0 290 return rv;
michael@0 291 }
michael@0 292
michael@0 293 /*
michael@0 294 ** Same as above, but with an I/O timeout.
michael@0 295 */
michael@0 296 SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
michael@0 297 PRBool flushCache,
michael@0 298 PRIntervalTime timeout)
michael@0 299 {
michael@0 300 if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
michael@0 301 return SECFailure;
michael@0 302 }
michael@0 303 return SSL_ReHandshake(fd, flushCache);
michael@0 304 }
michael@0 305
michael@0 306 SECStatus
michael@0 307 SSL_RedoHandshake(PRFileDesc *fd)
michael@0 308 {
michael@0 309 return SSL_ReHandshake(fd, PR_TRUE);
michael@0 310 }
michael@0 311
michael@0 312 /* Register an application callback to be called when SSL handshake completes.
michael@0 313 ** Acquires and releases HandshakeLock.
michael@0 314 */
michael@0 315 SECStatus
michael@0 316 SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
michael@0 317 void *client_data)
michael@0 318 {
michael@0 319 sslSocket *ss;
michael@0 320
michael@0 321 ss = ssl_FindSocket(fd);
michael@0 322 if (!ss) {
michael@0 323 SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback",
michael@0 324 SSL_GETPID(), fd));
michael@0 325 return SECFailure;
michael@0 326 }
michael@0 327
michael@0 328 if (!ss->opt.useSecurity) {
michael@0 329 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 330 return SECFailure;
michael@0 331 }
michael@0 332
michael@0 333 ssl_Get1stHandshakeLock(ss);
michael@0 334 ssl_GetSSL3HandshakeLock(ss);
michael@0 335
michael@0 336 ss->handshakeCallback = cb;
michael@0 337 ss->handshakeCallbackData = client_data;
michael@0 338
michael@0 339 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 340 ssl_Release1stHandshakeLock(ss);
michael@0 341
michael@0 342 return SECSuccess;
michael@0 343 }
michael@0 344
michael@0 345 /* Register an application callback to be called when false start may happen.
michael@0 346 ** Acquires and releases HandshakeLock.
michael@0 347 */
michael@0 348 SECStatus
michael@0 349 SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
michael@0 350 void *arg)
michael@0 351 {
michael@0 352 sslSocket *ss;
michael@0 353
michael@0 354 ss = ssl_FindSocket(fd);
michael@0 355 if (!ss) {
michael@0 356 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
michael@0 357 SSL_GETPID(), fd));
michael@0 358 return SECFailure;
michael@0 359 }
michael@0 360
michael@0 361 if (!ss->opt.useSecurity) {
michael@0 362 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 363 return SECFailure;
michael@0 364 }
michael@0 365
michael@0 366 ssl_Get1stHandshakeLock(ss);
michael@0 367 ssl_GetSSL3HandshakeLock(ss);
michael@0 368
michael@0 369 ss->canFalseStartCallback = cb;
michael@0 370 ss->canFalseStartCallbackData = arg;
michael@0 371
michael@0 372 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 373 ssl_Release1stHandshakeLock(ss);
michael@0 374
michael@0 375 return SECSuccess;
michael@0 376 }
michael@0 377
michael@0 378 SECStatus
michael@0 379 SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
michael@0 380 {
michael@0 381 sslSocket *ss;
michael@0 382
michael@0 383 *canFalseStart = PR_FALSE;
michael@0 384 ss = ssl_FindSocket(fd);
michael@0 385 if (!ss) {
michael@0 386 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
michael@0 387 SSL_GETPID(), fd));
michael@0 388 return SECFailure;
michael@0 389 }
michael@0 390
michael@0 391 if (!ss->ssl3.initialized) {
michael@0 392 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 393 return SECFailure;
michael@0 394 }
michael@0 395
michael@0 396 if (ss->version < SSL_LIBRARY_VERSION_3_0) {
michael@0 397 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
michael@0 398 return SECFailure;
michael@0 399 }
michael@0 400
michael@0 401 /* Require a forward-secret key exchange. */
michael@0 402 *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
michael@0 403 ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
michael@0 404 ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
michael@0 405 ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
michael@0 406
michael@0 407 return SECSuccess;
michael@0 408 }
michael@0 409
michael@0 410 /* Try to make progress on an SSL handshake by attempting to read the
michael@0 411 ** next handshake from the peer, and sending any responses.
michael@0 412 ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
michael@0 413 ** read the next handshake from the underlying socket.
michael@0 414 ** For SSLv2, returns when handshake is complete or fatal error occurs.
michael@0 415 ** For SSLv3, returns when handshake is complete, or application data has
michael@0 416 ** arrived that must be taken by application before handshake can continue,
michael@0 417 ** or a fatal error occurs.
michael@0 418 ** Application should use handshake completion callback to tell which.
michael@0 419 */
michael@0 420 SECStatus
michael@0 421 SSL_ForceHandshake(PRFileDesc *fd)
michael@0 422 {
michael@0 423 sslSocket *ss;
michael@0 424 SECStatus rv = SECFailure;
michael@0 425
michael@0 426 ss = ssl_FindSocket(fd);
michael@0 427 if (!ss) {
michael@0 428 SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
michael@0 429 SSL_GETPID(), fd));
michael@0 430 return rv;
michael@0 431 }
michael@0 432
michael@0 433 /* Don't waste my time */
michael@0 434 if (!ss->opt.useSecurity)
michael@0 435 return SECSuccess;
michael@0 436
michael@0 437 if (!ssl_SocketIsBlocking(ss)) {
michael@0 438 ssl_GetXmitBufLock(ss);
michael@0 439 if (ss->pendingBuf.len != 0) {
michael@0 440 int sent = ssl_SendSavedWriteData(ss);
michael@0 441 if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
michael@0 442 ssl_ReleaseXmitBufLock(ss);
michael@0 443 return SECFailure;
michael@0 444 }
michael@0 445 }
michael@0 446 ssl_ReleaseXmitBufLock(ss);
michael@0 447 }
michael@0 448
michael@0 449 ssl_Get1stHandshakeLock(ss);
michael@0 450
michael@0 451 if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
michael@0 452 int gatherResult;
michael@0 453
michael@0 454 ssl_GetRecvBufLock(ss);
michael@0 455 gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
michael@0 456 ssl_ReleaseRecvBufLock(ss);
michael@0 457 if (gatherResult > 0) {
michael@0 458 rv = SECSuccess;
michael@0 459 } else if (gatherResult == 0) {
michael@0 460 PORT_SetError(PR_END_OF_FILE_ERROR);
michael@0 461 } else if (gatherResult == SECWouldBlock) {
michael@0 462 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 463 }
michael@0 464 } else if (!ss->firstHsDone) {
michael@0 465 rv = ssl_Do1stHandshake(ss);
michael@0 466 } else {
michael@0 467 /* tried to force handshake on an SSL 2 socket that has
michael@0 468 ** already completed the handshake. */
michael@0 469 rv = SECSuccess; /* just pretend we did it. */
michael@0 470 }
michael@0 471
michael@0 472 ssl_Release1stHandshakeLock(ss);
michael@0 473
michael@0 474 return rv;
michael@0 475 }
michael@0 476
michael@0 477 /*
michael@0 478 ** Same as above, but with an I/O timeout.
michael@0 479 */
michael@0 480 SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
michael@0 481 PRIntervalTime timeout)
michael@0 482 {
michael@0 483 if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
michael@0 484 return SECFailure;
michael@0 485 }
michael@0 486 return SSL_ForceHandshake(fd);
michael@0 487 }
michael@0 488
michael@0 489
michael@0 490 /************************************************************************/
michael@0 491
michael@0 492 /*
michael@0 493 ** Grow a buffer to hold newLen bytes of data.
michael@0 494 ** Called for both recv buffers and xmit buffers.
michael@0 495 ** Caller must hold xmitBufLock or recvBufLock, as appropriate.
michael@0 496 */
michael@0 497 SECStatus
michael@0 498 sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
michael@0 499 {
michael@0 500 newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048);
michael@0 501 if (newLen > b->space) {
michael@0 502 unsigned char *newBuf;
michael@0 503 if (b->buf) {
michael@0 504 newBuf = (unsigned char *) PORT_Realloc(b->buf, newLen);
michael@0 505 } else {
michael@0 506 newBuf = (unsigned char *) PORT_Alloc(newLen);
michael@0 507 }
michael@0 508 if (!newBuf) {
michael@0 509 return SECFailure;
michael@0 510 }
michael@0 511 SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d",
michael@0 512 SSL_GETPID(), b->space, newLen));
michael@0 513 b->buf = newBuf;
michael@0 514 b->space = newLen;
michael@0 515 }
michael@0 516 return SECSuccess;
michael@0 517 }
michael@0 518
michael@0 519 SECStatus
michael@0 520 sslBuffer_Append(sslBuffer *b, const void * data, unsigned int len)
michael@0 521 {
michael@0 522 unsigned int newLen = b->len + len;
michael@0 523 SECStatus rv;
michael@0 524
michael@0 525 rv = sslBuffer_Grow(b, newLen);
michael@0 526 if (rv != SECSuccess)
michael@0 527 return rv;
michael@0 528 PORT_Memcpy(b->buf + b->len, data, len);
michael@0 529 b->len += len;
michael@0 530 return SECSuccess;
michael@0 531 }
michael@0 532
michael@0 533 /*
michael@0 534 ** Save away write data that is trying to be written before the security
michael@0 535 ** handshake has been completed. When the handshake is completed, we will
michael@0 536 ** flush this data out.
michael@0 537 ** Caller must hold xmitBufLock
michael@0 538 */
michael@0 539 SECStatus
michael@0 540 ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
michael@0 541 {
michael@0 542 SECStatus rv;
michael@0 543
michael@0 544 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
michael@0 545 rv = sslBuffer_Append(&ss->pendingBuf, data, len);
michael@0 546 SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)",
michael@0 547 SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
michael@0 548 return rv;
michael@0 549 }
michael@0 550
michael@0 551 /*
michael@0 552 ** Send saved write data. This will flush out data sent prior to a
michael@0 553 ** complete security handshake. Hopefully there won't be too much of it.
michael@0 554 ** Returns count of the bytes sent, NOT a SECStatus.
michael@0 555 ** Caller must hold xmitBufLock
michael@0 556 */
michael@0 557 int
michael@0 558 ssl_SendSavedWriteData(sslSocket *ss)
michael@0 559 {
michael@0 560 int rv = 0;
michael@0 561
michael@0 562 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
michael@0 563 if (ss->pendingBuf.len != 0) {
michael@0 564 SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
michael@0 565 SSL_GETPID(), ss->fd, ss->pendingBuf.len));
michael@0 566 rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
michael@0 567 if (rv < 0) {
michael@0 568 return rv;
michael@0 569 }
michael@0 570 ss->pendingBuf.len -= rv;
michael@0 571 if (ss->pendingBuf.len > 0 && rv > 0) {
michael@0 572 /* UGH !! This shifts the whole buffer down by copying it */
michael@0 573 PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv,
michael@0 574 ss->pendingBuf.len);
michael@0 575 }
michael@0 576 }
michael@0 577 return rv;
michael@0 578 }
michael@0 579
michael@0 580 /************************************************************************/
michael@0 581
michael@0 582 /*
michael@0 583 ** Receive some application data on a socket. Reads SSL records from the input
michael@0 584 ** stream, decrypts them and then copies them to the output buffer.
michael@0 585 ** Called from ssl_SecureRecv() below.
michael@0 586 **
michael@0 587 ** Caller does NOT hold 1stHandshakeLock because that handshake is over.
michael@0 588 ** Caller doesn't call this until initial handshake is complete.
michael@0 589 ** For SSLv2, there is no subsequent handshake.
michael@0 590 ** For SSLv3, the call to ssl3_GatherAppDataRecord may encounter handshake
michael@0 591 ** messages from a subsequent handshake.
michael@0 592 **
michael@0 593 ** This code is similar to, and easily confused with,
michael@0 594 ** ssl_GatherRecord1stHandshake() in sslcon.c
michael@0 595 */
michael@0 596 static int
michael@0 597 DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
michael@0 598 {
michael@0 599 int rv;
michael@0 600 int amount;
michael@0 601 int available;
michael@0 602
michael@0 603 /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
michael@0 604 * 1stHandshakeLock. */
michael@0 605 ssl_Get1stHandshakeLock(ss);
michael@0 606 ssl_GetRecvBufLock(ss);
michael@0 607
michael@0 608 available = ss->gs.writeOffset - ss->gs.readOffset;
michael@0 609 if (available == 0) {
michael@0 610 /* Get some more data */
michael@0 611 if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
michael@0 612 /* Wait for application data to arrive. */
michael@0 613 rv = ssl3_GatherAppDataRecord(ss, 0);
michael@0 614 } else {
michael@0 615 /* See if we have a complete record */
michael@0 616 rv = ssl2_GatherRecord(ss, 0);
michael@0 617 }
michael@0 618 if (rv <= 0) {
michael@0 619 if (rv == 0) {
michael@0 620 /* EOF */
michael@0 621 SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF",
michael@0 622 SSL_GETPID(), ss->fd));
michael@0 623 goto done;
michael@0 624 }
michael@0 625 if ((rv != SECWouldBlock) &&
michael@0 626 (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
michael@0 627 /* Some random error */
michael@0 628 goto done;
michael@0 629 }
michael@0 630
michael@0 631 /*
michael@0 632 ** Gather record is blocked waiting for more record data to
michael@0 633 ** arrive. Try to process what we have already received
michael@0 634 */
michael@0 635 } else {
michael@0 636 /* Gather record has finished getting a complete record */
michael@0 637 }
michael@0 638
michael@0 639 /* See if any clear data is now available */
michael@0 640 available = ss->gs.writeOffset - ss->gs.readOffset;
michael@0 641 if (available == 0) {
michael@0 642 /*
michael@0 643 ** No partial data is available. Force error code to
michael@0 644 ** EWOULDBLOCK so that caller will try again later. Note
michael@0 645 ** that the error code is probably EWOULDBLOCK already,
michael@0 646 ** but if it isn't (for example, if we received a zero
michael@0 647 ** length record) then this will force it to be correct.
michael@0 648 */
michael@0 649 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 650 rv = SECFailure;
michael@0 651 goto done;
michael@0 652 }
michael@0 653 SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d",
michael@0 654 SSL_GETPID(), ss->fd, available));
michael@0 655 }
michael@0 656
michael@0 657 /* Dole out clear data to reader */
michael@0 658 amount = PR_MIN(len, available);
michael@0 659 PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount);
michael@0 660 if (!(flags & PR_MSG_PEEK)) {
michael@0 661 ss->gs.readOffset += amount;
michael@0 662 }
michael@0 663 PORT_Assert(ss->gs.readOffset <= ss->gs.writeOffset);
michael@0 664 rv = amount;
michael@0 665
michael@0 666 SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d",
michael@0 667 SSL_GETPID(), ss->fd, amount, available));
michael@0 668 PRINT_BUF(4, (ss, "DoRecv receiving plaintext:", out, amount));
michael@0 669
michael@0 670 done:
michael@0 671 ssl_ReleaseRecvBufLock(ss);
michael@0 672 ssl_Release1stHandshakeLock(ss);
michael@0 673 return rv;
michael@0 674 }
michael@0 675
michael@0 676 /************************************************************************/
michael@0 677
michael@0 678 /*
michael@0 679 ** Return SSLKEAType derived from cert's Public Key algorithm info.
michael@0 680 */
michael@0 681 SSLKEAType
michael@0 682 NSS_FindCertKEAType(CERTCertificate * cert)
michael@0 683 {
michael@0 684 SSLKEAType keaType = kt_null;
michael@0 685 int tag;
michael@0 686
michael@0 687 if (!cert) goto loser;
michael@0 688
michael@0 689 tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
michael@0 690
michael@0 691 switch (tag) {
michael@0 692 case SEC_OID_X500_RSA_ENCRYPTION:
michael@0 693 case SEC_OID_PKCS1_RSA_ENCRYPTION:
michael@0 694 keaType = kt_rsa;
michael@0 695 break;
michael@0 696 case SEC_OID_X942_DIFFIE_HELMAN_KEY:
michael@0 697 keaType = kt_dh;
michael@0 698 break;
michael@0 699 #ifndef NSS_DISABLE_ECC
michael@0 700 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
michael@0 701 keaType = kt_ecdh;
michael@0 702 break;
michael@0 703 #endif /* NSS_DISABLE_ECC */
michael@0 704 default:
michael@0 705 keaType = kt_null;
michael@0 706 }
michael@0 707
michael@0 708 loser:
michael@0 709
michael@0 710 return keaType;
michael@0 711 }
michael@0 712
michael@0 713 static const PRCallOnceType pristineCallOnce;
michael@0 714 static PRCallOnceType setupServerCAListOnce;
michael@0 715
michael@0 716 static SECStatus serverCAListShutdown(void* appData, void* nssData)
michael@0 717 {
michael@0 718 PORT_Assert(ssl3_server_ca_list);
michael@0 719 if (ssl3_server_ca_list) {
michael@0 720 CERT_FreeDistNames(ssl3_server_ca_list);
michael@0 721 ssl3_server_ca_list = NULL;
michael@0 722 }
michael@0 723 setupServerCAListOnce = pristineCallOnce;
michael@0 724 return SECSuccess;
michael@0 725 }
michael@0 726
michael@0 727 static PRStatus serverCAListSetup(void *arg)
michael@0 728 {
michael@0 729 CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
michael@0 730 SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL);
michael@0 731 PORT_Assert(SECSuccess == rv);
michael@0 732 if (SECSuccess == rv) {
michael@0 733 ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
michael@0 734 return PR_SUCCESS;
michael@0 735 }
michael@0 736 return PR_FAILURE;
michael@0 737 }
michael@0 738
michael@0 739 SECStatus
michael@0 740 ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
michael@0 741 const CERTCertificateList *certChain,
michael@0 742 ssl3KeyPair *keyPair, SSLKEAType kea)
michael@0 743 {
michael@0 744 CERTCertificateList *localCertChain = NULL;
michael@0 745 sslServerCerts *sc = ss->serverCerts + kea;
michael@0 746
michael@0 747 /* load the server certificate */
michael@0 748 if (sc->serverCert != NULL) {
michael@0 749 CERT_DestroyCertificate(sc->serverCert);
michael@0 750 sc->serverCert = NULL;
michael@0 751 sc->serverKeyBits = 0;
michael@0 752 }
michael@0 753 /* load the server cert chain */
michael@0 754 if (sc->serverCertChain != NULL) {
michael@0 755 CERT_DestroyCertificateList(sc->serverCertChain);
michael@0 756 sc->serverCertChain = NULL;
michael@0 757 }
michael@0 758 if (cert) {
michael@0 759 sc->serverCert = CERT_DupCertificate(cert);
michael@0 760 /* get the size of the cert's public key, and remember it */
michael@0 761 sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
michael@0 762 if (!certChain) {
michael@0 763 localCertChain =
michael@0 764 CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
michael@0 765 PR_TRUE);
michael@0 766 if (!localCertChain)
michael@0 767 goto loser;
michael@0 768 }
michael@0 769 sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) :
michael@0 770 localCertChain;
michael@0 771 if (!sc->serverCertChain) {
michael@0 772 goto loser;
michael@0 773 }
michael@0 774 localCertChain = NULL; /* consumed */
michael@0 775 }
michael@0 776
michael@0 777 /* get keyPair */
michael@0 778 if (sc->serverKeyPair != NULL) {
michael@0 779 ssl3_FreeKeyPair(sc->serverKeyPair);
michael@0 780 sc->serverKeyPair = NULL;
michael@0 781 }
michael@0 782 if (keyPair) {
michael@0 783 SECKEY_CacheStaticFlags(keyPair->privKey);
michael@0 784 sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair);
michael@0 785 }
michael@0 786 if (kea == kt_rsa && cert && sc->serverKeyBits > 512 &&
michael@0 787 !ss->opt.noStepDown && !ss->stepDownKeyPair) {
michael@0 788 if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
michael@0 789 goto loser;
michael@0 790 }
michael@0 791 }
michael@0 792 return SECSuccess;
michael@0 793
michael@0 794 loser:
michael@0 795 if (localCertChain) {
michael@0 796 CERT_DestroyCertificateList(localCertChain);
michael@0 797 }
michael@0 798 if (sc->serverCert != NULL) {
michael@0 799 CERT_DestroyCertificate(sc->serverCert);
michael@0 800 sc->serverCert = NULL;
michael@0 801 }
michael@0 802 if (sc->serverCertChain != NULL) {
michael@0 803 CERT_DestroyCertificateList(sc->serverCertChain);
michael@0 804 sc->serverCertChain = NULL;
michael@0 805 }
michael@0 806 if (sc->serverKeyPair != NULL) {
michael@0 807 ssl3_FreeKeyPair(sc->serverKeyPair);
michael@0 808 sc->serverKeyPair = NULL;
michael@0 809 }
michael@0 810 return SECFailure;
michael@0 811 }
michael@0 812
michael@0 813 /* XXX need to protect the data that gets changed here.!! */
michael@0 814
michael@0 815 SECStatus
michael@0 816 SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
michael@0 817 SECKEYPrivateKey *key, SSL3KEAType kea)
michael@0 818 {
michael@0 819
michael@0 820 return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
michael@0 821 }
michael@0 822
michael@0 823 SECStatus
michael@0 824 SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
michael@0 825 const CERTCertificateList *certChainOpt,
michael@0 826 SECKEYPrivateKey *key, SSL3KEAType kea)
michael@0 827 {
michael@0 828 sslSocket *ss;
michael@0 829 SECKEYPublicKey *pubKey = NULL;
michael@0 830 ssl3KeyPair *keyPair = NULL;
michael@0 831 SECStatus rv = SECFailure;
michael@0 832
michael@0 833 ss = ssl_FindSocket(fd);
michael@0 834 if (!ss) {
michael@0 835 return SECFailure;
michael@0 836 }
michael@0 837
michael@0 838 /* Both key and cert must have a value or be NULL */
michael@0 839 /* Passing a value of NULL will turn off key exchange algorithms that were
michael@0 840 * previously turned on */
michael@0 841 if (!cert != !key) {
michael@0 842 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 843 return SECFailure;
michael@0 844 }
michael@0 845
michael@0 846 /* make sure the key exchange is recognized */
michael@0 847 if ((kea >= kt_kea_size) || (kea < kt_null)) {
michael@0 848 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
michael@0 849 return SECFailure;
michael@0 850 }
michael@0 851
michael@0 852 if (kea != NSS_FindCertKEAType(cert)) {
michael@0 853 PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
michael@0 854 return SECFailure;
michael@0 855 }
michael@0 856
michael@0 857 if (cert) {
michael@0 858 /* get the size of the cert's public key, and remember it */
michael@0 859 pubKey = CERT_ExtractPublicKey(cert);
michael@0 860 if (!pubKey)
michael@0 861 return SECFailure;
michael@0 862 }
michael@0 863
michael@0 864 if (key) {
michael@0 865 SECKEYPrivateKey * keyCopy = NULL;
michael@0 866 CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
michael@0 867
michael@0 868 if (key->pkcs11Slot) {
michael@0 869 PK11SlotInfo * bestSlot;
michael@0 870 bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
michael@0 871 if (bestSlot) {
michael@0 872 keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
michael@0 873 PK11_FreeSlot(bestSlot);
michael@0 874 }
michael@0 875 }
michael@0 876 if (keyCopy == NULL)
michael@0 877 keyMech = PK11_MapSignKeyType(key->keyType);
michael@0 878 if (keyMech != CKM_INVALID_MECHANISM) {
michael@0 879 PK11SlotInfo * bestSlot;
michael@0 880 /* XXX Maybe should be bestSlotMultiple? */
michael@0 881 bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
michael@0 882 if (bestSlot) {
michael@0 883 keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
michael@0 884 PK11_FreeSlot(bestSlot);
michael@0 885 }
michael@0 886 }
michael@0 887 if (keyCopy == NULL)
michael@0 888 keyCopy = SECKEY_CopyPrivateKey(key);
michael@0 889 if (keyCopy == NULL)
michael@0 890 goto loser;
michael@0 891 keyPair = ssl3_NewKeyPair(keyCopy, pubKey);
michael@0 892 if (keyPair == NULL) {
michael@0 893 SECKEY_DestroyPrivateKey(keyCopy);
michael@0 894 goto loser;
michael@0 895 }
michael@0 896 pubKey = NULL; /* adopted by serverKeyPair */
michael@0 897 }
michael@0 898 if (ssl_ConfigSecureServer(ss, cert, certChainOpt,
michael@0 899 keyPair, kea) == SECFailure) {
michael@0 900 goto loser;
michael@0 901 }
michael@0 902
michael@0 903 /* Only do this once because it's global. */
michael@0 904 if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
michael@0 905 &serverCAListSetup,
michael@0 906 (void *)(ss->dbHandle))) {
michael@0 907 rv = SECSuccess;
michael@0 908 }
michael@0 909
michael@0 910 loser:
michael@0 911 if (keyPair) {
michael@0 912 ssl3_FreeKeyPair(keyPair);
michael@0 913 }
michael@0 914 if (pubKey) {
michael@0 915 SECKEY_DestroyPublicKey(pubKey);
michael@0 916 pubKey = NULL;
michael@0 917 }
michael@0 918 return rv;
michael@0 919 }
michael@0 920
michael@0 921 /************************************************************************/
michael@0 922
michael@0 923 SECStatus
michael@0 924 ssl_CreateSecurityInfo(sslSocket *ss)
michael@0 925 {
michael@0 926 SECStatus status;
michael@0 927
michael@0 928 /* initialize sslv2 socket to send data in the clear. */
michael@0 929 ssl2_UseClearSendFunc(ss);
michael@0 930
michael@0 931 ss->sec.blockSize = 1;
michael@0 932 ss->sec.blockShift = 0;
michael@0 933
michael@0 934 ssl_GetXmitBufLock(ss);
michael@0 935 status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
michael@0 936 ssl_ReleaseXmitBufLock(ss);
michael@0 937
michael@0 938 return status;
michael@0 939 }
michael@0 940
michael@0 941 SECStatus
michael@0 942 ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
michael@0 943 {
michael@0 944 ss->sec.send = os->sec.send;
michael@0 945 ss->sec.isServer = os->sec.isServer;
michael@0 946 ss->sec.keyBits = os->sec.keyBits;
michael@0 947 ss->sec.secretKeyBits = os->sec.secretKeyBits;
michael@0 948
michael@0 949 ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert);
michael@0 950 if (os->sec.peerCert && !ss->sec.peerCert)
michael@0 951 goto loser;
michael@0 952
michael@0 953 ss->sec.cache = os->sec.cache;
michael@0 954 ss->sec.uncache = os->sec.uncache;
michael@0 955
michael@0 956 /* we don't dup the connection info. */
michael@0 957
michael@0 958 ss->sec.sendSequence = os->sec.sendSequence;
michael@0 959 ss->sec.rcvSequence = os->sec.rcvSequence;
michael@0 960
michael@0 961 if (os->sec.hash && os->sec.hashcx) {
michael@0 962 ss->sec.hash = os->sec.hash;
michael@0 963 ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx);
michael@0 964 if (os->sec.hashcx && !ss->sec.hashcx)
michael@0 965 goto loser;
michael@0 966 } else {
michael@0 967 ss->sec.hash = NULL;
michael@0 968 ss->sec.hashcx = NULL;
michael@0 969 }
michael@0 970
michael@0 971 SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret);
michael@0 972 if (os->sec.sendSecret.data && !ss->sec.sendSecret.data)
michael@0 973 goto loser;
michael@0 974 SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret);
michael@0 975 if (os->sec.rcvSecret.data && !ss->sec.rcvSecret.data)
michael@0 976 goto loser;
michael@0 977
michael@0 978 /* XXX following code is wrong if either cx != 0 */
michael@0 979 PORT_Assert(os->sec.readcx == 0);
michael@0 980 PORT_Assert(os->sec.writecx == 0);
michael@0 981 ss->sec.readcx = os->sec.readcx;
michael@0 982 ss->sec.writecx = os->sec.writecx;
michael@0 983 ss->sec.destroy = 0;
michael@0 984
michael@0 985 ss->sec.enc = os->sec.enc;
michael@0 986 ss->sec.dec = os->sec.dec;
michael@0 987
michael@0 988 ss->sec.blockShift = os->sec.blockShift;
michael@0 989 ss->sec.blockSize = os->sec.blockSize;
michael@0 990
michael@0 991 return SECSuccess;
michael@0 992
michael@0 993 loser:
michael@0 994 return SECFailure;
michael@0 995 }
michael@0 996
michael@0 997 /* Reset sec back to its initial state.
michael@0 998 ** Caller holds any relevant locks.
michael@0 999 */
michael@0 1000 void
michael@0 1001 ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset)
michael@0 1002 {
michael@0 1003 /* Destroy MAC */
michael@0 1004 if (sec->hash && sec->hashcx) {
michael@0 1005 (*sec->hash->destroy)(sec->hashcx, PR_TRUE);
michael@0 1006 sec->hashcx = NULL;
michael@0 1007 sec->hash = NULL;
michael@0 1008 }
michael@0 1009 SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
michael@0 1010 SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
michael@0 1011
michael@0 1012 /* Destroy ciphers */
michael@0 1013 if (sec->destroy) {
michael@0 1014 (*sec->destroy)(sec->readcx, PR_TRUE);
michael@0 1015 (*sec->destroy)(sec->writecx, PR_TRUE);
michael@0 1016 sec->readcx = NULL;
michael@0 1017 sec->writecx = NULL;
michael@0 1018 } else {
michael@0 1019 PORT_Assert(sec->readcx == 0);
michael@0 1020 PORT_Assert(sec->writecx == 0);
michael@0 1021 }
michael@0 1022 sec->readcx = 0;
michael@0 1023 sec->writecx = 0;
michael@0 1024
michael@0 1025 if (sec->localCert) {
michael@0 1026 CERT_DestroyCertificate(sec->localCert);
michael@0 1027 sec->localCert = NULL;
michael@0 1028 }
michael@0 1029 if (sec->peerCert) {
michael@0 1030 CERT_DestroyCertificate(sec->peerCert);
michael@0 1031 sec->peerCert = NULL;
michael@0 1032 }
michael@0 1033 if (sec->peerKey) {
michael@0 1034 SECKEY_DestroyPublicKey(sec->peerKey);
michael@0 1035 sec->peerKey = NULL;
michael@0 1036 }
michael@0 1037
michael@0 1038 /* cleanup the ci */
michael@0 1039 if (sec->ci.sid != NULL) {
michael@0 1040 ssl_FreeSID(sec->ci.sid);
michael@0 1041 }
michael@0 1042 PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
michael@0 1043 if (doMemset) {
michael@0 1044 memset(&sec->ci, 0, sizeof sec->ci);
michael@0 1045 }
michael@0 1046
michael@0 1047 }
michael@0 1048
michael@0 1049 /*
michael@0 1050 ** Called from SSL_ResetHandshake (above), and
michael@0 1051 ** from ssl_FreeSocket in sslsock.c
michael@0 1052 ** Caller should hold relevant locks (e.g. XmitBufLock)
michael@0 1053 */
michael@0 1054 void
michael@0 1055 ssl_DestroySecurityInfo(sslSecurityInfo *sec)
michael@0 1056 {
michael@0 1057 ssl_ResetSecurityInfo(sec, PR_FALSE);
michael@0 1058
michael@0 1059 PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
michael@0 1060 sec->writeBuf.buf = 0;
michael@0 1061
michael@0 1062 memset(sec, 0, sizeof *sec);
michael@0 1063 }
michael@0 1064
michael@0 1065 /************************************************************************/
michael@0 1066
michael@0 1067 int
michael@0 1068 ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
michael@0 1069 {
michael@0 1070 PRFileDesc *osfd = ss->fd->lower;
michael@0 1071 int rv;
michael@0 1072
michael@0 1073 if ( ss->opt.handshakeAsServer ) {
michael@0 1074 ss->securityHandshake = ssl2_BeginServerHandshake;
michael@0 1075 ss->handshaking = sslHandshakingAsServer;
michael@0 1076 } else {
michael@0 1077 ss->securityHandshake = ssl2_BeginClientHandshake;
michael@0 1078 ss->handshaking = sslHandshakingAsClient;
michael@0 1079 }
michael@0 1080
michael@0 1081 /* connect to server */
michael@0 1082 rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
michael@0 1083 if (rv == PR_SUCCESS) {
michael@0 1084 ss->TCPconnected = 1;
michael@0 1085 } else {
michael@0 1086 int err = PR_GetError();
michael@0 1087 SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
michael@0 1088 SSL_GETPID(), ss->fd, err));
michael@0 1089 if (err == PR_IS_CONNECTED_ERROR) {
michael@0 1090 ss->TCPconnected = 1;
michael@0 1091 }
michael@0 1092 }
michael@0 1093
michael@0 1094 SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d",
michael@0 1095 SSL_GETPID(), ss->fd, rv));
michael@0 1096 return rv;
michael@0 1097 }
michael@0 1098
michael@0 1099 /*
michael@0 1100 * The TLS 1.2 RFC 5246, Section 7.2.1 says:
michael@0 1101 *
michael@0 1102 * Unless some other fatal alert has been transmitted, each party is
michael@0 1103 * required to send a close_notify alert before closing the write side
michael@0 1104 * of the connection. The other party MUST respond with a close_notify
michael@0 1105 * alert of its own and close down the connection immediately,
michael@0 1106 * discarding any pending writes. It is not required for the initiator
michael@0 1107 * of the close to wait for the responding close_notify alert before
michael@0 1108 * closing the read side of the connection.
michael@0 1109 *
michael@0 1110 * The second sentence requires that we send a close_notify alert when we
michael@0 1111 * have received a close_notify alert. In practice, all SSL implementations
michael@0 1112 * close the socket immediately after sending a close_notify alert (which is
michael@0 1113 * allowed by the third sentence), so responding with a close_notify alert
michael@0 1114 * would result in a write failure with the ECONNRESET error. This is why
michael@0 1115 * we don't respond with a close_notify alert.
michael@0 1116 *
michael@0 1117 * Also, in the unlikely event that the TCP pipe is full and the peer stops
michael@0 1118 * reading, the SSL3_SendAlert call in ssl_SecureClose and ssl_SecureShutdown
michael@0 1119 * may block indefinitely in blocking mode, and may fail (without retrying)
michael@0 1120 * in non-blocking mode.
michael@0 1121 */
michael@0 1122
michael@0 1123 int
michael@0 1124 ssl_SecureClose(sslSocket *ss)
michael@0 1125 {
michael@0 1126 int rv;
michael@0 1127
michael@0 1128 if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
michael@0 1129 !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
michael@0 1130 ss->firstHsDone &&
michael@0 1131 !ss->recvdCloseNotify &&
michael@0 1132 ss->ssl3.initialized) {
michael@0 1133
michael@0 1134 /* We don't want the final alert to be Nagle delayed. */
michael@0 1135 if (!ss->delayDisabled) {
michael@0 1136 ssl_EnableNagleDelay(ss, PR_FALSE);
michael@0 1137 ss->delayDisabled = 1;
michael@0 1138 }
michael@0 1139
michael@0 1140 (void) SSL3_SendAlert(ss, alert_warning, close_notify);
michael@0 1141 }
michael@0 1142 rv = ssl_DefClose(ss);
michael@0 1143 return rv;
michael@0 1144 }
michael@0 1145
michael@0 1146 /* Caller handles all locking */
michael@0 1147 int
michael@0 1148 ssl_SecureShutdown(sslSocket *ss, int nsprHow)
michael@0 1149 {
michael@0 1150 PRFileDesc *osfd = ss->fd->lower;
michael@0 1151 int rv;
michael@0 1152 PRIntn sslHow = nsprHow + 1;
michael@0 1153
michael@0 1154 if ((unsigned)nsprHow > PR_SHUTDOWN_BOTH) {
michael@0 1155 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
michael@0 1156 return PR_FAILURE;
michael@0 1157 }
michael@0 1158
michael@0 1159 if ((sslHow & ssl_SHUTDOWN_SEND) != 0 &&
michael@0 1160 ss->version >= SSL_LIBRARY_VERSION_3_0 &&
michael@0 1161 !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
michael@0 1162 ss->firstHsDone &&
michael@0 1163 !ss->recvdCloseNotify &&
michael@0 1164 ss->ssl3.initialized) {
michael@0 1165
michael@0 1166 (void) SSL3_SendAlert(ss, alert_warning, close_notify);
michael@0 1167 }
michael@0 1168
michael@0 1169 rv = osfd->methods->shutdown(osfd, nsprHow);
michael@0 1170
michael@0 1171 ss->shutdownHow |= sslHow;
michael@0 1172
michael@0 1173 return rv;
michael@0 1174 }
michael@0 1175
michael@0 1176 /************************************************************************/
michael@0 1177
michael@0 1178
michael@0 1179 int
michael@0 1180 ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
michael@0 1181 {
michael@0 1182 sslSecurityInfo *sec;
michael@0 1183 int rv = 0;
michael@0 1184
michael@0 1185 sec = &ss->sec;
michael@0 1186
michael@0 1187 if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
michael@0 1188 PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
michael@0 1189 return PR_FAILURE;
michael@0 1190 }
michael@0 1191 if (flags & ~PR_MSG_PEEK) {
michael@0 1192 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
michael@0 1193 return PR_FAILURE;
michael@0 1194 }
michael@0 1195
michael@0 1196 if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
michael@0 1197 ssl_GetXmitBufLock(ss);
michael@0 1198 if (ss->pendingBuf.len != 0) {
michael@0 1199 rv = ssl_SendSavedWriteData(ss);
michael@0 1200 if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
michael@0 1201 ssl_ReleaseXmitBufLock(ss);
michael@0 1202 return SECFailure;
michael@0 1203 }
michael@0 1204 }
michael@0 1205 ssl_ReleaseXmitBufLock(ss);
michael@0 1206 }
michael@0 1207
michael@0 1208 rv = 0;
michael@0 1209 /* If any of these is non-zero, the initial handshake is not done. */
michael@0 1210 if (!ss->firstHsDone) {
michael@0 1211 ssl_Get1stHandshakeLock(ss);
michael@0 1212 if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
michael@0 1213 rv = ssl_Do1stHandshake(ss);
michael@0 1214 }
michael@0 1215 ssl_Release1stHandshakeLock(ss);
michael@0 1216 }
michael@0 1217 if (rv < 0) {
michael@0 1218 return rv;
michael@0 1219 }
michael@0 1220
michael@0 1221 if (len == 0) return 0;
michael@0 1222
michael@0 1223 rv = DoRecv(ss, (unsigned char*) buf, len, flags);
michael@0 1224 SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
michael@0 1225 SSL_GETPID(), ss->fd, rv, PORT_GetError()));
michael@0 1226 return rv;
michael@0 1227 }
michael@0 1228
michael@0 1229 int
michael@0 1230 ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
michael@0 1231 {
michael@0 1232 return ssl_SecureRecv(ss, buf, len, 0);
michael@0 1233 }
michael@0 1234
michael@0 1235 /* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */
michael@0 1236 int
michael@0 1237 ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
michael@0 1238 {
michael@0 1239 int rv = 0;
michael@0 1240
michael@0 1241 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
michael@0 1242 SSL_GETPID(), ss->fd, len));
michael@0 1243
michael@0 1244 if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
michael@0 1245 PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
michael@0 1246 rv = PR_FAILURE;
michael@0 1247 goto done;
michael@0 1248 }
michael@0 1249 if (flags) {
michael@0 1250 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
michael@0 1251 rv = PR_FAILURE;
michael@0 1252 goto done;
michael@0 1253 }
michael@0 1254
michael@0 1255 ssl_GetXmitBufLock(ss);
michael@0 1256 if (ss->pendingBuf.len != 0) {
michael@0 1257 PORT_Assert(ss->pendingBuf.len > 0);
michael@0 1258 rv = ssl_SendSavedWriteData(ss);
michael@0 1259 if (rv >= 0 && ss->pendingBuf.len != 0) {
michael@0 1260 PORT_Assert(ss->pendingBuf.len > 0);
michael@0 1261 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 1262 rv = SECFailure;
michael@0 1263 }
michael@0 1264 }
michael@0 1265 ssl_ReleaseXmitBufLock(ss);
michael@0 1266 if (rv < 0) {
michael@0 1267 goto done;
michael@0 1268 }
michael@0 1269
michael@0 1270 if (len > 0)
michael@0 1271 ss->writerThread = PR_GetCurrentThread();
michael@0 1272 /* If any of these is non-zero, the initial handshake is not done. */
michael@0 1273 if (!ss->firstHsDone) {
michael@0 1274 PRBool falseStart = PR_FALSE;
michael@0 1275 ssl_Get1stHandshakeLock(ss);
michael@0 1276 if (ss->opt.enableFalseStart &&
michael@0 1277 ss->version >= SSL_LIBRARY_VERSION_3_0) {
michael@0 1278 ssl_GetSSL3HandshakeLock(ss);
michael@0 1279 falseStart = ss->ssl3.hs.canFalseStart;
michael@0 1280 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1281 }
michael@0 1282 if (!falseStart &&
michael@0 1283 (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
michael@0 1284 rv = ssl_Do1stHandshake(ss);
michael@0 1285 }
michael@0 1286 ssl_Release1stHandshakeLock(ss);
michael@0 1287 }
michael@0 1288 if (rv < 0) {
michael@0 1289 ss->writerThread = NULL;
michael@0 1290 goto done;
michael@0 1291 }
michael@0 1292
michael@0 1293 /* Check for zero length writes after we do housekeeping so we make forward
michael@0 1294 * progress.
michael@0 1295 */
michael@0 1296 if (len == 0) {
michael@0 1297 rv = 0;
michael@0 1298 goto done;
michael@0 1299 }
michael@0 1300 PORT_Assert(buf != NULL);
michael@0 1301 if (!buf) {
michael@0 1302 PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
michael@0 1303 rv = PR_FAILURE;
michael@0 1304 goto done;
michael@0 1305 }
michael@0 1306
michael@0 1307 if (!ss->firstHsDone) {
michael@0 1308 PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
michael@0 1309 #ifdef DEBUG
michael@0 1310 ssl_GetSSL3HandshakeLock(ss);
michael@0 1311 PORT_Assert(ss->ssl3.hs.canFalseStart);
michael@0 1312 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1313 #endif
michael@0 1314 SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
michael@0 1315 SSL_GETPID(), ss->fd));
michael@0 1316 }
michael@0 1317
michael@0 1318 /* Send out the data using one of these functions:
michael@0 1319 * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
michael@0 1320 * ssl3_SendApplicationData
michael@0 1321 */
michael@0 1322 ssl_GetXmitBufLock(ss);
michael@0 1323 rv = (*ss->sec.send)(ss, buf, len, flags);
michael@0 1324 ssl_ReleaseXmitBufLock(ss);
michael@0 1325 ss->writerThread = NULL;
michael@0 1326 done:
michael@0 1327 if (rv < 0) {
michael@0 1328 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
michael@0 1329 SSL_GETPID(), ss->fd, rv, PORT_GetError()));
michael@0 1330 } else {
michael@0 1331 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
michael@0 1332 SSL_GETPID(), ss->fd, rv));
michael@0 1333 }
michael@0 1334 return rv;
michael@0 1335 }
michael@0 1336
michael@0 1337 int
michael@0 1338 ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len)
michael@0 1339 {
michael@0 1340 return ssl_SecureSend(ss, buf, len, 0);
michael@0 1341 }
michael@0 1342
michael@0 1343 SECStatus
michael@0 1344 SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
michael@0 1345 {
michael@0 1346 sslSocket *ss;
michael@0 1347
michael@0 1348 ss = ssl_FindSocket(fd);
michael@0 1349 if (!ss) {
michael@0 1350 SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook",
michael@0 1351 SSL_GETPID(), fd));
michael@0 1352 return SECFailure;
michael@0 1353 }
michael@0 1354
michael@0 1355 ss->handleBadCert = f;
michael@0 1356 ss->badCertArg = arg;
michael@0 1357
michael@0 1358 return SECSuccess;
michael@0 1359 }
michael@0 1360
michael@0 1361 /*
michael@0 1362 * Allow the application to pass the url or hostname into the SSL library
michael@0 1363 * so that we can do some checking on it. It will be used for the value in
michael@0 1364 * SNI extension of client hello message.
michael@0 1365 */
michael@0 1366 SECStatus
michael@0 1367 SSL_SetURL(PRFileDesc *fd, const char *url)
michael@0 1368 {
michael@0 1369 sslSocket * ss = ssl_FindSocket(fd);
michael@0 1370 SECStatus rv = SECSuccess;
michael@0 1371
michael@0 1372 if (!ss) {
michael@0 1373 SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL",
michael@0 1374 SSL_GETPID(), fd));
michael@0 1375 return SECFailure;
michael@0 1376 }
michael@0 1377 ssl_Get1stHandshakeLock(ss);
michael@0 1378 ssl_GetSSL3HandshakeLock(ss);
michael@0 1379
michael@0 1380 if ( ss->url ) {
michael@0 1381 PORT_Free((void *)ss->url); /* CONST */
michael@0 1382 }
michael@0 1383
michael@0 1384 ss->url = (const char *)PORT_Strdup(url);
michael@0 1385 if ( ss->url == NULL ) {
michael@0 1386 rv = SECFailure;
michael@0 1387 }
michael@0 1388
michael@0 1389 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1390 ssl_Release1stHandshakeLock(ss);
michael@0 1391
michael@0 1392 return rv;
michael@0 1393 }
michael@0 1394
michael@0 1395 /*
michael@0 1396 * Allow the application to pass the set of trust anchors
michael@0 1397 */
michael@0 1398 SECStatus
michael@0 1399 SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
michael@0 1400 {
michael@0 1401 sslSocket * ss = ssl_FindSocket(fd);
michael@0 1402 CERTDistNames *names = NULL;
michael@0 1403
michael@0 1404 if (!certList) {
michael@0 1405 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1406 return SECFailure;
michael@0 1407 }
michael@0 1408 if (!ss) {
michael@0 1409 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
michael@0 1410 SSL_GETPID(), fd));
michael@0 1411 return SECFailure;
michael@0 1412 }
michael@0 1413
michael@0 1414 names = CERT_DistNamesFromCertList(certList);
michael@0 1415 if (names == NULL) {
michael@0 1416 return SECFailure;
michael@0 1417 }
michael@0 1418 ssl_Get1stHandshakeLock(ss);
michael@0 1419 ssl_GetSSL3HandshakeLock(ss);
michael@0 1420 if (ss->ssl3.ca_list) {
michael@0 1421 CERT_FreeDistNames(ss->ssl3.ca_list);
michael@0 1422 }
michael@0 1423 ss->ssl3.ca_list = names;
michael@0 1424 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1425 ssl_Release1stHandshakeLock(ss);
michael@0 1426
michael@0 1427 return SECSuccess;
michael@0 1428 }
michael@0 1429
michael@0 1430 /*
michael@0 1431 ** Returns Negative number on error, zero or greater on success.
michael@0 1432 ** Returns the amount of data immediately available to be read.
michael@0 1433 */
michael@0 1434 int
michael@0 1435 SSL_DataPending(PRFileDesc *fd)
michael@0 1436 {
michael@0 1437 sslSocket *ss;
michael@0 1438 int rv = 0;
michael@0 1439
michael@0 1440 ss = ssl_FindSocket(fd);
michael@0 1441
michael@0 1442 if (ss && ss->opt.useSecurity) {
michael@0 1443 ssl_GetRecvBufLock(ss);
michael@0 1444 rv = ss->gs.writeOffset - ss->gs.readOffset;
michael@0 1445 ssl_ReleaseRecvBufLock(ss);
michael@0 1446 }
michael@0 1447
michael@0 1448 return rv;
michael@0 1449 }
michael@0 1450
michael@0 1451 SECStatus
michael@0 1452 SSL_InvalidateSession(PRFileDesc *fd)
michael@0 1453 {
michael@0 1454 sslSocket * ss = ssl_FindSocket(fd);
michael@0 1455 SECStatus rv = SECFailure;
michael@0 1456
michael@0 1457 if (ss) {
michael@0 1458 ssl_Get1stHandshakeLock(ss);
michael@0 1459 ssl_GetSSL3HandshakeLock(ss);
michael@0 1460
michael@0 1461 if (ss->sec.ci.sid && ss->sec.uncache) {
michael@0 1462 ss->sec.uncache(ss->sec.ci.sid);
michael@0 1463 rv = SECSuccess;
michael@0 1464 }
michael@0 1465
michael@0 1466 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1467 ssl_Release1stHandshakeLock(ss);
michael@0 1468 }
michael@0 1469 return rv;
michael@0 1470 }
michael@0 1471
michael@0 1472 SECItem *
michael@0 1473 SSL_GetSessionID(PRFileDesc *fd)
michael@0 1474 {
michael@0 1475 sslSocket * ss;
michael@0 1476 SECItem * item = NULL;
michael@0 1477
michael@0 1478 ss = ssl_FindSocket(fd);
michael@0 1479 if (ss) {
michael@0 1480 ssl_Get1stHandshakeLock(ss);
michael@0 1481 ssl_GetSSL3HandshakeLock(ss);
michael@0 1482
michael@0 1483 if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
michael@0 1484 item = (SECItem *)PORT_Alloc(sizeof(SECItem));
michael@0 1485 if (item) {
michael@0 1486 sslSessionID * sid = ss->sec.ci.sid;
michael@0 1487 if (sid->version < SSL_LIBRARY_VERSION_3_0) {
michael@0 1488 item->len = SSL2_SESSIONID_BYTES;
michael@0 1489 item->data = (unsigned char*)PORT_Alloc(item->len);
michael@0 1490 PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
michael@0 1491 } else {
michael@0 1492 item->len = sid->u.ssl3.sessionIDLength;
michael@0 1493 item->data = (unsigned char*)PORT_Alloc(item->len);
michael@0 1494 PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
michael@0 1495 }
michael@0 1496 }
michael@0 1497 }
michael@0 1498
michael@0 1499 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 1500 ssl_Release1stHandshakeLock(ss);
michael@0 1501 }
michael@0 1502 return item;
michael@0 1503 }
michael@0 1504
michael@0 1505 SECStatus
michael@0 1506 SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
michael@0 1507 {
michael@0 1508 sslSocket * ss;
michael@0 1509
michael@0 1510 ss = ssl_FindSocket(fd);
michael@0 1511 if (!ss)
michael@0 1512 return SECFailure;
michael@0 1513 if (!dbHandle) {
michael@0 1514 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1515 return SECFailure;
michael@0 1516 }
michael@0 1517 ss->dbHandle = dbHandle;
michael@0 1518 return SECSuccess;
michael@0 1519 }
michael@0 1520
michael@0 1521 /* DO NOT USE. This function was exported in ssl.def with the wrong signature;
michael@0 1522 * this implementation exists to maintain link-time compatibility.
michael@0 1523 */
michael@0 1524 int
michael@0 1525 SSL_RestartHandshakeAfterCertReq(sslSocket * ss,
michael@0 1526 CERTCertificate * cert,
michael@0 1527 SECKEYPrivateKey * key,
michael@0 1528 CERTCertificateList *certChain)
michael@0 1529 {
michael@0 1530 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
michael@0 1531 return -1;
michael@0 1532 }
michael@0 1533
michael@0 1534 /* DO NOT USE. This function was exported in ssl.def with the wrong signature;
michael@0 1535 * this implementation exists to maintain link-time compatibility.
michael@0 1536 */
michael@0 1537 int
michael@0 1538 SSL_RestartHandshakeAfterServerCert(sslSocket * ss)
michael@0 1539 {
michael@0 1540 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
michael@0 1541 return -1;
michael@0 1542 }
michael@0 1543
michael@0 1544 /* See documentation in ssl.h */
michael@0 1545 SECStatus
michael@0 1546 SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error)
michael@0 1547 {
michael@0 1548 SECStatus rv;
michael@0 1549 sslSocket *ss = ssl_FindSocket(fd);
michael@0 1550
michael@0 1551 if (!ss) {
michael@0 1552 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_AuthCertificateComplete",
michael@0 1553 SSL_GETPID(), fd));
michael@0 1554 return SECFailure;
michael@0 1555 }
michael@0 1556
michael@0 1557 ssl_Get1stHandshakeLock(ss);
michael@0 1558
michael@0 1559 if (!ss->ssl3.initialized) {
michael@0 1560 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1561 rv = SECFailure;
michael@0 1562 } else if (ss->version < SSL_LIBRARY_VERSION_3_0) {
michael@0 1563 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
michael@0 1564 rv = SECFailure;
michael@0 1565 } else {
michael@0 1566 rv = ssl3_AuthCertificateComplete(ss, error);
michael@0 1567 }
michael@0 1568
michael@0 1569 ssl_Release1stHandshakeLock(ss);
michael@0 1570
michael@0 1571 return rv;
michael@0 1572 }
michael@0 1573
michael@0 1574 /* For more info see ssl.h */
michael@0 1575 SECStatus
michael@0 1576 SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
michael@0 1577 void *arg)
michael@0 1578 {
michael@0 1579 sslSocket *ss;
michael@0 1580
michael@0 1581 ss = ssl_FindSocket(fd);
michael@0 1582 if (!ss) {
michael@0 1583 SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook",
michael@0 1584 SSL_GETPID(), fd));
michael@0 1585 return SECFailure;
michael@0 1586 }
michael@0 1587
michael@0 1588 ss->sniSocketConfig = func;
michael@0 1589 ss->sniSocketConfigArg = arg;
michael@0 1590 return SECSuccess;
michael@0 1591 }

mercurial