Compare commits
10 Commits
b5f2359881
...
667efc212c
Author | SHA1 | Date |
---|---|---|
|
667efc212c | |
|
f15cc5c838 | |
|
d7785ed520 | |
|
d4f11de258 | |
|
3f2c3a6ab6 | |
|
1fabd6f02a | |
|
d5ef468573 | |
|
d8021e9352 | |
|
3c746784b6 | |
|
2e4cc7ea48 |
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 73,
|
||||
"id": "5a87ea11-1c00-4097-a5b3-aa56cc33b7fb",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[44 44 45 ... 43 44 44]\n",
|
||||
" [44 45 45 ... 45 45 45]\n",
|
||||
" [44 45 45 ... 44 44 44]\n",
|
||||
" ...\n",
|
||||
" [45 45 45 ... 46 45 46]\n",
|
||||
" [44 44 45 ... 45 45 45]\n",
|
||||
" [45 46 45 ... 45 45 46]]\n",
|
||||
"(128, 750000)\n",
|
||||
"[59867 59631 64874 55734 51531 64641 63078 56084 62793 54154 50676 62981\n",
|
||||
" 55136 62640 58096 48365 62697 51194 54140 57243 59968 63117 45133 61542\n",
|
||||
" 59420 59012 61305 63438 58405 57121 62630 56219 54454 50854 65426 51115\n",
|
||||
" 47308 42314 54576 63390 62825 51672 51684 60670 51151 49354 51373 61212\n",
|
||||
" 61200 49430 64257 58178 63377 62001 57011 64714 64740 54700 56772 63292\n",
|
||||
" 57779 59093 61834 61733]\n",
|
||||
"True\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"TRNG_PAIR_CNT = 64\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" # reading info file - length of trace, sampling frequency (not necessary to know in our case), random value generated by the TRNG\n",
|
||||
" with open(\"data_info.txt\", \"r\") as fin:\n",
|
||||
" tracelen = int(fin.readline())\n",
|
||||
" fs = int(fin.readline())\n",
|
||||
" trng_val = fin.readline()\n",
|
||||
"\n",
|
||||
" traces = np.fromfile(\"data.bin\", dtype='uint8') # reading traces for individual ROs\n",
|
||||
" traces = np.reshape(traces, (traces.size//tracelen, tracelen)) # reshape of matrix, each row contains the trace for one RO\n",
|
||||
"\n",
|
||||
" traces_bin = traces > 128 # conversion of waveforms to rectangles - everything below threshold is 0, otherwise 1 (they are boolean values actually)\n",
|
||||
" print(traces)\n",
|
||||
" print(traces_bin.shape)\n",
|
||||
" rising_edges = np.logical_not(traces_bin[:,:-1]) & traces_bin[:,1:] # finding rising edges, each rising edge is represented by True\n",
|
||||
"\n",
|
||||
" cnt = np.count_nonzero(rising_edges, axis=1) # count the number of rising edges in rows\n",
|
||||
" \n",
|
||||
" # cnt is now a 1D vector\n",
|
||||
" cnt = cnt.reshape(TRNG_PAIR_CNT,2).min(axis=1) # Reshape of the count array into matrix, where each row contains 2 values - the number of rising edges for two ROs in a pair. Then we select the smaller value.\n",
|
||||
" \n",
|
||||
" cnt_sel = cnt & 0b00000011 # select only the two least significant bits\n",
|
||||
"\n",
|
||||
" estimate = ''.join([np.binary_repr(x, width=2) for x in cnt_sel]) # binary representation of the values (the last 2 bits) and joining them into one string\n",
|
||||
" estimate = '{0:0>32x}'.format(int(estimate, 2))\n",
|
||||
" # from data_info, output of the RNG in FPGA\n",
|
||||
" print(trng_val[:-1] == estimate)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7f8447e8-39c3-4706-902e-3970459ce515",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.15"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
test: aes_4.cpp aes_5a.cpp aes_5b.cpp aes_6.cpp test.cpp
|
||||
g++ test.cpp -lcrypto -march=native -maes -msse2 -msse -Ofast
|
|
@ -0,0 +1,211 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* AES-128 simple implementation template and testing */
|
||||
|
||||
/*
|
||||
Author: Ondrej Hladuvka, hladuond@fit.cvut.cz
|
||||
Template: Jiri Bucek 2017
|
||||
AES specification:
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
/* AES Constants */
|
||||
namespace aes128_4{
|
||||
// forward sbox
|
||||
const uint8_t SBOX[256] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // A
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // B
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // C
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // D
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // E
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 // F
|
||||
};
|
||||
|
||||
const uint8_t rCon[12] = {
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
|
||||
};
|
||||
|
||||
/* AES state type */
|
||||
typedef uint32_t t_state[4];
|
||||
|
||||
/* Helper functions */
|
||||
void hexprint16(uint8_t *p) {
|
||||
for (int i = 0; i < 16; i++)
|
||||
printf("%02hhx ", p[i]);
|
||||
puts("");
|
||||
}
|
||||
|
||||
void hexprintw(uint32_t w) {
|
||||
for (int i = 0; i < 32; i += 8)
|
||||
printf("%02hhx ", (w >> i) & 0xffU);
|
||||
}
|
||||
|
||||
void hexprintws(uint32_t * p, int cnt) {
|
||||
for (int i = 0; i < cnt; i++)
|
||||
hexprintw(p[i]);
|
||||
puts("");
|
||||
}
|
||||
void printstate(t_state s) {
|
||||
hexprintw(s[0]);
|
||||
hexprintw(s[1]);
|
||||
hexprintw(s[2]);
|
||||
hexprintw(s[3]);
|
||||
puts("");
|
||||
}
|
||||
|
||||
uint32_t word(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3) {
|
||||
return a0 | (uint32_t)a1 << 8 | (uint32_t)a2 << 16 | (uint32_t)a3 << 24;
|
||||
}
|
||||
|
||||
uint8_t wbyte(uint32_t w, int pos) {
|
||||
return (w >> (pos * 8)) & 0xff;
|
||||
}
|
||||
|
||||
// **************** AES functions ****************
|
||||
uint32_t subWord(uint32_t w) {
|
||||
return word(SBOX[wbyte(w, 0)], SBOX[wbyte(w, 1)], SBOX[wbyte(w, 2)], SBOX[wbyte(w, 3)]);
|
||||
}
|
||||
|
||||
void subBytes(t_state s) {
|
||||
unsigned char* p = reinterpret_cast<unsigned char*>(s);
|
||||
for (int i = 0; i < 16; ++i)
|
||||
p[i] = SBOX[p[i]];
|
||||
}
|
||||
|
||||
void shiftRows(t_state s) {
|
||||
uint32_t tmp[4];
|
||||
|
||||
tmp[0] = s[0] & 0x0000FF00;
|
||||
tmp[1] = s[1] & 0x0000FF00;
|
||||
tmp[2] = s[2] & 0x0000FF00;
|
||||
tmp[3] = s[3] & 0x0000FF00;
|
||||
|
||||
s[0] = (s[0] & 0xFFFF00FF) | tmp[1];
|
||||
s[1] = (s[1] & 0xFFFF00FF) | tmp[2];
|
||||
s[2] = (s[2] & 0xFFFF00FF) | tmp[3];
|
||||
s[3] = (s[3] & 0xFFFF00FF) | tmp[0];
|
||||
|
||||
tmp[0] = s[0] & 0x00FF0000;
|
||||
tmp[1] = s[1] & 0x00FF0000;
|
||||
tmp[2] = s[2] & 0x00FF0000;
|
||||
tmp[3] = s[3] & 0x00FF0000;
|
||||
|
||||
s[0] = (s[0] & 0xFF00FFFF) | tmp[2];
|
||||
s[1] = (s[1] & 0xFF00FFFF) | tmp[3];
|
||||
s[2] = (s[2] & 0xFF00FFFF) | tmp[0];
|
||||
s[3] = (s[3] & 0xFF00FFFF) | tmp[1];
|
||||
|
||||
tmp[0] = s[0] & 0xFF000000;
|
||||
tmp[1] = s[1] & 0xFF000000;
|
||||
tmp[2] = s[2] & 0xFF000000;
|
||||
tmp[3] = s[3] & 0xFF000000;
|
||||
|
||||
s[0] = (s[0] & 0x00FFFFFF) | tmp[3];
|
||||
s[1] = (s[1] & 0x00FFFFFF) | tmp[0];
|
||||
s[2] = (s[2] & 0x00FFFFFF) | tmp[1];
|
||||
s[3] = (s[3] & 0x00FFFFFF) | tmp[2];
|
||||
}
|
||||
|
||||
uint8_t xtime(uint8_t c) {
|
||||
uint8_t m = ((c & 0x80) >> 7) * 0x1B;
|
||||
return (c << 1) ^ m;
|
||||
}
|
||||
|
||||
void mixColumns(t_state s) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint8_t a0 = wbyte(s[i], 0);
|
||||
uint8_t a1 = wbyte(s[i], 1);
|
||||
uint8_t a2 = wbyte(s[i], 2);
|
||||
uint8_t a3 = wbyte(s[i], 3);
|
||||
|
||||
uint8_t r0 = xtime(a0) ^ xtime(a1) ^ a1 ^ a2 ^ a3;
|
||||
uint8_t r1 = xtime(a1) ^ xtime(a2) ^ a2 ^ a3 ^ a0;
|
||||
uint8_t r2 = xtime(a2) ^ xtime(a3) ^ a3 ^ a0 ^ a1;
|
||||
uint8_t r3 = xtime(a3) ^ xtime(a0) ^ a0 ^ a1 ^ a2;
|
||||
|
||||
s[i] = word(r0, r1, r2, r3);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion from 128bits (4*32b)
|
||||
* to 11 round keys (11*4*32b)
|
||||
* each round key is 4*32b
|
||||
*/
|
||||
void expandKey(uint8_t k[16], uint32_t ek[44]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ek[i] = word(k[4*i], k[4*i + 1], k[4*i + 2], k[4*i + 3]);
|
||||
}
|
||||
|
||||
for (int i = 4; i < 44; i++) {
|
||||
uint32_t temp = ek[i - 1];
|
||||
if (i % 4 == 0) {
|
||||
// RotWord, SubWord, and XOR with Rcon
|
||||
temp = subWord((temp >> 8) | (temp << 24)) ^ rCon[i / 4];
|
||||
}
|
||||
ek[i] = ek[i - 4] ^ temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Adding expanded round key (prepared before) */
|
||||
void addRoundKey(t_state s, uint32_t ek[], short index) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s[i] ^= ek[index + i];
|
||||
}
|
||||
}
|
||||
|
||||
void aes128_4(uint8_t *in, uint8_t *out, uint32_t * expKey) {
|
||||
t_state state;
|
||||
|
||||
state[0] = word(in[0], in[1], in[2], in[3]);
|
||||
state[1] = word(in[4], in[5], in[6], in[7]);
|
||||
state[2] = word(in[8], in[9], in[10], in[11]);
|
||||
state[3] = word(in[12], in[13], in[14], in[15]);
|
||||
|
||||
addRoundKey(state, expKey, 0);
|
||||
for (int round = 0; round < 9; ++round) {
|
||||
subBytes(state);
|
||||
shiftRows(state);
|
||||
mixColumns(state);
|
||||
addRoundKey(state, expKey, round * 4 + 4);
|
||||
}
|
||||
|
||||
subBytes(state);
|
||||
shiftRows(state);
|
||||
addRoundKey(state, expKey, 10 * 4);
|
||||
|
||||
out[0] = wbyte(state[0], 0);
|
||||
out[1] = wbyte(state[0], 1);
|
||||
out[2] = wbyte(state[0], 2);
|
||||
out[3] = wbyte(state[0], 3);
|
||||
|
||||
out[4] = wbyte(state[1], 0);
|
||||
out[5] = wbyte(state[1], 1);
|
||||
out[6] = wbyte(state[1], 2);
|
||||
out[7] = wbyte(state[1], 3);
|
||||
|
||||
out[8] = wbyte(state[2], 0);
|
||||
out[9] = wbyte(state[2], 1);
|
||||
out[10] = wbyte(state[2], 2);
|
||||
out[11] = wbyte(state[2], 3);
|
||||
|
||||
out[12] = wbyte(state[3], 0);
|
||||
out[13] = wbyte(state[3], 1);
|
||||
out[14] = wbyte(state[3], 2);
|
||||
out[15] = wbyte(state[3], 3);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Author: Ondrej Hladuvka, hladuond@fit.cvut.cz
|
||||
Template: Jiri Bucek 2017
|
||||
AES specification:
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
namespace aes128_5a {
|
||||
|
||||
/* AES Constants */
|
||||
|
||||
// forward sbox
|
||||
const uint8_t SBOX[256] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // A
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // B
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // C
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // D
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // E
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 // F
|
||||
};
|
||||
|
||||
/* AES state type */
|
||||
typedef uint32_t t_state[4];
|
||||
|
||||
#define word(a0, a1, a2, a3) ((uint32_t)(a0) | ((uint32_t)(a1) << 8) | ((uint32_t)(a2) << 16) | ((uint32_t)(a3) << 24))
|
||||
|
||||
uint8_t wbyte(uint32_t w, int pos) {
|
||||
return (w >> (pos * 8)) & 0xff;
|
||||
}
|
||||
|
||||
// **************** AES functions ****************
|
||||
uint32_t subWord(uint32_t w) {
|
||||
return word(SBOX[wbyte(w, 0)], SBOX[wbyte(w, 1)], SBOX[wbyte(w, 2)], SBOX[wbyte(w, 3)]);
|
||||
}
|
||||
|
||||
void subBytes(t_state s) {
|
||||
unsigned char* p = reinterpret_cast<unsigned char*>(s);
|
||||
for (int i = 0; i < 16; ++i)
|
||||
p[i] = SBOX[p[i]];
|
||||
}
|
||||
|
||||
void shiftRows(t_state s) {
|
||||
uint32_t tmp[4];
|
||||
|
||||
tmp[0] = s[0] & 0x0000FF00;
|
||||
tmp[1] = s[1] & 0x0000FF00;
|
||||
tmp[2] = s[2] & 0x0000FF00;
|
||||
tmp[3] = s[3] & 0x0000FF00;
|
||||
|
||||
s[0] = (s[0] & 0xFFFF00FF) | tmp[1];
|
||||
s[1] = (s[1] & 0xFFFF00FF) | tmp[2];
|
||||
s[2] = (s[2] & 0xFFFF00FF) | tmp[3];
|
||||
s[3] = (s[3] & 0xFFFF00FF) | tmp[0];
|
||||
|
||||
tmp[0] = s[0] & 0x00FF0000;
|
||||
tmp[1] = s[1] & 0x00FF0000;
|
||||
tmp[2] = s[2] & 0x00FF0000;
|
||||
tmp[3] = s[3] & 0x00FF0000;
|
||||
|
||||
s[0] = (s[0] & 0xFF00FFFF) | tmp[2];
|
||||
s[1] = (s[1] & 0xFF00FFFF) | tmp[3];
|
||||
s[2] = (s[2] & 0xFF00FFFF) | tmp[0];
|
||||
s[3] = (s[3] & 0xFF00FFFF) | tmp[1];
|
||||
|
||||
tmp[0] = s[0] & 0xFF000000;
|
||||
tmp[1] = s[1] & 0xFF000000;
|
||||
tmp[2] = s[2] & 0xFF000000;
|
||||
tmp[3] = s[3] & 0xFF000000;
|
||||
|
||||
s[0] = (s[0] & 0x00FFFFFF) | tmp[3];
|
||||
s[1] = (s[1] & 0x00FFFFFF) | tmp[0];
|
||||
s[2] = (s[2] & 0x00FFFFFF) | tmp[1];
|
||||
s[3] = (s[3] & 0x00FFFFFF) | tmp[2];
|
||||
}
|
||||
|
||||
uint8_t xtime(uint8_t c) {
|
||||
uint8_t m = ((c & 0x80) >> 7) * 0x1B;
|
||||
return (c << 1) ^ m;
|
||||
}
|
||||
|
||||
void mixColumns(t_state s) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint8_t a0 = wbyte(s[i], 0);
|
||||
uint8_t a1 = wbyte(s[i], 1);
|
||||
uint8_t a2 = wbyte(s[i], 2);
|
||||
uint8_t a3 = wbyte(s[i], 3);
|
||||
|
||||
uint8_t r0 = xtime(a0) ^ xtime(a1) ^ a1 ^ a2 ^ a3;
|
||||
uint8_t r1 = xtime(a1) ^ xtime(a2) ^ a2 ^ a3 ^ a0;
|
||||
uint8_t r2 = xtime(a2) ^ xtime(a3) ^ a3 ^ a0 ^ a1;
|
||||
uint8_t r3 = xtime(a3) ^ xtime(a0) ^ a0 ^ a1 ^ a2;
|
||||
|
||||
s[i] = word(r0, r1, r2, r3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adding expanded round key (prepared before) */
|
||||
void addRoundKey(t_state s, uint32_t ek[], short index) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s[i] ^= ek[index + i];
|
||||
}
|
||||
}
|
||||
|
||||
void aes128_5(uint8_t *in, uint8_t *out, uint32_t * expKey) {
|
||||
t_state state;
|
||||
|
||||
state[0] = word(in[0], in[1], in[2], in[3]);
|
||||
state[1] = word(in[4], in[5], in[6], in[7]);
|
||||
state[2] = word(in[8], in[9], in[10], in[11]);
|
||||
state[3] = word(in[12], in[13], in[14], in[15]);
|
||||
|
||||
addRoundKey(state, expKey, 0);
|
||||
for (int round = 0; round < 9; ++round) {
|
||||
subBytes(state);
|
||||
shiftRows(state);
|
||||
mixColumns(state);
|
||||
addRoundKey(state, expKey, round * 4 + 4);
|
||||
}
|
||||
subBytes(state);
|
||||
shiftRows(state);
|
||||
addRoundKey(state, expKey, 10 * 4);
|
||||
|
||||
out[0] = wbyte(state[0], 0);
|
||||
out[1] = wbyte(state[0], 1);
|
||||
out[2] = wbyte(state[0], 2);
|
||||
out[3] = wbyte(state[0], 3);
|
||||
|
||||
out[4] = wbyte(state[1], 0);
|
||||
out[5] = wbyte(state[1], 1);
|
||||
out[6] = wbyte(state[1], 2);
|
||||
out[7] = wbyte(state[1], 3);
|
||||
|
||||
out[8] = wbyte(state[2], 0);
|
||||
out[9] = wbyte(state[2], 1);
|
||||
out[10] = wbyte(state[2], 2);
|
||||
out[11] = wbyte(state[2], 3);
|
||||
|
||||
out[12] = wbyte(state[3], 0);
|
||||
out[13] = wbyte(state[3], 1);
|
||||
out[14] = wbyte(state[3], 2);
|
||||
out[15] = wbyte(state[3], 3);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <array>
|
||||
|
||||
/*
|
||||
Author: Ondrej Hladuvka, hladuond@fit.cvut.cz
|
||||
Template: Jiri Bucek 2017
|
||||
AES specification:
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
namespace aes128_5b {
|
||||
|
||||
/* AES Constants */
|
||||
|
||||
// forward sbox
|
||||
constexpr std::array<uint8_t, 256> SBOX = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // A
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // B
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // C
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // D
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // E
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 // F
|
||||
};
|
||||
|
||||
/* AES state type */
|
||||
typedef uint32_t t_state[4];
|
||||
|
||||
#define word(a0, a1, a2, a3) ((uint32_t)(a0) | ((uint32_t)(a1) << 8) | ((uint32_t)(a2) << 16) | ((uint32_t)(a3) << 24))
|
||||
|
||||
uint8_t wbyte(uint32_t w, int pos) {
|
||||
return (w >> (pos * 8)) & 0xff;
|
||||
}
|
||||
|
||||
// **************** AES functions ****************
|
||||
uint32_t T0[256], T1[256], T2[256], T3[256];
|
||||
bool t = false;
|
||||
|
||||
constexpr uint8_t xtime(uint8_t c) {
|
||||
uint8_t m = ((c & 0x80) >> 7) * 0x1B;
|
||||
return (c << 1) ^ m;
|
||||
}
|
||||
|
||||
constexpr uint8_t multiply(uint8_t x, uint8_t y) {
|
||||
uint8_t result = 0;
|
||||
while (y) {
|
||||
if (y & 1) result ^= x;
|
||||
x = xtime(x);
|
||||
y >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr void generateTBoxes() {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint8_t s = SBOX[i];
|
||||
T0[i] = word(multiply(s, 0x02), s, s, multiply(s, 0x03));
|
||||
T1[i] = word(multiply(s, 0x03), multiply(s, 0x02), s, s);
|
||||
T2[i] = word(s, multiply(s, 0x03), multiply(s, 0x02), s);
|
||||
T3[i] = word(s, s, multiply(s, 0x03), multiply(s, 0x02));
|
||||
}
|
||||
}
|
||||
|
||||
void addRoundKey(t_state s, uint32_t ek[], short index) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s[i] ^= ek[index + i];
|
||||
}
|
||||
}
|
||||
|
||||
void aesRound(uint32_t state[4]) {
|
||||
uint32_t tmp[4];
|
||||
tmp[0] = T0[wbyte(state[0], 0)] ^ T1[wbyte(state[1], 1)] ^ T2[wbyte(state[2], 2)] ^ T3[wbyte(state[3], 3)];
|
||||
tmp[1] = T0[wbyte(state[1], 0)] ^ T1[wbyte(state[2], 1)] ^ T2[wbyte(state[3], 2)] ^ T3[wbyte(state[0], 3)];
|
||||
tmp[2] = T0[wbyte(state[2], 0)] ^ T1[wbyte(state[3], 1)] ^ T2[wbyte(state[0], 2)] ^ T3[wbyte(state[1], 3)];
|
||||
tmp[3] = T0[wbyte(state[3], 0)] ^ T1[wbyte(state[0], 1)] ^ T2[wbyte(state[1], 2)] ^ T3[wbyte(state[2], 3)];
|
||||
for (int i = 0; i < 4; i++) state[i] = tmp[i];
|
||||
}
|
||||
|
||||
void shiftRows(t_state s) {
|
||||
uint32_t tmp[4];
|
||||
|
||||
tmp[0] = s[0] & 0x0000FF00;
|
||||
tmp[1] = s[1] & 0x0000FF00;
|
||||
tmp[2] = s[2] & 0x0000FF00;
|
||||
tmp[3] = s[3] & 0x0000FF00;
|
||||
|
||||
s[0] = (s[0] & 0xFFFF00FF) | tmp[1];
|
||||
s[1] = (s[1] & 0xFFFF00FF) | tmp[2];
|
||||
s[2] = (s[2] & 0xFFFF00FF) | tmp[3];
|
||||
s[3] = (s[3] & 0xFFFF00FF) | tmp[0];
|
||||
|
||||
tmp[0] = s[0] & 0x00FF0000;
|
||||
tmp[1] = s[1] & 0x00FF0000;
|
||||
tmp[2] = s[2] & 0x00FF0000;
|
||||
tmp[3] = s[3] & 0x00FF0000;
|
||||
|
||||
s[0] = (s[0] & 0xFF00FFFF) | tmp[2];
|
||||
s[1] = (s[1] & 0xFF00FFFF) | tmp[3];
|
||||
s[2] = (s[2] & 0xFF00FFFF) | tmp[0];
|
||||
s[3] = (s[3] & 0xFF00FFFF) | tmp[1];
|
||||
|
||||
tmp[0] = s[0] & 0xFF000000;
|
||||
tmp[1] = s[1] & 0xFF000000;
|
||||
tmp[2] = s[2] & 0xFF000000;
|
||||
tmp[3] = s[3] & 0xFF000000;
|
||||
|
||||
s[0] = (s[0] & 0x00FFFFFF) | tmp[3];
|
||||
s[1] = (s[1] & 0x00FFFFFF) | tmp[0];
|
||||
s[2] = (s[2] & 0x00FFFFFF) | tmp[1];
|
||||
s[3] = (s[3] & 0x00FFFFFF) | tmp[2];
|
||||
}
|
||||
|
||||
void aesFinalRound(uint32_t state[4], uint32_t * expKey) {
|
||||
t_state tmp;
|
||||
tmp[0] = word(SBOX[wbyte(state[0], 0)], SBOX[wbyte(state[1], 1)], SBOX[wbyte(state[2], 2)], SBOX[wbyte(state[3], 3)]);
|
||||
tmp[1] = word(SBOX[wbyte(state[1], 0)], SBOX[wbyte(state[2], 1)], SBOX[wbyte(state[3], 2)], SBOX[wbyte(state[0], 3)]);
|
||||
tmp[2] = word(SBOX[wbyte(state[2], 0)], SBOX[wbyte(state[3], 1)], SBOX[wbyte(state[0], 2)], SBOX[wbyte(state[1], 3)]);
|
||||
tmp[3] = word(SBOX[wbyte(state[3], 0)], SBOX[wbyte(state[0], 1)], SBOX[wbyte(state[1], 2)], SBOX[wbyte(state[2], 3)]);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
state[i] = tmp[i] ^ expKey[10 * 4 + i];
|
||||
}
|
||||
|
||||
void aes128_5(uint8_t *in, uint8_t *out, uint32_t * expKey) {
|
||||
if (!t) generateTBoxes();
|
||||
t = true;
|
||||
|
||||
uint32_t state[4] = {
|
||||
word(in[0], in[1], in[2], in[3]),
|
||||
word(in[4], in[5], in[6], in[7]),
|
||||
word(in[8], in[9], in[10], in[11]),
|
||||
word(in[12], in[13], in[14], in[15])
|
||||
};
|
||||
|
||||
addRoundKey(state, expKey, 0);
|
||||
for (int round = 0; round < 9; round++) {
|
||||
aesRound(state);
|
||||
addRoundKey(state, expKey, round * 4 + 4);
|
||||
}
|
||||
aesFinalRound(state, expKey);
|
||||
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
out[i * 4 + 0] = wbyte(state[i], 0);
|
||||
out[i * 4 + 1] = wbyte(state[i], 1);
|
||||
out[i * 4 + 2] = wbyte(state[i], 2);
|
||||
out[i * 4 + 3] = wbyte(state[i], 3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
#include <stdint.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
/*
|
||||
Author: Ondrej Hladuvka, hladuond@fit.cvut.cz
|
||||
AES specification:
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
namespace aes128_6 {
|
||||
static inline __m128i expandRoundKey(__m128i key, __m128i keygened){
|
||||
keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3));
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
return _mm_xor_si128(key, keygened);
|
||||
}
|
||||
|
||||
void expandKey(uint8_t *key, __m128i *ex){
|
||||
ex[0] = _mm_loadu_si128((const __m128i*) key);
|
||||
ex[1] = expandRoundKey(ex[0], _mm_aeskeygenassist_si128(ex[0], 0x01));
|
||||
ex[2] = expandRoundKey(ex[1], _mm_aeskeygenassist_si128(ex[1], 0x02));
|
||||
ex[3] = expandRoundKey(ex[2], _mm_aeskeygenassist_si128(ex[2], 0x04));
|
||||
ex[4] = expandRoundKey(ex[3], _mm_aeskeygenassist_si128(ex[3], 0x08));
|
||||
ex[5] = expandRoundKey(ex[4], _mm_aeskeygenassist_si128(ex[4], 0x10));
|
||||
ex[6] = expandRoundKey(ex[5], _mm_aeskeygenassist_si128(ex[5], 0x20));
|
||||
ex[7] = expandRoundKey(ex[6], _mm_aeskeygenassist_si128(ex[6], 0x40));
|
||||
ex[8] = expandRoundKey(ex[7], _mm_aeskeygenassist_si128(ex[7], 0x80));
|
||||
ex[9] = expandRoundKey(ex[8], _mm_aeskeygenassist_si128(ex[8], 0x1B));
|
||||
ex[10] = expandRoundKey(ex[9], _mm_aeskeygenassist_si128(ex[9], 0x36));
|
||||
}
|
||||
|
||||
void aes128_6(uint8_t *in, uint8_t *out, uint32_t* key) {
|
||||
__m128i *k = (__m128i *)key;
|
||||
__m128i state = _mm_loadu_si128((__m128i *) in);
|
||||
|
||||
state = _mm_xor_si128 (state, k[ 0]);
|
||||
state = _mm_aesenc_si128 (state, k[ 1]);
|
||||
state = _mm_aesenc_si128 (state, k[ 2]);
|
||||
state = _mm_aesenc_si128 (state, k[ 3]);
|
||||
state = _mm_aesenc_si128 (state, k[ 4]);
|
||||
state = _mm_aesenc_si128 (state, k[ 5]);
|
||||
state = _mm_aesenc_si128 (state, k[ 6]);
|
||||
state = _mm_aesenc_si128 (state, k[ 7]);
|
||||
state = _mm_aesenc_si128 (state, k[ 8]);
|
||||
state = _mm_aesenc_si128 (state, k[ 9]);
|
||||
state = _mm_aesenclast_si128(state, k[10]);
|
||||
|
||||
_mm_storeu_si128((__m128i *) out, state);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
100 000 cycles:
|
||||
|
||||
implementation: OpenSSL Naive (4) With macro (5a) With T-Box (5b) Intrinsics (6)
|
||||
total time: 6.74264ms 23.6295ms 23.494ms 8.70669ms 1.18704ms
|
||||
avg time: 67.4264ns 236.295ns 234.94ns 87.0669ns 11.8704ns
|
||||
avg CPU cycles: 255 896 891 330 45
|
||||
|
||||
|
||||
|
||||
1 000 000 cycles:
|
||||
|
||||
implementation: OpenSSL Naive (4) With macro (5a) With T-Box (5b) Intrinsics (6)
|
||||
total time: 65.397ms 23.6295ms 233.56ms 88.0696ms 11.8984ms
|
||||
avg time: 65.397ns 236.295ns 233.56ns 88.0696ns 11.8984ns
|
||||
avg CPU cycles: 248 896 885 334 45
|
|
@ -0,0 +1,139 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <cstring>
|
||||
#include <chrono>
|
||||
#include <immintrin.h>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include "aes_4.cpp"
|
||||
#include "aes_5a.cpp"
|
||||
#include "aes_5b.cpp"
|
||||
#include "aes_6.cpp"
|
||||
|
||||
// AES constants
|
||||
constexpr size_t blockSize = 16;
|
||||
constexpr size_t keySize = 16;
|
||||
|
||||
size_t numTests = 1'000'000;
|
||||
size_t payloadSize = numTests * blockSize;
|
||||
|
||||
using TestTimeUnit = std::milli;
|
||||
using CycleTimeUnit = std::nano;
|
||||
|
||||
void xor_into_128bit_u(uint8_t *a, uint8_t *b) {
|
||||
__m128i vec_a = _mm_loadu_si128((__m128i*)a);
|
||||
__m128i vec_b = _mm_loadu_si128((__m128i*)b);
|
||||
|
||||
__m128i vec_result = _mm_xor_si128(vec_a, vec_b);
|
||||
|
||||
_mm_storeu_si128((__m128i*)a, vec_result);
|
||||
}
|
||||
|
||||
void xor_128bit(__m128i *a, __m128i *b, __m128i *c) {
|
||||
__m128i vec_a = _mm_load_si128(a);
|
||||
__m128i vec_b = _mm_load_si128(b);
|
||||
|
||||
__m128i vec_result = _mm_xor_si128(vec_a, vec_b);
|
||||
|
||||
_mm_store_si128(c, vec_result);
|
||||
}
|
||||
|
||||
void mov_128bit(__m128i *a, __m128i *b) {
|
||||
__m128i tmp = _mm_load_si128(a);
|
||||
_mm_store_si128(b, tmp);
|
||||
}
|
||||
|
||||
void test(void (*aes)(uint8_t *in, uint8_t *out, uint32_t *expKey), uint8_t *in, uint8_t *refOut,
|
||||
uint32_t *expandedKey, uint8_t *iv, const std::string& name) {
|
||||
std::cout << "\n\ntesting: " << name << '\n';
|
||||
|
||||
uint8_t* tmpBlock(static_cast<uint8_t*>(std::aligned_alloc(blockSize, blockSize)));
|
||||
uint8_t* outBuf(static_cast<uint8_t*>(std::aligned_alloc(blockSize, payloadSize)));
|
||||
mov_128bit(reinterpret_cast<__m128i*>(iv), reinterpret_cast<__m128i*>(tmpBlock));
|
||||
|
||||
uint64_t cycles = __rdtsc();
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
for (size_t t = 0; t < numTests; ++t) {
|
||||
aes(tmpBlock, tmpBlock, expandedKey);
|
||||
xor_128bit(reinterpret_cast<__m128i*>(tmpBlock),
|
||||
reinterpret_cast<__m128i*>(in + blockSize * t),
|
||||
reinterpret_cast<__m128i*>(outBuf + blockSize * t));
|
||||
}
|
||||
cycles = __rdtsc() - cycles;
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (std::memcmp(outBuf, refOut, payloadSize)) std::cout << "test failed!\n";
|
||||
else std::cout << "test passed\n";
|
||||
|
||||
std::chrono::duration<double, CycleTimeUnit> time = end - start;
|
||||
double timeAVG = time.count() / numTests;
|
||||
|
||||
std::cout << "total time: " << time.count()/std::ratio_divide<CycleTimeUnit, TestTimeUnit>::den << "ms\n"
|
||||
<< "avg time pro block: " << timeAVG << "ns\n"
|
||||
<< "avg cpu cycles per block: " << cycles/numTests << std::endl;
|
||||
std::free(tmpBlock);
|
||||
std::free(outBuf);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
uint8_t key[keySize];
|
||||
uint8_t iv[blockSize];
|
||||
uint32_t expandedKey[44];
|
||||
AES_KEY opensslKey;
|
||||
|
||||
if (argc > 1) {
|
||||
numTests = strtoull(argv[1], nullptr, 10);
|
||||
if ((int64_t)numTests < 1) {
|
||||
std::cout << "ivalid param" << std::endl;
|
||||
__builtin_trap();
|
||||
}
|
||||
payloadSize = numTests * blockSize;
|
||||
}
|
||||
|
||||
uint8_t* input( static_cast<uint8_t*>(std::aligned_alloc(blockSize, payloadSize)));
|
||||
uint8_t* opensslOutput(static_cast<uint8_t*>(std::aligned_alloc(blockSize, payloadSize)));
|
||||
|
||||
RAND_bytes(key, keySize);
|
||||
RAND_bytes(iv, blockSize);
|
||||
RAND_bytes(input, payloadSize);
|
||||
|
||||
// OpenSSL beg #############################################################################
|
||||
std::cout << "measuring reference: OpenSSL\n";
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
AES_set_encrypt_key(key, 128, &opensslKey);
|
||||
uint8_t* tmpBlock(static_cast<uint8_t*>(std::aligned_alloc(blockSize, blockSize)));
|
||||
mov_128bit(reinterpret_cast<__m128i*>(iv), reinterpret_cast<__m128i*>(tmpBlock));
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
size_t opensslCycles = __rdtsc();
|
||||
for (int test = 0; test < numTests; ++test) {
|
||||
AES_encrypt(tmpBlock, tmpBlock, &opensslKey);
|
||||
xor_128bit(reinterpret_cast<__m128i*>(tmpBlock),
|
||||
reinterpret_cast<__m128i*>(input + blockSize * test),
|
||||
reinterpret_cast<__m128i*>(opensslOutput + blockSize * test));
|
||||
}
|
||||
opensslCycles = __rdtsc() - opensslCycles;
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, CycleTimeUnit> opensslTime = end - start;
|
||||
double timeAVG = opensslTime.count() / numTests;
|
||||
std::cout << "time: " << opensslTime.count()/std::ratio_divide<CycleTimeUnit, TestTimeUnit>::den << "ms\navg time: " << timeAVG << "ns\navg cycles: " << opensslCycles/numTests << std::endl;
|
||||
std::free(tmpBlock);
|
||||
#pragma GCC diagnostic pop
|
||||
// OpenSSL end #############################################################################
|
||||
|
||||
aes128_4::expandKey(key, expandedKey);
|
||||
|
||||
test(aes128_4::aes128_4, input, opensslOutput, expandedKey, iv, "Naive implementation (4)");
|
||||
test(aes128_5a::aes128_5, input, opensslOutput, expandedKey, iv, "With macro (5a)");
|
||||
test(aes128_5b::aes128_5, input, opensslOutput, expandedKey, iv, "With T-Box (5b)");
|
||||
|
||||
__m128i expandedKey_128[10];
|
||||
aes128_6::expandKey(key, expandedKey_128);
|
||||
test(aes128_6::aes128_6, input, opensslOutput, (uint32_t *)expandedKey_128, iv, "Intrinsics (6)");
|
||||
|
||||
std::free(input);
|
||||
std::free(opensslOutput);
|
||||
return 0;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,394 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 212,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570419,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "qIH9E-egIPJk"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"if not os.path.exists(\"chip1.bin\"):\n",
|
||||
" !wget https://users.fit.cvut.cz/bucekj/SRAM_data.zip\n",
|
||||
" !unzip SRAM_data.zip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 340,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "c6CaoHF7IVcf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"MEASUREMENTS = 1000\n",
|
||||
"MEM_SIZE = 512*8\n",
|
||||
"CHIPS = 10\n",
|
||||
"\n",
|
||||
"memories = np.array([\n",
|
||||
" np.unpackbits(\n",
|
||||
" np.fromfile(f\"chip{i+1}.bin\", dtype='uint8')\n",
|
||||
" ).reshape(MEASUREMENTS, MEM_SIZE)\n",
|
||||
" for i in range(CHIPS)\n",
|
||||
"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"executionInfo": {
|
||||
"elapsed": 8,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "IVARKdgpMOgI",
|
||||
"outputId": "1eb61f33-4c4d-46a4-aed1-ae467881f4de"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(10, 1000, 4096)"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"memories.shape\n",
|
||||
"# cip, mereni, bit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "Iba9M10hIZql"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create reference responses\n",
|
||||
"avgs = memories.mean(axis=1, keepdims=True)\n",
|
||||
"refs = avgs>0.5 # reference responses"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "0elUoltMIbZW"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"xors = refs ^ memories # HDintra\n",
|
||||
" # finish HDintra calculation (look at the definition)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "2orRDbEnIdKh"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"idxs = np.triu_indices(CHIPS, 1)\n",
|
||||
"pairwise_xors = refs[idxs[0]] ^ refs[idxs[1]]\n",
|
||||
"inter = pairwise_xors.mean()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "M4maPUbhIfF2"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create masks\n",
|
||||
"e = 0.05 # error rate into the mask (5%)\n",
|
||||
"masks = (avgs > (1-e)) | (avgs < e)\n",
|
||||
"masks = masks[:,0,:]\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "JQaOfv7Jin6S"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Save masks into file\n",
|
||||
"np.savetxt('masks.txt', masks.astype(int), fmt='%d', delimiter='')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "qsDh1_3DImCW"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create masked responses (1024 bits long)\n",
|
||||
"mask_idx = np.array([np.nonzero(masks[i])[0][:1024] for i in range(CHIPS)])\n",
|
||||
"memories_masked = np.array([memories[i][:,mask_idx[i]] for i in range(CHIPS)])\n",
|
||||
"refs_masked = np.array([refs[i][:,mask_idx[i]] for i in range(CHIPS)])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "IhsqiP0WIqTe"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Compute HDintra of masked PUF responses\n",
|
||||
"masked_xors = refs_masked ^ memories_masked # HDintra\n",
|
||||
" # finish HDintra calculation (look at the definition)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 7,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157570996,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "S8omYwr1It2_"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Compute HDinter of masked PUF responses\n",
|
||||
"idxs = np.triu_indices(CHIPS, 1)\n",
|
||||
"pairwise_xors = refs_masked[idxs[0]] ^ refs_masked[idxs[1]]\n",
|
||||
"masked_inter = pairwise_xors.mean()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"executionInfo": {
|
||||
"elapsed": 297,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157721196,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "jB0oHd-Mjkbx",
|
||||
"outputId": "75f811c4-4a3f-420a-8bb0-3a9b54bb94a9"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vzdalenosti jednotlivych cipu: [0.03431421 0.02955688 0.0316062 0.03096167 0.0320459 0.02866528\n",
|
||||
" 0.0269895 0.03107129 0.03059814 0.02904199]\n",
|
||||
"\n",
|
||||
"HDintra prumerny: 0.030485107421875\n",
|
||||
"HDinter: 0.43573133680555554\n",
|
||||
"\n",
|
||||
"vyhovujicich bitu je 0.8744384765625 %\n",
|
||||
"\n",
|
||||
"Masked vzdalenosti jednotlivych cipu: [0.00191406 0.0017832 0.00191211 0.00174609 0.00198633 0.00169141\n",
|
||||
" 0.0015 0.00189844 0.00163672 0.00171484]\n",
|
||||
"\n",
|
||||
"Masked HDintra prumerny: 0.0017783203125\n",
|
||||
"Masked HDinter: 0.4957682291666667\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Print a summary of results (HDintra, HDinter - for both unmasked and masked PUF responses)\n",
|
||||
"print(\"Vzdalenosti jednotlivych cipu:\", xors.mean(axis=1).mean(axis=1))\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(\"HDintra prumerny:\", xors.mean())\n",
|
||||
"print(\"HDinter: \", inter)\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(\"vyhovujicich bitu je \", masks.mean(), \"%\")\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(\"Masked vzdalenosti jednotlivych cipu: \", masked_xors.mean(axis=1).mean(axis=1))\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(\"Masked HDintra prumerny:\", masked_xors.mean())\n",
|
||||
"\n",
|
||||
"print(\"Masked HDinter: \", masked_inter)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"executionInfo": {
|
||||
"elapsed": 2,
|
||||
"status": "ok",
|
||||
"timestamp": 1733157571185,
|
||||
"user": {
|
||||
"displayName": "Ondřej Hladůvka",
|
||||
"userId": "07082375608847075000"
|
||||
},
|
||||
"user_tz": -60
|
||||
},
|
||||
"id": "ZFVMMBQ8PFBc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [
|
||||
{
|
||||
"file_id": "https://gist.github.com/kodytfil/ca2be4dfc2413f2335451994308fb3c5#file-puf_template-ipynb",
|
||||
"timestamp": 1733152912568
|
||||
}
|
||||
]
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.15"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
Loading…
Reference in New Issue