🔥

3rd Generation Intel® Xeon® Scalable Processors における暗号処理の高速化について

2023/03/13に公開

3rd Generation Xeon において追加された Crypto Acceleration についてのまとめです。

おかしな部分等あれば指摘いただけると幸いです。

概要

3rd Generation Intel® Xeon® Scalable processors (と一部の第 10 世代 Core シリーズ)においては AVX512 系の命令がいくつか追加されており、それらの命令を利用することで暗号処理の高速化を実現することができます。

これらの高速化に関連する拡張命令は次の 4 つです。

  • AVX512F
  • AVX512_IFMA
  • VAES
  • VPCLMULQDQ
    • (英語版 wikipediaより抜粋・翻訳) これらは AVX-512 の機能それ自体ではありません。AVX-512 とともに、GFNI、PCLMULQDQ、AES 命令の EVEX エンコード版を実現します。

また、これらの拡張命令を CPU が利用できるかは次のコマンドで確かめることができます

$ cpuid -1 | egrep 'VAES|VPCLM|GFNI|AVX512F|AVX512IFMA'
      AVX512F: AVX-512 foundation instructions = true
      AVX512IFMA: fused multiply add           = true
      VAES instructions                        = true
      VPCLMULQDQ instruction                   = true

後述するIntel® Quick Assist Technology (Intel® QAT) Engineの利用のためにはこれらの拡張命令をすべて利用できる必要があります

高速化の恩恵を受けるための各種ライブラリについて

Intel® Integrated Performance Primitives Cryptography (ipp-crypto)

x86-64 における各種 SIMD 命令(Streaming SIMD Extesions, AVX, AVX2, AVX512 等)を利用した暗号処理が提供されています

この中にCrypto Multi-buffer Libraryというのが入っており、これが AVX512 系の命令を使って暗号処理、特に RSA, ECDSA, SM3, x25519 を扱うことができるライブラリです。

Intel(R) Multi-Buffer Crypto for IPsec Library (intel-ipsec-mb)

AES 系の暗号はこちらで実装されています。各種の暗号と拡張命令を利用した実装状況に関してはREADME の Overviewに詳しいです。

Intel® QuickAssist Technology(QAT) OpenSSL* Engine

これは、先述の 2 つのライブラリを利用して OpenSSL の処理を高速化するためのライブラリです。

このライブラリには特殊なハードウェアを利用したqat_hwの実装と、SIMD 系命令を利用したqat_swを利用した実装の 2 種類が存在し、3rd Generation 以降の Xeon で利用できるのはqat_swの方の実装になります。

OpenSSL にはEngineという特殊なハードウェア実装を用いて処理を高速化するための仕組みをもとから備えており、それを経由して AVX512 系の命令を利用した高速化を行うことができます。

利用のためには制約もあり、OpenSSL は静的リンクされたものではなく共有ライブラリとしてビルドされたものからしか利用できません。

また、GitHub の README には OpenSSL 1.1 系での利用方法しか書いていませんが、OpenSSL 3 や BoringSSL からでも利用できます。

OpenSSL v3.1 以降

