📄 aes_tmr.cpp
字号:
// 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 <brg@gladman.uk.net> 1st June 2001.
//
// Measure the Encryption, Decryption and Key Setup Times for AES using
// the Pentium Time Stamp Counter
#include <iostream>
#include <fstream>
#include "aes.h"
#include "aes_aux.h"
#include "aes_tst.h"
// Use this define if testing aes++.c
//#define AESX
#if defined(AES_DLL)
fn_ptrs fn;
#endif
#define PROCESSOR "PIII" // Processor
void cycles(unsigned __int64 *rtn)
{ // read the Pentium Time Stamp Counter
__asm
{
_emit 0x0f // complete pending operations
_emit 0xa2
_emit 0x0f // read time stamp counter
_emit 0x31
mov ebx,rtn
mov [ebx],eax
mov [ebx+4],edx
_emit 0x0f // complete pending operations
_emit 0xa2
}
}
const unsigned int loops = 100; // number of timing loops
word rand32(void)
{ static word r4,r_cnt = -1,w = 521288629,z = 362436069;
z = 36969 * (z & 65535) + (z >> 16);
w = 18000 * (w & 65535) + (w >> 16);
r_cnt = 0; r4 = (z << 16) + w; return r4;
}
byte rand8(void)
{ static word r4,r_cnt = 4;
if(r_cnt == 4)
{
r4 = byte_swap(rand32()); r_cnt = 0;
}
return (char)(r4 >> (8 * r_cnt++));
}
// fill a block with random charactrers
void block_rndfill(byte l[], word len)
{ word i;
for(i = 0; i < len; ++i)
l[i] = rand8();
}
// measure cycles for an encryption call
word e_cycles(const word klen, aes* alg)
{ byte pt[16], ct[16], key[32];
word i, c1, c2;
unsigned __int64 cy0, cy1, cy2;
// set up a random key of 256 bits
block_rndfill(key, 32);
// set up a random plain text
block_rndfill(pt, 16);
// do a set_key in case it is necessary
f_set_key(alg, key, klen, both); c1 = c2 = 0xffffffff;
// do an encrypt to remove any 'first time through' effects
f_encrypt(alg, pt, ct);
for(i = 0; i < loops; ++i)
{
block_rndfill(pt, 16);
// time one and two encryptions
cycles(&cy0);
f_encrypt(alg, pt, ct);
cycles(&cy1);
f_encrypt(alg, pt, ct);
f_encrypt(alg, pt, ct);
cycles(&cy2);
cy2 -= cy1; cy1 -= cy0; // time for one and two calls
c1 = (c1 > cy1 ? cy1 : c1); // find minimum values over the loops
c2 = (c2 > cy2 ? cy2 : c2);
}
return c2 - c1; // return one call timing
}
// measure cycles for a decryption call
word d_cycles(const word klen, aes* alg)
{ byte pt[16], ct[16], key[32];
word i, c1, c2;
unsigned __int64 cy0, cy1, cy2;
// set up a random key of 256 bits
block_rndfill(key, 32);
// set up a random plain text
block_rndfill(pt, 16);
// do a set_key in case it is necessary
f_set_key(alg, key, klen, both); c1 = c2 = 0xffffffff;
// do an decrypt to remove any 'first time through' effects
f_decrypt(alg, pt, ct);
for(i = 0; i < loops; ++i)
{
block_rndfill(pt, 16);
// time one and two encryptions
cycles(&cy0);
f_decrypt(alg, pt, ct);
cycles(&cy1);
f_decrypt(alg, pt, ct);
f_decrypt(alg, pt, ct);
cycles(&cy2);
cy2 -= cy1; cy1 -= cy0; // time for one and two calls
c1 = (c1 > cy1 ? cy1 : c1); // find minimum values over the loops
c2 = (c2 > cy2 ? cy2 : c2);
}
return c2 - c1; // return one call timing
}
// measure cycles for a key setup
word k_cycles(const word klen, aes* alg, const enum aes_key f)
{ byte key[32];
word i, c1, c2;
unsigned __int64 cy0, cy1, cy2;
// set up a random key of 256 bits
block_rndfill(key, 32);
// do an set_key to remove any 'first time through' effects
f_set_key(alg, key, klen, f); c1 = c2 = 0xffffffff;
for(i = 0; i < loops; ++i)
{
block_rndfill(key, 32);
// time one and two encryptions
cycles(&cy0);
f_set_key(alg, key, klen, f);
cycles(&cy1);
f_set_key(alg, key, klen, f);
f_set_key(alg, key, klen, f);
cycles(&cy2);
cy2 -= cy1; cy1 -= cy0; // time for one and two calls
c1 = (c1 > cy1 ? cy1 : c1); // find minimum values over the loops
c2 = (c2 > cy2 ? cy2 : c2);
}
return c2 - c1; // return one call timing
}
static word kl[5] = { 16, 20, 24, 28, 32 };
static word ekt[5], dkt[5], et[5], dt[5];
void output(std::ofstream& outf, const inx, const word bits)
{ word t;
byte c0, c1, c2;
outf << "\n// " << 8 * kl[inx] << " Bit:";
outf << " Key Setup: " << ekt[inx] << '/' << dkt[inx] << " cycles";
t = (1000 * bits + et[inx] / 2) / et[inx];
c0 = '0' + t / 100; c1 = '0' + (t / 10) % 10; c2 = '0' + t % 10;
outf << "\n// Encrypt: " << et[inx] << " cycles = 0."
<< c0 << c1 << c2 << " bits/cycle";
t = (1000 * bits + et[inx] / 2) / dt[inx];
c0 = '0' + t / 100; c1 = '0' + (t / 10) % 10; c2 = '0' + t % 10;
outf << "\n// Decrypt: " << dt[inx] << " cycles = 0."
<< c0 << c1 << c2 << " bits/cycle";
}
#if defined(AESX)
#define INC 1
#else
#define INC 2
#endif
#if BLOCK_SIZE == 16
#define STR 0
#define CNT 1
#elif BLOCK_SIZE == 20
#define STR 1
#define CNT 2
#elif BLOCK_SIZE == 24
#define STR 2
#define CNT 3
#elif BLOCK_SIZE == 28
#define STR 3
#define CNT 4
#elif BLOCK_SIZE == 32
#define STR 4
#define CNT 5
#elif !defined(BLOCK_SIZE)
#define STR 0
#define CNT 5
#else
#error Illegal block size
#endif
#if defined(AES_DLL)
#include "windows.h"
HINSTANCE init_dll(fn_ptrs& fn)
{ HINSTANCE h_dll;
if(!(h_dll = LoadLibrary(dll_path)))
{
std::cout << "\n\nDynamic link Library AES_DLL not found\n\n"; return 0;
}
fn.fn_set_key = (f_ky*)GetProcAddress(h_dll, "_set_key@16");
fn.fn_encrypt = (f_ed*)GetProcAddress(h_dll, "_encrypt@12");
fn.fn_decrypt = (f_ed*)GetProcAddress(h_dll, "_decrypt@12");
fn.fn_set_blk = (f_bl*)GetProcAddress(h_dll, "_set_blk@8");
#if !defined(BLOCK_SIZE)
if(!fn.fn_set_key || !fn.fn_encrypt || !fn.fn_decrypt || !fn.fn_set_blk)
#else
if(!fn.fn_set_key || !fn.fn_encrypt || !fn.fn_decrypt)
#endif
{
std::cout << "\n\nRequired DLL Entry Point(s) not found\n\n";
FreeLibrary(h_dll);
return 0;
}
return h_dll;
}
#endif // AES_DLL
int main(int argc, char *argv[])
{ std::ofstream outf;
aes alg;
#if defined(REPORT_SPACE)
word lc, lt;
char fn[16];
length(&lc, <, fn);
#endif
#if defined(AES_DLL)
HINSTANCE h_dll;
if(!(h_dll = init_dll(fn))) return -1;
#endif
#if !defined(AES_IN_CPP)
alg.mode = 0;
#endif
#if defined(REPORT_SPACE)
outf.open(fn, std::ios_base::out);
#else
outf.open(argc == 2 ? argv[1] : "CON", std::ios_base::out);
#endif
outf << "\n// AES"
#if defined(AES_DLL)
" (DLL)"
#endif
" on " << PROCESSOR << " processor";
#if defined(REPORT_SPACE)
outf << "\n// " << fn << " (code " << lc << ", tables " << lt << ')';
#endif
for(int i = STR; i < CNT; i += INC)
{
#if !defined(BLOCK_SIZE)
f_set_blk(&alg, 16 + 4 * i);
#elif defined(AES_DLL)
if(fn.fn_set_blk) f_set_blk(&alg, BLOCK_SIZE);
#endif
for(word j = 0; j < 5; j += INC)
{
ekt[j] = k_cycles(kl[j], &alg, enc);
dkt[j] = k_cycles(kl[j], &alg, dec);
et[j] = e_cycles(kl[j], &alg);
dt[j] = d_cycles(kl[j], &alg);
}
outf << "\n// Block Length: " << 128 + 32 * i;
for(word k = 0; k < 5; k += INC)
output(outf, k, 128 + 32 * i);
}
#if defined(AES_DLL)
if(h_dll) FreeLibrary(h_dll);
#endif
outf << "\n\n";
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -