📄 gentest.c
字号:
/* parse up to closing bracket or a maximum of 5 inputs */
for( i = 1 ; *p != ')' && i < 6 ; ++i )
{
if( *p == '#' )
p = decimal_in( p + 1, cnt + i );
else
p = hexadecimal_in(p, cnt + i);
while(*p && ( *p == ' ' || *p == '\t' || *p == ',' ) )
++p;
}
if( *p == ')' && i < 7 ) /* good input */
cnt[0] = retv = i - 1;
else /* bad input - remove to next closing bracket */
{
while( *p && *p != ')' )
++p;
if(*p)
++p;
}
*cp = p;
return retv;
}
int init_sequence( char **cp, unsigned char val[], long long int cnt[5], int *ll )
{ int retv, i;
(*cp)++; /* step past opening bracket */
/* input the values in the bracket term */
retv = get_loop_vars( cp, cnt, 1 );
*ll = (int)(cnt[1]);
switch( retv )
{
case 1:
/* (nn) - nn random bytes */
block_rndfill( val, (unsigned long)(cnt[1]) );
/* step past closing bracket */
(*cp)++;
break;
case 2:
/* (nn,hh) - nn bytes each of value hh */
cnt[3] = 0;
case 3:
/* (nn,hh,hi) - nn bytes of value hh, hh + hi, hh + 2 * hi, ... */
for( i = 0; i < cnt[1]; ++i )
{
val[i] = (unsigned char)(cnt[2]);
cnt[2] += cnt[3];
}
/* step past closing bracket */
(*cp)++;
break;
case 4:
/* (nn,v1,v2,v3=1..4) - signal with negative cnt[5] value */
cnt[5] = -cnt[4];
case 5:
/* (nn,v1,v2,v3,v4) */
/* signal a sequence of values */
return 2;
default:
/* signal no value input */
return 0;
}
return 1;
}
void reverse_seq(unsigned char *lo, unsigned char *hi)
{ unsigned char t;
--lo;
while(++lo < --hi)
t = *lo, *lo = *hi, *hi = t;
}
int get_value( v_rec *v, unsigned char val[] , int *len, unsigned char w[])
{
char *p = v->rp + v->pos;
int ll = 0, retv = 0;
if(v->rp == 0)
return 0;
/* remove white space and a ',' delimiter if present */
while(*p && ( *p == ' ' || *p == '\t') )
++p;
if( *p == ',' )
++p;
if( *p )
{
if( *p == '=' )
{ /* use previous ciphertext */
if( w )
{
++p;
retv = 1;
memcpy(val, w, *len);
ll = *len;
}
}
else if( isxdigit( *p ) && isxdigit( *( p + 1 ) ) )
{ /* input a hexadecimal byte sequence */
while( hexbyte_in(p, &val[ll]) )
{
p += 2; ++ll;
}
retv = 1;
}
else if( *p == '#' )
{ /* input a decimal value and assembler into */
/* little endian byte sequence */
long long int num;
int f = 0;
if(*++p == '>' || *p == '<')
if(*p++ == '>')
f = 1;
p = decimal_in(p, &num);
ll = 0;
while(num)
{
val[ll++] = (unsigned char)(num & 0xff);
num >>= 8;
}
if(f)
reverse_seq(val, val + ll);
retv = 1;
}
else if( *p == '(' ) /* initialise for a bracket term */
retv = init_sequence( &p, val, v->cnt, &ll );
/* after the initialisation of a bracket term, the */
/* parse point is positioned on the final bracket */
if( retv == 2 || *p == ')')
{
if(v->cnt[1] == 0) /* if the sequence has finished */
{ /* go to next input value */
/* leave value in len untouched unless there is */
/* actual input because we may need the prior */
/* length in case we have to copy the previous */
/* ciphertext into the next plaintext */
v->pos = (unsigned int)(++p - v->rp); ll = *len;
retv = get_value(v, val, &ll, w);
}
else
{
(v->cnt[1])--; /* reduce remaining item count */
ll = (int)(v->cnt[2]); /* normal length count */
if(v->cnt[5] == -1 || v->cnt[5] == -2)
{
/* assemble sequential values v1 + n * v2 */
/* (nn,v1,v2,1) - little endian byte array */
/* (nn,v1,v2,2) - big endian byte array */
long long int x = v->cnt[2];
ll = 0;
v->cnt[2] += v->cnt[3];
while(x)
{
val[ll++] = (unsigned char)x;
x >>= 8;
}
if(v->cnt[5] == -2)
reverse_seq(val, val + ll);
}
else if(v->cnt[5] == -3)
{
/* (nn,v1,v2,3) - assemble random array of */
/* bytes of increasing length v1 + n * v2 */
block_rndfill(val, ll);
v->cnt[2] += v->cnt[3];
}
else if(v->cnt[5] == -4)
{
/* (nn,v1,v2,4) - assemble random array of */
/* bytes of random length v1 <= len <= v2 */
unsigned long long t = 0;
block_rndfill((unsigned char*)&t, 4);
ll += (int)(((v->cnt[3] + 1 - v->cnt[2]) * t) >> 32);
block_rndfill(val, ll);
}
else
{
/* (nn,v1,v2,h1,h2) - assemble random array */
/* bytes of increasing length v1 + n * v2 */
/* in which bytes also increment in value */
/* h1 + n * h2 withing each array generated */
int i = 0, j = (int)(v->cnt[4]);
while(i < ll)
{
val[i++] = (unsigned char)j;
j += (int)(v->cnt[5]);
}
v->cnt[2] += v->cnt[3];
}
retv = 1;
}
}
}
/* if a value is returned signal its length */
if(retv)
*len = ll;
v->pos = (unsigned int)(p - v->rp);
return retv;
}
/* restart a parse of a value record */
void restart( v_rec *v )
{
v->pos = 0;
}
/* initialise a value record */
void init( v_rec *v )
{
v->rp = NULL;
v->len = 0;
v->pos = 0;
}
/* empty a value record */
void reset( v_rec *v )
{
if(v->rp)
*(v->rp) = '\0';
v->len = 0;
v->pos = 0;
}
/* delete a value record */
void clear( v_rec *v )
{
if( v-> rp )
free( v->rp );
v->rp = NULL;
v->len = 0;
v->pos = 0;
}
int gen_vectors(char *in_file_name, char *out_file_name)
{
unsigned char h_val[4][MAX_BLOCK_SIZE]; /* input arrays: key, nonce, header & plaintext */
unsigned char ctx[2][MAX_BLOCK_SIZE]; /* BRG and LTC ciphertexts */
unsigned char tag[2][AES_BLOCK_SIZE]; /* BRG and LTC tags */
unsigned char line[128];
v_rec rec[4];
int h_len[4], err = RETURN_ERROR;
long long int vec_no;
FILE *in_file, *out_file;
enum mode mm;
ctx_union context[1];
init( rec ); /* key */
init( rec + 1 ); /* nonce */
init( rec + 2 ); /* header */
init( rec + 3 ); /* plaintext */
/* open template input file */
if( (in_file = fopen( in_file_name, "r" ) ) == NULL )
goto exit3;
/* open test vector output file */
if( ( out_file = fopen( out_file_name, "w" ) ) == NULL )
goto exit2;
for( ; !feof( in_file ) ; )
{
do /* look for start line 'MODE XXX' */
{
fgets( line, 80, in_file );
}
while
(strncmp(line, "MODE", 4) != 0);
if( !strncmp( line + 5, mode_name[0], 3 ) )
mm = m_ccm; /* CCM */
else if( !strncmp( line + 5, mode_name[1], 3 ) )
mm = m_gcm; /* GCM */
else if( !strncmp( line + 5, mode_name[2], 3 ) )
mm = m_eax; /* EAX */
else
continue;
/* output mode header 'MDE XXX' */
fprintf( out_file, "\nMDE %s", line + 5 );
{ /* output date and time */
time_t secs;
struct tm *now;
time( &secs );
now = localtime( &secs );
fprintf( out_file, "REM Produced by GENTEST on %s", asctime( now ) );
}
/* output line designatir summary */
fprintf( out_file, rem );
for( ; !feof( in_file ) ; )
{
for( ; !feof( in_file ) ; )
{
/* process lines in template file */
enum des_type ty;
char *cptr;
fgets( line, 80, in_file );
switch( ty = find_des(line, &cptr) )
{
case ERR:
goto error;
case NUL:
goto more;
case VEC:
decimal_in(cptr, &vec_no);
goto more;
case GEN:
case END:
goto generate;
default:
if(ty < 0 || ty >= 16)
goto error;
add_to_record( rec + ty, cptr);
goto more;
}
error: printf("\nunrecognised input: %s", line);
more: continue;
generate: break;
}
while( get_value( rec , h_val[0], &h_len[0], 0 ) ) /* key */
{
while( get_value( rec + 1, h_val[1], &h_len[1], 0 ) ) /* nonce */
{
while( get_value( rec + 2, h_val[2] , &h_len[2], 0 ) ) /* header */
{
while( get_value( rec + 3, h_val[3], &h_len[3], ctx[0] ) ) /* plaintext */
{
/* run mode funtions here */
/* key: h_val[0] of length h_len[0] */
/* nonce: h_val[1] of length h_len[1] */
/* header: h_val[2] of length h_len[2] */
/* plaintext: h_val[3] of length h_len[3] */
/* my mode functions */
if(ea_funs.brg_ifun[mm]( h_val[0], h_len[0], context ) != RETURN_OK)
{
printf("\nInitialisation failure in BRG's %s mode code", mode_name[mm]);
goto exit1;
}
memcpy( ctx[0], h_val[3], h_len[3] );
if(ea_funs.brg_efun[mm](
h_val[1], h_len[1],
h_val[2], h_len[2],
ctx[0], h_len[3],
tag[0], AES_BLOCK_SIZE,
context ) != RETURN_OK)
{
printf("\nEncryption failure in BRG's %s mode code", mode_name[mm]);
goto exit1;
}
/* mode functions derived from Tom St Denis' LTC */
if(ea_funs.ltc_fun[mm](
h_val[0], h_len[0],
h_val[1], h_len[1],
h_val[2], h_len[2],
h_val[3], h_len[3],
ctx[1],
tag[1], AES_BLOCK_SIZE,
LTC_ENCRYPT, 0) != EXIT_SUCCESS)
{
printf("\nFailure in LTC's %s mode code", mode_name[mm]);
goto exit1;
}
/* check for ciphertext equality */
if( memcmp( ctx[0], ctx[1], h_len[3] ) )
{
printf("\nCiphertext mismatch for %s mode on vector %d", mode_name[mm], (int)vec_no);
goto exit1;
}
/* check for tag equality */
if( memcmp( tag[0], tag[1], AES_BLOCK_SIZE ) )
{
printf("\nTag mismatch for %s mode on vector %d", mode_name[mm], (int)vec_no);
goto exit1;
}
/* output the generated test vector */
fprintf( out_file, "\nVEC %d", (int)vec_no++);
hex_out( out_file, des_name[0], h_val[0], h_len[0] );
if( h_len[1] )
hex_out( out_file, des_name[1], h_val[1], h_len[1] );
if( h_len[2] )
hex_out( out_file, des_name[2], h_val[2], h_len[2] );
if( h_len[3] )
{
hex_out( out_file, des_name[3], h_val[3], h_len[3] );
hex_out( out_file, des_name[4], ctx[0], h_len[3] );
}
hex_out( out_file, des_name[5], tag[0], AES_BLOCK_SIZE );
fprintf(out_file, "\n");
}
restart( rec + 3 );
}
restart( rec + 2 );
}
restart( rec + 1 );
}
reset( rec + 3 );
reset( rec + 2 );
reset( rec + 1 );
reset( rec );
}
}
fprintf(out_file, "\nEND \n");
exit1:
clear( rec + 3 );
clear( rec + 2 );
clear( rec + 1 );
clear( rec );
fclose(out_file);
exit2:
fclose(in_file);
exit3:
return err;
}
int main(int argc, char *argv[])
{
#ifdef TEST_CCM
do_test( 10000, m_ccm );
#endif
#ifdef TEST_GCM
do_test( 10000, m_gcm );
#endif
#ifdef TEST_EAX
do_test( 10000, m_eax );
#endif
#ifdef GEN_TEST
if(argc == 3)
gen_vectors( argv[1], argv[2] );
else
printf("\nusage: gentest vector_rule_file vector_output_file\n");
#endif
printf("\n\n");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -