암호화 하드웨어 가속 (Crypto HW Acceleration)
리눅스 커널 Crypto API의 하드웨어 가속 계층을 심층 분석합니다. AES-NI·ARM Crypto Extensions·SHA-NI 등 CPU ISA 확장, Intel QAT·AMD CCP·HiSilicon SEC·NXP CAAM 등 전용 가속기 디바이스, IPsec/kTLS/MACsec 네트워크 오프로드, blk-crypto 스토리지 인라인 암호화, SED/OPAL 자체 암호화 드라이브, HSM 하드웨어 보안 모듈까지 포괄합니다.
핵심 요약
- 우선순위 기반 선택 — Crypto API가 등록된 구현 중 가장 높은 우선순위(Priority)를 자동 선택합니다.
- SIMD 컨텍스트 제약 — kernel_fpu_begin/end 구간에서만 SIMD 명령어를 사용할 수 있습니다.
- 폴백 메커니즘 — 하드웨어 사용 불가 시 소프트웨어 구현으로 자동 전환됩니다.
- 오프로드 판단 — 패킷 크기, 처리량, 지연 요구에 따라 최적 오프로드 경로를 선택합니다.
- 벤더 다양성 — Intel, AMD, ARM, HiSilicon, NXP, Marvell, Samsung 등 다양한 가속기를 지원합니다.
단계별 이해
- CPU ISA 확인
CPUID/HWCAP으로 가속 명령어 지원 여부를 확인합니다. - 드라이버 로드
해당 가속 모듈이 적재되어 우선순위가 할당됩니다. - API 투명성
Crypto API가 자동으로 최적 구현을 선택합니다. - 벤치마크 검증
tcrypt 또는 openssl speed로 실제 성능을 측정합니다.
H/W 가속 상세
현대 리눅스 시스템에서 암호화 연산은 IPsec 터널, dm-crypt 디스크 암호화, kTLS 등 다양한 경로에서 대규모로 발생합니다. 소프트웨어만으로 이를 처리하면 CPU 사용률이 급증하고 처리량이 제한되므로, 하드웨어 가속은 보안과 성능을 동시에 확보하는 핵심 수단입니다. 커널이 활용하는 하드웨어 가속은 크게 네 가지 유형으로 나뉩니다.
- CPU ISA 확장 명령어 — AES-NI, SHA-NI, ARM Crypto Extensions 등. CPU 내부에서 인라인 실행되어 지연이 거의 없습니다.
- PCI 가속기 — Intel QAT, AMD CCP 등. 전용 PCI 디바이스가 대량 배치 처리를 오프로드하며, 호스트 CPU를 해방합니다.
- SoC 임베디드 엔진 — NXP CAAM, HiSilicon SEC 등. 임베디드·네트워크 장비의 SoC에 내장된 암호 엔진입니다.
- NIC 인라인 오프로드 — NVIDIA ConnectX-6/7, BlueField-2/3 DPU, Intel E810 등. 네트워크 카드가 패킷 단위로 IPsec/kTLS/MACsec을 와이어 속도로 처리합니다.
리눅스 Crypto API는 이 모든 유형을 단일 인터페이스 뒤에 추상화합니다.
각 드라이버는 자신의 priority 값을 등록하고, API는 동일 알고리즘의 구현 중 가장 높은 priority를 자동 선택합니다.
따라서 사용자 코드나 상위 서브시스템(IPsec, dm-crypt 등)은 하드웨어 유형을 의식하지 않아도 최적의 구현을 투명하게 활용할 수 있습니다.
| 유형 | 예시 | Priority 범위 | 지연 | 처리량 | CPU 점유 | 적합 워크로드 |
|---|---|---|---|---|---|---|
| CPU ISA 명령어 | AES-NI, SHA-NI, ARM CE | 300~400 | ~ns | ~10 GB/s/core | 100% (해당 코어) | 소량 데이터, 저지연 |
| PCI 가속기 | Intel QAT, AMD CCP | 200~4001 | ~μs | ~100 Gbps | <5% | 대량 배치 처리 |
| SoC 임베디드 | NXP CAAM, HiSilicon SEC | 3000~4001 | ~μs | SoC 의존 | <5% | 임베디드/네트워크 |
| NIC 인라인 | NVIDIA CX-6/7, Intel E810 | N/A (커널 우회) | ~ns | 와이어 속도 | 0% | IPsec/kTLS/MACsec |
하드웨어 가속 감지와 확인
실행 중인 시스템에서 어떤 하드웨어 암호 가속이 활성화되어 있는지 확인하는 방법을 정리합니다.
/proc/crypto는 커널에 등록된 모든 암호 알고리즘(소프트웨어 + 하드웨어)을 보여주며,
driver 필드와 priority 값으로 하드웨어 가속 여부를 판별할 수 있습니다.
# 사용 가능한 암호 알고리즘 확인 (H/W 가속 포함)
cat /proc/crypto | head -40
# name : __cbc(aes)
# driver : __cbc-aes-aesni ← AES-NI 하드웨어 가속
# module : aesni_intel
# priority : 400 ← 높은 우선순위 = 자동 선택
# type : skcipher
# x86: AES-NI 지원 확인
grep aes /proc/cpuinfo | head -1
# flags : ... aes ...
# x86: SHA-NI 지원 확인
grep sha_ni /proc/cpuinfo | head -1
# ARM64: Crypto Extensions(CE) 지원 확인 (HWCAP)
cat /proc/cpuinfo | grep -i 'Features' | head -1
# Features : ... aes pmull sha1 sha2 crc32 ...
# 로드된 하드웨어 가속 모듈 확인
lsmod | grep -E 'aesni|ccp|qat|caam|sahara|sun[48x]i'
# aesni_intel 393216 3
# 부팅 시 등록된 가속기 드라이버 확인
dmesg | grep -i crypto
# [ 1.234567] ccp 0000:03:00.2: enabling device
# [ 1.234890] ccp 0000:03:00.2: ccp enabled
# 특정 알고리즘의 구현 목록과 priority 비교
grep -A4 'name.*aes' /proc/crypto | grep -E 'name|driver|priority'
# name : __cbc(aes)
# driver : __cbc-aes-aesni
# priority : 400 ← H/W (자동 선택)
# name : __cbc(aes)
# driver : __cbc-aes-generic
# priority : 100 ← S/W 폴백
커널은 동일 알고리즘의 여러 구현 중 priority가 가장 높은 것을 자동 선택합니다. H/W 가속기 드라이버가 로드되면 자동으로 소프트웨어 구현보다 우선 사용됩니다.
AES-NI
AES-NI(Advanced Encryption Standard New Instructions)는 Intel이 2010년(Westmere)에 도입하고 AMD가 2011년(Bulldozer)부터 지원하는 AES 전용 하드웨어 명령어 세트입니다. 소프트웨어 AES 대비 3~10배 이상 빠른 처리량(Throughput)을 제공하며, 일반적인 테이블 기반 구현 대비 타이밍 기반 부채널 위험을 줄이는 데 유리합니다.
AES-NI 명령어 세트
AES-NI는 6개의 핵심 명령어로 구성됩니다. 모든 명령어는 128-bit XMM 레지스터(Register)에서 동작합니다:
| 명령어 | 동작 | 설명 |
|---|---|---|
AESENC | 1라운드 암호화 | ShiftRows → SubBytes → MixColumns → AddRoundKey |
AESENCLAST | 마지막 라운드 암호화 | ShiftRows → SubBytes → AddRoundKey (MixColumns 생략) |
AESDEC | 1라운드 복호화 | InvShiftRows → InvSubBytes → InvMixColumns → AddRoundKey |
AESDECLAST | 마지막 라운드 복호화 | InvShiftRows → InvSubBytes → AddRoundKey |
AESKEYGENASSIST | 키 확장 보조 | 라운드 키 생성에 필요한 SubWord/RotWord 수행 |
AESIMC | 역 MixColumns | 복호화용 라운드 키 변환 (Equivalent Inverse Cipher) |
AES 라운드 수: AES-128은 10라운드, AES-192는 12라운드, AES-256은 14라운드입니다. 각 라운드마다 AESENC 1개 명령어가 전체 라운드 변환을 수행합니다. 소프트웨어 구현에서는 S-Box 테이블 룩업, 행 시프트, 열 혼합, 키 합성을 별도로 수행하지만 AES-NI는 이를 단일 명령어로 처리합니다.
AES-NI 키 확장 (Key Expansion)
AES 키 확장은 원본 키(128/192/256비트)로부터 각 라운드에 사용할 라운드 키를 생성합니다. 커널의 aesni-intel_glue.c는 키 설정 시 모든 라운드 키를 미리 확장하여 crypto_aes_ctx에 저장합니다:
; AES-128 키 확장 (arch/x86/crypto/aesni-intel_asm.S 참고)
; 입력: %xmm0 = 원본 128-bit 키
; 출력: key_schedule[0..10] = 11개 라운드 키
_aesni_key_expansion_128:
movaps %xmm0, (%rdi) ; key_schedule[0] = 원본 키
; 라운드 1: RCON = 0x01
aeskeygenassist $0x01, %xmm0, %xmm1
call _key_expansion_128
movaps %xmm0, 0x10(%rdi) ; key_schedule[1]
; 라운드 2: RCON = 0x02
aeskeygenassist $0x02, %xmm0, %xmm1
call _key_expansion_128
movaps %xmm0, 0x20(%rdi) ; key_schedule[2]
; ... 라운드 3~10까지 반복 (RCON: 0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36)
; 키 확장 보조 루틴
_key_expansion_128:
pshufd $0xff, %xmm1, %xmm1 ; AESKEYGENASSIST 결과를 broadcast
shufps $0x10, %xmm0, %xmm4 ; temp = [0,0,key[0],key[1]]
pxor %xmm4, %xmm0 ; key ^= temp
shufps $0x8c, %xmm0, %xmm4
pxor %xmm4, %xmm0 ; key ^= temp (cascade)
pxor %xmm1, %xmm0 ; key ^= RCON 결과
ret
/* 커널 glue 코드: 키 설정 (arch/x86/crypto/aesni-intel_glue.c) */
static int aesni_set_key(struct crypto_aes_ctx *ctx,
const u8 *in_key, unsigned int key_len)
{
if (!crypto_simd_usable())
return aes_expandkey(ctx, in_key, key_len); /* SW fallback */
kernel_fpu_begin();
aesni_set_key_common(ctx, in_key, key_len); /* AES-NI 키 확장 */
kernel_fpu_end();
return 0;
}
/* struct crypto_aes_ctx — 확장된 키 스케줄 저장 */
struct crypto_aes_ctx {
u32 key_enc[AES_MAX_KEYLENGTH_U32]; /* 암호화용 라운드 키 (60 u32) */
u32 key_dec[AES_MAX_KEYLENGTH_U32]; /* 복호화용 라운드 키 (Inv) */
u32 key_length; /* 16, 24, 또는 32 */
};
운용 모드별 AES-NI 구현
커널의 aesni_intel 모듈은 다양한 운용 모드를 AES-NI로 가속합니다. 각 모드의 병렬화 특성에 따라 성능이 크게 달라집니다:
| 모드 | 커널 드라이버 이름 | 병렬 처리 | 특성 |
|---|---|---|---|
| ECB | ecb-aes-aesni | 완전 병렬 | 각 블록이 독립적이라 파이프라인(Pipeline) 최대 활용 |
| CBC 암호화 | cbc-aes-aesni | 직렬 (체인) | 이전 블록 암호문이 다음 블록 입력에 필요 |
| CBC 복호화 | cbc-aes-aesni | 완전 병렬 | 복호화는 모든 암호문 블록을 이미 알고 있으므로 병렬 가능 |
| CTR | ctr-aes-aesni | 완전 병렬 | 카운터 값이 독립적, IPsec/TLS에서 주력으로 사용 |
| XTS | xts-aes-aesni | 완전 병렬 | 디스크 암호화(dm-crypt, LUKS) 표준 모드 |
| GCM | gcm-aes-aesni | AES 병렬 + GHASH | AEAD, PCLMULQDQ로 GHASH 가속 포함 |
; AES-CBC 암호화 — 직렬 체인 (arch/x86/crypto/aesni-intel_asm.S 참고)
; 각 블록: C[i] = AES_ENC(P[i] XOR C[i-1])
_aesni_enc_cbc:
movups (%r8), %xmm2 ; IV 로드
.Lcbc_enc_loop:
movups (%rsi), %xmm3 ; 평문 블록 로드
pxor %xmm2, %xmm3 ; P[i] XOR C[i-1] (CBC 체이닝)
; 10라운드 AES-128 암호화
pxor 0x00(%rdi), %xmm3 ; AddRoundKey (라운드 0)
aesenc 0x10(%rdi), %xmm3 ; 라운드 1
aesenc 0x20(%rdi), %xmm3 ; 라운드 2
; ... 라운드 3~9 ...
aesenclast 0xa0(%rdi), %xmm3 ; 라운드 10 (마지막)
movups %xmm3, (%rdx) ; 암호문 저장
movaps %xmm3, %xmm2 ; C[i] → 다음 블록의 IV
add $16, %rsi
add $16, %rdx
dec %ecx
jnz .Lcbc_enc_loop
; AES-CTR 암호화 — 병렬 처리 (4블록 동시)
; C[i] = P[i] XOR AES_ENC(CTR+i)
_aesni_enc_ctr:
; 4개 카운터를 병렬로 준비
movaps %xmm0, %xmm1 ; CTR+0
movaps %xmm0, %xmm2 ; CTR+1 (inc)
movaps %xmm0, %xmm3 ; CTR+2 (inc)
movaps %xmm0, %xmm4 ; CTR+3 (inc)
; ... 각 카운터 증가 ...
; 4블록 동시 AES 라운드 (파이프라인 활용)
pxor (%rdi), %xmm1
pxor (%rdi), %xmm2
pxor (%rdi), %xmm3
pxor (%rdi), %xmm4
aesenc 0x10(%rdi), %xmm1
aesenc 0x10(%rdi), %xmm2
aesenc 0x10(%rdi), %xmm3
aesenc 0x10(%rdi), %xmm4
; ... 나머지 라운드 인터리빙 ...
CTR/ECB 병렬화 핵심: 최신 CPU의 AES-NI 파이프라인은 4사이클 레이턴시, 1사이클 스루풋입니다. AESENC 명령어는 이전 명령어 완료를 기다리지 않고 파이프라인에 투입되므로, 독립적인 블록 4~8개를 인터리빙하면 이론적 최대 스루풋에 도달합니다.
AES-GCM과 PCLMULQDQ
AES-GCM(Galois/Counter Mode)은 TLS 1.3, IPsec에서 가장 널리 사용되는 AEAD 모드입니다. GCM은 CTR 모드 암호화와 GHASH 인증을 결합합니다. 커널은 AES-NI와 PCLMULQDQ(Carry-less Multiplication) 명령어를 함께 사용하여 두 연산을 모두 하드웨어로 가속합니다:
/* GHASH에서 GF(2^128) 곱셈 — PCLMULQDQ 하드웨어 가속 */
/* PCLMULQDQ: Carry-less multiplication (XOR 기반 다항식 곱셈) */
/* 소프트웨어로 구현하면 수십 사이클 걸리는 연산을 단일 명령어로 수행 */
/* arch/x86/crypto/ghash-clmulni-intel_asm.S 에서: */
; GHASH 블록 처리:
; xmm0 = 현재 해시 값 (H_i)
; xmm1 = 해시 키 (H = AES_ENC(0))
; XOR → CLMUL → reduction → 새 해시 값
pxor %xmm2, %xmm0 ; H_i XOR C_i (입력 블록과 XOR)
; Karatsuba 분해를 사용한 128×128 bit carry-less 곱셈
movdqa %xmm0, %xmm3
pclmulqdq $0x00, %xmm1, %xmm3 ; a0 × b0 (하위 64-bit 곱)
movdqa %xmm0, %xmm4
pclmulqdq $0x11, %xmm1, %xmm4 ; a1 × b1 (상위 64-bit 곱)
movdqa %xmm0, %xmm5
pclmulqdq $0x10, %xmm1, %xmm5 ; a0 × b1 (교차 곱)
pclmulqdq $0x01, %xmm1, %xmm0 ; a1 × b0 (교차 곱)
pxor %xmm5, %xmm0 ; 교차 곱 합산
; → GF(2^128) 환원(reduction): x^128 + x^7 + x^2 + x + 1
커널 GCM 구현 구조: generic-gcm-aesni 드라이버(priority 400)는 AES-NI + PCLMULQDQ를 결합한 최적화 구현입니다. CTR 암호화와 GHASH 인증을 인터리빙하여 AES 파이프라인 대기 시간(Latency) 동안 GHASH를 수행합니다. 이 기법으로 GCM은 CTR 단독 대비 거의 추가 비용 없이 인증을 제공합니다.
aesni_intel 모듈 아키텍처
커널의 AES-NI 지원은 arch/x86/crypto/ 디렉터리에 위치하며, glue 코드와 어셈블리 구현으로 분리됩니다:
/* aesni-intel_glue.c — 주요 알고리즘 등록 구조 */
/* 1. 기본 블록 암호 (AES 단일 블록, 128-bit) */
static struct crypto_alg aesni_cipher_alg = {
.cra_name = "aes",
.cra_driver_name = "aes-aesni",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE, /* 16 */
.cra_u.cipher = {
.cia_min_keysize = AES_MIN_KEY_SIZE, /* 16 */
.cia_max_keysize = AES_MAX_KEY_SIZE, /* 32 */
.cia_setkey = aes_set_key,
.cia_encrypt = aesni_encrypt,
.cia_decrypt = aesni_decrypt,
},
};
/* 2. skcipher 알고리즘들 (CBC, CTR, XTS, ECB) */
static struct skcipher_alg aesni_skciphers[] = {
{ /* ECB — 병렬 처리, priority 400 */
.base.cra_name = "__ecb(aes)",
.base.cra_driver_name = "__ecb-aes-aesni",
.base.cra_priority = 400,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.setkey = aesni_skcipher_setkey,
.encrypt = ecb_encrypt,
.decrypt = ecb_decrypt,
},
{ /* CBC */
.base.cra_name = "__cbc(aes)",
.base.cra_driver_name = "__cbc-aes-aesni",
.base.cra_priority = 400,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.setkey = aesni_skcipher_setkey,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
},
{ /* CTR */
.base.cra_name = "__ctr(aes)",
.base.cra_driver_name = "__ctr-aes-aesni",
.base.cra_priority = 400,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.setkey = aesni_skcipher_setkey,
.encrypt = ctr_crypt,
.decrypt = ctr_crypt, /* CTR 모드: enc == dec */
},
{ /* XTS — 디스크 암호화 (dm-crypt) */
.base.cra_name = "__xts(aes)",
.base.cra_driver_name = "__xts-aes-aesni",
.base.cra_priority = 401,
.setkey = xts_aesni_setkey,
.encrypt = xts_encrypt,
.decrypt = xts_decrypt,
},
};
/* 3. AEAD (GCM) */
static struct aead_alg aesni_aeads[] = {
{
.base.cra_name = "__gcm(aes)",
.base.cra_driver_name = "__generic-gcm-aesni",
.base.cra_priority = 400,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.setkey = gcm_setkey,
.setauthsize = gcm_setauthsize,
.encrypt = gcm_encrypt,
.decrypt = gcm_decrypt,
.ivsize = GCM_AES_IV_SIZE, /* 12 */
.maxauthsize = 16,
},
};
INTERNAL 플래그와 SIMD 래퍼: __ecb-aes-aesni 등 __ 접두사 알고리즘은 CRYPTO_ALG_INTERNAL 플래그를 가지며 직접 사용할 수 없습니다. simd_register_skciphers_compat()가 이를 감싸서 ecb-aes-aesni(접두사 없음)를 외부에 공개합니다. SIMD 래퍼는 process context에서 직접 SIMD 실행, softirq/hardirq에서는 cryptd kthread로 위임하여 컨텍스트 안전성을 보장합니다.
aesni_intel 모듈 초기화 흐름
/* aesni-intel_glue.c — 모듈 초기화 */
static int __init aesni_init(void)
{
int err;
/* 1. CPU가 AES-NI를 지원하는지 확인 */
if (!boot_cpu_has(X86_FEATURE_AES))
return -ENODEV; /* AES-NI 미지원 → 모듈 로드 실패 → generic 사용 */
/* 2. PCLMULQDQ 지원 여부 확인 (GCM GHASH에 필요) */
if (!boot_cpu_has(X86_FEATURE_PCLMULQDQ))
pr_info("PCLMULQDQ not available, GCM acceleration disabled\\n");
/* 3. 기본 AES 블록 암호 등록 */
err = crypto_register_alg(&aesni_cipher_alg);
if (err)
return err;
/* 4. skcipher 알고리즘 등록 (INTERNAL 버전) */
err = crypto_register_skciphers(aesni_skciphers,
ARRAY_SIZE(aesni_skciphers));
/* 5. SIMD 래퍼 등록 (외부 공개 버전)
* __ecb-aes-aesni → ecb-aes-aesni
* __cbc-aes-aesni → cbc-aes-aesni
* ... */
err = simd_register_skciphers_compat(aesni_skciphers,
ARRAY_SIZE(aesni_skciphers),
aesni_simd_skciphers);
/* 6. AEAD (GCM) 등록 */
if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) {
err = crypto_register_aeads(aesni_aeads,
ARRAY_SIZE(aesni_aeads));
err = simd_register_aeads_compat(aesni_aeads,
ARRAY_SIZE(aesni_aeads),
aesni_simd_aeads);
}
return 0;
}
VAES: AVX-512 벡터 AES
VAES(Vector AES)는 Intel Ice Lake(2019)부터 도입된 확장으로, AES-NI를 AVX-512 레지스터(512-bit)에서 동작하게 합니다. 128-bit XMM 대신 512-bit ZMM 레지스터를 사용하여 한 명령어로 4개 AES 블록을 동시에 처리합니다:
| 세대 | 레지스터 | 블록/명령어 | 인터리빙 시 최대 |
|---|---|---|---|
| AES-NI (SSE) | XMM (128-bit) | 1블록 | ~4블록 (파이프라인) |
| VAES + AVX2 | YMM (256-bit) | 2블록 | ~8블록 |
| VAES + AVX-512 | ZMM (512-bit) | 4블록 | ~16블록 |
; VAES 예시: 512-bit ZMM 레지스터로 4블록 동시 AES 라운드
; 기존 AES-NI: aesenc %xmm_key, %xmm_data → 1블록 (128-bit)
; VAES: vaesenc %zmm_key, %zmm_data, %zmm_out → 4블록 (512-bit)
vaesenc %zmm1, %zmm0, %zmm0 ; 4블록 × 라운드 1
vaesenc %zmm2, %zmm0, %zmm0 ; 4블록 × 라운드 2
vaesenc %zmm3, %zmm0, %zmm0 ; 4블록 × 라운드 3
; ... 라운드 4~9 ...
vaesenclast %zmm11, %zmm0, %zmm0 ; 4블록 × 라운드 10 (마지막)
; 2개 ZMM을 인터리빙하면 8블록(1024-bit) 동시 처리:
vaesenc %zmm1, %zmm10, %zmm10 ; 블록 0~3
vaesenc %zmm1, %zmm11, %zmm11 ; 블록 4~7 (파이프라인 활용)
# VAES 지원 확인
grep vaes /proc/cpuinfo | head -1
# flags : ... vaes avx512f avx512bw ...
# 커널에서 VAES 가속 드라이버 확인
grep -E "aes.*(vaes|avx512)" /proc/crypto
# driver : xts-aes-vaes-avx512
# driver : gcm-aes-vaes-avx512
커널 VAES 지원: Linux 6.4+ 계열 x86에서는 arch/x86/crypto/aes-xts-avx-x86_64.S 등의 VAES+AVX-512 최적화 경로가 제공됩니다. 실제 선택 여부는 CPU 기능, 커널 설정, 알고리즘 등록 우선순위에 따라 달라질 수 있습니다.
AES-NI를 활용하는 주요 커널 서브시스템
| 서브시스템 | 사용 모드 | 설정/모듈 | 설명 |
|---|---|---|---|
| dm-crypt / LUKS | XTS(AES-256) | CONFIG_DM_CRYPT |
디스크 전체 암호화. cryptsetup으로 설정, 기본 aes-xts-plain64 |
| IPsec (XFRM) | GCM(AES-128/256) | CONFIG_XFRM |
VPN 터널(Tunnel) 암호화. ESP 프로토콜에서 AES-GCM이 기본 선택 |
| kTLS | GCM(AES-128/256) | CONFIG_TLS |
커널 내 TLS 오프로드. setsockopt(SOL_TLS)로 활성화 |
| WireGuard | — | CONFIG_WIREGUARD |
ChaCha20-Poly1305 사용 (AES-NI 미사용), 대신 SSSE3/AVX로 가속 |
| eCryptfs | CBC(AES-256) | CONFIG_ECRYPT_FS |
파일 단위 스택 암호화 파일시스템 |
| fscrypt (ext4/f2fs) | XTS(AES-256), CTS-CBC | CONFIG_FS_ENCRYPTION |
파일시스템 레벨 암호화. 파일명은 CTS-CBC, 데이터는 XTS |
| TCP-AO | CMAC(AES-128) | CONFIG_TCP_AO |
TCP 인증 옵션(RFC 5925). BGP 세션 보호 |
# dm-crypt에서 AES-NI 가속 확인 (LUKS 디스크)
cryptsetup luksDump /dev/sda2 | grep cipher
# cipher: aes-xts-plain64
# IPsec GCM 설정 예시 (strongSwan)
# ike=aes256gcm16-sha384-ecp384
# esp=aes256gcm16
# 현재 사용 중인 AES 구현 확인
cat /proc/crypto | grep -A4 "name.*: xts(aes)"
# name : xts(aes)
# driver : xts-aes-aesni
# module : aesni_intel
# priority : 401
# dm-crypt I/O 중 AES-NI CPU 사용 확인
perf top -e cycles -g -- -p $(pgrep -f kcryptd)
# aesni_xts_encrypt ← AES-NI가 사용되고 있음
AES-NI 성능 특성
# tcrypt 모듈로 AES-NI 벤치마크
modprobe tcrypt mode=500 sec=2
# mode=500대: skcipher 계열 벤치마크 (예: CBC/CTR/XTS)
# mode 번호는 커널 버전에 따라 세부 매핑이 달라질 수 있음
dmesg | tail -30
# 참고 결과 예시 (Xeon, AES-NI):
# testing speed of async cbc(aes) (cbc-aes-aesni) encryption
# test 0 (128 bit key, 16 byte blocks): 18742341 operations in 2 seconds (299877456 bytes)
# test 1 (128 bit key, 64 byte blocks): 12952847 operations in 2 seconds (828982208 bytes)
# test 2 (128 bit key, 256 byte blocks): 7348142 operations in 2 seconds (1881124352 bytes)
# test 3 (128 bit key, 1024 byte blocks): 3128904 operations in 2 seconds (3203997696 bytes)
# test 4 (128 bit key, 1472 byte blocks): 2352961 operations in 2 seconds (3463558592 bytes)
# test 5 (128 bit key, 8192 byte blocks): 537420 operations in 2 seconds (4402585600 bytes)
# → ~2.2 GB/s (CBC, 단일 코어)
| 모드 | 구현 | 1KB 블록 | 8KB 블록 | 비고 |
|---|---|---|---|---|
| ECB(AES-128) | aes_generic | ~200 MB/s | ~200 MB/s | 순수 소프트웨어, 테이블 룩업 |
| ECB(AES-128) | aesni | ~3.5 GB/s | ~5.0 GB/s | AES-NI, 4블록 인터리빙 |
| CBC(AES-128) 암호화 | aesni | ~1.5 GB/s | ~2.2 GB/s | 직렬 체인 → 파이프라인 제한 |
| CBC(AES-128) 복호화 | aesni | ~3.5 GB/s | ~4.8 GB/s | 복호화는 병렬 가능 |
| CTR(AES-128) | aesni | ~3.5 GB/s | ~5.0 GB/s | 카운터 병렬 → ECB급 성능 |
| GCM(AES-128) | aesni + clmul | ~3.0 GB/s | ~4.5 GB/s | CTR + GHASH 인터리빙 |
| XTS(AES-256) | aesni | ~2.5 GB/s | ~3.5 GB/s | tweak 연산 + 2배 키 길이 |
- 터보 부스트 영향 — AVX-512/VAES 사용 시 CPU가 다운클럭할 수 있어 순수 AES-NI 대비 의외로 느릴 수 있음. 워크로드 특성에 따라 판단 필요
- kernel_fpu_begin() 오버헤드(Overhead) — FPU 상태 저장/복원 비용(~수백 나노초)이 있어, 16바이트 단일 블록에서는 소프트웨어 구현이 더 빠를 수 있음
- dm-crypt 실제 성능 — I/O 스택 오버헤드(scatterlist 구성, bio 처리)로 인해 tcrypt 벤치마크의 50~70% 수준이 일반적
- NUMA 고려 — 암호화 워커 스레드(Thread)가 데이터의 NUMA 노드와 다른 노드에서 실행되면 메모리 접근 지연(Latency)으로 성능 저하
AES-NI 보안 이점: 부채널 공격 방어
소프트웨어 AES 구현은 S-Box 테이블 룩업을 사용하는데, 이는 cache-timing 부채널 공격에 취약합니다. 공격자는 AES 연산 중 캐시(Cache) 접근 패턴을 관측하여 키를 추출할 수 있습니다:
/* 소프트웨어 AES — cache-timing 취약점 */
/* crypto/aes_generic.c 의 S-Box 테이블 룩업 */
static const u32 Te0[256] = { ... }; /* 1KB 룩업 테이블 */
static const u32 Te1[256] = { ... };
static const u32 Te2[256] = { ... };
static const u32 Te3[256] = { ... };
/* 키에 의존하는 인덱스로 테이블 접근 → 캐시 라인 접근 패턴 노출 */
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ ...;
/* ↑ 공격자가 cache-line hit/miss 패턴으로 t0, t1 값을 추론 가능 */
/* AES-NI — 하드웨어 경로로 cache-timing 노출면을 축소 */
/* AESENC 명령어는 CPU 내부 회로에서 S-Box를 수행하므로
* 소프트웨어 테이블 룩업 대비 메모리 접근 패턴 노출이 줄어듦
* 전체 부채널 안전성은 마이크로아키텍처/플랫폼 조건을 함께 검토해야 함 */
aesenc %xmm_key, %xmm_state /* 실제 사이클 특성은 구현 경로와 환경에 따라 달라질 수 있음 */
FIPS 및 보안 권장: 보안에 민감한 환경에서는 aes_generic(소프트웨어)이 fallback으로 사용되지 않도록 aesni_intel 모듈이 확실히 로드되었는지 확인하세요. cat /proc/crypto | grep -B1 "aes-aesni"로 확인 가능합니다. 가상 머신(VM)에서는 호스트가 AES-NI CPUID 플래그를 패스스루하는지 확인해야 합니다(QEMU: -cpu host 또는 +aes).
AES-NI 커널 통합 메커니즘
AES-NI 하드웨어 가속의 커널 통합은 단순히 AESENC 명령어를 호출하는 것 이상의 복잡한 시스템 엔지니어링을 포함합니다. kernel_fpu_begin()/end() 기반의 FPU 컨텍스트 관리, SIMD 래퍼를 통한 인터럽트 안전성 보장, S/W fallback 전환 등 핵심 메커니즘을 분석합니다.
kernel_fpu_begin/end 내부 동작
/* arch/x86/kernel/fpu/core.c — kernel_fpu_begin() 내부 */
void kernel_fpu_begin_mask(unsigned int kfpu_mask)
{
/* 1. preemption 비활성화
* FPU 상태가 복원되기 전에 다른 태스크로 전환되면
* FPU 레지스터가 오염되므로 반드시 비활성화 */
preempt_disable();
/* 2. 현재 태스크의 FPU 상태를 메모리에 저장
* XSAVE/XSAVEOPT/FXSAVE 중 CPU가 지원하는 최적 명령어 사용 */
fpregs_lock();
fpu__save(current);
/* 3. 커널 FPU 사용 플래그 설정 */
current->flags |= PF_KTHREAD_FPU;
/* 이후 AES-NI 등 SIMD 명령어 사용 가능 */
}
void kernel_fpu_end(void)
{
/* 1. 태스크의 FPU 상태 복원 (XRSTOR 등) */
fpregs_unlock();
/* 2. preemption 재활성화 */
preempt_enable();
}
/* FPU 사용 가능 여부 확인 */
bool irq_fpu_usable(void)
{
/* hardirq 또는 softirq 컨텍스트에서는 false
* 이미 kernel_fpu_begin() 호출 중이면 false (중첩 금지) */
if (in_irq() || in_softirq())
return false;
if (current->flags & PF_KTHREAD_FPU)
return false;
return true;
}
SIMD 래퍼와 cryptd 위임
커널의 SIMD 래퍼(crypto/simd.c)는 실행 컨텍스트에 따라 자동으로 처리 경로를 분기합니다:
/* crypto/simd.c — SIMD 래퍼의 encrypt 함수 (간략화) */
static int simd_skcipher_encrypt(struct skcipher_request *req)
{
struct simd_skcipher_ctx *ctx = ...;
/* crypto_simd_usable(): irq_fpu_usable()의 래퍼 */
if (crypto_simd_usable()) {
/* Process context: 직접 SIMD 알고리즘 호출
* kernel_fpu_begin/end는 내부 알고리즘이 처리 */
return crypto_skcipher_encrypt(ctx->internal_req);
}
/* Interrupt context: cryptd kthread로 위임
* → cryptd 워커가 process context에서 실행
* → 완료 시 콜백으로 결과 통보 */
return cryptd_skcipher_enqueue(ctx->cryptd_req, req);
}
/* cryptd 워커 스레드 (crypto/cryptd.c) */
/* kcryptd 커널 스레드는 항상 process context에서 실행되므로
* kernel_fpu_begin() 호출이 안전함 */
static void cryptd_skcipher_encrypt(struct crypto_async_request *base,
int err)
{
/* process context → kernel_fpu_begin() 가능 */
err = crypto_skcipher_encrypt(subreq);
/* 원본 요청의 완료 콜백 호출 */
req->base.complete(&req->base, err);
}
S/W Fallback 메커니즘
H/W 가속기가 특정 조건(키 크기, 입력 크기, FPU 사용 불가 등)을 처리하지 못할 때 자동으로 S/W 구현으로 전환하는 메커니즘입니다:
/* H/W 가속 알고리즘의 fallback 구현 패턴 */
struct my_hw_ctx {
struct crypto_skcipher *fallback; /* S/W fallback tfm */
/* ... H/W 고유 컨텍스트 ... */
};
static int my_hw_init_tfm(struct crypto_skcipher *tfm)
{
struct my_hw_ctx *ctx = crypto_skcipher_ctx(tfm);
const char *name = crypto_skcipher_alg_name(tfm);
/* CRYPTO_ALG_NEED_FALLBACK으로 S/W 전용 구현을 요청
* → priority가 낮은 generic 구현이 선택됨 */
ctx->fallback = crypto_alloc_skcipher(name, 0,
CRYPTO_ALG_NEED_FALLBACK);
if (IS_ERR(ctx->fallback))
return PTR_ERR(ctx->fallback);
/* fallback의 reqsize를 반영 */
crypto_skcipher_set_reqsize(tfm,
max(crypto_skcipher_reqsize(ctx->fallback),
sizeof(struct my_hw_subreq)));
return 0;
}
static int my_hw_encrypt(struct skcipher_request *req)
{
struct my_hw_ctx *ctx = crypto_skcipher_ctx(
crypto_skcipher_reqtfm(req));
/* 조건 확인: SIMD 사용 가능 + H/W 지원 범위 */
if (!crypto_simd_usable() ||
req->cryptlen < MY_HW_MIN_SIZE) {
/* Fallback: S/W 구현으로 전환 */
skcipher_request_set_tfm(req, ctx->fallback);
return crypto_skcipher_encrypt(req);
}
/* H/W 가속 경로 */
kernel_fpu_begin();
/* ... AES-NI 명령어 사용 ... */
kernel_fpu_end();
return 0;
}
/* 알고리즘 등록 시 NEED_FALLBACK 플래그 설정 */
static struct skcipher_alg my_hw_alg = {
.base.cra_name = "xts(aes)",
.base.cra_driver_name = "xts-aes-my-hw",
.base.cra_priority = 500,
.base.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
/* ... */
};
코드 설명
H/W 가속 알고리즘이 S/W fallback을 내장하는 전형적 패턴으로, arch/x86/crypto/aesni-intel_glue.c 등 실제 드라이버에서 널리 사용됩니다.
- my_hw_ctx.fallbacktfm 초기화 시 같은 알고리즘의 S/W 전용 구현을
crypto_alloc_skcipher()로 확보합니다.CRYPTO_ALG_NEED_FALLBACKmask를 사용하여 H/W 구현이 아닌 generic 구현이 선택되도록 합니다. - crypto_skcipher_set_reqsize()fallback tfm의
reqsize와 H/W 서브요청 크기 중 큰 값을 설정하여, 요청 구조체에 두 경로 모두 충분한 컨텍스트 공간이 확보되도록 합니다. - crypto_simd_usable() 검사인터럽트 컨텍스트에서는 FPU/SIMD 레지스터를 사용할 수 없으므로, 이 조건이 false이면 S/W fallback으로 전환합니다. 데이터 크기가 H/W 최소 처리 단위보다 작은 경우에도 fallback을 사용합니다.
- skcipher_request_set_tfm(req, ctx->fallback)원본 요청의 tfm을 fallback tfm으로 교체한 뒤
crypto_skcipher_encrypt()를 호출하여 S/W 경로로 투명하게 전환합니다. - CRYPTO_ALG_NEED_FALLBACK 플래그알고리즘 등록 시 이 플래그를 설정하면 커널이 동일
cra_name의 S/W 구현 존재를 보장하며, fallback 할당 실패를 방지합니다.
Fallback 성능 영향: Fallback은 tfm 전환 오버헤드가 있지만, 일반적으로 작은 블록(16~64바이트)에서만 발생합니다. 대부분의 워크로드(dm-crypt, IPsec)는 킬로바이트 단위 데이터를 처리하므로 H/W 경로를 사용합니다. perf stat으로 aesni_* vs aes_generic_* 호출 비율을 확인하여 fallback 빈도를 모니터링할 수 있습니다.
ARM 암호화 가속
ARMv8-A 아키텍처는 Crypto Extensions(CE)를 통해 AES, SHA, 다항식 곱셈 등의 암호 연산을 하드웨어에서 직접 수행합니다. x86의 AES-NI에 대응하는 기능으로, 모바일 SoC부터 서버용 ARM 프로세서까지 널리 지원됩니다. 커널 Crypto API는 CE 명령어를 자동 감지하여 소프트웨어 구현보다 높은 우선순위로 등록합니다.
ARMv8-A Crypto Extensions 명령어
ARM CE는 AES, SHA-1, SHA-256, 다항식 곱셈(GCM용)을 위한 전용 명령어를 제공합니다:
| 명령어 | 동작 | 설명 |
|---|---|---|
AESE | AES 단일 라운드 암호화 | SubBytes + ShiftRows (AddRoundKey 별도) |
AESD | AES 단일 라운드 복호화 | InvSubBytes + InvShiftRows |
AESMC | AES MixColumns | 암호화 라운드의 열 혼합 단계 |
AESIMC | AES 역 MixColumns | 복호화 라운드의 역 열 혼합 |
SHA1C/P/M | SHA-1 라운드 | Choose/Parity/Majority 함수별 4라운드 처리 |
SHA1H | SHA-1 해시 고정 회전 | SHA-1 스케줄링 회전 연산 |
SHA1SU0/1 | SHA-1 스케줄 업데이트 | 메시지 스케줄 확장 |
SHA256H/H2 | SHA-256 라운드 | SHA-256 압축 함수 4라운드 처리 |
SHA256SU0/1 | SHA-256 스케줄 업데이트 | 메시지 스케줄 확장 |
PMULL/PMULL2 | 다항식 곱셈 | 64×64→128비트 캐리리스 곱셈 (GHASH용) |
x86 AES-NI와의 차이: AES-NI의 AESENC는 SubBytes+ShiftRows+MixColumns+AddRoundKey를 한 번에 수행하지만, ARM CE의 AESE는 SubBytes+ShiftRows만 처리하고 AESMC와 XOR을 별도로 수행합니다. 그러나 ARM 파이프라인에서 AESE+AESMC는 매크로 퓨전되어 실질적으로 단일 사이클에 처리됩니다.
커널 암호 모듈
ARM64 커널은 CE, NEON, 제네릭 세 가지 계층의 암호 모듈을 제공합니다:
| 모듈 | Kconfig | 알고리즘 | Priority | 요구사항 |
|---|---|---|---|---|
aes-arm64-ce | CRYPTO_AES_ARM64_CE_BLK | ecb/cbc/ctr/xts(aes) | 300 | ARM CE |
sha256-arm64-ce | CRYPTO_SHA256_ARM64_CE | sha256, sha224 | 300 | ARM CE |
sha512-arm64-ce | CRYPTO_SHA512_ARM64_CE | sha512, sha384 | 300 | ARM CE |
ghash-ce | CRYPTO_GHASH_ARM64_CE | ghash | 300 | PMULL |
aes-arm64-neon-blk | CRYPTO_AES_ARM64_NEON_BLK | ecb/cbc/ctr/xts(aes) | 200 | NEON/ASIMD |
sha256-arm64 | CRYPTO_SHA256_ARM64 | sha256 | 150 | NEON |
aes-generic | CRYPTO_AES | aes | 100 | 없음 |
모듈 등록과 priority 선택
ARM CE 모듈은 module_cpu_feature_match() 매크로를 사용하여 CPU가 해당 기능을 지원할 때만 자동 로드됩니다:
/* arch/arm64/crypto/aes-ce-core.S + aes-glue.c 패턴 */
/* CE 모듈: priority 300 — CPU에 CE 기능이 있으면 자동 선택 */
static struct skcipher_alg aes_algs[] = {{
.base.cra_name = "cbc(aes)",
.base.cra_driver_name = "cbc-aes-ce",
.base.cra_priority = 300,
.setkey = ce_aes_setkey,
.encrypt = ce_aes_cbc_encrypt,
.decrypt = ce_aes_cbc_decrypt,
}};
/* 모듈 로드 조건: ARM64_HAS_AES feature bit 확인 */
module_cpu_feature_match(AES, aes_ce_mod_init);
/* NEON 모듈: priority 200 — CE 없는 ARMv8에서 사용 */
static struct skcipher_alg aes_neon_algs[] = {{
.base.cra_name = "cbc(aes)",
.base.cra_driver_name = "cbc-aes-neon",
.base.cra_priority = 200,
}};
/* 제네릭 모듈: priority 100 — 항상 사용 가능한 최후의 수단 */
/* crypto/aes_generic.c */
# ARM64에서 Crypto Extensions 지원 확인
cat /proc/cpuinfo | grep -i features
# Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics ...
# ^^^ ^^^^^ ^^^^ ^^^^ — CE 관련 플래그
# 등록된 AES 드라이버와 priority 확인
grep -A4 'cbc(aes)' /proc/crypto
# name : cbc(aes)
# driver : cbc-aes-ce ← CE 모듈 (priority 300)
# priority : 300
NEON 기반 AES (bit-slicing)
CE가 없는 ARMv7이나 초기 ARMv8 프로세서에서는 NEON(ASIMD) SIMD 레지스터를 활용한 bit-slicing 기법으로 AES를 가속합니다. S-Box 테이블 룩업 대신 비트 연산으로 AES 라운드를 구현하여, 타이밍 부채널을 방지하면서 제네릭 구현보다 2~4배 빠른 성능을 제공합니다:
/* arch/arm64/crypto/aes-neonbs-glue.c — bit-sliced AES */
/* 8블록을 병렬로 처리하여 NEON 128-bit 레지스터 활용 극대화 */
static int aesbs_cbc_encrypt(struct skcipher_request *req)
{
/* NEON 레지스터 사용을 위해 커널 FPSIMD 컨텍스트 획득 */
kernel_neon_begin();
/* bit-slicing: 8개 AES 블록을 8개 NEON 레지스터에 전치하여
* 각 비트 위치별로 병렬 S-Box 연산 수행 */
aesbs_cbc_encrypt_neon(walk.dst.virt.addr,
walk.src.virt.addr, ctx->rk, nbytes, walk.iv);
kernel_neon_end();
}
SVE2 암호화 확장
ARMv9의 SVE2(Scalable Vector Extension 2)는 가변 길이 벡터 레지스터(128~2048비트)에서 동작하는 암호화 명령어를 추가합니다:
| 명령어 | 기능 | 비고 |
|---|---|---|
SM4E / SM4EKEY | SM4 암호화/키 확장 | 중국 국가 표준 블록 암호 |
AESE / AESMC (SVE2) | 벡터 길이만큼 AES 병렬 처리 | 256비트 SVE → 2블록 동시 |
RAX1 | SHA-3 rotate-and-XOR | Keccak 순열 가속 |
RSHAX / BEXT / BDEP | 비트 조작 | 암호 알고리즘 보조 |
SVE2 커널 지원 현황: Linux 6.x 기준 SVE2 crypto 명령어의 커널 Crypto API 드라이버는 아직 개발 초기 단계입니다. SM4 SVE2 드라이버(sm4-ce-core.S)가 먼저 합류했으며, AES/SHA-3 SVE2 최적화는 향후 커널에서 지원될 예정입니다. 벡터 길이가 가변이므로 기존 CE 고정 128비트 대비 처리량 확장이 가능합니다.
ARM CE 성능 비교
Cortex-A76 (ARMv8.2) 기준 tcrypt 벤치마크 결과:
| 알고리즘 | 구현 | 1024B 처리량 | 8192B 처리량 | 가속 배율 |
|---|---|---|---|---|
| AES-256-CBC | aes-generic | ~120 MB/s | ~130 MB/s | 1.0× |
| aes-neon (bit-slice) | ~450 MB/s | ~520 MB/s | ~4.0× | |
| aes-ce | ~1.8 GB/s | ~2.2 GB/s | ~17× | |
| SHA-256 | sha256-generic | ~95 MB/s | ~100 MB/s | 1.0× |
| sha256-ce | ~850 MB/s | ~1.1 GB/s | ~11× | |
| AES-256-GCM | gcm(aes-generic) | ~80 MB/s | ~90 MB/s | 1.0× |
| gcm(aes-ce) + ghash-ce | ~1.5 GB/s | ~1.9 GB/s | ~21× |
x86 추가 암호화 명령어
AES-NI 외에도 x86 아키텍처는 SHA, CRC32, SM3/SM4 등의 전용 명령어를 세대별로 추가해왔습니다. 커널은 각 명령어 세트에 대응하는 최적화 모듈을 제공하며, CPUID 플래그 기반으로 자동 선택합니다.
SHA-NI (SHA Extensions)
SHA-NI는 SHA-1과 SHA-256 라운드 함수를 하드웨어에서 수행하는 명령어 세트입니다:
| CPU | 도입 시기 | SHA-NI 명령어 | 커널 모듈 | Priority |
|---|---|---|---|---|
| Intel Goldmont (Atom) | 2016 | SHA1RNDS4, SHA1NEXTE, SHA256RNDS2, SHA256MSG1/2 | sha256-ni | 300 |
| Intel Ice Lake | 2019 | 동일 | sha256-ni | 300 |
| AMD Zen (Ryzen/EPYC) | 2017 | 동일 | sha256-ni | 300 |
# SHA-NI 지원 확인
grep sha_ni /proc/cpuinfo
# flags : ... sha_ni ...
# SHA-256 드라이버 확인: sha256-ni가 가장 높은 priority
grep -A3 'sha256' /proc/crypto | grep -E 'name|driver|priority'
# name : sha256
# driver : sha256-ni ← SHA-NI 하드웨어 가속
# priority : 300
# tcrypt 벤치마크: SHA-256
modprobe tcrypt mode=403 sec=3
# SHA-NI: ~2.5 GB/s (8K blocks) vs SW: ~300 MB/s → 약 8배 가속
AVX/AVX2 최적화 해시
SHA-NI가 없는 CPU에서는 AVX/AVX2 SIMD 명령어를 활용한 최적화 해시 구현을 사용합니다. Multi-buffer 기법은 여러 독립적인 해시 연산을 SIMD 레인에 배치하여 병렬 처리합니다:
| 모듈 | 명령어 세트 | Priority | 특징 |
|---|---|---|---|
sha256-ssse3 | SSSE3 | 150 | 기본 SIMD 최적화 |
sha256-avx | AVX | 160 | 256비트 레지스터 활용 |
sha256-avx2 | AVX2 | 170 | multi-buffer 4-way 병렬 |
sha512-avx2 | AVX2 | 170 | SHA-512 multi-buffer |
sha256-ni | SHA-NI | 300 | 전용 하드웨어 명령어 |
/* arch/x86/crypto/sha256_avx2_asm.S 개념 — multi-buffer 기법 */
/* 4개의 독립적인 SHA-256 연산을 YMM 레지스터에서 병렬 처리 */
/*
* YMM0 = [msg_A[0:31] | msg_B[0:31] | msg_C[0:31] | msg_D[0:31]]
* 각 64바이트 레인에서 독립적인 SHA-256 라운드 수행
* → 단일 스트림 대비 2~3배 처리량 향상
*/
/* 커널 등록 예시 */
static struct shash_alg sha256_avx2_alg = {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_avx2_update,
.final = sha256_avx2_final,
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-avx2",
.cra_priority = 170,
},
};
SM3/SM4 명령어 (Sapphire Rapids)
Intel Sapphire Rapids(4세대 Xeon)부터 중국 국가 표준 암호 알고리즘인 SM3(해시)과 SM4(블록 암호)의 전용 명령어를 지원합니다. 커널 모듈 sm4-aesni-avx2와 sm3-avx가 이를 활용합니다. SM4는 국제 표준 ISO/IEC 18033-3:2010에도 등록되어 있으며, 중국 시장 제품에서 AES 대신 필수적으로 사용됩니다.
| 명령어 | 기능 | CPU 최소 요구 | 커널 모듈 |
|---|---|---|---|
VSM3MSG1 / VSM3MSG2 | SM3 해시 메시지 확장 | Sapphire Rapids (4세대 Xeon) | sm3-avx |
VSM3RNDS2 | SM3 라운드 연산 (2라운드/1명령어) | Sapphire Rapids | sm3-avx |
VSM4KEY4 | SM4 키 확장 (4라운드) | Sapphire Rapids | sm4-aesni-avx2 |
VSM4RNDS4 | SM4 암복호화 (4라운드/1명령어) | Sapphire Rapids | sm4-aesni-avx2 |
# SM4 지원 확인 (CPUID bit)
grep sm[34] /proc/cpuinfo
# flags : ... sm3 sm4 ...
# SM4 커널 모듈 확인
grep sm4 /proc/crypto
# name : cbc(sm4)
# driver : cbc-sm4-aesni-avx2
# priority : 400
# SM4 성능 벤치마크
modprobe tcrypt mode=10 sec=1
# sm4-aesni-avx2: cbc-sm4 256bit ~4.5 GB/s (vs sm4-generic ~200 MB/s)
SM3/SM4는 중국 국가 암호 관리국(OSCCA)이 제정한 표준으로, 중국 시장 제품에서 AES/SHA 대신 필수 사용됩니다. IETF RFC 8998(TLS 1.3 + SM Cipher Suites)에서도 정의되어 국제적으로도 활용이 확대되고 있습니다.
CRC32C SSE4.2 가속
SSE4.2의 CRC32 명령어는 Castagnoli CRC(CRC32C)를 하드웨어에서 수행합니다. ext4, btrfs, iSCSI 등 커널 전반에서 데이터 무결성 검증에 사용됩니다:
# CRC32C 가속 모듈 확인
grep crc32 /proc/crypto
# name : crc32c
# driver : crc32c-intel ← SSE4.2 하드웨어 가속
# priority : 200
# ext4 파일시스템에서 CRC32C 사용 확인
dmesg | grep crc32c
# ext4: using crc32c-intel for CRC32C checksums
# 성능: crc32c-intel ~20 GB/s vs crc32c-generic ~800 MB/s
# → SSE4.2 CRC32 명령어는 클럭당 8바이트 처리 가능
Priority 스택 요약: x86에서 동일 알고리즘에 여러 구현이 존재할 때 선택 순서는 전용 명령어(300~400) > AVX2(170) > AVX(160) > SSSE3(150) > Generic(100)입니다. /proc/crypto에서 동일 name에 대해 driver와 priority를 확인하여 현재 시스템에서 어떤 구현이 활성화되어 있는지 파악할 수 있습니다.
네트워크 암호화 오프로드
네트워크 암호화를 NIC 하드웨어에 오프로드하면 CPU 부하를 대폭 줄이고 와이어 속도에 가까운 암호화 처리량을 달성할 수 있습니다. 커널은 IPsec, kTLS, MACsec 세 가지 프로토콜에서 NIC 암호화 오프로드를 지원하며, 각각 다른 오프로드 레벨과 드라이버 콜백을 제공합니다.
IPsec 인라인 오프로드
IPsec 오프로드는 xfrm_dev_offload 구조체를 통해 두 가지 모드를 지원합니다:
| 모드 | 상수 | NIC 처리 범위 | CPU 역할 |
|---|---|---|---|
| Crypto offload | XFRM_DEV_OFFLOAD_CRYPTO | ESP 암복호화만 | ESP 헤더 구성, 패킷 라우팅(Routing) |
| Packet offload | XFRM_DEV_OFFLOAD_PACKET | ESP 암복호화 + 헤더 삽입/제거 | SA/SP 정책만 관리 |
NIC 드라이버는 xfrmdev_ops 콜백을 구현하여 SA(Security Association)를 하드웨어에 설치합니다:
/* include/linux/netdevice.h — IPsec 오프로드 콜백 */
struct xfrmdev_ops {
int (*xdo_dev_state_add)(struct xfrm_state *x,
struct netlink_ext_ack *extack);
void (*xdo_dev_state_delete)(struct xfrm_state *x);
void (*xdo_dev_state_free)(struct xfrm_state *x);
bool (*xdo_dev_offload_ok)(struct sk_buff *skb,
struct xfrm_state *x);
int (*xdo_dev_policy_add)(struct xfrm_policy *xp,
struct netlink_ext_ack *extack);
void (*xdo_dev_policy_delete)(struct xfrm_policy *xp);
};
/* 지원 NIC 예시: NVIDIA ConnectX-6 Dx+/7 (mlx5), Intel E810 (ice) */
Crypto vs Packet offload 선택: Crypto offload는 SA만 NIC에 설치하므로 기존 라우팅/방화벽(Firewall) 규칙과 완전 호환됩니다. Packet offload는 ESP 헤더까지 NIC이 처리하여 CPU 부하가 더 낮지만, 라우팅/필터링이 ESP 내부 패킷에 접근할 수 없습니다. 대부분의 경우 crypto offload가 호환성과 성능의 균형이 좋습니다. 상세한 구현과 설정은 IPsec 하드웨어 오프로드를 참고하세요.
kTLS 암호화 오프로드
kTLS(Kernel TLS)는 TLS 레코드 계층의 암복호화를 NIC에 오프로드할 수 있습니다. 사용자 공간에서 TLS 핸드셰이크를 완료한 후 setsockopt(TCP_ULP, "tls")로 커널에 키를 전달하면, 지원 NIC이 자동으로 오프로드합니다:
| NIC | 드라이버 | TX offload | RX offload | 지원 암호 |
|---|---|---|---|---|
| NVIDIA ConnectX-6+/7 | mlx5 | TLS 1.2/1.3 | TLS 1.2/1.3 | AES-128/256-GCM |
| Broadcom BCM57504 | bnxt | TLS 1.2 | — | AES-128-GCM |
| Intel E810 | ice | TLS 1.2/1.3 | TLS 1.2/1.3 | AES-128/256-GCM |
kTLS 오프로드 조건: (1) NIC 드라이버가 tls_dev_add()/tls_dev_del() 콜백을 구현해야 하고, (2) ethtool -k eth0 | grep tls에서 tls-hw-tx-offload/tls-hw-rx-offload가 on이어야 합니다. 오프로드 불가 시 커널이 자동으로 소프트웨어 kTLS로 폴백합니다. 상세는 kTLS 하드웨어 오프로드를 참고하세요.
MACsec 오프로드
MACsec(IEEE 802.1AE)은 이더넷 프레임 레벨에서 AES-GCM-128/256 암호화를 수행합니다. 일부 NIC(NVIDIA ConnectX-6 Dx/7, Intel E810, Marvell Prestera)에서 MACsec 오프로드를 지원하며, macsec_ops 콜백으로 SA를 하드웨어에 설치합니다. MACsec의 상세 아키텍처와 설정은 이더넷 MACsec을 참고하세요.
MACsec은 OSI 레이어 2(Layer 2)에서 동작하여 이더넷 프레임 전체를 암호화합니다. IPsec이 레이어 3 이상에서 동작하는 것과 달리, MACsec은 동일 LAN 세그먼트 내의 모든 트래픽을 투명하게 보호합니다. NIC 드라이버는 macsec_ops 콜백 구조체를 통해 보안 연관(Security Association, SA)을 하드웨어에 설치하고, 오프로드가 활성화되면 NIC이 와이어 속도(Wire Speed)로 암복호화를 수행합니다. 상위 계층(IP, TCP 등)은 암호화 과정을 전혀 인식하지 못하며, CPU는 SA 설정과 키 관리 등 제어 경로(Control Path)만 담당합니다.
| NIC | 드라이버 | MACsec TX | MACsec RX | 최대 SA 수 | 비고 |
|---|---|---|---|---|---|
| NVIDIA ConnectX-6 Dx/7 | mlx5 |
✓ | ✓ | 1024 | Extended Packet Number (XPN) 지원 |
| Intel E810 | ice |
✓ | ✓ | 64 | IPsec offload와 공존 불가 (택 1) |
| Marvell Prestera | prestera |
✓ | ✓ | 128 | 스위치 칩 내장 MACsec |
# ━━━ MACsec 오프로드 설정 ━━━
# MACsec 인터페이스 생성 (offload 모드)
ip link add link eth0 macsec0 type macsec sci 1234567890abcdef \
encrypt on offload mac
# SA 키 설정
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 deca0000000000000000000000000000
# offload 상태 확인
ip macsec show
# offload: mac ← NIC에서 MACsec 처리 중
# NIC의 MACsec offload 기능 확인
ethtool -k eth0 | grep macsec
# macsec-hw-offload: on
오프로드 확인 및 설정
# ━━━ 네트워크 암호화 오프로드 확인/설정 ━━━
# IPsec offload 기능 확인
ethtool -k eth0 | grep esp
# esp-hw-offload: on ← IPsec crypto offload 가능
# esp-tx-csum-hw-offload: on
# IPsec SA에 오프로드 설정
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 proto esp spi 0x100 \
mode transport aead 'rfc4106(gcm(aes))' 0x... 128 \
offload dev eth0 dir out # ← offload 키워드
# 오프로드 상태 확인
ip xfrm state list | grep -A2 offload
# offload dev eth0 dir out type crypto
# kTLS offload 확인
ethtool -k eth0 | grep tls
# tls-hw-tx-offload: on
# tls-hw-rx-offload: on
# MACsec offload 확인
ethtool -k eth0 | grep macsec
# macsec-hw-offload: on
스토리지 인라인 암호화
스토리지 인라인 암호화(Inline Encryption)는 데이터가 저장장치에 기록/읽기될 때 전용 하드웨어 엔진(ICE, Inline Crypto Engine)이 와이어 속도로 실시간 암복호화를 수행하는 기술입니다. CPU 개입이 전혀 없으므로 dm-crypt 대비 성능 오버헤드가 없고, 모바일 기기의 파일 기반 암호화(FBE)에서 핵심 역할을 합니다.
blk-crypto 프레임워크
Linux 커널의 blk-crypto 프레임워크는 블록 레이어에서 인라인 암호화를 추상화합니다. 상위 계층(fscrypt, dm-crypt)이 blk_crypto_key를 설정하면, 하드웨어 지원 여부에 따라 ICE 또는 소프트웨어 폴백으로 자동 전환합니다:
/* include/linux/blk-crypto.h — 핵심 구조체 */
struct blk_crypto_key {
struct blk_crypto_config crypto_cfg; /* 암호 설정 */
unsigned int data_unit_size; /* 암호화 단위 (보통 4096) */
unsigned int size; /* 키 크기 */
u8 raw[BLK_CRYPTO_MAX_KEY_SIZE]; /* 원시 키 데이터 */
};
enum blk_crypto_mode_num {
BLK_ENCRYPTION_MODE_INVALID,
BLK_ENCRYPTION_MODE_AES_256_XTS, /* FBE 기본 */
BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, /* 레거시 FDE */
BLK_ENCRYPTION_MODE_ADIANTUM, /* CE 없는 저가형 */
BLK_ENCRYPTION_MODE_SM4_XTS, /* 중국 표준 */
};
/* blk_crypto_profile: 스토리지 디바이스의 ICE 능력 기술 */
struct blk_crypto_profile {
struct blk_crypto_ll_ops ll_ops; /* keyslot 관리 콜백 */
unsigned int max_dun_bytes_supported; /* DUN 크기 */
unsigned int num_slots; /* 하드웨어 keyslot 수 */
unsigned int modes_supported[BLK_ENCRYPTION_MODE_MAX];
};
| 암호 모드 | 키 크기 | 용도 | 비고 |
|---|---|---|---|
AES-256-XTS | 512비트 (2×256) | Android FBE 기본 | 대부분의 ICE가 지원 |
AES-128-CBC-ESSIV | 256비트 | 레거시 FDE | IV 예측 방지용 ESSIV |
Adiantum | 256비트 | CE 없는 저가형 기기 | ChaCha 기반, SW 전용 |
SM4-XTS | 256비트 | 중국 시장 규정 | SM4 블록 암호 + XTS |
인라인 암호화 엔진
주요 스토리지 인터페이스별 인라인 암호화 엔진:
| 엔진 | 스토리지 | 커널 드라이버 | 알고리즘 | keyslot 수 |
|---|---|---|---|---|
| Qualcomm ICE | UFS | ufs-qcom + qcom-ice | AES-256-XTS | 보통 32개 |
| Samsung FMP | UFS | ufs-exynos | AES-256-XTS | 8~16개 |
| MediaTek CQHCI | eMMC | cqhci | AES-256-XTS | 32개 |
| NVMe (TCG Opal) | NVMe SSD | nvme | AES-256-XTS | 벤더 종속 |
교차참조: UFS ICE의 하드웨어 아키텍처, keyslot 관리, 지원 알고리즘 상세는 UFS 인라인 암호화를 참고하세요. eMMC CQHCI 암호화는 eMMC를 참고하세요.
소프트웨어 폴백
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK이 활성화되면, ICE가 없는 디바이스에서도 blk-crypto 인터페이스를 사용할 수 있습니다. 폴백 모듈은 내부적으로 Crypto API의 crypto_skcipher를 사용하여 소프트웨어로 암복호화를 수행합니다:
/* block/blk-crypto-fallback.c — 소프트웨어 폴백 개요 */
static int blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
{
struct bio_crypt_ctx *bc = (*bio_ptr)->bi_crypt_context;
struct crypto_skcipher *tfm;
/* blk_crypto_mode → Crypto API 알고리즘 이름 매핑 */
/* AES_256_XTS → "xts(aes)" */
tfm = crypto_alloc_skcipher(
blk_crypto_modes[bc->bc_key->crypto_cfg.crypto_mode].name,
0, 0);
/* Crypto API를 통한 소프트웨어 암호화 수행 */
/* AES-NI/ARM CE가 있으면 HW 가속으로 폴백됨 */
crypto_skcipher_encrypt(req);
}
fscrypt + blk-crypto 연동
fscrypt(파일시스템 암호화)는 blk-crypto를 통해 ICE를 활용합니다. 각 파일(또는 디렉토리)마다 고유한 키를 생성하고, blk-crypto에 키를 등록하여 I/O 요청에 첨부합니다:
# ━━━ fscrypt + inline encryption 설정 ━━━
# 1. 디바이스의 inline encryption 지원 확인
cat /sys/block/sda/queue/crypto/max_dun_bytes
# 8 ← DUN(Data Unit Number) 크기, 0이면 미지원
cat /sys/block/sda/queue/crypto/modes/AES-256-XTS
# 4096 ← data_unit_size, 0이면 미지원
# 2. fscrypt에서 inline encryption 사용 (Android FBE)
# /data 파티션 마운트 시 inlinecrypt 옵션 추가
mount -o inlinecrypt /dev/block/sda13 /data
# 3. 키 해제 (파일 잠금)
# fscrypt lock /data → blk_crypto_evict_key()로 HW keyslot 제거
fscrypt lock /data
# → ICE keyslot이 안전하게 소거됨
dm-crypt passthrough: dm-crypt는 CONFIG_DM_DEFAULT_KEY와 --inline-crypt 옵션을 통해 자체 암호화 대신 blk-crypto로 요청을 전달할 수 있습니다. 이 경우 dm-crypt 계층은 키 관리만 담당하고 실제 암복호화는 ICE가 수행하여, dm-crypt의 CPU 오버헤드를 완전히 제거합니다.
암호화 오프로드 결정 가이드
다양한 암호화 오프로드 옵션 중 워크로드 특성에 맞는 방식을 선택하는 것이 중요합니다. CPU ISA 가속으로 충분한 경우 별도 가속기를 도입할 필요가 없고, 반대로 대규모 암호 처리에서는 전용 가속기가 CPU 자원을 확보해줍니다.
룩어사이드 오프로드와 인라인 오프로드
암호화 하드웨어 오프로드는 데이터가 가속기를 거치는 방식에 따라 룩어사이드 오프로드(Lookaside Offload)와 인라인 오프로드(Inline Offload) 두 가지 아키텍처로 나뉩니다. 룩어사이드 오프로드는 호스트 CPU가 암호화 요청을 명시적으로 PCIe 가속기에 전송하고 비동기로 결과를 받는 방식이며, 인라인 오프로드는 NIC이나 스토리지 컨트롤러가 데이터 경로(Data Path) 상에서 투명하게 암복호화를 수행하는 방식입니다. 두 아키텍처는 CPU 개입 수준, 지연 시간 특성, 유연성이 근본적으로 다르므로 워크로드에 맞는 선택이 필요합니다.
룩어사이드 오프로드 동작 원리
룩어사이드 오프로드에서 호스트 CPU는 암호화가 필요한 시점에 직접 가속기에 작업을 제출합니다. 전형적인 처리 흐름은 다음과 같습니다:
- 요청 구성: CPU가 암호 알고리즘, 키, IV, 입출력 버퍼 주소를 포함한 요청 디스크립터(Request Descriptor)를 구성합니다.
- Ring 제출: 디스크립터를 요청 링(Request Ring)에 기록하고 MMIO 도어벨(Doorbell)을 써서 가속기에 새 작업을 알립니다.
- DMA 전송: 가속기가 PCIe DMA로 호스트 메모리에서 입력 데이터를 읽어옵니다.
- 암호 연산: 가속기 내부의 암호 엔진(Crypto Engine)이 연산을 수행합니다. 이 동안 CPU는 다른 작업을 수행할 수 있습니다.
- 결과 기록: 연산 결과를 DMA로 호스트 메모리에 기록하고, 완료 링(Completion Ring)에 응답 디스크립터를 씁니다.
- 완료 통지: MSI-X 인터럽트 또는 폴링(Polling)으로 CPU가 완료를 감지하고 콜백(Callback)을 실행합니다.
커널 Crypto API에서는 이 비동기 흐름을 -EINPROGRESS 반환값으로 표현합니다.
호출자(IPsec, kTLS, dm-crypt 등)는 crypto_skcipher_encrypt() 호출 후 -EINPROGRESS를 받으면 완료 콜백을 기다리며,
가속기가 작업을 마치면 콜백이 호출되어 결과를 전달합니다.
이 패턴 덕분에 CPU 코어 하나가 수백~수천 개의 암호 요청을 동시에 가속기에 위임할 수 있어,
SSL/TLS 프록시나 VPN 게이트웨이(VPN Gateway)처럼 대량의 동시 암호 세션을 처리하는 워크로드에 적합합니다.
Host CPU 중심 룩어사이드
Host CPU 중심 룩어사이드(Host CPU-centric Lookaside)는 범용 x86_64 또는 ARM64 서버에 개별 PCIe 카드 형태의 가속기를 장착하는 모델입니다. CPU와 가속기가 물리적으로 분리되어 있으며, 모든 데이터 교환이 PCIe 버스의 DMA를 통해 이루어집니다. 이 모델의 핵심은 기존 서버 인프라를 변경하지 않고 PCIe 슬롯에 카드만 추가하여 암호화 가속 능력을 확보할 수 있는 점입니다. 전용 가속기 카드뿐 아니라, SoC 기반 DPU/SmartNIC을 PCIe 카드 형태로 서버에 장착하여 호스트 CPU의 룩어사이드 가속기로 활용하는 방식도 이 모델에 포함됩니다.
전형적인 구성과 데이터 경로는 다음과 같습니다:
- 물리적 분리: CPU(호스트)와 가속기(카드)가 PCIe 링크로 연결됩니다. 카드는 자체 SRAM, 마이크로엔진, DMA 컨트롤러를 보유합니다.
- PCIe DMA 오버헤드: 모든 입출력 데이터가 PCIe TLP(Transaction Layer Packet)로 전송되므로, 소량 데이터(~512B 이하)에서는 DMA 설정(Setup) 비용이 암호 연산 자체보다 클 수 있습니다.
- MMIO 도어벨: 요청 제출 시 CPU가 카드의 BAR(Base Address Register) 영역에 MMIO 쓰기를 수행하여 새 작업을 알립니다.
- MSI-X 완료: 카드가 연산을 마치면 MSI-X 인터럽트로 호스트에 통지하거나, 호스트가 Completion Ring을 폴링합니다.
Host CPU 중심 룩어사이드에 사용되는 PCIe 카드는 크게 두 종류로 나뉩니다:
| 카드 유형 | 구조 | 대표 제품 | 특징 |
|---|---|---|---|
| 전용 가속기 카드 | 암호 엔진 + DMA만 탑재 (범용 CPU 코어 없음) |
Intel QAT 카드 (DH895xCC, 8950/8970) Marvell NITROX V (CNN55XX) |
호스트 CPU가 모든 제어 담당 카드는 순수 연산만 수행 |
| DPU/SmartNIC 카드 | SoC 통째로 PCIe 카드에 탑재 (ARM 코어 + 가속기 + NIC) |
Marvell OCTEON 10 DPU (CN10K CPT) Marvell LiquidIO (OCTEON TX/TX2) |
카드 내부 ARM 코어에서 자체 처리 가능 호스트에 VF로 룩어사이드 노출 + SSO 파이프라인 겸용 |
OCTEON DPU의 이중 모드: Marvell OCTEON 10 DPU는 PCIe 카드로 x86 서버에 장착됩니다. 호스트 CPU 관점에서는 SR-IOV VF를 통해 CPT에 룩어사이드 암호 요청을 제출하는 일반적인 PCIe 가속기이지만, 카드 내부에서는 ARM 코어 + SSO + CPT가 SoC 중심 모델로 독립 동작할 수도 있습니다. 즉 호스트 오프로드와 카드 자체 처리(bump-in-the-wire IPsec 등)를 동시에 수행하는 하이브리드 모델이 가능합니다.
기타 대표 하드웨어: AMD CCP는 CPU 다이에 통합되지만 PCIe 디바이스로 노출되어 Host CPU 중심 모델과 동일한 인터페이스를 사용합니다(AMD CCP 섹션).
SoC 중심 룩어사이드
SoC 중심 룩어사이드(SoC-centric Lookaside)는 네트워크 SoC 내부에 암호화 가속 엔진이 통합된 모델입니다. CPU 코어와 가속기가 SoC 내부 인터커넥트(AMBA, CCN, IOBN 등)로 직접 연결되어, PCIe 버스를 경유하지 않고 메모리를 공유합니다. 이 모델은 임베디드·네트워크 장비(라우터, NGFW, DPU)에서 주로 사용됩니다.
Host CPU 중심 모델과의 핵심 차이점:
- 내부 버스 접근: PCIe TLP 오버헤드가 없어 요청 제출~완료 지연이 크게 낮습니다. 캐시 코히어런트(Cache Coherent) 인터커넥트를 사용하는 SoC에서는 DMA 없이 공유 메모리로 직접 접근하기도 합니다.
- HW 이벤트 스케줄러 연동: Marvell OCTEON의 SSO(Schedule/Synchronize/Order)처럼, 암호 연산 완료 시 CPU 인터럽트 없이 하드웨어가 다음 처리 단계로 작업을 자동 전달합니다. 이는 Host CPU 중심 모델에서 불가능한 고유 기능입니다.
- LMTST/원자적 제출: OCTEON CN10K에서는
LMTST(Large Memory Transaction Store)라는 ARM 확장 명령으로 디스크립터를 원자적으로 제출하여, MMIO 도어벨 단계를 생략합니다. - SoC 종속성: 특정 SoC 플랫폼에서만 사용 가능하며, 범용 x86 서버에 추가 장착할 수 없습니다.
Host CPU 중심 vs SoC 중심 룩어사이드 비교
| 특성 | Host CPU 중심 룩어사이드 | SoC 중심 룩어사이드 |
|---|---|---|
| 연결 방식 | PCIe 버스 (DMA/MMIO) | SoC 내부 인터커넥트 (AMBA/CCN/IOBN) |
| 요청 제출 | Ring에 기록 + MMIO 도어벨 | LMTST 원자적 쓰기 또는 Job Ring |
| 완료 통지 | MSI-X 인터럽트 / 폴링 | HW 이벤트(SSO) 자동 전달 / 인터럽트 |
| 요청 지연 | ~2-5 μs (PCIe TLP + DMA 설정) | ~0.5-1 μs (내부 버스 직접) |
| 메모리 접근 | DMA로 호스트 메모리 복사 | 캐시 코히어런트 공유 메모리 직접 접근 |
| HW 파이프라인 | 전용 카드: 불가 (호스트 CPU가 매 단계 개입) DPU 카드: 카드 내부에서는 가능 (SSO 연동) |
가능 — SSO가 CPT→NIX 등 HW 블록 간 자동 연결 |
| 플랫폼 유연성 | 모든 PCIe 슬롯 서버에 장착 가능 | 해당 SoC 플랫폼에서만 사용 가능 |
| 교체/업그레이드 | 카드 교체로 세대 업그레이드 가능 | SoC 전체 교체 필요 |
| Inline 겸용 | 전용 카드: Lookaside 전용 DPU 카드: Inline 겸용 가능 (카드 내부 NIX+IE) |
IE(IPsec Engine) 등으로 Inline 모드 겸용 |
| 대표 하드웨어 | 전용 카드: QAT 카드(DH895xCC, 8950/8970), NITROX V(CNN55XX) DPU 카드: OCTEON 10 DPU(CN10K), LiquidIO(TX/TX2) AMD CCP (다이 통합이나 PCIe 인터페이스) |
Marvell OCTEON CPT(CN96/CN10K) NXP CAAM(i.MX, Layerscape) HiSilicon SEC2(Kunpeng) QAT Gen4+(Xeon 내장 RCiEP) |
| 주요 사용처 | 데이터센터 SSL 프록시, CDN, VPN GW DPU: 클라우드 인프라, 가상화 호스트 |
캐리어 라우터, NGFW, DPU, 임베디드 |
수렴 추세: 최근 두 모델의 경계가 흐려지고 있습니다. Intel QAT는 Gen4(4세대 Xeon)부터 CPU 다이에 RCiEP(Root Complex Integrated Endpoint)로 통합되어, PCIe 카드 없이도 룩어사이드 가속을 사용할 수 있습니다. 반대로 Marvell OCTEON 10 DPU는 SoC 내장 CPT를 SmartNIC/DPU 형태로 x86 서버에 장착하여, SoC 중심 모델의 장점(SSO 연동, 저지연)을 Host CPU 환경에서 활용합니다. 하드웨어 선택 시 현재 인프라(범용 서버 vs 전용 SoC)와 워크로드 특성(범용 암호화 vs 네트워크 파이프라인)을 함께 고려해야 합니다.
룩어사이드 vs 인라인 비교
| 특성 | 룩어사이드 오프로드 | 인라인 오프로드 |
|---|---|---|
| 데이터 흐름 | CPU → 가속기 → CPU (요청/응답) | 데이터 경로 상에서 투명 처리 |
| CPU 역할 | 요청 제출 + 완료 콜백 처리 | SA/키 설정만 (제어 경로) |
| 오프로드 시점 | CPU가 명시적으로 결정 | 매칭 트래픽에 자동 적용 |
| 지연 시간 | ~수 μs (DMA + 엔진 처리) | 거의 없음 (와이어 속도) |
| 알고리즘 범위 | 넓음 (대칭 + 비대칭 + 해시) | 제한적 (AES-GCM, AES-XTS 등) |
| 유연성 | 높음 — 임의 데이터에 적용 가능 | 프로토콜 종속 (IPsec/TLS/MACsec) |
| 동시 세션 | 수천~수만 (Ring 기반 큐잉) | SA/keyslot 수에 제한 |
| 대표 하드웨어 | QAT, AMD CCP, Marvell NITROX, NXP CAAM | ConnectX-6 Dx, E810, UFS ICE |
| 적합한 워크로드 | SSL 프록시, VPN GW, 배치 암호화, PKI | 고대역폭 IPsec/TLS, 디스크 FBE |
실전 선택 기준: 암호화 대상이 특정 네트워크 프로토콜(IPsec, TLS)이나 스토리지에 한정되면 인라인 오프로드가 가장 효율적입니다. 반면 다양한 알고리즘·프로토콜에 걸쳐 대량의 암호 요청을 처리해야 하거나, RSA/ECDSA 같은 비대칭 연산이 필요한 경우에는 룩어사이드 오프로드가 유리합니다. QAT의 룩어사이드 구현 상세는 QAT Crypto 요청 처리 흐름을, NIC 인라인 오프로드 구현은 네트워크 암호화 오프로드를, 스토리지 인라인 오프로드는 스토리지 인라인 암호화를 참고하세요.
오프로드 유형별 선택 기준
| 오프로드 유형 | 장점 | 단점 | 적합한 경우 |
|---|---|---|---|
| CPU ISA (AES-NI, ARM CE) |
최저 지연, 추가 비용 없음, 모든 CPU에 내장 | CPU 코어 점유, FPU 컨텍스트 전환 비용 | 대부분의 범용 워크로드, 소량~중량 암호화 |
| PCI 가속기 (QAT, CCP) |
CPU 부하 없음, 고처리량, 비대칭 암호 지원 | DMA/MMIO 오버헤드, 비용, 드라이버 의존성 | SSL/TLS 프록시, 대량 배치 암호화, PKI 연산 |
| NIC 인라인 (IPsec/kTLS) |
와이어 속도 처리, CPU 완전 해방, 라인 레이트 | 제한된 알고리즘, NIC 종속, SA 수 제한 | 고대역폭 네트워크 암호화 (100G+ IPsec/TLS) |
| 스토리지 ICE (UFS/eMMC/NVMe) |
CPU 0%, 와이어 속도, 배터리 절약 | 제한된 알고리즘(AES-XTS), keyslot 수 제한 | 모바일 FBE, 서버 디스크 암호화 |
패킷 크기 임계값과 CPU 사용률
오프로드 효율은 데이터 크기에 크게 의존합니다. 소량 데이터에서는 오프로드 설정(DMA 맵핑, 디스크립터 전송)의 고정 비용이 암호화 자체보다 클 수 있습니다:
| 워크로드 | 데이터 크기 | 권장 방식 | 근거 |
|---|---|---|---|
| DNS/QUIC 패킷 | <512B | CPU ISA (AES-NI/CE) | 오프로드 setup 비용 > 암호화 비용 |
| 웹 HTTP/2 TLS | 1~16 KB | CPU ISA 또는 kTLS NIC | kTLS는 대역폭(Bandwidth) 높을 때 유리 |
| IPsec VPN 터널 | 1.4 KB (MTU) | NIC offload | 패킷 수가 많아 CPU 부하 누적 |
| 디스크 I/O (4KB) | 4~128 KB | ICE 또는 CPU ISA | ICE 있으면 무조건 ICE 사용 |
| SSL/TLS 프록시 | 다양 | QAT / CCP | 수천 연결의 핸드셰이크 + 벌크 암호화 |
| 배치 파일 암호화 | MB~GB | QAT / CCP | CPU 코어를 다른 작업에 활용 |
일반적인 경험칙: (1) 스토리지 암호화는 ICE가 있으면 항상 ICE 사용, (2) 네트워크 암호화는 10G 이상에서 NIC offload 고려, (3) 그 외 대부분의 경우 AES-NI/ARM CE만으로 충분합니다. QAT/CCP 같은 PCI 가속기는 SSL 프록시나 VPN 게이트웨이처럼 암호화가 주 워크로드인 경우에 도입 효과가 큽니다.
종합 비교
| 특성 | CPU ISA | PCI 가속기 | NIC 인라인 | 스토리지 ICE |
|---|---|---|---|---|
| 지연 시간 | 최저 (~ns) | 중간 (~μs) | 낮음 | 없음 (HW) |
| 처리량 | ~10 GB/s/코어 | ~100 Gbps | 라인 레이트 | 라인 레이트 |
| CPU 부하 | 높음 | 없음 | 없음 | 없음 |
| 알고리즘 범위 | 모든 알고리즘 | 넓음 | 제한적 | AES-XTS |
| 추가 비용 | 없음 | 가속기 카드 | 지원 NIC | SoC 내장 |
| 설정 복잡도 | 자동 | 드라이버 설정 | NIC + xfrm | inlinecrypt 옵션 |
| 대표 사례 | dm-crypt, TLS | SSL 프록시 | IPsec 게이트웨이 | Android FBE |
SmartNIC/DPU 오프로드: NVIDIA BlueField, AMD Pensando 같은 DPU는 NIC 인라인 오프로드와 PCI 가속기의 특성을 결합합니다. IPsec packet offload + OVS 룰 처리를 DPU에서 수행하여 호스트 CPU를 완전히 해방할 수 있습니다. 상세는 SmartNIC/DPU 암호화 오프로드를 참고하세요.
Intel® QuickAssist Technology (Intel® QAT)
Intel QAT는 암호화(Cipher), 해싱(Hash), 압축/해제(Compression)를 하드웨어로 가속하는 기술입니다. 커널 Crypto Framework (Crypto API)에 통합되어 IPsec, TLS(kTLS), dm-crypt, 스토리지 압축 등에서 CPU 오프로드를 제공합니다. QAT는 룩어사이드 오프로드 아키텍처의 대표적인 구현으로, CPU가 Ring Pair를 통해 암호 요청을 제출하고 비동기로 결과를 수신합니다. 초기에 개별 PCIe 카드(DH895xCC, 8950/8970)로 출발하여, 칩셋 내장(C62x — Lewisburg PCH, C3xxx — Atom Denverton), 그리고 4세대 Xeon부터 CPU 다이 통합(RCiEP)으로 진화해 왔습니다.
QAT 세대별 비교
QAT 하드웨어는 크게 개별 PCIe 카드(Discrete), 칩셋/SoC 내장(Chipset-integrated), CPU 다이 통합(On-die RCiEP) 세 가지 폼 팩터로 구분됩니다. 아래 테이블은 각 세대의 하드웨어 사양을 정리합니다.
| QAT 세대 | 폼 팩터 | 대표 제품 / 플랫폼 | PCIe | PCI Device ID (PF) | VF 수 | 암호 처리량 | 커널 드라이버 |
|---|---|---|---|---|---|---|---|
| Gen 1 | 개별 PCIe 카드 | DH895xCC (8950 카드) | PCIe 2.0 ×8 | 0x0435 |
32 | ~20 Gbps | qat_dh895xcc |
| Gen 2 | 칩셋 내장 | C62x (Lewisburg PCH, Xeon SP 1~3세대) | PCIe 3.0 | 0x37c8 |
3 PF × 16 VF | ~50 Gbps | qat_c62x |
| SoC 내장 | C3xxx (Atom C3000 Denverton) | PCIe 3.0 | 0x19e2 |
16 | ~20 Gbps | qat_c3xxx |
|
| 개별 PCIe 카드 | 8960 카드 (PCIe 3.0 ×8), 8970 카드 (PCIe 3.0 ×16) | PCIe 3.0 | 0x37c8 |
48 (8970) | ~100 Gbps | qat_c62x |
|
| Gen 4 | CPU 다이 통합 (RCiEP) | 4xxx — Sapphire Rapids / Emerald Rapids (Xeon 4·5세대) | RCiEP | 0x4940 |
CPU당 최대 4 EP × 16 VF | ~200 Gbps/소켓 | qat_4xxx |
| Gen 5 | CPU 다이 통합 (RCiEP) | 420xx — Granite Rapids / Sierra Forest (Xeon 6) | RCiEP | 0x4946 |
EP당 16 VF | Gen4 대비 향상 | qat_4xxx (6.8+) |
| Gen 6 | CPU 다이 통합 (RCiEP) | 6xxx — Clearwater Forest / Diamond Rapids | RCiEP | TBD | TBD | TBD | qat_6xxx (6.16+) |
개별 카드 vs CPU 내장: Gen 1~2의 개별 PCIe 카드(8950/8960/8970)와 칩셋 내장 QAT는 호스트 CPU와 PCIe 버스를 통해 통신하므로 DMA 전송 지연이 존재합니다. 반면 Gen 4 이후 CPU 다이에 통합된 QAT는 RCiEP(Root Complex Integrated Endpoint)로 PCIe 루트 콤플렉스에 직접 연결되어 외부 PCIe 링크를 거치지 않으므로 지연이 크게 줄어듭니다. 다만 개별 카드는 여러 서버에 유연하게 장착할 수 있고, 듀얼 소켓에서 두 CPU가 각각 카드에 접근할 수 있는 장점이 있습니다.
RCiEP 의미: RCiEP는 PCIe 루트 콤플렉스 내부에 통합된 엔드포인트로, lspci에서는 일반 PCIe 디바이스처럼 보이지만 실제로는 CPU 패키지 내부에 위치합니다. 따라서 SR-IOV VF 생성, /proc/crypto 등록 등 기존 PCIe 디바이스와 동일한 소프트웨어 인터페이스를 사용하면서도 하드웨어적으로 CPU에 더 가까운 위치에서 동작합니다.
QAT 폼 팩터 진화
QAT 내부 아키텍처
QAT 하드웨어는 내부적으로 Ring Pair(요청/응답 큐), Accelerator Engine(AE), Slice(실제 연산 유닛)의 3계층으로 구성됩니다. 소프트웨어가 Ring Pair에 디스크립터를 기록하면, AE가 이를 가져와 적절한 Slice(Cipher, Hash, PKE, Compression)에 할당하여 처리합니다. Gen 4 기준으로 CPU당 최대 4개의 QAT 엔드포인트(EP)가 존재하며, 각 EP마다 독립적인 AE 풀과 Ring Pair를 보유합니다.
QAT Crypto 요청 처리 흐름 (소프트웨어 경로)
커널 Crypto API에서 QAT 하드웨어까지의 암호화 요청이 어떻게 전달되고 완료되는지를 소프트웨어 관점에서 추적합니다.
사용자 공간 또는 커널 서브시스템(IPsec, kTLS, dm-crypt)이 crypto_skcipher_encrypt() 같은 Crypto API를 호출하면,
priority 기반으로 QAT 드라이버가 선택되고, Ring Pair를 통해 하드웨어에 요청이 전달됩니다.
커널 소스 분석: QAT 암호화 요청 경로
/* ━━━ 단계 ③: QAT 드라이버 진입 — qat_alg_skcipher_encrypt() ━━━ */
/* drivers/crypto/intel/qat/qat_common/qat_algs.c */
static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
{
struct qat_alg_skcipher_ctx *ctx = crypto_skcipher_ctx(
crypto_skcipher_reqtfm(req));
struct qat_crypto_request *qat_req = skcipher_request_ctx(req);
struct icp_qat_fw_la_bulk_req *msg = &qat_req->req;
/* FW 요청 메시지 구성: opcode + 키 컨텍스트 + IV */
qat_alg_set_req_iv(qat_req);
qat_req->cb = qat_alg_skcipher_encrypt_cb; /* 완료 콜백 등록 */
/* scatterlist → DMA 매핑 (flat buffer 또는 SGL) */
ret = qat_bl_sgl_to_bufl(ctx->inst->accel_dev,
req->src, req->dst,
&qat_req->buf, req->cryptlen);
/* ━━━ 단계 ④: Ring Pair에 메시지 제출 ━━━ */
return qat_alg_send_sym_message(qat_req, ctx->inst, &req->base);
}
/* qat_alg_send_sym_message() → adf_send_message() 내부 */
int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg)
{
/* Ring Full 체크: tail이 head를 따라잡으면 -EAGAIN */
if (adf_ring_nearly_full(ring))
return -EAGAIN;
/* 디스크립터를 Request Ring에 복사 */
memcpy(ring->base_addr + ring->tail, msg, ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
/* tail 포인터 갱신 + MMIO doorbell 쓰기 → FW에 새 요청 알림 */
ring->tail = adf_modulo(ring->tail + ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
ADF_RING_SIZE_MODULO(ring->ring_size));
WRITE_CSR_RING_TAIL(ring->bank->csr_addr, ring->bank->bank_number,
ring->ring_number, ring->tail);
return 0;
}
/* ━━━ 단계 ⑥: 완료 콜백 — 폴링/인터럽트에 의해 호출 ━━━ */
static void qat_alg_skcipher_encrypt_cb(
struct icp_qat_fw_la_resp *resp, struct qat_crypto_request *qat_req)
{
struct skcipher_request *sreq = qat_req->skcipher_req;
/* DMA 버퍼 해제 */
qat_bl_free_bufl(qat_req->buf);
/* FW 응답 상태 확인 */
int err = (ICP_QAT_FW_COMN_STATUS_FLAG_OK ==
ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(resp->comn_hdr.comn_status))
? 0 : -EBADMSG;
/* 호출자에게 결과 반환 */
skcipher_request_complete(sreq, err);
}
코드 설명
-
qat_alg_skcipher_encrypt
Crypto API의
.encrypt콜백으로 등록된 함수입니다.icp_qat_fw_la_bulk_req구조체에 FW가 이해하는 형식으로 요청을 인코딩하고, DMA 매핑 후 Ring에 제출합니다. -
adf_send_message
Request Ring의 tail에 디스크립터를 복사하고 CSR(Control/Status Register)에 tail 포인터를 기록합니다. 이 MMIO 쓰기가 doorbell 역할을 하여 FW에 새 요청이 있음을 알립니다. Ring이 가득 차면
-EAGAIN을 반환하여 상위에서 backlog 처리합니다. -
완료 콜백
FW가 Response Ring에 결과를 기록하면, 폴링 tasklet 또는 MSI-X 인터럽트 핸들러가 이를 감지하여 콜백을 호출합니다. DMA 버퍼를 해제하고, FW 응답 상태를 확인한 뒤
skcipher_request_complete()로 호출자에게 결과를 전달합니다.
세대별 상세 기능 비교
| 항목 | Gen 1 (DH895xCC) | Gen 2 (C62x / 8970) | Gen 4 (4xxx) | Gen 5 (420xx) | Gen 6 (6xxx) |
|---|---|---|---|---|---|
| 출시 연도 | 2013 | 2017 | 2023 (SPR) | 2024 (GNR) | 2025~(CWF/DMR) |
| 폼 팩터 | PCIe 카드 | PCH 내장 + 카드 | CPU 내장 (RCiEP) | CPU 내장 (RCiEP) | CPU 내장 (RCiEP) |
| 대칭키 알고리즘 | AES, 3DES, DES | AES, 3DES | AES, SM4, 3DES | AES, SM4, 3DES | AES, SM4, 3DES |
| 해시 알고리즘 | SHA-1/256/512 | SHA-1/256/512 | SHA-1/256/512, SM3 | SHA-1/256/512, SM3 | SHA-1/256/512, SM3 |
| 비대칭키 알고리즘 | RSA, DH | RSA, DH, ECDSA | RSA, DH, ECDSA, SM2 | RSA, DH, ECDSA, SM2 | RSA, DH, ECDSA, SM2 |
| 압축 | Deflate | Deflate | Deflate, LZ4, LZ4s | Deflate, LZ4, LZ4s | Deflate, LZ4, LZ4s |
| 동시 서비스 | 1 | 1 | 최대 2 (cy+dc) | 최대 2 (cy+dc) | 최대 3 (sym+asym+dc) |
| SR-IOV VF | 32 | 16/PF (최대 48) | 16/PF (최대 64) | 16/PF | TBD |
| 라이브 마이그레이션 | — | — | — | Linux 6.10+ | 지원 예정 |
| Kconfig | QAT_DH895xCC | QAT_C62X, QAT_C3XXX | QAT_4XXX | QAT_4XXX | QAT_6XXX |
| 커널 최소 버전 | 4.x | 4.x | 5.18 | 6.8 | 6.16 |
QAT 커널 드라이버 소스 구조
QAT 드라이버는 drivers/crypto/intel/qat/에 위치하며, 공통 프레임워크(qat_common)와 세대별 드라이버로 분리되어 있습니다:
drivers/crypto/intel/qat/
├── qat_common/ /* 세대 공통 프레임워크 */
│ ├── adf_accel_devices.h /* 가속기 디바이스 추상화 구조체 */
│ ├── adf_transport.c /* Ring Pair 전송 계층 (doorbell, polling) */
│ ├── adf_cfg.c /* sysfs cfg_services 서비스 구성 */
│ ├── adf_sriov.c /* SR-IOV VF 생성·관리 */
│ ├── adf_vf_isr.c /* VF 인터럽트 핸들러 */
│ ├── qat_crypto.c /* Crypto API 등록 (skcipher, aead, ahash) */
│ ├── qat_comp_algs.c /* acomp 압축 알고리즘 등록 */
│ ├── qat_algs.c /* 대칭키 알고리즘 구현 */
│ ├── qat_asym_algs.c /* RSA/DH/ECDSA 비대칭키 구현 */
│ ├── adf_gen4_pm.c /* Gen4 전력 관리 */
│ ├── adf_gen6_pm.c /* Gen6 전력 관리 */
│ └── adf_gen4_vf_mig.c /* Gen4/5 VF 라이브 마이그레이션 */
├── qat_dh895xcc/ /* Gen 1 드라이버 */
│ └── adf_dh895xcc_hw_data.c /* HW 사양 정의 (AE 수, Ring 수 등) */
├── qat_c62x/ /* Gen 2 (C62x) 드라이버 */
│ └── adf_c62x_hw_data.c
├── qat_c3xxx/ /* Gen 2 (C3xxx Atom) 드라이버 */
│ └── adf_c3xxx_hw_data.c
├── qat_4xxx/ /* Gen 4/5 (4xxx, 420xx) 드라이버 */
│ └── adf_4xxx_hw_data.c /* 4xxx + 420xx HW 사양 통합 */
├── qat_6xxx/ /* Gen 6 드라이버 (Linux 6.16+) */
│ └── adf_6xxx_hw_data.c /* Gen4 로직 재활용 + 3서비스 확장 */
└── Kconfig / Makefile
서비스 구성 방법: Gen 4 이후 QAT는 sysfs를 통해 서비스 조합을 런타임에 변경할 수 있습니다. echo "sym;dc" > /sys/bus/pci/devices/<BDF>/qat/cfg_services와 같이 설정하면, 대칭키 암호화와 압축을 동시에 사용할 수 있습니다. Gen 4에서는 sym;asym, sym;dc, asym;dc, dc, sym, asym 중 하나를 선택합니다. Gen 6에서는 sym;asym;dc 3개 서비스를 동시에 활성화할 수 있습니다.
Gen 2 카드(8960/8970)와 Gen 4 내장 병용: 동일 서버에 Gen 2 PCIe 카드와 Gen 4 CPU 내장 QAT를 동시에 사용할 수 있습니다. 커널 Crypto API는 priority가 동일하면(4001) 라운드로빈으로 부하를 분산합니다. NUMA 토폴로지를 고려하여 카드를 CPU에 가까운 PCIe 슬롯에 장착하세요.
QAT 커널 드라이버 설정
# ━━━ 세대별 QAT 디바이스 확인 ━━━
# Gen 1: DH895xCC (개별 PCIe 카드)
lspci -d :0435
# 03:00.0 Co-processor: Intel DH895xCC Series QAT
# Gen 2: C62x (칩셋 내장) / C3xxx (Atom SoC 내장)
lspci -d :37c8 # C62x (Lewisburg PCH)
lspci -d :19e2 # C3xxx (Atom Denverton)
# 3d:00.0 Co-processor: Intel C62x Series QAT
# Gen 4: 4xxx (CPU 다이 통합 — RCiEP)
lspci -d :4940 # PF: 0x4940
lspci -d :4941 # VF: 0x4941
# 6b:00.0 Co-processor: Intel 4xxx Series QAT (RCiEP)
# Gen 5: 420xx (Granite Rapids / Sierra Forest)
lspci -d :4946 # PF: 0x4946
# ━━━ 드라이버 로드 ━━━
modprobe intel_qat # 공통 프레임워크 (모든 세대 공통)
modprobe qat_4xxx # Gen4/5 (SPR/EMR/GNR)
modprobe qat_6xxx # Gen6 (CWF/DMR, Linux 6.16+)
modprobe qat_c62x # Gen2 (C62x 칩셋 / 8960·8970 카드)
modprobe qat_dh895xcc # Gen1 (DH895xCC / 8950 카드)
# ━━━ 서비스 구성 (Gen 4 이후 — sysfs 방식) ━━━
# 현재 서비스 구성 확인
cat /sys/bus/pci/devices/0000:6b:00.0/qat/cfg_services
# sym;dc
# 서비스 변경: 대칭키 + 압축 동시
echo "sym;dc" > /sys/bus/pci/devices/0000:6b:00.0/qat/cfg_services
# Gen4 조합: sym / asym / dc / sym;asym / sym;dc / asym;dc
# Gen6 조합: sym;asym;dc (3서비스 동시 가능)
# ━━━ 등록된 알고리즘 확인 ━━━
grep -E "^driver|^name|^priority" /proc/crypto | grep -B2 qat
# name : cbc(aes)
# driver : qat_aes_cbc
# priority : 4001 ← S/W(aesni=400)보다 높음 → 자동 선택
# ━━━ SR-IOV VF 관리 ━━━
# VF 생성 (Gen4: PF당 최대 16개)
echo 16 > /sys/bus/pci/devices/0000:6b:00.0/sriov_numvfs
# VF 확인
lspci -d :4941 | wc -l
# 16
# 라이브 마이그레이션용 VFIO 바인딩 (Gen5+, Linux 6.10+)
echo 0000:6b:00.1 > /sys/bus/pci/drivers/qat_4xxx/unbind
echo "8086 4947" > /sys/bus/pci/drivers/vfio-pci/new_id
QAT + IPsec 연동
QAT는 IPsec의 ESP(Encapsulating Security Payload) 암호화/복호화를 하드웨어로 오프로드합니다. 커널 xfrm 프레임워크에서 SA(Security Association)를 설정하면, Crypto API를 통해 QAT 드라이버가 자동 선택됩니다. QAT IPsec 오프로드는 crypto 모드(Crypto API 경유)로 동작하며, NIC의 인라인(packet) 오프로드와는 별개입니다.
| 오프로드 방식 | 처리 주체 | xfrm 설정 | 장점 | 제약 |
|---|---|---|---|---|
| S/W (AES-NI) | CPU | 기본 (offload 없음) | 설정 간단, 모든 알고리즘 | CPU 부하 높음 |
| QAT crypto offload | QAT PCIe/RCiEP | 자동 (priority 기반) | CPU 해방, 고처리량 | 소량 패킷 지연, Ring 포화 |
| NIC inline offload | NIC HW (ConnectX, E810) | offload packet dev eth0 |
와이어 속도, 최저 지연 | NIC 지원 알고리즘만 |
# ━━━ QAT crypto offload를 이용한 IPsec 터널 설정 ━━━
# 1. QAT 드라이버 로드 및 암호화 서비스 확인
modprobe intel_qat
modprobe qat_4xxx
grep qat /proc/crypto | head -5
# driver : qat_aes_cbc
# driver : qat_aes_gcm
# priority : 4001
# 2. IPsec SA 추가 (AES-256-GCM — ESP) — QAT가 자동 선택됨
ip xfrm state add \
src 10.0.1.1 dst 10.0.2.1 \
proto esp spi 0x1001 reqid 100 mode tunnel \
aead "rfc4106(gcm(aes))" \
0x$(dd if=/dev/urandom bs=36 count=1 2>/dev/null | xxd -p | tr -d '\n') 128
# 반대 방향 SA
ip xfrm state add \
src 10.0.2.1 dst 10.0.1.1 \
proto esp spi 0x1002 reqid 100 mode tunnel \
aead "rfc4106(gcm(aes))" \
0x$(dd if=/dev/urandom bs=36 count=1 2>/dev/null | xxd -p | tr -d '\n') 128
# 3. xfrm 정책 추가
ip xfrm policy add \
src 192.168.1.0/24 dst 192.168.2.0/24 \
dir out tmpl src 10.0.1.1 dst 10.0.2.1 \
proto esp reqid 100 mode tunnel
ip xfrm policy add \
src 192.168.2.0/24 dst 192.168.1.0/24 \
dir in tmpl src 10.0.2.1 dst 10.0.1.1 \
proto esp reqid 100 mode tunnel
# 4. QAT가 실제로 사용되는지 확인
cat /proc/crypto | grep -A4 "gcm(aes)"
# name : rfc4106(gcm(aes))
# driver : qat_aes_gcm
# module : intel_qat
# priority : 4001 ← AES-NI(300)보다 높음
# 5. 성능 측정
iperf3 -c 10.0.2.1 -t 30 -P 4
# SW (AES-NI): ~12 Gbps (CPU ~95%)
# QAT offload: ~40 Gbps (CPU ~15%)
# 6. SA별 패킷/바이트 카운터 확인
ip -s xfrm state list
# stats: replay-window 0 replay 0 failed 0
# lifetime current: 512342 bytes, 3847 packets
strongSwan/Libreswan 자동 연동: strongSwan과 Libreswan은 커널 xfrm을 통해 SA를 설정하므로, QAT 드라이버가 로드되어 있으면 별도 설정 없이 자동으로 QAT 가속이 적용됩니다. /proc/crypto에서 QAT 드라이버의 priority(4001)가 S/W 구현보다 높기 때문입니다. 특정 SA에서 QAT를 비활성화하려면 echo 0 > /sys/bus/pci/devices/<BDF>/qat/cfg_services로 서비스를 내리거나, modprobe -r qat_4xxx로 드라이버를 언로드합니다.
QAT + kTLS 연동
커널 TLS(kTLS)에서 QAT를 활용하면 TLS 레코드의 대칭키 암호화/복호화를 QAT 하드웨어로 오프로드할 수 있습니다.
kTLS는 SOL_TLS 소켓 옵션으로 활성화되며, 송신(TX) 경로에서 sendfile()/splice()의 제로카피 이점을 최대화합니다.
QAT kTLS 오프로드는 NIC 인라인 kTLS(TLS_HW)와 달리, 커널 Crypto API를 경유하는 소프트웨어 kTLS 경로에서 QAT가 암호화 엔진으로 동작하는 방식입니다.
# ━━━ kTLS + QAT 설정 및 확인 ━━━
# 1. QAT에서 대칭키 서비스 활성화
echo "sym" > /sys/bus/pci/devices/0000:6b:00.0/qat/cfg_services
# 또는 sym;dc (암호화 + 압축 동시)
# 2. QAT AES-GCM AEAD 알고리즘 등록 확인
grep -A3 "gcm(aes)" /proc/crypto | grep -E "driver|priority"
# driver : qat_aes_gcm
# priority : 4001
# 3. kTLS 모듈 로드
modprobe tls
# 4. 애플리케이션에서 kTLS 활성화 (OpenSSL 3.0+ 또는 직접 설정)
# setsockopt(fd, SOL_TCP, TCP_ULP, "tls", 3)
# setsockopt(fd, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info))
# → 이후 write()/sendfile()은 커널 kTLS가 처리
# → Crypto API priority에 의해 QAT가 AES-GCM 수행
# 5. nginx에서 kTLS 활성화 (OpenSSL 3.0 + kTLS 지원 빌드)
# /etc/nginx/nginx.conf:
# ssl_conf_command Options KTLS;
# sendfile on;
# → sendfile()로 파일 → TLS → 소켓 제로카피 전송
# → QAT가 TLS 레코드 암호화 담당
# 6. kTLS 통계 확인
cat /proc/net/tls_stat
# TlsCurrTxSw 128
# TlsCurrRxSw 64
# TlsTxSw 45230
# → TxSw: 소프트웨어 경로 (QAT는 Crypto API 레벨)
kTLS에서 QAT 자동 선택 원리: kTLS의 소프트웨어 TX 경로(tls_sw_sendmsg)는 내부적으로 crypto_aead_encrypt()를 호출합니다. 이때 crypto_alloc_aead("gcm(aes)", ...)가 /proc/crypto에서 가장 높은 priority를 가진 구현을 선택하므로, QAT 드라이버(priority 4001)가 로드되어 있으면 자동으로 QAT 경로가 사용됩니다. 별도의 kTLS-QAT 연동 설정은 필요하지 않습니다.
TLS 1.3 지원: QAT Gen 4 이상은 AES-128-GCM, AES-256-GCM을 지원하므로 TLS 1.2/1.3 모두에서 사용할 수 있습니다. ChaCha20-Poly1305는 QAT에서 지원하지 않으므로, 이 암호 스위트가 선택된 연결에서는 자동으로 CPU(AES-NI 또는 범용 구현)로 fallback됩니다.
QAT 사용 시 주의사항
- 소량 데이터 오버헤드 — 작은 패킷(64B 이하)에서는 QAT 오프로드 지연(~10μs)이 S/W AES-NI(~0.1μs)보다 클 수 있음. 일정 크기 이상에서만 이점
- 큐 깊이 관리 — Ring pair가 포화되면 요청이 거절됨. 비동기 API(crypto_async) 사용 시 완료 콜백(Callback)에서 에러 처리 필수
- NUMA 인지 — QAT 디바이스가 특정 NUMA 노드에 연결. 다른 노드의 CPU가 사용하면 cross-node 메모리 접근으로 지연 증가
- SR-IOV VF 개수 — VF당 할당되는 Ring pair 수가 줄어들어 VM별 처리량 제한. 적절한 VF 수 계획 필요
- 펌웨어 의존성 — QAT 펌웨어 로딩이 필요하며, 커널 빌드 시
CONFIG_CRYPTO_DEV_QAT_4XXX등 활성화 필요 - fallback 메커니즘 — QAT 장애 시 자동으로 S/W 구현(aesni_intel)으로 fallback. priority 기반 선택
- 라이브 마이그레이션 — Linux 6.10부터 QAT Gen4/5 SR-IOV VF의 라이브 마이그레이션을 지원합니다. VF를
qat_vfio_pci.ko에 바인딩하면 VM 이동 시 QAT 가속이 유지됩니다
QAT 에러 처리와 Heartbeat 메커니즘
QAT 하드웨어는 펌웨어(FW) 기반으로 동작하므로, FW 행(hang)이나 AE 오류가 발생할 수 있습니다. 커널 QAT 드라이버는 Heartbeat 메커니즘으로 FW 생존 여부를 주기적으로 확인하고, 장애 감지 시 자동으로 디바이스를 리셋·재초기화하는 복구 경로를 제공합니다.
커널 소스 분석: Heartbeat과 에러 복구
/* ━━━ Heartbeat 타이머 콜백 ━━━ */
/* drivers/crypto/intel/qat/qat_common/adf_heartbeat.c */
static void adf_heartbeat_check_ctrs(struct adf_accel_dev *accel_dev)
{
struct adf_heartbeat *hb = accel_dev->heartbeat;
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
u16 num_aes = hw_data->get_num_aes(hw_data);
/* 각 AE의 FW 카운터를 이전 값과 비교 */
for (ae = 0; ae < num_aes; ae++) {
curr = hb->dma.virt_addr->ae_data[ae].alive_counter;
prev = hb->prev_ctrs[ae];
if (curr == prev) {
/* FW 카운터 미변화 → 해당 AE 응답 없음 */
dev_err(&GET_DEV(accel_dev),
"Heartbeat failure on AE %u (cnt=%u)", ae, curr);
hb->status = HB_DEV_UNRESPONSIVE;
goto fatal;
}
hb->prev_ctrs[ae] = curr;
}
/* 정상 — 타이머 재스케줄 */
return;
fatal:
/* 장애 통지 → 리셋 워크큐 트리거 */
adf_notify_fatal_error(accel_dev);
}
/* ━━━ 디바이스 리셋 및 재초기화 ━━━ */
/* drivers/crypto/intel/qat/qat_common/adf_aer.c */
static void adf_device_reset_worker(struct work_struct *work)
{
struct adf_accel_dev *accel_dev = ...;
/* 1. 서비스 중단: Crypto API에서 알고리즘 등록 해제 */
adf_dev_stop(accel_dev);
/* 2. Ring Pair 정리, VF에 리셋 통지 (PF→VF 메시지) */
adf_dev_shutdown(accel_dev);
/* 3. FW 재로드, Ring 재구성 */
adf_dev_init(accel_dev);
/* 4. 서비스 재개: Crypto API에 알고리즘 재등록 */
adf_dev_start(accel_dev);
/* 5. Heartbeat 타이머 재시작 */
adf_heartbeat_restart(accel_dev);
}
코드 설명
-
adf_heartbeat_check_ctrs
QAT FW는 각 AE(Accelerator Engine)에서 내부 카운터를 주기적으로 증가시킵니다. 드라이버는 타이머 콜백에서 이 카운터의 변화를 확인하여 FW 생존 여부를 판단합니다. 모든 AE의 카운터가 정상이면 타이머를 재설정하고, 하나라도 미변화하면
adf_notify_fatal_error()를 호출하여 리셋 경로를 시작합니다. -
adf_device_reset_worker
워크큐에서 실행되는 리셋 워커입니다.
adf_dev_stop()은 진행 중인 요청에-EIO를 반환하고 Crypto API 등록을 해제합니다.adf_dev_shutdown()은 Ring Pair를 정리하고 SR-IOV VF에 리셋 사실을 통지합니다. 이후adf_dev_init()과adf_dev_start()로 FW를 다시 로드하고 서비스를 재개합니다. 전체 복구 시간은 일반적으로 수 초 이내입니다.
Heartbeat 실패 시 진행 중 요청 처리: 리셋이 시작되면 Ring Pair에 남아 있는 미완료 요청은 모두 -EIO 에러로 완료 콜백이 호출됩니다. IPsec, kTLS 등 상위 서브시스템은 이 에러를 받으면 Crypto API의 priority 기반 fallback에 의해 소프트웨어 구현(AES-NI)으로 자동 전환됩니다. QAT 디바이스 복구가 완료되면 다시 priority 4001로 새 요청이 QAT로 라우팅됩니다.
Heartbeat 타이머 주기: 기본값은 500ms이며, /sys/bus/pci/devices/<BDF>/qat/heartbeat_timer에서 조정할 수 있습니다. 너무 짧으면 오탐(false positive)이 증가하고, 너무 길면 장애 감지가 지연됩니다.
QAT 텔레메트리와 모니터링
QAT 디바이스의 운영 상태를 모니터링하려면 sysfs, debugfs, /proc/crypto 인터페이스를 활용합니다.
프로덕션 환경에서는 이러한 메트릭을 주기적으로 수집하여 QAT 장애 조기 감지, 용량 계획, 성능 최적화에 활용합니다.
# ━━━ sysfs: QAT 디바이스 상태 및 구성 ━━━
QAT_DEV="0000:6b:00.0"
# 디바이스 상태 (up/down)
cat /sys/bus/pci/devices/$QAT_DEV/qat/state
# up
# 현재 서비스 구성
cat /sys/bus/pci/devices/$QAT_DEV/qat/cfg_services
# sym;dc
# 구성 가능한 DC(압축) 레벨
cat /sys/bus/pci/devices/$QAT_DEV/qat/dc_level_avail
# 1 6 9
# NUMA 노드 확인 (NUMA-aware 배치에 필수)
cat /sys/bus/pci/devices/$QAT_DEV/numa_node
# 0
# SR-IOV VF 현재 수
cat /sys/bus/pci/devices/$QAT_DEV/sriov_numvfs
# 16
# ━━━ sysfs: Heartbeat 상태 ━━━
# Heartbeat 현재 상태 확인
cat /sys/bus/pci/devices/$QAT_DEV/qat/heartbeat
# 0 (0=정상, 비0=장애 발생 횟수)
# Heartbeat 타이머 주기 (ms)
cat /sys/bus/pci/devices/$QAT_DEV/qat/heartbeat_timer
# 500
# Heartbeat 누적 실패 횟수
cat /sys/bus/pci/devices/$QAT_DEV/qat/heartbeat_failed
# 0
# ━━━ sysfs: FW 카운터 (처리량 메트릭) ━━━
cat /sys/bus/pci/devices/$QAT_DEV/qat/fw_counters
# 세대에 따라 출력 형식 상이
# AE 0: req 1523847, resp 1523847
# AE 1: req 1498231, resp 1498231
# → req == resp이면 모든 요청이 정상 완료됨
# CNV(Copy-No-Verify) 에러 카운터 (압축 관련)
cat /sys/bus/pci/devices/$QAT_DEV/qat/cnv_errors
# 0
# ━━━ debugfs: 상세 디버깅 정보 (Gen 4+) ━━━
# debugfs 마운트 확인
mount | grep debugfs
# debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec)
# QAT 디버그 디렉터리 구조
ls /sys/kernel/debug/qat_${QAT_DEV}/
# fw_counters heartbeat transport dev_cfg pm_status
# Ring Pair 사용량 (전송 계층 통계)
cat /sys/kernel/debug/qat_${QAT_DEV}/transport
# bank 0: ring 0 - tx 152384, rx 152384, empty 0, full 12
# bank 0: ring 1 - tx 89421, rx 89421, empty 0, full 3
# → full 카운터가 지속 증가하면 Ring 포화 (용량 초과 징후)
# 전력 관리 상태
cat /sys/kernel/debug/qat_${QAT_DEV}/pm_status
# power: on, throttle: none, fw_irq: 0
# ━━━ /proc/crypto: 등록된 QAT 알고리즘 확인 ━━━
grep -B1 -A5 "driver.*qat" /proc/crypto
# name : cbc(aes)
# driver : qat_aes_cbc
# module : intel_qat
# priority : 4001
# refcnt : 12 ← 현재 12개 tfm이 이 알고리즘을 사용 중
| 모니터링 항목 | 경로 / 명령 | 정상 값 | 경고 조건 |
|---|---|---|---|
| 디바이스 상태 | qat/state |
up |
down → 즉시 조치 |
| Heartbeat | qat/heartbeat |
0 |
비0 → FW 장애 발생 이력 |
| FW req/resp 균형 | qat/fw_counters |
req ≈ resp | req >> resp → 요청 누적 (AE 행) |
| Ring Full 횟수 | debugfs transport |
full = 0 | full 증가 → Ring 포화, VF 추가 또는 EP 분리 필요 |
| CNV 에러 | qat/cnv_errors |
0 |
비0 → 압축 검증 실패 (데이터 무결성 확인) |
| NUMA 배치 | numa_node |
워크로드와 동일 노드 | cross-node → 지연 증가 |
운영 모니터링 체크리스트:
- Prometheus/Grafana 연동:
qat/fw_counters와debugfs transport를 node_exporter textfile collector로 주기적 수집 - Ring Full 경보: full 카운터의 증가율이 임계값을 초과하면 알람. QAT EP 추가 또는 서비스 분리로 대응
- Heartbeat 감시:
qat/heartbeat_failed> 0이면 PagerDuty/Slack 알림. 자동 복구 후에도 원인 분석 필요 - NUMA 검증: 신규 서버 프로비저닝 시
numactl --hardware와 QATnuma_node를 비교하여 워크로드 배치 확인
QAT 압축 가속 (crypto_comp / acomp)
Intel QAT는 암호화뿐 아니라 deflate, lz4 등의 데이터 압축/해제도 하드웨어로 가속합니다. 커널 Crypto API의 압축 인터페이스를 통해 zswap, 파일 시스템 압축, 네트워크 패킷 압축 등에서 CPU 부하를 대폭 줄일 수 있습니다.
crypto_comp vs crypto_acomp — 동기 vs 비동기 압축 API
커널은 두 가지 압축 API를 제공합니다.
crypto_comp는 동기(Synchronous) 인터페이스로, 호출 즉시 결과를 반환하며 주로 소프트웨어 구현에서 사용됩니다.
crypto_acomp는 비동기(Asynchronous) 인터페이스로, 하드웨어 가속기가 DMA를 통해 처리하고 완료 콜백으로 결과를 알려주는 방식입니다.
QAT 압축 드라이버(qat_comp)는 비동기 acomp 인터페이스로 등록됩니다.
acomp API 사용 패턴
비동기 압축 API(crypto_acomp)는 scatterlist 기반 입출력을 지원하며,
QAT 하드웨어가 존재하면 자동으로 HW 가속 경로가 선택됩니다.
커널 소스 분석: crypto_acomp_compress() 흐름
/* 비동기 압축 API 사용 예시 */
struct crypto_acomp *acomp;
struct acomp_req *req;
struct crypto_wait wait;
/* 1. acomp tfm 할당 — QAT가 있으면 priority에 의해 HW 드라이버 선택 */
acomp = crypto_alloc_acomp("deflate", 0, 0);
if (IS_ERR(acomp))
return PTR_ERR(acomp);
/* 2. request 할당 */
req = acomp_request_alloc(acomp);
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
crypto_req_done, &wait);
/* 3. 입출력 파라미터 설정 (src, dst, src_len, dst_len) */
acomp_request_set_params(req, &src_sg, &dst_sg, slen, dlen);
/* 4. 압축 실행 — HW에서 DMA로 처리, 완료 시 콜백 호출 */
err = crypto_wait_req(crypto_acomp_compress(req), &wait);
/* 5. 결과: req->dlen에 압축된 크기가 저장됨 */
compressed_size = req->dlen;
/* 6. 정리 */
acomp_request_free(req);
crypto_free_acomp(acomp);
코드 설명
-
핵심
crypto_alloc_acomp("deflate", 0, 0)은/proc/crypto에서 가장 높은 priority를 가진 deflate 구현을 선택합니다. QAT 드라이버(qat_comp)가 로드되어 있으면 priority 4001로 소프트웨어 구현(priority 0)보다 우선됩니다. -
핵심
acomp_request_set_params()는 scatterlist 기반으로 입출력 버퍼를 설정합니다. QAT HW는 DMA를 사용하므로 별도의 CPU 복사 없이 메모리에서 직접 읽고 씁니다. -
핵심
crypto_acomp_compress()는-EINPROGRESS를 반환할 수 있으며, 이 경우crypto_wait_req()가 completion을 대기합니다. HW 큐가 포화되어-ENOSPC가 반환되면 backlog 큐에 넣은 뒤-EBUSY로 재시도를 알립니다.
Btrfs/ZFS 압축과 QAT 연동
파일 시스템의 투명 압축(Transparent Compression) 기능과 QAT의 연동 상태는 다음과 같습니다.
| 파일 시스템 | 압축 알고리즘 | QAT 연동 가능 여부 | 비고 |
|---|---|---|---|
| Btrfs | zstd, lzo, zlib | 불가 (직접 연동 없음) | Btrfs는 자체 압축 경로를 사용하며 Crypto API의 acomp를 경유하지 않음. workspace 기반 동기 압축만 지원 |
| ZFS (OpenZFS) | gzip, lz4, zstd | 가능 (qat_compress 모듈) | OpenZFS의 qat_compress / qat_checksum 모듈이 gzip, lz4 HW 가속을 제공. zfs set compression=gzip 시 QAT 자동 사용 |
| zswap | deflate, lz4, lzo, zstd | 가능 (acomp 경로) | 커널 6.x+에서 zswap이 acomp 인터페이스를 사용하므로 QAT deflate/lz4 자동 가속 |
NAS 백업 파이프라인에서 QAT 압축 활용
NAS 백업 시스템에서 QAT 압축을 활용하면 CPU를 거의 사용하지 않고 대용량 데이터를 실시간 압축할 수 있습니다.
특히 ZFS 기반 NAS에서는 qat_compress 모듈을 통해 투명하게 HW 압축이 적용됩니다.
또한 사용자 공간에서 qatzip 라이브러리를 통해 tar 아카이브 생성 시 QAT 가속을 적용할 수도 있습니다.
# ━━━ QATzip을 사용한 NAS 백업 압축 (사용자 공간) ━━━
# QAT 장치 및 서비스 확인
adf_ctl status
# qat_dev0 - type: 4xxx, state: up
# Compression Instances: 16
# QATzip으로 백업 아카이브 생성 (gzip 호환)
qzip -k /backup/data.tar -o /backup/data.tar.gz
# → QAT HW에서 압축 처리, CPU 사용률 < 5%
# tar + qzip 파이프라인
tar cf - /data | qzip -o /backup/data.tar.gz
# → 10 GB 데이터를 ~2초에 압축 (QAT C62x 기준)
# 커널 공간: zswap에서 QAT 자동 사용
echo deflate > /sys/module/zswap/parameters/compressor
echo 1 > /sys/module/zswap/parameters/enabled
# → acomp priority에 의해 QAT deflate 자동 선택
QAT 인스턴스 분리 설정: 대규모 NAS 환경에서는 QAT 인스턴스를 압축 전용(dc)과 암호화 전용(cy)으로 분리 설정하여 워크로드 간섭을 방지합니다. /etc/4xxx_dev0.conf에서 ServicesEnabled = dc;cy로 혼합 모드를 설정하거나 ServicesEnabled = dc로 압축 전용 모드를 사용할 수 있습니다.
QAT 압축 성능 비교
| 방식 | 처리량 (MB/s) | CPU 사용률 | 지연시간 |
|---|---|---|---|
| SW deflate (single core) | ~200 | 100% | ~5ms |
| QAT deflate (C62x) | ~10,000 | <5% | ~1ms |
| SW lz4 | ~800 | 100% | ~1ms |
| QAT lz4 | ~20,000 | <5% | ~0.5ms |
ServicesEnabled = dc로 압축 전용 모드로 설정하면 모든 AE를 압축에 할당하여 최대 처리량을 확보할 수 있습니다.
암호화 가속기 디바이스
CPU 내장 명령어(AES-NI, ARM CE) 외에도 PCI 가속기, SoC 임베디드 엔진, 가상 디바이스 등 다양한 형태의 암호화 가속기가 커널 Crypto API에 등록됩니다. 이들은 CPU와 독립적으로 동작하므로 대량의 암호 연산을 CPU 부하 없이 처리할 수 있습니다.
암호화 가속기 종합 비교
아래 테이블은 커널에서 지원하는 주요 암호화 가속기의 폼 팩터(인터페이스)와 출시 상태를 종합 비교합니다. 폼 팩터는 가속기가 시스템에 연결되는 물리적 방식을, 출시 상태는 제품 가용성을 나타냅니다.
| 가속기 | 벤더 | 폼 팩터 | 인터페이스 | 출시 상태 (2025. 3 기준) | Crypto Priority | 주요 용도 |
|---|---|---|---|---|---|---|
| Intel QAT Gen 1 (DH895xCC / 8950) |
Intel | 개별 PCIe 카드 | PCIe 2.0 ×8 | 단종 (EOL) | 4001 | IPsec, VPN |
| Intel QAT Gen 2 (C62x / 8960 / 8970) |
Intel | 칩셋 내장 + 개별 카드 | PCIe 3.0 | 카드 단종, 칩셋 출시 중 | 4001 | IPsec, TLS, 압축 |
| Intel QAT Gen 4 (4xxx) |
Intel | CPU 다이 통합 (RCiEP) | RCiEP (내부) | 출시 중 | 4001 | IPsec, kTLS, zswap |
| Intel QAT Gen 5 (420xx) |
Intel | CPU 다이 통합 (RCiEP) | RCiEP (내부) | 출시 중 | 4001 | Gen4 + 라이브 마이그레이션 |
| Intel QAT Gen 6 (6xxx) |
Intel | CPU 다이 통합 (RCiEP) | RCiEP (내부) | 출시 예정 | 4001 | 3서비스 동시 |
| AMD CCP / PSP | AMD | CPU 다이 내장 코프로세서 | MMIO (내부) | 출시 중 (EPYC 전 세대) | ~200 | SEV/SEV-SNP, 배치 처리 |
| HiSilicon SEC2 | HiSilicon | SoC 내장 (Kunpeng 920/930) | AMBA/SoC 내부 | 출시 중 (중국 내 유통) | ~2001 | ARM 서버 암호화 |
| Marvell NITROX III (CNN35XX) |
Marvell | 개별 PCIe 카드 / SoC | PCIe 2.0/3.0 | 출시 중 | — (DPDK) | SSL/TLS 오프로드, VPN |
| Marvell NITROX V (CNN55XX) |
Marvell | 개별 PCIe 카드 | PCIe 3.0 ×8 | 출시 중 | — (커널 4.13+) | 고성능 암호화/압축 |
| Marvell LiquidSecurity 2 | Marvell | 개별 PCIe HSM 카드 | PCIe | 출시 중 (FIPS 140-3 L3) | — (PKCS#11) | 클라우드 HSM, 키 관리 |
| Marvell CPT v1 (OCTEON TX CN83xx) |
Marvell | SoC 내장 | AMBA/SoC 내부 | 단종 (레거시) | 4001 | 네트워크 장비 |
| Marvell CPT v2 (OCTEON TX2 CN96/98) |
Marvell | SoC 내장 | AMBA/SoC 내부 | 출시 중 | 4001 | 캐리어 라우터, NGFW |
| Marvell CPT v3 (OCTEON 10 CN10K) |
Marvell | SoC 내장 (DPU) | AMBA/SoC 내부 | 출시 중 | 4001 | DPU, 5G UPF |
| Marvell CN20K | Marvell | SoC 내장 (DPU) | AMBA/SoC 내부 | 개발 중 | TBD | 차세대 DPU |
| NXP CAAM (i.MX6~8, LS1/2) |
NXP | SoC 내장 (MMIO) | AXI/SoC 내부 | 출시 중 (장기 공급 ~2035) | 3000~3100 | 임베디드, 라우터 |
| NXP ELE (i.MX95) |
NXP | SoC 내장 보안 엔클레이브 | 메시지 기반 (내부) | 출시 중 | — | 자동차, 산업 IoT |
| Samsung S5P SSS (Exynos 4210~5420) |
Samsung | SoC 내장 | AMBA/SoC 내부 | 단종 (레거시) | 300 | Android dm-crypt |
| Samsung FMP (Exynos 850~2400) |
Samsung | UFS 인라인 엔진 | UFS HCI 내부 | 출시 중 | — (blk-crypto) | fscrypt FBE |
| virtio-crypto | OASIS | 가상 PCI 디바이스 | virtio (준가상화) | 사양 확정 | — | VM 암호화 오프로드 |
AMD CCP / PSP
AMD CCP(Cryptographic Co-Processor)는 AMD EPYC/Ryzen 프로세서의 CPU 다이에 내장된 보안 전용 코프로세서입니다. PCIe 디바이스로 노출되지만 실제로는 CPU 패키지 내부에 위치하며, MMIO를 통해 접근합니다. PSP(Platform Security Processor)는 CCP를 포함하는 상위 개념으로, SEV/SEV-ES/SEV-SNP 기밀 컴퓨팅(Confidential Computing)의 기반이 됩니다. CCP/PSP는 EPYC 1세대(Naples, Zen 1, 2017)부터 현재 5세대(Turin, Zen 5, 2024)까지 전 세대에 포함되어 있습니다.
| EPYC 세대 | 코드명 | Zen 세대 | 출시 | SEV 지원 | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|---|
| 1세대 (7001) | Naples | Zen 1 | 2017. 6 | SEV | 단종 |
| 2세대 (7002) | Rome | Zen 2 | 2019. 8 | SEV, SEV-ES | 출시 중 |
| 3세대 (7003) | Milan | Zen 3 | 2021. 3 | SEV, SEV-ES, SEV-SNP | 출시 중 |
| 4세대 (9004) | Genoa | Zen 4 | 2022. 11 | SEV, SEV-ES, SEV-SNP v2 | 출시 중 |
| 5세대 (9005) | Turin | Zen 5 | 2024. 10 | SEV, SEV-ES, SEV-SNP v2+ | 출시 중 |
SEV-SNP 호스트/게스트 지원은 Linux 6.x 메인라인에 완전 업스트림되어 프로덕션 환경에서 사용할 수 있습니다:
# ━━━ AMD CCP 드라이버 설정 ━━━
# Kconfig 옵션
# CONFIG_CRYPTO_DEV_CCP=m
# CONFIG_CRYPTO_DEV_CCP_CRYPTO=m ← Crypto API 연동
# CONFIG_CRYPTO_DEV_SP_PSP=y ← PSP/SEV 지원
# CCP 디바이스 확인
lspci | grep -i ccp
# 09:00.2 Encryption controller: AMD CCP/PSP
# 드라이버 로드 확인
dmesg | grep ccp
# ccp 0000:09:00.2: enabling device
# ccp 0000:09:00.2: ccp enabled
# ccp 0000:09:00.2: SEV API:1.55 build:21
# CCP가 등록한 Crypto API 알고리즘
grep ccp /proc/crypto | head -5
# driver : ccp-aes-cbc
# driver : ccp-aes-gcm
# driver : ccp-sha256
CCP vs AES-NI: CCP는 전용 코프로세서로 CPU 코어와 병렬 동작하지만, 통신 오버헤드(MMIO, DMA)가 있어 소량 데이터에서는 AES-NI보다 느릴 수 있습니다. CCP의 주요 가치는 (1) SEV/SEV-SNP 메모리 암호화, (2) 대량 배치 처리, (3) CPU 부하 분산(Load Balancing)에 있습니다. CCP의 crypto priority는 AES-NI보다 낮게 설정(~200)되어, 일반 용도에서는 AES-NI가 우선 선택됩니다. CCP가 지원하는 알고리즘은 AES(CBC/GCM/XTS), SHA(1/224/256/384/512), SHA3, AES-CMAC, 3DES 등이며, SM4나 포스트 양자 암호 알고리즘은 아직 지원하지 않습니다.
CCP 내부 아키텍처
CCP는 내부에 5개의 독립 명령 큐(Command Queue)를 보유하며, 각 큐가 별도의 DMA 채널과 인터럽트를 갖고 있어 멀티코어 환경에서 lock-free 병렬 처리가 가능합니다. 큐에 제출된 명령은 CCP 내부의 LSB(Local Storage Block)라는 전용 SRAM에 중간 결과를 저장하면서 처리됩니다.
CCP 커널 드라이버 내부 구조
CCP 드라이버는 drivers/crypto/ccp/에 위치하며, 크게 CCP 코어 드라이버(하드웨어 제어)와 CCP 암호 드라이버(Crypto API 연동) 두 계층으로 분리됩니다:
drivers/crypto/ccp/
├── ccp-dev.c /* CCP 디바이스 초기화·관리 */
├── ccp-dev-v5.c /* CCP v5 (Zen 이후) 하드웨어 제어 */
├── ccp-dev-v3.c /* CCP v3 (레거시) 하드웨어 제어 */
├── ccp-ops.c /* 암호 연산 오퍼레이션 (AES/SHA/RSA) */
├── ccp-dmaengine.c /* DMA 엔진 연동 */
├── ccp-crypto-aes.c /* Crypto API: AES skcipher 등록 */
├── ccp-crypto-aes-xts.c/* Crypto API: AES-XTS 등록 */
├── ccp-crypto-aes-gcm.c/* Crypto API: AES-GCM AEAD 등록 */
├── ccp-crypto-sha.c /* Crypto API: SHA shash 등록 */
├── ccp-crypto-des3.c /* Crypto API: 3DES 등록 */
├── ccp-crypto-rsa.c /* Crypto API: RSA akcipher 등록 */
├── sp-dev.c /* Security Processor(PSP) 공통 */
├── sp-pci.c /* PSP PCI 프로브/제거 */
├── sp-platform.c /* PSP 플랫폼 디바이스 (임베디드용) */
├── sev-dev.c /* SEV/SEV-ES/SEV-SNP 관리 */
├── psp-dev.c /* PSP 디바이스 관리 */
└── Kconfig / Makefile
/* drivers/crypto/ccp/ccp-ops.c — CCP 명령 제출 패턴 (간략화) */
/* CCP v5 명령 디스크립터 구조 (64바이트) */
struct ccp5_desc {
__le32 dw0; /* 엔진 선택(AES/SHA/RSA), 모드, 방향 */
__le32 length; /* 처리할 데이터 크기 */
__le32 src_lo; /* 소스 DMA 주소 (하위) */
__le32 src_hi;
__le32 dst_lo; /* 대상 DMA 주소 (하위) */
__le32 dst_hi;
__le32 key_lo; /* 키 LSB 슬롯 또는 DMA 주소 */
__le32 key_hi;
/* ... IV, context 등 추가 필드 ... */
};
/* 명령 큐에 디스크립터 제출 */
static int ccp5_do_cmd(struct ccp5_desc *desc,
struct ccp_cmd_queue *cmd_q)
{
/* 1. 디스크립터를 큐의 MMIO 링에 기록 */
memcpy_toio(cmd_q->reg_base + CMD5_Q_DESC_OFFSET,
desc, sizeof(*desc));
/* 2. 테일 포인터 갱신 → CCP가 새 명령 인식 */
iowrite32(cmd_q->qidx, cmd_q->reg_base + CMD5_Q_TAIL_OFFSET);
/* 3. 완료 대기 (인터럽트 또는 폴링) */
wait_for_completion_interruptible(&cmd_q->completion);
return cmd_q->cmd_error;
}
/* Crypto API 연동: AES-CBC 암호화 */
static int ccp_aes_cbc_encrypt(struct skcipher_request *req)
{
struct ccp_ctx *ctx = crypto_skcipher_ctx(
crypto_skcipher_reqtfm(req));
struct ccp_cmd cmd = {};
cmd.engine = CCP_ENGINE_AES;
cmd.u.aes.type = CCP_AES_TYPE_128; /* 또는 256 */
cmd.u.aes.mode = CCP_AES_MODE_CBC;
cmd.u.aes.action = CCP_AES_ACTION_ENCRYPT;
cmd.u.aes.key = &ctx->u.aes.key_sg;
cmd.u.aes.iv = &ctx->u.aes.iv_sg;
cmd.u.aes.src = req->src;
cmd.u.aes.dst = req->dst;
cmd.u.aes.src_len = req->cryptlen;
/* CCP 큐에 비동기 제출 → 완료 시 콜백 */
return ccp_crypto_enqueue_request(&req->base, &cmd);
}
코드 설명
CCP v5 드라이버의 명령 제출 과정을 보여줍니다.
- ccp5_desc 구조체64바이트 하드웨어 디스크립터로, 엔진 유형(AES/SHA/RSA), 모드(CBC/GCM/XTS), 소스/대상 DMA 주소, 키/IV 위치를 포함합니다. LSB(Local Storage Block) 슬롯 번호로 키를 지정하면 호스트 메모리를 거치지 않고 CCP 내부 SRAM에서 키를 읽습니다.
- memcpy_toio + iowrite32디스크립터를 MMIO 영역에 기록한 뒤 테일 포인터를 갱신하면 CCP가 새 명령을 인식합니다. 각 명령 큐는 독립적이므로 서로 다른 CPU 코어가 다른 큐에 동시 제출할 수 있습니다.
- ccp_aes_cbc_encryptCrypto API의
skcipher_request를 CCP 내부 명령 형식(ccp_cmd)으로 변환하여 큐에 비동기 제출합니다.-EINPROGRESS반환 후 완료 시 콜백이 호출됩니다.
SEV/SEV-SNP 메모리 암호화 연동
CCP/PSP의 가장 중요한 역할은 SEV(Secure Encrypted Virtualization) 메모리 암호화입니다. SEV가 활성화되면 CCP 내부의 전용 AES 엔진이 VM 메모리를 실시간으로 암복호화하며, 각 VM마다 고유한 암호화 키(VEK, VM Encryption Key)를 사용합니다:
# ━━━ SEV/SEV-SNP 활성화 확인 ━━━
# SEV 지원 여부 확인
dmesg | grep -i sev
# ccp 0000:09:00.2: SEV firmware update successful
# ccp 0000:09:00.2: SEV API:1.55 build:21
# SEV supported: 509 ASIDs
# SEV-ES supported: 509 ASIDs
# SEV-SNP supported: 509 ASIDs
# SEV 상태 확인 (sysfs)
cat /sys/module/kvm_amd/parameters/sev
# Y
cat /sys/module/kvm_amd/parameters/sev_snp
# Y
# SEV VM 실행 (QEMU 예시)
qemu-system-x86_64 \
-machine q35,confidential-guest-support=sev0 \
-object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 \
-cpu EPYC-v4 \
# ... 나머지 옵션 ...
# 게스트 내에서 SEV 활성화 확인
dmesg | grep -i "memory encryption"
# AMD Memory Encryption Features active: SEV SEV-ES SEV-SNP
CCP 활용 요약: (1) Crypto API 경로 — ccp-crypto 모듈이 AES/SHA/RSA를 등록하며, priority ~200으로 AES-NI(400)보다 낮아 일반적으로 자동 선택되지 않습니다. dm-crypt나 IPsec에서 명시적으로 ccp-aes-* 드라이버를 선택하면 CPU 코어를 해방할 수 있습니다. (2) SEV 경로 — KVM이 PSP 명령(CQ4)을 통해 VM별 VEK를 설정하면, CCP의 메모리 암호화 엔진이 메모리 접근 시 자동으로 암복호화합니다. 이 경로는 Crypto API를 거치지 않으며 하드웨어가 투명하게 처리합니다.
HiSilicon SEC / SEC2
HiSilicon SEC2는 Kunpeng 920/930(ARM 서버 SoC)에 SoC 내장된 고속 암호화 가속기입니다. hisi_sec2 드라이버를 통해 Crypto API에 등록되며, UACCE(Unified/User-space Accelerator Framework)를 통해 사용자 공간에서도 직접 접근할 수 있습니다. Kunpeng 930(HiP10)에서는 레지스터 구성 변경과 함께 HPRE(High Performance RSA Engine)에 ECDH/CURVE25519 지원이 추가되었습니다. Kunpeng 프로세서는 TSMC 7nm 공정으로 제조되었으나, 미국 수출 제재로 인해 중국 내 유통이 주를 이루며, 글로벌 가용성은 제한적입니다:
| 특성 | SEC2 사양 |
|---|---|
| 알고리즘 | AES/SM4 (ECB/CBC/XTS), 3DES, SHA-256/512, SM3, AEAD |
| 처리량 | 최대 100 Gbps (AES-256-XTS) |
| 큐 | 최대 256개 하드웨어 큐 |
| Kconfig | CONFIG_CRYPTO_DEV_HISI_SEC2 |
| UACCE | /dev/hisi_sec2-* 디바이스 노드 (UADK 유저스페이스 프레임워크) |
| 관련 가속기 | HPRE (CONFIG_CRYPTO_DEV_HISI_HPRE, RSA/ECC/DH), ZIP (CONFIG_CRYPTO_DEV_HISI_ZIP, 압축) |
SEC2 내부 아키텍처
SEC2는 내부에 다수의 하드웨어 큐 쌍(SQ/CQ)과 암호 코어를 포함하며, 각 큐는 독립적으로 동작합니다. 커널 드라이버는 Crypto API를 통해 요청을 수신하고, BD(Buffer Descriptor)를 하드웨어 큐에 제출하여 비동기로 처리합니다.
# ━━━ HiSilicon SEC2 드라이버 설정 ━━━
# Kconfig 옵션
# CONFIG_CRYPTO_DEV_HISI_SEC2=m
# CONFIG_UACCE=m ← UACCE 프레임워크
# SEC2 디바이스 확인
lspci | grep -i sec
# 76:00.0 Network and computing encryption device: Huawei SEC2
# 등록된 알고리즘 확인
grep hisi /proc/crypto | head -10
# driver : hisi_sec2-aes-cbc
# driver : hisi_sec2-aes-xts
# driver : hisi_sec2-aes-gcm
# driver : hisi_sec2-sm4-xts
# UACCE 디바이스 확인 (유저스페이스 접근)
ls /dev/hisi_sec2-*
# /dev/hisi_sec2-0 /dev/hisi_sec2-1
# SR-IOV VF 생성 (VM별 격리)
echo 4 > /sys/bus/pci/devices/0000:76:00.0/sriov_numvfs
/* SEC2 BD(Buffer Descriptor) 제출 흐름 (간략화) */
/* drivers/crypto/hisilicon/sec2/sec_crypto.c */
static int sec_skcipher_bd_fill(struct sec_ctx *ctx,
struct sec_req *req)
{
struct sec_sqe *sqe = &req->sec_sqe;
/* 1. BD 타입 설정 (skcipher / AEAD / digest) */
sqe->type = BD_TYPE2;
sqe->scene = SEC_COMM_SCENE; /* 일반 암호 */
/* 2. 알고리즘/모드 설정 */
sqe->c_alg = SEC_CALG_AES; /* AES 또는 SM4 */
sqe->c_mode = SEC_CMODE_XTS; /* XTS/CBC/GCM */
sqe->c_key_len = SEC_CKEY_256BIT;
/* 3. DMA 주소 설정 (소스/대상/키/IV) */
sqe->data_src_addr = cpu_to_le64(req->in_dma);
sqe->data_dst_addr = cpu_to_le64(req->out_dma);
sqe->c_key_addr = cpu_to_le64(ctx->key_dma);
sqe->ipsec_scene.c_ivin_addr = cpu_to_le64(req->iv_dma);
/* 4. SQ(Submission Queue)에 BD 제출 */
return hisi_qm_send(ctx->qm, sqe, 1, ctx->qp_idx);
}
UACCE/UADK 유저스페이스 가속: UACCE(Unified/User-space Accelerator Framework)는 HiSilicon 가속기를 유저스페이스에서 커널 우회로 직접 접근하는 프레임워크입니다. /dev/hisi_sec2-* 디바이스를 mmap()하여 하드웨어 큐에 직접 BD를 제출하면 시스템 콜 오버헤드가 제거됩니다. UADK(User-space Accelerator Development Kit) 라이브러리가 이를 추상화하며, OpenSSL 3.x의 uadk_provider를 통해 투명하게 가속할 수 있습니다.
Marvell / Cavium OcteonTX CPT
CPT(Crypto Processing Thread)는 Marvell(구 Cavium) OCTEON TX2 및 CN10K 시리즈 네트워크 SoC에 내장된 암호화 가속 유닛입니다. 데이터센터·캐리어 등급 네트워크 장비를 위해 설계되었으며, 룩어사이드 오프로드와 인라인 오프로드를 모두 지원합니다. IPsec ESP, TLS/DTLS, MACsec 등 프로토콜별 오프로드를 하드웨어 수준에서 지원하며, CPT의 핵심 특징은 SoC 내부의 SSO(Schedule/Synchronize/Order) 이벤트 스케줄러와 직접 연동되어, 암호화 완료 시 CPU 개입 없이 다음 처리 단계로 패킷이 자동 전달되는 것입니다. 최대 100 Gbps 대칭키 처리량을 제공하며, cpt(OcteonTX1) 및 otx2_cpt/cnxk_cpt(OcteonTX2/CN10K) 드라이버를 통해 커널 Crypto API에 등록됩니다.
SoC별 CPT 사양
| SoC 시리즈 | CPT 세대 | 엔진 (AE/SE/IE) | VF 지원 | 대칭키 처리량 | 비대칭키 | 주요 용도 | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|---|---|---|
| OCTEON TX (CN83xx) | CPT v1 | SE×16 | 최대 16 VF | ~25 Gbps | RSA-2048 10K | 엔터프라이즈 라우터 | 단종 |
| OCTEON TX2 (CN96xx) | CPT v2 | AE×4, SE×30, IE×4 | 최대 128 VF | ~100 Gbps | RSA-2048 50K | 캐리어 라우터, NGFW | 출시 중 |
| OCTEON TX2 (CN98xx) | CPT v2 | AE×8, SE×46, IE×8 | 최대 128 VF | ~140 Gbps | RSA-2048 80K | 캐리어 코어 라우터 | 출시 중 |
| CN10K (CN106xx) | CPT v3 | AE×8, SE×40, IE×8 | 최대 256 VF | ~100 Gbps | RSA-2048 60K | DPU, 5G UPF, NGFW | 출시 중 |
| OCTEON 10 DPU | CPT v3 | AE×12, SE×48, IE×12 | 최대 256 VF | ~200 Gbps | RSA-2048 100K | 클라우드 DPU, CDN | 출시 중 |
차세대 CN20K: Marvell은 OCTEON 시리즈의 차세대 실리콘인 CN20K을 개발 중이며, 2025년 1월부터 Linux 네트워킹 서브시스템에 CN20K 지원 패치가 제출되고 있습니다. CN20K은 "OCTEON 20" DPU 제품군에 해당하며, CPT를 포함한 가속기 블록이 개선될 예정입니다.
엔진 유형 구분: CPT v2/v3는 3종류의 마이크로엔진(Micro-Engine)으로 구성됩니다. SE(Symmetric Engine)는 AES/SHA 등 대칭키·해시 연산, AE(Asymmetric Engine)는 RSA/ECC/DH 비대칭키 연산, IE(IPsec/Inline Engine)는 ESP/AH 프로토콜 캡슐화를 전담합니다. 각 엔진은 독립적으로 동작하며, 유형별로 개수를 조정하여 워크로드에 맞게 성능을 최적화할 수 있습니다.
CPT 하드웨어 블록 구조
CPT는 SoC 내부 인터커넥트(AMBA/CCN)를 통해 CPU 코어, SSO 이벤트 스케줄러, NIX(네트워크 인터페이스) 블록과 직접 연결됩니다. PF(Physical Function)가 전체 리소스를 관리하며, VF(Virtual Function)를 통해 각 애플리케이션(커널 또는 DPDK)이 독립된 명령 큐를 사용합니다.
CPT 명령 제출/완료 흐름
CPT의 모든 암호 연산은 CPT_INST_S(Instruction Structure) 디스크립터를 명령 큐(IQ)에 기록하는 방식으로 제출됩니다. 각 VF는 독립된 IQ를 보유하며, CPT 하드웨어가 빈 엔진을 자동으로 할당합니다. 완료 결과는 CPT_RES_S(Result Structure)로 전달되며, SSO 이벤트 또는 인터럽트/폴링 방식으로 통지됩니다.
CPT ↔ SSO 연동 (이벤트 드리븐 파이프라인)
OCTEON의 가장 강력한 특성은 CPT와 SSO(Schedule/Synchronize/Order) 이벤트 스케줄러의 하드웨어 직접 연동입니다. NGFW/IPsec 파이프라인에서 패킷이 암호화 처리를 거칠 때, CPU가 CPT 완료를 폴링하거나 인터럽트를 기다릴 필요 없이 CPT가 완료 이벤트를 SSO에 직접 제출합니다:
Linux 드라이버 소스 구조
CPT 드라이버는 drivers/crypto/marvell/octeontx2/에 위치하며, PF/VF 분리 구조입니다:
drivers/crypto/marvell/
├── octeontx/ /* OcteonTX1 CPT v1 드라이버 */
│ ├── otx_cptvf_main.c /* VF 드라이버 (crypto API 등록) */
│ ├── otx_cptvf_algs.c /* skcipher·aead 알고리즘 */
│ └── otx_cptvf_reqmgr.c /* 명령 큐 관리 */
├── octeontx2/ /* OcteonTX2/CN10K CPT v2/v3 드라이버 */
│ ├── otx2_cptpf_main.c /* PF: 엔진 그룹 할당, VF 관리 */
│ ├── otx2_cptvf_main.c /* VF: Crypto API 등록 */
│ ├── otx2_cptvf_algs.c /* skcipher·aead·ahash 알고리즘 */
│ ├── otx2_cpt_reqmgr.c /* IQ 제출, 완료 폴링/IRQ */
│ ├── otx2_cptlf.c /* LF(Logical Function) 관리 */
│ ├── cn10k_cpt.c /* CN10K 전용 로직 (CPT v3) */
│ └── otx2_cpt_common.h /* CPT_INST_S, CPT_RES_S 정의 */
└── Kconfig / Makefile
Kconfig 설정과 드라이버 확인
# ━━━ Marvell CPT 드라이버 설정 ━━━
# Kconfig 옵션
# CONFIG_CRYPTO_DEV_OCTEONTX_CPT=m ← OcteonTX1 CPT v1
# CONFIG_CRYPTO_DEV_OCTEONTX2_CPT=m ← OcteonTX2/CN10K CPT v2/v3
# PF/VF 디바이스 확인
lspci | grep -i cpt
# 0002:0e:00.0 Encryption controller: Cavium CPT PF (rev 54)
# 0002:0e:00.1 Encryption controller: Cavium CPT VF (rev 54)
# 드라이버 로드 확인
dmesg | grep -i cpt
# otx2_cpt 0002:0e:00.0: CPT PF: eng grps=8, SE=30, AE=4, IE=4
# otx2_cpt 0002:0e:00.1: CPT VF[0] ready
# 엔진 그룹 할당 상태 (sysfs)
cat /sys/bus/pci/drivers/otx2_cpt/*/eng_grp_info
# Engine Group 0: SE [cipher/hash] engines: 30
# Engine Group 1: AE [asymmetric] engines: 4
# Engine Group 2: IE [ipsec inline] engines: 4
# CPT가 등록한 Crypto API 알고리즘
grep -E "^driver|^name|^priority" /proc/crypto | grep -B2 otx2
# name : cbc(aes)
# driver : otx2-cpt-cbc-aes
# priority : 4001
# ---
# name : gcm(aes)
# driver : otx2-cpt-gcm-aes
# priority : 4001
# ---
# name : sha256
# driver : otx2-cpt-sha256
# priority : 4001
# ---
# name : rsa
# driver : otx2-cpt-rsa
# priority : 4001
# ---
# name : authenc(hmac(sha256),cbc(aes))
# driver : otx2-cpt-authenc-hmac-sha256-cbc-aes
# priority : 4001
인라인 IPsec 모드
CPT v2/v3의 IE(IPsec Engine)는 인라인(Inline) IPsec 모드를 지원합니다. 이 모드에서는 NIX(네트워크 인터페이스)가 수신·송신 패킷을 CPT에 직접 전달하여 ESP 캡슐화/역캡슐화를 수행하며, CPU는 SA(Security Association) 설정만 담당합니다. xfrm 프레임워크의 offload 모드로 활성화됩니다:
# ━━━ OCTEON 인라인 IPsec 설정 ━━━
# xfrm offload 모드로 SA 추가
ip xfrm state add \
src 192.168.1.1 dst 10.0.0.1 \
proto esp spi 0x100 reqid 1 mode tunnel \
aead "rfc4106(gcm(aes))" 0x$(xxd -l 20 -p /dev/urandom) 128 \
offload dev eth0 dir out # ← offload 키워드가 핵심
# 인라인 IPsec 통계 확인
ethtool -S eth0 | grep ipsec
# ipsec_tx_pkts: 1234567
# ipsec_tx_bytes: 890123456
# ipsec_rx_pkts: 1234560
# ipsec_rx_bytes: 890120000
# SA 오프로드 상태 확인
ip xfrm state show | grep offload
# offload dev eth0 dir out
# → NIX TX → CPT IE → 와이어 (CPU 0% 암호화 부하)
성능 특성
| 알고리즘 | OcteonTX1 (25G) | OcteonTX2 CN96 (100G) | CN10K (100G) | OCTEON 10 DPU (200G) |
|---|---|---|---|---|
| AES-128-CBC | ~20 Gbps | ~95 Gbps | ~100 Gbps | ~180 Gbps |
| AES-256-GCM | ~15 Gbps | ~80 Gbps | ~100 Gbps | ~170 Gbps |
| SHA-256 | ~18 Gbps | ~70 Gbps | ~80 Gbps | ~150 Gbps |
| RSA-2048 Sign | ~10K op/s | ~50K op/s | ~60K op/s | ~100K op/s |
| RSA-2048 Verify | ~60K op/s | ~200K op/s | ~250K op/s | ~400K op/s |
| ECDSA P-256 Sign | ~15K op/s | ~80K op/s | ~100K op/s | ~150K op/s |
| 인라인 IPsec (GCM) | 미지원 | ~100 Gbps | ~100 Gbps | ~200 Gbps |
우선순위와 자동 선택: CPT 드라이버의 crypto priority는 4001로, 대부분의 소프트웨어 구현(100~400)과 다른 SoC 가속기(CAAM 3000, CCP 200)보다 높습니다. OCTEON 플랫폼에서는 별도 설정 없이 CPT가 기본 암호 제공자(crypto provider)로 자동 선택됩니다.
SR-IOV 격리: CPT PF는 최대 128~256개 VF를 생성할 수 있어, 각 VM/컨테이너에 독립된 암호 가속 인스턴스를 할당할 수 있습니다. VF 간 큐와 엔진이 완전히 격리되므로 멀티테넌트 환경에서 안전합니다.
DPDK 연동: DPDK crypto_cnxk(CN10K) / crypto_octeontx2(TX2) PMD를 통해 유저스페이스에서 CPT에 직접 접근할 수 있습니다. SSO eventdev(event_cnxk)와 결합하면 CPU 개입 없는 완전 HW 파이프라인이 구성됩니다. 상세 파이프라인 코드는 NGFW 오프로드 — OCTEON SSO를 참고하세요.
Lookaside vs Inline: 룩어사이드 모드는 범용 암호화(dm-crypt, AF_ALG)에, 인라인 모드는 IPsec/MACsec 네트워크 오프로드에 사용합니다. 두 모드를 동시에 사용할 수 있으며, IE 엔진 수를 조정하여 워크로드에 맞게 리소스를 분배합니다.
Marvell NITROX — 개별 PCIe 암호화 가속기
Marvell(구 Cavium)은 SoC 내장 CPT 외에도 NITROX 시리즈라는 개별 PCIe 카드형 암호화 가속기를 제공합니다. NITROX는 룩어사이드 오프로드 아키텍처의 대표적인 PCIe 카드 구현으로, SSL/TLS 오프로드, VPN 가속, 압축 등에 특화된 전용 보안 프로세서입니다. 서버의 PCIe 슬롯에 장착하여 CPU 부하 없이 대량의 암호 연산을 처리합니다. OCTEON CPT가 SoC에 통합된 네트워크 장비용이라면, NITROX는 범용 x86/ARM 서버에 추가 장착하는 형태입니다.
NITROX 세대별 사양
| 제품 | 칩셋 | PCIe | 대칭키 처리량 | RSA-2048 | 압축 | SR-IOV | 커널 드라이버 | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|---|---|---|---|
| NITROX III | CNN35XX | PCIe 2.0 ×16 / 3.0 ×8 | ~40 Gbps | ~12K op/s | Deflate ~30 Gbps | 지원 | — (DPDK PMD) | 출시 중 |
| NITROX V | CNN55XX | PCIe 3.0 ×8 | ~100 Gbps | ~130K op/s | Deflate ~60 Gbps | 최대 256 VF | nitrox (커널 4.13+) |
출시 중 |
| NITROX XL 어댑터 | CNN35XX-NHB | PCIe 3.0 | ~60 Gbps | ~150K op/s | Deflate ~40 Gbps | 지원 | — (DPDK PMD) | 출시 중 |
| LiquidSecurity 2 | HSM 전용 | PCIe | — | ~1M op/s | — | 42 파티션 | — (PKCS#11) | 출시 중 (FIPS 140-3 L3) |
NITROX 내부 아키텍처
NITROX V(CNN55XX)는 내부에 다수의 RISC 기반 보안 코어와 전용 압축 엔진을 통합한 보안 프로세서입니다. 호스트와는 PCIe DMA를 통해 통신하며, SR-IOV VF를 통해 VM별로 독립된 암호 가속 인스턴스를 제공합니다.
커널 드라이버와 DPDK 연동
NITROX V(CNN55XX)는 Linux 커널 4.13부터 메인라인에 nitrox 드라이버가 포함되어 있습니다. 드라이버는 drivers/crypto/cavium/nitrox/에 위치하며, Crypto API에 대칭키·비대칭키 알고리즘을 등록합니다. NITROX III(CNN35XX)와 NITROX XL 어댑터는 커널 드라이버가 없으며 DPDK crypto_nitrox PMD를 통해 유저스페이스에서 접근합니다.
# ━━━ NITROX V (CNN55XX) 드라이버 설정 ━━━
# Kconfig 옵션
# CONFIG_CRYPTO_DEV_NITROX=m
# CONFIG_CRYPTO_DEV_NITROX_CNN55XX=m
# PCIe 디바이스 확인
lspci | grep -i nitrox
# 05:00.0 Co-processor: Cavium NITROX V CNN55XX (rev 01)
# 드라이버 로드 (펌웨어 자동 로딩)
modprobe nitrox
# nitrox 0000:05:00.0: NITROX ready, firmware loaded
# nitrox 0000:05:00.0: SE cores: 64, AE cores: 16
# 등록된 알고리즘 확인
grep -E "^driver|^name|^priority" /proc/crypto | grep -B2 nitrox
# name : cbc(aes)
# driver : nitrox-cbc-aes
# name : ecb(aes)
# driver : nitrox-ecb-aes
# SR-IOV VF 생성
echo 16 > /sys/bus/pci/devices/0000:05:00.0/sriov_numvfs
drivers/crypto/cavium/nitrox/
├── nitrox_main.c /* PF 드라이버 프로브, 펌웨어 로딩 */
├── nitrox_algs.c /* skcipher 알고리즘 (AES-CBC/ECB/CTR 등) */
├── nitrox_aead.c /* AEAD 알고리즘 (AES-GCM 등) */
├── nitrox_reqmgr.c /* 명령 큐 관리, DMA 디스크립터 */
├── nitrox_isr.c /* 인터럽트 핸들러 (완료 폴링/IRQ) */
├── nitrox_sriov.c /* SR-IOV VF 관리 */
├── nitrox_dev.h /* 디바이스 구조체 (SE/AE 코어 수 등) */
└── Kconfig / Makefile
NITROX vs CPT 선택 기준: NITROX(CNN55XX)는 범용 x86 서버에 PCIe 카드로 장착하여 SSL/TLS 오프로드, VPN 가속 등에 사용합니다. 반면 CPT(OcteonTX2/CN10K)는 Marvell SoC 기반 네트워크 장비에 내장되어 인라인 IPsec, 방화벽 등에 사용됩니다. Intel QAT Gen 4 이후 CPU 내장 가속이 보편화되면서, NITROX는 QAT가 없는 서버나 멀티벤더 환경에서 주로 활용됩니다.
LiquidSecurity 2 HSM: LiquidSecurity는 NITROX 하드웨어 기반의 FIPS 140-3 Level 3 인증 HSM입니다. 최대 42개의 암호학적으로 격리된 파티션을 제공하며, 초당 100만 이상의 AES 연산을 처리합니다. Microsoft Azure Cloud HSM 서비스의 기반 하드웨어로 사용되고 있습니다. PKCS#11 인터페이스를 통해 접근하며, Linux 커널 Crypto API에는 등록되지 않습니다.
NXP CAAM (Cryptographic Acceleration and Assurance Module)
CAAM(Cryptographic Acceleration and Assurance Module)은 NXP i.MX6/7/8 시리즈 및 Layerscape LS1/LS2 시리즈 SoC에 내장된 암호화 가속 모듈입니다. 잡 링(Job Ring) 기반 비동기 아키텍처가 핵심으로, 최대 4개의 독립 잡 링(JR0~JR3)이 각각 자체 인터럽트와 디스크립터 큐를 갖고 있어 멀티코어 환경에서 lock-free 병렬 처리가 가능합니다. 내부적으로 DECO(DEscriptor COntroller) 엔진이 디스크립터를 독립 실행하며, AES(전 모드), SHA-1/256/384/512, RSA(최대 4096비트), ECDSA, 하드웨어 난수 생성기(TRNG)를 지원합니다. Layerscape SoC에서는 잡 링 외에 QI(Queue Interface)를 통해 DPAA(Data Path Acceleration Architecture) 프레임 큐와 직접 연동할 수 있어, 네트워크 데이터 플레인에서 CPU 개입 없는 인라인 암호화가 가능합니다.
SoC별 CAAM 사양
| SoC 시리즈 | CAAM 버전 | 잡 링 | DECO | QI | 대칭키 처리량 | 주요 용도 | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|---|---|---|
| i.MX6 시리즈 | SEC 4.x | 2 JR | 2~3 | 없음 | ~300 Mbps | IoT 게이트웨이, 산업용 | 장기 공급 (~2036) |
| i.MX7 시리즈 | SEC 4.x | 2 JR | 2 | 없음 | ~300 Mbps | 웨어러블, 저전력 IoT | 장기 공급 (~2035) |
| i.MX8M 시리즈 | SEC 4.x | 3 JR | 3 | 없음 | ~1 Gbps | 멀티미디어, 엣지 AI | 출시 중 |
| i.MX8X / i.MX8QXP | SEC 5.x | 4 JR | 4 | 없음 | ~1.5 Gbps | 자동차(ADAS), 산업용 | 출시 중 |
| i.MX93 | SEC 5.x (EdgeLock) | 4 JR | 4+ | 없음 | ~2 Gbps | 자동차, 산업 IoT | 출시 중 |
| i.MX95 | ELE (EdgeLock Enclave) | — | — | 없음 | ~2 Gbps | 자동차, 산업 IoT | 출시 중 |
| LS1012A | SEC 5.x | 2 JR | 4 | 있음 | ~2.5 Gbps | 소형 라우터, CPE | 출시 중 |
| LS1028A | SEC 5.x | 4 JR | 6 | 있음 | ~5 Gbps | TSN 스위치, 산업용 | 출시 중 |
| LS1043A/LS1046A | SEC 5.x | 4 JR | 6~8 | 있음 | ~10 Gbps | 엔터프라이즈 라우터 | 출시 중 |
| LS1088A | SEC 5.x | 4 JR | 8 | 있음 | ~10 Gbps | 네트워크 어플라이언스 | 출시 중 |
| LS2088A/LX2160A | SEC 5.4 | 4 JR | 12~16 | 있음 | ~20 Gbps | 캐리어 등급 라우터 | 출시 중 |
CAAM 하드웨어 블록 구조
CAAM은 내부적으로 잡 링(JR), QI(Queue Interface), DECO, 암호 코어의 4개 주요 블록으로 구성됩니다. 잡 링은 CPU가 디스크립터를 제출하는 일반적인 인터페이스이며, QI는 DPAA 프레임워크의 프레임 큐(Frame Queue)와 직접 연동하여 네트워크 패킷을 CPU 개입 없이 처리합니다.
잡 디스크립터와 링 메커니즘
CAAM의 모든 암호 연산은 잡 디스크립터(Job Descriptor)라는 명령어 시퀀스로 기술됩니다. 각 잡 링은 입력 링(Input Ring)과 출력 링(Output Ring)으로 구성된 한 쌍의 순환 버퍼(circular buffer)입니다. CPU가 디스크립터 포인터를 입력 링에 기록하고 도어벨(doorbell) 레지스터를 쓰면, CAAM은 빈 DECO에 디스크립터를 할당하여 실행합니다. 완료 후 결과 포인터가 출력 링에 기록되고 인터럽트가 발생합니다.
QI(Queue Interface)와 DPAA 연동
Layerscape SoC에서 CAAM은 잡 링 외에 QI(Queue Interface) 경로를 제공합니다. QI는 DPAA(Data Path Acceleration Architecture)의 QMan(Queue Manager) 프레임 큐와 직접 연동되어, 네트워크 패킷이 CPU를 거치지 않고 CAAM으로 전달됩니다. IPsec ESP 처리에서 이 경로를 사용하면 CPU 오버헤드가 크게 줄어듭니다:
# ━━━ QI 인터페이스 활성화 (Layerscape) ━━━
# Kconfig: CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI=m
# QI 드라이버가 DPAA QMan 프레임 큐를 통해 CAAM에 직접 접근
# QI 활성 확인
dmesg | grep qi_init
# caam_qi: registering rng-caam-qi
# caam_qi: 2 congestion groups, threshold 512
# QI 기반 알고리즘은 별도 드라이버명으로 등록
grep caam-qi /proc/crypto
# driver : authenc-hmac-sha256-cbc-aes-caam-qi
# driver : gcm-aes-caam-qi
Linux 드라이버 소스 구조
CAAM 드라이버는 drivers/crypto/caam/에 위치하며, 기능별로 모듈화되어 있습니다:
drivers/crypto/caam/
├── ctrl.c /* CAAM 컨트롤러 프로브·초기화 (platform_driver) */
├── jr.c /* 잡 링 드라이버 (입출력 링 관리, IRQ 핸들러) */
├── caamalg.c /* skcipher·aead 알고리즘 (JR 경로) */
├── caamalg_qi.c /* skcipher·aead 알고리즘 (QI 경로, Layerscape) */
├── caamalg_qi2.c /* skcipher·aead 알고리즘 (DPAA2 QI, LX2160A 등) */
├── caamhash.c /* ahash 알고리즘 (SHA, HMAC) */
├── caampkc.c /* RSA·ECC 비대칭키 알고리즘 */
├── caamrng.c /* 하드웨어 RNG (/dev/hwrng) */
├── key_gen.c /* 키 확장·분할 키(Split Key) 생성 */
├── desc_constr.h /* 디스크립터 빌더 매크로 (inline_cnstr_*) */
├── desc.h /* SEC 명령어 정의 (OP_TYPE, OP_ALG 등) */
├── regs.h /* CAAM 레지스터 맵 (JR 레지스터, 도어벨 등) */
├── intern.h /* 내부 자료구조 (caam_drv_private 등) */
├── blob_gen.c /* Blob 프로토콜 (블랙 키 캡슐화) */
└── sm.h /* 보안 메모리(Secure Memory) 인터페이스 */
Kconfig 설정과 드라이버 확인
# ━━━ NXP CAAM 드라이버 설정 ━━━
# Kconfig 옵션
# CONFIG_CRYPTO_DEV_FSL_CAAM=y ← CAAM 컨트롤러 (ctrl.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_JR=m ← Job Ring 드라이버 (jr.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m ← 대칭키·AEAD (caamalg.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI=m ← QI 경로 (caamalg_qi.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=m ← 해시 (caamhash.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=m ← RSA/ECC (caampkc.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=m ← /dev/hwrng (caamrng.c)
# CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN=y ← Blob 캡슐화 (blob_gen.c)
# Job Ring 디바이스 확인
dmesg | grep caam
# caam 1700000.crypto: device ID = 0x0A16010000000000
# caam 1700000.crypto: job rings = 4, qi = 1
# caam 1700000.crypto: desc_fifo_len = 63
# caam_jr 1710000.jr: registering rng-caam
# caam_jr 1720000.jr: registering cbc-aes-caam
# CAAM이 등록한 Crypto API 알고리즘 전체 목록
grep -E "^driver|^name|^priority" /proc/crypto | grep -B2 caam
# name : cbc(aes)
# driver : cbc-aes-caam
# priority : 3000
# ---
# name : gcm(aes)
# driver : gcm-aes-caam
# priority : 3000
# ---
# name : sha256
# driver : sha256-caam
# priority : 3000
# ---
# name : rsa
# driver : rsa-caam
# priority : 3000
# ---
# name : authenc(hmac(sha256),cbc(aes))
# driver : echainiv-authenc-hmac-sha256-cbc-aes-caam
# priority : 3100
# CAAM hwrng 상태
cat /sys/class/misc/hw_random/rng_current
# rng-caam
Device Tree 바인딩
CAAM은 SoC에 메모리 맵(MMIO) 방식으로 연결되며, Device Tree에서 잡 링·RNG·보안 메모리 등을 개별 자식 노드로 선언합니다:
/* NXP Layerscape LS1046A — CAAM Device Tree 바인딩 */
crypto@1700000 {
compatible = "fsl,sec-v5.4", "fsl,sec-v5.0",
"fsl,sec-v4.0";
/* CAAM 레지스터 영역 (컨트롤러 + 보안 메모리) */
reg = <0x0 0x1700000 0x0 0x100000>;
ranges = <0x0 0x0 0x1700000 0x100000>;
#address-cells = <1>;
#size-cells = <1>;
fsl,sec-era = <8>; /* SEC 하드웨어 세대 */
/* Job Ring 0 — 독립 IRQ, 커널 암호 API용 */
jr@10000 {
compatible = "fsl,sec-v5.4-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x10000 0x10000>;
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
};
/* Job Ring 1 — 독립 IRQ */
jr@20000 {
compatible = "fsl,sec-v5.4-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x20000 0x10000>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
};
/* Job Ring 2 — OP-TEE/TF-A에 할당 가능 */
jr@30000 {
compatible = "fsl,sec-v5.4-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x30000 0x10000>;
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
};
/* Job Ring 3 */
jr@40000 {
compatible = "fsl,sec-v5.4-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x40000 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
};
};
OP-TEE와 잡 링 분할: ARM TrustZone 환경에서 OP-TEE가 하나의 잡 링(보통 JR2)을 독점 사용하는 경우, 해당 잡 링의 Device Tree 노드에 status = "disabled"를 설정하여 Linux 커널이 접근하지 않도록 합니다. i.MX8M에서 OP-TEE + CAAM 조합이 일반적이며, 이 경우 Linux는 나머지 2~3개 잡 링만 사용합니다.
CAAM Blob 메커니즘 (블랙 키)
CAAM의 고유한 보안 기능 중 하나가 Blob 프로토콜입니다. Blob은 CAAM의 마스터 키(OTP에 퓨즈된 SoC 고유 키)로 데이터를 캡슐화(encapsulation)하는 메커니즘으로, 해당 SoC에서만 복호화할 수 있습니다. 이를 통해 키 자료를 외부 저장소(eMMC, NAND)에 안전하게 보관할 수 있습니다:
- 레드 키(Red Key) — 평문 키. CAAM 보안 메모리 내에서만 존재하며 외부 버스에 노출되지 않음
- 블랙 키(Black Key) — CAAM 마스터 키로 암호화된 키. 일반 메모리에 저장해도 안전
- Blob — 블랙 키 + MAC + 메타데이터를 하나로 묶은 캡슐. 다른 SoC에서는 복호화 불가능
/* CAAM Blob 캡슐화/역캡슐화 — drivers/crypto/caam/blob_gen.c */
/* Blob 구조: [Blob Header(16B)] + [암호화된 키 데이터] + [MAC(16B)] */
#define CAAM_BLOB_OVERHEAD (32 + 16) /* 헤더 + MAC */
/* 캡슐화: 레드 키 → Blob */
struct caam_blob_priv *blob = caam_blob_gen_init();
struct caam_blob_info info = {
.input = red_key, /* 평문 키 */
.input_len = key_len,
.output = blob_buf, /* Blob 출력 버퍼 */
.output_len = key_len + CAAM_BLOB_OVERHEAD,
.key_mod = key_modifier, /* 키 한정자 (용도별 분리) */
.key_mod_len = 16,
};
caam_encap_blob(blob, &info); /* HW 마스터 키로 캡슐화 */
/* 역캡슐화: Blob → 레드 키 (동일 SoC에서만 성공) */
caam_decap_blob(blob, &info); /* HW 마스터 키로 복호화 */
/* Trusted Keys에서 CAAM Blob 활용 (Linux 5.13+) */
/* keyctl add trusted mykey "new 32 keyhandle=caam" @u */
/* → CAAM Blob으로 키 실링, 파일시스템에 안전하게 저장 */
디스크립터 빌드 예제
CAAM 드라이버는 desc_constr.h의 매크로를 사용하여 하드웨어 디스크립터를 빌드합니다. 아래는 AES-CBC 암호화 디스크립터의 구성 과정입니다:
/* caamalg.c — AES-CBC 암호화 디스크립터 빌드 (간소화) */
#include "desc_constr.h"
u32 *desc = ctx->sh_desc_enc;
/* 공유 디스크립터(Shared Descriptor) 헤더 */
init_sh_desc(desc, HDR_SHARE_SERIAL);
/* 1. 키 로드 — DMA로 키를 CAAM 키 레지스터에 적재 */
append_key_aead(desc, ctx->key_dma, ctx->adata.keylen_pad,
ctx->cdata.keylen, ctx->cdata.key_virt);
/* 2. 잡 디스크립터 헤더 — 잡별 가변 파라미터 시작점 */
set_jump_tgt_here(desc, key_jump_cmd);
/* 3. IV 로드 — CBC 초기 벡터를 CONTEXT1에 적재 */
append_seq_in_ptr_intlen(desc, 0, ivsize, LDST_SGF);
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
LDST_CLASS_1_CCB | ivsize);
/* 4. 암호화 연산 — AES-CBC 인코드 */
append_operation(desc, ctx->cdata.algtype |
OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
/* 5. FIFO Load/Store — DMA로 입력 데이터 읽기·출력 데이터 쓰기 */
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 |
FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA);
/* 디스크립터 완성 — DECO가 이 시퀀스를 순차 실행 */
공유 디스크립터 vs 잡 디스크립터: CAAM은 두 종류의 디스크립터를 사용합니다. 공유 디스크립터(Shared Descriptor)는 알고리즘·키 등 세션 단위로 변하지 않는 명령을 담고, 잡 디스크립터(Job Descriptor)는 IV·데이터 포인터 등 요청마다 달라지는 파라미터를 담습니다. DECO는 두 디스크립터를 결합하여 하나의 연산으로 실행합니다.
성능 특성과 활용 가이드
| 알고리즘 | i.MX8M (1 Gbps) | LS1046A (10 Gbps) | LS2088A (20 Gbps) | 비고 |
|---|---|---|---|---|
| AES-128-CBC | ~800 Mbps | ~8 Gbps | ~18 Gbps | 블록 암호 기본 |
| AES-256-GCM | ~600 Mbps | ~7 Gbps | ~15 Gbps | IPsec ESP 표준 |
| SHA-256 | ~700 Mbps | ~6 Gbps | ~14 Gbps | HMAC 포함 |
| RSA-2048 Sign | ~500 op/s | ~2,000 op/s | ~5,000 op/s | 비대칭 연산 |
| RSA-2048 Verify | ~5,000 op/s | ~20,000 op/s | ~50,000 op/s | 검증이 훨씬 빠름 |
| ECDSA P-256 Sign | ~1,000 op/s | ~4,000 op/s | ~10,000 op/s | TLS 핸드셰이크 |
| RNG (TRNG) | ~100 Mbps | ~100 Mbps | ~100 Mbps | /dev/hwrng |
우선순위와 자동 선택: CAAM 드라이버의 crypto priority는 3000~4000으로 소프트웨어 fallback(100~300)보다 높습니다. 따라서 i.MX/Layerscape 플랫폼에서는 별도 설정 없이 CAAM이 기본 암호 제공자(crypto provider)로 자동 선택됩니다. AEAD 복합 알고리즘(authenc(hmac(sha256),cbc(aes)))은 priority 3100으로 더 높게 설정됩니다.
Trusted Keys 연동: Linux 5.13부터 CONFIG_TRUSTED_KEYS_CAAM을 통해 TPM 없이도 CAAM의 Blob 메커니즘으로 키 실링(sealing)이 가능합니다. 상세는 커널 키링 — trusted 키 타입을 참고하세요.
네트워크 오프로드: Layerscape 플랫폼에서는 CAAM QI 경로를 통한 IPsec xfrm 오프로드가 가능합니다. Device Tree 바인딩 상세와 DPAA 연동 설정은 NGFW 하드웨어 오프로드 페이지를 참고하세요.
성능 최적화 팁: (1) 잡 링을 CPU 코어에 1:1 매핑(irq_set_affinity)하면 lock 경합이 제거됩니다. (2) 소형 패킷이 많은 경우 디스크립터 배치(batching)로 도어벨 쓰기를 줄이세요. (3) Layerscape에서 IPsec 트래픽은 JR보다 QI 경로가 CPU 효율이 훨씬 높습니다.
i.MX95와 EdgeLock Enclave(ELE): i.MX95부터 NXP는 기존 CAAM 대신 EdgeLock Enclave(ELE)라는 독립 보안 도메인으로 전환하고 있습니다. ELE는 키 관리, 난수 생성, 암호화 서비스를 독립된 보안 프로세서에서 실행하며, Linux 커널에서는 fsl,imx95-se 호환 노드를 통해 접근합니다. ELE-HSM은 TLS 1.3, HKDF, SHE(Secure Hardware Extension) API를 지원하며, 기존 CAAM 잡 링 인터페이스와는 다른 메시지 기반 통신 모델을 사용합니다.
Samsung Exynos S5P SSS
Samsung S5P SSS(Security SubSystem)는 Exynos SoC에 내장된 암호 엔진입니다. s5p-sss 드라이버가 AES(ECB/CBC/CTR), SHA-1/256, PRNG를 Crypto API에 등록합니다. 주로 Android 기기에서 dm-crypt 가속에 활용됩니다.
S5P SSS는 Exynos SoC 내부에 AES 엔진, SHA 엔진, PRNG 엔진을 포함합니다. 각 엔진은 FIFO 기반 DMA로 데이터를 처리하며, 커널의 crypto_engine 프레임워크를 통해 요청을 큐잉합니다.
| SoC | 모듈 | 지원 알고리즘 | Kconfig | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|
| Exynos 4210/4412 | s5p-sss | AES(ECB/CBC), SHA-1/256 | CRYPTO_DEV_S5P | 단종 |
| Exynos 5250/5420 | s5p-sss | AES(ECB/CBC/CTR), SHA-1/256, PRNG | CRYPTO_DEV_S5P | 단종 |
| Exynos 7420/8890 | exynos-rng | PRNG (DRBG) | CRYPTO_DEV_EXYNOS_RNG | 단종 |
| Exynos 850/990 | FMP (UFS inline) | AES-256-XTS | UFS_EXYNOS_CRYPTO | 출시 중 |
| Exynos 2200/2400/2500 | FMP (UFS inline) | AES-256-XTS | UFS_EXYNOS_CRYPTO | 출시 중 |
# S5P SSS 드라이버 확인
dmesg | grep s5p-sss
# s5p-sss 10830000.sss: s5p-sss driver registered
# 등록된 알고리즘 확인
grep s5p /proc/crypto
# driver : ecb-aes-s5p
# priority : 300
Exynos 7420 이후 SoC에서는 FMP(Flash Memory Protector)가 UFS 인라인 암호화를 담당하며, S5P SSS와 별도로 동작합니다. FMP는 blk-crypto 프레임워크와 연동되어 fscrypt 파일 기반 암호화(FBE)를 하드웨어로 가속합니다.
SoC 임베디드 암호 엔진 종합
| 벤더 | SoC / 칩 | 드라이버 | Kconfig | 지원 알고리즘 | 인터페이스 | 출시 상태 (2025. 3 기준) |
|---|---|---|---|---|---|---|
| Broadcom | BCM58xx SPU | bcm-spu | CRYPTO_DEV_BCM_SPU | AES, SHA, 3DES, MD5 | SoC 내장 | 출시 중 |
| Allwinner | sun8i/sun50i CE | sun8i-ce | CRYPTO_DEV_SUN8I_CE | AES, SHA, PRNG | SoC 내장 | 출시 중 |
| Rockchip | RK3288/3399/3568/3588 | rk3288-crypto | CRYPTO_DEV_ROCKCHIP | AES, SHA, MD5 | SoC 내장 | 출시 중 |
| Amlogic | GXL/G12/S4 | amlogic-gxl | CRYPTO_DEV_AMLOGIC_GXL | AES (CBC/ECB) | SoC 내장 | 출시 중 |
| STMicro | STM32 CRYP | stm32-cryp | CRYPTO_DEV_STM32_CRYP | AES, DES, 3DES | MCU 내장 | 출시 중 |
| Texas Instr. | AM65x/J721E SA2UL | sa2ul | CRYPTO_DEV_SA2UL | AES, SHA, HMAC | SoC 내장 | 출시 중 |
| NXP | i.MX CAAM | caam | CRYPTO_DEV_FSL_CAAM | AES, SHA, RSA, RNG | SoC 내장 (MMIO) | 출시 중 |
| Microchip | ATMEL AES/SHA | atmel-aes | CRYPTO_DEV_ATMEL_AES | AES, SHA | SoC 내장 | 출시 중 |
| Qualcomm | QCE (IPQ/SDM/SM) | qce | CRYPTO_DEV_QCE | AES, DES, SHA | SoC 내장 | 출시 중 |
| MediaTek | EIP-97 (MT7623 등) | mtk-crypto | CRYPTO_DEV_MEDIATEK | AES, SHA, HMAC | SoC 내장 | 출시 중 |
| ARM | CryptoCell 7xx | ccree | CRYPTO_DEV_CCREE | AES, SHA, RSA, ECC, TRNG | SoC IP 블록 | 출시 중 |
| Intel | Keembay OCS | keembay-ocs-aes | CRYPTO_DEV_KEEMBAY_OCS_AES | AES, SM4, SHA | SoC 내장 | 출시 중 |
| Aspeed | AST2500/2600 HACE | aspeed-hace | CRYPTO_DEV_ASPEED_HACE | SHA, HMAC | BMC SoC 내장 | 출시 중 |
| Inside Secure | SafeXcel EIP-197 | safexcel | CRYPTO_DEV_SAFEXCEL | AES, SHA, HMAC, AEAD | SoC IP 블록 | 출시 중 |
virtio-crypto 가상 디바이스
virtio-crypto는 가상 머신에서 호스트의 암호화 가속기를 활용할 수 있는 준가상화(paravirtual) 디바이스입니다. QEMU/KVM 환경에서 게스트 커널이 virtio_crypto 드라이버를 통해 호스트의 Crypto API(또는 하드웨어 가속기)에 접근합니다:
# ━━━ QEMU에서 virtio-crypto 디바이스 추가 ━━━
# 방법 1: 내장 백엔드
qemu-system-x86_64 \
-device virtio-crypto-pci,cryptodev=crypto0 \
-object cryptodev-backend-builtin,id=crypto0
# 방법 2: vhost-user 백엔드 (DPDK cryptodev 연동)
qemu-system-x86_64 \
-chardev socket,id=chardev0,path=/tmp/vhost-crypto.sock \
-object cryptodev-vhost-user,id=crypto0,chardev=chardev0 \
-device virtio-crypto-pci,cryptodev=crypto0
/* virtio_crypto 서비스 유형 */
#define VIRTIO_CRYPTO_SERVICE_CIPHER 0 /* 대칭 암호 */
#define VIRTIO_CRYPTO_SERVICE_HASH 1 /* 해시 */
#define VIRTIO_CRYPTO_SERVICE_MAC 2 /* MAC */
#define VIRTIO_CRYPTO_SERVICE_AEAD 3 /* AEAD */
#define VIRTIO_CRYPTO_SERVICE_AKCIPHER 4 /* 비대칭 암호 (RSA) */
/* 게스트 커널의 /proc/crypto에서 확인 */
/* driver: virtio-crypto-xxx */
DPDK cryptodev 연동: DPDK 기반 가상 스위치(OVS-DPDK)에서 암호화 처리가 필요한 경우 vhost-user-crypto 백엔드를 통해 호스트의 QAT 가속기를 게스트에 노출할 수 있습니다. DPDK cryptodev의 상세는 DPDK 암호화 가속을 참고하세요.
virtio-crypto 호스트-게스트 데이터 흐름
virtio-crypto는 virtio 표준의 virtqueue 메커니즘을 통해 게스트와 호스트 간 암호 요청을 교환합니다. 게스트 커널의 virtio_crypto 드라이버가 Crypto API에 알고리즘을 등록하면, 상위 서브시스템(dm-crypt, IPsec 등)은 가상 머신 안에서도 투명하게 호스트의 가속기를 활용할 수 있습니다.
/* drivers/crypto/virtio/virtio_crypto_skcipher_algs.c — 게스트 드라이버 (간략화) */
/* virtio-crypto 알고리즘 등록 */
static struct virtio_crypto_algo virtio_crypto_algs[] = {
{
.algonum = VIRTIO_CRYPTO_CIPHER_AES_CBC,
.service = VIRTIO_CRYPTO_SERVICE_CIPHER,
.algo.skcipher = {
.base.cra_name = "cbc(aes)",
.base.cra_driver_name = "virtio-crypto-cbc-aes",
.base.cra_priority = 150, /* AES-NI보다 낮음 */
.setkey = virtio_crypto_skcipher_setkey,
.encrypt = virtio_crypto_skcipher_encrypt,
.decrypt = virtio_crypto_skcipher_decrypt,
},
},
/* ... AES-GCM, AES-CTR 등 ... */
};
/* 암호화 요청 처리 — virtqueue로 호스트에 전달 */
static int virtio_crypto_skcipher_encrypt(
struct skcipher_request *req)
{
struct virtio_crypto_request *vc_req;
struct scatterlist sg[4];
int ret;
/* 1. 요청 헤더 구성 (알고리즘, 세션 ID, IV) */
vc_req->header.opcode = VIRTIO_CRYPTO_CIPHER_ENCRYPT;
vc_req->header.session_id = ctx->session_id;
/* 2. scatterlist 구성: [header][IV][src_data][dst_data] */
sg_init_table(sg, 4);
sg_set_buf(&sg[0], &vc_req->header, sizeof(vc_req->header));
sg_set_buf(&sg[1], req->iv, crypto_skcipher_ivsize(tfm));
/* 3. virtqueue에 제출 → VM Exit → 호스트 처리 */
ret = virtqueue_add_sgs(data_vq, sgs, out_sgs, in_sgs,
vc_req, GFP_ATOMIC);
virtqueue_kick(data_vq);
return -EINPROGRESS; /* 비동기 — 호스트 완료 시 콜백 */
}
성능 비교와 선택 기준: (1) builtin 백엔드는 설정이 간단하지만 QEMU 사용자 공간에서 소프트웨어로 처리하므로 성능이 가장 낮습니다. (2) vhost-user 백엔드는 DPDK를 통해 호스트의 QAT/CCP를 활용하여 높은 처리량을 제공합니다. (3) SR-IOV VF 패스스루는 가속기 VF를 게스트에 직접 할당하여 virtio 오버헤드 없이 네이티브에 가까운 성능을 제공하지만, 라이브 마이그레이션이 제한됩니다. 대부분의 경우 게스트 VM에서 AES-NI CPUID를 패스스루(-cpu host)하여 CPU ISA 가속을 사용하는 것이 가장 실용적입니다.
AF_ALG 사용자 공간 인터페이스
AF_ALG는 커널 Crypto API를 사용자 공간에서 소켓 인터페이스로 접근할 수 있게 하는 주소 패밀리(Address Family)입니다. 하드웨어 가속기(AES-NI, ARM CE, QAT, CCP 등)가 등록한 알고리즘을 사용자 프로그램이 직접 활용할 수 있으므로, OpenSSL이나 별도 라이브러리 없이도 커널 수준의 최적화된 암호 연산을 수행할 수 있습니다.
AF_ALG 동작 구조
지원 소켓 유형
| 유형 | salg_type | 커널 모듈 | 용도 | Kconfig |
|---|---|---|---|---|
| skcipher | "skcipher" | algif_skcipher | 대칭 암호 (AES-CBC, AES-XTS 등) | CONFIG_CRYPTO_USER_API_SKCIPHER |
| hash | "hash" | algif_hash | 해시/HMAC (SHA-256, HMAC-SHA256 등) | CONFIG_CRYPTO_USER_API_HASH |
| aead | "aead" | algif_aead | AEAD (AES-GCM, ChaCha20-Poly1305) | CONFIG_CRYPTO_USER_API_AEAD |
| rng | "rng" | algif_rng | 난수 생성 (DRBG) | CONFIG_CRYPTO_USER_API_RNG |
AF_ALG 사용 예시
/* AF_ALG를 사용한 AES-256-CBC 암호화 예시 */
#include <linux/if_alg.h>
#include <sys/socket.h>
int afalg_aes_cbc_encrypt(const uint8_t *key, size_t keylen,
const uint8_t *iv,
const uint8_t *plaintext, size_t len,
uint8_t *ciphertext)
{
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "skcipher", /* 대칭 암호 */
.salg_name = "cbc(aes)", /* 알고리즘 이름 */
};
int tfmfd, opfd;
/* 1. AF_ALG 소켓 생성 및 알고리즘 바인드 */
tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa));
/* 2. 암호화 키 설정 */
setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, keylen);
/* 3. 연산 소켓 획득 (accept) */
opfd = accept(tfmfd, NULL, 0);
/* 4. IV 설정 + 데이터 전송 (sendmsg) */
struct msghdr msg = {};
struct cmsghdr *cmsg;
struct af_alg_iv *aiv;
char cbuf[CMSG_SPACE(4) + CMSG_SPACE(4 + 16)] = {};
struct iovec iov = { .iov_base = (void *)plaintext, .iov_len = len };
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
/* cmsg: 연산 유형 (암호화) */
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(4);
*(__u32 *)CMSG_DATA(cmsg) = ALG_OP_ENCRYPT;
/* cmsg: IV 설정 */
cmsg = CMSG_NXTHDR(&msg, cmsg);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
cmsg->cmsg_len = CMSG_LEN(4 + 16);
aiv = (void *)CMSG_DATA(cmsg);
aiv->ivlen = 16;
memcpy(aiv->iv, iv, 16);
/* 5. 데이터 전송 → 커널 Crypto API → H/W 가속 */
sendmsg(opfd, &msg, 0);
/* 6. 암호문 수신 */
read(opfd, ciphertext, len);
close(opfd);
close(tfmfd);
return 0;
}
코드 설명
AF_ALG 소켓을 사용한 AES-CBC 암호화의 전체 흐름입니다.
- sockaddr_alg.salg_name = "cbc(aes)"Crypto API의 알고리즘 이름을 직접 지정합니다. 커널은 등록된 구현 중 가장 높은 priority를 자동 선택하므로, AES-NI가 있으면
cbc-aes-aesni가 사용됩니다. - setsockopt(ALG_SET_KEY)암호화 키를 커널에 전달합니다. 내부적으로
crypto_skcipher_setkey()가 호출되어 키 스케줄이 확장됩니다. - accept()tfm 소켓에서 연산 소켓을 생성합니다. 하나의 tfm에서 여러 연산 소켓을 accept하여 동시에 다른 IV/데이터로 암호화할 수 있습니다.
- sendmsg + cmsg
cmsg(control message)로 연산 방향(암호화/복호화)과 IV를 전달하고,iov로 평문 데이터를 전송합니다. 커널은 수신 즉시 Crypto API를 통해 암호화를 수행합니다. - read()암호화된 결과를 읽습니다.
splice()를 사용하면 zero-copy로 파일/파이프로 직접 전달할 수도 있습니다.
# ━━━ AF_ALG 커맨드라인 활용 예시 ━━━
# SHA-256 해시 계산 (AF_ALG + openssl speed 비교용)
# Python으로 AF_ALG 소켓 직접 사용:
python3 -c "
import socket, struct
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
s.bind(('hash', 'sha256'))
op, _ = s.accept()
op.sendall(b'Hello, AF_ALG!')
digest = op.recv(32)
print(digest.hex())
"
# AF_ALG이 사용 중인 알고리즘 확인
cat /proc/crypto | grep -B2 -A2 "refcnt.*[1-9]"
# 활성 참조가 있는 알고리즘 = 현재 사용 중
# 커널 모듈 확인
lsmod | grep algif
# algif_skcipher 16384 0
# algif_hash 16384 1
# algif_aead 16384 0
AF_ALG vs 라이브러리 암호화: AF_ALG는 시스템 콜 오버헤드가 있어 소량 데이터(~수 KB 이하)에서는 OpenSSL/libgcrypt보다 느릴 수 있습니다. 대량 데이터(수 MB 이상)에서는 커널의 하드웨어 가속을 직접 활용하므로 효율적입니다. OpenSSL 3.x는 afalg 엔진(또는 provider)을 통해 AF_ALG를 투명하게 활용할 수 있습니다: openssl speed -evp aes-256-cbc -engine afalg.
암호화 성능 추적 및 디버깅
암호화 하드웨어 가속이 기대대로 동작하는지 확인하고, 병목 구간을 파악하려면 커널의 성능 추적 도구를 활용합니다. tcrypt 벤치마크, ftrace 트레이스포인트, perf 프로파일링으로 Crypto 서브시스템을 심층 분석할 수 있습니다.
tcrypt 모듈 벤치마크
tcrypt는 커널 내장 Crypto API 벤치마크 모듈로, 특정 알고리즘의 처리량을 직접 측정합니다. 실제 I/O 스택 없이 순수 암호 연산 성능만 측정하므로 하드웨어 가속 효과를 정확히 평가할 수 있습니다:
# ━━━ tcrypt 벤치마크 사용법 ━━━
# AES-CBC skcipher 벤치마크 (2초 측정)
modprobe tcrypt mode=500 sec=2
# mode 번호는 커널 버전별로 다를 수 있음 — dmesg로 결과 확인
dmesg | tail -20
# AES-GCM AEAD 벤치마크
modprobe tcrypt mode=211 sec=2
# SHA-256 해시 벤치마크
modprobe tcrypt mode=403 sec=3
# 특정 키 크기만 테스트 (num_mb: 동시 버퍼 수)
modprobe tcrypt mode=500 sec=2 num_mb=8
# tcrypt 결과 예시 (dmesg)
# testing speed of async cbc(aes) (cbc-aes-aesni) encryption
# test 0 (128 bit key, 16 byte blocks): 18742341 ops in 2 sec (299877456 bytes)
# test 5 (128 bit key, 8192 byte blocks): 537420 ops in 2 sec (4402585600 bytes)
# → ~2.2 GB/s
# ⚠️ tcrypt는 한 번 실행 후 -EAGAIN 반환 → rmmod 후 재실행
rmmod tcrypt 2>/dev/null; modprobe tcrypt mode=500 sec=2
ftrace로 Crypto 경로 추적
커널 Crypto API의 호출 경로를 ftrace로 추적하면 어떤 드라이버가 실제로 호출되는지, FPU 컨텍스트 전환이 발생하는지 등을 확인할 수 있습니다:
# ━━━ ftrace로 Crypto API 호출 추적 ━━━
# 1. function_graph 트레이서 설정
cd /sys/kernel/debug/tracing
echo function_graph > current_tracer
# 2. AES-NI 관련 함수 필터링
echo 'aesni_*' > set_ftrace_filter
echo 'kernel_fpu_begin' >> set_ftrace_filter
echo 'kernel_fpu_end' >> set_ftrace_filter
echo 'crypto_skcipher_encrypt' >> set_ftrace_filter
# 3. 특정 프로세스만 추적 (dm-crypt 워커)
echo $(pgrep -f kcryptd) > set_ftrace_pid
# 4. 추적 시작
echo 1 > tracing_on
# ... dm-crypt I/O 발생 대기 ...
echo 0 > tracing_on
# 5. 결과 확인
cat trace | head -30
# kcryptd-123 | crypto_skcipher_encrypt() {
# kcryptd-123 | kernel_fpu_begin() {
# kcryptd-123 | fpu__save();
# kcryptd-123 | } /* kernel_fpu_begin: 0.450 us */
# kcryptd-123 | aesni_xts_encrypt(); ← AES-NI 가속 확인!
# kcryptd-123 | kernel_fpu_end();
# kcryptd-123 | } /* crypto_skcipher_encrypt: 2.130 us */
# 정리
echo nop > current_tracer
echo > set_ftrace_filter
echo > set_ftrace_pid
perf로 암호화 CPU 프로파일링
perf로 암호화 워크로드의 CPU 사용 분포를 분석하면 하드웨어 가속 효과를 정량적으로 평가할 수 있습니다:
# ━━━ perf로 dm-crypt 암호화 프로파일링 ━━━
# dm-crypt 워커의 CPU 사용 분포
perf top -p $(pgrep -f kcryptd) -e cycles
# 결과 예시 (AES-NI 활성):
# 45.2% [kernel] aesni_xts_encrypt ← AES-NI 가속
# 12.3% [kernel] crypt_convert
# 8.7% [kernel] memcpy_erms
# 5.1% [kernel] bio_advance_iter
# 결과 예시 (AES-NI 미활성, 제네릭 폴백):
# 78.5% [kernel] aes_encrypt ← S/W 구현 (병목!)
# 10.2% [kernel] crypt_convert
# 전체 시스템에서 crypto 관련 CPU 사용 비율
perf record -a -g -- sleep 10
perf report --sort=symbol | grep -i -E "aes|sha|crypto|crypt"
# IPsec 오프로드 효과 확인
# NIC offload 활성 시 aesni_* 호출이 사라져야 함
perf stat -e task-clock -p $(pgrep -f "xfrm") -- sleep 5
# H/W 가속 vs S/W 폴백 비율 확인
perf stat -e 'crypto:*' -a -- sleep 10
# crypto:crypto_request_submit 1,234,567
# (tracepoint가 있는 커널 버전에서만 동작)
/proc/crypto 진단 체크리스트
# ━━━ /proc/crypto 진단 체크리스트 ━━━
# 1. 특정 알고리즘의 모든 구현 비교
grep -A5 'name.*: cbc(aes)' /proc/crypto | grep -E 'name|driver|priority|module'
# → priority가 가장 높은 드라이버가 기본 사용됨
# 2. H/W 가속기가 등록한 알고리즘만 필터링
grep -B1 -A4 'priority.*[3-9][0-9][0-9]' /proc/crypto | grep -E 'name|driver|priority'
# → priority 300 이상 = H/W 가속 가능성 높음
# 3. 특정 모듈의 알고리즘만 확인
grep -B2 -A3 'module.*aesni_intel' /proc/crypto
grep -B2 -A3 'module.*ccp' /proc/crypto
grep -B2 -A3 'module.*qat' /proc/crypto
# 4. 자가 테스트(selftest) 실패 여부 확인
grep -B2 'selftest.*: fail' /proc/crypto
# → 비어 있어야 정상
# 5. 비동기(async) 알고리즘 확인 (QAT/CCP 등)
grep -B3 'type.*: givcipher\|async.*: yes' /proc/crypto | grep -E 'name|driver|async'
# 6. 알고리즘 총 개수
grep '^name' /proc/crypto | wc -l
# 일반적으로 100~300개 (HW 가속기에 따라 증가)
실전 디버깅 팁: (1) dm-crypt가 느리면 perf top에서 aes_encrypt(제네릭)이 보이는지 확인 — 보이면 aesni_intel 모듈 로드 누락. (2) IPsec 처리량이 기대 이하면 ethtool -k eth0 | grep esp로 NIC offload 상태 확인. (3) QAT가 등록되었는지 grep qat /proc/crypto로 확인 — 비어 있으면 intel_qat + qat_4xxx 모듈 로드 필요.
SED/OPAL 커널 인터페이스
SED(Self-Encrypting Drive)는 드라이브 내부 컨트롤러가 모든 데이터를 실시간으로 암호화/복호화하는 저장 장치입니다.
CPU나 운영체제의 개입 없이 하드웨어 수준에서 전체 디스크 암호화(Full Disk Encryption, FDE)를 수행하므로
성능 저하가 전혀 없는 것이 가장 큰 장점입니다.
Linux 커널은 TCG Opal 2.0 표준을 구현한 SED 장치를 sed-opal 모듈로 지원합니다.
TCG Opal 2.0 표준
TCG(Trusted Computing Group)의 Opal 표준은 SED 디스크의 잠금/해제, 범위 관리, 인증 절차를 정의합니다. 핵심 개념은 다음과 같습니다.
- Locking SP (Locking Security Provider) — 디스크 잠금/해제를 관리하는 보안 도메인. 활성화해야 SED 기능이 동작합니다.
- Admin SP — Locking SP 활성화, SID(Security ID) 관리, 초기화를 담당합니다.
- Locking Range — 디스크의 LBA 범위 단위로 독립적인 잠금/해제가 가능합니다. Range 0은 전체 디스크를 의미합니다.
- MEK (Media Encryption Key) — 드라이브 내부에서 데이터를 실제로 암호화하는 키. 외부로 노출되지 않습니다.
- PSID (Physical Security ID) — 드라이브 라벨에 인쇄된 비밀번호. 공장 초기화(Revert)에만 사용됩니다.
Linux 커널 SED/OPAL 지원
커널의 sed-opal 모듈(CONFIG_BLK_SED_OPAL)은 블록 디바이스 레이어에서
TCG Opal 명령을 NVMe Security Send/Receive 또는 ATA Trusted Send/Receive 명령으로 변환합니다.
사용자 공간은 ioctl() 시스템 호출을 통해 SED 기능을 제어합니다.
# 커널 설정 확인
grep CONFIG_BLK_SED_OPAL /boot/config-$(uname -r)
# CONFIG_BLK_SED_OPAL=y
# Opal 지원 여부 확인 (NVMe)
nvme id-ctrl /dev/nvme0 | grep oacs
# oacs: 0x17 ← bit 0 (Security Send/Receive) 설정됨
# sedutil로 디스크 상태 확인
sedutil-cli --query /dev/nvme0n1
핵심 ioctl 인터페이스
커널이 제공하는 주요 IOC_OPAL_* ioctl 명령은 다음과 같습니다.
| ioctl | 기능 | 설명 |
|---|---|---|
IOC_OPAL_SAVE |
비밀번호 저장 | 커널 키링에 Opal 비밀번호를 저장하여 suspend/resume 시 자동 잠금 해제에 사용 |
IOC_OPAL_LOCK_UNLOCK |
잠금/해제 | 특정 Locking Range의 읽기/쓰기 잠금 상태를 변경 |
IOC_OPAL_ACTIVATE_LSP |
Locking SP 활성화 | SED 기능을 처음 활성화. 이후 Locking Range 설정이 가능해짐 |
IOC_OPAL_SET_PW |
비밀번호 설정 | Admin 또는 User 비밀번호를 설정/변경 |
IOC_OPAL_REVERT_TPR |
공장 초기화 | PSID를 사용하여 드라이브를 공장 상태로 되돌림 (모든 데이터 삭제) |
IOC_OPAL_ERASE_LR |
Locking Range 삭제 | 특정 범위의 MEK를 재생성하여 해당 범위의 데이터를 암호학적으로 삭제 |
커널 소스 분석: opal_lock_unlock() 커널 내부 흐름
/* block/sed-opal.c — Opal 잠금/해제 핵심 경로 */
static int opal_lock_unlock(struct opal_dev *dev,
struct opal_lock_unlock *lk_unlk)
{
/* 1. Opal 세션 시작 — Admin SP 또는 Locking SP에 인증 */
const struct opal_step unlock_steps[] = {
{ start_auth_opal_session, &lk_unlk->session },
{ lock_unlock_locking_range, lk_unlk },
{ end_opal_session, NULL },
};
/* 2. 단계별 실행 — TCG Opal 프로토콜 패킷 전송 */
return execute_steps(dev, unlock_steps,
ARRAY_SIZE(unlock_steps));
}
/* lock_unlock_locking_range() 내부 */
static int lock_unlock_locking_range(struct opal_dev *dev, void *data)
{
/* Locking Range N의 ReadLocked/WriteLocked 속성을 Set 메서드로 변경 */
/* OPAL_LOCKING_RANGE + range_id → 대상 UID 결정 */
/* l_state: OPAL_RO (읽기 전용), OPAL_RW (읽기/쓰기), OPAL_LK (잠금) */
add_token_u8(&err, dev, OPAL_STARTNAME);
add_token_u8(&err, dev, OPAL_VALUES);
/* ReadLocked = (l_state != OPAL_RW && l_state != OPAL_RO) */
/* WriteLocked = (l_state != OPAL_RW) */
...
}
코드 설명
-
핵심
opal_lock_unlock()은 3단계 프로토콜로 동작합니다: (1) Opal 세션을 시작하고 비밀번호로 인증, (2) Locking Range의 ReadLocked/WriteLocked 속성을 변경, (3) 세션을 종료합니다. -
핵심
execute_steps()는 각 단계를 순차적으로 실행하며, NVMe Security Send/Receive 명령을 통해 드라이브와 통신합니다. TCG Opal 프로토콜은 토큰 기반 바이너리 포맷을 사용하며,add_token_u8()등으로 패킷을 구성합니다. -
핵심
잠금 상태(
l_state)는OPAL_RO(읽기 전용),OPAL_RW(읽기/쓰기 허용),OPAL_LK(완전 잠금) 세 가지가 있습니다. suspend/resume 시 커널은IOC_OPAL_SAVE로 저장된 비밀번호를 사용하여 자동 잠금 해제를 수행합니다.
sedutil 사용자 공간 도구
sedutil-cli는 SED/Opal 디스크를 관리하는 오픈소스 도구입니다.
초기 설정부터 잠금/해제, 비밀번호 변경, 공장 초기화까지 모든 Opal 작업을 수행할 수 있습니다.
# 1. 초기 설정 — SID 비밀번호 설정 + Locking SP 활성화 + MBR 섀도잉
sedutil-cli --initialsetup password /dev/nvme0n1
# 2. Locking Range 0 (전체 디스크) 잠금 활성화
sedutil-cli --enableLockingRange 0 password /dev/nvme0n1
# 3. 디스크 잠금 해제
sedutil-cli --setLockingRange 0 RW password /dev/nvme0n1
# 4. 디스크 잠금 (재부팅 시 자동 잠금과 동일)
sedutil-cli --setLockingRange 0 LK password /dev/nvme0n1
# 5. 비밀번호 변경
sedutil-cli --setSIDPassword old_password new_password /dev/nvme0n1
sedutil-cli --setAdmin1Pwd old_password new_password /dev/nvme0n1
# 6. 공장 초기화 (PSID 사용 — 드라이브 라벨 확인)
# ⚠️ 모든 데이터가 영구 삭제됩니다
sedutil-cli --PSIDrevert PSID_FROM_LABEL /dev/nvme0n1
SED vs dm-crypt vs blk-crypto 비교
| 방식 | 암호화 위치 | CPU 부하 | 성능 영향 | 키 관리 |
|---|---|---|---|---|
| dm-crypt (LUKS) | 블록 레이어 (SW) | 높음 (AES-NI 시 중간) | 10-30% 감소 | dm-crypt / LUKS 키슬롯 |
| blk-crypto | 인라인 HW 엔진 | 없음 | 0-2% 감소 | blk-crypto keyslot manager |
| SED/OPAL | 드라이브 내부 컨트롤러 | 없음 | 0% (투명) | TCG Opal (드라이브 자체 관리) |
NAS 환경에서 SED는 제로 성능 손실로 전체 디스크 암호화를 제공하는 가장 효율적인 방법입니다.
다수의 NVMe SSD를 사용하는 NAS에서 dm-crypt의 CPU 오버헤드를 제거할 수 있으며,
드라이브 교체나 폐기 시 IOC_OPAL_ERASE_LR을 통해 MEK를 재생성하면 즉시 암호학적 삭제(Crypto Erase)가 가능합니다.
PSIDrevert)이며,
이 경우 MEK가 재생성되어 모든 데이터가 영구적으로 삭제됩니다.
운영 환경에서는 비밀번호를 안전한 곳에 백업하고, IOC_OPAL_SAVE를 통해 커널 키링에 저장하여 suspend/resume 시 자동 잠금 해제를 설정하세요.
HSM (Hardware Security Module, 하드웨어 보안 모듈)
HSM(Hardware Security Module)은 암호화 키의 생성·저장·사용을 물리적으로 격리된 전용 하드웨어에서 수행하는 보안 장치입니다. 일반 서버나 소프트웨어에서는 개인키가 메모리에 노출되어 추출 위험이 존재하지만, HSM은 키가 장치 내부를 절대 떠나지 않도록 설계됩니다. FIPS 140-2/140-3 Level 3 이상의 인증을 갖추며, 물리적 탬퍼 감지(tamper detection) 및 탬퍼 대응(tamper response) 메커니즘으로 키를 보호합니다.
HSM vs TPM vs 소프트웨어 키 저장소
| 특성 | HSM | TPM | 소프트웨어 키스토어 |
|---|---|---|---|
| 키 저장 위치 | 전용 하드웨어 (FIPS 인증) | SoC/마더보드 내장 칩 | 디스크/메모리 |
| 키 추출 가능 여부 | 불가 (탬퍼 시 자동 삭제) | 불가 (제한적 연산만 지원) | 가능 (메모리 덤프 위험) |
| 암호 연산 성능 | 수만~수십만 TPS | 수십~수백 TPS | CPU 의존 |
| FIPS 인증 등급 | Level 2~4 | Level 1~2 | Level 1 (소프트웨어) |
| 폼 팩터 | PCIe 카드 / 네트워크 어플라이언스 / USB | SPI/I2C 칩 (2×3mm) | 해당 없음 |
| 비용 | 수백~수천만 원 | 수천~수만 원 | 무료 |
| 주요 용도 | CA 루트키, 코드 서명, 결제, PKI | 플랫폼 무결성, Measured Boot | 개발/테스트 |
| 다중 테넌트 | 파티션/슬롯으로 격리 | 단일 소유자 | 파일 권한 |
HSM 내부 아키텍처
HSM은 외부 환경과 완전히 격리된 보안 경계(Security Boundary) 내에서 동작합니다. 모든 암호화 연산은 전용 프로세서에서 수행되며, 키 자료(Key Material)는 보안 경계를 벗어나지 않습니다. 호스트 시스템은 PKCS#11, KMIP, 또는 벤더 전용 API를 통해 HSM에 연산을 요청하고 결과만 받습니다.
FIPS 140-2/140-3 보안 등급
HSM의 보안 등급은 미국 NIST의 FIPS 140 표준으로 정의됩니다. 대부분의 상용 HSM은 Level 3 인증을 갖추고 있으며, 금융·군사·정부 기관에서는 Level 3 이상을 요구합니다.
| 등급 | 물리 보안 요구사항 | 키 관리 | 환경 방어 | 적용 예 |
|---|---|---|---|---|
| Level 1 | 생산 등급 장비, 탬퍼 증거 없음 | 소프트웨어 기반 허용 | 없음 | 소프트웨어 암호 모듈 |
| Level 2 | 탬퍼 증거 (봉인 씰, 코팅) | 역할 기반 인증 필수 | 없음 | TPM, 기본 HSM |
| Level 3 | 탬퍼 감지+대응 (개봉 시 키 삭제) | ID 기반 인증 필수 | 없음 | Thales Luna, Utimaco, Entrust nShield |
| Level 4 | Level 3 + 능동적 물리 방어 | 다중 인자 인증 | 전압·온도 변조 감지 | 군사·정부 최고 등급 |
FIPS 140-2 vs 140-3: FIPS 140-3(2019년 발표, ISO 19790 기반)은 140-2를 대체하는 최신 표준입니다. 주요 변경점은 (1) 소프트웨어 모듈에 대한 테스트 강화, (2) 비결정적 난수 생성기(NDRNG) 요구, (3) 조건부 자체 테스트(Conditional Self-Test) 의무화입니다. 2026년 현재 대부분의 신규 HSM은 FIPS 140-3 인증을 취득하고 있습니다.
주요 HSM 제품군
| 제조사 / 제품 | 폼 팩터 | FIPS 등급 | RSA-2048 서명/초 | 파티션 | 인터페이스 | Linux 지원 |
|---|---|---|---|---|---|---|
| Thales Luna Network HSM 7 | 네트워크 어플라이언스 (1U) | 140-3 L3 | 20,000 | 최대 100 | Ethernet (NTLS/TLS) | PKCS#11 라이브러리 |
| Thales Luna PCIe HSM 7 | PCIe 카드 | 140-3 L3 | 20,000 | 최대 20 | PCIe 3.0 x4 | 커널 모듈 + PKCS#11 |
| Entrust nShield Connect XC | 네트워크 어플라이언스(1U) | 140-2 L3 | 14,400 | 다중 Security World | Ethernet | PKCS#11 / JCE / CAPI |
| Utimaco CryptoServer Se Gen2 | PCIe 카드 | 140-2 L3 | 15,000 | 다중 펌웨어 파티션 | PCIe 3.0 | PKCS#11 / JCE |
| AWS CloudHSM | 클라우드 (전용 하드웨어) | 140-2 L3 | ~1,100 | VPC 격리 | ENI (네트워크) | PKCS#11 / OpenSSL |
| Azure Managed HSM | 클라우드 (전용 풀) | 140-2 L3 | 가변 | 구독 격리 | REST API / SDK | az CLI / SDK |
| YubiHSM 2 | USB (나노 크기) | 140-2 L3 | ~100 | 최대 16 인증 키 | USB 2.0 | PKCS#11 / yubihsm-shell |
| Nitrokey HSM 2 | USB 스마트카드 | CC EAL5+ | ~50 | 최대 48 키 슬롯 | USB (PC/SC) | PKCS#11 (OpenSC) |
Linux 커널과 HSM 연동
리눅스 커널은 HSM에 직접적으로 의존하지 않지만, 여러 서브시스템이 HSM과 연동됩니다. 커널 모듈 서명, 커널 키링(Keyring), PKCS#11을 통한 TLS 인증서 관리 등이 대표적입니다.
PKCS#11과 HSM 활용
PKCS#11(Cryptoki)은 OASIS(구 RSA Laboratories) 표준으로, 암호화 토큰(HSM, 스마트카드, TPM)에 대한 플랫폼 독립적 C API를 정의합니다.
리눅스에서 PKCS#11은 HSM과 소통하는 사실상의 표준 인터페이스이며, p11-kit과 p11-kit-proxy를 통해 여러 HSM 벤더 모듈을 통합 관리할 수 있습니다.
# ━━━ PKCS#11 기본 설정 ━━━
# p11-kit 설치 (여러 PKCS#11 모듈 통합 관리)
sudo apt install p11-kit p11-kit-modules libengine-pkcs11-openssl
# HSM 벤더 PKCS#11 모듈 등록 (예: Thales Luna)
cat > /etc/pkcs11/modules/luna.module <<EOF
module: /usr/lib/libCryptoki2_64.so
EOF
# 등록된 토큰/슬롯 확인
p11tool --list-tokens
# Token 0:
# URL: pkcs11:model=Luna%20K7;manufacturer=SafeNet;serial=01234567;token=production
# Type: Hardware token
# Flags: RNG, Login required
# 토큰 내 키/인증서 목록
p11tool --login --list-all "pkcs11:token=production"
# Object 0:
# URL: pkcs11:...;object=tls-server-key;type=private
# Type: Private key (RSA-2048)
# ID: 01:23:45:67:89:ab
OpenSSL + HSM (PKCS#11 ENGINE / PROVIDER)
# ━━━ OpenSSL 1.x: PKCS#11 ENGINE 사용 ━━━
# HSM 내부에서 RSA-2048 키 쌍 생성 (키가 HSM을 떠나지 않음)
pkcs11-tool --module /usr/lib/libCryptoki2_64.so \
--login --pin "****" \
--keypairgen --key-type rsa:2048 \
--label "tls-server-key" --id 01
# CSR 생성 (OpenSSL ENGINE으로 HSM 키 참조)
openssl req -new -engine pkcs11 \
-keyform engine \
-key "pkcs11:token=production;object=tls-server-key;type=private" \
-subj "/CN=web.example.com" \
-out server.csr
# HSM 키로 인증서 서명
openssl x509 -req -engine pkcs11 \
-signkey "pkcs11:token=ca;object=ca-root-key;type=private" \
-in server.csr -out server.crt -days 365
# ━━━ OpenSSL 3.x: PKCS#11 PROVIDER 사용 ━━━
# openssl.cnf에 provider 등록
# [openssl_init]
# providers = provider_sect
# [provider_sect]
# pkcs11 = pkcs11_sect
# [pkcs11_sect]
# module = /usr/lib/ossl-modules/pkcs11.so
# pkcs11-module-path = /usr/lib/libCryptoki2_64.so
# activate = 1
openssl pkey -provider pkcs11 \
-in "pkcs11:token=production;object=tls-server-key;type=private" \
-pubout -out server-pub.pem
NGINX + HSM (TLS 개인키 보호)
# ━━━ nginx.conf — HSM에 저장된 개인키로 TLS 종단 ━━━
# OpenSSL ENGINE 방식 (OpenSSL 1.x)
ssl_engine pkcs11;
server {
listen 443 ssl;
server_name web.example.com;
ssl_certificate /etc/nginx/certs/server.crt;
# 개인키를 파일 대신 PKCS#11 URI로 지정
# → 키가 HSM 내부에 있으므로 서버 침해 시에도 키 추출 불가
ssl_certificate_key "engine:pkcs11:pkcs11:token=production;object=tls-server-key;type=private;pin-value=****";
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
}
커널 모듈 서명에 HSM 활용
# ━━━ 커널 모듈 서명 키를 HSM에 보관 ━━━
# 1. HSM 내부에서 서명 키 생성
pkcs11-tool --module /usr/lib/libCryptoki2_64.so \
--login --pin "****" \
--keypairgen --key-type rsa:4096 \
--label "kernel-module-signing" --id 10
# 2. 공개키만 추출 (DER 형식)
pkcs11-tool --module /usr/lib/libCryptoki2_64.so \
--login --pin "****" \
--read-object --type pubkey --label "kernel-module-signing" \
-o signing_key_pub.der
# 3. 커널 빌드 설정
# .config:
# CONFIG_MODULE_SIG=y
# CONFIG_MODULE_SIG_SHA512=y
# CONFIG_MODULE_SIG_KEY="pkcs11:token=build;object=kernel-module-signing;type=private"
# CONFIG_SYSTEM_TRUSTED_KEYS="certs/signing_key_pub.pem"
# 4. sign-file로 HSM 키를 사용하여 모듈 서명
scripts/sign-file sha512 \
"pkcs11:token=build;object=kernel-module-signing;type=private" \
certs/signing_key_pub.pem \
drivers/example/example.ko
# 5. 서명 확인
modinfo drivers/example/example.ko | grep sig
# sig_id: PKCS#7
# sig_hashalgo: sha512
# sig_key: AB:CD:EF:...
키 세레모니 (Key Ceremony)
HSM에 루트 CA 키를 생성하는 절차를 키 세레모니(Key Ceremony)라 합니다. 이 과정은 다수의 인증된 참여자가 물리적으로 입회하여 진행하며, 전체 과정이 영상 녹화되고 공증됩니다. 키 세레모니는 다음 단계로 구성됩니다.
HSM 고가용성과 백업
HSM은 단일 장애점(Single Point of Failure)이 될 수 있으므로, 프로덕션 환경에서는 반드시 고가용성(HA) 구성과 키 백업 전략이 필요합니다.
| 전략 | 방식 | 장점 | 주의사항 |
|---|---|---|---|
| HA 그룹 (Active-Active) | 동일 키를 복수 HSM에 복제, 로드밸런서가 분배 | 무중단 서비스, 자동 페일오버 | 동기화 지연 시 키 불일치 위험 |
| KEK 래핑 백업 | 마스터 키(KEK)로 암호화된 키 블롭을 외부 저장 | HSM 장애 시 다른 HSM에 복원 가능 | KEK 자체의 안전한 분산 보관 필수 |
| 클로닝 (동일 모델) | 동일 벤더·모델 HSM 간 전체 키 복제 | 완전한 동기화 보장 | 벤더 종속적, 동일 모델만 가능 |
| M-of-N 분할 백업 | 마스터 키를 N개 조각으로 분할, M개 모으면 복원 | 단일 백업 조각 탈취 무효화 | 관리자 간 협조 필수, 분실 위험 |
# ━━━ Thales Luna HA 그룹 설정 예시 ━━━
# HA 그룹 생성 (2개 HSM 파티션을 HA 쌍으로 구성)
lunacm:> hagroup creategroup \
-label "production-ha" \
-slot 1 \
-password "****"
# 두 번째 HSM을 HA 멤버로 추가
lunacm:> hagroup addmember \
-group "production-ha" \
-slot 2 \
-password "****"
# HA 그룹 상태 확인
lunacm:> hagroup listgroups
# HA Group Label: production-ha
# HA Group Number: 1
# HA Group Slot: 6
# Sync Status: Yes (All members synchronized)
# Members:
# Slot 1 (hsm-primary.internal) — Online
# Slot 2 (hsm-secondary.internal) — Online
# ━━━ 키 백업 (KEK 래핑) ━━━
# 백업 HSM에 키 블롭 내보내기
lunacm:> partition backup \
-slot 1 \
-password "****" \
-backupTokenSlot 3
# 백업에서 복원 (다른 Luna HSM)
lunacm:> partition restore \
-slot 4 \
-password "****" \
-backupTokenSlot 3
HSM 주요 활용 사례
- PKI / CA 루트키 보호 — 인증 기관(CA)의 루트 개인키를 HSM에 저장하여, 키 탈취로 인한 전체 PKI 체계 붕괴를 방지합니다. 대부분의 공인 CA는 오프라인 HSM에 루트키를 보관하고, 온라인 중간 CA만 서명에 사용합니다.
- TLS 서버 개인키 보호 — 웹 서버(NGINX, HAProxy)의 TLS 개인키를 HSM에 저장하면, 서버가 침해되어도 키 추출이 불가능합니다. PCI DSS 4.0에서는 카드 데이터를 처리하는 서버의 TLS 키를 HSM으로 보호하도록 권고합니다.
- 코드 서명 (Code Signing) — 리눅스 커널 모듈, 펌웨어 업데이트, 컨테이너 이미지에 대한 서명 키를 HSM에 보관하여 공급망 공격(Supply Chain Attack)을 방지합니다.
- 결제 시스템 (PCI HSM) — EMV 카드 발급, PIN 검증, 토큰화(Tokenization)에 사용되는 키는 PCI PIN/PTS 인증을 받은 결제 전용 HSM(예: Thales payShield)에서 관리됩니다.
- 데이터베이스 TDE (Transparent Data Encryption) — Oracle TDE, MySQL Enterprise 등에서 데이터 암호화 마스터키를 HSM에 저장하여, DBA가 키에 직접 접근하지 못하게 분리합니다.
- DNSSEC 서명 — DNS 존(Zone) 서명 키(ZSK)와 키 서명 키(KSK)를 HSM에서 관리하여, DNS 스푸핑 공격을 방지합니다.
- 시크릿 관리 (Vault Auto-Unseal) — HashiCorp Vault, AWS KMS 등의 시크릿 관리 시스템이 마스터키를 HSM에 위임하여 자동 봉인 해제(Auto-Unseal)를 구현합니다.
관련 문서
암호화 하드웨어 가속과 관련된 다른 주제를 더 깊이 이해하고 싶다면 다음 문서를 참고하세요.
외부 참고 자료
커널 공식 문서
- Kernel Crypto API — Documentation — 커널 암호화 프레임워크 공식 문서입니다
- Crypto API Architecture — Crypto API 아키텍처, tfm/request 모델, 알고리즘 선택 메커니즘 문서입니다
- Developing Cipher Algorithms — 커널 암호 알고리즘 드라이버 개발 가이드입니다
- User Space Interface (AF_ALG) — AF_ALG 소켓을 통한 사용자 공간 암호 인터페이스 문서입니다
- Inline Encryption (blk-crypto) — 블록 레이어 인라인 암호화(blk-crypto) 프레임워크 문서입니다
- XFRM Device Offload — IPsec 하드웨어 오프로드(xfrm_dev_offload) 인터페이스 문서입니다
- UACCE (Unified/User-space Accelerator Framework) — HiSilicon 가속기의 사용자 공간 접근 프레임워크 문서입니다
- Trusted and Encrypted Keys — TPM/CAAM 기반 trusted 키와 encrypted 키 사용법 문서입니다
CPU ISA 확장 (AES-NI, ARM CE, SHA-NI)
- Intel AES-NI Technical Reference — AES-NI 명령어 세트 기술 문서입니다
- Intel SHA Extensions — SHA-NI(SHA-1/SHA-256 하드웨어 가속) 명령어 기술 문서입니다
- ARM Architecture Reference Manual — ARMv8 Crypto Extensions(AES, SHA, PMULL) 포함 공식 아키텍처 레퍼런스입니다
- ARM Crypto Intrinsics — ARM 암호화 확장 명령어 인트린식 문서입니다
- x86 Crypto 가속 구현 소스 — AES-NI, AVX2, SHA-NI 등 x86 하드웨어 가속 드라이버 소스입니다
- ARM64 Crypto 가속 구현 소스 — ARM Crypto Extensions, NEON 기반 가속 드라이버 소스입니다
Intel QAT
- Intel QuickAssist Technology Overview — QAT 기술 개요 및 개발자 리소스입니다
- Intel QAT Software Documentation — QAT 소프트웨어 스택 설치·설정·API 가이드입니다
- QAT In-Tree Driver Release Notes — 커널 내장 QAT 드라이버 릴리스 노트입니다
- GitHub — intel/qatlib — QAT 사용자 공간 라이브러리(QATlib) 오픈소스 저장소입니다
- QAT 커널 드라이버 소스 — qat_4xxx, qat_6xxx, qat_c62x 등 QAT 커널 드라이버 소스입니다
- Intel QAT GEN6 Linux Driver (Phoronix) — QAT Gen6(qat_6xxx) 드라이버의 Linux 6.16 통합 소식입니다
AMD CCP / PSP / SEV
- AMD SEV Developer Resources — SEV/SEV-ES/SEV-SNP 개발자 문서 및 펌웨어 리소스입니다
- Using SEV with AMD EPYC Processors (PDF) — EPYC 프로세서에서 SEV 설정 및 튜닝 가이드입니다
- GitHub — AMDESE/AMDSEV — AMD SEV/SEV-SNP 참조 구현 및 테스트 도구 저장소입니다
- CCP 커널 드라이버 소스 — AMD CCP/PSP 커널 드라이버 소스입니다
- AMD EPYC 9005 SEV-SNP 성능 평가 (Phoronix) — EPYC Turin(Zen 5)에서 SEV-SNP 성능 영향 벤치마크입니다
NXP CAAM
- CAAM 커널 드라이버 소스 — NXP CAAM(SEC 엔진) 전체 드라이버 소스입니다
- AN12714 — i.MX Encrypted Storage Using CAAM Secure Keys (PDF) — CAAM 보안 키를 활용한 i.MX 스토리지 암호화 가이드입니다
- i.MX Linux Release Notes — i.MX 시리즈 최신 Linux BSP 릴리스 노트입니다
- GitHub — i.MX EdgeLock Enclave Demo — i.MX95 EdgeLock Enclave(ELE) 보안 데모 코드입니다
Marvell OCTEON CPT
- OcteonTX2/CN10K CPT 커널 드라이버 소스 — CPT v2/v3 PF/VF 드라이버 소스입니다
- Marvell OCTEON DPU Platform — OCTEON 10 DPU 제품 소개 및 사양입니다
- DPDK — Marvell cnxk Crypto PMD — DPDK 환경에서 CN10K CPT 가속기 사용법 문서입니다
- Marvell CN20K Linux Support (Phoronix) — 차세대 CN20K DPU의 Linux 지원 개시 소식입니다
HiSilicon SEC / HPRE / ZIP
- HiSilicon 가속기 커널 드라이버 소스 — SEC2, HPRE, ZIP 드라이버 전체 소스입니다
- GitHub — Kunpeng Accelerator Engine (KAE) Driver — Kunpeng 920/930 가속 엔진 사용자 공간 드라이버입니다
- HiSilicon Kunpeng Processor — Kunpeng ARM 서버 프로세서 제품 정보입니다
NIC 암호화 오프로드
- NVIDIA DOCA — IPsec Crypto Offload — ConnectX-7/BlueField DPU IPsec 크립토 오프로드 가이드입니다
- NVIDIA DOCA — IPsec Packet Offload — ConnectX/BlueField IPsec 패킷 오프로드(Full offload) 가이드입니다
- Kernel TLS Offload — 커널 kTLS 하드웨어 오프로드 인터페이스 문서입니다
- MACsec — Kernel Documentation — MACsec(IEEE 802.1AE) 커널 지원 문서입니다
SED/OPAL, HSM
- TCG Opal SSC Specification — TCG Opal 2.0 자체 암호화 드라이브 표준 사양입니다
- GitHub — sedutil — TCG Opal SED 관리 오픈소스 도구입니다
- PKCS#11 v3.0 Specification — HSM 표준 인터페이스(Cryptoki) 사양입니다
- GitHub — SoftHSMv2 — 개발·테스트용 소프트웨어 HSM 구현입니다
일반 참고
- Linux 커널 drivers/crypto/ — 하드웨어 가속기 드라이버 소스 전체 디렉터리입니다
- DPDK Crypto Device Drivers — DPDK 암호화 디바이스 드라이버 전체 목록 및 사용법입니다
- OpenSSL 3.x Provider — OpenSSL 3.x Provider 아키텍처 문서입니다. AF_ALG 또는 PKCS#11로 커널/HSM 가속기와 연동합니다
- GnuTLS — Hardware Security Modules — GnuTLS에서 PKCS#11을 통한 HSM 연동 가이드입니다