📄 ssl_tls_c.htm
字号:
ssl->out_msg, ssl->out_msglen );
break;
#endif
default:
return( ERR_SSL_FEATURE_UNAVAILABLE );
}
}
return( 0 );
}
static int ssl_decrypt_buf( ssl_context *ssl )
{
int i, padlen;
unsigned char tmp[20];
if( ssl->in_msglen < ssl->minlen )
return( ERR_SSL_INVALID_MAC );
if( ssl->ivlen == 0 )
{
#if !defined(NO_ARC4)
padlen = 0;
arc4_crypt( (arc4_context *) ssl->ctx_dec,
ssl->in_msg, ssl->in_msglen );
#else
return( ERR_SSL_FEATURE_UNAVAILABLE );
#endif
}
else
{
/*
* Decrypt and check the padding
*/
if( ssl->in_msglen % ssl->ivlen != 0 )
return( ERR_SSL_INVALID_MAC );
switch( ssl->ivlen )
{
#if !defined(NO_DES)
case 8:
des3_cbc_decrypt( (des3_context *) ssl->ctx_dec,
ssl->iv_dec, ssl->in_msg,
ssl->in_msg, ssl->in_msglen );
break;
#endif
#if !defined(NO_AES)
case 16:
aes_cbc_decrypt( (aes_context *) ssl->ctx_dec,
ssl->iv_dec, ssl->in_msg,
ssl->in_msg, ssl->in_msglen );
break;
#endif
default:
return( ERR_SSL_FEATURE_UNAVAILABLE );
}
padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
if( ssl->minor_ver == SSLV3_MINOR_VERSION )
{
if( padlen > ssl->ivlen )
padlen = 0;
}
else
{
for( i = 1; i <= (int) padlen; i++ )
if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 )
padlen = 0;
}
}
/*
* Always compute the MAC (RFC4346, CBCTIME).
*/
ssl->in_msglen -= ( ssl->maclen + padlen );
ssl->in_hdr[3] = ssl->in_msglen >> 8;
ssl->in_hdr[4] = ssl->in_msglen;
memcpy( tmp, ssl->in_msg + ssl->in_msglen, 20 );
if( ssl->minor_ver == SSLV3_MINOR_VERSION )
{
if( ssl->maclen == 16 )
ssl_mac_md5( ssl->mac_dec,
ssl->in_msg, ssl->in_msglen,
ssl->in_ctr, ssl->in_msgtype );
else
ssl_mac_sha1( ssl->mac_dec,
ssl->in_msg, ssl->in_msglen,
ssl->in_ctr, ssl->in_msgtype );
}
else
{
if( ssl->maclen == 16 )
md5_hmac( ssl->mac_dec, 16,
ssl->in_ctr, ssl->in_msglen + 13,
ssl->in_msg + ssl->in_msglen );
else
sha1_hmac( ssl->mac_dec, 20,
ssl->in_ctr, ssl->in_msglen + 13,
ssl->in_msg + ssl->in_msglen );
}
if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
ssl->maclen ) != 0 )
return( ERR_SSL_INVALID_MAC );
/*
* Finally verify the padding length; bad padding
* will produce the same error as an invalid MAC.
*/
if( ssl->ivlen != 0 && padlen == 0 )
return( ERR_SSL_INVALID_MAC );
if( ssl->in_msglen == 0 )
{
ssl->nb_zero++;
/*
* Three or more empty messages may be a DoS attack.
*/
if( ssl->nb_zero > 2 )
return( ERR_SSL_INVALID_MAC );
}
else
ssl->nb_zero = 0;
for( i = 7; i >= 0; i-- )
if( ++ssl->in_ctr[i] != 0 )
break;
return( 0 );
}
/*
* Record layer functions
*/
int ssl_write_record( ssl_context *ssl, int do_crypt )
{
int ret, len = ssl->out_msglen;
ssl->out_hdr[0] = ssl->out_msgtype;
ssl->out_hdr[1] = ssl->major_ver;
ssl->out_hdr[2] = ssl->minor_ver;
ssl->out_hdr[3] = len >> 8;
ssl->out_hdr[4] = len;
if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
{
ssl->out_msg[1] = ( len - 4 ) >> 16;
ssl->out_msg[2] = ( len - 4 ) >> 8;
ssl->out_msg[3] = ( len - 4 );
md5_update( &ssl->hs_md5 , ssl->out_msg, len );
sha1_update( &ssl->hs_sha1, ssl->out_msg, len );
}
if( do_crypt != 0 )
{
if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
return( ret );
len = ssl->out_msglen;
ssl->out_hdr[3] = len >> 8;
ssl->out_hdr[4] = len;
}
ssl->out_left = 5 + ssl->out_msglen;
return( net_send( ssl->write_fd,
ssl->out_hdr,
&ssl->out_left ) );
}
int ssl_read_record( ssl_context *ssl, int do_crypt )
{
int ret, len;
if( ssl->in_hslen != 0 &&
ssl->in_hslen < ssl->in_msglen )
{
/*
* Get next Handshake message in the current record
*/
ssl->in_msglen -= ssl->in_hslen;
memcpy( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
ssl->in_msglen );
if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
return( ERR_SSL_INVALID_RECORD );
ssl->in_hslen = 4;
ssl->in_hslen += ( (int) ssl->in_msg[2] << 8 )
| ( (int) ssl->in_msg[3] );
if( ssl->in_msglen < ssl->in_hslen )
return( ERR_SSL_INVALID_RECORD );
return( 0 );
}
ssl->in_hslen = 0;
/*
* Read the record header and validate it
*/
if( ssl->in_left < 5 )
{
len = 5 - ssl->in_left;
ret = net_recv( ssl->read_fd, ssl->in_hdr
+ ssl->in_left, &len );
ssl->in_left += len;
if( ret != 0 )
return( ret );
}
ssl->in_msgtype = ssl->in_hdr[0];
ssl->in_msglen = ( (int) ssl->in_hdr[3] << 8 )
| ( (int) ssl->in_hdr[4] );
if( ssl->in_hdr[1] != ssl->major_ver )
return( ERR_SSL_INVALID_RECORD );
if( ssl->in_hdr[2] != SSLV3_MINOR_VERSION &&
ssl->in_hdr[2] != TLS10_MINOR_VERSION )
return( ERR_SSL_INVALID_RECORD );
/*
* Make sure the message length is acceptable
*/
if( do_crypt == 0 )
{
if( ssl->in_msglen < 1 ||
ssl->in_msglen > SSL_MAX_CONTENT_LEN )
return( ERR_SSL_INVALID_RECORD );
}
else
{
if( ssl->in_msglen < ssl->minlen )
return( ERR_SSL_INVALID_RECORD );
if( ssl->minor_ver == 0 &&
ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN )
return( ERR_SSL_INVALID_RECORD );
/*
* TLS encrypted messages can have up to 256 bytes of padding
*/
if( ssl->minor_ver != 0 &&
ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
return( ERR_SSL_INVALID_RECORD );
}
/*
* Read and optionally decrypt the message contents
*/
len = ssl->in_msglen - ( ssl->in_left - 5 );
ret = net_recv( ssl->read_fd, ssl->in_hdr
+ ssl->in_left, &len );
ssl->in_left += len;
if( ret != 0 )
return( ret );
if( do_crypt != 0 )
{
if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
return( ret );
if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
return( ERR_SSL_INVALID_RECORD );
}
if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
{
/*
* Additional checks to validate the handshake header
*/
if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
return( ERR_SSL_INVALID_RECORD );
ssl->in_hslen = 4;
ssl->in_hslen += ( (int) ssl->in_msg[2] << 8 )
| ( (int) ssl->in_msg[3] );
if( ssl->in_msglen < ssl->in_hslen )
return( ERR_SSL_INVALID_RECORD );
md5_update( &ssl->hs_md5 , ssl->in_msg, ssl->in_msglen );
sha1_update( &ssl->hs_sha1, ssl->in_msg, ssl->in_msglen );
}
if( ssl->in_msgtype == SSL_MSG_ALERT )
{
/*
* Ignore non-fatal alerts, except close_notify
*/
if( ssl->in_msg[0] == SSL_ALERT_FATAL )
return( ERR_SSL_FATAL_ALERT_MESSAGE );
if( ssl->in_msg[0] == SSL_ALERT_WARNING &&
ssl->in_msg[1] == SSL_ALERT_CLOSE_NOTIFY )
return( ERR_SSL_PEER_CLOSE_NOTIFY );
}
ssl->in_left = 0;
return( 0 );
}
/*
* Flush any data not yet written
*/
int ssl_flush_output( ssl_context *ssl )
{
int ret = 0;
unsigned char *buf;
if( ssl->out_left > 0 )
{
buf = ssl->out_hdr + ssl->out_msglen -
( ssl->out_left - 5 );
ret = net_send( ssl->write_fd, buf,
&ssl->out_left );
}
return( ret );
}
/*
* Handshake functions
*/
int ssl_write_certificate( ssl_context *ssl )
{
int i, n;
x509_cert *crt;
if( ssl->endpoint == SSL_IS_CLIENT )
{
if( ssl->client_auth == 0 )
{
ssl->state++;
return( 0 );
}
/*
* If using SSLv3 and got no cert, send an Alert message
* (otherwise an empty Certificate message will be sent).
*/
if( ssl->own_cert == NULL &&
ssl->minor_ver == SSLV3_MINOR_VERSION )
{
ssl->out_msglen = 2;
ssl->out_msgtype = SSL_MSG_ALERT;
ssl->out_msg[0] = SSL_ALERT_WARNING;
ssl->out_msg[1] = SSL_ALERT_NO_CERTIFICATE;
ssl->state++;
return( ssl_write_record( ssl, 0 ) );
}
}
else /* SSL_IS_SERVER */
if( ssl->own_cert == NULL )
return( ERR_SSL_CERTIFICATE_REQUIRED );
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 6 length of all certs
* 7 . 9 length of cert. 1
* 10 . n-1 peer certificate
* n . n+2 length of cert. 2
* n+3 . ... upper level cert, etc.
*/
i = 7;
crt = ssl->own_cert;
while( crt != NULL && crt->next != NULL )
{
n = crt->raw.len;
if( i + 3 + n > SSL_MAX_CONTENT_LEN )
return( ERR_SSL_CERTIFICATE_TOO_LARGE );
ssl->out_msg[i ] = ( n >> 16 );
ssl->out_msg[i + 1] = ( n >> 8 );
ssl->out_msg[i + 2] = ( n );
i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
i += n; crt = crt->next;
}
ssl->out_msg[4] = ( i - 7 ) >> 16;
ssl->out_msg[5] = ( i - 7 ) >> 8;
ssl->out_msg[6] = ( i - 7 ) ;
ssl->out_msglen = i;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_CERTIFICATE;
ssl->state++;
return( ssl_write_record( ssl, 0 ) );
}
int ssl_parse_certificate( ssl_context *ssl )
{
int ret, i, n;
if( ssl->endpoint == SSL_IS_SERVER &&
ssl->authmode == SSL_VERIFY_NONE )
{
ssl->state++;
return( 0 );
}
if( ( ret = ssl_read_record( ssl, 0 ) ) != 0 )
return( ret );
ssl->state++;
/*
* Check if the client sent an empty certificate
*/
if( ssl->endpoint == SSL_IS_SERVER &&
ssl->minor_ver == SSLV3_MINOR_VERSION )
{
if( ssl->in_msglen == 2 &&
ssl->in_msgtype == SSL_MSG_ALERT &&
ssl->in_msg[0] == SSL_ALERT_WARNING &&
ssl->in_msg[1] == SSL_ALERT_NO_CERTIFICATE )
{
if( ssl->authmode == SSL_VERIFY_OPTIONAL )
return( 0 );
else
return( ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
if( ssl->endpoint == SSL_IS_SERVER &&
ssl->minor_ver != SSLV3_MINOR_VERSION )
{
if( ssl->in_hslen == 7 &&
ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
ssl->in_msg[0] == SSL_HS_CERTIFICATE &&
memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
{
if( ssl->authmode == SSL_VERIFY_OPTIONAL )
return( 0 );
else
return( ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
return( ERR_SSL_UNEXPECTED_MESSAGE );
if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
return( ERR_SSL_BAD_HS_CERTIFICATE );
/*
* Same message structure as shown above
*/
n = ( (int) ssl->in_msg[5] << 8 )
| ( (int) ssl->in_msg[6] );
if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
return( ERR_SSL_BAD_HS_CERTIFICATE );
if( ( ssl->peer_cert = (x509_cert *) malloc(
sizeof( x509_cert ) ) ) == NULL )
return( 1 );
memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
i = 7;
while( i < ssl->in_hslen )
{
if( ssl->in_msg[i] != 0 )
return( ERR_SSL_BAD_HS_CERTIFICATE );
n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
| ( (unsigned int) ssl->in_msg[i + 2] );
i += 3;
if( n < 128 || i + n > ssl->in_hslen )
return( ERR_SSL_BAD_HS_CERTIFICATE );
ret = x509_add_certs( ssl->peer_cert, ssl->in_msg + i, n );
if( ret != 0 )
return( ret );
i += n;
}
if( ssl->authmode != SSL_VERIFY_NONE )
{
if( ssl->ca_chain == NULL )
return( ERR_SSL_CA_CHAIN_REQUIRED );
ret = x509_verify_cert( ssl->peer_cert, ssl->ca_chain,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -