📄 aes_gav.c
字号:
// Copyright in this code is held by Dr B. R. Gladman but free direct or
// derivative use is permitted subject to acknowledgement of its origin.
// Dr B. R. Gladman . 25th January 2000.
// AES Algorithm Test - Generate local test files for KAT and Monte Carlo
// tests and optionally compare these files with a reference set of test
// files
//
// usage: aes_gav /a:[12345] /t:[kec] [/c] [/h]
// where:
// /a:[12345] algorithms to be tested
// /t:[kec] type of test
// /c compare output and reference file(s)
// /h use author's byte order (serpent)
// and:
// 1:mars, 2:rc6, 3:rijndael, 4:serpent, 5:twofish
// k: generate ECB Known Answer Test files
// e: generate ECB Monte Carlo Test files
// c: generate CBC Monte Carlo Test files
//
// The reference files have a ".txt" extension while those generated use
// ".txt" if in a different directory or ".dat" otherwise. The directory
// paths for files are set below. Note that, when compared with the NIST
// test vector sequences, this code implements one additional (all zero)
// test vector as the first vector in each set (test 0).
#ifdef __cplusplus
# include <iostream>
# include <fstream>
#else
# include <stdio.h>
#endif
#include "aes_config.h"
#include "aes_defs.h"
#include "aes_aux.h"
#include "mars.h"
#include "rc6.h"
#include "rijndael.h"
#include "serpent.h"
#include "twofish.h"
#if KEEP_USER_HAPPY
# define OUT_DOTS(x) \
{ \
if(!(x % 40)) \
con_char('\n'); \
con_char('.'); \
}
#else
# define OUT_DOTS(x)
#endif
// Serpent hack to get test agreement because the test vectors for this
// algorithm assemble the key vectors in the reverse direction in memory
bool serpent_hack = false;
// Outputs a test vector file header
void header(OFREF outf, int type, char alg_name[])
{
put_string(outf, "=======================================================");
put_string(outf, "\nAuthor: Dr B R Gladman ( )");
put_string(outf, "\nTest: "); put_string(outf, type < 4 ? "ECB " : "CBC ");
switch(type)
{
case 0: put_string(outf, "Variable Key Known Answer Tests"); break;
case 1: put_string(outf, "Variable Text Known Answer Tests"); break;
case 2:
case 4: put_string(outf, "Monte Carlo (Encryption) Tests"); break;
case 3:
case 5: put_string(outf, "Monte Carlo (Decryption) Tests"); break;
}
put_string(outf, "\nAlgorithm: "); put_string(outf, alg_name);
put_string(outf, "\nFilename: "); put_string(outf, type < 4 ? "ecb_" : "cbc_");
switch(type)
{
case 0: put_string(outf, "vk.txt\n"); break;
case 1: put_string(outf, "vt.txt\n"); break;
case 2:
case 4: put_string(outf, "e_m.txt\n"); break;
case 3:
case 5: put_string(outf, "d_m.txt\n"); break;
}
put_string(outf, "=======================================================");
}
// Test of Electronic Code Book (ECB) Mode with Fixed Key and Variable Text
void ecb_vt(OFREF outf, AESREF alg)
{ u4byte i, j;
u1byte pt[16], ct[16], key[32], dummy;
block_clear(key, 32); // all zero key
for(i = 0; i < 3; ++i) // key lengthes 128, 192 and 256
{
block_out(0, &dummy, outf, 128 + 64 * i); // output key length;
put_char(outf, '\n');
block_out(3, key, outf, 16 + 8 * i); // output key value
alg.set_key(key, 128 + 64 * i, both); // set key value
for(j = 0; j <= 128; ++j) // 129 test vectors including
{ // an all zero one
block_out(1, &dummy, outf, j); // output test number
block_clear(pt, 16); // set all zero plain text
if(j) // set bit (j-1) if j <> 0
*(pt + (j - 1) / 8) = 0x80 >> (j - 1) % 8;
block_out(4, pt, outf, 16); // output plaintext
if(serpent_hack) // reverse plaintext
// block for Serpent
block_reverse(pt, 16);
alg.encrypt(pt , ct); // do encryption
if(serpent_hack) // reverse ciphertext
// block for Serpent
block_reverse(ct, 16);
block_out(5, ct, outf, 16); // output ciphertext
}
}
}
// Test of Electronic Code Book (ECB) Mode with Fixed Text and Variable Key
void ecb_vk(OFREF outf, AESREF alg)
{ u4byte i, j;
u1byte pt[16], ct[16], key[32], dummy;
block_clear(pt, 16); // all zero plaintext
for(i = 0; i < 3; ++i) // key lengths of 128, 192 and 256 bits
{
block_out(0, &dummy, outf, 128 + 64 * i); // output key length;
put_char(outf, '\n');
block_out(4, pt, outf, 16); // output plaintext
for(j = 0; j <= 128 + 64 * i; ++j) // 129, 193 or 257 tests
{
block_out(1, &dummy, outf, j); // output test number
block_clear(key, 32);
if(j) // set bit (j-1) if j <> 0
*(key + (j - 1) / 8) = 0x80 >> (j - 1) % 8;
block_out(3, key, outf, 16 + 8 * i); // output key value
if(serpent_hack) // reverse key block for Serpent
block_reverse(key, 16 + 8 * i);
alg.set_key(key, 128 + 64 * i, enc); // set key value
alg.encrypt(pt , ct); // alg.encrypt
if(serpent_hack) // reverse ciphertext for Serpent
block_reverse(ct, 16);
block_out(5, ct, outf, 16); // output ciphertext
}
}
}
// Monte Carlo Encryption Test of Electronic Code Book (ECB) Mode
void ecb_me(OFREF outf, AESREF alg)
{ u4byte i, j, k;
u1byte pt[16], ct[32], key[32], dummy;
for(i = 0; i < 3; ++i) // key lengths of 128, 192 and 256 bits
{
block_out(0, &dummy, outf, 128 + 64 * i); // output key length;
block_clear(pt, 16); block_clear(key, 32); // clear initial plaintext
// and key blocks
block_copy(ct + 16, pt, 16); // put plaintext in upper half
// of double length buffer
for(j = 0; j < 400; j++) // 400 Monte Carlo tests
{
OUT_DOTS(j);
block_out(1, &dummy, outf, j); // output test number
block_out(3, key, outf, 16 + 8 * i);// output key
block_out(4, pt, outf, 16); // output plaintext
if(serpent_hack) // reverse both input blocks for Serpent
{
block_reverse(key, 16 + 8 * i); block_reverse(ct + 16, 16);
}
alg.set_key(key, 128 + 64 * i, enc); // set the key
for(k = 0; k < 5000; ++k) // 10000 encryptions alternating
{ // upper and lower blocks in ct
alg.encrypt(ct + 16, ct); alg.encrypt(ct, ct + 16);
}
// compile next key as defined by NIST
block_xor(key, ct + 16 - 8 * i, 16 + 8 * i);
if(serpent_hack) // put blocks in normal mode for Serpent
{
block_reverse(key, 16 + 8 * i); block_reverse(ct + 16, 16);
}
block_out(5, ct + 16, outf, 16); // output ciphertext
block_copy(pt, ct + 16, 16); // copy cipertext as next plaintext
}
}
}
// Monte Carlo Decryption Test of Electronic Code Book (ECB) Mode
void ecb_md(OFREF outf, AESREF alg)
{ u4byte i, j, k;
u1byte pt[16], ct[32], key[32], dummy;
for(i = 0; i < 3; ++i) // key lengths 128, 192 and 256 bits
{
block_out(0, &dummy, outf, 128 + 64 * i); // output key length;
block_clear(pt, 16); // clear initial plaintext and key
block_clear(key, 32);
block_copy(ct + 16, pt, 16); // copy plaintext into upper half
// of double length ciphertext block
for(j = 0; j < 400; j++) // 400 Monte Carlo tests
{
OUT_DOTS(j);
block_out(1, &dummy, outf, j); // output test number
block_out(3, key, outf, 16 + 8 * i); // output key
block_out(5, pt, outf, 16); // output plaintext
if(serpent_hack) // reverse input blocks for Serpent
{
block_reverse(key, 16 + 8 * i); block_reverse(ct + 16, 16);
}
alg.set_key(key, 128 + 64 * i, dec); // set key
for(k = 0; k < 5000; ++k) // 10000 decryptions alternating
{ // upper and lower blocks in ct
alg.decrypt(ct + 16, ct); alg.decrypt(ct, ct + 16);
}
// compile next key as defined by NIST
block_xor(key, ct + 16 - 8 * i, 16 + 8 * i);
if(serpent_hack) // put blocks in normal mode for Serpent
{
block_reverse(key, 16 + 8 * i); block_reverse(ct + 16, 16);
}
block_out(4, ct + 16, outf, 16); // output ciphertext
block_copy(pt, ct + 16, 16); // set ciphertext as next plaintext
}
}
}
// Monte Carlo Encryption Test of Cipher Block Chaining (CBC) Mode
void cbc_me(OFREF outf, AESREF alg)
{ u4byte i, j, k;
u1byte ct[32], key[32], dummy;
for(i = 0; i < 3; ++i) // key lengths 128, 192 and 256 bits
{
block_out(0, &dummy, outf, 128 + 64 * i); // output key length;
block_clear(key, 32); // clear key: KEY[0]
block_clear(ct, 32); // clear ct: PT[0], ct + 16: IV[0]
for(j = 0; j < 400; j++) // 400 Monte Carlo tests
{
OUT_DOTS(j);
block_out(1, &dummy, outf, j); // output test number
block_out(3, key, outf, 16 + 8 * i);// output key
block_out(2, ct + 16, outf, 16); // output initialisation vector
block_out(4, ct, outf, 16); // output plaintext
if(serpent_hack) // reverse key block if Serpent
{
block_reverse(key, 16 + 8 * i);
}
alg.set_key(key, 128 + 64 * i, enc); // set key
for(k = 0; k < 5000; ++k) // 10000 encryptions, two at a time
{
block_xor(ct, ct + 16, 16); // do CBC chaining
if(serpent_hack) // reverse input block for Serpent
{
block_reverse(ct, 16);
}
alg.encrypt(ct, ct); // do block encryption
if(serpent_hack) // reverse output block for Serpent
{
block_reverse(ct, 16);
}
block_xor(ct + 16, ct, 16); // do CBC chaining
if(serpent_hack) // reverse input block for Serpent
{
block_reverse(ct + 16, 16);
}
alg.encrypt(ct + 16, ct + 16); // do block encryption
if(serpent_hack) // reverse output block for Serpent
{
block_reverse(ct + 16, 16);
}
}
block_out(5, ct + 16, outf, 16); // output ciphertext
if(serpent_hack) // reverse blocks for Serpent
{
block_reverse(ct, 16); block_reverse(ct + 16, 16);
}
// compile next key as defined by NIST
block_xor(key, ct + 16 - 8 * i, 16 + 8 * i);
if(serpent_hack) // put blocks in normal order for Serpent
{
block_reverse(key, 16 + 8 * i);
block_reverse(ct, 16); block_reverse(ct + 16, 16);
}
}
}
}
// Monte Carlo Encryption Test of Cipher Block Chaining (CBC) Mode
void cbc_md(OFREF outf, AESREF alg)
{ u4byte i, j, k;
u1byte pt[16], ct[32], key[32], dummy;
for(i = 0; i < 3; ++i) // key lengths 128, 192 and 256 bits
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -