[Sumover-dev] [svn commit] r4046 - in vic/branches/mpeg4: net

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Wed May 30 23:54:02 BST 2007


Author: piers
Date: Wed May 30 23:54:00 2007
New Revision: 4046

Added:
   vic/branches/mpeg4/net/crypt-rijndael.cpp   (contents, props changed)
   vic/branches/mpeg4/net/rijndael-alg-fst.c   (contents, props changed)
   vic/branches/mpeg4/net/rijndael-alg-fst.h   (contents, props changed)
   vic/branches/mpeg4/net/rijndael-api-fst.c   (contents, props changed)
   vic/branches/mpeg4/net/rijndael-api-fst.h   (contents, props changed)
   vic/branches/mpeg4/net/rijndael-test-fst.c   (contents, props changed)
Modified:
   vic/branches/mpeg4/Makefile.in

Log:
Added AES/Rijndael crypto code from AG repository


Modified: vic/branches/mpeg4/Makefile.in
==============================================================================
--- vic/branches/mpeg4/Makefile.in	(original)
+++ vic/branches/mpeg4/Makefile.in	Wed May 30 23:54:00 2007
@@ -87,7 +87,7 @@
 OBJ_GRABBER = @V_OBJ_GRABBER@
 SRC_GRABBER = $(OBJ_GRABBER:.o=.cpp) 
 OBJ_XIL = @V_OBJ_XIL@
-OBJ_CRYPT = @V_OBJ_CRYPT@
+OBJ_CRYPT = net/crypt-rijndael.o net/rijndael-alg-fst.o net/rijndael-api-fst.o @V_OBJ_CRYPT@
 CODEC_LIB = @V_CODEC_LIB@ codec/tmndec/libh263.a codec/tmn-x/libh263coder.a
 
 LIB = $(LIB_GRABBER) @V_LIB_TK@ @V_LIB_TCL@ @V_LIB_X11@ @V_LIB@ $(CODEC_LIB) $(VIDEO_LIB) \

Added: vic/branches/mpeg4/net/crypt-rijndael.cpp
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/crypt-rijndael.cpp	Wed May 30 23:54:00 2007
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the Network Research
+ * 	Group at Lawrence Berkeley National Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+static const char rcsid[] =
+"@(#) $Header: /cvs/fl/ag-media/vic/net/crypt-rijndael.cpp,v 1.2 2006/04/03 19:33:37 turam Exp $ (LBL)";
+ 
+extern "C" {
+#include "rijndael-api-fst.h"
+}
+
+#include "crypt.h"
+#include "inet.h"
+#include "rtp.h"
+
+class CryptRijndael : public Crypt {
+public:
+    CryptRijndael();
+    ~CryptRijndael();
+    virtual int install_key(const u_int8_t* key);
+    virtual u_char* Encrypt(const u_char* in, int& len);
+    virtual int Decrypt(const u_char* in, int len, u_char* out);
+
+protected:
+    int decrypt(const u_char* in, int len, u_char* out, int rtcp);
+
+    keyInstance keyInstEncrypt_;
+    keyInstance keyInstDecrypt_;
+    cipherInstance cipherInst_;
+    static int didinit_;
+    u_char* wrkbuf_;
+};
+
+class CryptRijndaelCtrl : public CryptRijndael {
+public:
+    virtual u_char* Encrypt(const u_char* in, int& len);
+    virtual int Decrypt(const u_char* in, int len, u_char* out);
+};
+
+static class CryptRijndaelMatcher : public Matcher {
+public:
+    CryptRijndaelMatcher() : Matcher("crypt") {}
+    TclObject* match(const char* id) {
+	if (strcmp(id, "Rijndael/data") == 0 ||
+	    strcmp(id, "Rijndael1/data") == 0 ||
+        strcmp(id, "AES/data") == 0)
+	    return (new CryptRijndael);
+	if (strcmp(id, "Rijndael/ctrl") == 0 ||
+	    strcmp(id, "Rijndael1/ctrl") == 0 ||
+        strcmp(id, "AES/ctrl") == 0)
+	    return (new CryptRijndaelCtrl);
+	return (0);
+    }
+} rijndael_matcher;
+
+CryptRijndael::CryptRijndael() 
+{
+    /* enough extra space for padding and RTCP 4-byte random header */
+    wrkbuf_ = new u_char[2*RTP_MTU + 4 ];
+}
+
+CryptRijndael::~CryptRijndael()
+{
+    delete wrkbuf_;
+}
+
+int CryptRijndael::install_key(const u_int8_t* key)
+{
+    debug_msg("Install rijndael key '%s'\n", key);
+
+    int rc;
+//    int keylen = strlen((const char *) key);
+
+    //
+    // The vic framework gives us an md5 hash which is 16 bytes long.
+    //
+    int keylen = 16;
+    rc = makeKey(&keyInstEncrypt_, DIR_ENCRYPT, keylen * 8, (char *) key);
+    if (rc < 0)
+	debug_msg("makeKey failed: %d\n", rc);
+
+    rc = makeKey(&keyInstDecrypt_, DIR_DECRYPT, keylen * 8, (char *) key);
+    if (rc < 0)
+	debug_msg("makeKey failed: %d\n", rc);
+
+    rc = cipherInit(&cipherInst_, MODE_ECB, NULL);
+    if (rc < 0)
+	debug_msg("ciperInit failed: %d\n", rc);
+
+    return (0);
+}
+
+u_char* CryptRijndael::Encrypt(const u_char* in, int& len)
+{
+    // Pad with zeros to the nearest 8 octet boundary       
+    int pad = len & 15;
+    if (pad != 0) {
+	/* pad to an block (16 octet) boundary */
+	pad = 16 - pad;
+	u_char* rh = (u_char*)in;
+	*rh |= 0x20; // set P bit
+	u_char *padding = ((u_char*)in + len);
+	for (int i=1; i<pad; i++)
+	    *padding++ = 0;
+	*padding++ = (char)pad;
+	len += pad;
+    }
+
+    int rc = blockEncrypt(&cipherInst_, &keyInstEncrypt_, (unsigned char *) in, len * 8, wrkbuf_);
+    if (rc < 0)
+	debug_msg("blockEncrypt failed: %d\n", rc);
+    
+    return(wrkbuf_);        
+}
+
+int CryptRijndael::decrypt(const u_char* in, int len, u_char* out, int rtcp)
+{
+    /* check that packet is an integral number of blocks */
+    if ((len & 15) != 0) {
+	++badpktlen_;
+	return (-1);
+    }
+
+    blockDecrypt(&cipherInst_, &keyInstDecrypt_, (unsigned char *) in, len * 8, out);
+
+    // Strip the header of the first 4 bytes if it is an RTCP packet
+    if (rtcp)
+    {
+	memmove(out, (u_char *)(out+4), (unsigned long)(len-4));
+	len -= 4;
+    }
+
+    if ((out[0] & 0x20) != 0) {
+	/* P bit set - trim off padding */
+	int pad = out[len - 1];
+	if (pad > 15 || pad == 0) {
+	    ++badpbit_;
+	    return (-1);
+	}
+	len -= pad;
+    }
+    return (len);
+}
+
+int CryptRijndael::Decrypt(const u_char* in, int len, u_char* out)
+{
+    return decrypt(in, len, out, 0);
+}
+
+u_char* CryptRijndaelCtrl::Encrypt(const u_char* in, int& len)
+{
+    // Attach 4 random bytes to the top of the header to reduce chances of a
+    // plaintext attack on the otherwise fixed header.
+    u_int32_t* new_random = (u_int32_t*)wrkbuf_;
+    new_random[0] = random();
+ 
+    // Copy into the working buffer
+    memcpy((u_char *)(wrkbuf_+4),(u_char *)(in),(unsigned long)(len));
+    len +=4;
+ 
+    // Pad with zeros to the nearest 8 octet boundary	
+    int pad = len & 15;
+    if (pad != 0) {
+	/* pad to an block (8 octet) boundary */
+	pad = 16 - pad;
+	u_char* rh = (wrkbuf_+4);
+	*rh |= 0x20; // set P bit
+	u_char *padding = (wrkbuf_ + len);
+	for (int i=1; i<pad; i++)
+	    *padding++ = 0;
+	*padding++ = (char)pad;
+	len += pad;
+    }
+ 
+    int rc = blockEncrypt(&cipherInst_, &keyInstEncrypt_, wrkbuf_, len * 8, wrkbuf_);
+    if (rc < 0)
+	debug_msg("blockEncrypt failed: %d\n", rc);
+
+    return (wrkbuf_);
+}
+
+int CryptRijndaelCtrl::Decrypt(const u_char* in, int len, u_char* out)
+{
+    return (decrypt(in, len, out, 1));
+}

Added: vic/branches/mpeg4/net/rijndael-alg-fst.c
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/rijndael-alg-fst.c	Wed May 30 23:54:00 2007
@@ -0,0 +1,441 @@
+/*
+ * rijndael-alg-fst.c   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *          v2.4: Vincent Rijmen
+ *
+ * This code is placed in the public domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rijndael-alg-fst.h"
+
+#include "boxes-fst.dat"
+
+int rijndaelKeySched(word8 k[MAXKC][4], word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	/* Calculate the necessary round keys
+	 * The number of calculations depends on keyBits and blockBits
+	 */ 
+	int j, r, t, rconpointer = 0;
+	word8 tk[MAXKC][4];
+	int KC = ROUNDS - 6;
+
+	for (j = KC-1; j >= 0; j--) {
+		*((word32*)tk[j]) = *((word32*)k[j]);
+	}
+	r = 0;
+	t = 0;
+	/* copy values into round key array */
+	for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+		for (; (j < KC) && (t < 4); j++, t++) {
+			*((word32*)W[r][t]) = *((word32*)tk[j]);
+		}
+		if (t == 4) {
+			r++;
+			t = 0;
+		}
+	}
+		
+	while (r < ROUNDS + 1) { /* while not enough round key material calculated */
+		/* calculate new values */
+		tk[0][0] ^= S[tk[KC-1][1]];
+		tk[0][1] ^= S[tk[KC-1][2]];
+		tk[0][2] ^= S[tk[KC-1][3]];
+		tk[0][3] ^= S[tk[KC-1][0]];
+		tk[0][0] ^= rcon[rconpointer++];
+
+		if (KC != 8) {
+			for (j = 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		} else {
+			for (j = 1; j < KC/2; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+			tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
+			tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
+			tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
+			tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
+			for (j = KC/2 + 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		}
+		/* copy values into round key array */
+		for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+			for (; (j < KC) && (t < 4); j++, t++) {
+				*((word32*)W[r][t]) = *((word32*)tk[j]);
+			}
+			if (t == 4) {
+				r++;
+				t = 0;
+			}
+		}
+	}		
+	return 0;
+}
+
+int rijndaelKeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	word8 *w;
+
+	for (r = 1; r < ROUNDS; r++) {
+		w = W[r][0];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][1];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][2];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][3];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+	}
+	return 0;
+}	
+
+/**
+ * Encrypt a single block. 
+ */
+int rijndaelEncrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	word8 temp[4][4];
+
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[0][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[0][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[0][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
+    *((word32*)(b    )) = *((word32*)T1[temp[0][0]])
+						^ *((word32*)T2[temp[1][1]])
+						^ *((word32*)T3[temp[2][2]]) 
+						^ *((word32*)T4[temp[3][3]]);
+    *((word32*)(b + 4)) = *((word32*)T1[temp[1][0]])
+						^ *((word32*)T2[temp[2][1]])
+						^ *((word32*)T3[temp[3][2]]) 
+						^ *((word32*)T4[temp[0][3]]);
+    *((word32*)(b + 8)) = *((word32*)T1[temp[2][0]])
+						^ *((word32*)T2[temp[3][1]])
+						^ *((word32*)T3[temp[0][2]]) 
+						^ *((word32*)T4[temp[1][3]]);
+    *((word32*)(b +12)) = *((word32*)T1[temp[3][0]])
+						^ *((word32*)T2[temp[0][1]])
+						^ *((word32*)T3[temp[1][2]]) 
+						^ *((word32*)T4[temp[2][3]]);
+	for (r = 1; r < ROUNDS-1; r++) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+
+		*((word32*)(b    )) = *((word32*)T1[temp[0][0]])
+							^ *((word32*)T2[temp[1][1]])
+							^ *((word32*)T3[temp[2][2]]) 
+							^ *((word32*)T4[temp[3][3]]);
+		*((word32*)(b + 4)) = *((word32*)T1[temp[1][0]])
+							^ *((word32*)T2[temp[2][1]])
+							^ *((word32*)T3[temp[3][2]]) 
+							^ *((word32*)T4[temp[0][3]]);
+		*((word32*)(b + 8)) = *((word32*)T1[temp[2][0]])
+							^ *((word32*)T2[temp[3][1]])
+							^ *((word32*)T3[temp[0][2]]) 
+							^ *((word32*)T4[temp[1][3]]);
+		*((word32*)(b +12)) = *((word32*)T1[temp[3][0]])
+							^ *((word32*)T2[temp[0][1]])
+							^ *((word32*)T3[temp[1][2]]) 
+							^ *((word32*)T4[temp[2][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[ROUNDS-1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[ROUNDS-1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[ROUNDS-1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[ROUNDS-1][3]);
+	b[ 0] = T1[temp[0][0]][1];
+	b[ 1] = T1[temp[1][1]][1];
+	b[ 2] = T1[temp[2][2]][1];
+	b[ 3] = T1[temp[3][3]][1];
+	b[ 4] = T1[temp[1][0]][1];
+	b[ 5] = T1[temp[2][1]][1];
+	b[ 6] = T1[temp[3][2]][1];
+	b[ 7] = T1[temp[0][3]][1];
+	b[ 8] = T1[temp[2][0]][1];
+	b[ 9] = T1[temp[3][1]][1];
+	b[10] = T1[temp[0][2]][1];
+	b[11] = T1[temp[1][3]][1];
+	b[12] = T1[temp[3][0]][1];
+	b[13] = T1[temp[0][1]][1];
+	b[14] = T1[temp[1][2]][1];
+	b[15] = T1[temp[2][3]][1];
+	*((word32*)(b   )) ^= *((word32*)rk[ROUNDS][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[ROUNDS][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[ROUNDS][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[ROUNDS][3]);
+
+	return 0;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Encrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ */
+int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r;
+	word8 temp[4][4];
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+
+	*((word32*)a[0]) = *((word32*)a[0]) ^ *((word32*)rk[0][0]);
+	*((word32*)a[1]) = *((word32*)a[1]) ^ *((word32*)rk[0][1]);
+	*((word32*)a[2]) = *((word32*)a[2]) ^ *((word32*)rk[0][2]);
+	*((word32*)a[3]) = *((word32*)a[3]) ^ *((word32*)rk[0][3]);
+
+	for (r = 1; (r <= rounds) && (r < ROUNDS); r++) {
+		*((word32*)temp[0]) = *((word32*)T1[a[0][0]])
+           ^ *((word32*)T2[a[1][1]])
+           ^ *((word32*)T3[a[2][2]]) 
+           ^ *((word32*)T4[a[3][3]]);
+		*((word32*)temp[1]) = *((word32*)T1[a[1][0]])
+           ^ *((word32*)T2[a[2][1]])
+           ^ *((word32*)T3[a[3][2]]) 
+           ^ *((word32*)T4[a[0][3]]);
+		*((word32*)temp[2]) = *((word32*)T1[a[2][0]])
+           ^ *((word32*)T2[a[3][1]])
+           ^ *((word32*)T3[a[0][2]]) 
+           ^ *((word32*)T4[a[1][3]]);
+		*((word32*)temp[3]) = *((word32*)T1[a[3][0]])
+           ^ *((word32*)T2[a[0][1]])
+           ^ *((word32*)T3[a[1][2]]) 
+           ^ *((word32*)T4[a[2][3]]);
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[r][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[r][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[r][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[r][3]);
+	}
+	if (rounds == ROUNDS) {
+	   	/* last round is special */   
+	   	temp[0][0] = T1[a[0][0]][1];
+	   	temp[0][1] = T1[a[1][1]][1];
+	   	temp[0][2] = T1[a[2][2]][1]; 
+	   	temp[0][3] = T1[a[3][3]][1];
+	   	temp[1][0] = T1[a[1][0]][1];
+	   	temp[1][1] = T1[a[2][1]][1];
+	   	temp[1][2] = T1[a[3][2]][1]; 
+	   	temp[1][3] = T1[a[0][3]][1];
+	   	temp[2][0] = T1[a[2][0]][1];
+	   	temp[2][1] = T1[a[3][1]][1];
+	   	temp[2][2] = T1[a[0][2]][1]; 
+	   	temp[2][3] = T1[a[1][3]][1];
+	   	temp[3][0] = T1[a[3][0]][1];
+	   	temp[3][1] = T1[a[0][1]][1];
+	   	temp[3][2] = T1[a[1][2]][1]; 
+	   	temp[3][3] = T1[a[2][3]][1];
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[ROUNDS][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[ROUNDS][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[ROUNDS][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[ROUNDS][3]);
+	}
+
+	return 0;
+}   
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+/**
+ * Decrypt a single block.
+ */
+int rijndaelDecrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	word8 temp[4][4];
+	
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[ROUNDS][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[ROUNDS][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[ROUNDS][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[ROUNDS][3]);
+
+    *((word32*)(b   )) = *((word32*)T5[temp[0][0]])
+           ^ *((word32*)T6[temp[3][1]])
+           ^ *((word32*)T7[temp[2][2]]) 
+           ^ *((word32*)T8[temp[1][3]]);
+	*((word32*)(b+ 4)) = *((word32*)T5[temp[1][0]])
+           ^ *((word32*)T6[temp[0][1]])
+           ^ *((word32*)T7[temp[3][2]]) 
+           ^ *((word32*)T8[temp[2][3]]);
+	*((word32*)(b+ 8)) = *((word32*)T5[temp[2][0]])
+           ^ *((word32*)T6[temp[1][1]])
+           ^ *((word32*)T7[temp[0][2]]) 
+           ^ *((word32*)T8[temp[3][3]]);
+	*((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
+           ^ *((word32*)T6[temp[2][1]])
+           ^ *((word32*)T7[temp[1][2]]) 
+           ^ *((word32*)T8[temp[0][3]]);
+	for (r = ROUNDS-1; r > 1; r--) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+		*((word32*)(b   )) = *((word32*)T5[temp[0][0]])
+           ^ *((word32*)T6[temp[3][1]])
+           ^ *((word32*)T7[temp[2][2]]) 
+           ^ *((word32*)T8[temp[1][3]]);
+		*((word32*)(b+ 4)) = *((word32*)T5[temp[1][0]])
+           ^ *((word32*)T6[temp[0][1]])
+           ^ *((word32*)T7[temp[3][2]]) 
+           ^ *((word32*)T8[temp[2][3]]);
+		*((word32*)(b+ 8)) = *((word32*)T5[temp[2][0]])
+           ^ *((word32*)T6[temp[1][1]])
+           ^ *((word32*)T7[temp[0][2]]) 
+           ^ *((word32*)T8[temp[3][3]]);
+		*((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
+           ^ *((word32*)T6[temp[2][1]])
+           ^ *((word32*)T7[temp[1][2]]) 
+           ^ *((word32*)T8[temp[0][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[1][3]);
+	b[ 0] = S5[temp[0][0]];
+	b[ 1] = S5[temp[3][1]];
+	b[ 2] = S5[temp[2][2]];
+	b[ 3] = S5[temp[1][3]];
+	b[ 4] = S5[temp[1][0]];
+	b[ 5] = S5[temp[0][1]];
+	b[ 6] = S5[temp[3][2]];
+	b[ 7] = S5[temp[2][3]];
+	b[ 8] = S5[temp[2][0]];
+	b[ 9] = S5[temp[1][1]];
+	b[10] = S5[temp[0][2]];
+	b[11] = S5[temp[3][3]];
+	b[12] = S5[temp[3][0]];
+	b[13] = S5[temp[2][1]];
+	b[14] = S5[temp[1][2]];
+	b[15] = S5[temp[0][3]];
+	*((word32*)(b   )) ^= *((word32*)rk[0][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[0][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[0][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[0][3]);
+
+	return 0;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Decrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ * Operations rearranged such that the intermediate values
+ * of decryption correspond with the intermediate values
+ * of encryption.
+ */
+int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r, i;
+	word8 temp[4], shift;
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+    /* first round is special: */
+	*(word32 *)a[0] ^= *(word32 *)rk[ROUNDS][0];
+	*(word32 *)a[1] ^= *(word32 *)rk[ROUNDS][1];
+	*(word32 *)a[2] ^= *(word32 *)rk[ROUNDS][2];
+	*(word32 *)a[3] ^= *(word32 *)rk[ROUNDS][3];
+	for (i = 0; i < 4; i++) {
+		a[i][0] = Si[a[i][0]];
+		a[i][1] = Si[a[i][1]];
+		a[i][2] = Si[a[i][2]];
+		a[i][3] = Si[a[i][3]];
+	}
+	for (i = 1; i < 4; i++) {
+		shift = (4 - i) & 3;
+		temp[0] = a[(0 + shift) & 3][i];
+		temp[1] = a[(1 + shift) & 3][i];
+		temp[2] = a[(2 + shift) & 3][i];
+		temp[3] = a[(3 + shift) & 3][i];
+		a[0][i] = temp[0];
+		a[1][i] = temp[1];
+		a[2][i] = temp[2];
+		a[3][i] = temp[3];
+	}
+	/* ROUNDS-1 ordinary rounds */
+	for (r = ROUNDS-1; r > rounds; r--) {
+		*(word32 *)a[0] ^= *(word32 *)rk[r][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[r][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[r][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[r][3];
+
+		*((word32*)a[0]) =
+			  *((word32*)U1[a[0][0]])
+			^ *((word32*)U2[a[0][1]])
+			^ *((word32*)U3[a[0][2]])
+			^ *((word32*)U4[a[0][3]]);
+
+		*((word32*)a[1]) =
+			  *((word32*)U1[a[1][0]])
+			^ *((word32*)U2[a[1][1]])
+			^ *((word32*)U3[a[1][2]])
+			^ *((word32*)U4[a[1][3]]);
+
+		*((word32*)a[2]) =
+			  *((word32*)U1[a[2][0]])
+			^ *((word32*)U2[a[2][1]])
+			^ *((word32*)U3[a[2][2]])
+			^ *((word32*)U4[a[2][3]]);
+
+		*((word32*)a[3]) =
+			  *((word32*)U1[a[3][0]])
+			^ *((word32*)U2[a[3][1]])
+			^ *((word32*)U3[a[3][2]])
+			^ *((word32*)U4[a[3][3]]);
+		for (i = 0; i < 4; i++) {
+			a[i][0] = Si[a[i][0]];
+			a[i][1] = Si[a[i][1]];
+			a[i][2] = Si[a[i][2]];
+			a[i][3] = Si[a[i][3]];
+		}
+		for (i = 1; i < 4; i++) {
+			shift = (4 - i) & 3;
+			temp[0] = a[(0 + shift) & 3][i];
+			temp[1] = a[(1 + shift) & 3][i];
+			temp[2] = a[(2 + shift) & 3][i];
+			temp[3] = a[(3 + shift) & 3][i];
+			a[0][i] = temp[0];
+			a[1][i] = temp[1];
+			a[2][i] = temp[2];
+			a[3][i] = temp[3];
+		}
+	}
+	if (rounds == 0) {
+		/* End with the extra key addition */	
+		*(word32 *)a[0] ^= *(word32 *)rk[0][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[0][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[0][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[0][3];
+	}    
+	return 0;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */

Added: vic/branches/mpeg4/net/rijndael-alg-fst.h
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/rijndael-alg-fst.h	Wed May 30 23:54:00 2007
@@ -0,0 +1,40 @@
+/*
+ * rijndael-alg-fst.h   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * #define INTERMEDIATE_VALUE_KAT to generate the Intermediate Value Known Answer Test.
+ */
+
+#ifndef __RIJNDAEL_ALG_FST_H
+#define __RIJNDAEL_ALG_FST_H
+
+#define BINARY_KEY_MATERIAL
+#define MAXKC			(256/32)
+#define MAXROUNDS		14
+
+#ifndef USUAL_TYPES
+#define USUAL_TYPES
+typedef unsigned char	byte;
+typedef unsigned char	word8;	
+typedef unsigned short	word16;	
+typedef unsigned int	word32;
+#endif /* USUAL_TYPES */
+
+int rijndaelKeySched(word8 k[MAXKC][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndaelKeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndaelEncrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+int rijndaelDecrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /* __RIJNDAEL_ALG_FST_H */

Added: vic/branches/mpeg4/net/rijndael-api-fst.c
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/rijndael-api-fst.c	Wed May 30 23:54:00 2007
@@ -0,0 +1,498 @@
+/*
+ * rijndael-api-fst.c   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.1: Vincent Rijmen
+ *          v2.2: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *          v2.4: Vincent Rijmen
+ *
+ * This code is placed in the public domain.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rijndael-alg-fst.h"
+#include "rijndael-api-fst.h"
+
+int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
+	word8 k[MAXKC][4];
+	int i;
+	char *keyMat;
+	
+	if (key == NULL) {
+		return BAD_KEY_INSTANCE;
+	}
+
+	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
+		key->direction = direction;
+	} else {
+		return BAD_KEY_DIR;
+	}
+
+	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 
+		key->keyLen = keyLen;
+	} else {
+		return BAD_KEY_MAT;
+	}
+
+	if (keyMaterial != NULL) {
+		strncpy(key->keyMaterial, keyMaterial, keyLen/4);
+	}
+
+	key->ROUNDS = keyLen/32 + 6;
+
+	/* initialize key schedule: */
+	keyMat = key->keyMaterial;
+#ifndef BINARY_KEY_MATERIAL
+ 	for (i = 0; i < key->keyLen/8; i++) {
+		int t, j;
+
+		t = *keyMat++;
+		if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
+		else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 
+		else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 
+		else return BAD_KEY_MAT;
+		
+		t = *keyMat++;
+		if ((t >= '0') && (t <= '9')) j ^= (t - '0');
+		else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 
+		else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 
+		else return BAD_KEY_MAT;
+		
+		k[i >> 2][i & 3] = (word8)j; 
+	}
+#else
+	for (i = 0; i < key->keyLen/8; i++) {
+		k[i >> 2][i & 3] = (word8)keyMat[i]; 
+	}
+#endif /* ?BINARY_KEY_MATERIAL */
+	rijndaelKeySched(k, key->keySched, key->ROUNDS);
+	if (direction == DIR_DECRYPT) {
+		rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
+	}
+
+	return TRUE;
+}
+
+int cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
+	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
+		cipher->mode = mode;
+	} else {
+		return BAD_CIPHER_MODE;
+	}
+	if (IV != NULL) {
+#ifndef BINARY_KEY_MATERIAL
+		int i;
+ 		for (i = 0; i < MAX_IV_SIZE; i++) {
+			int t, j;
+
+			t = IV[2*i];
+			if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
+			else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 
+			else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 
+			else return BAD_CIPHER_INSTANCE;
+		
+			t = IV[2*i+1];
+			if ((t >= '0') && (t <= '9')) j ^= (t - '0');
+			else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 
+			else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 
+			else return BAD_CIPHER_INSTANCE;
+			
+			cipher->IV[i] = (word8)j;
+		}
+#else
+		memcpy(cipher->IV, IV, MAX_IV_SIZE);
+#endif /* ?BINARY_KEY_MATERIAL */
+	} else {
+		memset(cipher->IV, 0, MAX_IV_SIZE);
+	}
+	return TRUE;
+}
+
+int blockEncrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer) {
+	int i, k, numBlocks;
+	word8 block[16], iv[4][4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+	
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+		((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
+		((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
+		((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
+		((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		input += 16;
+		for (i = numBlocks - 1; i > 0; i--) {
+			((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
+			((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
+			((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
+			((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
+			outBuffer += 16;
+			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+		}
+		break;
+	
+	case MODE_CFB1:
+#if STRICT_ALIGN 
+		memcpy(iv, cipher->IV, 16); 
+#else  /* !STRICT_ALIGN */
+		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif /* ?STRICT_ALIGN */
+		for (i = numBlocks; i > 0; i--) {
+			for (k = 0; k < 128; k++) {
+				*((word32*) block    ) = *((word32*)iv[0]);
+				*((word32*)(block+ 4)) = *((word32*)iv[1]);
+				*((word32*)(block+ 8)) = *((word32*)iv[2]);
+				*((word32*)(block+12)) = *((word32*)iv[3]);
+				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
+				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
+			}
+		}
+		break;
+	
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+/**
+ * Encrypt data partitioned in octets, using RFC 2040-like padding.
+ *
+ * @param   input           data to be encrypted (octet sequence)
+ * @param   inputOctets		input length in octets (not bits)
+ * @param   outBuffer       encrypted output data
+ *
+ * @return	length in octets (not bits) of the encrypted output buffer.
+ */
+int padEncrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer) {
+	int i, numBlocks, padLen;
+	word8 block[16], *iv;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		assert(padLen > 0 && padLen <= 16);
+		memcpy(block, input, 16 - padLen);
+		memset(block + 16 - padLen, padLen, padLen);
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		break;
+
+	case MODE_CBC:
+		iv = cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0];
+			((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1];
+			((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2];
+			((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3];
+			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		assert(padLen > 0 && padLen <= 16);
+		for (i = 0; i < 16 - padLen; i++) {
+			block[i] = input[i] ^ iv[i];
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			block[i] = (BYTE)padLen ^ iv[i];
+		}
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 16*(numBlocks + 1);
+}
+
+int blockDecrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer) {
+	int i, k, numBlocks;
+	word8 block[16], iv[4][4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) { 
+			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+#if STRICT_ALIGN 
+		memcpy(iv, cipher->IV, 16); 
+#else
+		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+			((word32*)block)[0] ^= *((word32*)iv[0]);
+			((word32*)block)[1] ^= *((word32*)iv[1]);
+			((word32*)block)[2] ^= *((word32*)iv[2]);
+			((word32*)block)[3] ^= *((word32*)iv[3]);
+#if STRICT_ALIGN
+			memcpy(iv, input, 16);
+			memcpy(outBuf, block, 16);
+#else
+			*((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
+			*((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
+			*((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
+			*((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
+#endif
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+	
+	case MODE_CFB1:
+#if STRICT_ALIGN 
+		memcpy(iv, cipher->IV, 16); 
+#else
+		*((word32*)iv[0]) = *((word32*)(cipher->IV));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif
+		for (i = numBlocks; i > 0; i--) {
+			for (k = 0; k < 128; k++) {
+				*((word32*) block    ) = *((word32*)iv[0]);
+				*((word32*)(block+ 4)) = *((word32*)iv[1]);
+				*((word32*)(block+ 8)) = *((word32*)iv[2]);
+				*((word32*)(block+12)) = *((word32*)iv[3]);
+				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
+				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
+				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+			}
+		}
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+int padDecrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer) {
+	int i, numBlocks, padLen;
+	word8 block[16];
+	word32 iv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_ENCRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+	if (inputOctets % 16 != 0) {
+		return BAD_DATA;
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) { 
+			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+		padLen = block[15];
+		if (padLen >= 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+		
+	case MODE_CBC:
+		memcpy(iv, cipher->IV, 16);
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) {
+			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+			((word32*)block)[0] ^= iv[0];
+			((word32*)block)[1] ^= iv[1];
+			((word32*)block)[2] ^= iv[2];
+			((word32*)block)[3] ^= iv[3];
+			memcpy(iv, input, 16);
+			memcpy(outBuffer, block, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+		((word32*)block)[0] ^= iv[0];
+		((word32*)block)[1] ^= iv[1];
+		((word32*)block)[2] ^= iv[2];
+		((word32*)block)[3] ^= iv[3];
+		padLen = block[15];
+		if (padLen <= 0 || padLen > 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+	
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 16*numBlocks - padLen;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ *	cipherUpdateRounds:
+ *
+ *	Encrypts/Decrypts exactly one full block a specified number of rounds.
+ *	Only used in the Intermediate Value Known Answer Test.	
+ *
+ *	Returns:
+ *		TRUE - on success
+ *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
+ */
+int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
+	int j;
+	word8 block[4][4];
+
+	if (cipher == NULL || key == NULL) {
+		return BAD_CIPHER_STATE;
+	}
+
+	for (j = 3; j >= 0; j--) {
+		/* parse input stream into rectangular array */
+  		*((word32*)block[j]) = *((word32*)(input+4*j));
+	}
+
+	switch (key->direction) {
+	case DIR_ENCRYPT:
+		rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
+		break;
+		
+	case DIR_DECRYPT:
+		rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
+		break;
+		
+	default:
+		return BAD_KEY_DIR;
+	} 
+
+	for (j = 3; j >= 0; j--) {
+		/* parse rectangular array into output ciphertext bytes */
+		*((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
+	}
+	
+	return TRUE;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */

Added: vic/branches/mpeg4/net/rijndael-api-fst.h
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/rijndael-api-fst.h	Wed May 30 23:54:00 2007
@@ -0,0 +1,100 @@
+/*
+ * rijndael-api-fst.h   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * #define INTERMEDIATE_VALUE_KAT to generate the Intermediate Value Known Answer Test.
+ */
+
+#ifndef __RIJNDAEL_API_FST_H
+#define __RIJNDAEL_API_FST_H
+
+#include <stdio.h>
+#include "rijndael-alg-fst.h"
+
+/*  Defines:
+	Add any additional defines you need
+*/
+
+#define     DIR_ENCRYPT           0 /*  Are we encrpyting?  */
+#define     DIR_DECRYPT           1 /*  Are we decrpyting?  */
+#define     MODE_ECB              1 /*  Are we ciphering in ECB mode?   */
+#define     MODE_CBC              2 /*  Are we ciphering in CBC mode?   */
+#define     MODE_CFB1             3 /*  Are we ciphering in 1-bit CFB mode? */
+#define     TRUE                  1
+#define     FALSE                 0
+#define     BITSPERBLOCK        128 /* Default number of bits in a cipher block */
+
+/*  Error Codes - CHANGE POSSIBLE: inclusion of additional error codes  */
+#define     BAD_KEY_DIR          -1 /*  Key direction is invalid, e.g., unknown value */
+#define     BAD_KEY_MAT          -2 /*  Key material not of correct length */
+#define     BAD_KEY_INSTANCE     -3 /*  Key passed is not valid */
+#define     BAD_CIPHER_MODE      -4 /*  Params struct passed to cipherInit invalid */
+#define     BAD_CIPHER_STATE     -5 /*  Cipher in wrong state (e.g., not initialized) */
+#define     BAD_BLOCK_LENGTH     -6
+#define     BAD_CIPHER_INSTANCE  -7
+#define     BAD_DATA             -8 /*  Data contents are invalid, e.g., invalid padding */
+#define     BAD_OTHER            -9 /*  Unknown error */
+
+/*  CHANGE POSSIBLE:  inclusion of algorithm specific defines  */
+#define     MAX_KEY_SIZE         64 /* # of ASCII char's needed to represent a key */
+#define     MAX_IV_SIZE          16 /* # bytes needed to represent an IV  */
+
+/*  Typedefs:
+
+	Typedef'ed data storage elements.  Add any algorithm specific 
+parameters at the bottom of the structs as appropriate.
+*/
+
+typedef unsigned char   BYTE;
+
+/*  The structure for key information */
+typedef struct {
+    BYTE  direction;                /* Key used for encrypting or decrypting? */
+    int   keyLen;                   /* Length of the key  */
+    char  keyMaterial[MAX_KEY_SIZE+1];  /* Raw key data in ASCII, e.g., user input or KAT values */
+        /*  The following parameters are algorithm dependent, replace or add as necessary  */
+	int   ROUNDS;                   /* key-length-dependent number of rounds */
+    int   blockLen;                 /* block length */
+    word8 keySched[MAXROUNDS+1][4][4];	/* key schedule		*/
+} keyInstance;
+
+/*  The structure for cipher information */
+typedef struct {                    /* changed order of the components */
+    BYTE  mode;                     /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
+    BYTE  IV[MAX_IV_SIZE];          /* A possible Initialization Vector for ciphering */
+        /*  Add any algorithm specific parameters needed here  */
+    int   blockLen;                 /* Sample: Handles non-128 bit block sizes (if available) */
+} cipherInstance;
+
+/*  Function prototypes  */
+/*  CHANGED: nothing
+	TODO: implement the following extensions to setup 192-bit and 256-bit block lengths:
+        makeKeyEx():    parameter blockLen added
+                        -- this parameter is absolutely necessary if you want to
+                        setup the round keys in a variable block length setting 
+	    cipherInitEx(): parameter blockLen added (for obvious reasons)		
+ */
+
+int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial);
+
+int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);
+
+int blockEncrypt(cipherInstance *cipher, keyInstance *key,
+        BYTE *input, int inputLen, BYTE *outBuffer);
+
+int padEncrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer);
+
+int blockDecrypt(cipherInstance *cipher, keyInstance *key,
+        BYTE *input, int inputLen, BYTE *outBuffer);
+
+int padDecrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
+        BYTE *input, int inputLen, BYTE *outBuffer, int Rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /*  __RIJNDAEL_API_FST_H */

Added: vic/branches/mpeg4/net/rijndael-test-fst.c
==============================================================================
--- (empty file)
+++ vic/branches/mpeg4/net/rijndael-test-fst.c	Wed May 30 23:54:00 2007
@@ -0,0 +1,824 @@
+/*
+ * rijndael-test-fst.c   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Paulo Barreto
+ *                Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *
+ * This code is placed in the public domain.
+ */
+
+#ifndef INTERMEDIATE_VALUE_KAT
+#error "Must #define INTERMEDIATE_VALUE_KAT to generate the Intermediate Value Known Answer Test."
+#endif /* INTERMEDIATE_VALUE_KAT */
+#define TRACE_KAT_MCT
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "rijndael-api-fst.h"
+
+#define SUBMITTER "Joan Daemen"
+
+static void blockPrint(FILE *fp, const BYTE *block, const char *tag) {
+	int i;
+	fprintf (fp, "%s=", tag);
+	for (i = 0; i < 16; i++) {
+		fprintf (fp, "%02X", block[i]);
+	}
+	fprintf (fp, "\n");
+	fflush (fp);
+} /* blockPrint */
+
+static void rijndaelVKKAT(FILE *fp, int keyLength) {
+	int i, j, r;
+	BYTE block[4*4];
+	BYTE keyMaterial[320];
+	BYTE byteVal = (BYTE)'8';
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+
+#ifdef TRACE_KAT_MCT
+	printf("Executing Variable-Key KAT (key %d): ", keyLength);
+	fflush(stdout);
+#endif /* ?TRACE_KAT_MCT */
+	fprintf(fp,
+		"\n"
+		"==========\n"
+		"\n"
+		"KEYSIZE=%d\n"
+		"\n", keyLength);
+	fflush(fp);
+	memset(block, 0, 16);
+	blockPrint(fp, block, "PT");
+	memset(keyMaterial, 0, sizeof (keyMaterial));
+	memset(keyMaterial, '0', keyLength/4);
+	for (i = 0; i < keyLength; i++) {
+		keyMaterial[i/4] = byteVal; /* set only the i-th bit of the i-th test key */
+		r = makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+		if (TRUE != r) {
+			fprintf(stderr,"makeKey error %d\n",r);
+			exit(-1);
+		}
+		fprintf(fp, "\nI=%d\n", i+1);
+		fprintf(fp, "KEY=%s\n", keyMaterial);
+		memset(block, 0, 16);
+		r = cipherInit(&cipherInst, MODE_ECB, NULL);
+		if (TRUE != r) {
+			fprintf(stderr,"cipherInit error %d\n",r);
+			exit(-1);
+		}
+		r = blockEncrypt(&cipherInst, &keyInst, block, 128, block);
+		if (128 != r) {
+			fprintf(stderr,"blockEncrypt error %d\n",r);
+			exit(-1);
+		}
+		blockPrint(fp, block, "CT");
+		/* now check decryption: */
+		makeKey(&keyInst, DIR_DECRYPT, keyLength, keyMaterial);
+		blockDecrypt(&cipherInst, &keyInst, block, 128, block);
+		for (j = 0; j < 16; j++) {
+			assert(block[j] == 0);
+		}
+		/* undo changes for the next iteration: */
+		keyMaterial[i/4] = (BYTE)'0';
+		byteVal =
+			(byteVal == '8') ?	'4' :
+			(byteVal == '4') ?	'2' :
+			(byteVal == '2') ?	'1' :
+		/*	(byteVal == '1') */	'8';
+	}
+	assert(byteVal == (BYTE)'8');
+	
+#ifdef TRACE_KAT_MCT
+	printf(" done.\n");
+#endif /* ?TRACE_KAT_MCT */
+} /* rijndaelVKKAT */
+
+
+static void rijndaelVTKAT(FILE *fp, int keyLength) {
+	int i;
+	BYTE block[4*4];
+	BYTE keyMaterial[320];
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+
+#ifdef TRACE_KAT_MCT
+	printf("Executing Variable-Text KAT (key %d): ", keyLength);
+	fflush(stdout);
+#endif /* ?TRACE_KAT_MCT */
+	fprintf(fp,
+		"\n"
+		"==========\n"
+		"\n"
+		"KEYSIZE=%d\n"
+		"\n", keyLength);
+	fflush(fp);
+	memset(keyMaterial, 0, sizeof (keyMaterial));
+	memset(keyMaterial, '0', keyLength/4);
+	makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+	fprintf(fp, "KEY=%s\n", keyMaterial);
+	for (i = 0; i < 128; i++) {
+		memset(block, 0, 16);
+		block[i/8] |= 1 << (7 - i%8); /* set only the i-th bit of the i-th test block */
+		fprintf (fp, "\nI=%d\n", i+1);
+		blockPrint(fp, block, "PT");
+		cipherInit(&cipherInst, MODE_ECB, NULL);
+		blockEncrypt(&cipherInst, &keyInst, block, 128, block);
+		blockPrint(fp, block, "CT");
+	}
+#ifdef TRACE_KAT_MCT
+	printf(" done.\n");
+#endif /* ?TRACE_KAT_MCT */
+}
+
+
+static void rijndaelTKAT(FILE *fp,  int keyLength, FILE *in) {
+	int i, j;
+	unsigned int s;
+	BYTE block[4*4], block2[4*4];
+	BYTE keyMaterial[320];
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+
+#ifdef TRACE_KAT_MCT
+	printf("Executing Tables KAT (key %d): ", keyLength);
+	fflush(stdout);
+#endif /* ?TRACE_KAT_MCT */
+	fprintf(fp,
+		"\n"
+		"==========\n"
+		"\n"
+		"KEYSIZE=%d\n"
+		"\n", keyLength);
+	fflush(fp);
+
+	memset(keyMaterial, 0, sizeof (keyMaterial));
+	
+	for (i = 0; i < 64; i++) {
+		fprintf(fp, "\nI=%d\n", i+1);
+		for(j = 0; j < keyLength/4; j++) {
+			fscanf(in, "%c", &keyMaterial[j]);
+		}
+		makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+		
+		fprintf(fp, "KEY=%s\n", keyMaterial);
+		
+		for (j = 0; j < 16; j++) {
+			fscanf(in,"%02x",&s);
+			block[j] = s;
+		}
+		fscanf(in, "%c", &s);
+		fscanf(in, "%c", &s);
+		blockPrint(fp, block, "PT");
+		cipherInit(&cipherInst, MODE_ECB, NULL);
+		blockEncrypt(&cipherInst, &keyInst, block, 128, block2);
+		blockPrint(fp, block2, "CT");
+	}
+	for (i = 64; i < 128; i++) {
+		fprintf(fp, "\nI=%d\n", i+1);
+		for(j = 0; j < keyLength/4; j++) {
+			fscanf(in, "%c", &keyMaterial[j]);
+		}
+		makeKey(&keyInst, DIR_DECRYPT, keyLength, keyMaterial);
+		
+		fprintf(fp, "KEY=%s\n", keyMaterial);
+		
+		for (j = 0; j < 16; j++) {
+			fscanf(in, "%02x", &s);
+			block[j] = s;
+		}
+		fscanf(in, "%c", &s);
+		fscanf(in, "%c", &s);
+		cipherInit(&cipherInst, MODE_ECB, NULL);
+		blockDecrypt(&cipherInst, &keyInst, block, 128, block2);
+		blockPrint(fp, block2, "PT");
+		blockPrint(fp, block, "CT");
+	}
+
+#ifdef TRACE_KAT_MCT
+	printf(" done.\n");
+#endif /* ?TRACE_KAT_MCT */
+}
+
+static void rijndaelIVKAT (FILE *fp, int keyLength)
+{
+	int i;
+	BYTE block[4*4], block2[4*4];
+	BYTE keyMaterial[320];
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+	char format[10];
+#ifdef TRACE_KAT_MCT
+	printf ("Executing Intermediate value KAT (key %d): ", keyLength);
+	fflush (stdout);
+#endif /* ?TRACE_KAT_MCT */
+
+	fprintf(fp,
+		"\n"
+		"==========\n"
+		"\n"
+		"KEYSIZE=%d\n",
+		keyLength);
+	fflush(fp);
+	memset(keyMaterial, 0, sizeof (keyMaterial));
+	for (i = 0; i < keyLength/8; i++) {
+		sprintf(&keyMaterial[2*i], "%02X", i);
+	}
+	makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+	fprintf(fp, "KEY=%s\n", keyMaterial);
+	fprintf(fp, "\nIntermediate Ciphertext Values (Encryption)\n\n");
+	for (i = 0; i < 16; i++) {
+		block[i] = i;
+	}
+	blockPrint(fp, block, "PT");
+	cipherInit(&cipherInst, MODE_ECB, NULL);
+	for(i = 1; i < keyInst.ROUNDS; i++) {
+		cipherUpdateRounds(&cipherInst, &keyInst, block, 16, block2, i);
+		sprintf(format, "CT%d", i);
+		blockPrint(fp, block2, format);
+	}
+	cipherUpdateRounds(&cipherInst, &keyInst, block, 128, block2, keyInst.ROUNDS);
+	blockPrint(fp, block2, "CT");
+	
+	/* BEGIN HACK */
+	/* in order to get the same intermediate values in decryption
+	   as in decryption, we need to use the encryption roundkeys,
+	   but the key direction has to be DIR_DECRYPT
+	   
+	   consider it as a dirty trick 
+	 */
+	makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+	keyInst.direction = DIR_DECRYPT;
+	/* END HACK */
+
+	fprintf(fp, "\nIntermediate Ciphertext Values (Decryption)\n\n");
+	blockPrint(fp, block2, "CT");
+	cipherInit(&cipherInst, MODE_ECB, NULL);
+	for(i = 1; i < keyInst.ROUNDS; i++) {
+		cipherUpdateRounds(&cipherInst, &keyInst, block2, 128, block, keyInst.ROUNDS - i);
+		sprintf(format, "PT%d", i);
+		blockPrint(fp, block, format);
+	}
+	cipherUpdateRounds(&cipherInst, &keyInst, block2, 128, block, 0);
+	blockPrint(fp, block, "PT");
+	
+#ifdef TRACE_KAT_MCT
+	printf(" done.\n");
+#endif 
+}
+
+static void makeKATs (const char *vkFile, const char *vtFile, const char *tblFile, const char *ivFile) {
+	FILE *fp, *fp2;
+
+	/* prepare Variable Key Known Answer Tests: */
+	fp = fopen(vkFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode\n"
+		"Variable Key Known Answer Tests\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		vkFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelVKKAT(fp, 128); /* test for 128-bit key */
+	rijndaelVKKAT(fp, 192); /* test for 192-bit key */
+	rijndaelVKKAT(fp, 256); /* test for 256-bit key */
+
+	fprintf(fp,
+		"\n"
+		"==========");
+	fclose(fp);
+
+	/* prepare Variable Text Known Answer Tests: */
+	fp = fopen(vtFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode\n"
+		"Variable Text Known Answer Tests\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		vtFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelVTKAT(fp, 128);
+	rijndaelVTKAT(fp, 192);
+	rijndaelVTKAT(fp, 256);
+
+	fprintf(fp,
+		"\n"
+		"==========");
+	fclose(fp);
+
+	/* prepare Tables Known Answer Tests: */
+	fp = fopen(tblFile, "w");
+	fprintf(fp,
+	    "/* Description of what tables are tested:\n"
+		"   The provided implementations each use a different set of tables\n"
+		"    - Java implementation: uses no tables\n"
+		"    - reference C implementation: uses Logtable, Alogtable, S, Si, rcon\n"
+		"    - fast C implementation: uses Logtable, Alogtable,  rcon\n"
+		"        and additionally, T1, T2, T3, T4, T5, T6, T7, T8\n"
+		"   All these tables are tested.\n" 
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode\n"
+		"Tables Known Answer Tests\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		tblFile, SUBMITTER);
+	fflush(fp);
+
+	if (NULL != (fp2 = fopen("table.128", "r"))) {
+		rijndaelTKAT(fp, 128, fp2);
+		fclose(fp2);
+	} else {
+		printf("Table Known Answer test expects file table.128\n");
+		fclose(fp);
+		exit(EXIT_FAILURE);		
+	}
+	if (NULL != (fp2 = fopen("table.192", "r"))) {
+		rijndaelTKAT(fp, 192, fp2);
+		fclose(fp2);
+	} else {
+		printf("Table Known Answer test expects file table.192\n");
+		fclose(fp);
+		exit(EXIT_FAILURE);		
+	}
+	if (NULL != (fp2 = fopen("table.256", "r"))) {
+		rijndaelTKAT (fp, 256, fp2);
+		fclose(fp2);
+	} else {
+		printf("Table Known Answer test expects file table.192\n");
+		fclose(fp);
+		exit(EXIT_FAILURE);		
+	}
+	
+	fprintf(fp,
+		"\n"
+		"==========");
+	fclose(fp);
+
+	/* prepare Intermediate Values Known Answer Tests: */
+	fp = fopen(ivFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode\n"
+		"Intermediate Value Known Answer Tests\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		ivFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelIVKAT(fp, 128);
+	rijndaelIVKAT(fp, 192);
+	rijndaelIVKAT(fp, 256);
+
+	fprintf(fp,
+		"\n"
+		"==========");
+	fclose(fp);
+}
+
+static void rijndaelECB_MCT(FILE *fp, int keyLength, BYTE direction) {
+	int i, j;
+	BYTE inBlock[4*4], outBlock[4*4], binKey[4*MAXKC];
+	BYTE keyMaterial[320];
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+
+#ifdef TRACE_KAT_MCT
+	int width = 0;
+	clock_t elapsed = -clock();
+	printf("Executing ECB MCT (%s, key %d): ",
+		direction == DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT", keyLength);
+	fflush(stdout);
+#endif /* ?TRACE_KAT_MCT */
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"KEYSIZE=%d\n", keyLength);
+	fflush(fp);
+	memset(outBlock, 0, 16);
+	memset(binKey, 0, keyLength/8);
+	for (i = 0; i < 400; i++) {
+#ifdef TRACE_KAT_MCT                 
+        while (width-- > 0) {
+        	putchar('\b');
+        }
+        width = printf("%d", i);
+        fflush(stdout);    
+#endif /* ?TRACE_KAT_MCT */
+		fprintf(fp, "\nI=%d\n", i);
+		/* prepare key: */
+		for (j = 0; j < keyLength/8; j++) {
+			sprintf(&keyMaterial[2*j], "%02X", binKey[j]);
+		}
+		keyMaterial[keyLength/4] = 0;
+		fprintf(fp, "KEY=%s\n", keyMaterial);
+		makeKey(&keyInst, direction, keyLength, keyMaterial);
+		/* do encryption/decryption: */
+		blockPrint(fp, outBlock, direction == DIR_ENCRYPT ? "PT" : "CT");
+		cipherInit(&cipherInst, MODE_ECB, NULL);
+		if (direction == DIR_ENCRYPT) {
+			for (j = 0; j < 10000; j++) {
+				memcpy(inBlock, outBlock, 16);
+				blockEncrypt(&cipherInst, &keyInst, inBlock, 128, outBlock);
+			}
+		} else {
+			for (j = 0; j < 10000; j++) {
+				memcpy(inBlock, outBlock, 16);
+				blockDecrypt(&cipherInst, &keyInst, inBlock, 128, outBlock);
+			}
+		}
+		blockPrint(fp, outBlock, direction == DIR_ENCRYPT ? "CT" : "PT");
+		/* prepare new key: */
+		switch (keyLength) {
+		case 128:
+			for (j = 0; j < 128/8; j++) {
+				binKey[j] ^= outBlock[j];
+			}
+			break;
+		case 192:
+			for (j = 0; j < 64/8; j++) {
+				binKey[j] ^= inBlock[j + 64/8];
+			}
+			for (j = 0; j < 128/8; j++) {
+				binKey[j + 64/8] ^= outBlock[j];
+			}
+			break;
+		case 256:
+			for (j = 0; j < 128/8; j++) {
+				binKey[j] ^= inBlock[j];
+			}
+			for (j = 0; j < 128/8; j++) {
+				binKey[j + 128/8] ^= outBlock[j];
+			}
+			break;
+		}
+	}
+#ifdef TRACE_KAT_MCT
+	elapsed += clock();
+	printf(" done (%.1f s).\n", (float)elapsed/CLOCKS_PER_SEC);
+#endif /* ?TRACE_KAT_MCT */
+} /* rijndaelECB_MCT */
+
+
+static void rijndaelCBC_MCT(FILE *fp, int keyLength, BYTE direction) {
+	int i, j, r, t;
+	BYTE inBlock[256/8], outBlock[256/8], binKey[256/8], cv[256/8];
+	BYTE keyMaterial[320];
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+
+#ifdef TRACE_KAT_MCT
+	int width = 0;
+	clock_t elapsed = -clock();
+	printf("Executing CBC MCT (%s, key %d): ",
+		direction == DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT", keyLength);
+	fflush (stdout);
+#endif /* ?TRACE_KAT_MCT */
+	fprintf (fp,
+		"\n"
+		"==========\n"
+		"\n"
+		"KEYSIZE=%d\n", keyLength);
+	fflush(fp);
+	memset(cv,0,16);
+	memset(inBlock,0,16);
+	memset(binKey,0,keyLength/8);
+	for (i = 0; i < 400; i++) {
+#ifdef TRACE_KAT_MCT                 
+        while (width-- > 0) {
+        	putchar('\b');
+        }
+        width = printf("%d", i);
+        fflush(stdout);    
+#endif /* ?TRACE_KAT_MCT */
+		fprintf (fp, "\nI=%d\n", i);
+		/* prepare key: */
+		for (j = 0; j < keyLength/8; j++) {
+			sprintf (&keyMaterial[2*j], "%02X", binKey[j]);
+		}
+		keyMaterial[keyLength/4] = 0;
+		fprintf(fp, "KEY=%s\n", keyMaterial);
+		r = makeKey(&keyInst, direction, keyLength, keyMaterial);
+		if (TRUE != r) {
+			fprintf(stderr,"makeKey error %d\n",r);
+			exit(-1);
+		}
+		r = cipherInit(&cipherInst, MODE_ECB, NULL);
+		if (TRUE != r) {
+			fprintf(stderr,"cipherInit error %d\n",r);
+			exit(-1);
+		}
+		/* do encryption/decryption: */
+		blockPrint(fp, cv, "IV");
+		blockPrint(fp, inBlock, direction == DIR_ENCRYPT ? "PT" : "CT");
+		if (direction == DIR_ENCRYPT) {
+			for (j = 0; j < 10000; j++) {
+				for (t = 0; t < 16; t++) {
+					inBlock[t] ^= cv[t];
+				}
+				r = blockEncrypt(&cipherInst, &keyInst, inBlock, 128, outBlock);
+				if (128 != r) {
+					fprintf(stderr,"blockEncrypt error %d\n",r);
+					exit(-1);
+				}
+				memcpy(inBlock, cv, 16);
+				memcpy(cv, outBlock, 16);
+			}
+		} else {
+			for (j = 0; j < 10000; j++) {
+				blockDecrypt(&cipherInst, &keyInst, inBlock, 128, outBlock);
+				for (t = 0; t < 16; t++) {
+					outBlock[t] ^= cv[t];
+				}
+				memcpy(cv, inBlock, 16);
+				memcpy(inBlock, outBlock, 16);
+			}
+		}
+		blockPrint(fp, outBlock, direction == DIR_ENCRYPT ? "CT" : "PT");
+		/* prepare new key: */
+		switch (keyLength) {
+		case 128:
+			for (j = 0; j < 128/8; j++) {
+				binKey[j] ^= outBlock[j];
+			}
+			break;
+		case 192:
+			for (j = 0; j < 64/8; j++) {
+				if (direction == DIR_ENCRYPT) {
+					binKey[j] ^= inBlock[j + 64/8];
+				} else {
+					binKey[j] ^= cv[j + 64/8];
+				}
+			}
+			for (j = 0; j < 128/8; j++) {
+				binKey[j + 64/8] ^= outBlock[j];
+			}
+			break;
+		case 256:
+			for (j = 0; j < 128/8; j++) {
+				if (direction == DIR_ENCRYPT) {
+					binKey[j] ^= inBlock[j];
+				} else {
+					binKey[j] ^= cv[j];
+				}
+			}
+			for (j = 0; j < 128/8; j++) {
+				binKey[j + 128/8] ^= outBlock[j];
+			}
+			break;
+		}
+	}
+#ifdef TRACE_KAT_MCT
+	elapsed += clock();
+	printf(" done (%.1f s).\n", (float)elapsed/CLOCKS_PER_SEC);
+#endif /* ?TRACE_KAT_MCT */
+} /* rijndaelCBC_MCT */
+
+
+static void makeMCTs(const char *ecbEncryptionFile, const char *ecbDecryptionFile,
+		const char *cbcEncryptionFile, const char *cbcDecryptionFile) {
+	FILE *fp;
+
+	/* prepare ECB Encryption Monte Carlo Tests: */
+	fp = fopen(ecbEncryptionFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode - ENCRYPTION\n"
+		"Monte Carlo Test\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		ecbEncryptionFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelECB_MCT(fp, 128, DIR_ENCRYPT);
+	rijndaelECB_MCT(fp, 192, DIR_ENCRYPT);
+	rijndaelECB_MCT(fp, 256, DIR_ENCRYPT);
+
+	fprintf(fp,
+		"\n"
+		"===========");
+	fclose(fp);
+
+	/* prepare ECB Decryption Monte Carlo Tests: */
+	fp = fopen(ecbDecryptionFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Electronic Codebook (ECB) Mode - DECRYPTION\n"
+		"Monte Carlo Test\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		ecbDecryptionFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelECB_MCT(fp, 128, DIR_DECRYPT);
+	rijndaelECB_MCT(fp, 192, DIR_DECRYPT);
+	rijndaelECB_MCT(fp, 256, DIR_DECRYPT);
+
+	fprintf(fp,
+		"\n"
+		"===========");
+	fclose(fp);
+
+	/* prepare CBC Encryption Monte Carlo Tests: */
+	fp = fopen (cbcEncryptionFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Cipher Block Chaining (CBC) Mode - ENCRYPTION\n"
+		"Monte Carlo Test\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		cbcEncryptionFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelCBC_MCT(fp, 128, DIR_ENCRYPT);
+	rijndaelCBC_MCT(fp, 192, DIR_ENCRYPT);
+	rijndaelCBC_MCT(fp, 256, DIR_ENCRYPT);
+
+
+	fprintf(fp,
+		"\n"
+		"===========");
+	fclose(fp);
+
+	/* prepare CBC Decryption Monte Carlo Tests: */
+	fp = fopen(cbcDecryptionFile, "w");
+	fprintf(fp,
+		"\n"
+		"=========================\n"
+		"\n"
+		"FILENAME:  \"%s\"\n"
+		"\n"
+		"Cipher Block Chaining (CBC) Mode - DECRYPTION\n"
+		"Monte Carlo Test\n"
+		"\n"
+		"Algorithm Name: Rijndael\n"
+		"Principal Submitter: %s\n",
+		cbcDecryptionFile, SUBMITTER);
+	fflush(fp);
+
+	rijndaelCBC_MCT(fp, 128, DIR_DECRYPT);
+	rijndaelCBC_MCT(fp, 192, DIR_DECRYPT);
+	rijndaelCBC_MCT(fp, 256, DIR_DECRYPT);
+
+	fprintf(fp,
+		"\n"
+		"===========");
+	fclose(fp);
+} /* makeMCTs */
+
+void rand_init(void) {
+	srand(time(NULL));
+}
+
+word32 rand_word32(void) {
+	return
+		((word32)(rand() >> 7) << 24) | 
+		((word32)(rand() >> 7) << 16) | 
+		((word32)(rand() >> 7) <<  8) | 
+		((word32)(rand() >> 7));
+}
+
+static void rijndaelSpeed(FILE *fp, int keyLength, BYTE mode, int iterations) {
+	int i, rounds;
+	BYTE block[4*4];
+	BYTE keyMaterial[320];
+	char IV[2*4*4+1] = "A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5";
+	keyInstance keyInst;
+	cipherInstance cipherInst;
+	clock_t elapsed;
+	double sec;
+
+	printf("Measuring speed (key %d): \n", keyLength);
+	fflush(stdout);
+
+	rounds = iterations;
+	rand_init();
+	for (i = 3; i >= 0; i--) {
+		((word32*)block)[i] = rand_word32();
+	}
+   	blockPrint(fp, block, "plaintext");
+
+	memset(keyMaterial, 0, sizeof (keyMaterial));
+	memset(keyMaterial, '0', keyLength/4);
+	for (i = 0; i < keyLength/4; i++) {
+		keyMaterial[i] = '0'+ i;
+	}
+
+	printf("Measuring key scheduling speed...");
+	elapsed = -clock ();
+	for (i = rounds; i > 0; i--) {
+		makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
+	}
+	elapsed += clock ();
+	sec = elapsed ? (double)elapsed/CLOCKS_PER_SEC : 1.0;
+	printf(" %.2f sec, %.1f Mbit/sec.\n",
+		sec, (double)keyLength*iterations/1E6/sec);
+
+	if (mode == MODE_ECB) {
+		cipherInit(&cipherInst, mode, NULL);
+	} else {
+		cipherInit(&cipherInst, mode, IV);
+	}
+
+	printf("Measuring encryption speed...");
+	elapsed = -clock ();
+	for (i = rounds; i > 0; i--) {
+		blockEncrypt(&cipherInst, &keyInst, block, 128, block);
+	}
+	elapsed += clock ();
+
+	sec = elapsed ? (double)elapsed/CLOCKS_PER_SEC : 1.0;
+	printf(" %.2f sec, %.1f Mbit/sec.\n",
+		sec, (double)128*iterations/1E6/sec);
+   	blockPrint (fp, block, "encrypted text");
+
+	if (mode == MODE_ECB) {
+		cipherInit(&cipherInst, mode, NULL);
+	} else {
+		cipherInit(&cipherInst, mode, IV);
+	}
+
+	if (mode != MODE_CFB1) {
+		printf("Measuring key scheduling speed...");
+		elapsed = -clock ();
+		for (i = rounds; i > 0; i--) {
+			makeKey(&keyInst, DIR_DECRYPT, keyLength, keyMaterial);
+		}
+		elapsed += clock ();
+		sec = elapsed ? (double)elapsed/CLOCKS_PER_SEC : 1.0;
+		printf(" %.2f sec, %.1f Mbit/sec.\n",
+			sec, (double)keyLength*iterations/1E6/sec);
+	}
+	printf("Measuring decryption speed...");
+	elapsed = -clock ();
+	for (i = rounds; i > 0; i--) {
+		blockDecrypt(&cipherInst, &keyInst, block, 128, block);
+	}
+	elapsed += clock ();
+	sec = elapsed ? (double)elapsed/CLOCKS_PER_SEC : 1.0;
+	printf(" %.2f sec, %.1f Mbit/sec.\n",
+		sec, (double)128*iterations/1E6/sec);
+   	blockPrint(fp, block, "decrypted text");
+	
+	printf("done.\n");
+} /* rijndaelSpeed */
+
+int main(void) {
+	makeKATs("ecb_vk.txt", "ecb_vt.txt", "ecb_tbl.txt", "ecb_iv.txt");
+	makeMCTs("ecb_e_m.txt", "ecb_d_m.txt", "cbc_e_m.txt", "cbc_d_m.txt");
+
+	printf("ECB:\n");
+	rijndaelSpeed(stdout, 128, MODE_ECB, 1000000);
+	rijndaelSpeed(stdout, 192, MODE_ECB, 1000000);
+	rijndaelSpeed(stdout, 256, MODE_ECB, 1000000);
+	printf("CFB1:\n");
+	rijndaelSpeed(stdout, 128, MODE_CFB1, 10000);
+
+	return 0;
+}



More information about the Sumover-dev mailing list