chiark / gitweb /
Import release 0.08
[secnet.git] / transform.c
index f94f5ae5571a19073017a3c8d5c16bb380c91beb..a870449bb2ff63f219b6be63ac792bfd8802916c 100644 (file)
 #include "secnet.h"
 #include "util.h"
 #include "serpent.h"
 #include "secnet.h"
 #include "util.h"
 #include "serpent.h"
+#include "unaligned.h"
 
 /* Required key length in bytes */
 #define REQUIRED_KEYLEN ((512+64+32)/8)
 
 
 /* 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;
 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);
 
     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;
 
     ti->lastrecvseq=ti->sendseq;
     ti->keyed=True;
 
@@ -93,7 +105,7 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf,
     }
 
     /* Sequence number */
     }
 
     /* Sequence number */
-    *(uint32_t *)buf_prepend(buf,4)=htonl(ti->sendseq);
+    buf_prepend_uint32(buf,ti->sendseq);
     ti->sendseq++;
 
     /* PKCS5, stolen from IWJ */
     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)
     {
        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];
        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);
        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,
     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;
     /* 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)
     {
     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];
        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);
        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;
     }
 
        p=n;
     }
 
-    *(uint32_t *)buf_prepend(buf,4)=ti->cryptiv;
+    buf_prepend_uint32(buf,ti->cryptiv);
     ti->cryptiv++;
     ti->cryptiv++;
-
     return 0;
 }
 
     return 0;
 }
 
@@ -173,19 +219,36 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        return 1;
     }
 
        return 1;
     }
 
+
     /* CBC */
     memset(iv,0,16);
     /* 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);
     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)
     {
     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);
        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];
        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];
     }
 
        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)
     {
        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];
        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);
        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;
     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. */
 
     /* 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 */
     skew=seqnum-ti->lastrecvseq;
     if (skew<10) {
        /* Ok */