⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cryptocontext.cxx

📁 MiniSip Client with DomainKeys Authentication, Sip, Audio communications, Echo Cancel
💻 CXX
字号:
/* Copyright (C) 2004-2006 the Minisip Team  This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA *//* Copyright (C) 2004  * * Authors: Israel Abad <i_abad@terra.es> *          Erik Eliasson <eliasson@it.kth.se> *          Johan Bilien <jobi@via.ecp.fr> *	    Joachim Orrblad <joachim@orrblad.com>*/#include <config.h>#include<iostream>#include<libmutil/massert.h>#include<libminisip/rtp/CryptoContext.h>#include<libmutil/print_hex.h>#include<libmikey/MikeyPayloadSP.h>CryptoContext::CryptoContext( uint32_t ssrc ):ssrc(ssrc),using_mki(false),mki_length(0),mki(NULL),roc(0),guessed_roc(0),s_l(0),key_deriv_rate(0),replay_window(0),master_key(NULL), master_key_length(0),master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0),master_salt(NULL), master_salt_length(0),n_e(0),k_e(NULL),n_a(0),k_a(NULL),n_s(0),k_s(NULL),ealg(MIKEY_SRTP_EALG_NULL), aalg(MIKEY_SRTP_AALG_NULL),ekeyl(0), akeyl(0), skeyl(0), encr(1), auth(1){}/*These should be set to 0, but for backward compatability they are set to 1  *///encryption(no_encr),authentication(no_auth)CryptoContext::CryptoContext( uint32_t ssrc, int roc, uint16_t seq_no,			        int key_deriv_rate,				//enum encr_method encryption, 				uint8_t ealg,				//enum auth_method authentication,				uint8_t aalg,				unsigned char * master_key,				unsigned int master_key_length,				unsigned char * master_salt,				unsigned int master_salt_length, 				uint8_t ekeyl, 				uint8_t akeyl,				uint8_t skeyl,				uint8_t encr, 				uint8_t auth,				uint8_t tag_length):ssrc(ssrc),using_mki(false),mki_length(0),mki(NULL),roc(roc),guessed_roc(0),s_l(seq_no),key_deriv_rate(key_deriv_rate),replay_window(0),master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0)//encryption(encryption),authentication(authentication){	this->ealg = ealg; 	this->aalg = aalg;	this->encr = encr;	this->auth = auth;	this->ekeyl = ekeyl;	this->akeyl = akeyl; 	this->skeyl = skeyl;	this->master_key_length = master_key_length;	this->master_key = new unsigned char[ master_key_length ];	memcpy( this->master_key, master_key, master_key_length );		this->master_salt_length = master_salt_length;	this->master_salt = new unsigned char[ master_salt_length ];	memcpy( this->master_salt, master_salt, master_salt_length );		switch( ealg ){		case MIKEY_SRTP_EALG_NULL:			n_e = 0;			k_e = NULL;			n_s = 0;			k_s = NULL;			break;		case MIKEY_SRTP_EALG_AESCM:		case MIKEY_SRTP_EALG_AESF8:			n_e = ekeyl;			k_e = new unsigned char[ n_e ];			n_s = skeyl;			k_s = new unsigned char[ n_s ];			break;	}	switch( aalg ){		case MIKEY_SRTP_AALG_NULL:			n_a = 0;			k_a = NULL;			this->tag_length = 0;			break;		case MIKEY_SRTP_AALG_SHA1HMAC:			n_a = akeyl;			k_a = new unsigned char[ n_a ];			this->tag_length = tag_length;			break;	}}	CryptoContext::~CryptoContext(){	if( mki )		delete [] mki;	if( master_key )		delete [] master_key;	if( master_salt )		delete [] master_salt;	if( k_e )		delete [] k_e;	if( k_a )		delete [] k_a;	if( k_s )		delete [] k_s;}	void CryptoContext::rtp_encrypt( RtpPacket * rtp, uint64_t index ){		// FIXME: handle f8 mode	if( ealg == MIKEY_SRTP_EALG_AESCM )	{		/* Compute the IV:		  k_s   XX XX XX XX XX XX XX XX XX XX XX XX XX XX		  SSRC              XX XX XX XX		  index                         XX XX XX XX XX XX		  ------------------------------------------------------XOR		  IV    XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00		*/		  		unsigned char iv[16];		uint32_t ssrc = rtp->getHeader().getSSRC();		memcpy( iv, k_s, 4 );				int i;		for(i = 4; i < 8; i++ ){			iv[i] = ( 0xFF & ( ssrc >> ((7-i)*8) ) ) ^ k_s[i];		}		for(i = 8; i < 14; i++ ){			iv[i] = ( 0xFF & (unsigned char)( index >> ((13-i)*8) ) ) ^ k_s[i];		}		iv[14] = iv[15] = 0;				AES * aes = new AES( k_e, n_e );		aes->ctr_encrypt( rtp->getContent(),				  rtp->getContentLength(),				  iv );		delete aes;	}	if( ealg == MIKEY_SRTP_EALG_AESF8 )	{		/* Create the IV:		   IV = 0x00 || M || PT || SEQ  ||      TS    ||    SSRC   ||    ROC		        8Bit  1bit  7bit  16bit       32bit        32bit        32bit		   ------------\       /----------------------------		         XX       XX      XX XX   XX XX XX XX   XX XX XX XX  XX XX XX XX		*/	    unsigned char iv[16];	    RtpHeader &rtph = rtp->getHeader();	    uint16_t seq_no = rtph.getSeqNo();	    uint32_t ui32;	    uint32_t *ui32p = (uint32_t *)iv;	    uint16_t *ui16p = (uint16_t *)iv;	    iv[0] = 0;	    iv[1] = rtph.getMarker() ? 0x80 : 0x00;	    iv[1] |= rtph.getPayloadType() & 0x7f;	    ui16p[1] = hton16(seq_no);	    // Set the timestamp in big endian order into IV	    ui32 = rtph.getTimestamp();	    ui32p[1] = hton32(ui32);	    // set the SSRC in big endian order into IV	    ui32 = rtph.getSSRC();	    ui32p[2] = hton32(ui32);	    // set the ROC in big endian order into IV	    // TODO: cross check if ROC has to be in big endian order and if we have	    // the correct (current) ROC here !!!	    ui32p[3] = hton32(roc);	    AES *aes = new AES(k_e, n_e);	    aes->f8_encrypt(rtp->getContent(),			    rtp->getContentLength(),			    iv, k_e, n_e, k_s, n_s);	    delete aes;	}}/* Warning: tag must have been initialized */void CryptoContext::rtp_authenticate( RtpPacket * rtp, uint32_t roc, unsigned char * tag ){	unsigned int tag_length;		if( aalg == MIKEY_SRTP_AALG_SHA1HMAC )	{		unsigned char temp[20];		unsigned char * chunks[4];		unsigned int chunkLength[4];		uint32_t beRoc = hton32( roc );				char * bytes = rtp->getHeader().getBytes();		unsigned char * content = rtp->getContent();		unsigned int header_size = rtp->getHeader().size() ;		unsigned int content_size = rtp->getContentLength() ;				chunks[0] = (unsigned char *)bytes;		chunkLength[0] = header_size;		chunks[1] = (unsigned char *)content;		chunkLength[1] = content_size;		chunks[2] = (unsigned char *)&beRoc;		chunkLength[2] = 4;		chunks[3] = NULL;//		cerr << "packet no: " << rtp->getHeader().getSeqNo() << endl;//		cerr << "HMAC input size: " << header_size + content_size << endl;//		cerr << "HMAC input: " << print_hex( (unsigned char *)bytes, header_size + content_size ) << endl;		hmac_sha1( k_a, n_a,		    /* data */ chunks, 		    /*authenticated part length */			    	chunkLength,		    /* tag */  temp, &tag_length );		massert( tag_length == 20 );		/* truncate the result */		memcpy( tag, temp, get_tag_length() );		delete [] bytes;			}}/* used by the key derivation method */static void compute_iv( unsigned char * iv, uint64_t label, uint64_t index, int key_deriv_rate, unsigned char * master_salt ){        uint64_t key_id;        if( key_deriv_rate == 0 )                key_id = label << 48;        else                key_id = ((label << 48) || index / key_deriv_rate);        //printf( "Key_ID: %llx\n", key_id );        /* compute the IV        key_id:                           XX XX XX XX XX XX XX        master_salt: XX XX XX XX XX XX XX XX XX XX XX XX XX XX        ------------------------------------------------------------ XOR        IV:          XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00        */	int i;        for(i = 0; i < 7 ; i++ ){                iv[i] = master_salt[i];        }        for(i = 7; i < 14 ; i++ ){                iv[i] = (unsigned char)(0xFF & (key_id >> (8*(13-i)))) ^                        master_salt[i];        }        iv[14] = iv[15] = 0;        //cerr << "AES-CM input: " << print_hex( iv, 16 ) << endl;}/* Derives the srtp session keys from the master key */void CryptoContext::derive_srtp_keys( uint64_t index ){	AES * aes;	unsigned char iv[16];	uint64_t label = 0;	compute_iv( iv, label, index, key_deriv_rate, master_salt );        aes = new AES( master_key, 16/*master_key_length*/ );        aes->get_ctr_cipher_stream( k_e, n_e, iv );   //     cerr << "Session Encryption Key: " << print_hex( k_e, n_e ) << endl;        label = 0x01;        compute_iv( iv, label, index, key_deriv_rate, master_salt );        aes = new AES( master_key, 16/*master_key_length*/ );        aes->get_ctr_cipher_stream( k_a, n_a, iv );//        cerr << "Session Authentication Key: " << print_hex( k_a, n_a ) << endl;        label = 0x02;        compute_iv( iv, label, index, key_deriv_rate, master_salt );        aes = new AES( master_key, 16/*master_key_length*/ );        aes->get_ctr_cipher_stream( k_s, n_s, iv );//        cerr << "Session Salt: " << print_hex( k_s, n_s ) << endl;	delete aes;}/* Based on the algorithm provided in Appendix A - draft-ietf-srtp-05.txt */uint64_t CryptoContext::guess_index( unsigned short new_seq_nb ){	if( s_l < 32768 ){		if( new_seq_nb - s_l > 32768 )			guessed_roc = roc - 1;		else			guessed_roc = roc;	}	else{		if( s_l - 32768 > new_seq_nb )			guessed_roc = roc + 1;		else			guessed_roc = roc;	}	return ((uint64_t)guessed_roc) << 16 | new_seq_nb;}bool CryptoContext::check_replay( unsigned short new_seq_nb ){	if( aalg == MIKEY_SRTP_AALG_NULL && ealg == MIKEY_SRTP_EALG_NULL ){		/* No security policy, don't use the replay protection */		return true;	}	uint64_t guessed_index = guess_index( new_seq_nb );	uint64_t local_index = 		(((uint64_t)roc) << 16 & 0xFFFF) | s_l;		int64_t delta = guessed_index - local_index;	//fprintf( stderr, "roc: %u\n", roc );	//fprintf( stderr, "guessed_index: %llu\n", guessed_index );	//fprintf( stderr, "local_index: %llu\n", local_index );	//fprintf( stderr, "s_l: %lli\n", s_l );	//fprintf( stderr, "delta: %lli\n", delta );	if( delta > 0 )		/* Packet not yet received*/		return true;	else{		if( -delta > REPLAY_WINDOW_SIZE )			/* Packet too old */			return false;		else{			if( (replay_window >> (-delta)) & 0x1 )				/* Packet already received ! */				return false;			else				/* Packet not yet received */				return true;		}	}}void CryptoContext::update( unsigned short new_seq_nb ){		int64_t delta = guess_index( new_seq_nb ) - 		( ((uint64_t)roc) << 16 | s_l );		/* update the replay bitmask */	if( delta > 0 ){		replay_window = replay_window << delta;		replay_window |= 1;	}	else{		replay_window |= ( 1 << delta );	}	/* update the locally stored ROC and highest sequence number */	if( new_seq_nb > s_l )		s_l = new_seq_nb;	if( guessed_roc > roc ){		roc = guessed_roc;		s_l = new_seq_nb;	}}void CryptoContext::set_roc( unsigned int roc ){	this->roc = roc;}unsigned int CryptoContext::get_roc(){	return roc;}int CryptoContext::get_tag_length(){	switch( aalg ){		case MIKEY_SRTP_AALG_NULL:			return 0;		case MIKEY_SRTP_AALG_SHA1HMAC:			return tag_length;	}	return -1;}int CryptoContext::get_mki_length(){	return mki_length;}uint32_t CryptoContext::getSsrc(){	return ssrc;}

⌨️ 快捷键说明

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