t1_enc.c

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

C
634
字号
/* ssl/t1_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/comp.h>#include <openssl/md5.h>#include <openssl/sha.h>#include <openssl/evp.h>#include <openssl/hmac.h>#include "ssl_locl.h"static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,			int sec_len, unsigned char *seed, int seed_len,			unsigned char *out, int olen)	{	int chunk,n;	unsigned int j;	HMAC_CTX ctx;	HMAC_CTX ctx_tmp;	unsigned char A1[HMAC_MAX_MD_CBLOCK];	unsigned int A1_len;		chunk=EVP_MD_size(md);	HMAC_Init(&ctx,sec,sec_len,md);	HMAC_Update(&ctx,seed,seed_len);	HMAC_Final(&ctx,A1,&A1_len);	n=0;	for (;;)		{		HMAC_Init(&ctx,NULL,0,NULL); /* re-init */		HMAC_Update(&ctx,A1,A1_len);		memcpy(&ctx_tmp,&ctx,sizeof(ctx)); /* Copy for A2 */ /* not needed for last one */		HMAC_Update(&ctx,seed,seed_len);		if (olen > chunk)			{			HMAC_Final(&ctx,out,&j);			out+=j;			olen-=j;			HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */			}		else	/* last one */			{			HMAC_Final(&ctx,A1,&A1_len);			memcpy(out,A1,olen);			break;			}		}	HMAC_cleanup(&ctx);	HMAC_cleanup(&ctx_tmp);	memset(A1,0,sizeof(A1));	}static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1,		     unsigned char *label, int label_len,		     const unsigned char *sec, int slen, unsigned char *out1,		     unsigned char *out2, int olen)	{	int len,i;	const unsigned char *S1,*S2;	len=slen/2;	S1=sec;	S2= &(sec[len]);	len+=(slen&1); /* add for odd, make longer */		tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);	tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);	for (i=0; i<olen; i++)		out1[i]^=out2[i];	}static void tls1_generate_key_block(SSL *s, unsigned char *km,	     unsigned char *tmp, int num)	{	unsigned char *p;	unsigned char buf[SSL3_RANDOM_SIZE*2+		TLS_MD_MAX_CONST_SIZE];	p=buf;	memcpy(p,TLS_MD_KEY_EXPANSION_CONST,		TLS_MD_KEY_EXPANSION_CONST_SIZE);	p+=TLS_MD_KEY_EXPANSION_CONST_SIZE;	memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);	p+=SSL3_RANDOM_SIZE;	memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);	p+=SSL3_RANDOM_SIZE;	tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),		 s->session->master_key,s->session->master_key_length,		 km,tmp,num);	}int tls1_change_cipher_state(SSL *s, int which)	{	static const unsigned char empty[]="";	unsigned char *p,*key_block,*mac_secret;	unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+		SSL3_RANDOM_SIZE*2];	unsigned char tmp1[EVP_MAX_KEY_LENGTH];	unsigned char tmp2[EVP_MAX_KEY_LENGTH];	unsigned char iv1[EVP_MAX_IV_LENGTH*2];	unsigned char iv2[EVP_MAX_IV_LENGTH*2];	unsigned char *ms,*key,*iv,*er1,*er2;	int client_write;	EVP_CIPHER_CTX *dd;	const EVP_CIPHER *c;	const SSL_COMP *comp;	const EVP_MD *m;	int _exp,n,i,j,k,exp_label_len,cl;	_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);	c=s->s3->tmp.new_sym_enc;	m=s->s3->tmp.new_hash;	comp=s->s3->tmp.new_compression;	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;		if (s->expand != NULL)			{			COMP_CTX_free(s->expand);			s->expand=NULL;			}		if (comp != NULL)			{			s->expand=COMP_CTX_new(comp->method);			if (s->expand == NULL)				{				SSLerr(SSL_F_TLS1_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_ENCRYPTED_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;		if (s->compress != NULL)			{			COMP_CTX_free(s->compress);			s->compress=NULL;			}		if (comp != NULL)			{			s->compress=COMP_CTX_new(comp->method);			if (s->compress == NULL)				{				SSLerr(SSL_F_TLS1_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);	er1= &(s->s3->client_random[0]);	er2= &(s->s3->server_random[0]);	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;		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;		client_write=1;		}	else		{		n=i;		ms=  &(p[ n]); n+=i+j;		key= &(p[ n]); n+=j+k;		iv=  &(p[ n]); n+=k;		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;		client_write=0;		}	if (n > s->s3->tmp.key_block_length)		{		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR);		goto err2;		}	memcpy(mac_secret,ms,i);#ifdef TLS_DEBUGprintf("which = %04X\nmac key=",which);{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }#endif	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 :-).		 */		p=buf;		memcpy(p,exp_label,exp_label_len);		p+=exp_label_len;		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);		p+=SSL3_RANDOM_SIZE;		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);		p+=SSL3_RANDOM_SIZE;		tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j,			 tmp1,tmp2,EVP_CIPHER_key_length(c));		key=tmp1;		if (k > 0)			{			p=buf;			memcpy(p,TLS_MD_IV_BLOCK_CONST,				TLS_MD_IV_BLOCK_CONST_SIZE);			p+=TLS_MD_IV_BLOCK_CONST_SIZE;			memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);			p+=SSL3_RANDOM_SIZE;			memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);			p+=SSL3_RANDOM_SIZE;			tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0,				 iv1,iv2,k*2);			if (client_write)				iv=iv1;			else				iv= &(iv1[k]);			}		}	s->session->key_arg_length=0;	EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));#ifdef TLS_DEBUGprintf("which = %04X\nkey=",which);{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }printf("\niv=");

⌨️ 快捷键说明

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