Commit 90f3e4cf authored by Andy Polyakov's avatar Andy Polyakov
Browse files

Back-port TLS AEAD framework [from HEAD].

parent 7bd8bf58
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ struct evp_cipher_st
 * as finalisation.
 */
#define 	EVP_CIPH_FLAG_CUSTOM_CIPHER	0x100000
#define		EVP_CIPH_FLAG_AEAD_CIPHER	0x200000

/* ctrl() values */

@@ -383,6 +384,14 @@ struct evp_cipher_st
#define		EVP_CTRL_CCM_SET_TAG		EVP_CTRL_GCM_SET_TAG
#define		EVP_CTRL_CCM_SET_L		0x14
#define		EVP_CTRL_CCM_SET_MSGLEN		0x15
/* AEAD cipher deduces payload length and returns number of bytes
 * required to store MAC and eventual padding. Subsequent call to
 * EVP_Cipher even appends/verifies MAC.
 */
#define		EVP_CTRL_AEAD_TLS1_AAD		0x16
/* Used by composite AEAD ciphers, no-op in GCM, CCM... */
#define		EVP_CTRL_AEAD_SET_MAC_KEY	0x17


typedef struct evp_cipher_info_st
	{
+22 −1
Original line number Diff line number Diff line
@@ -583,8 +583,29 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
		if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
	}	

	if ((*enc != NULL) && (*md != NULL) && (!mac_pkey_type||*mac_pkey_type != NID_undef))
	if ((*enc != NULL) &&
	    (*md != NULL || (EVP_CIPHER_flags(*enc)&EVP_CIPH_FLAG_AEAD_CIPHER)) &&
	    (!mac_pkey_type||*mac_pkey_type != NID_undef))
		{
		const EVP_CIPHER *evp;

		if	(s->ssl_version >= TLS1_VERSION &&
			 c->algorithm_enc == SSL_RC4 &&
			 c->algorithm_mac == SSL_MD5 &&
			 (evp=EVP_get_cipherbyname("RC4-HMAC-MD5")))
			*enc = evp, *md = NULL;
		else if (s->ssl_version >= TLS1_VERSION &&
			 c->algorithm_enc == SSL_AES128 &&
			 c->algorithm_mac == SSL_SHA1 &&
			 (evp=EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1")))
			*enc = evp, *md = NULL;
		else if (s->ssl_version >= TLS1_VERSION &&
			 c->algorithm_enc == SSL_AES256 &&
			 c->algorithm_mac == SSL_SHA1 &&
			 (evp=EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
			*enc = evp, *md = NULL;
		return(1);
		}
	else
		return(0);
	}
+65 −16
Original line number Diff line number Diff line
@@ -485,10 +485,14 @@ int tls1_change_cipher_state(SSL *s, int which)
		}

	memcpy(mac_secret,ms,i);

	if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER))
		{
		mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
				mac_secret,*mac_secret_size);
		EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
		EVP_PKEY_free(mac_key);
		}
#ifdef TLS_DEBUG
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
@@ -536,6 +540,12 @@ printf("which = %04X\nmac key=",which);
#endif	/* KSSL_DEBUG */

	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));

	/* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
	if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size)
		EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY,
				*mac_secret_size,mac_secret);

#ifdef TLS_DEBUG
printf("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'); }
@@ -652,14 +662,14 @@ int tls1_enc(SSL *s, int send)
	SSL3_RECORD *rec;
	EVP_CIPHER_CTX *ds;
	unsigned long l;
	int bs,i,ii,j,k,n=0;
	int bs,i,ii,j,k,pad=0;
	const EVP_CIPHER *enc;

	if (send)
		{
		if (EVP_MD_CTX_md(s->write_hash))
			{
			n=EVP_MD_CTX_size(s->write_hash);
			int n=EVP_MD_CTX_size(s->write_hash);
			OPENSSL_assert(n >= 0);
			}
		ds=s->enc_write_ctx;
@@ -694,7 +704,7 @@ int tls1_enc(SSL *s, int send)
		{
		if (EVP_MD_CTX_md(s->read_hash))
			{
			n=EVP_MD_CTX_size(s->read_hash);
			int n=EVP_MD_CTX_size(s->read_hash);
			OPENSSL_assert(n >= 0);
			}
		ds=s->enc_read_ctx;
@@ -720,7 +730,43 @@ int tls1_enc(SSL *s, int send)
		l=rec->length;
		bs=EVP_CIPHER_block_size(ds->cipher);

		if ((bs != 1) && send)
		if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
			{
			unsigned char buf[13],*seq;

			seq = send?s->s3->write_sequence:s->s3->read_sequence;

			if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
				{
				unsigned char dtlsseq[9],*p=dtlsseq;

				s2n(send?s->d1->w_epoch:s->d1->r_epoch,p);
				memcpy(p,&seq[2],6);
				memcpy(buf,dtlsseq,8);
				}
			else
				{
				memcpy(buf,seq,8);
				for (i=7; i>=0; i--)	/* increment */
					{
					++seq[i];
					if (seq[i] != 0) break; 
					}
				}

			buf[8]=rec->type;
			buf[9]=(unsigned char)(s->version>>8);
			buf[10]=(unsigned char)(s->version);
			buf[11]=rec->length>>8;
			buf[12]=rec->length&0xff;
			pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf);
			if (send)
				{
				l+=pad;
				rec->length+=pad;
				}
			}
		else if ((bs != 1) && send)
			{
			i=bs-((int)l%bs);

@@ -769,7 +815,8 @@ int tls1_enc(SSL *s, int send)
				}
			}
		
		EVP_Cipher(ds,rec->data,rec->input,l);
		if (!EVP_Cipher(ds,rec->data,rec->input,l))
			return -1;	/* AEAD can fail to verify MAC */

#ifdef KSSL_DEBUG
		{
@@ -828,6 +875,8 @@ int tls1_enc(SSL *s, int send)
				rec->length -= bs;
				}
			}
		if (pad && !send)
			rec->length -= pad;
		}
	return(1);
	}