PDF

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