diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-03-23 02:45:35 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-03-23 02:45:35 +0100 |
commit | aa6673fcfbe3bc41078487f4ef5d5aea459cd953 (patch) | |
tree | 691a08eb0191904f7f8ba8a7f9ad4939aafa9907 /sys/src/9 | |
parent | 7ff779ff52b3da9c3b4cfee38cd90088ac65d6c3 (diff) |
add portable AES-GCM (Galois/Counter Mode) implementation to libsec and devtls
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/port/devtls.c | 97 |
1 files changed, 79 insertions, 18 deletions
diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 93bd8225e..a30a60b35 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -88,11 +88,12 @@ struct Secret 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 (*aead_enc)(Secret*, uchar*, int, uchar*, uchar*, int); + int (*aead_dec)(Secret*, uchar*, int, uchar*, uchar*, int); int block; /* encryption block len, 0 if none */ int maclen; + int recivlen; void *enckey; uchar mackey[MaxMacLen]; }; @@ -246,8 +247,10 @@ static int des3enc(Secret *sec, uchar *buf, int n); 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 ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, 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); @@ -821,14 +824,16 @@ if(tr->debug) pprint("decrypted %d\n", unpad_len); if(tr->debug) pdump(unpad_len, p, "decrypted:"); } + ivlen = sec->recivlen; if(tr->version >= TLS11Version){ - ivlen = sec->block; - len -= ivlen; - if(len < 0) - rcvError(tr, EDecodeError, "runt record message"); - unpad_len -= ivlen; - p += ivlen; + if(ivlen == 0) + ivlen = sec->block; } + len -= ivlen; + if(len < 0) + rcvError(tr, EDecodeError, "runt record message"); + unpad_len -= ivlen; + p += ivlen; if(unpad_len >= sec->maclen) len = unpad_len - sec->maclen; @@ -837,7 +842,7 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:"); put16(header+3, len); aadlen = (*tr->packAAD)(in->seq++, header, aad); if(sec->aead_dec != nil) { - len = (*sec->aead_dec)(sec, aad, aadlen, p, unpad_len); + len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len); if(len < 0) rcvError(tr, EBadRecordMac, "record mac mismatch"); } else { @@ -1299,8 +1304,11 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); if(sec != nil){ maclen = sec->maclen; pad = maclen + sec->block; - if(tr->version >= TLS11Version) - ivlen = sec->block; + ivlen = sec->recivlen; + if(tr->version >= TLS11Version){ + if(ivlen == 0) + ivlen = sec->block; + } } n = BLEN(bb); if(n > MaxRecLen){ @@ -1326,12 +1334,12 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); put16(p+3, n); if(sec != nil){ - if(ivlen > 0) - randfill(p + RecHdrLen, 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; + n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen; else { + if(ivlen > 0) + randfill(p + RecHdrLen, ivlen); packMac(sec, aad, aadlen, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n); n = (*sec->enc)(sec, p + RecHdrLen, ivlen + n + maclen); } @@ -1527,6 +1535,23 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv) } static void +initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) +{ + s->enckey = smalloc(sizeof(AESGCMstate)); + s->enc = noenc; + s->dec = noenc; + s->mac = nomac; + s->aead_enc = aesgcm_aead_enc; + s->aead_dec = aesgcm_aead_dec; + s->block = 0; + s->maclen = 16; + s->recivlen = 8; + memmove(s->mackey, iv, ea->ivlen); + randfill(s->mackey + ea->ivlen, s->recivlen); + setupAESGCMstate(s->enckey, p, ea->keylen, nil, 0); +} + +static void initclearenc(Encalg *, Secret *s, uchar *, uchar *) { s->enc = noenc; @@ -1543,6 +1568,8 @@ static Encalg encrypttab[] = { "aes_256_cbc", 256/8, 16, initAESkey }, { "ccpoly64_aead", 256/8, 0, initccpolykey }, { "ccpoly96_aead", 256/8, 96/8, initccpolykey }, + { "aes_128_gcm_aead", 128/8, 4, initaesgcmkey }, + { "aes_256_gcm_aead", 256/8, 4, initaesgcmkey }, { 0 } }; @@ -1697,6 +1724,7 @@ tlswrite(Chan *c, void *a, long n, vlong off) if(!tos->mac || !tos->enc || !tos->dec || !toc->mac || !toc->enc || !toc->dec) error("missing algorithm implementations"); + if(strtol(cb->f[3], nil, 0) == 0){ tr->in.new = tos; tr->out.new = toc; @@ -2155,16 +2183,18 @@ ccpoly_aead_setiv(Secret *sec, uchar seq[8]) } static int -ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len) +ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) { + USED(reciv); 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) +ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) { + USED(reciv); len -= sec->maclen; if(len < 0) return -1; @@ -2174,6 +2204,37 @@ ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len) return len; } +static int +aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) +{ + uchar iv[12]; + int i; + + memmove(iv, sec->mackey, 4+8); + for(i=0; i<8; i++) iv[4+i] ^= aad[i]; + memmove(reciv, iv+4, 8); + aesgcm_setiv(sec->enckey, iv, 12); + aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey); + return len + sec->maclen; +} + +static int +aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) +{ + uchar iv[12]; + + len -= sec->maclen; + if(len < 0) + return -1; + memmove(iv, sec->mackey, 4); + memmove(iv+4, reciv, 8); + aesgcm_setiv(sec->enckey, iv, 12); + if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0) + return -1; + return len; +} + + static DigestState* nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *) { |