summaryrefslogtreecommitdiff
path: root/sys/src/libsec
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-12-21 04:55:54 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2015-12-21 04:55:54 +0100
commit9b0de7f9d63386bc5e2cb5889559bbdb0c11503d (patch)
tree6fa390dc52135dc36053e1c2464561af3a5ecf9c /sys/src/libsec
parentd19144155e3825507cc01901a83d99bd64a8b0aa (diff)
tls: implement chacha20/poly1305 aead cipher suits
Diffstat (limited to 'sys/src/libsec')
-rw-r--r--sys/src/libsec/port/ccpoly.c57
-rw-r--r--sys/src/libsec/port/chachatest.c56
-rw-r--r--sys/src/libsec/port/mkfile3
-rw-r--r--sys/src/libsec/port/poly1305.c4
-rw-r--r--sys/src/libsec/port/tlshand.c8
5 files changed, 102 insertions, 26 deletions
diff --git a/sys/src/libsec/port/ccpoly.c b/sys/src/libsec/port/ccpoly.c
index 14a8a9cd4..76162f60f 100644
--- a/sys/src/libsec/port/ccpoly.c
+++ b/sys/src/libsec/port/ccpoly.c
@@ -15,7 +15,7 @@ ccpolyotk(Chachastate *cs, DigestState *ds)
}
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 @@ ccpolymac(uchar *buf, ulong nbuf, DigestState *ds)
}
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 @@ ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Ch
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 @@ ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Ch
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);
diff --git a/sys/src/libsec/port/chachatest.c b/sys/src/libsec/port/chachatest.c
index e578dec17..92a5d0897 100644
--- a/sys/src/libsec/port/chachatest.c
+++ b/sys/src/libsec/port/chachatest.c
@@ -57,6 +57,26 @@ uchar ccptag[] = {
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)
{
@@ -114,6 +134,42 @@ main(int argc, char **argv)
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");
+ }
print("passed\n");
exits(nil);
diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile
index d76e81b91..fa46b39a5 100644
--- a/sys/src/libsec/port/mkfile
+++ b/sys/src/libsec/port/mkfile
@@ -47,3 +47,6 @@ UPDATE=mkfile\
$O.rsatest: rsatest.$O
$LD -o $target $prereq
+
+$O.chachatest: chachatest.$O
+ $LD -o $target $prereq
diff --git a/sys/src/libsec/port/poly1305.c b/sys/src/libsec/port/poly1305.c
index 63fbe48c3..0ec15be26 100644
--- a/sys/src/libsec/port/poly1305.c
+++ b/sys/src/libsec/port/poly1305.c
@@ -63,6 +63,10 @@ poly1305(uchar *m, ulong len, uchar *key, ulong klen, uchar *digest, DigestState
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;
}
}
diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c
index fef121402..c2599b999 100644
--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -283,6 +283,10 @@ enum {
};
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 @@ static int
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 @@ isECDHE(int tlsid)
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;