changelog によると、OpenSSL の 3.1 系では AVX512 系命令を利用した AES-GCM が有効化されています。
(https://github.com/openssl/openssl/blob/master/CHANGES.md#:~:text=AES-GCM enabled with AVX512 vAES and vPCLMULQDQ)

ベンチマーク

QAT Engine を利用した OpenSSL3.0 系と OpenSSL3.1-beta1 において検証を行いました。

検証環境の構築

GCP の n2-standard-8 インスタンスを用いて検証を行いました。
N2 インスタンスでは Ice Lake のプロセッサ(=3rd Generation Xeon)を選択できます。

QAT Engine のビルド

基本的には
https://www.intel.com/content/www/us/en/developer/articles/guide/building-software-acceleration-features-in-the-intel-qat-engine-for-openssl.html
こちらの手順にしたがってビルドができます。

ただし、OpenSSL は 3.0.2(Ubuntu 22.04 のデフォルト)、ipp-crypto は2021.7、intel-ipsec-mb はv1.3を利用しました。

また、QAT Engine に関してもv0.6.19を利用しました。

OpenSSL 3.1 のビルド

./Configure no-sharedを指定してビルドしたものを利用しました。

結果

OpenSSL 3.0.2 + QAT Engine での結果

$ openssl version
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
$ openssl engine -v qatengine
(qatengine) Reference implementation of QAT crypto engine(qat_sw) v0.6.19
     ENABLE_EXTERNAL_POLLING, POLL, ENABLE_HEURISTIC_POLLING,
     GET_NUM_REQUESTS_IN_FLIGHT, INIT_ENGINE, SW_ALGO_BITMAP
809B1728167F0000:error:1280006A:DSO support routines:dlfcn_bind_func:could not bind to the requested symbol name:../crypto/dso/dso_dlfcn.c:188:symname(EVP_PKEY_base_id): /usr/lib/x86_64-linux-gnu/engines-3/qatengine.so: undefined symbol: EVP_PKEY_base_id
809B1728167F0000:error:1280006A:DSO support routines:DSO_bind_func:could not bind to the requested symbol name:../crypto/dso/dso_lib.c:176:

なんかエラー出てるけどよくわからないので誰か教えてください

aes-128-gcm

QAT Engine なし
$ openssl speed -evp aes-128-gcm
Doing AES-128-GCM for 3s on 16 size blocks: 127992858 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 64 size blocks: 76284376 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 256 size blocks: 42488086 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 1024 size blocks: 15397757 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 8192 size blocks: 2273200 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 16384 size blocks: 1150996 AES-128-GCM's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-GCM     682628.58k  1627400.02k  3625650.01k  5255767.72k  6207351.47k  6285972.82k
QAT Engine あり
$ openssl speed -engine qatengine -evp aes-128-gcm
Engine "qatengine" set.
Doing AES-128-GCM for 3s on 16 size blocks: 109974541 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 64 size blocks: 89364103 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 256 size blocks: 50045002 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 1024 size blocks: 29516005 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 8192 size blocks: 4564498 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 16384 size blocks: 2353982 AES-128-GCM's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-GCM     586530.89k  1906434.20k  4270506.84k 10074796.37k 12464122.54k 12855880.36k

1024 bytes 以降は大体 2 倍くらい速い

aes-128-ctr

QAT Engine なし
$ openssl speed -evp aes-128-ctr
Doing AES-128-CTR for 3s on 16 size blocks: 177189451 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 64 size blocks: 129222686 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 256 size blocks: 71686196 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 1024 size blocks: 25626352 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 8192 size blocks: 3662314 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 16384 size blocks: 1840201 AES-128-CTR's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-CTR     945010.41k  2756750.63k  6117222.06k  8747128.15k 10000558.76k 10049951.06k
QAT Engine あり
$ openssl speed -engine qatengine -evp aes-128-ctr
Engine "qatengine" set.
Doing AES-128-CTR for 3s on 16 size blocks: 177708180 AES-128-CTR's in 2.99s
Doing AES-128-CTR for 3s on 64 size blocks: 129253145 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 256 size blocks: 71697346 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 1024 size blocks: 25668842 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 8192 size blocks: 3655854 AES-128-CTR's in 3.00s
Doing AES-128-CTR for 3s on 16384 size blocks: 1843037 AES-128-CTR's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-CTR     950946.78k  2757400.43k  6118173.53k  8761631.40k  9982918.66k 10065439.40k

変化なし

chacha20-poly1305

QAT Engine なし
$ openssl speed -evp chacha20-poly1305
Doing ChaCha20-Poly1305 for 3s on 16 size blocks: 51876085 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 64 size blocks: 25916354 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 256 size blocks: 21052322 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 1024 size blocks: 9419079 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 8192 size blocks: 1337422 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 16384 size blocks: 672829 ChaCha20-Poly1305's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
ChaCha20-Poly1305   276672.45k   552882.22k  1796464.81k  3215045.63k  3652053.67k  3674543.45k
QAT Engine あり
$ openssl speed -engine qatengine -evp chacha20-poly1305
Engine "qatengine" set.
Doing ChaCha20-Poly1305 for 3s on 16 size blocks: 51898009 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 64 size blocks: 26196760 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 256 size blocks: 21134291 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 1024 size blocks: 9479344 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 8192 size blocks: 1336801 ChaCha20-Poly1305's in 3.00s
Doing ChaCha20-Poly1305 for 3s on 16384 size blocks: 672172 ChaCha20-Poly1305's in 3.00s
version: 3.0.2
built on: Mon Feb  6 17:57:17 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-hnAO60/openssl-3.0.2=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
ChaCha20-Poly1305   276789.38k   558864.21k  1803459.50k  3235616.09k  3650357.93k  3670955.35k

変化なし

OpenSSL 3.1.0-beta1 での結果

$ ./openssl speed -evp aes-128-gcm
Doing AES-128-GCM for 3s on 16 size blocks: 136722134 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 64 size blocks: 127713350 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 256 size blocks: 62024856 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 1024 size blocks: 20155531 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 8192 size blocks: 4373650 AES-128-GCM's in 3.00s
Doing AES-128-GCM for 3s on 16384 size blocks: 2313676 AES-128-GCM's in 3.00s
version: 3.1.0-beta1
built on: Fri Mar 10 10:35:57 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG
CPUINFO: OPENSSL_ia32cap=0xfefa32035f8bffff:0x405f46f1bf2ffb
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
AES-128-GCM     729184.71k  2724551.47k  5292787.71k  6879754.58k 11942980.27k 12635755.86k

大体 QAT Engine ありと同じくらいの結果が出ています。

その他のベンチマーク

intel 公式から nginx などのソフトウェアを利用したベンチマークなども公開されています。
https://www.intel.co.jp/content/www/jp/ja/architecture-and-technology/crypto-acceleration-in-xeon-scalable-processors-wp.html

まとめ

3rd Generation Xeon での暗号処理では OpenSSL3.0.2 において QAT Engine を利用するか、もしくは 3.1 系へと移行することで AES-128-GCM で最大 2 倍程度の高速化を実現できることがわかりました。

もしこれらのプロセッサを利用することができ、暗号処理がボトルネックになっている場合は今後 OpenSSL3.1 への移行などを検討する価値はありそうです。

参考文献

  1. Crypto Processing with Intel® Xeon® Scalable Processor
  2. インテル ® クリプト・アクセラレーションのソリューション概要
  3. Intel® Integrated Performance Primitives Cryptography
  4. Intel(R) Multi-Buffer Crypto for IPsec Library
  5. Intel® QuickAssist Technology(QAT) OpenSSL* Engine

Discussion