summaryrefslogtreecommitdiff
path: root/sys/src/libsec/port/ccpoly.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-11-26 15:25:10 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2015-11-26 15:25:10 +0100
commit254031cf7020f1b185c6d0af89c653a271e0ed01 (patch)
tree9d8b55c3639a7c137ca6cd135a81b5f395d5f860 /sys/src/libsec/port/ccpoly.c
parent90695e2eb24430a984e76afb6aaf1c10e2d4809e (diff)
libsec: add chacha20 poly1305 aead, allow 64 bit iv's for chacha, add tsmemcmp()
chacha20 comes in two variants: ietf rfc7539, using 96 bit iv and 32 bit counter and draft-agl-tls-chacha20poly1305 using 64 bit iv and a 64 bit counter. so setupChachastate() now takes a ivlen argument which sets the mode. add ccpoly_encrypt()/ccpoly_decrypt() routines. to implement timing safe ccpoly_decrypt(), a constant time memcmp was needed, so adding tsmemcmp() to libsec.
Diffstat (limited to 'sys/src/libsec/port/ccpoly.c')
-rw-r--r--sys/src/libsec/port/ccpoly.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/sys/src/libsec/port/ccpoly.c b/sys/src/libsec/port/ccpoly.c
new file mode 100644
index 000000000..14a8a9cd4
--- /dev/null
+++ b/sys/src/libsec/port/ccpoly.c
@@ -0,0 +1,84 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+
+static void
+ccpolyotk(Chachastate *cs, DigestState *ds)
+{
+ uchar otk[ChachaBsize];
+
+ memset(ds, 0, sizeof(*ds));
+ memset(otk, 0, 32);
+ chacha_setblock(cs, 0);
+ chacha_encrypt(otk, ChachaBsize, cs);
+ poly1305(nil, 0, otk, 32, nil, ds);
+}
+
+static void
+ccpolymac(uchar *buf, ulong nbuf, DigestState *ds)
+{
+ static uchar zeros[16] = {0};
+ ulong npad;
+
+ if(nbuf == 0)
+ return;
+ poly1305(buf, nbuf, nil, 0, nil, ds);
+ npad = nbuf % 16;
+ if(npad == 0)
+ return;
+ poly1305(zeros, 16 - npad, nil, 0, nil, ds);
+}
+
+static void
+ccpolytag(ulong ndat, ulong naad, uchar tag[16], DigestState *ds)
+{
+ uchar info[16];
+
+ info[0] = naad;
+ info[1] = naad>>8;
+ info[2] = naad>>16;
+ info[3] = naad>>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);
+}
+
+void
+ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs)
+{
+ DigestState ds;
+
+ ccpolyotk(cs, &ds);
+ ccpolymac(aad, naad, &ds);
+ chacha_encrypt(dat, ndat, cs);
+ ccpolymac(dat, ndat, &ds);
+ ccpolytag(ndat, naad, tag, &ds);
+}
+
+int
+ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs)
+{
+ DigestState ds;
+ uchar tmp[16];
+
+ ccpolyotk(cs, &ds);
+ ccpolymac(aad, naad, &ds);
+ ccpolymac(dat, ndat, &ds);
+ ccpolytag(ndat, naad, tmp, &ds);
+ if(tsmemcmp(tag, tmp, 16) != 0)
+ return -1;
+ chacha_encrypt(dat, ndat, cs);
+ return 0;
+}