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 + -
显示快捷键?