chiark / gitweb /
serpent: Provide little-endian version too, but ours is big
[secnet.git] / transform.c
index dc6ac3ea097ab2e6815d3ccdf10dd9e2ce1e37d6..a0665ad97769c4926eadbfa110adc30ced2008c7 100644 (file)
@@ -19,7 +19,6 @@
 
 struct transform {
     closure_t cl;
-    uint32_t line;
     struct transform_if ops;
     uint32_t max_seq_skew;
 };
@@ -38,7 +37,7 @@ struct transform_inst {
 
 #define PKCS5_MASK 15
 
-static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen)
+static bool_t transform_setkey(void *sst, uint8_t *key, int32_t keylen)
 {
     struct transform_inst *ti=sst;
 
@@ -58,23 +57,30 @@ static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen)
     }
 #endif /* 0 */
 
-    serpent_makekey(&ti->cryptkey,256,key);
-    serpent_makekey(&ti->mackey,256,key+32);
-    ti->cryptiv=GET_32BIT_MSB_FIRST(key+64);
-    ti->maciv=GET_32BIT_MSB_FIRST(key+68);
-    ti->sendseq=GET_32BIT_MSB_FIRST(key+72);
+    serpentbe_makekey(&ti->cryptkey,256,key);
+    serpentbe_makekey(&ti->mackey,256,key+32);
+    ti->cryptiv=get_uint32(key+64);
+    ti->maciv=get_uint32(key+68);
+    ti->sendseq=get_uint32(key+72);
     ti->lastrecvseq=ti->sendseq;
     ti->keyed=True;
 
     return True;
 }
 
+static bool_t transform_valid(void *sst)
+{
+    struct transform_inst *ti=sst;
+
+    return ti->keyed;
+}
+
 static void transform_delkey(void *sst)
 {
     struct transform_inst *ti=sst;
 
-    memset(&ti->cryptkey,0,sizeof(ti->cryptkey));
-    memset(&ti->mackey,0,sizeof(ti->mackey));
+    FILLZERO(ti->cryptkey);
+    FILLZERO(ti->mackey);
     ti->keyed=False;
 }
 
@@ -115,8 +121,8 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf,
        it we've have to add 16 bytes to each message, not 4, so that the
        message stays a multiple of 16 bytes long.) */
     memset(iv,0,16);
-    PUT_32BIT_MSB_FIRST(iv, ti->maciv);
-    serpent_encrypt(&ti->mackey,iv,macacc);
+    put_uint32(iv, ti->maciv);
+    serpentbe_encrypt(&ti->mackey,iv,macacc);
 
     /* CBCMAC: encrypt in CBC mode. The MAC is the last encrypted
        block encrypted once again. */
@@ -124,16 +130,16 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf,
     {
        for (i = 0; i < 16; i++)
            macplain[i] = macacc[i] ^ n[i];
-       serpent_encrypt(&ti->mackey,macplain,macacc);
+       serpentbe_encrypt(&ti->mackey,macplain,macacc);
     }
-    serpent_encrypt(&ti->mackey,macacc,macacc);
+    serpentbe_encrypt(&ti->mackey,macacc,macacc);
     memcpy(buf_append(buf,16),macacc,16);
 
     /* Serpent-CBC. We expand the ID as for CBCMAC, do the encryption,
        and prepend the IV before increasing it. */
     memset(iv,0,16);
-    PUT_32BIT_MSB_FIRST(iv, ti->cryptiv);
-    serpent_encrypt(&ti->cryptkey,iv,iv);
+    put_uint32(iv, ti->cryptiv);
+    serpentbe_encrypt(&ti->cryptkey,iv,iv);
 
     /* CBC: each block is XORed with the previous encrypted block (or the IV)
        before being encrypted. */
@@ -143,7 +149,7 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf,
     {
        for (i = 0; i < 16; i++)
            n[i] ^= p[i];
-       serpent_encrypt(&ti->cryptkey,n,n);
+       serpentbe_encrypt(&ti->cryptkey,n,n);
        p=n;
     }
 
@@ -157,7 +163,7 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
 {
     struct transform_inst *ti=sst;
     uint8_t *padp;
-    unsigned padlen;
+    int padlen;
     int i;
     uint32_t seqnum, skew;
     uint8_t iv[16];
@@ -172,23 +178,28 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        return 1;
     }
 
+    if (buf->size < 4 + 16 + 16) {
+       *errmsg="msg too short";
+       return 1;
+    }
 
     /* CBC */
     memset(iv,0,16);
     {
        uint32_t ivword = buf_unprepend_uint32(buf);
-       PUT_32BIT_MSB_FIRST(iv, ivword);
+       put_uint32(iv, ivword);
     }
     /* Assert bufsize is multiple of blocksize */
     if (buf->size&0xf) {
        *errmsg="msg not multiple of cipher blocksize";
+       return 1;
     }
