svn: ecrypt/trunk/submissions/hermes/hermes.c
File:
[svn] /
ecrypt /
trunk /
submissions /
hermes / hermes.c
(
download)
(
as text)
Revision:
1,
Sun Jun 26 18:46:26 2005 UTC (7 years, 11 months ago) by
cdecanni
File size: 84765 byte(s)
* imported original ECRYPT submissions after first automatic cleanup.
/* --------------------------------------------------------------------
hermes Algorithm (c) 2005 Dr. Ulrich Kaiser, (Texas Instruments) Germany
UK20050317 initial version, copy from sc.c
UK20050318 added visible stream and binary stream
UK20050320 added initialization of RandReg
UK20050328 added SBOX application to key byte afer init, after 11 rounds
added plaintext length
added Hermes_encrypt
UK20050403 added loop to Hermes_encrypt; added Hermes_decrypt
UK20050408 added encrypt/decrypt loopback check;
added chisquare test to Hermes_encrypt.
UK20050410 added FIPS 140-2 test to Hermes_encrypt
UK20050415 added SetKey(); added sensitivity test for SAC checking.
UK20050424 added MY_IV_LENGTH to SetLength for algo dependence.
added SetPlaintext pattern.
UK20050517 started changes in order to close the backdoor:
made p1, p2, accu dependent on key;
extended state to 23 resp. 37 bytes;
defined variables OUTPUTBYTES, OUTPUTBITS;
updated SetLength acordingly.
UK20050602 corrected setIVlength, 37 max.
corrected makesequence()
TODO
-
----------------------------------------------------------------------- */
#define credits "HERMES Advanced Stream Cipher Ulrich Kaiser (c) 2005 "
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* statistical tool suite definitions */
#define CHISQ_95 0.00393214
#define CHISQ_90 0.0157908
#define CHISQ_10 2.70554
#define CHISQ_05 3.84146
/* CUSTOMIZE HERE */
#define LOPC 10
#define HIPC 90
#define EXPERIMENTS 100
#define EXPERIMENTSIZE 50
int TestRounds;
float CHISQ_LO, CHISQ_HI;
#define K_LENGTH 32
#define S_LENGTH 37
#define S_LENGTH1 23
#define S_LENGTH2 37
#define P_LENGTH 8
#include "ecrypt-sync.h"
/* working space for other routines: crunch, init, stream */
u8 k[K_LENGTH]; /* key space */
u8 state[S_LENGTH]; /* cipher state */
u32 parm[P_LENGTH]; /* parameters */
u8 kh[K_LENGTH]; /* key helper */
#define X_LENGTH 37
#define Y_LENGTH 32
unsigned char x[X_LENGTH];
unsigned char y[Y_LENGTH];
/* global definition of number of rounds for initialisation ! */
int MY_INIT_ROUNDS = 10;
/* global definition of number of rounds for stream cipher operation ! */
int MY_SC_ROUNDS = 100;
/* global definition of number of IV bytes ! */
int MY_IV_LENGTH = S_LENGTH;
/* global definition of number of plaintext resp. ciphertext bytes ! */
int MY_PT_LENGTH = 25600;
#define PTSIZE 320000
u8 my_plaintext[PTSIZE];
u8 my_ciphertext[PTSIZE];
int MY_PT_PATTERN = 0;
/* now dependent on algorithm ..., is set by SetLength */
int KEYBYTES = -1;
int KEYBITS = -1;
int STATEBYTES = -1;
int STATEBITS = -1;
int OUTPUTBYTES = -1;
int OUTPUTBITS = -1;
int algo = -1; /* selects algorithm */
#define ALGO_NOT_VALID "AlgorithmNumber not valid !\n"
#define choice "[ Hermes8-80 = 1, Hermes8-128 = 2 ]"
/* fail cunters */
int totalfail_runs_test=0;
int totalfail_long_runs=0;
int totalfail_poker=0;
int total_fail_monobit=0;
/* ----- random number generator ----- */
unsigned char RandReg[8];
/* output file handle */
FILE *op;
/* --------- S-BOXes for SC algorithm -------------- */
/* ---------- AES code definitions ---------- */
typedef unsigned char word8;
/* ----- AES encryption SBOX ----- */
word8 S[256] = {
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22,
};/* ddt: 32130 255 0 0 0 0 0 */
unsigned char sbox130[256] =
{130,150,219,161,127,160,229,198, 99, 26, 22, 63, 74,136,215,201
, 82,195, 3,225,239, 94,129, 80, 18,213,149,245, 7, 57,197,115
,113,230,116,163,212,133,162,222,105, 60, 19,170,244, 30, 1,137
,176, 27,185, 42,153, 16,104,202,221, 11,172,190,154,151,103, 71
, 28,187, 2, 88,231,204, 17, 37,228, 73, 44, 31,134,100,144,211
, 89,117,108, 39,227,241,232,247, 20,226,110,254,169, 14,174,119
,131,152, 55,205, 49,164,142, 43,132, 12, 98,224,135,157,114, 83
, 78,236,111, 23,147, 70, 47,252,189, 32, 41,124,120, 58,102, 33
,234,184,158,177,140,121,246,180,175, 45,101,233,168,138,203,188
, 15, 97,183,196, 59,250, 54, 6,148,207, 72,118,206, 86, 48,112
,199, 36, 96,145, 75, 85,220,186,106,217, 34,240, 87,178, 69, 65
,238, 91,179,159,249,146,107,214, 56,141, 10,243,125,165, 8, 29
, 52, 13,253,193, 66, 21,126, 50, 77,251,143, 84,192, 25, 9, 79
, 93, 46, 81, 0, 38, 4, 35, 5,194, 95,128,242,122,156,109, 90
,248,166, 61, 76,167, 67,210,155,139,255, 24, 40, 53, 62,216,218
,173,181,200, 68,191,223,171, 64,209, 92,123,237,182,235, 51,208
};/* ddt: 22166 4629 400 4 0 0 0 0 */
unsigned char sboxAF[256] =
{0xAF, 0x1B, 0xDD, 0xBC, 0x30, 0xEB, 0xF0, 0x56,
0xC1, 0x08, 0x93, 0x36, 0x03, 0xCB, 0x81, 0x80,
0x43, 0x2F, 0xDF, 0x2D, 0x26, 0x05, 0x0A, 0xF8,
0x7D, 0x21, 0xE0, 0xC4, 0x06, 0xD5, 0xA6, 0xE8,
0x8E, 0x70, 0xDC, 0xA4, 0x6D, 0x23, 0xAC, 0x18,
0x40, 0x00, 0x64, 0x0E, 0xF6, 0x79, 0xB5, 0x1F,
0x5D, 0x9A, 0x3B, 0xFA, 0x48, 0x5F, 0x74, 0xA1,
0x8D, 0xD3, 0x5C, 0x4E, 0x9E, 0x14, 0x25, 0xEF,
0xD6, 0xC9, 0x3F, 0xC5, 0xA0, 0x10, 0x50, 0xFB,
0x31, 0xF4, 0x17, 0x88, 0xAB, 0x32, 0x76, 0x3E,
0x15, 0x2A, 0x3D, 0xA9, 0x52, 0x20, 0xC3, 0xFC,
0x7B, 0x49, 0x3A, 0x6E, 0xB7, 0x1D, 0xAD, 0xAA,
0x5A, 0x0D, 0x35, 0x38, 0xC8, 0xF5, 0xF3, 0xB3,
0x8F, 0xE6, 0x13, 0x55, 0x33, 0x8A, 0xC0, 0x67,
0x2E, 0xE7, 0x82, 0x8C, 0x09, 0xCF, 0x1E, 0x97,
0x28, 0x07, 0xBA, 0x4D, 0x42, 0x04, 0x73, 0x41,
0x5B, 0xB1, 0xF9, 0xE5, 0xF7, 0x6C, 0xD8, 0x12,
0x8B, 0x84, 0xCC, 0xB0, 0x69, 0x37, 0xAE, 0x6F,
0xE2, 0xDB, 0x0C, 0x86, 0x29, 0x78, 0x34, 0x7C,
0x1A, 0x85, 0x27, 0xA3, 0x9B, 0x92, 0xE3, 0xBD,
0x59, 0x63, 0x66, 0x19, 0xCA, 0x5E, 0xFF, 0x75,
0x72, 0x24, 0x4F, 0x47, 0x61, 0x11, 0x0B, 0xBE,
0xA7, 0x16, 0x3C, 0xB2, 0xFD, 0x7F, 0x44, 0x99,
0x6B, 0x98, 0x22, 0x46, 0x4A, 0x1C, 0x02, 0x6A,
0x51, 0x39, 0x60, 0x4B, 0x57, 0x01, 0x2C, 0xE1,
0xEE, 0x83, 0x89, 0xDA, 0x58, 0x0F, 0xBB, 0x2B,
0xD2, 0xD4, 0x62, 0x9F, 0x90, 0x7E, 0xDE, 0xB8,
0x4C, 0xCD, 0x68, 0xA8, 0xF2, 0x54, 0xE9, 0xE4,
0xF1, 0xEA, 0xD7, 0x77, 0x9D, 0x96, 0xEC, 0xFE,
0xB9, 0x91, 0xBF, 0xD1, 0xD9, 0xA2, 0x95, 0xED,
0xA5, 0xC2, 0x7A, 0xC6, 0xC7, 0x45, 0x94, 0xB6,
0x65, 0xD0, 0xCE, 0x9C, 0x71, 0x87, 0xB4, 0x53
};/* ddt: 19763 4917 854 106 9 2 0 */
/* ---------------------- bad s-box --------------------- */
unsigned char sboxBAD[256] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209,
225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
0, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241,
};
/************ This is the 8-bit algorithm under test ***************/
/************ This is the 8-bit algorithm under test ***************/
/************ This is the 8-bit algorithm under test ***************/
/*
* DESCRIPTION OF ALGORITHM
*
* accu is one byte
* s-box is a table with 256 bytes, i.e. 8 bit input and 8 bit output
*
* A state byte and a key byte and the previous result (accu)
* are EXORed. Then the s-box function is applied. The output is
* fed into accu and into the oldest state byte.
* Number of initial rounds: >= 4
* Number of sub-rounds : 20 (Hermes8-80) or 32 (Hermes8-128)
*
* Confusion by: S-Box, non-linear boolean function
* Diffusion by: Accu overwriting state byte
*
*
* Notation
*
* Hermes8-80
* State register x consists of 20 bytes x[19]..x[0].
* Key register k consists of 10 bytes k[9]..k[0].
* or
* Hermes8-128
* State register x consists of 32 bytes x[31]..x[0].
* Key register k consists of 16 bytes k[15]..k[0].
*
*/
/* ALGO1 ALGO2 */
void dump_state_key( int nx, int nk )
{
int j;
fprintf(op, "State: 0x \n");
for( j=0; j<nx; j++ ){ fprintf(op, " %2x", state[j] );}
fprintf(op, "\n");
fprintf(op, "Key:\n 0x ");
for( j=0; j<nk; j++ ){ fprintf(op, " %2x", k[j] );}
fprintf(op, "\n");
}/* dump_state_key ------------------------------------ */
void dump_key_hex( int nk )
{
int j;
fprintf(op, "Key: 0x \n");
for( j=0; j<nk; j++ ){ fprintf(op, " %2x", k[j] );}
fprintf(op, "\n");
printf( "Key: 0x \n");
for( j=0; j<nk; j++ ){ printf( " %2x", k[j] );}
printf( "\n");
}/* dump_key_hex ------------------------------------ */
/*
The routine crunch_Hermes8 is needed to evaluate the quality of the
initialization, i.e. find the number of initial rounds that are
needed to get a proper avalanche effect for the state vector.
*/
void crunch_Hermes8( unsigned char xin[], unsigned char y[],
unsigned char k[], int algo )
{
int j; /* inner counter */
int nx; /* number of state bytes */
int nk; /* number of key bytes */
int round; /* round counter */
int src; /* sub-round counter */
int p1; /* pointer to actual state byte */
int p2; /* pointer to actual key byte */
unsigned char accu;
unsigned char state[S_LENGTH];
int nrounds; /* number of rounds to run */
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
/* copy needed in order to destroy k in menu ! */
for( j=0; j<K_LENGTH; j++ ){ kh[j] = k[j]; }
/* local copy needed in order to avoid overwriting xin ! */
for( j=0; j<S_LENGTH1; j++ ){ state[j] = xin[j]; }
nx = S_LENGTH1;
nk = 10;
if( algo == 2 )
{
for( j=20; j<S_LENGTH2; j++ ){ state[j] = xin[j]; }
nx = S_LENGTH2;
nk = 16;
}
for( j=MY_IV_LENGTH; j<S_LENGTH2; j++ ){ state[j] = 0; }
nrounds = MY_INIT_ROUNDS; /* number of rounds, i.e. outer loop count !! */
p1 = ( k[0] ^ k[1] ^ k[2] ) % nx ;
p2 = ( k[3] ^ k[4] ^ k[5] ) % nk ;
accu = k[6] ^ k[7] ^ k[8] ;
#define KEY_STEP3 7
src = ( k[9] ^ k[0] ^ k[3] ) % KEY_STEP3;
for( round=1; round <= nrounds; round++ )
{
#include "hermes_core2.h"
}/* for round */
/* copy result to output */
for( j=0; j<S_LENGTH1; j++ ){ y[j] = state[j]; }
if( algo == 2 )
{
for( j=20; j<S_LENGTH2; j++ ){ y[j] = state[j]; }
}
/* dump_key_hex( nk ); */
/*
dump_state_key( nx, nk );
fprintf(op, "State: 0x \n");
for( j=0; j<nx; j++ ){ fprintf(op, " %2x", state[j] );}
fprintf(op, "\n");
*/
/* restore key array (for crunch only!) */
for( j=0; j<K_LENGTH; j++ ){ k[j] = kh[j]; }
} /* crunch_Hermes8 ------------------------------------------------ */
/*
Does not generate stream bytes, but uses the initialization vector to feed the
state register and to run some rounds in order to obtain initial avalanche
effect. Do not use the state bytes !!!
*/
void Hermes8_init( unsigned char iv[], unsigned char k[], unsigned char state[],
u32 parameters[], int nx, int nk, int n_init )
{
u16 round; /* round counter */
int src; /* sub-round counter */
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u8 accu;
u16 p3, p4; /* scratch */
int nrounds; /* number of rounds to run */
int j;
u8 tmp; /* scratch */
/* feed state[] with Initialization Vector */
for( j=0; j<nx; j++ ){ state[j] = iv[j]; }
for( j=MY_IV_LENGTH; j<S_LENGTH; j++ ){ state[j] = 0; }
for( j=0; j<nk; j++){ printf(" %2d 0x%2x \n", j, k[j] ); }
printf(" key setup done. \n");
for( j=0; j<nk; j++){ fprintf(op, " %2d 0x%2x \n", j, k[j] ); }
fprintf(op, " key setup done. \n");
for( j=0; j<nx; j++){ printf(" %2d 0x%2x \n", j, state[j] ); }
printf(" IV setup done. \n");
for( j=0; j<nx; j++){ fprintf(op, " %2d 0x%2x \n", j, state[j] ); }
fprintf(op, " IV setup done. \n");
/* ----------------- start of algorithm ----------------- */
fprintf(op, "Hermes8_init started...\n");
nrounds = n_init; /* number of rounds, i.e. outer loop count !! */
p1 = ( k[0] ^ k[1] ^ k[2] ) % nx ;
p2 = ( k[3] ^ k[4] ^ k[5] ) % nk ;
accu = k[6] ^ k[7] ^ k[8] ;
#define KEY_STEP3 7
src = ( k[9] ^ k[0] ^ k[3] ) % KEY_STEP3;
for( round=1; round <= nrounds; round++ )
{
#include "hermes_core2.h"
fprintf(op,"CORE-K k[%2d]= 0x%2x \n", p3, k[p3] );
}/* for round */
parameters[0] = accu;
parameters[1] = p1;
parameters[2] = p2;
parameters[3] = src;
parameters[4] = n_init;
printf("INIT accu=0x%2x p1=%d p2=%d src=%d round=%d done.\n",
parameters[0],parameters[1],parameters[2],parameters[3],parameters[4] );
fprintf(op, "INIT accu=0x%2x p1=%d p2=%d src=%d round=%d done.\n",
parameters[0],parameters[1],parameters[2],parameters[3],parameters[4]);
for( j=0; j<MY_IV_LENGTH; j++){ printf(" %2d 0x%2x \n", j, state[j] ); }
printf(" Initialization done. \n\n");
for( j=0; j<MY_IV_LENGTH; j++){ fprintf(op, " %2d 0x%2x \n", j, state[j] ); }
fprintf(op, " Initialization done. \n\n");
}/* Hermes8_init ---------------------------------------------------------*/
/*
generates stream bytes for one round only, i.e. as many bytes
as state has available.
*/
int Hermes8_stream( unsigned char k[], unsigned char state[],
u32 parameters[], int nx, int nk )
{
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u8 accu;
u16 round;
int src; /* sub-round counter */
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
u16 j, m;
fprintf(op, "Hermes8_stream started...\n");
/* ----------------- start of algorithm ----------------- */
accu = parameters[0] & 0x00FF;
p1 = parameters[1];
p2 = parameters[2];
src = parameters[3];
round = parameters[4];
fprintf(op,"STREAM accu= 0x%2x p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round );
#define STREAM_ROUNDS 3
for( m=1; m<=STREAM_ROUNDS; m++)
{
round++;
#include "hermes_core2.h"
}
parameters[0] = accu;
parameters[1] = p1;
parameters[2] = p2;
parameters[3] = src;
parameters[4] = round;
/* printf(" accu=%d p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round ); */
return( p1 );
}/* Hermes8_stream ---------------------------------------------------------*/
/*
The routine stream_Hermes8 is needed to evaluate the quality of the
long key stream. After initialization very many bits are produced
and can be tested w.r.t. randomness.
Uses: state[], k[], parameters[]
*/
#define YES 1
#define NO 0
void stream_Hermes8( unsigned char xin[], unsigned char y[],
int algo, int init_q )
{
int j; /* inner counter */
int nx; /* number of state bytes */
int nk; /* number of key bytes */
int po; /* pointer to state[] */
nx = S_LENGTH1;
nk = 10;
if( algo == 2 )
{
nx = S_LENGTH2;
nk = 16;
}
if( init_q == YES )
{
for( j=MY_IV_LENGTH; j<S_LENGTH2; j++ ) /* reset undefined bytes */
{ xin[j] = 0; }
/* ********************** */
Hermes8_init( xin, k, state, parm, nx, nk, MY_INIT_ROUNDS );
/* ********************** */
}
else
{
/* ********************** */
po = Hermes8_stream( k, state, parm, nx, nk );
/* ********************** */
/* copy result to output */
for( j=0; j<OUTPUTBYTES; j++ )
{
y[j] = state[po];
po = po + 2;
if( po >= nx ) po = po - nx;
}
}
/* dump_key_hex( nk ); */
} /* stream_Hermes8 ------------------------------------------------ */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* -------------------- support for ECRYPT APIs --------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void print_ciphertext_hex( u32 length )
{
u32 j;
fprintf(op, "\n");
fprintf(op, " printing ciphertext now .... \n" );
for(j=0; j<length; j++ )
{
fprintf(op, " %2x", my_ciphertext[j] );
if( j % 16 == 15 ) fprintf(op, "\n");
}
fprintf(op, "\n %d bytes of ciphertext printed. \n", length );
}
void print_ciphertext( u32 length )
{
u32 j;
fprintf(op, "\n");
fprintf(op, " printing ciphertext now .... \n" );
for(j=0; j<length; j++ )
{
fprintf(op, " %3d", my_ciphertext[j] );
if( j % 16 == 15 ) fprintf(op, "\n");
}
fprintf(op, "\n %d bytes of ciphertext printed. \n", length );
}
/**
Run over the full ciphertext and count the occurence of the values as histogram.
Print the histogram resulta as matrix 16 x 16.
Calculate the chi-square test.
*/
void ciphertext_histogram( u32 length )
{
int hist[256];
int j;
u32 n, count, index;
float chisqu;
for(j=0; j<256; j++ ){ hist[j] = 0; }
for(n=0; n<length; n++ ) /* build histogram */
{
hist[ my_ciphertext[n] ]++;
}
printf("\nHistogram: \n"); /* print histogram */
fprintf(op, "\nHistogram: \n"); /* print histogram */
for(j=0; j<256; j++ )
{
printf(" %4d" , hist[j] );
if( j % 16 == 15 ) printf("\n");
fprintf(op, " %4d" , hist[j] );
if( j % 16 == 15 ) fprintf(op, "\n");
}
/* Chi Square Test */
n = length / 256;
printf("===> expected value %d \n", n );
fprintf(op, "===> expected value %d \n", n );
chisqu = 0.0;
for( index=0; index<256; index++ ) /* calculate Chi^2 */
{
count = hist[index];
chisqu = chisqu + (count-n)*(count-n)/n ;
}
/* v=255, alpha=10% ==> x=284.366 */
printf("===> chisqu = %9.2f <? 284.336 \n", chisqu );
fprintf(op, "===> chisqu = %9.2f <? 284.336 \n", chisqu );
if( chisqu > 284.336 )
{
printf("====> ERROR: chisqu = %6.2f > 284.336 \n", chisqu );
fprintf(op, "====> ERROR: chisqu = %6.2f > 284.336 \n", chisqu );
}
}/* ciphertext_histogram -------------------------------- */
void print_plaintext( u32 length )
{
u32 j;
fprintf(op, "\n");
fprintf(op, " printing plaintext now .... \n" );
for(j=0; j<length; j++ )
{
fprintf(op, " %3d", my_plaintext[j] );
if( j % 16 == 15 ) fprintf(op, "\n");
}
fprintf(op, "\n %d bytes of plaintext printed. \n", length );
}
void print_plaintext_hex( u32 length )
{
u32 j;
fprintf(op, "\n");
fprintf(op, " printing plaintext now .... \n" );
for(j=0; j<length; j++ )
{
fprintf(op, " %2x", my_plaintext[j] );
if( j % 16 == 15 ) fprintf(op, "\n");
}
fprintf(op, "\n %d bytes of plaintext printed. \n", length );
}
void ECRYPT_dump_state_key( ECRYPT_ctx* ctxx, int nx, int nk )
{
int j;
fprintf(op, "State: 0x \n");
for( j=0; j<nx; j++ ){ fprintf(op," %2x", ctxx->state[j] );}
fprintf(op,"\n");
fprintf(op, "Key:0x \n");
for( j=0; j<nk; j++ ){ fprintf(op," %2x", ctxx->k[j] );}
fprintf(op,"\n");
}/* ECRYPT_dump_state_key ------------------------------------ */
void ECRYPT_dump_state_hex( ECRYPT_ctx* ctxx, int nx )
{
int j;
fprintf(op, "State: 0x \n");
for( j=0; j<nx; j++ ){ fprintf(op, " %2x", ctxx->state[j] );}
fprintf(op, "\n");
}/* ECRYPT_dump_state_hex ------------------------------------ */
void ECRYPT_dump_key_hex( ECRYPT_ctx* ctxx, int nk )
{
int j;
fprintf(op, "Key:0x \n");
for( j=0; j<nk; j++ ){ fprintf(op, " %2x", ctxx->k[j] );}
fprintf(op, "\n");
}/* ECRYPT_dump_key_hex ------------------------------------ */
void dump_IV( u8* x, int nx )
{
int j;
fprintf(op, "IV: 0x \n");
for( j=0; j<nx; j++ ){ fprintf(op, " %2x", x[j] );}
fprintf(op, "\n");
}/* dump_IV ------------------------------------ */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* -------------------- ECRYPT APIs --------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/**
loads key[] into k[] of the ctx record
stores key size value in record
stores iv size value in record
@param ctx ptr to record
@param key ptr to array with crypto key
@param keysize in bits
@param ivsize in bits
*/
void ECRYPT_keysetup(
ECRYPT_ctx* ctx,
const u8* key,
u32 keysize, /* Key size in bits. */
u32 ivsize ) /* IV size in bits. */
{
u16 j, kb;
kb = keysize / 8;
for( j=0; j<kb; j++ ){ ctx->k[j] = key[j]; }
ctx->parm[5] = kb;
ctx->parm[6] = ivsize / 8;
for( j=0; j<kb; j++){ printf(" %2d 0x%2x \n", j, ctx->k[j] ); }
printf(" ECRYPT_keysetup done. \n");
for( j=0; j<kb; j++){ fprintf(op, " %2d 0x%2x \n", j, ctx->k[j] ); }
fprintf(op, " ECRYPT_keysetup done. \n");
}/* ECRYPT_keysetup ------------------------------------------ */
/**
loads iv[] into state[],
runs initial rounds in order to hide IV and KEY from
first key stream output.
@param ctx ptr to record
@param iv ptr to array with initial value IV
*/
void ECRYPT_ivsetup(
ECRYPT_ctx* ctx,
const u8* iv )
{
u16 ivb; /* IV size in bytes. */
u16 round; /* round counter */
u16 nk; /* number of key bytes */
u16 nx; /* number of state bytes */
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u8 accu;
u16 src; /* sub-round counter */
u16 nrounds; /* number of rounds to run */
u16 j; /* little helpers */
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
/* fill IV into state[] */
ivb = ctx->parm[6];
for( j=0; j<ivb; j++ ){ ctx->state[j] = iv[j]; }
for( j=0; j<ivb; j++){ printf(" %2d %2x \n", j, ctx->state[j] ); }
printf(" ECRYPT_ivsetup done. \n");
for( j=0; j<ivb; j++){ fprintf(op, " %2d %2x \n", j, ctx->state[j] ); }
fprintf(op, " ECRYPT_ivsetup done. \n");
/* ----------------- start of algorithm ----------------- */
/* fprintf(op, "Hermes8_init started...\n"); */
nrounds = MY_INIT_ROUNDS; /* number of rounds, i.e. outer loop count !! */
nk = ctx->parm[5]; /* kb */
nx = STATEBYTES; /* state size in bytes */
p1 = ( k[0] ^ k[1] ^ k[2] ) % nx ;
p2 = ( k[3] ^ k[4] ^ k[5] ) % nk ;
accu = k[6] ^ k[7] ^ k[8] ;
#define KEY_STEP3 7
src = ( k[9] ^ k[0] ^ k[3] ) % KEY_STEP3;
for( round=1; round <= nrounds; round++ )
{
#include "hermes_core.h"
}/* for round */
ctx->parm[0] = accu;
ctx->parm[1] = p1;
ctx->parm[2] = p2;
ctx->parm[3] = src;
ctx->parm[4] = MY_INIT_ROUNDS;
printf( "INIT accu=0x%2x p1=%d p2=%d src=%d round=%d done.\n",
ctx->parm[0],ctx->parm[1],ctx->parm[2],ctx->parm[3],ctx->parm[4] );
/* fprintf(op, "INIT accu=%d p1=%d p2=%d src=%d round=%d done.\n",
ctx->parm[0],ctx->parm[1],ctx->parm[2],ctx->parm[3],ctx->parm[4] ); */
for( j=0; j<ivb; j++){ printf(" %2d 0x%2x \n", j, ctx->state[j] ); }
printf(" ECRYPT_initialization done. \n\n");
for( j=0; j<ivb; j++){ fprintf(op, " %2d 0x%2x \n", j, ctx->state[j] ); }
fprintf(op, " ECRYPT_initialization done. \n\n");
}/* ECRYPT_ivsetup ------------------------------------------ */
/**
Encrypts a certain number of bytes of the plaintext.
@param in ctx ptr to record
@param in plaintext ptr to array with plaintext
@param out ciphertext ptr to array with ciphertext
@param in msglen number of bytes to process
*/
void ECRYPT_encrypt_bytes(
ECRYPT_ctx* ctx,
const u8* plaintext,
u8* ciphertext,
u32 msglen) /* Message length in bytes. */
{
u32 round;
u16 nx; /* number of state bytes */
u16 nk; /* number of key bytes */
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u16 src; /* sub-round counter */
u8 accu;
u16 po; /* output pointer */
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
u32 m, n, pc; /* little helpers */
u16 j; /* little helpers */
u32 maxloops; /* loops needed to process msglen bytes */
/* ----------------- start of algorithm ----------------- */
accu = ctx->parm[0] & 0x00FF;
p1 = ctx->parm[1];
p2 = ctx->parm[2];
src = ctx->parm[3];
round = ctx->parm[4];
nk = ctx->parm[5];
nx = ctx->parm[6];
fprintf(op,"STREAM start accu=0x%2x p1=%d p2=%d scr=%d round=%d \n", accu, p1, p2, src, round );
printf("STREAM start accu=0x%2x p1=%d p2=%d scr=%d round=%d \n", accu, p1, p2, src, round );
maxloops = (u32)( msglen / OUTPUTBYTES + 1.0 );
pc = 0;
for( n=0; n<maxloops; n++ )
{
#define STREAM_ROUNDS 3
for( m=1; m<=STREAM_ROUNDS; m++)
{
round++;
#include "hermes_core.h"
}
po = p1;
for( j=0; j<OUTPUTBYTES; j++ )
{
ciphertext[pc+j] = plaintext[pc+j]^ctx->state[po];
po = po + 2;
if( po >= nx ) po = po - nx;
}
pc = pc + OUTPUTBYTES;
}/* for n */
/* printf(" accu=%d p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round ); */
/* avoid further usage of this routine !!! */
ctx->parm[1] = 9999;
ctx->parm[2] = 9999;
/* show resulting state in GUI */
for(j=0; j<=STATEBYTES; j++){ y[j] = ctx->state[j]; }
}/* ECRYPT_encrypt_bytes ------------------------------------------ */
/**
Decrypts a certain number of bytes of the plaintext.
@param in ctx ptr to record
@param in ciphertext ptr to array with ciphertext
@param out plaintext ptr to array with plaintext
@param in msglen number of bytes to process
*/
void ECRYPT_decrypt_bytes(
ECRYPT_ctx* ctx,
const u8* ciphertext,
u8* plaintext,
u32 msglen) /* Message length in bytes. */
{
u32 round;
u16 nx; /* number of state bytes */
u16 nk; /* number of key bytes */
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u16 src; /* sub-round counter */
u8 accu;
u16 po; /* output pointer */
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
u32 n, pc; /* little helpers */
u16 j, m; /* little helpers */
u32 maxloops; /* loops needed to process msglen bytes */
/* fprintf(op, "Hermes8_stream started...\n"); */
/* ----------------- start of algorithm ----------------- */
accu = ctx->parm[0] & 0x00FF;
p1 = ctx->parm[1];
p2 = ctx->parm[2];
src = ctx->parm[3];
round = ctx->parm[4];
nk = ctx->parm[5];
nx = ctx->parm[6];
fprintf(op,"STREAM start accu=%2x hex p1=%d p2=%d round=%d \n", accu, p1, p2, round );
printf("STREAM start accu=%2x hex p1=%d p2=%d round=%d \n", accu, p1, p2, round );
maxloops = (u32)( msglen / OUTPUTBYTES + 0.5 );
pc = 0;
for( n=0; n<maxloops; n++ )
{
for( m=1; m<=STREAM_ROUNDS; m++)
{
round++;
#include "hermes_core.h"
}
po = p1;
for( j=0; j<OUTPUTBYTES; j++ )
{
plaintext[pc+j] = ciphertext[pc+j]^ctx->state[po];
po = po + 2;
if( po >= nx ) po = po - nx;
}
pc = pc + OUTPUTBYTES;
}/* for n */
/* printf(" accu=%d p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round ); */
/* avoid further usage of this routine !!! */
ctx->parm[1] = 9999;
ctx->parm[2] = 9999;
/* show resulting state in GUI */
for(j=0; j<=STATEBYTES; j++){ y[j] = ctx->state[j]; }
} /* ECRYPT_decrypt_bytes ------------------------------------------ */
/**
Generates key stream....
@param in ctx ptr to record
@param out keystream ptr to array with key stream
@param in length number of bytes to process
*/
void ECRYPT_keystream_bytes( /* based on ECRYPT_encrypt_bytes */
ECRYPT_ctx* ctx,
u8* keystream,
u32 length) /* Length of keystream in bytes. */
{
u32 round;
u16 nx; /* number of state bytes */
u16 nk; /* number of key bytes */
u16 p1; /* pointer to actual state byte */
u16 p2; /* pointer to actual key byte */
u16 src; /* sub-round counter */
u8 accu;
u16 p3, p4; /* scratch */
u8 tmp; /* scratch */
u32 n, pc; /* little helpers */
u16 j, m; /* little helpers */
u32 maxloops; /* loops needed to process msglen bytes */
/* ----------------- start of algorithm ----------------- */
accu = ctx->parm[0] & 0x00FF;
p1 = ctx->parm[1];
p2 = ctx->parm[2];
src = ctx->parm[3];
round = ctx->parm[4];
nk = ctx->parm[5];
nx = ctx->parm[6];
fprintf(op,"STREAM accu=%3d p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round );
printf("STREAM accu=%3d p1=%d p2=%d src=%d round=%d \n", accu, p1, p2, src, round );
maxloops = (u32)( length / OUTPUTBYTES + 0.5 );
pc = 0;
for( n=0; n<maxloops; n++ )
{
for( m=1; m<=STREAM_ROUNDS; m++)
{
round++;
#include "hermes_core.h"
}
/* for( j=0; j<nx; j++ ){ ciphertext[pc+j] = ctx->state[j]; } */
for( j=0; j<OUTPUTBYTES; j++ ){ keystream[pc+j] = ctx->state[j]; }
pc = pc + OUTPUTBYTES;
}/* for n */
} /* ECRYPT_keystream_bytes ------------------------------------------ */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* ---------------- wrappers for ECRYPT APIs ------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/**
Encryption of plaintext of length pt_length
Uses:
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
ECRYPT_ivsetup( &ctx, x );
ECRYPT_encrypt_bytes( &ctx, plaintext, ciphertext, msg_length );
-
@input x
@input k
@input algo
@input plaintext
@input pt_length
-
@global ciphertext
*/
void Hermes_encrypt( u8 x[], u8 k[], int algo, const u8* plaintext, u8* ciphertext, u32 pt_length )
{
u32 key_length;
u32 iv_length;
u32 msg_length;
ECRYPT_ctx ctx; /* create data structure */
msg_length = pt_length;
key_length = 10;
iv_length = S_LENGTH1;
if( algo == 2 ){ key_length = 16; iv_length = S_LENGTH2;}
printf("\n");
printf("Test of ECRYPT_* procedures \n");
printf(" key length = %5d \n", key_length );
printf(" iv length = %5d \n", iv_length );
printf(" pt length = %5d \n", pt_length );
/* Call the ECRYPT API subroutine */
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
/* Call the ECRYPT API subroutine */
ECRYPT_ivsetup( &ctx, x );
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
/* Call the ECRYPT API subroutine */
ECRYPT_encrypt_bytes( &ctx, plaintext, ciphertext, msg_length );
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
/* print_ciphertext( msg_length ); */
ciphertext_histogram( msg_length );
ECRYPT_dump_state_key( &ctx, iv_length, key_length );
ECRYPT_dump_key_hex( &ctx, key_length );
printf("\n");
}/* Hermes_encrypt ----------------------------------------------------------- */
/**
Decryption of ciphertext of length pt_length
Uses:
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
ECRYPT_ivsetup( &ctx, x );
ECRYPT_decrypt_bytes( &ctx, ciphertext, plaintext, msg_length );
-
@input x
@input k
@input algo
@input ciphertext
@input pt_length
-
@global plaintext
*/
void Hermes_decrypt( u8 x[], u8 k[], int algo, const u8* ciphertext, u8* plaintext, u32 pt_length )
{
u32 key_length;
u32 iv_length;
u32 msg_length;
ECRYPT_ctx ctx; /* create data structure */
msg_length = pt_length;
key_length = 10;
iv_length = S_LENGTH1;
if( algo == 2 ){ key_length = 16; iv_length = S_LENGTH2;}
printf("\n");
printf("Test of ECRYPT_* procedures \n");
printf(" key length = %5d \n", key_length );
printf(" iv length = %5d \n", iv_length );
printf(" pt length = %5d \n", pt_length );
/* Call the ECRYPT API subroutine */
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
/* Call the ECRYPT API subroutine */
ECRYPT_ivsetup( &ctx, x );
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
/* Call the ECRYPT API subroutine */
ECRYPT_decrypt_bytes( &ctx, ciphertext, plaintext, msg_length );
printf( "==> accu=%d p1=%d p2=%d round=%d kb=%d ivb=%d done.\n",
ctx.parm[0],ctx.parm[1],ctx.parm[2],ctx.parm[3],ctx.parm[4],ctx.parm[5]);
print_plaintext( msg_length );
ECRYPT_dump_state_key( &ctx, iv_length, key_length );
printf("\n");
}/* Hermes_decrypt ----------------------------------------------------------- */
/**
Perform loops of encryption and decryption and
check if the original plaintest is recovered again.
-
@input x
@input k
@input algo
@input pt_length
-
@global plaintext
@global ciphertext
*/
void Hermes_EncryptDecrypt( u8 x[], u8 k[], int algo, u32 pt_length )
{
int j, n, loops=15;
u8 pt[PTSIZE];
int FAILS = 0;
u32 my_ptlength;
/* u8 key[K_LENGTH];
for(j=0; j<K_LENGTH; j++){ key[j] = k[j];} */
my_ptlength = 2000;
/* my_ptlength = pt_length; */
loops=15;
for( n=0; n<=loops; n++ )
{
/* fill global plaintext and reference pt */
for( j=0; j<pt_length; j++ ){ my_plaintext[j] = n; pt[j] = n; }
Hermes_encrypt( x, k, algo, my_plaintext, my_ciphertext, my_ptlength ); /* fill ciphertext */
print_ciphertext_hex( my_ptlength );
fprintf( op, "\n");
for( j=0; j<my_ptlength; j++ ){ my_plaintext[j] = 99; }/* destroy plaintext */
printf("\n\n start decryption....\n");
fprintf(op, "\n\n start decryption....\n");
Hermes_decrypt( x, k, algo, my_ciphertext, my_plaintext, my_ptlength ); /* derive new plaintext */
for( j=0; j<my_ptlength; j++ ) /* check */
{
if( my_plaintext[j] != pt[j] ){ FAILS++; }
}
}/* for n */
printf("E/D loop test: FAILS = %d \n", FAILS );
printf("============================\n" );
printf("\n" );
}/* Hermes_EncryptDecrypt ----------------------------------------------------------- */
/**
Encryption of plaintext of length pt_length to produce test vector
Uses:
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
ECRYPT_ivsetup( &ctx, x );
ECRYPT_encrypt_bytes( &ctx, plaintext, ciphertext, msg_length );
-
@input x
@input k
@input algo
@input plaintext
@input pt_length
-
@global ciphertext
*/
void Hermes_testvector( u8 x[], u8 k[], int algo, u8 plaintext[], u32 pt_length )
{
u32 key_length;
u32 iv_length;
u32 msg_length;
ECRYPT_ctx ctx; /* create data structure */
msg_length = pt_length;
key_length = 10;
iv_length = 20;
if( algo == 2 ){ key_length = 16; iv_length = 32;}
printf("\n");
printf("Test of ECRYPT_* procedures \n");
printf(" key length = %5d \n", key_length );
printf(" iv length = %5d \n", iv_length );
printf(" pt length = %5d \n", pt_length );
print_plaintext_hex( 40 );
fprintf( op, "\n");
/* Call the ECRYPT API subroutine */
ECRYPT_keysetup( &ctx, k, key_length*8, iv_length*8);
ECRYPT_dump_key_hex( &ctx, key_length );
/* Call the ECRYPT API subroutine */
fprintf( op, "Initialization ....... \n");
ECRYPT_ivsetup( &ctx, x );
dump_IV( x, iv_length );
fprintf( op, "Initialization done. \n");
ECRYPT_dump_state_hex( &ctx, iv_length );
ECRYPT_dump_key_hex( &ctx, key_length );
/* Call the ECRYPT API subroutine */
ECRYPT_encrypt_bytes( &ctx, my_plaintext, my_ciphertext, msg_length );
print_ciphertext_hex( msg_length );
fprintf( op, "\n");
fprintf( op, "final state and key: \n");
ECRYPT_dump_state_hex( &ctx, iv_length );
ECRYPT_dump_key_hex( &ctx, key_length );
print_plaintext_hex( 40 );
fprintf( op, "\n");
fprintf( op, "\n");
printf("\n");
}/* Hermes_testvector ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------- little helpers -------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* FILL RandReg[] WITH A FRESH SET OF BYTES
USING LINEAR FEEDBACK SHIFT REGISTER USING
A SPECIFIED NUMBER OF BIT SHIFTS.
IF YOU ONLY WANT 16 BITS OF RANDOM NUMBER IT'S NOT
WORTH SHIFTING MORE THAN ABOUT 16 BITS
*/
void MakeRnd( int bits ){
int j, carryin, carryout;
while ( bits ){
carryin = 0;
for ( j=0; j<8; j++){
carryout = ( RandReg[j] & 0x80 );
RandReg[j] <<= 1;
if ( carryin ) RandReg[j]++;
carryin = carryout;
}/*for*/
/*Primitive polynomial 1 C526 F0E9 EFA3 4021 deg=64*/
if ( carryout ){
RandReg[0]^=0x21;
RandReg[1]^=0x40;
RandReg[2]^=0xA3;
RandReg[3]^=0xEF;
RandReg[4]^=0xE9;
RandReg[5]^=0xF0;
RandReg[6]^=0x26;
RandReg[7]^=0xC5;
}
bits--;
}/*while*/
}/* MakeRnd --------------------------------------------- */
unsigned char RandByte(){
MakeRnd(12);
return RandReg[0];
}/* RandByte ---------------- */
void cputs( char *s )
{
printf( "%s", s );
}/* cputs ---------------- */
/* get a character from keyboard, needs CR !!! */
char getch()
{
char test;
test = getchar();
getchar(); /* for CR */
return test;
}/* getch --------------------------------------------- */
void BinPrnt( unsigned char x){
int j;
for (j=0;j<8;j++){
if (x & 0x80) fprintf(op,"1"); else fprintf(op,"o");
x <<= 1;
}
fprintf(op," ");
}
/* write REGISTER CONTENTS to file op */
void WriteReg( char *msg, unsigned char *x, int n ){
int j;
fprintf(op, msg );
for( j=n-1; j>=0; j-- )
{
fprintf(op, "%02x", x[j] );
}
fprintf(op, " ");
for( j=n-1; j>=0; j-- ) BinPrnt( x[j] );
fprintf(op, " \n");
}
/* PRINT CHAR X IN BINARY */
void BinPrint( unsigned char x )
{
int j;
for (j=0;j<8;j++){
if (x & 0x80) cputs("1"); else cputs("o");
x <<= 1;
}
}
/* DISPLAY REGISTER CONTENTS ON CONSOLE */
void ShowReg( char *msg, unsigned char *x, int n ){
int j;
cputs(msg);
for (j=n-1;j>=0;j--){
printf("%02x",x[j]);
}
cputs(" ");
for (j=n-1;j>=0;j--) BinPrint(x[j]);
}
/* INTEGER CORRESPONDING TO HEX SYMBOL */
int HexVal(char ch){
int k;
ch=toupper(ch);
if (ch>='A'){
k=ch-'A'+10;
}
else{
k=ch-'0';
}
return k;
} /* HexVal --------------------------------- */
/* SET REGISTER x (n BYTES) ACCORDING TO
STRING s REPRESENTING HEX VALUE */
void SetReg( unsigned char *x, int n, char *s )
{
int j,k,i;
for (j=0;j<n;j++) x[j]=0;
k=0;i=n-1;
while ((s[k]) && (i>=0) && (i<n)){
i=n-1-k/2;
if (k & 1){
x[i] |= HexVal(s[k]);
} else {
j=HexVal(s[k]);
j <<= 4;
x[i] = j;
}
k++;
}
} /* SetReg ------------------------------------------- */
/* GET VALUE AS TYPED ON CONSOLE INTO REGISTER x[] */
void GetReg( char *msg, unsigned char *x, int n )
{
int j;
char s[100];
cputs(msg);
for (j=0;j<2*n;j++) cputs("-");
gets(s);
for (j=0;j<n;j++) x[j]=0;
SetReg(x,n,s);
}/* GetReg ----------------------------------- */
void SetLength( int algo )
{
if( algo == 1 ) /* Hermes8-80 key 10 bytes, state 20 bytes*/
{
KEYBYTES = 10;
KEYBITS = 80;
STATEBYTES = 23;
STATEBITS = 184;
MY_IV_LENGTH = 23;
OUTPUTBYTES = 8; /* 15 bytes hidden */
OUTPUTBITS = 64;
}
else
if( algo == 2 ) /* Hermes8-128 key 16 bytes, state 32 bytes*/
{
KEYBYTES = 16;
KEYBITS = 128;
STATEBYTES = 37;
STATEBITS = 296;
MY_IV_LENGTH = 37;
OUTPUTBYTES = 16; /* 21 bytes hidden */
OUTPUTBITS = 128;
}
else
{
printf( ALGO_NOT_VALID );
exit(1);
}
printf("\n");
printf("Algorithm = %d %s \n", algo, choice );
printf("KEYBYTES = %d \n", KEYBYTES );
printf("STATEBYTES = %d \n",STATEBYTES );
}/* SetLength ------------------------------------------------------------ */
void SetKey()
{
int j;
u8 t;
/* initialise KEY k[n]..k[0] = 0123456789..... */
t=0x01;
for( j=KEYBYTES-1; j>=0; j--) {
k[j]=t;
t+=0x22;
}/* for */
}/* SetKey ------------------------------------------------------------ */
void writeAlgorithmName()
{
fprintf(op,"%s \n", choice );
fprintf(op,"Algorithm = %2d \n\n", algo );
}
void writeAlgorithmInitRounds()
{
fprintf(op,"Number of INIT_ROUNDS = %2d \n\n", MY_INIT_ROUNDS );
}
void writeAlgorithmIvLength()
{
fprintf(op,"Number of IV bytes = %2d \n\n", MY_IV_LENGTH );
}
int GetAlgorithm( char *msg, char *msg2 )
{
int alg, N=1;
char s[2];
cputs( msg );
cputs( msg2 );
gets( s );
alg = (int) s[0] ;
alg = alg - 48 ;
printf("alg = %d \n", alg );
if( alg == 1 ) N = alg;
else if( alg == 2 ) N = alg;
else printf("ERROR !!! Algorithm not defined !!! \n");
return N;
}/* GetAlgorithm ----------------------------------- */
int GetIvLength( char *msg, char *msg2 )
{
int r, r1, N=-1;
char s[2];
s[0]='-';
s[1]='-';
cputs( msg );
cputs( msg2 );
gets( s );
printf(" s = %s \n", s );
r = (int) s[0] ;
r = r - 48 ;
r1 = (int) s[1] ;
r1 = r1 - 48 ;
if( r1 >= 0 && r1 <= 9 )
{
r = r * 10;
r = r + r1;
}
printf("rounds = %d \n", r );
if( r >= 4 && r <= 37 ) N = r;
else printf("ERROR !!! Need 4..37 !!! \n");
return N;
}/* GetIvLength----------------------------------- */
int GetInitRounds( char *msg, char *msg2 )
{
int r, r1, N=-1;
char s[2];
s[0]='-';
s[1]='-';
cputs( msg );
cputs( msg2 );
gets( s );
printf(" s = %s \n", s );
r = (int) s[0] ;
r = r - 48 ;
r1 = (int) s[1] ;
r1 = r1 - 48 ;
if( r1 >= 0 && r1 <= 9 )
{
r = r * 10;
r = r + r1;
}
printf("rounds = %d \n", r );
if( r > 0 && r <= 32 ) N = r;
else printf("ERROR !!! Need 1..32 !!! \n");
return N;
}/* GetInitRounds----------------------------------- */
int GetScRounds( char *msg, char *msg2 )
{
int j, r, r1, N=-1;
char s[4];
s[0]='-';
s[1]='-';
s[2]='-';
s[3]='-';
cputs( msg );
cputs( msg2 );
gets( s );
printf(" s = %s \n", s );
r = 0;
for( j=0; j<4; j++ )
{
r1 = (int) s[j] ;
r1 = r1 - 48 ;
if( r1 >= 0 && r1 <= 9 )
{
r = r * 10;
r = r + r1;
}
}/*for*/
printf("rounds = %d \n", r );
if( r > 0 && r <= 1000 ) N = r;
else printf("ERROR !!! Need 1..1000 !!! \n");
return N;
}/* GetScRounds----------------------------------- */
int GetPtLength( char *msg, char *msg2 )
{
int j, r, r1, N=-1;
char s[5];
s[0]='-';
s[1]='-';
s[2]='-';
s[3]='-';
s[4]='-';
cputs( msg );
cputs( msg2 );
gets( s );
printf(" s = %s \n", s );
r = 0;
for( j=0; j<5; j++ )
{
r1 = (int) s[j] ;
r1 = r1 - 48 ;
if( r1 >= 0 && r1 <= 9 )
{
r = r * 10;
r = r + r1;
}
}/*for*/
printf("rounds = %d \n", r );
if( r >= 256 && r <= 32000 ) N = r;
else printf("ERROR !!! Need 256..32000 !!! \n");
return N;
}/* GetPtLength----------------------------------- */
int GetPtPattern( char *msg, char *msg2 )
{
int j, r, r1, N=-1;
char s[3];
s[0]='-';
s[1]='-';
s[2]='-';
cputs( msg );
cputs( msg2 );
gets( s );
printf(" s = %s \n", s );
r = 0;
for( j=0; j<3; j++ )
{
r1 = (int) s[j] ;
r1 = r1 - 48 ;
if( r1 >= 0 && r1 <= 9 )
{
r = r * 10;
r = r + r1;
}
}/*for*/
printf("pattern value (dec) = %d \n", r );
if( r >= 0 && r <= 255) N = r;
else printf("ERROR !!! Need 0..255 !!! \n");
return N;
}/* GetPtPattern----------------------------------- */
/* makes sequence of 1 million bits by concatenating
responses to successive states each an increment
of the previous one.
*/
void makesequence()
{
int j;
long count=0, bytes=0, maxbytes=1000000L;
FILE *a;
maxbytes = 4 * 50000025;
maxbytes = 268500000;
a = fopen("STREAM.DAT","wb");
printf("Generating %ld bytes .... \n", maxbytes );
stream_Hermes8( x, y, algo, YES ); /* initialization of stream generator */
bytes = 0;
while (bytes<maxbytes)
{
if( algo >=1 && algo <= 2 ) stream_Hermes8( x, y, algo, NO ); else
printf( ALGO_NOT_VALID );
/* write to file */
for (j=0;j<OUTPUTBYTES;j++) putc( y[j], a );
count++;
bytes += OUTPUTBYTES;
if( bytes % 1000000 == 0 ) printf(" bytes = %ld \n", bytes );
}
fclose(a);
}/* makesequence ----------------------------------------------------------- */
void makevisiblesequence( int runs )
{
int j;
long r;
fprintf(op,"IV , initial state\n");
fprintf(op," ");
for( j=0; j<STATEBYTES;j++ ) { BinPrnt( x[j] );} /* print IV */
fprintf(op,"\n\n");
stream_Hermes8( x, y, algo, YES ); /* initialize the stream cipher */
fprintf(op,"\n");
for ( r=0; r<runs; r++ )
{
if( algo >=1 && algo <= 2 ) stream_Hermes8( x, y, algo, NO ); else
printf( ALGO_NOT_VALID );
/* write to file */
fprintf(op,"%4ld ",r);
for (j=0; j<OUTPUTBYTES;j++) { BinPrnt( y[j] );} /* print result */
fprintf(op,"\n");
}/*for*/
}/* makevisiblesequence --------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* ================== TEST SUITE FIPS_140_2 =========================== */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* T_FIPS */
long fail_FIPS_140_2( char *bit_string ) /* UK20020205 */
/* Statistical tests for randomness
returns 4000000 if bit_string fails monobit test,
30000 if it fails poker test,
200 if it fails runs test,
1 if it fails the long run test,
0 otherwise;
all fails -> code =4030201
*/
{
long result = 0;
long BIT_STRING_LENGTH = 20000L; /* fixed for FIPS 140-2 !!! */
float X1, X3, sum = 0.0, mu;
long i, index, j, k, n1 = 0;
/* for the runs test */
long B[6]= {0}, G[6] = {0}, n[16] = {0};
long max_run = 0;
long interval_lo[6] = { 2315, 1114, 527, 240, 103, 103 };
long interval_hi[6] = { 2685, 1386, 723, 384, 209, 209 };
printf("===> 1 \n" );
/* ----- monobit test ----- */
printf("monobit test .... \n");
for( i = 0; i < BIT_STRING_LENGTH; i++ )
if( bit_string[i] == 1 ) n1++;
mu = (float)( BIT_STRING_LENGTH / 2 );
X1 = 2.0 * ( n1 - mu ) * ( n1 - mu ) / mu ;
printf("===> 2 \n" );
/* ----- poker test m=4 ----- */
printf("poker test m=4 .... \n");
i = 0;
k = BIT_STRING_LENGTH / 4;
for (j = 0; j < k; j++)
{
index = 8 * bit_string[i + 3] + 4 * bit_string[i + 2]
+ 2 * bit_string[i + 1] + bit_string[i];
n[index]++;
i += 4;
}
for( i = 0; i < 16; i++ ) sum += n[i] * n[i];
X3 = 16.0 * sum / k - k ;
printf("===> 3 \n" );
/* ----- runs test ----- */
printf("runs test .... \n");
i = 0;
while (i < BIT_STRING_LENGTH) { /* search for BLOCKS */
j = 0;
while(i < BIT_STRING_LENGTH && bit_string[i] == 1) i++, j++;
if(j <= 6) B[j - 1]++; else B[5]++;
if(j > max_run) max_run = j;
while(i < BIT_STRING_LENGTH && bit_string[i] == 0) i++;
}
printf("===> 4 \n" );
i = 0;
while (i < BIT_STRING_LENGTH) { /* search for GAPS */
j = 0;
while(i < BIT_STRING_LENGTH && bit_string[i] == 0) i++, j++;
if(j <= 6) G[j - 1]++; else G[5]++;
if(j > max_run) max_run = j;
while(i < BIT_STRING_LENGTH && bit_string[i] == 1) i++;
}
printf("===> 5 \n" );
/* print out results of the tests */
printf("monobit statistic: n1 = %ld X1 = %f \n", n1, X1);
fprintf(op,"monobit statistic: n1 = %ld X1 = %f \n", n1, X1);
printf("poker test statistic: X3 = %f\n", X3);
fprintf(op,"poker test statistic: X3 = %f\n", X3);
printf("runs test:\n");
printf("# blocks\tgaps\n");
for (i = 0; i < 6; i++)
printf("%ld %4ld\t\t%4ld\n", i + 1, B[i], G[i]);
printf("long runs statistic: maxrun = %ld\n", max_run);
fprintf(op,"long runs statistic: maxrun = %ld\n", max_run);
printf("===> 6 \n" );
/* compute return value based on statistics */
for (i = 0; i < 6; i++) {
if(B[i] < interval_lo[i] || B[i] > interval_hi[i]) result = result + 20;
if(G[i] < interval_lo[i] || G[i] > interval_hi[i]) result = result + 20;
}
if( result > 0 )
{
printf("runs test FAILED \n");
fprintf(op, "runs test FAILED \n");
result = 200;
totalfail_runs_test++;
}
if ( max_run >= 26 )
{
printf("long runs test FAILED \n");
fprintf(op, "long runs test FAILED \n");
result = result + 1;
totalfail_long_runs++;
}
if (X3 <= 2.16 || X3 >= 46.17 )
{
printf("poker test FAILED \n");
fprintf(op, "poker test FAILED \n");
result = result + 30000;
totalfail_poker++;
}
if (n1 <= 9725 || n1 >= 10275 )
{
printf("monobit test FAILED \n");
fprintf(op, "monobit test FAILED \n");
result = result + 4000000;
total_fail_monobit++;
}
return result;
} /* fail_FIPS_140_2 ------------------------------------------------------- */
/* C_FIPS */
void doFIPS1402_crunch() /* UK20020205 */
{
/*char bit_string[20032]; UK 9.Jan.2004 +32 because of 64 bit states */
char bit_string[20224]; /* UK 20.Feb.2005 because of 256 bit states */
long result;
unsigned char z;
int bit;
int j, i, jj, t, fail=0, ntest=100;
long count, bits=0, maxbits=20000;
int j_start, bits_inc;
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "====> crunch: FIPS 140-2 Random Number Generator Quality Test <====\n\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "Key is unchanged for every FIPS test; IV is incremented from zero start value.\n" );
fprintf(op, "The initialization is run as often as 20000 bits are collected.\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
j_start = OUTPUTBYTES - 1;
bits_inc = OUTPUTBITS;
for (j=0;j<X_LENGTH;j++) x[j]=0; /* default x = 0x0000000000 */
for( t = 1; t <= ntest; t++ ) /* perform 100 tests ... */
{
count = 0;
printf("Generating %ld bits .... \n", maxbits );
bits = 0;
while ( bits < maxbits ){
if( algo >=1 && algo <= 2 ) crunch_Hermes8( x, y, k, algo ); else
printf( ALGO_NOT_VALID );
/* printf("crunch %02x %02x %02x %02x %02x \n",
y[4], y[3], y[2], y[1], y[0] ); */
/* write to long bit_string */
for ( j=j_start; j>=0; j-- )
{
z = y[j];
for ( jj=0; jj<8; jj++ )
{
if( z & 0x80 ) { bit = 1; }
else { bit = 0; }
/* printf(" %d %d ", j, jj );
printf(" count = %ld bit = %d \n", count, bit ); */
bit_string[ count ] = bit ;
count++;
z <<= 1;
}/*for*/
}/*for*/
/* INC x[] for next crunch() */
j=0;
do{
x[j]++;
i=x[j];
j++;
} while (!i);
bits += bits_inc;
if( bits % 4000 == 0 ) printf(" bits = %ld %ld \n", bits, count );
if( bits % 6400 == 0 ) printf(" bits = %ld %ld \n", bits, count );
}/*while*/
printf("Test: %d \n", t );
printf("Generated %ld bits .... \n", maxbits );
fprintf(op,"Test: %d \n", t );
fprintf(op,"Generated %ld bits .... \n", maxbits );
/* check the bit string now ... */
result = fail_FIPS_140_2( bit_string );
if( result )
{ printf("----- FAILED FIPS_140_2 result = %8ld\n\n", result );
fail++;
fprintf(op,"----- FAILED FIPS_140_2 result = %8ld\n\n", result );
}
else printf("+++++ PASSED FIPS_140_2 result = %8ld\n\n", result );
}/* for ntest */
printf("\n ====> total number of FAIL = %d !!! (%d) \n", fail, ntest );
fprintf(op,"\n ====> FIPS_140_2: total number of FAIL = %d !!! (%d) \n\n", fail, ntest );
printf("\n *** FIPS 140-2 done. ***\n" );
}/* doFIPS1402_crunch ------------------------------------------------------- */
/*
Run t=ntest FIPS140-2 tests.
For given IV=x and Key=k we perform init_Hermes8.
For every t we keep these IV and Key and run the stream_Hermes8
again and again in order to produce 20000 random bits
*/
/* S_FIPS */
void doFIPS1402_stream( int n_tests )
{
/* char bit_string[20032]; */
char bit_string[20224]; /* UK 20.Feb.2005 because of 256 bit states */
long result;
unsigned char z;
int bit;
int j, jj, t, fail=0, ntest=100;
long count, bits=0, maxbits=20000;
int n;
u32 pt_length;
ntest = n_tests; /* variable number of FIPS tests ... */
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "====> stream: FIPS 140-2 Random Number Generator Quality Test <====\n\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "IV is unchanged for every FIPS test.\n" );
fprintf(op, "The stream subroutine is run as often as 20000 bits are collected.\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
/* for (j=0;j<X_LENGTH;j++) x[j]=0; default x = 0x0000000000 */
stream_Hermes8( x, y, algo, YES ); /* initialize the stream cipher */
printf( "Initialization of stream cipher done. \n");
for( t = 1; t <= ntest; t++ ) /* perform e.g. 100 tests ... */
{
count = 0;
pt_length = 0;
printf("Generating %ld bits .... \n", maxbits );
bits = 0;
while ( bits < maxbits ){
if( algo >=1 && algo <= 2 ) stream_Hermes8( x, y, algo, NO ); else
printf( ALGO_NOT_VALID );
for( n=0; n<OUTPUTBYTES; n++)
{
my_ciphertext[pt_length] = y[n];
pt_length++;
}
/* write to long bit_string */
for ( j=0; j<OUTPUTBYTES; j++ )
{
z = y[j];
for ( jj=0; jj<8; jj++ )
{
if( z & 0x80 ) { bit = 1; }
else { bit = 0; }
/* printf(" %d %d ", j, jj );
printf(" count = %ld bit = %d \n", count, bit ); */
bit_string[ count ] = bit ;
count++;
z <<= 1;
}/*for*/
}/*for*/
bits += OUTPUTBITS;
if( bits % 4000 == 0 ) printf(" bits = %ld %ld \n", bits, count );
if( bits % 6400 == 0 ) printf(" bits = %ld %ld \n", bits, count );
}/*while*/
printf("Test: %d \n", t );
printf("Generated %ld bits .... \n", maxbits );
fprintf(op,"Test: %d \n", t );
fprintf(op,"Generated %ld bits .... \n", maxbits );
pt_length = 2500;
printf(" pt_length = %d \n", pt_length );
for( n=0; n<128; n++ ){ printf( " %2x", my_ciphertext[n]); } /* dump ciphertext */
printf("\n");
printf(" pt_length = %d \n", pt_length );
for( n=pt_length-128; n<pt_length; n++ ){ printf( " %2x", my_ciphertext[n]); } /* dump ciphertext */
printf("\n");
fprintf(op," pt_length = %d first 128 bytes...\n", pt_length );
for( n=0; n<128; n++ ){ fprintf(op, " %2x", my_ciphertext[n]); } /* dump ciphertext */
fprintf(op,"\n");
fprintf(op," pt_length = %d last 128 bytes...\n", pt_length );
for( n=pt_length-128; n<pt_length; n++ ){ fprintf(op, " %2x", my_ciphertext[n]); } /* dump ciphertext */
fprintf(op,"\n");
/*
fprintf(op,"\n");
fprintf(op,"\n");
for( n=0; n<2500; n++ )
{
fprintf(op, " %2x", my_ciphertext[n]);
if( n % 50 == 49 ){ fprintf(op,"\n"); }
}
exit(1);
*/
/* check the bit string now ... */
result = fail_FIPS_140_2( bit_string );
if( result )
{ printf("----- FAILED FIPS_140_2 result = %8ld\n\n", result );
fail++;
fprintf(op,"----- FAILED FIPS_140_2 result = %8ld\n\n", result );
}
else printf("+++++ PASSED FIPS_140_2 result = %8ld\n\n", result );
}/* for ntest */
printf("\n ====> total number of FAIL = %d !!! (%d) \n", fail, ntest );
fprintf(op,"\n ====> FIPS_140_2: total number of FAIL = %d !!! (%d) \n\n", fail, ntest );
}/* doFIPS1402_stream ------------------------------------------------------- */
/*
Run N=longtest loops in order to run t=ntest FIPS140-2 tests.
For every N we define a new randome set of IV and Key values
and perform init_Hermes8.
For every t we keep these IV and Key and run the stream_Hermes8
again and again in order to produce 20000 random bits
*/
/* LS_FIPS */
void doFIPS1402_longstream() /* UK20050214 */
{
/* char bit_string[20032]; */
char bit_string[20224]; /* UK 20.Feb.2005 because of 256 bit states */
long result;
unsigned char z;
int bit;
int j, jj;
int t, ntest=100, fail;
int total_fail=0, longtest=50, N;
long count, bits=0, maxbits=20000;
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "====> longstream: FIPS 140-2 Random Number Generator Quality Test <====\n\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "IV is unchanged for every FIPS test; key is changeing automatically.\n" );
fprintf(op, "The stream subroutine is run as often as 20000 bits are collected.\n" );
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
totalfail_runs_test=0;
totalfail_long_runs=0;
totalfail_poker=0;
total_fail_monobit=0;
for( N = 1; N <=longtest; N++ )
{
/* apply random IV, random Key */
for (j=0;j<X_LENGTH;j++){ x[j] = RandByte(); }
for (j=0;j<K_LENGTH;j++){ k[j] = RandByte(); }
printf("RNG: x0= %3d k0= %3d ", x[0], k[0] );
fail = 0;
stream_Hermes8( x, y, algo, YES ); /* initialize the stream cipher */
printf( "Initialization of stream cipher done. \n");
for( t = 1; t <= ntest; t++ ) /* perform e.g. 100 tests ... */
{
count = 0;
printf("Generating %ld bits .... \n", maxbits );
bits = 0;
while ( bits < maxbits ){
if( algo >=1 && algo <= 2 ) stream_Hermes8( x, y, algo, NO ); else
printf( ALGO_NOT_VALID );
/* printf("crunch %02x %02x %02x %02x %02x ntest= %d\n",
y[4], y[3], y[2], y[1], y[0] , ntest ); */
/* write to long bit_string */
for ( j=0; j<OUTPUTBYTES; j++ )
{
z = y[j];
for ( jj=0; jj<8; jj++ )
{
if( z & 0x80 ) { bit = 1; }
else { bit = 0; }
/* printf(" %d %d ", j, jj );
printf(" count = %ld bit = %d \n", count, bit ); */
bit_string[ count ] = bit ;
count++;
z <<= 1;
}/*for*/
}/*for*/
bits += OUTPUTBITS;
if( bits % 4000 == 0 ) printf(" bits = %ld %ld \n", bits, count );
if( bits % 6400 == 0 ) printf(" bits = %ld %ld \n", bits, count );
}/*while*/
printf("Generated %ld bits .... \n", maxbits );
fprintf(op,"Test: %d \n", t );
fprintf(op,"Generated %ld bits .... \n", maxbits );
/* check the bit string now ... */
result = fail_FIPS_140_2( bit_string );
if( result )
{ printf("----- FAILED FIPS_140_2 result = %8ld\n\n", result );
fail++;
total_fail++;
fprintf(op,"----- FAILED FIPS_140_2 result = %8ld\n\n", result );
}
else printf("+++++ PASSED FIPS_140_2 result = %8ld\n\n", result );
}/* for ntest */
printf(" N = %d \n", N );
fprintf(op, " N = %d \n", N );
printf("\n ====> number of FAILs = %d !!! of(%d) \n", fail, ntest );
fprintf(op,"\n ====> FIPS_140_2: number of FAILs = %d !!! of(%d) \n\n", fail, ntest );
}/*for N */
printf("\n");
printf(" Number of FAILs : %d of total tests %d \n", total_fail, longtest*ntest );
fprintf(op,"\n");
fprintf(op," Number of FAILs : %d of total test %d \n", total_fail, longtest*ntest );
printf(" Number of runs test FAILs : %d \n", totalfail_runs_test );
printf(" Number of long runs FAILs : %d \n", totalfail_long_runs );
printf(" Number of poker tst FAILs : %d \n", totalfail_poker );
printf(" Number of mono bit FAILs : %d \n", total_fail_monobit );
fprintf(op," Number of runs test FAILs : %d \n", totalfail_runs_test );
fprintf(op," Number of long runs FAILs : %d \n", totalfail_long_runs );
fprintf(op," Number of poker tst FAILs : %d \n", totalfail_poker );
fprintf(op," Number of mono bit FAILs : %d \n", total_fail_monobit );
}/* doFIPS1402_longstream ------------------------------------------------------- */
/*
Run t=ntest FIPS140-2 tests.
For given IV=x and Key=k we perform ECRYPT_encryption_bytes().
The plaintext is set to zero !
For every t we keep the ciphertext and take 2500 bytes to form
the 20000 bit stream.
*/
/* A_FIPS */
void doFIPS1402_ECRYPTstream( int n_tests )
{
/* char bit_string[20032]; */
char bit_string[20224]; /* UK 20.Feb.2005 because of 256 bit states */
long result;
unsigned char z;
int bit;
int jj, t, fail=0, ntest=100;
long count, bits=0, maxbits=20000;
u32 pos, n;
u32 pt_length;
ntest = n_tests; /* variable number of FIPS test ... */
pt_length = 2500 * ntest;
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "====> ECRYPT stream: FIPS 140-2 Random Number Generator Quality Test <====\n\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "IV and key are unchanged for every FIPS test.\n" );
fprintf(op, "Number of tests: %d \n", ntest );
fprintf(op, "The stream subroutine is run once for %d bytes.\n", pt_length );
fprintf(op, "\n" );
fprintf(op, "\n" );
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
for( n=0; n<pt_length; n++ ){ my_plaintext[n] = 0; } /* reset plaintext */
/*for( n=0; n<pt_length; n++ ){ printf( " %d", plaintext[n]); } dump plaintext */
Hermes_encrypt( x, k, algo, my_plaintext, my_ciphertext, pt_length ); /* fill ciphertext */
printf( "Initialization of ciphertext done. \n");
printf(" pt_length = %d \n", pt_length );
for( n=0; n<128; n++ ){ printf( " %2x", my_ciphertext[n]); } /* dump ciphertext */
printf("\n");
printf(" pt_length = %d \n", pt_length );
for( n=pt_length-128; n<pt_length; n++ ){ printf( " %2x", my_ciphertext[n]); } /* dump ciphertext */
printf("\n");
fprintf(op," pt_length = %d first 128 bytes...\n", pt_length );
for( n=0; n<128; n++ ){ fprintf(op, " %2x", my_ciphertext[n]); } /* dump ciphertext */
fprintf(op,"\n");
fprintf(op," pt_length = %d last 128 bytes...\n", pt_length );
for( n=pt_length-128; n<pt_length; n++ ){ fprintf(op, " %2x", my_ciphertext[n]); } /* dump ciphertext */
fprintf(op,"\n");
/*
fprintf(op,"\n");
fprintf(op,"\n");
for( n=0; n<2500; n++ )
{
fprintf(op, " %2x", my_ciphertext[n]);
if( n % 50 == 49 ){ fprintf(op,"\n"); }
}
exit(0);
*/
pos = 0; /* position in ciphertext */
for( t = 1; t <= ntest; t++ ) /* perform e.g. 100 tests ... */
{
count = 0;
printf("Taking %ld bits .... \n", maxbits );
bits = 0;
while ( bits < maxbits )
{
z = my_ciphertext[pos];
for ( jj=0; jj<8; jj++ )
{
if( z & 0x80 ) { bit = 1; }
else { bit = 0; }
/* printf(" %d %d ", j, jj );
printf(" count = %ld bit = %d \n", count, bit ); */
bit_string[ count ] = bit ;
count++;
z <<= 1;
}/*for*/
pos++;
bits += 8;
if( bits % 4000 == 0 ) printf(" bits = %ld %ld \n", bits, count );
}/*while*/
printf("Test: %d position: %d\n", t, pos );
printf("Generated %ld bits .... \n", maxbits );
fprintf(op,"Test: %d \n", t );
fprintf(op,"Generated %ld bits .... \n", maxbits );
/* check the bit string now ... */
result = fail_FIPS_140_2( bit_string );
if( result )
{ printf("----- FAILED FIPS_140_2 result = %8ld\n\n", result );
fail++;
fprintf(op,"----- FAILED FIPS_140_2 result = %8ld\n\n", result );
}
else printf("+++++ PASSED FIPS_140_2 result = %8ld\n\n", result );
}/* for ntest */
printf("\n ====> total number of FAIL = %d !!! (%d) \n", fail, ntest );
fprintf(op,"\n ====> FIPS_140_2: total number of FAIL = %d !!! (%d) \n\n", fail, ntest );
}/* doFIPS1402_ECRYPTstream ------------------------------------------------------- */
/*
Run t=ntest FIPS140-2 tests.
For given IV=x and Key=k we perform ECRYPT_encryption_bytes().
The plaintext is set to zero !
For every t we keep the ciphertext and take 2500 bytes to form
the 20000 bit stream.
*/
/* B_FIPS */
void doFIPS1402_ECRYPTlongstream() /* UK20050410 */
{
char bit_string[20224];
long result;
unsigned char z;
int bit;
int j, jj, t, fail=0, ntest=100;
long count, bits=0, maxbits=20000;
u32 pos, n;
u32 pt_length;
int total_fail=0, longtest=50, N;
pt_length = 2500 * ntest;
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "====> ECRYPT longstream: FIPS 140-2 Random Number Generator Quality Test <====\n\n" );
fprintf(op, "\n" );
fprintf(op, "\n" );
fprintf(op, "IV and key are random, but unchanged for every 100 FIPS tests.\n" );
fprintf(op, "Number of tests: %d \n", ntest );
fprintf(op, "The stream subroutine is run once for %d bytes.\n", pt_length );
fprintf(op, "\n" );
fprintf(op, "\n" );
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
totalfail_runs_test=0;
totalfail_long_runs=0;
totalfail_poker=0;
total_fail_monobit=0;
for( N = 1; N <=longtest; N++ )
{
/* apply random IV, random Key */
for (j=0;j<X_LENGTH;j++){ x[j] = RandByte(); }
for (j=0;j<K_LENGTH;j++){ k[j] = RandByte(); }
printf("RNG: x0= %3d k0= %3d ", x[0], k[0] );
fail = 0;
for( n=0; n<pt_length; n++ ){ my_plaintext[n] = 0; } /* reset plaintext */
/*for( n=0; n<pt_length; n++ ){ printf( " %d", plaintext[n]); } dump plaintext */
Hermes_encrypt( x, k, algo, my_plaintext, my_ciphertext, pt_length ); /* fill ciphertext */
printf( "Initialization of ciphertext done. \n");
/* printf(" pt_length = %d \n", pt_length );
for( n=0; n<128; n++ ){ printf( " %d", ciphertext[n]); } */ /* dump ciphertext */
/* printf(" pt_length = %d \n", pt_length );
for( n=pt_length-128; n<pt_length; n++ ){ printf( " %d", ciphertext[n]); } */ /* dump ciphertext */
/* exit(0); */
pos = 0; /* position in ciphertext */
for( t = 1; t <= ntest; t++ ) /* perform e.g. 100 tests ... */
{
count = 0;
printf("Taking %ld bits .... \n", maxbits );
bits = 0;
while ( bits < maxbits )
{
z = my_ciphertext[pos];
for ( jj=0; jj<8; jj++ )
{
if( z & 0x80 ) { bit = 1; }
else { bit = 0; }
/* printf(" %d %d ", j, jj );
printf(" count = %ld bit = %d \n", count, bit ); */
bit_string[ count ] = bit ;
count++;
z <<= 1;
}/*for*/
pos++;
bits += 8;
if( bits % 4000 == 0 ) printf(" bits = %ld %ld \n", bits, count );
}/*while*/
printf("Test: %d position: %d\n", t, pos );
printf("Generated %ld bits .... \n", maxbits );
fprintf(op,"Test: %d \n", t );
fprintf(op,"Generated %ld bits .... \n", maxbits );
/* check the bit string now ... */
result = fail_FIPS_140_2( bit_string );
if( result )
{ printf("----- FAILED FIPS_140_2 result = %8ld\n\n", result );
fail++;
total_fail++;
fprintf(op,"----- FAILED FIPS_140_2 result = %8ld\n\n", result );
}
else printf("+++++ PASSED FIPS_140_2 result = %8ld\n\n", result );
}/* for ntest */
printf(" N = %d \n", N );
fprintf(op, " N = %d \n", N );
printf("\n ====> number of FAIL = %d !!! (%d) \n", fail, ntest );
fprintf(op,"\n ====> FIPS_140_2: number of FAIL = %d !!! (%d) \n\n", fail, ntest );
}/*for N */
printf("\n");
printf(" Number of FAILs : %d of total tests %d \n", total_fail, longtest*ntest );
fprintf(op,"\n");
fprintf(op," Number of FAILs : %d of total test %d \n", total_fail, longtest*ntest );
printf(" Number of runs test FAILs : %d \n", totalfail_runs_test );
printf(" Number of long runs FAILs : %d \n", totalfail_long_runs );
printf(" Number of poker tst FAILs : %d \n", totalfail_poker );
printf(" Number of mono bit FAILs : %d \n", total_fail_monobit );
fprintf(op," Number of runs test FAILs : %d \n", totalfail_runs_test );
fprintf(op," Number of long runs FAILs : %d \n", totalfail_long_runs );
fprintf(op," Number of poker tst FAILs : %d \n", totalfail_poker );
fprintf(op," Number of mono bit FAILs : %d \n", total_fail_monobit );
}/* doFIPS1402_ECRYPTslongtream ------------------------------------------------------- */
void showparams( char *msg ){
printf("%s\n\n",msg);
printf("runs/experiment = %4d\n",EXPERIMENTSIZE);
printf("experiments = %4d\n",EXPERIMENTS);
printf("significance level = %4d%%\n",LOPC);
}/* showparams ------------------------------------- */
/* writes to file */
void writeparams(char *msg){
fprintf(op,"\n\n\n====> %s <====\n\n",msg);
fprintf(op,"runs/experiment = %4d\n",EXPERIMENTSIZE);
fprintf(op,"experiments = %4d\n",EXPERIMENTS);
fprintf(op,"significance level = %4d%%\n\n",LOPC);
}
/* -------------------------------------------------------- */
/* ----------test sensitivity to challenge or key --------- */
/* -------------------------------------------------------- */
/* T_SENS */
/*
Csens = 0 => do Challenge-Sensitivity Test
Csens = 1 => do k[] Key-Sensitivity Test
Toggle the bits of x one at a time
and note which bits of y change.
------------------------------------------*/
void TestSensitivities( int Csens ){
#define MAX_I 296
#define MAX_J 256
int h[MAX_I][MAX_J], highs[MAX_I][MAX_J], lows[MAX_I][MAX_J];
long runs = 0;
int wrd,i,j,bits;
int blocks=0;
int BlockSize = EXPERIMENTSIZE;
int inblock=0;
int maxblocks = EXPERIMENTS;
float chisq;
unsigned char msk, yy[Y_LENGTH];
int index;
int histogram[26];
long count = 0;
long mincount, maxcount;
long avgcount = 0;
if (Csens==0){
bits = STATEBITS;
showparams("State-Sensitivity Test");
}
if (Csens==1){
bits = KEYBITS;
showparams("k[] Key-Sensitivity Test");
}
/* first index i for stepping over key bits or state bits, vertical */
/* second index j for stepping over output bits , horizontal */
/* reset all arrays */
for (i=0;i<MAX_I;i++) /*UK20040502*/
for (j=0;j<MAX_J;j++)
h[i][j]= highs[i][j]= lows[i][j]= 0;
mincount = 9999999L;
maxcount = -1;
do{
runs++;
if( runs % EXPERIMENTSIZE == 0 )
printf(" runs = %ld \n", runs );
/* setup random state */
for( j=0; j<STATEBYTES; j++) x[j] = RandByte();
/* setup random key */
for( j=0; j<KEYBYTES; j++ ) k[j] = RandByte();
/* find yy[] as a reference */
if( algo >=1 && algo <= 2 ) crunch_Hermes8( x, yy, k, algo ); else
printf( ALGO_NOT_VALID );
/* toggle the bits of x (resp. k) one at a time
and note which bits of y change */
for( i=0; i<bits; i++){
wrd=i/8;
msk=1 << (i & 7);
if (Csens==0){
/* toggle bit j */
x[wrd] ^= msk;
/* crunch into y[] for comparison with yy[] */
if( algo >=1 && algo <= 2 ) crunch_Hermes8( x, y, k, algo ); else
printf( ALGO_NOT_VALID );
/* restore x[] */
x[wrd] ^= msk;
}
if (Csens==1){
/* toggle bit j in k[] */
k[wrd] ^= msk;
/* crunch into y[] for comparison with yy[] */
if( algo >=1 && algo <= 2 ) crunch_Hermes8( x, y, k, algo ); else
printf( ALGO_NOT_VALID );
/* restore k[] */
k[wrd] ^= msk;
}
wrd=0;
msk=1;
j=0;
while( j<OUTPUTBITS ){
if( (y[wrd] ^ yy[wrd]) & msk ){ h[i][j]++; count++; }
/* fprintf(op,"%d %d %d \n", i, j, h[i][j] ); */
msk <<= 1;
if( !msk ){
msk=1;
wrd++;
}
j++;
}/*while j */
}/* for i */
inblock++;
if( inblock==BlockSize ){
blocks++;
inblock=0;
/* fprintf(op,"count = %d \n", count ); */
avgcount += count;
if( count > maxcount ) maxcount = count;
if( count < mincount ) mincount = count;
count = 0;
/* showprogress( blocks, maxblocks ); */
for( i=0; i<bits; i++ )
for( j=0; j<OUTPUTBITS; j++ ){
chisq = ( 2*h[i][j] - BlockSize );
chisq = chisq*chisq/BlockSize;
/* fprintf(op,"%d %d %d \n", i, j, h[i][j] ); */
if( chisq > CHISQ_HI ) highs[i][j]++;
if( chisq < CHISQ_LO ) lows[i][j]++;
h[i][j]=0;
}/*for*/
}/*if*/
} while( blocks < maxblocks );
/* print results */
if (Csens==0) writeparams("State-Sensitivity Test");
if (Csens==1) writeparams("k[] Key-Sensitivity Test");
writeAlgorithmName();
writeAlgorithmInitRounds();
writeAlgorithmIvLength();
fprintf(op,"mincount = %ld \n", mincount );
fprintf(op,"maxcount = %ld \n", maxcount );
fprintf(op,"avgcount = %ld \n", avgcount/EXPERIMENTS );
fprintf(op,"expected = %d \n", OUTPUTBITS*bits*EXPERIMENTSIZE/2 );
fprintf(op,"experiments = %d \n", EXPERIMENTS );
fprintf(op,"\n\n" );
fprintf(op,"percent highs\n\n ");
for (j=0;j<OUTPUTBITS;j++) fprintf(op,"%3d",j);
for (i=0;i<bits;i++){
fprintf(op,"\n%3d",i);
if (blocks) for (j=0;j<OUTPUTBITS;j++) fprintf(op,"%3.0f",100.0*highs[i][j]/blocks);
}
fprintf(op,"\n\npercent lows\n\n ");
for (j=0;j<OUTPUTBITS;j++) fprintf(op,"%3d",j);
for (i=0;i<bits;i++){
fprintf(op,"\n%3d",i);
if (blocks) for (j=0;j<OUTPUTBITS;j++) fprintf(op,"%3.0f",100.0*lows[i][j]/blocks);
}
/* make histogram on highs */
fprintf(op,"\n\nHistogram for percent highs\n\n");
for( index=0; index<26; index++ ){ histogram[index] = 0; }
for( j=0; j<OUTPUTBITS; j++ )
for( i=0; i<bits; i++ )
{
index = highs[i][j];
if( index >25 ){ index = 25; }
histogram[index]++;
}
for( index=0; index<26; index++ )
{
fprintf(op, "%2d %4d ", index, histogram[index] );
for( j=0; j<(int)(0.5+histogram[index]/10.0); j++ ){ fprintf(op, "*" ); }
fprintf(op, "\n" );
}
if( histogram[25] > 0 )
fprintf(op, "====> HIGH-25 : %d\n", histogram[25] );
/* make histogram on lows */
fprintf(op,"\n\nHistogram for percent lows\n\n");
for( index=0; index<26; index++ ){ histogram[index] = 0; }
for( j=0; j<OUTPUTBITS; j++ )
for( i=0; i<bits; i++ )
{
index = lows[i][j];
if( index >25 ){ index = 25; }
histogram[index]++;
}
for( index=0; index<26; index++ )
{
fprintf(op, "%2d %4d ", index, histogram[index] );
for( j=0; j<(int)(0.5+histogram[index]/10.0); j++ ){ fprintf(op, "*" ); }
fprintf(op, "\n" );
}
if( histogram[0] > 0 )
fprintf(op, "====> LOW-0 : %d\n", histogram[0] );
}/* TestSensitivities --------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------- M A I N ------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* ------------------------ MAIN with crude menu -------------------------*/
int main()
{
unsigned char test, done=0;
int j, escseq;
u32 n;
j = LOPC; /* either 5% or 10% possible !!! */
if (j>6){
CHISQ_LO=CHISQ_90;
CHISQ_HI=CHISQ_10;
} else {
CHISQ_LO=CHISQ_95;
CHISQ_HI=CHISQ_05;
}
algo = 1;
SetLength( algo );
SetKey();
/* initialize the pseudo random generator */
for( j=0; j<8; j++ ) RandReg[j] = 0;
RandReg[0]=1;
/* initialize plaintext */
for( n=0; n<PTSIZE; n++ ) my_plaintext[n] = 0;
/* initialize ciphertext */
for( n=0; n<PTSIZE; n++ ) my_ciphertext[n] = 99;
op=fopen("RESULTS.TXT","wb");
/* PRESENT SIMPLE MENU TO USER */
while( !done )
{
cputs(credits);
cputs("\n\n");
/* SHOW STATE OF KEY[] AND REG[] */
printf( " alg = %d %s\n", algo, choice );
ShowReg(" k[] = ", k, KEYBYTES);cputs("\n");
ShowReg(" x[] = ", x, STATEBYTES);cputs("\n");
ShowReg(" y[] = ", y, OUTPUTBYTES);cputs("\n");
printf( " PT_LENGTH = %4d \n", MY_PT_LENGTH );
printf( " IV_LENGTH = %4d \n", MY_IV_LENGTH );
printf( " INIT_ROUNDS = %4d \n", MY_INIT_ROUNDS );
printf( " SC_ROUNDS = %4d \n", MY_SC_ROUNDS );
/* SHOW MENU OPTIONS */
cputs("=== choose ===\n");
cputs(" Z choose algorithm \n");
cputs(" K|X choose k[] | x[] \n");
cputs(" E|D Perform ECRYPT Stream Cipher En|Decryption \n");
cputs(" L Perform ECRYPT Stream Cipher LoopCheck \n");
cputs(" A Perform ECRYPT FIPS 140-2 stream test with 100 * 20,000 bits \n");
cputs(" B Perform ECRYPT FIPS 140-2 stream test with 50 * (100 * 20,000 bits) \n");
cputs(" 1 Set MY_PT_LENGTH 3 Set MY_IV_LENGTH\n");
cputs(" 6 Set MY_INIT_ROUNDS 7 Set MY_SC_ROUNDS\n");
cputs(" H State-Sensitivities test I Key-Sensitivities test\n");
cputs(" T Test Vectors with ECRYPT Stream Cipher Encryption \n");
cputs(" 4 Set Plaintext pattern\n");
if( algo == 1 ) cputs(" C Crunch_Hermes8( x, y, k, 1 )\n");
if( algo == 2 ) cputs(" C Crunch_Hermes8( x, y, k, 2 )\n");
cputs(" Q Perform FIPS 140-2 crunch test with 100 * 20,000 bits \n");
cputs(" S Perform FIPS 140-2 stream test with 100 * 20,000 bits \n");
cputs(" R Perform FIPS 140-2 stream test with 50 * (100 * 20,000 bits) \n");
cputs(" M Make binary STREAM.DAT for external testing (n=12e6)\n");
cputs(" N Make visible stream\n");
ShowReg(" RandReg = ", RandReg, 8 );printf("\n");
cputs(" 5 Set RandomGenerator\n");
cputs(" 8 Perform FIPS 140-2 stream test with 1 * 20,000 bits \n");
cputs(" 9 Perform ECRYPT FIPS 140-2 stream test with 1 * 20,000 bits \n");
cputs(" Esc|. Exit\n");
cputs("\n");
cputs(" Choice =[ ]");
/* GET USER'S CHOICE */
do {
escseq = 0;
test = getch();
if ( !test ) { escseq=1; getch();}
} while ( escseq );
fprintf(op, "Command chosen: %c \n", test );
test = toupper(test);
/* printf("MAXINT = %d \n", MAX_INT ); */
/* EXECUTE USER'S CHOICE */
switch (test){
case 'Z': algo = GetAlgorithm( "Algorithm = ? ", choice );
SetLength( algo );
SetKey();
break;
case 'K': GetReg("k = ", k, KEYBYTES); break;
case 'X': GetReg("x = ",x,STATEBYTES); break;
case 'C': if( algo==1) { crunch_Hermes8( x, y, k, 1 ); } else
if( algo==2) { crunch_Hermes8( x, y, k, 2 ); } else
if( algo==99) { crunch_Hermes8( x, y, k, 99 ); };
break;
case 'E': Hermes_encrypt( x, k, algo, my_plaintext, my_ciphertext, MY_PT_LENGTH );
break;
case 'D': Hermes_decrypt( x, k, algo, my_ciphertext, my_plaintext, MY_PT_LENGTH );
break;
case 'L': Hermes_EncryptDecrypt( x, k, algo, MY_PT_LENGTH );
break;
case 'A': doFIPS1402_ECRYPTstream( 100 );
printf(" doFIPS1402_ECRYPTstream done. \n");
break; /* UK20050408 */
case 'B': doFIPS1402_ECRYPTlongstream();
printf(" doFIPS1402_ECRYPTlongstream done. \n");
break; /* UK20050410 */
case 'H': TestSensitivities(0); break;
case 'I': TestSensitivities(1); break;
case 'T': Hermes_testvector( x, k, algo, my_plaintext, MY_PT_LENGTH );
break;
case 'M': makesequence();break;
case 'N': makevisiblesequence( MY_SC_ROUNDS );break;
case 'Q': doFIPS1402_crunch();
printf(" doFIPS1402_crunch done. \n");
break; /* UK20020205 */
case 'S': doFIPS1402_stream( 100 );
printf(" doFIPS1402_stream done. \n");
break; /* UK20050213 */
case 'R': doFIPS1402_longstream();
printf(" doFIPS1402_longstream done. \n");
break; /* UK20050214 */
case '1': MY_PT_LENGTH = GetPtLength( "PT_LENGTH = ? ", "[256..32000]" );
break;
case '3': MY_IV_LENGTH = GetIvLength( "IV_LENGTH = ? ", "[4..37]" );
break;
case '4': MY_PT_PATTERN = GetPtPattern( "PT_PATTERN = ? ", "[0..255]" );
/* initialize plaintext */
for( n=0; n<PTSIZE; n++ ) my_plaintext[n] = (u8)MY_PT_PATTERN;
break;
case '6': MY_INIT_ROUNDS = GetInitRounds( "InitRounds = ? ", "[1..32]" );
break;
case '7': MY_SC_ROUNDS = GetScRounds( "StreamCipherRounds = ? ", "[1..1000]" );
break;
case '8': doFIPS1402_stream( 1 );
printf(" doFIPS1402_stream done. \n");
break; /* UK20050527 */
case '9': doFIPS1402_ECRYPTstream( 1 );
printf(" doFIPS1402_ECRYPTstream done. \n");
break; /* UK20050527 */
case '5': GetReg("r = ", RandReg, 8);break;
case 27: done=1;break;
case '.': done=1;break;
}/*switch*/
/* fclose( op );
op=fopen("RESULTS.TXT","wa"); */
}/*while*/
return 0;
}/* main */
/* ----------------------------------- end ------------------------------- */