summaryrefslogtreecommitdiff
path: root/sys/src/9
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-03-23 02:45:35 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2016-03-23 02:45:35 +0100
commitaa6673fcfbe3bc41078487f4ef5d5aea459cd953 (patch)
tree691a08eb0191904f7f8ba8a7f9ad4939aafa9907 /sys/src/9
parent7ff779ff52b3da9c3b4cfee38cd90088ac65d6c3 (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.c97
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 *)
{