} rv = cwSpec->encode( cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH, &cipherBytes, bufSize, write->buf + SSL3_RECORD_HEADER_LENGTH, fragLen);
p2Len = fragLen - p1Len; } if (p1Len < 256) { oddLen = p1Len; p1Len = 0; } else { p1Len -= oddLen; } if (oddLen) { p2Len += oddLen; PORT_Assert( (cipher_def->block_size < 2) || \ (p2Len % cipher_def->block_size) == 0); memcpy(write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, buf + p1Len, oddLen); } if (p1Len > 0) { rv = cwSpec->encode( cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH,  &cipherBytes,                            p1Len,                                   buf, p1Len);                       PORT_Assert(rv == SECSuccess && cipherBytes == p1Len); if (rv != SECSuccess || cipherBytes != p1Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); goto spec_locked_loser; } } if (p2Len > 0) { PRInt32 cipherBytesPart2 = -1; rv = cwSpec->encode( cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, &cipherBytesPart2,           p2Len,                              write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, p2Len);                             PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len); if (rv != SECSuccess || cipherBytesPart2 != p2Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); goto spec_locked_loser; } cipherBytes += cipherBytesPart2; }
ssl3_SendRecord(   sslSocket *        ss,                   SSL3ContentType    type,		   const SSL3Opaque * buf,		   PRInt32            bytes,		   PRInt32            flags){    ssl3CipherSpec *          cwSpec;    sslBuffer      *          write 	  = &ss->sec.writeBuf;    const ssl3BulkCipherDef * cipher_def;    SECStatus                 rv;    PRUint32                  bufSize     =  0;    PRInt32                   sent        =  0;    PRInt32                   cipherBytes = -1;    PRBool                    isBlocking  = ssl_SocketIsBlocking(ss);    PRBool                    ssl3WasNull = PR_FALSE;    SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s bytes=%d",		SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),		bytes));    PRINT_BUF(3, (ss, "Send record (plain text)", buf, bytes));    PORT_Assert( ssl_HaveXmitBufLock(ss) );    if (ss->ssl3 == NULL) {	/* This can happen on a server if the very first incoming record	** looks like a defective ssl3 record (e.g. too long), and we're	** trying to send an alert.	*/	ssl3WasNull = PR_TRUE;	PR_ASSERT(type == content_alert);	rv = ssl3_InitState(ss);	if (rv != SECSuccess) {	    return SECFailure;	/* ssl3_InitState has set the error code. */    	}    }    /* check for Token Presence */    if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {	PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);	return SECFailure;    }    while (bytes > 0) {    	PRInt32   count;	PRUint32  contentLen;	PRUint32  fragLen;	PRUint32  macLen;	contentLen = PR_MIN(bytes, MAX_FRAGMENT_LENGTH);	if (write->space < contentLen + SSL3_BUFFER_FUDGE) {	    rv = sslBuffer_Grow(write, contentLen + SSL3_BUFFER_FUDGE);	    if (rv != SECSuccess) {		SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",			 SSL_GETPID(), ss->fd, contentLen + SSL3_BUFFER_FUDGE));		return SECFailure; /* sslBuffer_Grow set a memory error code. */	    }	}	/* This variable records the actual size of the buffer allocated above.	 * Some algorithms may expand the number of bytes needed to send data. 	 * If we only supply the output buffer with the same number	 * of bytes as the input buffer, we will fail.	 */	bufSize = contentLen + SSL3_BUFFER_FUDGE;	/*	 * null compression is easy to do	 */	PORT_Memcpy(write->buf + SSL3_RECORD_HEADER_LENGTH, buf, contentLen);	buf   += contentLen;	bytes -= contentLen;	PORT_Assert( bytes >= 0 );	ssl_GetSpecReadLock(ss);	/********************************/	cwSpec = ss->ssl3->cwSpec;	cipher_def = cwSpec->cipher_def;	/*	 * Add the MAC	 */	rv = ssl3_ComputeRecordMAC(	    cwSpec, (ss->sec.isServer) ? cwSpec->server.write_mac_context	                               : cwSpec->client.write_mac_context,	    type, cwSpec->version, cwSpec->write_seq_num,	    write->buf + SSL3_RECORD_HEADER_LENGTH, contentLen,	    write->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen);	if (rv != SECSuccess) {	    ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);	    goto spec_locked_loser;	}	fragLen = contentLen + macLen;	/* needs to be encrypted */	PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);	/*	 * Pad the text (if we're doing a block cipher)	 * then Encrypt it	 */	if (cipher_def->type == type_block) {	    int             padding_length;	    int             i;	    unsigned char * pBuf;	    /* Assume blockSize is a power of two */	    padding_length = cipher_def->block_size - 1 -		((fragLen) & (cipher_def->block_size - 1));	    fragLen += padding_length + 1;	    PORT_Assert((fragLen % cipher_def->block_size) == 0);	    /* Pad according to TLS rules (also acceptable to SSL3). */	    pBuf = &write->buf[fragLen + SSL3_RECORD_HEADER_LENGTH - 1];	    for (i = padding_length + 1; i > 0; --i) {	    	*pBuf-- = padding_length;	    }	}	rv = cwSpec->encode(	    cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH,	    &cipherBytes, bufSize, write->buf + SSL3_RECORD_HEADER_LENGTH,	    fragLen);	if (rv != SECSuccess) {	    ssl_MapLowLevelError(SSL_ERROR_ENCRYPTION_FAILURE);spec_locked_loser:	    ssl_ReleaseSpecReadLock(ss);	    return SECFailure;	}	PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);	/*	 * XXX should we zero out our copy of the buffer after compressing	 * and encryption ??	 */	ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);	ssl_ReleaseSpecReadLock(ss); /************************************/	/* PORT_Assert(fragLen == cipherBytes); */	write->len    = cipherBytes + SSL3_RECORD_HEADER_LENGTH;	write->buf[0] = type;	write->buf[1] = MSB(cwSpec->version);	write->buf[2] = LSB(cwSpec->version);	write->buf[3] = MSB(cipherBytes);	write->buf[4] = LSB(cipherBytes);	PRINT_BUF(50, (ss, "send (encrypted) record data:", write->buf, write->len));	/* If there's still some previously saved ciphertext,	 * or the caller doesn't want us to send the data yet,	 * then add all our new ciphertext to the amount previously saved.	 */	if ((ss->pendingBuf.len > 0) ||	    (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {	    rv = ssl_SaveWriteData(ss, &ss->pendingBuf,				   write->buf, write->len);	    if (rv != SECSuccess) {		/* presumably a memory error, SEC_ERROR_NO_MEMORY */		return SECFailure;	    }	    write->len = 0;	/* All cipher text is saved away. */	    if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {		ss->handshakeBegun = 1;		count = ssl_SendSavedWriteData(ss, &ss->pendingBuf,		                               &ssl_DefSend);		if (count < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {		    ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);		    return SECFailure;		}	    }	} else if (write->len > 0) {	    ss->handshakeBegun = 1;	    count = ssl_DefSend(ss, write->buf, write->len,				flags & ~ssl_SEND_FLAG_MASK);	    if (count < 0) {		if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {		    ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);		    return (sent > 0) ? sent : SECFailure;		}		/* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */		count = 0;	    }	    /* now take all the remaining unsent newly-generated ciphertext and	     * append it to the buffer of previously unsent ciphertext.	     */	    if ((unsigned)count < write->len) {		rv = ssl_SaveWriteData(ss, &ss->pendingBuf,				       write->buf + (unsigned)count,				       write->len - (unsigned)count);		if (rv != SECSuccess) {		    /* presumably a memory error, SEC_ERROR_NO_MEMORY */		    return SECFailure;		}	    }	    write->len = 0;	}	sent += contentLen;	if ((flags & ssl_SEND_FLAG_NO_BUFFER) &&	    (isBlocking || (ss->pendingBuf.len > 0))) {	    break;	}    }    return sent;}