diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-11-26 15:25:10 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-11-26 15:25:10 +0100 |
commit | 254031cf7020f1b185c6d0af89c653a271e0ed01 (patch) | |
tree | 9d8b55c3639a7c137ca6cd135a81b5f395d5f860 /sys/src/libsec/port/ccpoly.c | |
parent | 90695e2eb24430a984e76afb6aaf1c10e2d4809e (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.c | 84 |
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; +} |