sslcon.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,213 行 · 第 1/5 页

C
2,213
字号
    (*sec->hash->update)(sec->hashcx, seq, 4);    /* Get result */    (*sec->hash->end)(sec->hashcx, result, &nout, sec->hash->length);    return SECSuccess;}/*** Maximum transmission amounts. These are tiny bit smaller than they** need to be (they account for the MAC length plus some padding),** assuming the MAC is 16 bytes long and the padding is a max of 7 bytes** long. This gives an additional 9 bytes of slop to work within.*/#define MAX_STREAM_CYPHER_LEN	0x7fe0#define MAX_BLOCK_CYPHER_LEN	0x3fe0/*** Send some data in the clear. ** Package up data with the length header and send it.**** Return count of bytes succesfully written, or negative number (failure).*/static PRInt32 ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags){    sslSecurityInfo * sec	= ss->sec;    PRUint8         * out;    int               rv;    int               amount;    int               count	= 0;    PORT_Assert(sec != 0);    PORT_Assert( ssl_HaveXmitBufLock(ss) );    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear",		 SSL_GETPID(), ss->fd, len));    PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len));    while (len) {	amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN );	if (amount + 2 > sec->writeBuf.space) {	    rv = sslBuffer_Grow(&sec->writeBuf, amount + 2);	    if (rv != SECSuccess) {		count = rv;		break;	    }	}	out = sec->writeBuf.buf;	/*	** Construct message.	*/	out[0] = 0x80 | MSB(amount);	out[1] = LSB(amount);	PORT_Memcpy(&out[2], in, amount);	/* Now send the data */	rv = ssl_DefSend(ss, out, amount + 2, flags & ~ssl_SEND_FLAG_MASK);	if (rv < 0) {	    if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {		rv = 0;	    } else {		/* Return short write if some data already went out... */		if (count == 0)		    count = rv;		break;	    }	}	if ((unsigned)rv < (amount + 2)) {	    /* Short write.  Save the data and return. */	    if (ssl_SaveWriteData(ss, &ss->pendingBuf, out + rv,				   amount + 2 - rv) == SECFailure) {		count = SECFailure;	    } else {		count += amount;		sec->sendSequence++;	    }	    break;	}	sec->sendSequence++;	in    += amount;	count += amount;	len   -= amount;    }    return count;}/*** Send some data, when using a stream cipher. Stream ciphers have a** block size of 1. Package up the data with the length header** and send it.*/static PRInt32 ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags){    sslSecurityInfo *sec	= ss->sec;    PRUint8       *  out;    int              rv;    int              count	= 0;    int              amount;    PRUint8          macLen;    int              nout;    int              buflen;    PORT_Assert(sec != 0);    PORT_Assert( ssl_HaveXmitBufLock(ss) );    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher",		 SSL_GETPID(), ss->fd, len));    PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len));    while (len) {	ssl_GetSpecReadLock(ss);  /*************************************/	macLen = sec->hash->length;	amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN );	buflen = amount + 2 + macLen;	if (buflen > sec->writeBuf.space) {	    rv = sslBuffer_Grow(&sec->writeBuf, buflen);	    if (rv != SECSuccess) {		goto loser;	    }	}	out    = sec->writeBuf.buf;	nout   = amount + macLen;	out[0] = 0x80 | MSB(nout);	out[1] = LSB(nout);	/* Calculate MAC */	rv = ssl2_CalcMAC(out+2, 		/* put MAC here */	                  sec, 		          in, amount, 		/* input addr & length */			  0); 			/* no padding */	if (rv != SECSuccess) 	    goto loser;	/* Encrypt MAC */	rv = (*sec->enc)(sec->writecx, out+2, &nout, macLen, out+2, macLen);	if (rv) goto loser;	/* Encrypt data from caller */	rv = (*sec->enc)(sec->writecx, out+2+macLen, &nout, amount, in, amount);	if (rv) goto loser;	ssl_ReleaseSpecReadLock(ss);  /*************************************/	PRINT_BUF(50, (ss, "encrypted data:", out, buflen));	rv = ssl_DefSend(ss, out, buflen, flags & ~ssl_SEND_FLAG_MASK);	if (rv < 0) {	    if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {		SSL_TRC(50, ("%d: SSL[%d]: send stream would block, "			     "saving data", SSL_GETPID(), ss->fd));		rv = 0;	    } else {		SSL_TRC(10, ("%d: SSL[%d]: send stream error %d",			     SSL_GETPID(), ss->fd, PORT_GetError()));		/* Return short write if some data already went out... */		if (count == 0)		    count = rv;		goto done;	    }	}	if ((unsigned)rv < buflen) {	    /* Short write.  Save the data and return. */	    if (ssl_SaveWriteData(ss, &ss->pendingBuf, out + rv,				  buflen - rv) == SECFailure) {		count = SECFailure;	    } else {	    	count += amount;		sec->sendSequence++;	    }	    goto done;	}	sec->sendSequence++;	in    += amount;	count += amount;	len   -= amount;    }done:    return count;loser:    ssl_ReleaseSpecReadLock(ss);    return SECFailure;}/*** Send some data, when using a block cipher. Package up the data with** the length header and send it.*//* XXX assumes blocksize is > 7 */static PRInt32ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags){    sslSecurityInfo *sec	= ss->sec;    PRUint8       *  out;  		    /* begining of output buffer.    */    PRUint8       *  op;		    /* next output byte goes here.   */    int              rv;		    /* value from funcs we called.   */    int              count	= 0;        /* this function's return value. */    unsigned int     hlen;		    /* output record hdr len, 2 or 3 */    unsigned int     macLen;		    /* MAC is this many bytes long.  */    int              amount;		    /* of plaintext to go in record. */    unsigned int     padding;		    /* add this many padding byte.   */    int              nout;		    /* ciphertext size after header. */    int              buflen;		    /* size of generated record.     */    PORT_Assert(sec != 0);    PORT_Assert( ssl_HaveXmitBufLock(ss) );    SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher",		 SSL_GETPID(), ss->fd, len));    PRINT_BUF(50, (ss, "clear data:", in, len));    while (len) {	ssl_GetSpecReadLock(ss);  /*************************************/	macLen = sec->hash->length;	/* Figure out how much to send, including mac and padding */	amount  = PR_MIN( len, MAX_BLOCK_CYPHER_LEN );	nout    = amount + macLen;	padding = nout & (sec->blockSize - 1);	if (padding) {	    hlen    = 3;	    padding = sec->blockSize - padding;	    nout   += padding;	} else {	    hlen = 2;	}	buflen = hlen + nout;	if (buflen > sec->writeBuf.space) {	    rv = sslBuffer_Grow(&sec->writeBuf, buflen);	    if (rv != SECSuccess) {		goto loser;	    }	}	out = sec->writeBuf.buf;	/* Construct header */	op = out;	if (padding) {	    *op++ = MSB(nout);	    *op++ = LSB(nout);	    *op++ = padding;	} else {	    *op++ = 0x80 | MSB(nout);	    *op++ = LSB(nout);	}	/* Calculate MAC */	rv = ssl2_CalcMAC(op, 		/* MAC goes here. */	                  sec, 		          in, amount, 	/* intput addr, len */			  padding);	if (rv != SECSuccess) 	    goto loser;	op += macLen;	/* Copy in the input data */	/* XXX could eliminate the copy by folding it into the encryption */	PORT_Memcpy(op, in, amount);	op += amount;	if (padding) {	    PORT_Memset(op, padding, padding);	    op += padding;	}	/* Encrypt result */	rv = (*sec->enc)(sec->writecx, out+hlen, &nout, buflen-hlen,			 out+hlen, op - (out + hlen));	if (rv) 	    goto loser;	ssl_ReleaseSpecReadLock(ss);  /*************************************/	PRINT_BUF(50, (ss, "final xmit data:", out, op - out));	rv = ssl_DefSend(ss, out, op - out, flags & ~ssl_SEND_FLAG_MASK);	if (rv < 0) {	    if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {		rv = 0;	    } else {		SSL_TRC(10, ("%d: SSL[%d]: send block error %d",			     SSL_GETPID(), ss->fd, PORT_GetError()));		/* Return short write if some data already went out... */		if (count == 0)		    count = rv;		goto done;	    }	}	if (rv < (op - out)) {	    /* Short write.  Save the data and return. */	    if (ssl_SaveWriteData(ss, &ss->pendingBuf, out + rv,				  op - out - rv) == SECFailure) {		count = SECFailure;	    } else {		count += amount;		sec->sendSequence++;	    }	    goto done;	}	sec->sendSequence++;	in    += amount;	count += amount;	len   -= amount;    }done:    return count;loser:    ssl_ReleaseSpecReadLock(ss);    return SECFailure;}/*** Called from: ssl2_HandleServerHelloMessage,**              ssl2_HandleClientSessionKeyMessage,**              ssl2_RestartHandshakeAfterServerCert,**              ssl2_HandleClientHelloMessage,**              */static voidssl2_UseEncryptedSendFunc(sslSocket *ss){    sslSecurityInfo *sec;    ssl_GetXmitBufLock(ss);    PORT_Assert(ss->sec != 0);    sec = ss->sec;    PORT_Assert(sec->hashcx != 0);    ss->gather->encrypted = 1;    sec->send = (sec->blockSize > 1) ? ssl2_SendBlock : ssl2_SendStream;    ssl_ReleaseXmitBufLock(ss);}/* Called while initializing socket in ssl_CreateSecurityInfo().** This function allows us to keep the name of ssl2_SendClear static.*/voidssl2_UseClearSendFunc(sslSocket *ss){    ss->sec->send = ssl2_SendClear;}/************************************************************************** 			END of Send functions.                          * *************************************************************************//*********************************************************************** * For SSL3, this gathers in and handles records/messages until either  *	the handshake is complete or application data is available. * * For SSL2, this gathers in only the next SSLV2 record. * * Called from ssl_Do1stHandshake() via function pointer ss->handshake. * Caller must hold handshake lock. * This function acquires and releases the RecvBufLock. * * returns SECSuccess for success. * returns SECWouldBlock when that value is returned by ssl2_GatherRecord() or *	ssl3_GatherCompleteHandshake(). * returns SECFailure on all other errors. * * The gather functions called by ssl_GatherRecord1stHandshake are expected  * 	to return values interpreted as follows: *  1 : the function completed without error. *  0 : the function read EOF. * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. * -2 : the function wants ssl_GatherRecord1stHandshake to be called again  *	immediately, by ssl_Do1stHandshake. * * This code is similar to, and easily confused with, DoRecv() in sslsecur.c * * This function is called from ssl_Do1stHandshake().   * The following functions put ssl_GatherRecord1stHandshake into ss->handshake: *	ssl2_HandleMessage *	ssl2_HandleVerifyMessage *	ssl2_HandleServerHelloMessage *	ssl2_BeginClientHandshake	 *	ssl2_HandleClientSessionKeyMessage *	ssl2_RestartHandshakeAfterCertReq  *	ssl3_RestartHandshakeAfterCertReq  *	ssl2_RestartHandshakeAfterServerCert  *	ssl3_RestartHandshakeAfterServerCert  *	ssl2_HandleClientHelloMessage *	ssl2_BeginServerHandshake */SECStatusssl_GatherRecord1stHandshake(sslSocket *ss){    int rv;    PORT_Assert((ss->sec != 0) && (ss->gather != 0));    PORT_Assert( ssl_Have1stHandshakeLock(ss) );    ssl_GetRecvBufLock(ss);    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {	/* Wait for handshake to complete, or application data to arrive.  */	rv = ssl3_GatherCompleteHandshake(ss, 0);    } else {	/* See if we have a complete record */	rv = ssl2_GatherRecord(ss, 0);    }    SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d",		 SSL_GETPID(), ss->fd, rv));    ssl_ReleaseRecvBufLock(ss);    if (rv <= 0) {	if (rv == SECWouldBlock) {	    /* Progress is blocked waiting for callback completion.  */	    SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",			 SSL_GETPID(), ss->fd, ss->gather->remainder));	    return SECWouldBlock;	}	if (rv == 0) {	    /* EOF. Loser  */	    PORT_SetError(PR_END_OF_FILE_ERROR);	}	return SECFailure;	/* rv is < 0 here. */    }    SSL_TRC(10, ("%d: SSL[%d]: got handshake record of %d bytes",		 SSL_GETPID(), ss->fd, ss->gather->recordLen));    ss->handshake = 0;	/* makes ssl_Do1stHandshake call ss->nextHandshake.*/    return SECSuccess;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?