shithub: riscv

Download patch

ref: 9b0de7f9d63386bc5e2cb5889559bbdb0c11503d
parent: d19144155e3825507cc01901a83d99bd64a8b0aa
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 20 23:55:54 EST 2015

tls: implement chacha20/poly1305 aead cipher suits

--- a/sys/src/9/port/devtls.c
+++ b/sys/src/9/port/devtls.c
@@ -87,10 +87,14 @@
 	int		(*dec)(Secret*, uchar*, int);
 	int		(*unpad)(uchar*, int, int);
 	DigestState	*(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+
+	int		(*aead_enc)(Secret*, uchar*, int, uchar*, int);
+	int		(*aead_dec)(Secret*, uchar*, int, uchar*, int);
+
 	int		block;		/* encryption block len, 0 if none */
 	int		maclen;
 	void		*enckey;
-	uchar	mackey[MaxMacLen];
+	uchar		mackey[MaxMacLen];
 };
 
 struct OneWay
@@ -97,7 +101,7 @@
 {
 	QLock		io;		/* locks io access */
 	QLock		seclock;	/* locks secret paramaters */
-	ulong		seq;
+	u64int		seq;
 	Secret		*sec;		/* cipher in use */
 	Secret		*new;		/* cipher waiting for enable */
 };
@@ -119,8 +123,11 @@
 	int		state;
 	int		debug;
 
-	/* record layer mac functions for different protocol versions */
-	void		(*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
+	/*
+	 * function to genrate authenticated data blob for different
+	 * protocol versions
+	 */
+	int		(*packAAD)(u64int, uchar*, uchar*);
 
 	/* input side -- protected by in.io */
 	OneWay		in;
@@ -221,9 +228,10 @@
 static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static void	sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void	tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void	put64(uchar *p, vlong x);
+static int	sslPackAAD(u64int, uchar*, uchar*);
+static int	tlsPackAAD(u64int, uchar*, uchar*);
+static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
+static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
 static void	put24(uchar *p, int);
 static void	put16(uchar *p, int);
@@ -238,6 +246,8 @@
 static int	des3dec(Secret *sec, uchar *buf, int n);
 static int	aesenc(Secret *sec, uchar *buf, int n);
 static int	aesdec(Secret *sec, uchar *buf, int n);
+static int	ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len);
+static int	ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
 static int	sslunpad(uchar *buf, int n, int block);
 static int	tlsunpad(uchar *buf, int n, int block);
