📄 ssl_tls_c.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0046)http://xyssl.org/code/source/ssl_tls/ssl_tls.c -->
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.3790.2954" name=GENERATOR></HEAD>
<BODY><PRE>/*
* SSLv3/TLSv1 shared functions
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* The SSL 3.0 specification was drafted by Netscape in 1996,
* and became an IETF standard in 1999.
*
* http://wp.netscape.com/eng/ssl3/
* http://www.ietf.org/rfc/rfc2246.txt
* http://www.ietf.org/rfc/rfc4346.txt
*/
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "xyssl/net.h"
#include "xyssl/ssl.h"
#include "xyssl/aes.h"
#include "xyssl/arc4.h"
#include "xyssl/des.h"
/*
* Key material generation
*/
static void tls1_prf( unsigned char *secret, int slen, char *label,
unsigned char *random, int rlen,
unsigned char *dstbuf, int dlen )
{
int nb, hs;
int i, j, k;
unsigned char *S1, *S2;
unsigned char tmp[128];
unsigned char h_i[20];
if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
return;
hs = ( slen + 1 ) / 2;
S1 = secret;
S2 = secret + slen - hs;
nb = strlen( label );
memcpy( tmp + 20, label, nb );
memcpy( tmp + 20 + nb, random, rlen );
nb += rlen;
/*
* First compute P_md5(secret,label+random)[0..dlen]
*/
md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
for( i = 0; i < dlen; i += 16 )
{
md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp );
k = ( i + 16 > dlen ) ? dlen % 16 : 16;
for( j = 0; j < k; j++ )
dstbuf[i + j] = h_i[j];
}
/*
* XOR out with P_sha1(secret,label+random)[0..dlen]
*/
sha1_hmac( S2, hs, tmp + 20, nb, tmp );
for( i = 0; i < dlen; i += 20 )
{
sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
sha1_hmac( S2, hs, tmp, 20, tmp );
k = ( i + 20 > dlen ) ? dlen % 20 : 20;
for( j = 0; j < k; j++ )
dstbuf[i + j] ^= h_i[j];
}
}
int ssl_derive_keys( ssl_context *ssl )
{
int i;
md5_context md5;
sha1_context sha1;
unsigned char padding[16];
unsigned char sha1sum[20];
unsigned char keyblk[256];
unsigned char *key1, *key2;
void *ctx1, *ctx2;
/*
* SSLv3:
* master =
* MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
* MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
* MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
*
* TLSv1:
* master = PRF( premaster, "master secret", randbytes )[0..47]
*/
if( ssl->resumed == 0 )
{
int len = ssl->pmslen;
if( ssl->minor_ver == SSLV3_MINOR_VERSION )
{
for( i = 0; i < 3; i++ )
{
memset( padding, 'A' + i, i + 1 );
sha1_starts( &sha1 );
sha1_update( &sha1, padding, i + 1 );
sha1_update( &sha1, ssl->premaster, len );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_finish( &sha1, sha1sum );
md5_starts( &md5 );
md5_update( &md5, ssl->premaster, len );
md5_update( &md5, sha1sum, 20 );
md5_finish( &md5, ssl->master + i * 16 );
}
}
else
tls1_prf( ssl->premaster, len, "master secret",
ssl->randbytes, 64, ssl->master, 48 );
memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
}
/*
* SSLv3:
* key block =
* MD5( master + SHA1( 'A' + master + randbytes ) ) +
* MD5( master + SHA1( 'BB' + master + randbytes ) ) +
* MD5( master + SHA1( 'CCC' + master + randbytes ) ) +
* MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
* ...
*
* TLSv1:
* key block = PRF( master, "key expansion", randbytes )
*/
{
/*
* Swap the client and server random values.
*/
unsigned char tmp[64];
memcpy( tmp, ssl->randbytes, 64 );
memcpy( ssl->randbytes, tmp + 32, 32 );
memcpy( ssl->randbytes + 32, tmp, 32 );
memset( tmp, 0, sizeof( tmp ) );
}
if( ssl->minor_ver == SSLV3_MINOR_VERSION )
{
for( i = 0; i < 16; i++ )
{
memset( padding, 'A' + i, i + 1 );
sha1_starts( &sha1 );
sha1_update( &sha1, padding, i + 1 );
sha1_update( &sha1, ssl->master, 48 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_finish( &sha1, sha1sum );
md5_starts( &md5 );
md5_update( &md5, ssl->master, 48 );
md5_update( &md5, sha1sum, 20 );
md5_finish( &md5, keyblk + i * 16 );
}
memset( &md5, 0, sizeof( md5 ) );
memset( &sha1, 0, sizeof( sha1 ) );
memset( padding, 0, sizeof( padding ) );
memset( sha1sum, 0, sizeof( sha1sum ) );
}
else
tls1_prf( ssl->master, 48, "key expansion",
ssl->randbytes, 64, keyblk, 256 );
memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) );
/*
* Determine the appropriate key, IV and MAC length.
*/
switch( ssl->cipher )
{
#if !defined(NO_ARC4)
case SSL3_RSA_RC4_128_MD5:
ssl->keylen = 16;
ssl->ivlen = 0;
ssl->maclen = 16;
ssl->minlen = 16;
ssl->ctxlen = sizeof( arc4_context );
break;
case SSL3_RSA_RC4_128_SHA:
ssl->keylen = 16;
ssl->ivlen = 0;
ssl->maclen = 20;
ssl->minlen = 20;
ssl->ctxlen = sizeof( arc4_context );
break;
#endif
#if !defined(NO_DES)
case SSL3_RSA_DES_168_SHA:
case SSL3_EDH_RSA_DES_168_SHA:
ssl->keylen = 24;
ssl->ivlen = 8;
ssl->maclen = 20;
ssl->minlen = 24;
ssl->ctxlen = sizeof( des3_context );
break;
#endif
#if !defined(NO_AES)
case TLS1_RSA_AES_256_SHA:
case TLS1_EDH_RSA_AES_256_SHA:
ssl->keylen = 32;
ssl->ivlen = 16;
ssl->maclen = 20;
ssl->minlen = 32;
ssl->ctxlen = sizeof( aes_context );
break;
#endif
default:
return( ERR_SSL_FEATURE_UNAVAILABLE );
}
/*
* Finally setup the cipher contexts, IVs and MAC secrets.
*/
key1 = keyblk + ssl->maclen * 2;
key2 = keyblk + ssl->maclen * 2 + ssl->keylen;
if( ( ctx1 = (void *) malloc( ssl->ctxlen ) ) == NULL ||
( ctx2 = (void *) malloc( ssl->ctxlen ) ) == NULL )
return( 1 );
switch( ssl->cipher )
{
#if !defined(NO_ARC4)
case SSL3_RSA_RC4_128_MD5:
case SSL3_RSA_RC4_128_SHA:
arc4_setup( (arc4_context *) ctx1, key1, ssl->keylen );
arc4_setup( (arc4_context *) ctx2, key2, ssl->keylen );
break;
#endif
#if !defined(NO_DES)
case SSL3_RSA_DES_168_SHA:
case SSL3_EDH_RSA_DES_168_SHA:
des3_set_3keys( (des3_context *) ctx1, key1 );
des3_set_3keys( (des3_context *) ctx2, key2 );
break;
#endif
#if !defined(NO_AES)
case TLS1_RSA_AES_256_SHA:
case TLS1_EDH_RSA_AES_256_SHA:
aes_set_key( (aes_context *) ctx1, key1, 256 );
aes_set_key( (aes_context *) ctx2, key2, 256 );
break;
#endif
default:
return( ERR_SSL_FEATURE_UNAVAILABLE );
}
if( ssl->endpoint == SSL_IS_CLIENT )
{
memcpy( ssl->mac_enc, keyblk, ssl->maclen );
memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen );
ssl->ctx_enc = ctx1;
ssl->ctx_dec = ctx2;
memcpy( ssl->iv_enc, key2 + ssl->keylen, ssl->ivlen );
memcpy( ssl->iv_dec, key2 + ssl->keylen + ssl->ivlen,
ssl->ivlen );
}
else
{
memcpy( ssl->mac_dec, keyblk, ssl->maclen );
memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen );
ssl->ctx_dec = ctx1;
ssl->ctx_enc = ctx2;
memcpy( ssl->iv_dec, key2 + ssl->keylen, ssl->ivlen );
memcpy( ssl->iv_enc, key2 + ssl->keylen + ssl->ivlen,
ssl->ivlen );
}
memset( keyblk, 0, sizeof( keyblk ) );
return( 0 );
}
/*
* Compute the client CertificateVerify MAC
*/
int ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] )
{
md5_context md5;
sha1_context sha1;
unsigned char pad_1[48];
unsigned char pad_2[48];
memcpy( &md5, &ssl->hs_md5, sizeof( md5_context ) );
memcpy( &sha1, &ssl->hs_sha1, sizeof( sha1_context ) );
if( ssl->minor_ver != SSLV3_MINOR_VERSION )
{
md5_finish( &md5, hash );
sha1_finish( &sha1, hash + 16 );
return( 0 );
}
memset( pad_1, 0x36, 48 );
memset( pad_2, 0x5C, 48 );
md5_update( &md5, ssl->master, 48 );
md5_update( &md5, pad_1, 48 );
md5_finish( &md5, hash );
md5_starts( &md5 );
md5_update( &md5, ssl->master, 48 );
md5_update( &md5, pad_2, 48 );
md5_update( &md5, hash, 16 );
md5_finish( &md5, hash );
sha1_update( &sha1, ssl->master, 48 );
sha1_update( &sha1, pad_1, 40 );
sha1_finish( &sha1, hash + 16 );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->master, 48 );
sha1_update( &sha1, pad_2, 40 );
sha1_update( &sha1, hash + 16, 20 );
sha1_finish( &sha1, hash + 16 );
return( 0 );
}
/*
* SSLv3 MAC functions
*/
static void ssl_mac_md5( unsigned char *secret,
unsigned char *buf, int len,
unsigned char *ctr, int type )
{
unsigned char header[11];
unsigned char padding[48];
md5_context md5;
memcpy( header, ctr, 8 );
header[ 8] = type;
header[ 9] = len >> 8;
header[10] = len;
memset( padding, 0x36, 48 );
md5_starts( &md5 );
md5_update( &md5, secret, 16 );
md5_update( &md5, padding, 48 );
md5_update( &md5, header, 11 );
md5_update( &md5, buf, len );
md5_finish( &md5, buf + len );
memset( padding, 0x5C, 48 );
md5_starts( &md5 );
md5_update( &md5, secret, 16 );
md5_update( &md5, padding, 48 );
md5_update( &md5, buf + len, 16 );
md5_finish( &md5, buf + len );
}
static void ssl_mac_sha1( unsigned char *secret,
unsigned char *buf, int len,
unsigned char *ctr, int type )
{
unsigned char header[11];
unsigned char padding[40];
sha1_context sha1;
memcpy( header, ctr, 8 );
header[ 8] = type;
header[ 9] = len >> 8;
header[10] = len;
memset( padding, 0x36, 40 );
sha1_starts( &sha1 );
sha1_update( &sha1, secret, 20 );
sha1_update( &sha1, padding, 40 );
sha1_update( &sha1, header, 11 );
sha1_update( &sha1, buf, len );
sha1_finish( &sha1, buf + len );
memset( padding, 0x5C, 40 );
sha1_starts( &sha1 );
sha1_update( &sha1, secret, 20 );
sha1_update( &sha1, padding, 40 );
sha1_update( &sha1, buf + len, 20 );
sha1_finish( &sha1, buf + len );
}
/*
* Message encryption/decryption
*/
static int ssl_encrypt_buf( ssl_context *ssl )
{
int i, padlen;
/*
* Add MAC then encrypt
*/
if( ssl->minor_ver == SSLV3_MINOR_VERSION )
{
if( ssl->maclen == 16 )
ssl_mac_md5( ssl->mac_enc, ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype );
if( ssl->maclen == 20 )
ssl_mac_sha1( ssl->mac_enc, ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype );
}
else
{
if( ssl->maclen == 16 )
md5_hmac( ssl->mac_enc, 16, ssl->out_ctr,
ssl->out_msglen + 13,
ssl->out_msg + ssl->out_msglen );
if( ssl->maclen == 20 )
sha1_hmac( ssl->mac_enc, 20, ssl->out_ctr,
ssl->out_msglen + 13,
ssl->out_msg + ssl->out_msglen );
}
ssl->out_msglen += ssl->maclen;
for( i = 7; i >= 0; i-- )
if( ++ssl->out_ctr[i] != 0 )
break;
if( ssl->ivlen == 0 )
{
#if !defined(NO_ARC4)
padlen = 0;
arc4_crypt( (arc4_context *) ssl->ctx_enc,
ssl->out_msg, ssl->out_msglen );
#else
return( ERR_SSL_FEATURE_UNAVAILABLE );
#endif
}
else
{
padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen;
if( padlen == ssl->ivlen )
padlen = 0;
for( i = 0; i <= padlen; i++ )
ssl->out_msg[ssl->out_msglen + i] = padlen;
ssl->out_msglen += padlen + 1;
switch( ssl->ivlen )
{
case 8:
#if !defined(NO_DES)
des3_cbc_encrypt( (des3_context *) ssl->ctx_enc,
ssl->iv_enc, ssl->out_msg,
ssl->out_msg, ssl->out_msglen );
break;
#endif
case 16:
#if !defined(NO_AES)
aes_cbc_encrypt( (aes_context *) ssl->ctx_enc,
ssl->iv_enc, ssl->out_msg,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -