[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