POWER8 のメモリー内暗号化 AES 命令の使用法の紹介 Leonidas S. Barbosa ([email protected]) Software engineer, IBM IBM 2015年 11月 12日 POWER8 に用意されているメモリー内命令を暗号アプリケーションで使用すると、Advanced Encryption Standard (AES) による暗号化/復号化が高速化されて、パフォーマンスが向上しま す。この記事では、メモリー内命令を使用する方法を説明します。 POWER8 は、POWER アーキテクチャーをベースとしたスーパー・スカラー方式の対称型マルチプ ロセッサー・ファミリーです。POWER8 シリーズでは暗号化機能を強化しており、AES (Advanced Encryption Standard) 対称鍵暗号標準に従って、メモリー内で暗号化するように強化した機能を実 装しています。 POWER8 の AES 命令セットには、AES ブロック暗号の暗号化/復号化を処理する 5 つのベクトル命 令があります。さらに POWER8 にはガロア体で乗算を行うための命令も用意されていて、GCM (Galois/Counter Mode: ガロア/カウンター・モード) および GHASH アルゴリズムを実装するために 使用できるようになっています [1]。 この記事では POWER8 の暗号化関連の命令を紹介するとともに、それらの命令を使用してアプリ ケーションやドライバーに AES や AES モードを実装する方法をデモンストレーションする、簡単 な例を紹介します。 AES の概要 Rijndael としても知られる AES (Advanced Encryption Standard) は、米国国立標準技術研究所 (NIST) によって 2001年に電子データの暗号化標準として制定されました。AES は対称鍵アルゴリズムで あり、16 バイト/128 ビットのデータ・ブロックを処理します。つまり、AES はブロック暗号アル ゴリズムです。AES が処理する 128 ビットのブロックは、VMX/VSX の 128 ビットのレジスターに 収まります。このアルゴリズムでの鍵長は、128 ビット、192 ビット、256 ビットのいずれかで す。POWER8 アーキテクチャーでは、AES アルゴリズムを実装して 5 つの命令によって AES アル ゴリズムの極めて重要なステップ (特に拡張鍵と AES 暗号化/復号化のラウンド処理の部分) をメモ リー内で実行することができます。 © Copyright IBM Corporation 2015 POWER8 のメモリー内暗号化 商標 ページ 1 / 12 developerWorks® ibm.com/developerWorks/jp/ VMX (Vector Multimedia eXtension) POWER8 で強化された機能の 1 つは、SIMD 型の統合マルチパイプライン・ベクトル命令を実装 し、32 個の 128 ビット VMX ベクトル・レジスターをサポートしていることです。ベクトル・ データは、以下の表に示すようにさまざまな方法で表現することができます。 qword dword dword word word hword 0x00 hword 0x01 0x02 word wword 0x03 0x04 hword 0x05 0x06 word hword 0x07 0x08 hword 0x09 0x0a hword 0x0b 0x0c hword 0x0d 0x0e 0x0f * hword = 2 バイト、word = 4 バイト、dword = 8 バイト、qword = 16 バイト ここで AES を使用する目的として、暗号化/復号化ステップで最大長の AES 鍵の処理やステート/ 暗号テキストの処理を実行可能な 16 バイト・フルのベクトルを使用する場合を考えてください。 AES アルゴリズム AES アルゴリズムは、次のステップに分けることができます。 • 鍵の拡張/ラウンド鍵の生成 • RotWord • SubBytes • Rcon Xor • InitialRound • AddKeyRound • Rounds • SubBytes • ShiftRows • MixColumns • AddRoundKey • Final Round (no Mixcolumns) • SubBytes • ShiftRows • AddRoundKey 次の「鍵の拡張/ラウンド鍵の生成」セクションでこのアルゴリズムの概要を説明し、そのサブセ クションで、それぞれのステップについて説明します。 POWER8 のメモリー内暗号化 ページ 2 / 12 ibm.com/developerWorks/jp/ developerWorks® 図 1. AES のフローチャート 鍵の拡張/ラウンド鍵の生成 鍵の拡張/ラウンド鍵の生成ステップでは、特定の鍵を出発点に、その鍵を複数の鍵へと拡張しま す。128 ビットの鍵は 11 個の鍵へと拡張されます。192 ビットの鍵は 13 個の鍵へと拡張されま す。256 ビットの鍵は 15 個の鍵へと拡張されます。 最初の拡張鍵は、元の鍵の最後のワードから生成されます。この元の鍵の最後のワードは 3 つの ステップで処理され、それによって 1 つのワードが生成されます。そして今度はこの 3 つのス テップによって生成されたワードが、拡張鍵を構成する 4 つすべてのワードを生成するために使 用されます。次のラウンドでは、前のラウンドで生成された鍵の最後のワードを使用します。こ のプロセスが、すべての鍵が生成されるまで繰り返されます。注意する点として、初期の鍵のサ イズとは関係なく、AES は内部では常に 16 バイトの鍵を使用します。 RotWord ステップ RotWord (Rotate Word) ステップでは、ワードを処理してワードのバイトを次のようにローテート します。 バイト 0 1 2 3 -> 1 2 3 0 例: 以下のワードを処理するとします。 79 d2 85 46 RotWord ステップにより、以下のように処理されます。 POWER8 のメモリー内暗号化 ページ 3 / 12 developerWorks® ibm.com/developerWorks/jp/ d2 85 46 79 SubBytes ステップ SubBytes ステップでは、ワード内のバイトをそのワードのガロア体 GF(28) における乗法逆元で置 8 4 3 き換える変換テーブル (S-Box) を使用します GF(2)[x]/(x +X +x +x+1) [2]。復号化の場合は、逆 SBox を使用します。 図 2. S-Box S-Box を使用すると、例えばバイト 0x9a は 0xb8 で置き換えられます。このステップは、vcipher 命令と vcipherlast 命令を使用して内部で行われます。逆 S-Box の演算も内部で行われ、vncipher 命令と vncipherlast 命令が使用されます。 例えば、以下のワードを処理するとします。 af 7f 67 98 SubBytes (ワード) 演算によって、以下の結果になります。 79 d2 85 46 Rcon Xor ステップ ラウンド・カウンター・ステップ Rcon は、ユーザーによって指定された値に対して 2 の指数関数 を適用した値です [3]。AES では、この値がラウンド定数となります。 必要となる AES ラウンド定数の数は、鍵のサイズで決まります。128 ビット鍵の場合は Rcon(10) まで、192 ビット鍵の場合は Rcon(8) まで、256 ビット鍵の場合は Rcon(7) までが必要となりま す。したがって、AES で考えられるあらゆる場合に備え、次のように Rcon(1) から Rcon(10) を保 存しておく必要があります。 POWER8 のメモリー内暗号化 ページ 4 / 12 ibm.com/developerWorks/jp/ developerWorks® Rcon(1-10) = 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 最初の拡張鍵を生成するには、Rcon を使用した加算を行います。つまり、<鍵のワード> xor Rcon(1) すなわち <鍵のワード> xor 01 00 00 00 を実行します。 以下に拡張鍵の仕組みの完全な例を示します。 Key: 0xac 0x2b 0x3c 0xdd 0xee 0x04 0x11 0x44 0xa1 0x4b 0x5c 0xd1 0x6a 0xb9 0x1c 0xdd Splitting key W0 = ac 2b 3c W1 = ee 04 11 W2 = a1 4b 5c W3 = 6a b9 1c into words for the first key in key expand buffer: dd 44 d1 dd Key expand algorithm always uses the last word to execute steps, in our case W3: X1 <- RotWord(w3) X1 = b9 1c dd 6a Y1 <- SubBytes(X1) Y1 = 56 9c c1 02 Rcon(1) = 01 00 00 00 Z1 <- Y1 xor 01 00 00 00 Z1 = 57 9c c1 02 -------------------Second key in key expand buffer: W4 = W0 xor Z1 = fb b7 fd df W5 = (W4 xor W1) = 15 b3 ec 9b W6 = (W5 xor W2) = b4 f8 b0 4a W7 = (W6 xor W3) = de 41 ac 97 ______________________________ X2 <- RodWord(W7) X2 = 41 ac 97 de Y2 <- SubBytes(X2) Y2 = 83 91 88 1d Rcon(2) = 02 00 00 00 Z2 <- Y2 xor 02 00 00 00 Z2 = 81 91 88 1d -----------------------------Third key in key expand buffer: W8 = W4 xor z2 = 7a 26 75 c2 W9 = (W8 xor W5) = 6f 95 99 59 W10 = (W9 xor W6) = db 6d 29 13 W11 = (W10 xor W7) = 52 c8 58 40 (...) ここで、POWER8 のベクトル命令と AES 命令を使用して拡張鍵を作成する方法を見ていきましょ う。 まず始めに、AES 命令を調べる必要があります。前述のように、POWER8 には 5 つの AES 命令が 用意されています。具体的には、vcipher, vcipherlast, vncipher, vncipherlast、および vsbox の 5 つです。それでは、最初の 2 つに目を向けてみましょう。 vcipher VRT,VRA,VRB State ← VR[VRA] RoundKey ← VR[VRB] vtemp1 ← SubBytes(State) vtemp2 ← ShiftRows(vtemp1) vtemp3 ← MixColumns(vtemp2) VR[VRT] ← vtemp3 ^ RoundKey POWER8 のメモリー内暗号化 ページ 5 / 12 developerWorks® ibm.com/developerWorks/jp/ は、現在のラウンドでの暗号テキストですが、AES の最初のステップでの平文の場合もあ ります。どちらの値も 16 バイト、つまり AES のブロック・サイズです。RoundKey は、その名前 からわかるように、現在のラウンドでの鍵です。VMX ベクトルは 16 バイトであるため、フルサ イズのラウンド鍵と暗号テキストを処理することができます。 State vcipherlast VRT,VRA,VRB State ←VR[VRA] RoundKey ← VR[VRB] vtemp1 ← SubBytes(State) vtemp2 ← ShiftRows(vtemp1) VR[VRT] ← vtemp2 ^ RoundKey vcipherlast は、MixColumns の 1 ステップがないことを除けば、vcipher と同じです。 vncipher と vncipherlastt は、vcipher と vcipherlast と比べると、復号化を目的としていて逆 のステップを使用していること以外はまったく同じです。 POWER8 には、鍵の拡張に固有の命令はありませんが、vcipherlast にいくつかのステップを追加 して使用すれば、鍵の拡張操作を行うことができます。 以下のステップでは、vcipherlast を使用して鍵の拡張操作を実行する方法の一例を示します。 この例では Rcon ポインターがすでにベクトルにロードされていますが、vmx-crypto ドライバー を調べれば、詳細を確認することができます [5]。また、Power PC アセンブリーのコード・レジ スターは、名前ではなく番号で参照されることに注意してください。例えば、vperm 3,1,1,5 の場 合、vr3 を結果のレジスターとして取り、vr1 と vr5 をパラメーターのレジスターとして使用しま す。詳細については、[4] を参照してください。 /** * vr1 is the first key = 0xac 0x2b 0x3c 0xdd 0xee 0x04 0x11 0x44 0xa1 0x4b 0x5c 0xd1 0x6a 0xb9 0x1c 0xdd * vr5 is a mask to rotate a word in applied for all four words in our key. * vr5 = 0x0d0e0f0c 0d0e0f0c 0d0e0f0c 0d0e0f0c * vr3 is the key in use destination * vr4 is the first rcon loaded: 01 00 00 00 01 00 00 00 01 00 00 00 * 01 00 00 00 **/ Loop128: 1 vperm 3,1,1,5 2 vsldoi 6,0,1,12 3 vcipherlast 3,3,4 4 vxor 1,1,6 5 vsldoi 6,0,6,12 6 vxor 1,1,6 7 vsldoi 6,0,6,12 8 vxor 1,1,6 9 vadduwm 4,4,4 10 vxor 1,1,3 11 bdnz Loop128 ライン 1 は、鍵にマスクを適用します。この例の場合、vperm 命令の実行後は、vr3 が以下のよう になります。 0xb91cdd6a 0xb91cdd6a 0xb91cdd6a 0xb91cdd6a POWER8 のメモリー内暗号化 ページ 6 / 12 ibm.com/developerWorks/jp/ developerWorks® ライン 2 の実行後は、以下の結果になります。 0x0000000ac2b3cddee041144a14b5cd1 ライン 3 は vcipherlast を呼び出して、SubBytes、ShiftRows、および xor Rcon(n) を実行します。 ただし、Power ISA 2.07B での ShiftRows 関数の定義により [4]、このベクトルでは ShiftRows を適 用しても有効になりません。この特定のシナリオで実行されるのは、SubBytes および xor Rcon(n) のみです。つまり、最初のワード Z または Z1 だけが生成されます。したがって、vcipherlast の 実行後は以下の結果となります。 Z1: 0x579cc102 579cc102 579cc102 579cc102 ライン 4 からライン 8 までは、鍵拡張アルゴリズムで鍵のワードを生成するための計算を行いま す。 W4 W5 W6 W7 = = = = (W0 (W1 (W2 (W3 xor xor xor xor Z1) W4) W5) W6) これらは、以下のように書き換えることもできます。 W4' W5' W6' W7' = = = = W0 W1 xor W0 W2 xor W1 or W0 W3 xor W2 Xor W1 xor W0 ここで、「'」は Z1 が適用される前のテンポラリー・ワードを意味します。 ライン 4 からライン 8 の詳細な演算は以下のとおりです。 W0 W1 W2 W3 vr1 0xac2b3cdd 0xee041144 0xa14b5cd1 0x6ab91cdd W0 W1 W2 w3 vr6 0x00000000 0xac2b3cdd 0xee041144 0xa14b5cd1 ------------------------------------------W4' W5' temp-W6' temp-W7' vr1 0xac2b3cdd 0x422f2d99 0x4f4f4d95 0xcbf2400c W0 W1 vr6 0x00000000 0x00000000 0xac2b3cdd 0xee041144 ------------------------------------------W4' W5' W6' temp-W7' vr1 0xac2b3cdd 0x422f2d99 0xe3647148 0x25f65148 W0 vr6 0x00000000 0x00000000 0x00000000 0xac2b3cdd ------------------------------------------W4' W5' W6' W7' vr1 0xac2b3cdd 0x422f2d99 0xe3647148 0x89dd6d95 ライン 9 は、次のラウンドのための rcon を追加します。 vr4 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 最後にライン 10 が Z1 ワードを適用して、拡張される最初の鍵が生成されます。 POWER8 のメモリー内暗号化 ページ 7 / 12 developerWorks® ibm.com/developerWorks/jp/ W4' W5' W6' W7' vr1 0xac2b3cdd 0x422f2d99 0xe3647148 0x89dd6d95 Z1 Z1 Z1 Z1 vr3 0x579cc102 0x579cc102 0x579cc102 0x579cc102 ------------------------------------------W4 W5 W6 W7 vr1 0xfbb7fddf 0x15b3ec9b 0xb4f8b04a 0xde41ac97 ライン 11 でループの先頭に戻り、必要とされるラウンド数の回数に従って、上記のすべてのス テップが繰り返されます。 鍵の拡張と比べると、AES のラウンドが単純になっているのは、これらのラウンドには、拡張鍵 と暗号化または復号化対象のデータしか必要でないためです。 以下の単純な例に、メモリー内の命令を使用する方法を示します。これよりも正確なサンプル・ コードについては、付録 A を参照してください。 /** * vr0 is our state or the vector register where our * plaintext/point address resides. * vr1 is the key0 provided by the user or first key * vr2 is the second generated by expand key * vr3 is the third and so on till vr11 **/ 1 vxor 0,0,1 2 vcipher 0,0,2 3 vcipher 0,0,3 4 vcipher 0,0,4 5 vcipher 0,0,5 ... 11 vcipherlast 0,0,11 ライン 1 の key0 が、初期ステートの AES に追加されます。 ライン 2 は、key1 に対する AES の最初のラウンドです。 ライン 3 は、AES の 2 回目のラウンドです。このようにラウンドが繰り返されます。 ライン 11 は、最終的な key10 に対する AES の最後のラウンドです。 POWER8 のメモリー内命令を使用するカーネル・ドライバー vmx-crypto は、POWER8 のメモリー内 AES 命令をサポートしているカーネル・ドライバーで、初 期ステートでは AES を CBC モードと CTR モードでサポートします。このドライバーは、GHASH アルゴリズムもサポートしており、カーネル 4.1 およびそれ以降のバージョンで使用することが できます。また、リトルエンディアンとビッグエンディアンの両方に対応しています。 カーネルが vmx-crypto を使用しているかどうかを確認するには、lsmod | grep vmx を実行しま す。ご使用のマシンでこのドライバーをまだ使用していない場合は、modprobe vmx-crypto を実 行してドライバーを追加し、lsmod で再び確認するか、cat /proc/crypto | less を実行して p8 プレフィックスを検索することもできます。このドライバーでサポートしているアルゴリズムと モードは以下のとおりです。 POWER8 のメモリー内暗号化 ページ 8 / 12 ibm.com/developerWorks/jp/ developerWorks® • 名前: ghash ドライバー: p8_ghash モジュール: vmx_crypto • 名前: aes ドライバー: p8_aes モジュール: vmx_crypto • 名前: cbc(aes) ドライバー: p8_aes_cbc モジュール: vmx_crypto • 名前: ctr(aes) ドライバー: p8_aes_ctr モジュール: vmx_crypto ユーザー空間での POWER8 メモリー内命令 多くのプロジェクトで暗号プロバイダーとして使用されているのは、OpenSSL です。OpenSSL バージョン 1.0.2 からは、POWER8 メモリー内命令を使用して SSL 暗号が実装されるようになっ ています。実行中のシステムで OpenSSL のこのバージョン (および以降のバージョン) が使用可 能になっている場合、VMX POWER8 アセンブリー・コードとハードウェア最適化を使用すること で、OpenSSL のパフォーマンスを向上させることができます。暗号に OpenSSL を使用しているア プリケーションは数えきれないほどあるので、この強化された OpenSSL により、多種多様なアプ リケーションが POWER8 の AES 命令を利用できるようになります。 まとめ POWER8 システムでのメモリー内命令は、POWER8 ハードウェアの能力を直接活かした暗号ス タックを実装することを可能にします。これにより、コードが暗号ベンチマーク・テストでパ フォーマンスを発揮できるようになります。 参考資料 [1] 『Performance Optimization and Tuning Techniques for IBM Processors Including IBM POWER8』 (Brian Hall、Ryan Arnold、Peter Bergner、Wainer dos Santos Moschetta、Robert Enenkel、Pat Haugen、Michael R. Meissner、Alex Mericas、Philipp Oehler、Berni Shiefer、Brian F. Veale、Suresh Warrier、Daniel Zabawa、Adhemerval Zanella 共著、IBM Redbooks 出版、2014年) [2] G. David Forney 氏による「Principles of Digital Communication II - Spring 2005. Introduction to Finite Fields」(2005年) [3] 「Announcing the ADVANCED ENCRYPTION STANDARD (AES)」(Federal Information Processing Standards Publication、2001年) [4] 『Power ISA 2.07B』(IBM、2015 年) の「Vector Facilities」(p.217)。https://www.power.org/ documentation/power-isa-v-2-07b/から入手できます。 POWER8 のメモリー内暗号化 ページ 9 / 12 developerWorks® ibm.com/developerWorks/jp/ [5] Cerri, M. 氏による VMX 暗号ドライバー。http://lxr.free-electrons.com/source/drivers/crypto/ vmx/ から入手できます。 Appendix A /** * vmx-crypto AES encrypt/OpenSSL aes encryption * At kernel: /drivers/crypto/vmx/aesp8-ppc.S * At OpenSSL: /crypto/aes/aesp8-ppc.s **/ .aes_p8_encrypt: lwz 6,240(5) lis 0,0xfc00 mfspr 12,256 li 7,15 mtspr 256,0 lvx 0,0,3 neg 11,4 lvx 1,7,3 lvsl 2,0,3 lvsl 3,0,11 li 7,16 vperm 0,0,1,2 lvx 1,0,5 lvsl 5,0,5 srwi 6,6,1 lvx 2,7,5 addi 7,7,16 subi 6,6,1 vperm 1,1,2,5 vxor 0,0,1 lvx 1,7,5 addi 7,7,16 mtctr 6 .Loop_enc: vperm 2,2,1,5 vcipher 0,0,2 lvx 2,7,5 addi 7,7,16 vperm 1,1,2,5 vcipher 0,0,1 lvx 1,7,5 addi 7,7,16 bdnz .Loop_enc vperm 2,2,1,5 vcipher 0,0,2 lvx 2,7,5 vperm 1,1,2,5 vcipherlast 0,0,1 vspltisb 2,-1 vxor 1,1,1 li 7,15 vperm 2,1,2,3 lvx 1,0,4 vperm 0,0,0,3 vsel 1,1,0,2 POWER8 のメモリー内暗号化 ページ 10 / 12 ibm.com/developerWorks/jp/ developerWorks® lvx 4,7,4 stvx 1,0,4 vsel 0,0,4,2 stvx 0,7,4 mtspr 256,12 blr /** * vmx-crypto AES decrypt * At kernel: /drivers/crypto/vmx/aesp8-ppc.S * At OpenSSL: /crypto/aes/aesp8-ppc.s **/ .aes_p8_decrypt: lwz 6,240(5) lis 0,0xfc00 mfspr 12,256 li 7,15 mtspr 256,0 lvx 0,0,3 neg 11,4 lvx 1,7,3 lvsl 2,0,3 lvsl 3,0,11 li 7,16 vperm 0,0,1,2 lvx 1,0,5 lvsl 5,0,5 srwi 6,6,1 lvx 2,7,5 addi 7,7,16 subi 6,6,1 vperm 1,1,2,5 vxor 0,0,1 lvx 1,7,5 addi 7,7,16 mtctr 6 .Loop_dec: vperm 2,2,1,5 vncipher 0,0,2 lvx 2,7,5 addi 7,7,16 vperm 1,1,2,5 vncipher 0,0,1 lvx 1,7,5 addi 7,7,16 bdnz .Loop_dec vperm 2,2,1,5 vncipher 0,0,2 lvx 2,7,5 vperm 1,1,2,5 vncipherlast 0,0,1 vspltisb 2,-1 vxor 1,1,1 li 7,15 vperm 2,1,2,3 lvx 1,0,4 vperm 0,0,0,3 vsel 1,1,0,2 POWER8 のメモリー内暗号化 ページ 11 / 12 developerWorks® ibm.com/developerWorks/jp/ lvx 4,7,4 stvx 1,0,4 vsel 0,0,4,2 stvx 0,7,4 mtspr 256,12 blr © Copyright IBM Corporation 2015 (www.ibm.com/legal/copytrade.shtml) 商標 (www.ibm.com/developerworks/jp/ibm/trademarks/) POWER8 のメモリー内暗号化 ページ 12 / 12