@@ -734,9 +744,10 @@
 {
 	OneWay *volatile in;
 	Block *volatile b;
-	uchar *p, seq[8], header[RecHdrLen], hmac[MaxMacLen];
+	uchar *p, aad[8+RecHdrLen], header[RecHdrLen], hmac[MaxMacLen];
 	int volatile nconsumed;
-	int len, type, ver, unpad_len;
+	int len, type, ver, unpad_len, aadlen, ivlen;
+	Secret *sec;
 
 	nconsumed = 0;
 	if(waserror()){
@@ -798,36 +809,44 @@
 	}
 	qlock(&in->seclock);
 	p = b->rp;
-	if(in->sec != nil) {
+	sec = in->sec;
+	if(sec != nil) {
 		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
 		        should look alike, including timing of the response. */
-		unpad_len = (*in->sec->dec)(in->sec, p, len);
+		if(sec->aead_dec != nil)
+			unpad_len = len;
+		else {
+			unpad_len = (*sec->dec)(sec, p, len);
+if(tr->debug) pprint("decrypted %d\n", unpad_len);
+if(tr->debug) pdump(unpad_len, p, "decrypted:");
+		}
 
-		/* excplicit iv */
 		if(tr->version >= TLS11Version){
-			len -= in->sec->block;
+			ivlen = sec->block;
+			len -= ivlen;
 			if(len < 0)
 				rcvError(tr, EDecodeError, "runt record message");
-
-			unpad_len -= in->sec->block;
-			p += in->sec->block;
+			unpad_len -= ivlen;
+			p += ivlen;
 		}
 
-		if(unpad_len >= in->sec->maclen)
-			len = unpad_len - in->sec->maclen;
+		if(unpad_len >= sec->maclen)
+			len = unpad_len - sec->maclen;
 
-if(tr->debug) pprint("decrypted %d\n", unpad_len);
-if(tr->debug) pdump(unpad_len, p, "decrypted:");
-
 		/* update length */
 		put16(header+3, len);
-		put64(seq, in->seq);
-		in->seq++;
-		(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
-		if(unpad_len < in->sec->maclen)
-			rcvError(tr, EBadRecordMac, "short record mac");
-		if(memcmp(hmac, p+len, in->sec->maclen) != 0)
-			rcvError(tr, EBadRecordMac, "record mac mismatch");
+		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		if(sec->aead_dec != nil) {
+			len = (*sec->aead_dec)(sec, aad, aadlen, p, unpad_len);
+			if(len < 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		} else {
+			packMac(sec, aad, aadlen, p, len, hmac);
+			if(unpad_len < sec->maclen)
+				rcvError(tr, EBadRecordMac, "short record mac");
+			if(tsmemcmp(hmac, p + len, sec->maclen) != 0)
+				rcvError(tr, EBadRecordMac, "record mac mismatch");
+		}
 		b->rp = p;
 		b->wp = p+len;
 	}
@@ -1239,9 +1258,10 @@
 {
 	Block *volatile bb;
 	Block *nb;
-	uchar *p, seq[8];
+	uchar *p, aad[8+RecHdrLen];
 	OneWay *volatile out;
-	int n, ivlen, maclen, pad, ok;
+	int n, ivlen, maclen, aadlen, pad, ok;
+	Secret *sec;
 
 	out = &tr->out;
 	bb = b;
@@ -1275,11 +1295,12 @@
 		maclen = 0;
 		pad = 0;
 		ivlen = 0;
-		if(out->sec != nil){
-			maclen = out->sec->maclen;
-			pad = maclen + out->sec->block;
+		sec = out->sec;
+		if(sec != nil){
+			maclen = sec->maclen;
+			pad = maclen + sec->block;
 			if(tr->version >= TLS11Version)
-				ivlen = out->sec->block;
+				ivlen = sec->block;
 		}
 		n = BLEN(bb);
 		if(n > MaxRecLen){
@@ -1304,20 +1325,16 @@
 		put16(p+1, tr->version);
 		put16(p+3, n);
 
-		if(out->sec != nil){
-			put64(seq, out->seq);
-			out->seq++;
-			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
-			n += maclen;
-
-			/* explicit iv */
-			if(ivlen > 0){
+		if(sec != nil){
+			if(ivlen > 0)
 				randfill(p + RecHdrLen, ivlen);
-				n += ivlen;
+			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			if(sec->aead_enc != nil)
+				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen + ivlen, n) + ivlen;
+			else {
+				packMac(sec, aad, aadlen, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n);
+				n = (*sec->enc)(sec, p + RecHdrLen, ivlen + n + maclen);
 			}
-
-			/* encrypt */
-			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
 			nb->wp = p + RecHdrLen + n;
 
 			/* update length */
@@ -1489,6 +1506,27 @@
 }
 
 static void
+initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+	s->enckey = smalloc(sizeof(Chachastate));
+	s->enc = noenc;
+	s->dec = noenc;
+	s->mac = nomac;
+	s->aead_enc = ccpoly_aead_enc;
+	s->aead_dec = ccpoly_aead_dec;
+	s->block = 0;
+	s->maclen = Poly1305dlen;
+	if(ea->ivlen == 0) {
+		/* older draft version, iv is 64-bit sequence number */
+		setupChachastate(s->enckey, p, ea->keylen, nil, 64/8, 20);
+	} else {
+		/* IETF standard, 96-bit iv xored with sequence number */
+		memmove(s->mackey, iv, ea->ivlen);
+		setupChachastate(s->enckey, p, ea->keylen, iv, ea->ivlen, 20);
+	}
+}
+
+static void
 initclearenc(Encalg *, Secret *s, uchar *, uchar *)
 {
 	s->enc = noenc;
@@ -1503,6 +1541,8 @@
 	{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
 	{ "aes_128_cbc", 128/8, 16, initAESkey },
 	{ "aes_256_cbc", 256/8, 16, initAESkey },
+	{ "ccpoly64_aead", 256/8, 0, initccpolykey },
+	{ "ccpoly96_aead", 256/8, 96/8, initccpolykey },
 	{ 0 }
 };
 
@@ -1607,9 +1647,9 @@
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
 		if(m == SSL3Version)
-			tr->packMac = sslPackMac;
+			tr->packAAD = sslPackAAD;
 		else
-			tr->packMac = tlsPackMac;
+			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -2094,6 +2134,46 @@
 	return (*sec->unpad)(buf, n, 16);
 }
 
+static void
+ccpoly_aead_setiv(Secret *sec, uchar seq[8])
+{
+	uchar iv[ChachaIVlen];
+	Chachastate *cs;
+	int i;
+
+	cs = (Chachastate*)sec->enckey;
+	if(cs->ivwords == 2){
+		chacha_setiv(cs, seq);
+		return;
+	}
+
+	memmove(iv, sec->mackey, ChachaIVlen);
+	for(i=0; i<8; i++)
+		iv[i+(ChachaIVlen-8)] ^= seq[i];
+
+	chacha_setiv(cs, iv);
+}
+
+static int
+ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len)
+{
+	ccpoly_aead_setiv(sec, aad);
+	ccpoly_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
+	return len + sec->maclen;
+}
+
+static int
+ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len)
+{
+	len -= sec->maclen;
+	if(len < 0)
+		return -1;
+	ccpoly_aead_setiv(sec, aad);
+	if(ccpoly_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+		return -1;
+	return len;
+}
+
 static DigestState*
 nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *)
 {
@@ -2153,32 +2233,35 @@
 	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
 }
 
-static void
-sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+static int
+sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
 {
-	DigestState *s;
-	uchar buf[11];
+	put64(aad, seq);
+	aad[8] = hdr[0];
+	aad[9] = hdr[3];
+	aad[10] = hdr[4];
+	return 11;
+}
 
-	memmove(buf, seq, 8);
-	buf[8] = header[0];
-	buf[9] = header[3];
-	buf[10] = header[4];
-
-	s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
-	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+static int
+tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+{
+	put64(aad, seq);
+	aad[8] = hdr[0];
+	aad[9] = hdr[1];
+	aad[10] = hdr[2];
+	aad[11] = hdr[3];
+	aad[12] = hdr[4];
+	return 13;
 }
 
 static void
-tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+packMac(Secret *sec, uchar *aad, int aadlen, uchar *body, int bodylen, uchar *mac)
 {
 	DigestState *s;
-	uchar buf[13];
 
-	memmove(buf, seq, 8);
-	memmove(&buf[8], header, 5);
-
-	s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
-	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+	s = (*sec->mac)(aad, aadlen, sec->mackey, sec->maclen, nil, nil);
+	(*sec->mac)(body, bodylen, sec->mackey, sec->maclen, mac, s);
 }
 
 static void
@@ -2191,10 +2274,10 @@
 }
 
 static void
-put64(uchar *p, vlong x)
+put64(uchar *p, u64int x)
 {
-	put32(p, (u32int)(x >> 32));
-	put32(p+4, (u32int)x);
+	put32(p, x >> 32);
+	put32(p+4, x);
 }
 
 static void
--- a/sys/src/libsec/port/ccpoly.c
+++ b/sys/src/libsec/port/ccpoly.c
@@ -15,7 +15,7 @@
 }
 
 static void
-ccpolymac(uchar *buf, ulong nbuf, DigestState *ds)
+ccpolypad(uchar *buf, ulong nbuf, DigestState *ds)
 {
 	static uchar zeros[16] = {0};
 	ulong npad;
@@ -30,29 +30,19 @@
 }
 
 static void
-ccpolytag(ulong ndat, ulong naad, uchar tag[16], DigestState *ds)
+ccpolylen(ulong n, uchar tag[16], DigestState *ds)
 {
-	uchar info[16];
+	uchar info[8];
 
-	info[0] = naad;
-	info[1] = naad>>8;
-	info[2] = naad>>16;
-	info[3] = naad>>24;
+	info[0] = n;
+	info[1] = n>>8;
+	info[2] = n>>16;
+	info[3] = n>>24;
 	info[4] = 0;
 	info[5] = 0;
 	info[6] = 0;
 	info[7] = 0;
-
-	info[8]  = ndat;
-	info[9]  = ndat>>8;
-	info[10] = ndat>>16;
-	info[11] = ndat>>24;
-	info[12] = 0;
-	info[13] = 0;
-	info[14] = 0;
-	info[15] = 0;
-
-	poly1305(info, 16, nil, 0, tag, ds);
+	poly1305(info, 8, nil, 0, tag, ds);
 }
 
 void
@@ -61,10 +51,19 @@
 	DigestState ds;
 
 	ccpolyotk(cs, &ds);
-	ccpolymac(aad, naad, &ds);
-	chacha_encrypt(dat, ndat, cs);
-	ccpolymac(dat, ndat, &ds);
-	ccpolytag(ndat, naad, tag, &ds);
+	if(cs->ivwords == 2){
+		poly1305(aad, naad, nil, 0, nil, &ds);
+		ccpolylen(naad, nil, &ds);
+		chacha_encrypt(dat, ndat, cs);
+		poly1305(dat, ndat, nil, 0, nil, &ds);
+		ccpolylen(ndat, tag, &ds);
+	} else {
+		ccpolypad(aad, naad, &ds);
+		chacha_encrypt(dat, ndat, cs);
+		ccpolypad(dat, ndat, &ds);
+		ccpolylen(naad, nil, &ds);
+		ccpolylen(ndat, tag, &ds);
+	}
 }
 
 int
@@ -74,9 +73,17 @@
 	uchar tmp[16];
 
 	ccpolyotk(cs, &ds);
-	ccpolymac(aad, naad, &ds);
-	ccpolymac(dat, ndat, &ds);
-	ccpolytag(ndat, naad, tmp, &ds);
+	if(cs->ivwords == 2){
+		poly1305(aad, naad, nil, 0, nil, &ds);
+		ccpolylen(naad, nil, &ds);
+		poly1305(dat, ndat, nil, 0, nil, &ds);
+		ccpolylen(ndat, tmp, &ds);
+	} else {
+		ccpolypad(aad, naad, &ds);
+		ccpolypad(dat, ndat, &ds);
+		ccpolylen(naad, nil, &ds);
+		ccpolylen(ndat, tmp, &ds);
+	}
 	if(tsmemcmp(tag, tmp, 16) != 0)
 		return -1;
 	chacha_encrypt(dat, ndat, cs);
--- a/sys/src/libsec/port/chachatest.c
+++ b/sys/src/libsec/port/chachatest.c
@@ -57,6 +57,26 @@
 	0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91,
 };
 
+uchar	ccp64aad[] = {
+	0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0,
+};
+uchar	ccp64key[] = {
+	0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, 0x57, 0xf3, 0xbe, 0x3b, 0x50,
+	0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07,
+};
+uchar	ccp64iv[] = {
+	0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a,
+};
+uchar	ccp64inp[] = {
+	0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca, 
+};
+uchar	ccp64out[] = {
+	0xe3, 0xe4, 0x46, 0xf7, 0xed, 0xe9, 0xa1, 0x9b, 0x62, 0xa4,
+};
+uchar	ccp64tag[] = {
+	0x67, 0x7d, 0xab, 0xf4, 0xe3, 0xd2, 0x4b, 0x87, 0x6b, 0xb2, 0x84, 0x75, 0x38, 0x96, 0xe1, 0xd6,
+};
+
 void
 main(int argc, char **argv)
 {
@@ -112,6 +132,42 @@
 
 	if(memcmp(rfcout, rfctext, sizeof(rfctext)-1) != 0){
 		print("ccpoly bad decryption\n");
+		exits("wrong");
+	}
+	print("\n");
+
+	print("ccpoly64 key:\n");
+	printblock(ccp64key, sizeof(ccp64key));
+
+	print("ccpoly64 iv:\n");
+	printblock(ccp64iv, sizeof(ccp64iv));
+
+	setupChachastate(&s, ccp64key, sizeof(ccp64key), ccp64iv, sizeof(ccp64iv), 20);
+
+	memmove(rfcout, ccp64inp, sizeof(ccp64inp));
+	ccpoly_encrypt(rfcout, sizeof(ccp64inp), ccp64aad, sizeof(ccp64aad), tag, &s);
+
+	print("ccpoly64 cipher:\n");
+	printblock(rfcout, sizeof(ccp64inp));
+
+	print("ccpoly64 tag:\n");
+	printblock(tag, sizeof(tag));
+
+	if(memcmp(rfcout, ccp64out, sizeof(ccp64out)) != 0){
+		print("ccpoly64 bad ciphertext\n");
+		exits("wrong");
+	}
+	if(memcmp(tag, ccp64tag, sizeof(ccp64tag)) != 0){
+		print("ccpoly64 bad encryption tag\n");
+		exits("wrong");
+	}
+
+	if(ccpoly_decrypt(rfcout, sizeof(ccp64inp), ccp64aad, sizeof(ccp64aad), tag, &s) != 0){
+		print("ccpoly64 decryption failed\n");
+		exits("wrong");
+	}
+	if(memcmp(rfcout, ccp64inp, sizeof(ccp64inp)) != 0){
+		print("ccpoly64 bad decryption\n");
 		exits("wrong");
 	}
 
--- a/sys/src/libsec/port/mkfile
+++ b/sys/src/libsec/port/mkfile
@@ -47,3 +47,6 @@
 
 $O.rsatest: rsatest.$O
 	$LD -o $target $prereq
+
+$O.chachatest: chachatest.$O
+	$LD -o $target $prereq
--- a/sys/src/libsec/port/poly1305.c
+++ b/sys/src/libsec/port/poly1305.c
@@ -63,6 +63,10 @@
 		if(s->blen == 16){
 			s->blen = 0;
 			poly1305(s->buf, 16, key, klen, nil, s);
+		} else if(len == 0){
+			m = s->buf;
+			len = s->blen;
+			s->blen = 0;
 		}
 	}
 
--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -283,6 +283,10 @@
 };
 
 static Algs cipherAlgs[] = {
+	{"ccpoly96_aead", "clear", 2*(32+12), 0xCCA8},	// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (IETF)
+	{"ccpoly96_aead", "clear", 2*(32+12), 0xCCAA},	// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (IETF)
+	{"ccpoly64_aead", "clear", 2*32, 0xCC13},	// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (draft)
+	{"ccpoly64_aead", "clear", 2*32, 0xCC15},	// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (draft)
 	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
 	{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 	{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
@@ -778,10 +782,11 @@
 isDHE(int tlsid)
 {
 	switch(tlsid){
- 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
  	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
  	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
  	case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ 	case 0xCCAA: case 0xCC15:	// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
 		return 1;
 	}
 	return 0;
@@ -794,6 +799,7 @@
 	case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
 	case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
 	case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+	case 0xCCA8: case 0xCC13:	// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
 		return 1;
 	}
 	return 0;