diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-10-17 21:34:01 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-10-17 21:34:01 +0200 |
commit | 45b7d60bf385aa9ac0bab7bb8c694f8221893024 (patch) | |
tree | fc0cd92b12aa8c4815b68e33a84368c76218f1ed /sys/src/libsec | |
parent | 0db4f40629762d1be583c49756cbcfc2561cb0fa (diff) |
libsec: add AES CFB and AES OFB stream ciphers
Diffstat (limited to 'sys/src/libsec')
-rw-r--r-- | sys/src/libsec/port/aes.c | 159 | ||||
-rw-r--r-- | sys/src/libsec/port/aesCBC.c | 60 | ||||
-rw-r--r-- | sys/src/libsec/port/aesCFB.c | 50 | ||||
-rw-r--r-- | sys/src/libsec/port/aesOFB.c | 28 | ||||
-rw-r--r-- | sys/src/libsec/port/aesXCBmac.c | 93 | ||||
-rw-r--r-- | sys/src/libsec/port/mkfile | 3 |
6 files changed, 238 insertions, 155 deletions
diff --git a/sys/src/libsec/port/aes.c b/sys/src/libsec/port/aes.c index 417920354..a4b344c6b 100644 --- a/sys/src/libsec/port/aes.c +++ b/sys/src/libsec/port/aes.c @@ -42,20 +42,6 @@ static const u32 Td1[256]; static const u32 Td2[256]; static const u32 Td3[256]; static const u8 Te4[256]; -static uchar basekey[3][16] = { - { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - }, - { - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - }, - { - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - }, -}; static int aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[], int keyBits); @@ -65,6 +51,11 @@ static int aes_setup(ulong erk[/*4*(Nr + 1)*/], ulong drk[/*4*(Nr + 1)*/], void aes_encrypt(const ulong rk[], int Nr, const uchar pt[16], uchar ct[16]); void aes_decrypt(const ulong rk[], int Nr, const uchar ct[16], uchar pt[16]); +#define GETU32(pt) (((u32)(pt)[0]<<24) ^ ((u32)(pt)[1]<<16) ^ \ + ((u32)(pt)[2]<< 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st)>>24); (ct)[1] = (u8)((st)>>16); \ + (ct)[2] = (u8)((st)>> 8); (ct)[3] = (u8)(st); } + void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec) { @@ -82,141 +73,6 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec) } /* - * AES-XCBC-MAC-96 message authentication, per rfc3566. - */ - -void -setupAESXCBCstate(AESstate *s) /* was setupmac96 */ -{ - int i, j; - uint q[16 / sizeof(uint)]; - uchar *p; - - assert(s->keybytes == 16); - for(i = 0; i < 3; i++) - aes_encrypt(s->ekey, s->rounds, basekey[i], - s->mackey + AESbsize*i); - - p = s->mackey; - memset(q, 0, AESbsize); - - /* - * put the in the right endian. once figured, probably better - * to use some fcall macros. - * keys for encryption in local endianness for the algorithm... - * only key1 is used for encryption; - * BUG!!: I think this is what I got wrong. - */ - for(i = 0; i < 16 / sizeof(uint); i ++){ - for(j = 0; j < sizeof(uint); j++) - q[i] |= p[sizeof(uint)-j-1] << 8*j; - p += sizeof(uint); - } - memmove(s->mackey, q, 16); -} - -/* - * Not dealing with > 128-bit keys, not dealing with strange corner cases like - * empty message. Should be fine for AES-XCBC-MAC-96. - */ -uchar* -aesXCBCmac(uchar *p, int len, AESstate *s) -{ - uchar *p2, *ip, *eip, *mackey; - uchar q[AESbsize]; - - assert(s->keybytes == 16); /* more complicated for bigger */ - memset(s->ivec, 0, AESbsize); /* E[0] is 0+ */ - - for(; len > AESbsize; len -= AESbsize){ - memmove(q, p, AESbsize); - p2 = q; - ip = s->ivec; - for(eip = ip + AESbsize; ip < eip; ) - *p2++ ^= *ip++; - aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec); - p += AESbsize; - } - /* the last one */ - - memmove(q, p, len); - p2 = q+len; - if(len == AESbsize) - mackey = s->mackey + AESbsize; /* k2 */ - else{ - mackey = s->mackey+2*AESbsize; /* k3 */ - *p2++ = 1 << 7; /* padding */ - len = AESbsize - len - 1; - memset(p2, 0, len); - } - - ip = s->ivec; - p2 = q; - for(eip = ip + AESbsize; ip < eip; ) - *p2++ ^= *ip++ ^ *mackey++; - aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec); - return s->ivec; /* only the 12 bytes leftmost */ -} - -/* - * Define by analogy with desCBCencrypt; AES modes are not standardized yet. - * Because of the way that non-multiple-of-16 buffers are handled, - * the decryptor must be fed buffers of the same size as the encryptor. - */ -void -aesCBCencrypt(uchar *p, int len, AESstate *s) -{ - uchar *p2, *ip, *eip; - uchar q[AESbsize]; - - for(; len >= AESbsize; len -= AESbsize){ - p2 = p; - ip = s->ivec; - for(eip = ip+AESbsize; ip < eip; ) - *p2++ ^= *ip++; - aes_encrypt(s->ekey, s->rounds, p, q); - memmove(s->ivec, q, AESbsize); - memmove(p, q, AESbsize); - p += AESbsize; - } - - if(len > 0){ - ip = s->ivec; - aes_encrypt(s->ekey, s->rounds, ip, q); - memmove(s->ivec, q, AESbsize); - for(eip = ip+len; ip < eip; ) - *p++ ^= *ip++; - } -} - -void -aesCBCdecrypt(uchar *p, int len, AESstate *s) -{ - uchar *ip, *eip, *tp; - uchar tmp[AESbsize], q[AESbsize]; - - for(; len >= AESbsize; len -= AESbsize){ - memmove(tmp, p, AESbsize); - aes_decrypt(s->dkey, s->rounds, p, q); - memmove(p, q, AESbsize); - tp = tmp; - ip = s->ivec; - for(eip = ip+AESbsize; ip < eip; ){ - *p++ ^= *ip; - *ip++ = *tp++; - } - } - - if(len > 0){ - ip = s->ivec; - aes_encrypt(s->ekey, s->rounds, ip, q); - memmove(s->ivec, q, AESbsize); - for(eip = ip+len; ip < eip; ) - *p++ ^= *ip++; - } -} - -/* * this function has been changed for plan 9. * Expand the cipher key into the encryption and decryption key schedules. * @@ -955,11 +811,6 @@ static const u32 rcon[] = { /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; -#define GETU32(pt) (((u32)(pt)[0]<<24) ^ ((u32)(pt)[1]<<16) ^ \ - ((u32)(pt)[2]<< 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { (ct)[0] = (u8)((st)>>24); (ct)[1] = (u8)((st)>>16); \ - (ct)[2] = (u8)((st)>> 8); (ct)[3] = (u8)(st); } - /* * Expand the cipher key into the encryption key schedule. * diff --git a/sys/src/libsec/port/aesCBC.c b/sys/src/libsec/port/aesCBC.c new file mode 100644 index 000000000..918455797 --- /dev/null +++ b/sys/src/libsec/port/aesCBC.c @@ -0,0 +1,60 @@ +#include "os.h" +#include <libsec.h> + +/* + * Define by analogy with desCBCencrypt; AES modes are not standardized yet. + * Because of the way that non-multiple-of-16 buffers are handled, + * the decryptor must be fed buffers of the same size as the encryptor. + */ +void +aesCBCencrypt(uchar *p, int len, AESstate *s) +{ + uchar *p2, *ip, *eip; + uchar q[AESbsize]; + + for(; len >= AESbsize; len -= AESbsize){ + p2 = p; + ip = s->ivec; + for(eip = ip+AESbsize; ip < eip; ) + *p2++ ^= *ip++; + aes_encrypt(s->ekey, s->rounds, p, q); + memmove(s->ivec, q, AESbsize); + memmove(p, q, AESbsize); + p += AESbsize; + } + + if(len > 0){ + ip = s->ivec; + aes_encrypt(s->ekey, s->rounds, ip, q); + memmove(s->ivec, q, AESbsize); + for(eip = ip+len; ip < eip; ) + *p++ ^= *ip++; + } +} + +void +aesCBCdecrypt(uchar *p, int len, AESstate *s) +{ + uchar *ip, *eip, *tp; + uchar tmp[AESbsize], q[AESbsize]; + + for(; len >= AESbsize; len -= AESbsize){ + memmove(tmp, p, AESbsize); + aes_decrypt(s->dkey, s->rounds, p, q); + memmove(p, q, AESbsize); + tp = tmp; + ip = s->ivec; + for(eip = ip+AESbsize; ip < eip; ){ + *p++ ^= *ip; + *ip++ = *tp++; + } + } + + if(len > 0){ + ip = s->ivec; + aes_encrypt(s->ekey, s->rounds, ip, q); + memmove(s->ivec, q, AESbsize); + for(eip = ip+len; ip < eip; ) + *p++ ^= *ip++; + } +} diff --git a/sys/src/libsec/port/aesCFB.c b/sys/src/libsec/port/aesCFB.c new file mode 100644 index 000000000..a61dc92bd --- /dev/null +++ b/sys/src/libsec/port/aesCFB.c @@ -0,0 +1,50 @@ +#include "os.h" +#include <libsec.h> + +typedef ulong u32; + +void +aesCFBencrypt(uchar *p, int len, AESstate *s) +{ + u32 a, o = s->offset; + + while(len > 0){ + if(o % 16){ + Odd: + a = (s->ivec[o++ % 16] ^= *p), *p++ = a, len--; + continue; + } + aes_encrypt(s->ekey, s->rounds, s->ivec, s->ivec); + if(len < 16 || ((p-(uchar*)0) & 3) != 0) + goto Odd; + ((u32*)p)[0] = (((u32*)s->ivec)[0] ^= ((u32*)p)[0]); + ((u32*)p)[1] = (((u32*)s->ivec)[1] ^= ((u32*)p)[1]); + ((u32*)p)[2] = (((u32*)s->ivec)[2] ^= ((u32*)p)[2]); + ((u32*)p)[3] = (((u32*)s->ivec)[3] ^= ((u32*)p)[3]); + o += 16, p += 16, len -= 16; + } + s->offset = o; +} + +void +aesCFBdecrypt(uchar *p, int len, AESstate *s) +{ + u32 a, o = s->offset; + + while(len > 0){ + if(o % 16){ + Odd: + a = *p, *p++ ^= s->ivec[o % 16], s->ivec[o++ % 16] = a, len--; + continue; + } + aes_encrypt(s->ekey, s->rounds, s->ivec, s->ivec); + if(len < 16 || ((p-(uchar*)0) & 3) != 0) + goto Odd; + a = ((u32*)p)[0], ((u32*)p)[0] ^= ((u32*)s->ivec)[0], ((u32*)s->ivec)[0] = a; + a = ((u32*)p)[1], ((u32*)p)[1] ^= ((u32*)s->ivec)[1], ((u32*)s->ivec)[1] = a; + a = ((u32*)p)[2], ((u32*)p)[2] ^= ((u32*)s->ivec)[2], ((u32*)s->ivec)[2] = a; + a = ((u32*)p)[3], ((u32*)p)[3] ^= ((u32*)s->ivec)[3], ((u32*)s->ivec)[3] = a; + o += 16, p += 16, len -= 16; + } + s->offset = o; +} diff --git a/sys/src/libsec/port/aesOFB.c b/sys/src/libsec/port/aesOFB.c new file mode 100644 index 000000000..e58db210d --- /dev/null +++ b/sys/src/libsec/port/aesOFB.c @@ -0,0 +1,28 @@ +#include "os.h" +#include <libsec.h> + +typedef ulong u32; + +void +aesOFBencrypt(uchar *p, int len, AESstate *s) +{ + u32 o = s->offset; + + while(len > 0){ + if(o % 16){ + Odd: + *p++ ^= s->ivec[o++ % 16], len--; + continue; + } + aes_encrypt(s->ekey, s->rounds, s->ivec, s->ivec); + if(len < 16 || ((p-(uchar*)0) & 3) != 0) + goto Odd; + ((u32*)p)[0] ^= ((u32*)s->ivec)[0]; + ((u32*)p)[1] ^= ((u32*)s->ivec)[1]; + ((u32*)p)[2] ^= ((u32*)s->ivec)[2]; + ((u32*)p)[3] ^= ((u32*)s->ivec)[3]; + o += 16, p += 16, len -= 16; + } + s->offset = o; +} + diff --git a/sys/src/libsec/port/aesXCBmac.c b/sys/src/libsec/port/aesXCBmac.c new file mode 100644 index 000000000..6f17f87db --- /dev/null +++ b/sys/src/libsec/port/aesXCBmac.c @@ -0,0 +1,93 @@ +#include "os.h" +#include <libsec.h> + +/* + * AES-XCBC-MAC-96 message authentication, per rfc3566. + */ +static uchar basekey[3][16] = { + { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + }, + { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + }, + { + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + }, +}; + +void +setupAESXCBCstate(AESstate *s) /* was setupmac96 */ +{ + int i, j; + uint q[16 / sizeof(uint)]; + uchar *p; + + assert(s->keybytes == 16); + for(i = 0; i < 3; i++) + aes_encrypt(s->ekey, s->rounds, basekey[i], + s->mackey + AESbsize*i); + + p = s->mackey; + memset(q, 0, AESbsize); + + /* + * put the in the right endian. once figured, probably better + * to use some fcall macros. + * keys for encryption in local endianness for the algorithm... + * only key1 is used for encryption; + * BUG!!: I think this is what I got wrong. + */ + for(i = 0; i < 16 / sizeof(uint); i ++){ + for(j = 0; j < sizeof(uint); j++) + q[i] |= p[sizeof(uint)-j-1] << 8*j; + p += sizeof(uint); + } + memmove(s->mackey, q, 16); +} + +/* + * Not dealing with > 128-bit keys, not dealing with strange corner cases like + * empty message. Should be fine for AES-XCBC-MAC-96. + */ +uchar* +aesXCBCmac(uchar *p, int len, AESstate *s) +{ + uchar *p2, *ip, *eip, *mackey; + uchar q[AESbsize]; + + assert(s->keybytes == 16); /* more complicated for bigger */ + memset(s->ivec, 0, AESbsize); /* E[0] is 0+ */ + + for(; len > AESbsize; len -= AESbsize){ + memmove(q, p, AESbsize); + p2 = q; + ip = s->ivec; + for(eip = ip + AESbsize; ip < eip; ) + *p2++ ^= *ip++; + aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec); + p += AESbsize; + } + /* the last one */ + + memmove(q, p, len); + p2 = q+len; + if(len == AESbsize) + mackey = s->mackey + AESbsize; /* k2 */ + else{ + mackey = s->mackey+2*AESbsize; /* k3 */ + *p2++ = 1 << 7; /* padding */ + len = AESbsize - len - 1; + memset(p2, 0, len); + } + + ip = s->ivec; + p2 = q; + for(eip = ip + AESbsize; ip < eip; ) + *p2++ ^= *ip++ ^ *mackey++; + aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec); + return s->ivec; /* only the 12 bytes leftmost */ +} diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index bf831bc0e..1580fbff4 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -3,7 +3,8 @@ LIB=/$objtype/lib/libsec.a CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ - aes.c aes_gcm.c blowfish.c \ + aes.c aesCBC.c aesCFB.c aesOFB.c aesXCBmac.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\ |