はじめに AESのIPコア 仕様 設計 テスト ビルド ソフトでのテスト 感想
H8とFPGAが接続されたボードとして、 ストロベリーリナックスの SPARTAN-COMPLETE を使います。
また、ツールは、XilinxのISE WebPack 9.1i を使います。
※ (H8とFPGAのバス接続の)簡単な例は、 こちらをご参照。
このコアの概略仕様:
一方、systemcaes は小規模になるように作られていて、
XC2S200にも収めることができました。
その代わり、性能的には、
aes_core が暗号:11サイクル、復号:22サイクル(内鍵拡張11サイクル)に対して、
暗号、復号とも:約500サイクルかかってしまうようです。
なお、systemcaesの仕様は、aes_coreのものと同様になっていて、 テストベンチもaes_coreのものを改造して使っているようです。
なお、全部(284個のテストデータについて)実行するとすごーーく時間がかかるので、 最初の3データについて実行してみました。 そのため、テストベンチtest_bench_top.v中のループ箇所を以下のようにしたりしました。
//for(n=0;n<284;n=n+1) for(n=0;n<3;n=n+1) begin
シミュレータとしては、WebPack ISE9.1i に付属する ISE Simulator を使いました。 実行して、最初のテストデータについて暗号化および復号化している箇所を表示してみました。
最初のテストデータ:
tv[0]= 384'h00000000000000000000000000000000f34481ec3cc627bacd5dc3fb08f273e60336763e966d92595a567cc9ce537f5e;
まず、暗号化の開始部分を拡大してみました。
keyが鍵、text_inが平文です。
kld (load_i)をアサートすることで、暗号化を開始するようです。
done (ready_o)がアサートされて、 text_out(data_o)に暗号文(0336763e966d92595a567cc9ce537f5e)が出てきています。
doneは復号用にインスタンシエートしたu1のload_iにも接続されているので、 暗号化終了と同時に復号化を開始します。 (復号終了時にはdone2(ready_o)がアサートされます。)
機能としては以下の通りとします。
H8ソフトから見て、
バスコントローラ設定としては、 エリア4について、
アドレス | レジスタ名 | 機能 |
---|---|---|
0x00 : 0x0f | KEY 0 : KEY 15 | 鍵(8bit×16個) |
0x10 : 0x1f | DIN 0 : DIN 15 | 入力データ(8bit×16個) |
0x20 : 0x2f | IV 0 : IV 15 | IV(8bit×16個) |
0x30 : 0x3f | DOUT 0 : DOUT 15 | 出力データ(8bit×16個) |
0x40 | CTRL | 暗号(bit0=0)/復号(bit0=1)選択、CBC(bit1=1)、処理開始(bit2=1) |
0x41 | STATUS | ビジー(bit7=1) |
ISEのプロジェクト一式:
aes_h8.zip
aes_h8がトップレベルのモジュールです。 その直下のモジュールは以下の3つに分かれています。
H8 CPUからバスを介してこのFPGAにアクセスするシーケンスを シミュレートしています。
なお、AES128-CBCのテストベクタは、 http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf にあるものを使用しています。
ビジービットが落ちた後 DOUTレジスタ (アドレス30h〜3fh) をリードする部分です。
DOUTレジスタからは暗号文 (128'h5086cb9b507219ee95db113a917678b2)
を先頭から読み出しています。
前述のプロジェクトに含まれる。 aes_h8.ise をクリックして、 ISEを起動して、ビルド(論理合成、配置配線、等)します。
FPGAに書き込む aes_h8.bit ができるとこまでやります。
デバイス使用率はこちら。
# NET "CLK" LOC = "P185" ; NET "ADDR<0>" LOC = "P181" ; NET "ADDR<1>" LOC = "P180" ; NET "ADDR<2>" LOC = "P179" ; NET "ADDR<3>" LOC = "P178" ; NET "ADDR<4>" LOC = "P176" ; NET "ADDR<5>" LOC = "P175" ; NET "ADDR<6>" LOC = "P174" ; NET "DATA<0>" LOC = "P195" ; NET "DATA<1>" LOC = "P194" ; NET "DATA<2>" LOC = "P193" ; NET "DATA<3>" LOC = "P192" ; NET "DATA<4>" LOC = "P191" ; NET "DATA<5>" LOC = "P189" ; NET "DATA<6>" LOC = "P188" ; NET "DATA<7>" LOC = "P187" ; NET "nWE" LOC = "P147" ; NET "nOE" LOC = "P150" ; NET "nCS" LOC = "P149" ; NET "nRST" LOC = "P138" | PULLUP ; NET "nAS" LOC = "P139" ;
ただし、SPARTAN-COPLETEは25MHzクロックを使っているので、 以下の変更が必要です。 monix/sys.hの
# define CPU_HZ 20 /* MHz */を
# define CPU_HZ 25 /* MHz */に変えます。
また、AESのテストコマンドを追加します。
aes128.h
#ifndef __AES128_H__ #define __AES128_H__ #include "types.h" /* Base address */ #define AES_BASE 0x800000 /* Registers */ #define AES_KEY (AES_BASE + 0x00) #define AES_DIN (AES_BASE + 0x10) #define AES_IV (AES_BASE + 0x20) #define AES_DOUT (AES_BASE + 0x30) #define AES_CTRL (AES_BASE + 0x40) #define AES_STATUS (AES_BASE + 0x41) /* Bit definitions */ # define AES_CTRL_ENC 0x00 # define AES_CTRL_DEC 0x01 # define AES_CTRL_CBC 0x02 # define AES_CTRL_START 0x04 # define AES_STATUS_BUSY 0x80 /* Register access macros */ #define aes_outb(x, y) *(volatile u_char *)(x) = (y) #define aes_inb(x) *(volatile u_char *)(x) /* AES128-CBC functions */ extern void aes128_encrypt(u_char *key, u_char *iv, u_char *din, u_char *dout, u_long len); extern void aes128_decrypt(u_char *key, u_char *iv, u_char *din, u_char *dout, u_long len); #endif /* __AES128_H__ */
aes128.c
#include "aes128.h" void aes128_encrypt(u_char *key, u_char *iv, u_char *din, u_char *dout, u_long len) { u_char *dinp; u_char *doutp; u_char *ivp; int i; /* Input key */ for (i = 0; i < 16; i++) aes_outb(AES_KEY + i, key[i]); for (dinp = din, doutp = dout, ivp = iv; len >= 16; ivp = doutp, dinp += 16, doutp += 16, len -= 16) { /* Input IV */ for (i = 0; i < 16; i++) aes_outb(AES_IV + i, ivp[i]); /* Input plaintext */ for (i = 0; i < 16; i++) aes_outb(AES_DIN + i, dinp[i]); /* Start encryption */ aes_outb(AES_CTRL, AES_CTRL_ENC | AES_CTRL_CBC | AES_CTRL_START); while (aes_inb(AES_STATUS) & AES_STATUS_BUSY) ; /* Output ciphertext */ for (i = 0; i < 16; i++) doutp[i] = aes_inb(AES_DOUT + i); } } void aes128_decrypt(u_char *key, u_char *iv, u_char *din, u_char *dout, u_long len) { u_char *dinp; u_char *doutp; u_char *ivp; int i; /* Input key */ for (i = 0; i < 16; i++) aes_outb(AES_KEY + i, key[i]); for (dinp = din, doutp = dout, ivp = iv; len >= 16; ivp = dinp, dinp += 16, doutp += 16, len -= 16) { /* Input IV */ for (i = 0; i < 16; i++) aes_outb(AES_IV + i, ivp[i]); /* Input ciphertext */ for (i = 0; i < 16; i++) aes_outb(AES_DIN + i, dinp[i]); /* Start decryption */ aes_outb(AES_CTRL, AES_CTRL_DEC | AES_CTRL_CBC | AES_CTRL_START); while (aes_inb(AES_STATUS) & AES_STATUS_BUSY) ; /* Output plaintext */ for (i = 0; i < 16; i++) doutp[i] = aes_inb(AES_DOUT + i); } }
{"aestest", CmdAesTest},
// Test Vector from // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf // // F.2.1 CBC-AES128.Encrypt // Key 2b7e151628aed2a6abf7158809cf4f3c // IV 000102030405060708090a0b0c0d0e0f // // Block #1 // Plaintext 6bc1bee22e409f96e93d7e117393172a // Input Block 6bc0bce12a459991e134741a7f9e1925 // Output Block 7649abac8119b246cee98e9b12e9197d // Ciphertext 7649abac8119b246cee98e9b12e9197d // // Block #2 // Plaintext ae2d8a571e03ac9c9eb76fac45af8e51 // Input Block d86421fb9f1a1eda505ee1375746972c // Output Block 5086cb9b507219ee95db113a917678b2 // Ciphertext 5086cb9b507219ee95db113a917678b2 // // Block #3 // Plaintext 30c81c46a35ce411e5fbc1191a0a52ef // Input Block 604ed7ddf32efdff7020d0238b7c2a5d // Output Block 73bed6b8e3c1743b7116e69e22229516 // Ciphertext 73bed6b8e3c1743b7116e69e22229516 // // Block #4 // Plaintext f69f2445df4f9b17ad2b417be66c3710 // Input Block 8521f2fd3c8eef2cdc3da7e5c44ea206 // Output Block 3ff1caa1681fac09120eca307586e1a7 // Ciphertext 3ff1caa1681fac09120eca307586e1a7 unsigned char key[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; unsigned char iv[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; unsigned char plain[][16] = { {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, {0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}, {0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef}, {0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}, }; unsigned char cipher[][16] = { {0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d}, {0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2}, {0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16}, {0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7}, }; unsigned char out[4][16]; #include "aes128.h" int CmdAesTest(char *arg) { /* Set Bus Controller */ BSC.CSCR.BIT.CS4E = 1; /* Enable /CS4 */ BSC.ABWCR.BIT.ABW4 = 1; /* 8-bit width access for area4 */ BSC.ASTCR.BIT.AST4 = 1; /* 3-state access for area 4 */ BSC.WCR.BIT.W4 = 0; /* no program wait for area 4 */ /* AES128-CBC encrypt */ printf("==== CBC encrypt ====\n"); printf("key:\n"); MemDump(key, 16, 0); printf("iv:\n"); MemDump(iv, 16, 0); printf("plain:\n"); MemDump(plain[0], 16, 0); aes128_encrypt(key, iv, plain[0], out[0], 16); printf("cipher:\n"); MemDump(out[0], 16, 0); if (memcmp(out[0], cipher[0], 16) != 0) { printf("NG expected:\n"); MemDump(cipher[0], 16, 0); } else { printf("OK\n"); } printf("Registers:\n"); MemDump((u_char *)AES_BASE, 128, 0); /* AES128-CBC decrypt */ printf("==== CBC decrypt ====\n"); printf("key:\n"); MemDump(key, 16, 0); printf("iv:\n"); MemDump(iv, 16, 0); printf("cipher:\n"); MemDump(cipher[0], 16, 0); aes128_decrypt(key, iv, cipher[0], out[0], 16); printf("plain:\n"); MemDump(out[0], 16, 0); if (memcmp(out[0], plain[0], 16) != 0) { printf("NG expected:\n"); MemDump(plain[0], 16, 0); } else { printf("OK\n"); } printf("Registers:\n"); MemDump((u_char *)AES_BASE, 128, 0); /* AES128-CBC encrypt */ printf("==== CBC encrypt (Multiple blocks) ====\n"); printf("key:\n"); MemDump(key, 16, 0); printf("iv:\n"); MemDump(iv, 16, 0); printf("plain:\n"); MemDump(plain, 16 * 4, 0); aes128_encrypt(key, iv, plain, out, 16 * 4); printf("cipher:\n"); MemDump(out, 16 * 4, 0); if (memcmp(out, cipher, 16 * 4) != 0) { printf("NG expected:\n"); MemDump(cipher, 16 * 4, 0); } else { printf("OK\n"); } printf("Registers:\n"); MemDump((u_char *)AES_BASE, 128, 0); /* AES128-CBC decrypt */ printf("==== CBC decrypt (Multiple blocks) ====\n"); printf("key:\n"); MemDump(key, 16, 0); printf("iv:\n"); MemDump(iv, 16, 0); printf("cipher:\n"); MemDump(cipher, 16 * 4, 0); aes128_decrypt(key, iv, cipher, out, 16 * 4); printf("plain:\n"); MemDump(out, 16 * 4, 0); if (memcmp(out, plain, 16 * 4) != 0) { printf("NG expected:\n"); MemDump(plain, 16 * 4, 0); } else { printf("OK\n"); } printf("Registers:\n"); MemDump((u_char *)AES_BASE, 128, 0); return 0; }
これでビルドしたものを使います。
ビルドしたmonix.motをH8の内蔵ROMに書きます。
MONIX Ver.0.1 (Mar 14 2007, 23:05:33) BootMode: 0x00 1:
aes_h8.bitをISE(の書き込みツールIMPACT)を使ってFPGAに書き込みます。※
※ 私はコンフィグROMを搭載してないSPARTAN-COMPLETEを買ったので、 電源を入れ直すたびに書き込みをする必要があります。
ロジックを書けたら、aestestコマンドを実行します。
1:aestest ==== CBC encrypt ==== →CBC暗号化テスト key: →鍵 ffbf20 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< iv: →IV ffbf30 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ plain: →平文 ffbf40 6bc1 bee2 2e40 9f96 - e93d 7e11 7393 172a k....@...=~.s..* cipher: →暗号文(暗号化結果) ffc470 7649 abac - 8119 b246 cee9 8e9b vI.....F.... ffc480 12e9 197d - ...} OK Registers: →レジスタダンプ 800000 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< 800010 6bc1 bee2 2e40 9f96 - e93d 7e11 7393 172a k....@...=~.s..* 800020 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ 800030 7649 abac 8119 b246 - cee9 8e9b 12e9 197d vI.....F.......} 800040 0200 0000 0000 0000 - 0000 0000 0000 0000 ................ 800050 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800060 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800070 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ ==== CBC decrypt ==== →CBC復号化テスト key: →鍵 ffbf20 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< iv: →IV ffbf30 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ cipher: →暗号文 ffbf80 7649 abac 8119 b246 - cee9 8e9b 12e9 197d vI.....F.......} plain: →平文(復号化結果) ffc470 6bc1 bee2 - 2e40 9f96 e93d 7e11 k....@...=~. ffc480 7393 172a - s..* OK Registers: →レジスタダンプ 800000 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< 800010 7649 abac 8119 b246 - cee9 8e9b 12e9 197d vI.....F.......} 800020 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ 800030 6bc1 bee2 2e40 9f96 - e93d 7e11 7393 172a k....@...=~.s..* 800040 0300 0000 0000 0000 - 0000 0000 0000 0000 ................ 800050 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800060 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800070 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ ==== CBC encrypt (Multiple blocks) ==== →CBC暗号化(複数ブロック)テスト key: ffbf20 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< iv: ffbf30 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ plain: ffbf40 6bc1 bee2 2e40 9f96 - e93d 7e11 7393 172a k....@...=~.s..* ffbf50 ae2d 8a57 1e03 ac9c - 9eb7 6fac 45af 8e51 .-.W......o.E..Q ffbf60 30c8 1c46 a35c e411 - e5fb c119 1a0a 52ef 0..F.\........R. ffbf70 f69f 2445 df4f 9b17 - ad2b 417b e66c 3710 ..$E.O...+A{.l7. cipher: ffc470 7649 abac - 8119 b246 cee9 8e9b vI.....F.... ffc480 12e9 197d 5086 cb9b - 5072 19ee 95db 113a ...}P...Pr.....: ffc490 9176 78b2 73be d6b8 - e3c1 743b 7116 e69e .vx.s.....t;q... ffc4a0 2222 9516 3ff1 caa1 - 681f ac09 120e ca30 ""..?...h......0 ffc4b0 7586 e1a7 - u... OK Registers: 800000 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< 800010 f69f 2445 df4f 9b17 - ad2b 417b e66c 3710 ..$E.O...+A{.l7. 800020 73be d6b8 e3c1 743b - 7116 e69e 2222 9516 s.....t;q..."".. 800030 3ff1 caa1 681f ac09 - 120e ca30 7586 e1a7 ?...h......0u... 800040 0200 0000 0000 0000 - 0000 0000 0000 0000 ................ 800050 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800060 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800070 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ ==== CBC decrypt (Multiple blocks) ==== →CBC復号化(複数ブロック)テスト key: ffbf20 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< iv: ffbf30 0001 0203 0405 0607 - 0809 0a0b 0c0d 0e0f ................ cipher: ffbf80 7649 abac 8119 b246 - cee9 8e9b 12e9 197d vI.....F.......} ffbf90 5086 cb9b 5072 19ee - 95db 113a 9176 78b2 P...Pr.....:.vx. ffbfa0 73be d6b8 e3c1 743b - 7116 e69e 2222 9516 s.....t;q..."".. ffbfb0 3ff1 caa1 681f ac09 - 120e ca30 7586 e1a7 ?...h......0u... plain: ffc470 6bc1 bee2 - 2e40 9f96 e93d 7e11 k....@...=~. ffc480 7393 172a ae2d 8a57 - 1e03 ac9c 9eb7 6fac s..*.-.W......o. ffc490 45af 8e51 30c8 1c46 - a35c e411 e5fb c119 E..Q0..F.\...... ffc4a0 1a0a 52ef f69f 2445 - df4f 9b17 ad2b 417b ..R...$E.O...+A{ ffc4b0 e66c 3710 - .l7. OK Registers: 800000 2b7e 1516 28ae d2a6 - abf7 1588 09cf 4f3c +~..(.........O< 800010 3ff1 caa1 681f ac09 - 120e ca30 7586 e1a7 ?...h......0u... 800020 73be d6b8 e3c1 743b - 7116 e69e 2222 9516 s.....t;q..."".. 800030 f69f 2445 df4f 9b17 - ad2b 417b e66c 3710 ..$E.O...+A{.l7. 800040 0300 0000 0000 0000 - 0000 0000 0000 0000 ................ 800050 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800060 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 800070 0000 0000 0000 0000 - 0000 0000 0000 0000 ................ 1: