PageRenderTime 78ms CodeModel.GetById 10ms app.highlight 57ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/ssl/sslsecur.c

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