add portable AES-GCM (Galois/Counter Mode) implementation to libsec and devtls
This commit is contained in:
parent
7ff779ff52
commit
aa6673fcfb
7 changed files with 669 additions and 22 deletions
|
@ -27,7 +27,7 @@ struct AESstate
|
|||
ulong ekey[4*(AESmaxrounds + 1)]; /* encryption key */
|
||||
ulong dkey[4*(AESmaxrounds + 1)]; /* decryption key */
|
||||
uchar ivec[AESbsize]; /* initialization vector */
|
||||
uchar mackey[3 * AESbsize]; /* 3 XCBC mac 96 keys */
|
||||
uchar mackey[3 * AESbsize]; /* 3 XCBC mac 96 keys */
|
||||
};
|
||||
|
||||
/* block ciphers */
|
||||
|
@ -41,6 +41,20 @@ void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
|||
void setupAESXCBCstate(AESstate *s);
|
||||
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
|
||||
|
||||
typedef struct AESGCMstate AESGCMstate;
|
||||
struct AESGCMstate
|
||||
{
|
||||
AESstate;
|
||||
|
||||
ulong H[4];
|
||||
ulong M[16][256][4];
|
||||
};
|
||||
|
||||
void setupAESGCMstate(AESGCMstate *s, uchar *key, int keylen, uchar *iv, int ivlen);
|
||||
void aesgcm_setiv(AESGCMstate *s, uchar *iv, int ivlen);
|
||||
void aesgcm_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s);
|
||||
int aesgcm_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s);
|
||||
|
||||
/*
|
||||
* Blowfish Definitions
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.TH AES 2
|
||||
.SH NAME
|
||||
setupAESstate, aesCBCencrypt, aesCBCdecrypt, setupAESXCBCstate, aesXCBCmac - advanced encryption standard (rijndael)
|
||||
setupAESstate, aesCBCencrypt, aesCBCdecrypt, setupAESXCBCstate, aesXCBCmac, setupAESGCMstate - advanced encryption standard (rijndael)
|
||||
.SH SYNOPSIS
|
||||
.B #include <u.h>
|
||||
.br
|
||||
|
@ -32,6 +32,18 @@ void setupAESXCBCstate(AESstate *s)
|
|||
.PP
|
||||
.B
|
||||
void aesXCBCmac(uchar *p, int len, AESstate *s)
|
||||
.PP
|
||||
.B
|
||||
void setupAESGCMstate(AESGCMstate *s, uchar *key, int keylen, uchar *iv, int ivlen)
|
||||
.PP
|
||||
.B
|
||||
void aesgcm_setiv(AESGCMstate *s, uchar *iv, int ivlen)
|
||||
.PP
|
||||
.B
|
||||
void aesgcm_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
|
||||
.PP
|
||||
.B
|
||||
int aesgcm_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
|
||||
.SH DESCRIPTION
|
||||
AES (a.k.a. Rijndael) has replaced DES as the preferred
|
||||
block cipher.
|
||||
|
@ -46,10 +58,27 @@ are the block ciphers, corresponding to
|
|||
and
|
||||
.I aesCBCdecrypt
|
||||
implement cipher-block-chaining encryption.
|
||||
.I setupAESXCBCstate
|
||||
.I SetupAESXCBCstate
|
||||
and
|
||||
.I aesXCBCmac
|
||||
implement AES XCBC message authentication, per RFC 3566.
|
||||
.IR SetupAESGCMstate ,
|
||||
.IR aesgcm_setiv ,
|
||||
.I aesgcm_encrypt
|
||||
and
|
||||
.I aesgcm_decrypt
|
||||
implement Galois/Counter Mode (GCM) authenticated encryption with associated data (AEAD).
|
||||
Before encryption or decryption, a new initialization vector (nonce) has to be set with
|
||||
.I aesgcm_setiv
|
||||
or by calling
|
||||
.I setupAESGCMstate
|
||||
with non-zero
|
||||
.I iv
|
||||
and
|
||||
.I ivlen
|
||||
arguments.
|
||||
Aesgcm_decrypt returns zero when authentication and decryption where successfull and
|
||||
non-zero otherwise.
|
||||
All ciphering is performed in place.
|
||||
.I Keybytes
|
||||
should be 16, 24, or 32.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -1526,6 +1534,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 *)
|
||||
{
|
||||
|
@ -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 *)
|
||||
{
|
||||
|
|
200
sys/src/libsec/port/aes_gcm.c
Normal file
200
sys/src/libsec/port/aes_gcm.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <mp.h>
|
||||
#include <libsec.h>
|
||||
|
||||
static void
|
||||
load128(uchar b[16], ulong W[4])
|
||||
{
|
||||
W[0] = (ulong)b[15] | (ulong)b[14]<<8 | (ulong)b[13]<<16 | (ulong)b[12]<<24;
|
||||
W[1] = (ulong)b[11] | (ulong)b[10]<<8 | (ulong)b[ 9]<<16 | (ulong)b[ 8]<<24;
|
||||
W[2] = (ulong)b[ 7] | (ulong)b[ 6]<<8 | (ulong)b[ 5]<<16 | (ulong)b[ 4]<<24;
|
||||
W[3] = (ulong)b[ 3] | (ulong)b[ 2]<<8 | (ulong)b[ 1]<<16 | (ulong)b[ 0]<<24;
|
||||
}
|
||||
|
||||
static void
|
||||
store128(ulong W[4], uchar b[16])
|
||||
{
|
||||
b[15] = W[0], b[14] = W[0]>>8, b[13] = W[0]>>16, b[12] = W[0]>>24;
|
||||
b[11] = W[1], b[10] = W[1]>>8, b[ 9] = W[1]>>16, b[ 8] = W[1]>>24;
|
||||
b[ 7] = W[2], b[ 6] = W[2]>>8, b[ 5] = W[2]>>16, b[ 4] = W[2]>>24;
|
||||
b[ 3] = W[3], b[ 2] = W[3]>>8, b[ 1] = W[3]>>16, b[ 0] = W[3]>>24;
|
||||
}
|
||||
|
||||
static void
|
||||
gfmul(ulong X[4], ulong Y[4], ulong Z[4])
|
||||
{
|
||||
long m, i;
|
||||
|
||||
Z[0] = Z[1] = Z[2] = Z[3] = 0;
|
||||
for(i=127; i>=0; i--){
|
||||
m = ((long)Y[i>>5] << 31-(i&31)) >> 31;
|
||||
Z[0] ^= X[0] & m;
|
||||
Z[1] ^= X[1] & m;
|
||||
Z[2] ^= X[2] & m;
|
||||
Z[3] ^= X[3] & m;
|
||||
m = ((long)X[0]<<31) >> 31;
|
||||
X[0] = X[0]>>1 | X[1]<<31;
|
||||
X[1] = X[1]>>1 | X[2]<<31;
|
||||
X[2] = X[2]>>1 | X[3]<<31;
|
||||
X[3] = X[3]>>1 ^ (0xE1000000 & m);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prepareM(ulong H[4], ulong M[16][256][4])
|
||||
{
|
||||
ulong X[4], i, j;
|
||||
|
||||
for(i=0; i<16; i++){
|
||||
for(j=0; j<256; j++){
|
||||
X[0] = X[1] = X[2] = X[3] = 0;
|
||||
X[i>>2] = j<<((i&3)<<3);
|
||||
gfmul(X, H, M[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ghash1(AESGCMstate *s, ulong X[4], ulong Y[4])
|
||||
{
|
||||
ulong *Xi, i;
|
||||
|
||||
X[0] ^= Y[0], X[1] ^= Y[1], X[2] ^= Y[2], X[3] ^= Y[3];
|
||||
if(0){
|
||||
gfmul(X, s->H, Y);
|
||||
return;
|
||||
}
|
||||
|
||||
Y[0] = Y[1] = Y[2] = Y[3] = 0;
|
||||
for(i=0; i<16; i++){
|
||||
Xi = s->M[i][(X[i>>2]>>((i&3)<<3))&0xFF];
|
||||
Y[0] ^= Xi[0];
|
||||
Y[1] ^= Xi[1];
|
||||
Y[2] ^= Xi[2];
|
||||
Y[3] ^= Xi[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ghashn(AESGCMstate *s, uchar *dat, ulong len, ulong Y[4])
|
||||
{
|
||||
uchar tmp[16];
|
||||
ulong X[4];
|
||||
|
||||
while(len >= 16){
|
||||
load128(dat, X);
|
||||
ghash1(s, X, Y);
|
||||
dat += 16, len -= 16;
|
||||
}
|
||||
if(len > 0){
|
||||
memmove(tmp, dat, len);
|
||||
memset(tmp+len, 0, 16-len);
|
||||
load128(tmp, X);
|
||||
ghash1(s, X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
static ulong
|
||||
aesxctr1(AESstate *s, uchar ctr[AESbsize], uchar *dat, ulong len)
|
||||
{
|
||||
uchar tmp[AESbsize];
|
||||
ulong i;
|
||||
|
||||
aes_encrypt(s->ekey, s->rounds, ctr, tmp);
|
||||
if(len > AESbsize)
|
||||
len = AESbsize;
|
||||
for(i=0; i<len; i++)
|
||||
dat[i] ^= tmp[i];
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
aesxctrn(AESstate *s, uchar *dat, ulong len)
|
||||
{
|
||||
uchar ctr[AESbsize];
|
||||
ulong i;
|
||||
|
||||
memmove(ctr, s->ivec, AESbsize);
|
||||
while(len > 0){
|
||||
for(i=AESbsize-1; i>=AESbsize-4; i--)
|
||||
if(++ctr[i] != 0)
|
||||
break;
|
||||
|
||||
if(aesxctr1(s, ctr, dat, len) < AESbsize)
|
||||
break;
|
||||
dat += AESbsize;
|
||||
len -= AESbsize;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aesgcm_setiv(AESGCMstate *s, uchar *iv, int ivlen)
|
||||
{
|
||||
if(ivlen == 96/8){
|
||||
memmove(s->ivec, iv, ivlen);
|
||||
memset(s->ivec+ivlen, 0, AESbsize-ivlen);
|
||||
s->ivec[AESbsize-1] = 1;
|
||||
} else {
|
||||
ulong L[4], Y[4] = {0};
|
||||
|
||||
ghashn(s, iv, ivlen, Y);
|
||||
L[0] = ivlen << 3;
|
||||
L[1] = ivlen >> 29;
|
||||
L[2] = L[3] = 0;
|
||||
ghash1(s, L, Y);
|
||||
store128(Y, s->ivec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setupAESGCMstate(AESGCMstate *s, uchar *key, int keylen, uchar *iv, int ivlen)
|
||||
{
|
||||
setupAESstate(s, key, keylen, nil);
|
||||
|
||||
memset(s->mackey, 0, AESbsize);
|
||||
aes_encrypt(s->ekey, s->rounds, s->mackey, s->mackey);
|
||||
load128(s->mackey, s->H);
|
||||
prepareM(s->H, s->M);
|
||||
|
||||
if(iv != nil && ivlen > 0)
|
||||
aesgcm_setiv(s, iv, ivlen);
|
||||
}
|
||||
|
||||
void
|
||||
aesgcm_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
|
||||
{
|
||||
ulong L[4], Y[4] = {0};
|
||||
|
||||
ghashn(s, aad, naad, Y);
|
||||
aesxctrn(s, dat, ndat);
|
||||
ghashn(s, dat, ndat, Y);
|
||||
L[0] = ndat << 3;
|
||||
L[1] = ndat >> 29;
|
||||
L[2] = naad << 3;
|
||||
L[3] = naad >> 29;
|
||||
ghash1(s, L, Y);
|
||||
store128(Y, tag);
|
||||
aesxctr1(s, s->ivec, tag, 16);
|
||||
}
|
||||
|
||||
int
|
||||
aesgcm_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
|
||||
{
|
||||
ulong L[4], Y[4] = {0};
|
||||
uchar tmp[16];
|
||||
|
||||
ghashn(s, aad, naad, Y);
|
||||
ghashn(s, dat, ndat, Y);
|
||||
L[0] = ndat << 3;
|
||||
L[1] = ndat >> 29;
|
||||
L[2] = naad << 3;
|
||||
L[3] = naad >> 29;
|
||||
ghash1(s, L, Y);
|
||||
store128(Y, tmp);
|
||||
aesxctr1(s, s->ivec, tmp, 16);
|
||||
if(tsmemcmp(tag, tmp, 16) != 0)
|
||||
return -1;
|
||||
aesxctrn(s, dat, ndat);
|
||||
return 0;
|
||||
}
|
314
sys/src/libsec/port/aesgcmtest.c
Normal file
314
sys/src/libsec/port/aesgcmtest.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <libsec.h>
|
||||
#include <mp.h>
|
||||
|
||||
typedef struct Test Test;
|
||||
struct Test
|
||||
{
|
||||
char *K;
|
||||
char *P;
|
||||
char *A;
|
||||
char *IV;
|
||||
char *T;
|
||||
};
|
||||
|
||||
Test tests[] = {
|
||||
{ /* Test Case 1 */
|
||||
"00000000000000000000000000000000",
|
||||
"",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"58E2FCCEFA7E3061367F1D57A4E7455A"
|
||||
},
|
||||
{ /* Test Case 2 */
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"AB6E47D42CEC13BDF53A67B21257BDDF",
|
||||
},
|
||||
{ /* Test Case 3 */
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b391aafd255",
|
||||
"",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"4D5C2AF327CD64A62CF35ABD2BA6FAB4"
|
||||
},
|
||||
{ /* Test Case 4 */
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"5BC94FBC3221A5DB94FAE95AE7121A47"
|
||||
},
|
||||
{ /* Test Case 5 */
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbad",
|
||||
|
||||
"3612D2E79E3B0785561BE14AACA2FCCB"
|
||||
},
|
||||
{ /* Test Case 6 */
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"9313225df88406e555909c5aff5269aa"
|
||||
"6a7a9538534f7da1e4c303d2a318a728"
|
||||
"c3c0c95156809539fcf0e2429a6b5254"
|
||||
"16aedbf5a0de6a57a637b39b",
|
||||
|
||||
"619CC5AEFFFE0BFA462AF43C1699D050"
|
||||
},
|
||||
{ /* Test Case 7 */
|
||||
"00000000000000000000000000000000"
|
||||
"0000000000000000",
|
||||
"",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"CD33B28AC773F74BA00ED1F312572435"
|
||||
},
|
||||
{ /* Test Case 8 */
|
||||
"00000000000000000000000000000000"
|
||||
"0000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"2FF58D80033927AB8EF4D4587514F0FB"
|
||||
},
|
||||
{ /* Test Case 9 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b391aafd255",
|
||||
"",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"9924A7C8587336BFB118024DB8674A14"
|
||||
},
|
||||
{ /* Test Case 10 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"2519498E80F1478F37BA55BD6D27618C"
|
||||
},
|
||||
{ /* Test Case 11 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbad",
|
||||
|
||||
"65DCC57FCF623A24094FCCA40D3533F8"
|
||||
},
|
||||
{ /* Test Case 12 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"9313225df88406e555909c5aff5269aa"
|
||||
"6a7a9538534f7da1e4c303d2a318a728"
|
||||
"c3c0c95156809539fcf0e2429a6b5254"
|
||||
"16aedbf5a0de6a57a637b39b",
|
||||
|
||||
"DCF566FF291C25BBB8568FC3D376A6D9"
|
||||
},
|
||||
{ /* Test Case 13 */
|
||||
"00000000000000000000000000000000"
|
||||
"00000000000000000000000000000000",
|
||||
"",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"530F8AFBC74536B9A963B4F1C4CB738B"
|
||||
},
|
||||
{ /* Test Case 14 */
|
||||
"00000000000000000000000000000000"
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"",
|
||||
"000000000000000000000000",
|
||||
|
||||
"D0D1C8A799996BF0265B98B5D48AB919"
|
||||
},
|
||||
{ /* Test Case 15 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b391aafd255",
|
||||
"",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"B094DAC5D93471BDEC1A502270E3CC6C"
|
||||
},
|
||||
{ /* Test Case 16 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbaddecaf888",
|
||||
|
||||
"76FC6ECE0F4E1768CDDF8853BB2D551B"
|
||||
},
|
||||
{ /* Test Case 17 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"cafebabefacedbad",
|
||||
|
||||
"3A337DBF46A792C45E454913FE2EA8F2"
|
||||
},
|
||||
{ /* Test Case 18 */
|
||||
"feffe9928665731c6d6a8f9467308308"
|
||||
"feffe9928665731c6d6a8f9467308308",
|
||||
"d9313225f88406e5a55909c5aff5269a"
|
||||
"86a7a9531534f7da2e4c303d8a318a72"
|
||||
"1c3c0c95956809532fcf0e2449a6b525"
|
||||
"b16aedf5aa0de657ba637b39",
|
||||
"feedfacedeadbeeffeedfacedeadbeef"
|
||||
"abaddad2",
|
||||
"9313225df88406e555909c5aff5269aa"
|
||||
"6a7a9538534f7da1e4c303d2a318a728"
|
||||
"c3c0c95156809539fcf0e2429a6b5254"
|
||||
"16aedbf5a0de6a57a637b39b",
|
||||
|
||||
"A44A8266EE1C8EB0C8B5D4CF5AE9F19A"
|
||||
},
|
||||
};
|
||||
|
||||
int
|
||||
parsehex(char *s, uchar *h, char *l)
|
||||
{
|
||||
char *e;
|
||||
mpint *m;
|
||||
int n;
|
||||
|
||||
n = strlen(s);
|
||||
if(n == 0)
|
||||
return 0;
|
||||
assert((n & 1) == 0);
|
||||
n >>= 1;
|
||||
e = nil;
|
||||
m = strtomp(s, &e, 16, nil);
|
||||
if(m == nil || *e != '\0')
|
||||
abort();
|
||||
mptober(m, h, n);
|
||||
if(l != nil)
|
||||
print("%s = %.*H\n", l, n, h);
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
runtest(Test *t)
|
||||
{
|
||||
AESGCMstate s;
|
||||
uchar key[1024], plain[1024], aad[1024], iv[1024], tag[16], tmp[16];
|
||||
int nkey, nplain, naad, niv;
|
||||
|
||||
nkey = parsehex(t->K, key, "K");
|
||||
nplain = parsehex(t->P, plain, "P");
|
||||
naad = parsehex(t->A, aad, "A");
|
||||
niv = parsehex(t->IV, iv, "IV");
|
||||
|
||||
setupAESGCMstate(&s, key, nkey, iv, niv);
|
||||
aesgcm_encrypt(plain, nplain, aad, naad, tag, &s);
|
||||
print("C = %.*H\n", nplain, plain);
|
||||
print("T = %.*H\n", 16, tag);
|
||||
|
||||
parsehex(t->T, tmp, nil);
|
||||
assert(memcmp(tmp, tag, 16) == 0);
|
||||
}
|
||||
|
||||
void
|
||||
perftest(void)
|
||||
{
|
||||
AESGCMstate s;
|
||||
static uchar zeros[16];
|
||||
uchar buf[1024*1024], tag[16];
|
||||
vlong now;
|
||||
int i, delta;
|
||||
|
||||
now = nsec();
|
||||
for(i=0; i<100; i++){
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if(1){
|
||||
setupAESGCMstate(&s, zeros, 16, zeros, 12);
|
||||
aesgcm_encrypt(buf, sizeof(buf), nil, 0, tag, &s);
|
||||
} else {
|
||||
setupAESstate(&s, zeros, 16, zeros);
|
||||
aesCBCencrypt(buf, sizeof(buf), &s);
|
||||
}
|
||||
}
|
||||
delta = (nsec() - now) / 1000000000LL;
|
||||
fprint(2, "%ds = %d/s\n", delta, i*sizeof(buf) / delta);
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
fmtinstall('H', encodefmt);
|
||||
|
||||
ARGBEGIN {
|
||||
case 'p':
|
||||
perftest();
|
||||
exits(nil);
|
||||
} ARGEND;
|
||||
|
||||
for(i=0; i<nelem(tests); i++){
|
||||
print("Test Case %d\n", i+1);
|
||||
runtest(&tests[i]);
|
||||
print("\n");
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
LIB=/$objtype/lib/libsec.a
|
||||
|
||||
CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
||||
aes.c blowfish.c \
|
||||
aes.c aes_gcm.c blowfish.c \
|
||||
hmac.c md5.c md5block.c md4.c sha1.c sha1block.c\
|
||||
sha2_64.c sha2_128.c sha2block64.c sha2block128.c\
|
||||
sha1pickle.c md5pickle.c\
|
||||
|
@ -61,3 +61,6 @@ $O.rsatest: rsatest.$O
|
|||
|
||||
$O.chachatest: chachatest.$O
|
||||
$LD -o $target $prereq
|
||||
|
||||
$O.aesgcmtest: aesgcmtest.$O
|
||||
$LD -o $target $prereq
|
||||
|
|
|
@ -269,6 +269,23 @@ enum {
|
|||
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C,
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D,
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067,
|
||||
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
|
||||
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
|
||||
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
|
||||
TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
|
||||
TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
|
||||
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
|
||||
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
|
||||
TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
|
||||
TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
|
||||
TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
|
||||
TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
|
||||
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
|
||||
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0XC013,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0XC014,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
|
||||
|
@ -302,6 +319,11 @@ static Algs cipherAlgs[] = {
|
|||
{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},
|
||||
{"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305},
|
||||
|
||||
{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
|
||||
{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
|
||||
{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_RSA_WITH_AES_128_GCM_SHA256},
|
||||
|
||||
{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
|
||||
{"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},
|
||||
|
@ -856,6 +878,7 @@ static int
|
|||
isDHE(int tlsid)
|
||||
{
|
||||
switch(tlsid){
|
||||
case TLS_DHE_RSA_WITH_AES_128_GCM_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:
|
||||
|
@ -877,6 +900,9 @@ isECDHE(int tlsid)
|
|||
case GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
|
||||
case GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305:
|
||||
|
||||
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||
|
||||
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
|
||||
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
|
||||
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
|
||||
|
|
Loading…
Reference in a new issue