X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=transform.c;h=a870449bb2ff63f219b6be63ac792bfd8802916c;hp=f94f5ae5571a19073017a3c8d5c16bb380c91beb;hb=8689b3a94c043f04e334a7b181a7250ad5940616;hpb=2fe58dfd10216a37f1ece081f926971882de112e diff --git a/transform.c b/transform.c index f94f5ae..a870449 100644 --- a/transform.c +++ b/transform.c @@ -11,10 +11,22 @@ #include "secnet.h" #include "util.h" #include "serpent.h" +#include "unaligned.h" /* Required key length in bytes */ #define REQUIRED_KEYLEN ((512+64+32)/8) +#ifdef WORDS_BIGENDIAN +static inline uint32_t byteswap(uint32_t a) +{ + return + ((a&0x000000ff)<<24) | + ((a&0x0000ff00)<<8) | + ((a&0x00ff0000)>>8) | + ((a&0xff000000)>>24); +} +#endif + struct transform { closure_t cl; uint32_t line; @@ -58,9 +70,9 @@ static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen) serpent_makekey(&ti->cryptkey,256,key); serpent_makekey(&ti->mackey,256,key+32); - ti->cryptiv=*(uint32_t *)(key+64); - ti->maciv=*(uint32_t *)(key+68); - ti->sendseq=*(uint32_t *)(key+72); + ti->cryptiv=ntohl(*(uint32_t *)(key+64)); + ti->maciv=ntohl(*(uint32_t *)(key+68)); + ti->sendseq=ntohl(*(uint32_t *)(key+72)); ti->lastrecvseq=ti->sendseq; ti->keyed=True; @@ -93,7 +105,7 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, } /* Sequence number */ - *(uint32_t *)buf_prepend(buf,4)=htonl(ti->sendseq); + buf_prepend_uint32(buf,ti->sendseq); ti->sendseq++; /* PKCS5, stolen from IWJ */ @@ -119,13 +131,26 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, block encrypted once again. */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + macplain[0]=macacc[0]^byteswap(n[0]); + macplain[1]=macacc[1]^byteswap(n[1]); + macplain[2]=macacc[2]^byteswap(n[2]); + macplain[3]=macacc[3]^byteswap(n[3]); +#else macplain[0]=macacc[0]^n[0]; macplain[1]=macacc[1]^n[1]; macplain[2]=macacc[2]^n[2]; macplain[3]=macacc[3]^n[3]; +#endif serpent_encrypt(&ti->mackey,macplain,macacc); } serpent_encrypt(&ti->mackey,macacc,macacc); +#ifdef WORDS_BIGENDIAN + macacc[0]=byteswap(macacc[0]); + macacc[1]=byteswap(macacc[1]); + macacc[2]=byteswap(macacc[2]); + macacc[3]=byteswap(macacc[3]); +#endif memcpy(buf_append(buf,16),macacc,16); /* Serpent-CBC. We expand the ID as for CBCMAC, do the encryption, @@ -137,19 +162,40 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, /* CBC: each block is XORed with the previous encrypted block (or the IV) before being encrypted. */ p=iv; +#ifdef WORDS_BIGENDIAN + /* This counters the byteswap() in the first half of the loop, which in + turn counters the byteswap() in the second half of the loop. Ick. */ + iv[0]=byteswap(iv[0]); + iv[1]=byteswap(iv[1]); + iv[2]=byteswap(iv[2]); + iv[3]=byteswap(iv[3]); +#endif for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + /* Think of this as byteswap(p[x])^byteswap(n[x]) */ + n[0]=byteswap(p[0]^n[0]); + n[1]=byteswap(p[1]^n[1]); + n[2]=byteswap(p[2]^n[2]); + n[3]=byteswap(p[3]^n[3]); +#else n[0]=p[0]^n[0]; n[1]=p[1]^n[1]; n[2]=p[2]^n[2]; n[3]=p[3]^n[3]; +#endif serpent_encrypt(&ti->cryptkey,n,n); +#ifdef WORDS_BIGENDIAN + n[0]=byteswap(n[0]); + n[1]=byteswap(n[1]); + n[2]=byteswap(n[2]); + n[3]=byteswap(n[3]); +#endif p=n; } - *(uint32_t *)buf_prepend(buf,4)=ti->cryptiv; + buf_prepend_uint32(buf,ti->cryptiv); ti->cryptiv++; - return 0; } @@ -173,19 +219,36 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, return 1; } + /* CBC */ memset(iv,0,16); - iv[0]=*(uint32_t *)buf_unprepend(buf,4); + iv[0]=buf_unprepend_uint32(buf); + /* Assert bufsize is multiple of blocksize */ + if (buf->size&0xf) { + *errmsg="msg not multiple of cipher blocksize"; + } serpent_encrypt(&ti->cryptkey,iv,iv); - /* XXX assert bufsize is multiple of blocksize */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + n[0]=byteswap(n[0]); + n[1]=byteswap(n[1]); + n[2]=byteswap(n[2]); + n[3]=byteswap(n[3]); +#endif pct[0]=n[0]; pct[1]=n[1]; pct[2]=n[2]; pct[3]=n[3]; serpent_decrypt(&ti->cryptkey,n,n); +#ifdef WORDS_BIGENDIAN + n[0]=byteswap(iv[0]^n[0]); + n[1]=byteswap(iv[1]^n[1]); + n[2]=byteswap(iv[2]^n[2]); + n[3]=byteswap(iv[3]^n[3]); +#else n[0]=iv[0]^n[0]; n[1]=iv[1]^n[1]; n[2]=iv[2]^n[2]; n[3]=iv[3]^n[3]; +#endif iv[0]=pct[0]; iv[1]=pct[1]; iv[2]=pct[2]; iv[3]=pct[3]; } @@ -199,13 +262,26 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, block encrypted once again. */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + macplain[0]=macacc[0]^byteswap(n[0]); + macplain[1]=macacc[1]^byteswap(n[1]); + macplain[2]=macacc[2]^byteswap(n[2]); + macplain[3]=macacc[3]^byteswap(n[3]); +#else macplain[0]=macacc[0]^n[0]; macplain[1]=macacc[1]^n[1]; macplain[2]=macacc[2]^n[2]; macplain[3]=macacc[3]^n[3]; +#endif serpent_encrypt(&ti->mackey,macplain,macacc); } serpent_encrypt(&ti->mackey,macacc,macacc); +#ifdef WORDS_BIGENDIAN + macacc[0]=byteswap(macacc[0]); + macacc[1]=byteswap(macacc[1]); + macacc[2]=byteswap(macacc[2]); + macacc[3]=byteswap(macacc[3]); +#endif if (memcmp(macexpected,macacc,16)!=0) { *errmsg="invalid MAC"; return 1; @@ -230,7 +306,7 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, /* Sequence number must be within max_skew of lastrecvseq; lastrecvseq is only allowed to increase. */ - seqnum=ntohl(*(uint32_t *)buf_unprepend(buf,4)); + seqnum=buf_unprepend_uint32(buf); skew=seqnum-ti->lastrecvseq; if (skew<10) { /* Ok */