-    serpent_encrypt(&ti->cryptkey,iv,iv);
+    serpentbe_encrypt(&ti->cryptkey,iv,iv);
     for (n=buf->start; n<buf->start+buf->size; n+=16)
     {
        for (i = 0; i < 16; i++)
            pct[i] = n[i];
-       serpent_decrypt(&ti->cryptkey,n,n);
+       serpentbe_decrypt(&ti->cryptkey,n,n);
        for (i = 0; i < 16; i++)
            n[i] ^= iv[i];
        memcpy(iv, pct, 16);
@@ -197,8 +208,8 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
     /* CBCMAC */
     macexpected=buf_unappend(buf,16);
     memset(iv,0,16);
-    PUT_32BIT_MSB_FIRST(iv, ti->maciv);
-    serpent_encrypt(&ti->mackey,iv,macacc);
+    put_uint32(iv, ti->maciv);
+    serpentbe_encrypt(&ti->mackey,iv,macacc);
 
     /* CBCMAC: encrypt in CBC mode. The MAC is the last encrypted
        block encrypted once again. */
@@ -206,10 +217,10 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
     {
        for (i = 0; i < 16; i++)
            macplain[i] = macacc[i] ^ n[i];
-       serpent_encrypt(&ti->mackey,macplain,macacc);
+       serpentbe_encrypt(&ti->mackey,macplain,macacc);
     }
-    serpent_encrypt(&ti->mackey,macacc,macacc);
-    if (memcmp(macexpected,macacc,16)!=0) {
+    serpentbe_encrypt(&ti->mackey,macacc,macacc);
+    if (!consttime_memeq(macexpected,macacc,16)!=0) {
        *errmsg="invalid MAC";
        return 1;
     }
@@ -223,13 +234,7 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        return 1;
     }
 
-    padp=buf_unappend(buf,padlen-1);
-    for (i=0; i<padlen-1; i++) {
-       if (*++padp != padlen) {
-           *errmsg="pkcs5: corrupted padding";
-           return 1;
-       }
-    }
+    buf_unappend(buf,padlen-1);
 
     /* Sequence number must be within max_skew of lastrecvseq; lastrecvseq
        is only allowed to increase. */
@@ -243,7 +248,7 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
     } else {
        /* Too much skew */
        *errmsg="seqnum: too much skew";
-       return 1;
+       return 2;
     }
     
     return 0;
@@ -253,7 +258,7 @@ static void transform_destroy(void *sst)
 {
     struct transform_inst *st=sst;
 
-    memset(st,0,sizeof(*st)); /* Destroy key material */
+    FILLZERO(*st); /* Destroy key material */
     free(st);
 }
 
@@ -267,6 +272,7 @@ static struct transform_inst_if *transform_create(void *sst)
 
     ti->ops.st=ti;
     ti->ops.setkey=transform_setkey;
+    ti->ops.valid=transform_valid;
     ti->ops.delkey=transform_delkey;
     ti->ops.forwards=transform_forward;
     ti->ops.reverse=transform_reverse;
@@ -311,7 +317,6 @@ static list_t *transform_apply(closure_t *self, struct cloc loc,
     return new_closure(&st->cl);
 }
 
-init_module transform_module;
 void transform_module(dict_t *dict)
 {
     struct keyInstance k;
@@ -322,8 +327,9 @@ void transform_module(dict_t *dict)
     /*
      * Serpent self-test.
      * 
-     * This test pattern is taken directly from the Serpent test
-     * vectors, to ensure we have all endianness issues correct. -sgt
+     * This test pattern was taken directly from the Serpent test
+     * vectors, which results in a big-endian Serpent which is not
+     * compatible with other implementations.
      */
 
     /* Serpent self-test */
@@ -331,18 +337,18 @@ void transform_module(dict_t *dict)
            "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
            "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00",
            32);
-    serpent_makekey(&k,256,data);
+    serpentbe_makekey(&k,256,data);
 
     memcpy(plaintext,
            "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10",
            16);
-    serpent_encrypt(&k,plaintext,ciphertext);
+    serpentbe_encrypt(&k,plaintext,ciphertext);
 
     if (memcmp(ciphertext, "\xca\x7f\xa1\x93\xe3\xeb\x9e\x99"
                "\xbd\x87\xe3\xaf\x3c\x9a\xdf\x93", 16)) {
        fatal("transform_module: serpent failed self-test (encrypt)");
     }
-    serpent_decrypt(&k,ciphertext,plaintext);
+    serpentbe_decrypt(&k,ciphertext,plaintext);
     if (memcmp(plaintext, "\x01\x23\x45\x67\x89\xab\xcd\xef"
                "\xfe\xdc\xba\x98\x76\x54\x32\x10", 16)) {
        fatal("transform_module: serpent failed self-test (decrypt)");