chiark / gitweb /
Import release 0.1.12
[secnet.git] / transform.c
index 174beda7dd874cdd91117d3356f3ba12707eeb8d..dba0ef8193334651ec963dbefd25c196c4bc213a 100644 (file)
@@ -8,6 +8,7 @@
    the packets sent over the wire. */
 
 #include <stdio.h>
+#include <string.h>
 #include "secnet.h"
 #include "util.h"
 #include "serpent.h"
@@ -53,7 +54,7 @@ static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen)
     struct transform_inst *ti=sst;
 
     if (keylen<REQUIRED_KEYLEN) {
-       Message(M_ERROR,"transform_create: insufficient key material supplied "
+       Message(M_ERR,"transform_create: insufficient key material supplied "
                "(need %d bytes, got %d)\n",REQUIRED_KEYLEN,keylen);
        return False;
     }
@@ -162,9 +163,18 @@ 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]);
@@ -176,12 +186,17 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf,
        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;
     }
 
     buf_prepend_uint32(buf,ti->cryptiv);
     ti->cryptiv++;
-
     return 0;
 }
 
@@ -205,13 +220,23 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        return 1;
     }
 
+
     /* CBC */
     memset(iv,0,16);
     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
@@ -284,10 +309,10 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        is only allowed to increase. */
     seqnum=buf_unprepend_uint32(buf);
     skew=seqnum-ti->lastrecvseq;
-    if (skew<10) {
+    if (skew<0x8fffffff) {
        /* Ok */
        ti->lastrecvseq=seqnum;
-    } else if ((0-skew)<10) {
+    } else if ((0-skew)<ti->max_skew) {
        /* Ok */
     } else {
        /* Too much skew */