libsec: add AES CFB and AES OFB stream ciphers
This commit is contained in:
parent
0db4f40629
commit
45b7d60bf3
10 changed files with 267 additions and 159 deletions
|
@ -29,6 +29,7 @@ typedef struct AESstate AESstate;
|
||||||
struct AESstate
|
struct AESstate
|
||||||
{
|
{
|
||||||
ulong setup;
|
ulong setup;
|
||||||
|
ulong offset;
|
||||||
int rounds;
|
int rounds;
|
||||||
int keybytes;
|
int keybytes;
|
||||||
uchar key[AESmaxkey]; /* unexpanded key */
|
uchar key[AESmaxkey]; /* unexpanded key */
|
||||||
|
@ -45,6 +46,9 @@ void aes_decrypt(ulong rk[], int Nr, uchar ct[16], uchar pt[16]);
|
||||||
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
|
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
|
||||||
void aesCBCencrypt(uchar *p, int len, AESstate *s);
|
void aesCBCencrypt(uchar *p, int len, AESstate *s);
|
||||||
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesCFBencrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesCFBdecrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesOFBencrypt(uchar *p, int len, AESstate *s);
|
||||||
|
|
||||||
void setupAESXCBCstate(AESstate *s);
|
void setupAESXCBCstate(AESstate *s);
|
||||||
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
|
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
|
||||||
|
|
|
@ -21,6 +21,7 @@ typedef struct AESstate AESstate;
|
||||||
struct AESstate
|
struct AESstate
|
||||||
{
|
{
|
||||||
ulong setup;
|
ulong setup;
|
||||||
|
ulong offset;
|
||||||
int rounds;
|
int rounds;
|
||||||
int keybytes;
|
int keybytes;
|
||||||
uchar key[AESmaxkey]; /* unexpanded key */
|
uchar key[AESmaxkey]; /* unexpanded key */
|
||||||
|
@ -37,6 +38,9 @@ void aes_decrypt(ulong rk[], int Nr, uchar ct[16], uchar pt[16]);
|
||||||
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
|
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
|
||||||
void aesCBCencrypt(uchar *p, int len, AESstate *s);
|
void aesCBCencrypt(uchar *p, int len, AESstate *s);
|
||||||
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesCFBencrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesCFBdecrypt(uchar *p, int len, AESstate *s);
|
||||||
|
void aesOFBencrypt(uchar *p, int len, AESstate *s);
|
||||||
|
|
||||||
void setupAESXCBCstate(AESstate *s);
|
void setupAESXCBCstate(AESstate *s);
|
||||||
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
|
uchar* aesXCBCmac(uchar *p, int len, AESstate *s);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.TH AES 2
|
.TH AES 2
|
||||||
.SH NAME
|
.SH NAME
|
||||||
setupAESstate, aesCBCencrypt, aesCBCdecrypt, setupAESXCBCstate, aesXCBCmac, setupAESGCMstate - advanced encryption standard (rijndael)
|
setupAESstate, aesCBCencrypt, aesCBCdecrypt, aesCFBencrypt, aesCFBdecrypt, aesOFBencrypt, setupAESXCBCstate, aesXCBCmac, setupAESGCMstate - advanced encryption standard (rijndael)
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <u.h>
|
.B #include <u.h>
|
||||||
.br
|
.br
|
||||||
|
@ -28,6 +28,15 @@ void aesCBCencrypt(uchar *p, int len, AESstate *s)
|
||||||
void aesCBCdecrypt(uchar *p, int len, AESstate *s)
|
void aesCBCdecrypt(uchar *p, int len, AESstate *s)
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
|
void aesCFBencrypt(uchar *p, int len, AESstate *s)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
void aesCFBdecrypt(uchar *p, int len, AESstate *s)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
void aesOFBencrypt(uchar *p, int len, AESstate *s)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
void setupAESXCBCstate(AESstate *s)
|
void setupAESXCBCstate(AESstate *s)
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
|
@ -53,11 +62,18 @@ and
|
||||||
are the block ciphers, corresponding to
|
are the block ciphers, corresponding to
|
||||||
.IR des (2)'s
|
.IR des (2)'s
|
||||||
.IR block_cipher .
|
.IR block_cipher .
|
||||||
.IR SetupAESstate ,
|
.IR AesCBCencrypt ,
|
||||||
.IR aesCBCencrypt ,
|
|
||||||
and
|
and
|
||||||
.I aesCBCdecrypt
|
.I aesCBCdecrypt
|
||||||
implement cipher-block-chaining encryption.
|
implement cipher-block-chaining encryption.
|
||||||
|
.IR AesCFBencrypt ,
|
||||||
|
.I aesCFBdecrypt
|
||||||
|
and
|
||||||
|
.I aesOFBencrypt
|
||||||
|
implement cipher-feedback- and output-feedback-mode
|
||||||
|
stream cipher encryption.
|
||||||
|
.IR SetupAESstate
|
||||||
|
is used to initialize the state of the above encryption modes.
|
||||||
.I SetupAESXCBCstate
|
.I SetupAESXCBCstate
|
||||||
and
|
and
|
||||||
.I aesXCBCmac
|
.I aesXCBCmac
|
||||||
|
|
|
@ -4,7 +4,8 @@ APE=/sys/src/ape
|
||||||
LIB=/$objtype/lib/ape/libsec.a
|
LIB=/$objtype/lib/ape/libsec.a
|
||||||
|
|
||||||
CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
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\
|
hmac.c md5.c md5block.c md4.c sha1.c sha1block.c\
|
||||||
sha2_64.c sha2_128.c sha2block64.c sha2block128.c\
|
sha2_64.c sha2_128.c sha2block64.c sha2block128.c\
|
||||||
sha1pickle.c md5pickle.c\
|
sha1pickle.c md5pickle.c\
|
||||||
|
|
|
@ -42,20 +42,6 @@ static const u32 Td1[256];
|
||||||
static const u32 Td2[256];
|
static const u32 Td2[256];
|
||||||
static const u32 Td3[256];
|
static const u32 Td3[256];
|
||||||
static const u8 Te4[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[],
|
static int aes_setupEnc(ulong rk[/*4*(Nr + 1)*/], const uchar cipherKey[],
|
||||||
int keyBits);
|
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_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]);
|
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
|
void
|
||||||
setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
|
setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
|
||||||
{
|
{
|
||||||
|
@ -81,141 +72,6 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec)
|
||||||
/* else aes_setup was invalid */
|
/* else aes_setup was invalid */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
* this function has been changed for plan 9.
|
||||||
* Expand the cipher key into the encryption and decryption key schedules.
|
* 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 */
|
/* 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.
|
* Expand the cipher key into the encryption key schedule.
|
||||||
*
|
*
|
||||||
|
|
60
sys/src/libsec/port/aesCBC.c
Normal file
60
sys/src/libsec/port/aesCBC.c
Normal file
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
50
sys/src/libsec/port/aesCFB.c
Normal file
50
sys/src/libsec/port/aesCFB.c
Normal file
|
@ -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;
|
||||||
|
}
|
28
sys/src/libsec/port/aesOFB.c
Normal file
28
sys/src/libsec/port/aesOFB.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
93
sys/src/libsec/port/aesXCBmac.c
Normal file
93
sys/src/libsec/port/aesXCBmac.c
Normal file
|
@ -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 */
|
||||||
|
}
|
|
@ -3,7 +3,8 @@
|
||||||
LIB=/$objtype/lib/libsec.a
|
LIB=/$objtype/lib/libsec.a
|
||||||
|
|
||||||
CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
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\
|
hmac.c md5.c md5block.c md4.c sha1.c sha1block.c\
|
||||||
sha2_64.c sha2_128.c sha2block64.c sha2block128.c\
|
sha2_64.c sha2_128.c sha2block64.c sha2block128.c\
|
||||||
sha1pickle.c md5pickle.c\
|
sha1pickle.c md5pickle.c\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue