s3_enc.c

来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 584 行 · 第 1/2 页

C
584
字号
/* ssl/s3_enc.c *//* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. *  * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to.  The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code.  The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). *  * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *    "This product includes cryptographic software written by *     Eric Young (eay@cryptsoft.com)" *    The word 'cryptographic' can be left out if the rouines from the library *    being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from  *    the apps directory (application code) you must include an acknowledgement: *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" *  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed.  i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */#include <stdio.h>#include <openssl/md5.h>#include <openssl/sha.h>#include <openssl/evp.h>#include "ssl_locl.h"static unsigned char ssl3_pad_1[48]={	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36 };static unsigned char ssl3_pad_2[48]={	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,	0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c };static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx,	const char *sender, int len, unsigned char *p);static void ssl3_generate_key_block(SSL *s, unsigned char *km, int num)	{	MD5_CTX m5;	SHA_CTX s1;	unsigned char buf[8],smd[SHA_DIGEST_LENGTH];	unsigned char c='A';	int i,j,k;#ifdef CHARSET_EBCDIC	c = os_toascii[c]; /*'A' in ASCII */#endif	k=0;	for (i=0; i<num; i+=MD5_DIGEST_LENGTH)		{		k++;		for (j=0; j<k; j++)			buf[j]=c;		c++;		SHA1_Init(  &s1);		SHA1_Update(&s1,buf,k);		SHA1_Update(&s1,s->session->master_key,			s->session->master_key_length);		SHA1_Update(&s1,s->s3->server_random,SSL3_RANDOM_SIZE);		SHA1_Update(&s1,s->s3->client_random,SSL3_RANDOM_SIZE);		SHA1_Final( smd,&s1);		MD5_Init(  &m5);		MD5_Update(&m5,s->session->master_key,			s->session->master_key_length);		MD5_Update(&m5,smd,SHA_DIGEST_LENGTH);		if ((i+MD5_DIGEST_LENGTH) > num)			{			MD5_Final(smd,&m5);			memcpy(km,smd,(num-i));			}		else			MD5_Final(km,&m5);		km+=MD5_DIGEST_LENGTH;		}	memset(smd,0,SHA_DIGEST_LENGTH);	}int ssl3_change_cipher_state(SSL *s, int which)	{	unsigned char *p,*key_block,*mac_secret;	unsigned char exp_key[EVP_MAX_KEY_LENGTH];	unsigned char exp_iv[EVP_MAX_KEY_LENGTH];	unsigned char *ms,*key,*iv,*er1,*er2;	EVP_CIPHER_CTX *dd;	const EVP_CIPHER *c;	COMP_METHOD *comp;	const EVP_MD *m;	MD5_CTX md;	int exp,n,i,j,k,cl;	exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);	c=s->s3->tmp.new_sym_enc;	m=s->s3->tmp.new_hash;	if (s->s3->tmp.new_compression == NULL)		comp=NULL;	else		comp=s->s3->tmp.new_compression->method;	key_block=s->s3->tmp.key_block;	if (which & SSL3_CC_READ)		{		if ((s->enc_read_ctx == NULL) &&			((s->enc_read_ctx=(EVP_CIPHER_CTX *)			OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))			goto err;		dd= s->enc_read_ctx;		s->read_hash=m;		/* COMPRESS */		if (s->expand != NULL)			{			COMP_CTX_free(s->expand);			s->expand=NULL;			}		if (comp != NULL)			{			s->expand=COMP_CTX_new(comp);			if (s->expand == NULL)				{				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);				goto err2;				}			if (s->s3->rrec.comp == NULL)				s->s3->rrec.comp=(unsigned char *)					OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH);			if (s->s3->rrec.comp == NULL)				goto err;			}		memset(&(s->s3->read_sequence[0]),0,8);		mac_secret= &(s->s3->read_mac_secret[0]);		}	else		{		if ((s->enc_write_ctx == NULL) &&			((s->enc_write_ctx=(EVP_CIPHER_CTX *)			OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))			goto err;		dd= s->enc_write_ctx;		s->write_hash=m;		/* COMPRESS */		if (s->compress != NULL)			{			COMP_CTX_free(s->compress);			s->compress=NULL;			}		if (comp != NULL)			{			s->compress=COMP_CTX_new(comp);			if (s->compress == NULL)				{				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);				goto err2;				}			}		memset(&(s->s3->write_sequence[0]),0,8);		mac_secret= &(s->s3->write_mac_secret[0]);		}	EVP_CIPHER_CTX_init(dd);	p=s->s3->tmp.key_block;	i=EVP_MD_size(m);	cl=EVP_CIPHER_key_length(c);	j=exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?		 cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */	k=EVP_CIPHER_iv_length(c);	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||		(which == SSL3_CHANGE_CIPHER_SERVER_READ))		{		ms=  &(p[ 0]); n=i+i;		key= &(p[ n]); n+=j+j;		iv=  &(p[ n]); n+=k+k;		er1= &(s->s3->client_random[0]);		er2= &(s->s3->server_random[0]);		}	else		{		n=i;		ms=  &(p[ n]); n+=i+j;		key= &(p[ n]); n+=j+k;		iv=  &(p[ n]); n+=k;		er1= &(s->s3->server_random[0]);		er2= &(s->s3->client_random[0]);		}	if (n > s->s3->tmp.key_block_length)		{		SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR);		goto err2;		}	memcpy(mac_secret,ms,i);	if (exp)		{		/* In here I set both the read and write key/iv to the		 * same value since only the correct one will be used :-).		 */		MD5_Init(&md);		MD5_Update(&md,key,j);		MD5_Update(&md,er1,SSL3_RANDOM_SIZE);		MD5_Update(&md,er2,SSL3_RANDOM_SIZE);		MD5_Final(&(exp_key[0]),&md);		key= &(exp_key[0]);		if (k > 0)			{			MD5_Init(&md);			MD5_Update(&md,er1,SSL3_RANDOM_SIZE);			MD5_Update(&md,er2,SSL3_RANDOM_SIZE);			MD5_Final(&(exp_iv[0]),&md);			iv= &(exp_iv[0]);			}		}	s->session->key_arg_length=0;	EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));	memset(&(exp_key[0]),0,sizeof(exp_key));	memset(&(exp_iv[0]),0,sizeof(exp_iv));	return(1);err:	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);err2:	return(0);	}int ssl3_setup_key_block(SSL *s)	{	unsigned char *p;	const EVP_CIPHER *c;	const EVP_MD *hash;	int num;	SSL_COMP *comp;	if (s->s3->tmp.key_block_length != 0)		return(1);	if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp))		{		SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);		return(0);		}

⌨️ 快捷键说明

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