암호화 하드웨어 가속 (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 하드웨어 보안 모듈까지 포괄합니다.

전제 조건: Linux Crypto Framework (Crypto API) 문서를 먼저 읽으세요. 하드웨어 가속은 Crypto API의 tfm/request/scatterlist 개념을 이해한 상태에서 활용할 수 있습니다.
일상 비유: 이 주제는 전용 연산 장비 도입과 비슷합니다. 범용 도구(소프트웨어)로도 작업할 수 있지만, 특화 장비(하드웨어 가속기)를 사용하면 처리량과 효율이 크게 향상됩니다.

핵심 요약

  • 우선순위 기반 선택 — Crypto API가 등록된 구현 중 가장 높은 우선순위(Priority)를 자동 선택합니다.
  • SIMD 컨텍스트 제약 — kernel_fpu_begin/end 구간에서만 SIMD 명령어를 사용할 수 있습니다.
  • 폴백 메커니즘 — 하드웨어 사용 불가 시 소프트웨어 구현으로 자동 전환됩니다.
  • 오프로드 판단 — 패킷 크기, 처리량, 지연 요구에 따라 최적 오프로드 경로를 선택합니다.
  • 벤더 다양성 — Intel, AMD, ARM, HiSilicon, NXP, Marvell, Samsung 등 다양한 가속기를 지원합니다.

단계별 이해

  1. CPU ISA 확인
    CPUID/HWCAP으로 가속 명령어 지원 여부를 확인합니다.
  2. 드라이버 로드
    해당 가속 모듈이 적재되어 우선순위가 할당됩니다.
  3. API 투명성
    Crypto API가 자동으로 최적 구현을 선택합니다.
  4. 벤치마크 검증
    tcrypt 또는 openssl speed로 실제 성능을 측정합니다.

H/W 가속 상세

현대 리눅스 시스템에서 암호화 연산은 IPsec 터널, dm-crypt 디스크 암호화, kTLS 등 다양한 경로에서 대규모로 발생합니다. 소프트웨어만으로 이를 처리하면 CPU 사용률이 급증하고 처리량이 제한되므로, 하드웨어 가속은 보안과 성능을 동시에 확보하는 핵심 수단입니다. 커널이 활용하는 하드웨어 가속은 크게 네 가지 유형으로 나뉩니다.

리눅스 Crypto API는 이 모든 유형을 단일 인터페이스 뒤에 추상화합니다. 각 드라이버는 자신의 priority 값을 등록하고, API는 동일 알고리즘의 구현 중 가장 높은 priority를 자동 선택합니다. 따라서 사용자 코드나 상위 서브시스템(IPsec, dm-crypt 등)은 하드웨어 유형을 의식하지 않아도 최적의 구현을 투명하게 활용할 수 있습니다.

IPsec (xfrm) dm-crypt kTLS / MACsec Crypto API — Priority 기반 자동 선택 CPU ISA 확장 AES-NI · SHA-NI · ARM CE PCI 가속기 Intel QAT · AMD CCP SoC 임베디드 엔진 NXP CAAM · HiSilicon SEC NIC 인라인 오프로드 CX-7 · E810 · BF-3 ~ns 지연 · 인라인 Priority 300~400 ~μs 지연 · 배치 오프로드 Priority 200~4001 ~μs 지연 · SoC 내장 Priority 3000~4001 ~ns 지연 · 와이어 속도 커널 우회 (N/A) ※ Priority 값이 높을수록 우선 선택됩니다. NIC 인라인 오프로드는 Crypto API를 거치지 않고 NIC 하드웨어가 직접 처리합니다.
유형 예시 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)에서 동작합니다:

명령어동작설명
AESENC1라운드 암호화ShiftRows → SubBytes → MixColumns → AddRoundKey
AESENCLAST마지막 라운드 암호화ShiftRows → SubBytes → AddRoundKey (MixColumns 생략)
AESDEC1라운드 복호화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로 가속합니다. 각 모드의 병렬화 특성에 따라 성능이 크게 달라집니다:

모드커널 드라이버 이름병렬 처리특성
ECBecb-aes-aesni완전 병렬각 블록이 독립적이라 파이프라인(Pipeline) 최대 활용
CBC 암호화cbc-aes-aesni직렬 (체인)이전 블록 암호문이 다음 블록 입력에 필요
CBC 복호화cbc-aes-aesni완전 병렬복호화는 모든 암호문 블록을 이미 알고 있으므로 병렬 가능
CTRctr-aes-aesni완전 병렬카운터 값이 독립적, IPsec/TLS에서 주력으로 사용
XTSxts-aes-aesni완전 병렬디스크 암호화(dm-crypt, LUKS) 표준 모드
GCMgcm-aes-aesniAES 병렬 + GHASHAEAD, 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) 명령어를 함께 사용하여 두 연산을 모두 하드웨어로 가속합니다:

AES-GCM 동작 구조 Counter (J₀+i) AES-NI ENC AESENC × 10 rounds XOR ⊕ Plaintext Ciphertext AAD 추가 인증 데이터 XOR ⊕ H_i GHASH (GF(2¹²⁸)) PCLMULQDQ 가속 H_{i+1} GHASH Final ⊕ AES_ENC(J₀) Auth Tag (128-bit) ← 기밀성 ← 무결성/인증
AES-GCM: CTR 모드(기밀성) + GHASH(인증)를 병렬 수행
/* 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 모듈 아키텍처 arch/x86/crypto/ C Glue 계층 aesni-intel_glue.c ghash-clmulni-intel_glue.c 역할: 알고리즘 등록, setkey, FPU 관리 어셈블리 최적화 계층 aesni-intel_asm.S (ECB/CBC/CTR) aes_ctrby8_avx-x86_64.S (CTR by8) aesni-intel_avx-x86_64.S (GCM) ghash-clmulni-intel_asm.S, aes-gcm-aesni-x86_64.S
/* 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 + AVX2YMM (256-bit)2블록~8블록
VAES + AVX-512ZMM (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/sAES-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/sCTR + GHASH 인터리빙
XTS(AES-256)aesni~2.5 GB/s~3.5 GB/stweak 연산 + 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 내부 동작

kernel_fpu_begin/end 동작 흐름 Process Context (프로세스 문맥) kernel_fpu_begin() preempt_disable() FPU 상태 저장 (XSAVE) task→thread.fpu.state SIMD 명령어 사용 가능 AESENC, PCLMULQDQ... kernel_fpu_end() → XRSTOR + preempt_enable() Softirq / Hardirq Context (인터럽트 문맥) kernel_fpu_begin() 불가! irq_fpu_usable() == false SIMD 래퍼 동작 cryptd kthread로 위임 kthread에서 FPU 사용 process context → 안전
Process context에서는 직접 FPU 사용, 인터럽트 context에서는 cryptd kthread로 위임
/* 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_FALLBACK mask를 사용하여 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용)을 위한 전용 명령어를 제공합니다:

명령어동작설명
AESEAES 단일 라운드 암호화SubBytes + ShiftRows (AddRoundKey 별도)
AESDAES 단일 라운드 복호화InvSubBytes + InvShiftRows
AESMCAES MixColumns암호화 라운드의 열 혼합 단계
AESIMCAES 역 MixColumns복호화 라운드의 역 열 혼합
SHA1C/P/MSHA-1 라운드Choose/Parity/Majority 함수별 4라운드 처리
SHA1HSHA-1 해시 고정 회전SHA-1 스케줄링 회전 연산
SHA1SU0/1SHA-1 스케줄 업데이트메시지 스케줄 확장
SHA256H/H2SHA-256 라운드SHA-256 압축 함수 4라운드 처리
SHA256SU0/1SHA-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-ceCRYPTO_AES_ARM64_CE_BLKecb/cbc/ctr/xts(aes)300ARM CE
sha256-arm64-ceCRYPTO_SHA256_ARM64_CEsha256, sha224300ARM CE
sha512-arm64-ceCRYPTO_SHA512_ARM64_CEsha512, sha384300ARM CE
ghash-ceCRYPTO_GHASH_ARM64_CEghash300PMULL
aes-arm64-neon-blkCRYPTO_AES_ARM64_NEON_BLKecb/cbc/ctr/xts(aes)200NEON/ASIMD
sha256-arm64CRYPTO_SHA256_ARM64sha256150NEON
aes-genericCRYPTO_AESaes100없음

모듈 등록과 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 / SM4EKEYSM4 암호화/키 확장중국 국가 표준 블록 암호
AESE / AESMC (SVE2)벡터 길이만큼 AES 병렬 처리256비트 SVE → 2블록 동시
RAX1SHA-3 rotate-and-XORKeccak 순열 가속
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-CBCaes-generic~120 MB/s~130 MB/s1.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-256sha256-generic~95 MB/s~100 MB/s1.0×
sha256-ce~850 MB/s~1.1 GB/s~11×
AES-256-GCMgcm(aes-generic)~80 MB/s~90 MB/s1.0×
gcm(aes-ce) + ghash-ce~1.5 GB/s~1.9 GB/s~21×
ARM64 Crypto 모듈 Priority 선택 흐름 crypto_alloc_skcipher("cbc(aes)") CE feature available? Yes cbc-aes-ce priority 300 No NEON available? Yes cbc-aes-neon priority 200 No aes-generic priority 100
Crypto API는 등록된 구현 중 priority가 가장 높은 모듈을 자동 선택합니다

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)2016SHA1RNDS4, SHA1NEXTE, SHA256RNDS2, SHA256MSG1/2sha256-ni300
Intel Ice Lake2019동일sha256-ni300
AMD Zen (Ryzen/EPYC)2017동일sha256-ni300
# 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-ssse3SSSE3150기본 SIMD 최적화
sha256-avxAVX160256비트 레지스터 활용
sha256-avx2AVX2170multi-buffer 4-way 병렬
sha512-avx2AVX2170SHA-512 multi-buffer
sha256-niSHA-NI300전용 하드웨어 명령어
/* 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-avx2sm3-avx가 이를 활용합니다. SM4는 국제 표준 ISO/IEC 18033-3:2010에도 등록되어 있으며, 중국 시장 제품에서 AES 대신 필수적으로 사용됩니다.

명령어기능CPU 최소 요구커널 모듈
VSM3MSG1 / VSM3MSG2SM3 해시 메시지 확장Sapphire Rapids (4세대 Xeon)sm3-avx
VSM3RNDS2SM3 라운드 연산 (2라운드/1명령어)Sapphire Rapidssm3-avx
VSM4KEY4SM4 키 확장 (4라운드)Sapphire Rapidssm4-aesni-avx2
VSM4RNDS4SM4 암복호화 (4라운드/1명령어)Sapphire Rapidssm4-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를 확인하여 현재 시스템에서 어떤 구현이 활성화되어 있는지 파악할 수 있습니다.

x86 Crypto 구현 Priority 스택 AES AES-NI (400) AES-NI+AVX2 XTS (250) aes-generic (100) SHA-256 SHA-NI (300) sha256-avx2 (170) sha256-avx (160) sha256-ssse3 (150) sha256-generic (100) CRC32C crc32c-intel (200) crc32c-generic (100) Priority: 높을수록 우선 선택 — 전용 HW(300~400) > AVX2(170) > AVX(160) > SSSE3(150) > Generic(100)
x86 암호화 구현은 CPU 기능에 따라 계층적으로 등록되며, 가장 높은 priority가 자동 선택됩니다

네트워크 암호화 오프로드

네트워크 암호화를 NIC 하드웨어에 오프로드하면 CPU 부하를 대폭 줄이고 와이어 속도에 가까운 암호화 처리량을 달성할 수 있습니다. 커널은 IPsec, kTLS, MACsec 세 가지 프로토콜에서 NIC 암호화 오프로드를 지원하며, 각각 다른 오프로드 레벨과 드라이버 콜백을 제공합니다.

IPsec 인라인 오프로드

IPsec 오프로드는 xfrm_dev_offload 구조체를 통해 두 가지 모드를 지원합니다:

모드상수NIC 처리 범위CPU 역할
Crypto offloadXFRM_DEV_OFFLOAD_CRYPTOESP 암복호화만ESP 헤더 구성, 패킷 라우팅(Routing)
Packet offloadXFRM_DEV_OFFLOAD_PACKETESP 암복호화 + 헤더 삽입/제거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 offloadRX offload지원 암호
NVIDIA ConnectX-6+/7mlx5TLS 1.2/1.3TLS 1.2/1.3AES-128/256-GCM
Broadcom BCM57504bnxtTLS 1.2AES-128-GCM
Intel E810iceTLS 1.2/1.3TLS 1.2/1.3AES-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 TXMACsec 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
네트워크 암호화 오프로드 경로 비교 Application (IPsec/TLS) SW 경로 Crypto offload Packet offload CPU: Crypto API (AES-NI / ARM CE) CPU: ESP 헤더 구성 CPU: ESP 헤더 구성 (암호화는 NIC에 위임) CPU: SA/SP 정책만 (모든 처리를 NIC에 위임) NIC: 패킷 전송만 NIC: 암복호화 수행 NIC: ESP 전체 처리 Wire (네트워크)
SW 경로는 CPU가 모든 처리를 담당하고, Crypto offload는 암복호화만, Packet offload는 ESP 전체를 NIC에 위임합니다

스토리지 인라인 암호화

스토리지 인라인 암호화(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-XTS512비트 (2×256)Android FBE 기본대부분의 ICE가 지원
AES-128-CBC-ESSIV256비트레거시 FDEIV 예측 방지용 ESSIV
Adiantum256비트CE 없는 저가형 기기ChaCha 기반, SW 전용
SM4-XTS256비트중국 시장 규정SM4 블록 암호 + XTS

인라인 암호화 엔진

주요 스토리지 인터페이스별 인라인 암호화 엔진:

엔진스토리지커널 드라이버알고리즘keyslot 수
Qualcomm ICEUFSufs-qcom + qcom-iceAES-256-XTS보통 32개
Samsung FMPUFSufs-exynosAES-256-XTS8~16개
MediaTek CQHCIeMMCcqhciAES-256-XTS32개
NVMe (TCG Opal)NVMe SSDnvmeAES-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 오버헤드를 완전히 제거합니다.

blk-crypto 인라인 암호화 스택 fscrypt (FBE) dm-crypt (--inline) dm-default-key blk-crypto 프레임워크 blk_crypto_key + keyslot 관리 ICE HW 지원? Yes ICE 하드웨어 와이어 속도 암호화 No SW Fallback Crypto API (AES-NI/CE) 스토리지 디바이스 (UFS / eMMC / NVMe) ICE 경로: CPU 0% + 와이어 속도 | SW Fallback: CPU 암호화 오버헤드 발생 (dm-crypt 동등)
blk-crypto는 ICE 지원 여부에 따라 하드웨어 또는 소프트웨어 암호화 경로를 자동 선택합니다

암호화 오프로드 결정 가이드

다양한 암호화 오프로드 옵션 중 워크로드 특성에 맞는 방식을 선택하는 것이 중요합니다. CPU ISA 가속으로 충분한 경우 별도 가속기를 도입할 필요가 없고, 반대로 대규모 암호 처리에서는 전용 가속기가 CPU 자원을 확보해줍니다.

룩어사이드 오프로드와 인라인 오프로드

암호화 하드웨어 오프로드는 데이터가 가속기를 거치는 방식에 따라 룩어사이드 오프로드(Lookaside Offload)인라인 오프로드(Inline Offload) 두 가지 아키텍처로 나뉩니다. 룩어사이드 오프로드는 호스트 CPU가 암호화 요청을 명시적으로 PCIe 가속기에 전송하고 비동기로 결과를 받는 방식이며, 인라인 오프로드는 NIC이나 스토리지 컨트롤러가 데이터 경로(Data Path) 상에서 투명하게 암복호화를 수행하는 방식입니다. 두 아키텍처는 CPU 개입 수준, 지연 시간 특성, 유연성이 근본적으로 다르므로 워크로드에 맞는 선택이 필요합니다.

룩어사이드 오프로드 동작 원리

룩어사이드 오프로드에서 호스트 CPU는 암호화가 필요한 시점에 직접 가속기에 작업을 제출합니다. 전형적인 처리 흐름은 다음과 같습니다:

  1. 요청 구성: CPU가 암호 알고리즘, 키, IV, 입출력 버퍼 주소를 포함한 요청 디스크립터(Request Descriptor)를 구성합니다.
  2. Ring 제출: 디스크립터를 요청 링(Request Ring)에 기록하고 MMIO 도어벨(Doorbell)을 써서 가속기에 새 작업을 알립니다.
  3. DMA 전송: 가속기가 PCIe DMA로 호스트 메모리에서 입력 데이터를 읽어옵니다.
  4. 암호 연산: 가속기 내부의 암호 엔진(Crypto Engine)이 연산을 수행합니다. 이 동안 CPU는 다른 작업을 수행할 수 있습니다.
  5. 결과 기록: 연산 결과를 DMA로 호스트 메모리에 기록하고, 완료 링(Completion Ring)에 응답 디스크립터를 씁니다.
  6. 완료 통지: MSI-X 인터럽트 또는 폴링(Polling)으로 CPU가 완료를 감지하고 콜백(Callback)을 실행합니다.

커널 Crypto API에서는 이 비동기 흐름을 -EINPROGRESS 반환값으로 표현합니다. 호출자(IPsec, kTLS, dm-crypt 등)는 crypto_skcipher_encrypt() 호출 후 -EINPROGRESS를 받으면 완료 콜백을 기다리며, 가속기가 작업을 마치면 콜백이 호출되어 결과를 전달합니다. 이 패턴 덕분에 CPU 코어 하나가 수백~수천 개의 암호 요청을 동시에 가속기에 위임할 수 있어, SSL/TLS 프록시나 VPN 게이트웨이(VPN Gateway)처럼 대량의 동시 암호 세션을 처리하는 워크로드에 적합합니다.

룩어사이드 오프로드 vs 인라인 오프로드 데이터 경로 룩어사이드 오프로드 (Lookaside) Host CPU IPsec · kTLS · dm-crypt · 사용자 ① 디스크립터 기록 Request Ring (큐) ② PCIe DMA 읽기 PCIe Bus (DMA) PCIe 가속기 카드 ③ Crypto Engine 암호 연산 (CPU 해방) ④ DMA 결과 쓰기 PCIe Bus (DMA) Completion Ring ⑤ 완료 통지 + 콜백 Host CPU 콜백 실행 CPU가 오프로드 시점을 결정 인라인 오프로드 (Inline) 애플리케이션 일반 send/recv · 블록 I/O 커널 네트워크/스토리지 스택 SA · 키 설정만 관리 (제어 경로) 평문 데이터 NIC / 스토리지 컨트롤러 Crypto Engine 내장 와이어 경로에서 투명하게 암복호화 암호문 데이터 네트워크 / 스토리지 매체 이더넷 · NVMe · UFS 데이터 경로에 통합 QAT · CCP · NITROX · CAAM IPsec NIC · kTLS NIC · ICE
룩어사이드 오프로드는 CPU가 요청/완료 링을 통해 가속기와 비동기로 통신하며, 인라인 오프로드는 데이터 경로상의 NIC/컨트롤러가 투명하게 암복호화를 수행합니다

Host CPU 중심 룩어사이드

Host CPU 중심 룩어사이드(Host CPU-centric Lookaside)는 범용 x86_64 또는 ARM64 서버에 개별 PCIe 카드 형태의 가속기를 장착하는 모델입니다. CPU와 가속기가 물리적으로 분리되어 있으며, 모든 데이터 교환이 PCIe 버스의 DMA를 통해 이루어집니다. 이 모델의 핵심은 기존 서버 인프라를 변경하지 않고 PCIe 슬롯에 카드만 추가하여 암호화 가속 능력을 확보할 수 있는 점입니다. 전용 가속기 카드뿐 아니라, SoC 기반 DPU/SmartNIC을 PCIe 카드 형태로 서버에 장착하여 호스트 CPU의 룩어사이드 가속기로 활용하는 방식도 이 모델에 포함됩니다.

전형적인 구성과 데이터 경로는 다음과 같습니다:

  1. 물리적 분리: CPU(호스트)와 가속기(카드)가 PCIe 링크로 연결됩니다. 카드는 자체 SRAM, 마이크로엔진, DMA 컨트롤러를 보유합니다.
  2. PCIe DMA 오버헤드: 모든 입출력 데이터가 PCIe TLP(Transaction Layer Packet)로 전송되므로, 소량 데이터(~512B 이하)에서는 DMA 설정(Setup) 비용이 암호 연산 자체보다 클 수 있습니다.
  3. MMIO 도어벨: 요청 제출 시 CPU가 카드의 BAR(Base Address Register) 영역에 MMIO 쓰기를 수행하여 새 작업을 알립니다.
  4. 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 중심 모델과의 핵심 차이점:

  1. 내부 버스 접근: PCIe TLP 오버헤드가 없어 요청 제출~완료 지연이 크게 낮습니다. 캐시 코히어런트(Cache Coherent) 인터커넥트를 사용하는 SoC에서는 DMA 없이 공유 메모리로 직접 접근하기도 합니다.
  2. HW 이벤트 스케줄러 연동: Marvell OCTEON의 SSO(Schedule/Synchronize/Order)처럼, 암호 연산 완료 시 CPU 인터럽트 없이 하드웨어가 다음 처리 단계로 작업을 자동 전달합니다. 이는 Host CPU 중심 모델에서 불가능한 고유 기능입니다.
  3. LMTST/원자적 제출: OCTEON CN10K에서는 LMTST(Large Memory Transaction Store)라는 ARM 확장 명령으로 디스크립터를 원자적으로 제출하여, MMIO 도어벨 단계를 생략합니다.
  4. SoC 종속성: 특정 SoC 플랫폼에서만 사용 가능하며, 범용 x86 서버에 추가 장착할 수 없습니다.
ℹ️

대표 하드웨어: Marvell OCTEON CPT(CPT 섹션 — SSO 연동, LMTST 제출), NXP CAAM(CAAM 섹션 — Job Ring 기반), HiSilicon SEC2(SEC2 섹션), Samsung Exynos SSS. Intel QAT Gen4 이후(4세대 Xeon 내장 RCiEP)도 CPU 다이에 통합되어 SoC 중심 모델에 가까워지고 있습니다.

Host CPU 중심 vs SoC 중심 룩어사이드 비교

Host CPU 중심 vs SoC 중심 룩어사이드 아키텍처 Host CPU 중심 (PCIe 카드) 호스트 서버 (x86_64 / ARM64) CPU 코어 Xeon, EPYC, ... 호스트 메모리 Request/Completion Ring MMIO 도어벨 ↓ ↑ MSI-X 인터럽트 DMA ↕ PCIe Bus (Gen3/4/5) PCIe 카드 (가속기 또는 DPU) Crypto Engine AES, SHA, RSA DMA 컨트롤러 SRAM 내부 물리적 분리 — PCIe 슬롯 장착/교체 가능 ✓ 기존 서버에 카드 추가만으로 가속 확보 ✓ SR-IOV로 VM별 격리 가능 △ PCIe DMA 지연 ~2-5 μs (소량 데이터 비효율) 예: QAT 카드, NITROX V, OCTEON DPU, AMD CCP SoC 중심 (내부 통합) 네트워크 SoC (단일 다이) ARM 코어 Cortex-A72/78 공유 메모리 (DDR) 캐시 코히어런트 접근 SoC 내부 인터커넥트 (AMBA / CCN / IOBN) Crypto Engine CPT / CAAM / SEC2 SSO 이벤트 스케줄러 NIX 네트워크 I/F PCIe 불필요 — 내부 버스 직접 연결 LMTST 원자적 제출 HW 이벤트 자동 전달 인라인 모드 겸용 이더넷 포트 ✓ 내부 버스 — 지연 ~0.5-1 μs (PCIe 대비 2-5배 빠름) ✓ HW 이벤트 스케줄러(SSO) 연동 → CPU 인터럽트 제거 △ 특정 SoC 플랫폼에 종속 (범용 서버 불가) 예: OCTEON CPT, NXP CAAM, HiSilicon SEC2
Host CPU 중심 모델은 PCIe 카드를 범용 서버에 추가하여 가속하고, SoC 중심 모델은 내부 인터커넥트로 직접 연결되어 지연이 낮고 HW 이벤트 연동이 가능합니다
특성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 패킷<512BCPU ISA (AES-NI/CE)오프로드 setup 비용 > 암호화 비용
웹 HTTP/2 TLS1~16 KBCPU ISA 또는 kTLS NICkTLS는 대역폭(Bandwidth) 높을 때 유리
IPsec VPN 터널1.4 KB (MTU)NIC offload패킷 수가 많아 CPU 부하 누적
디스크 I/O (4KB)4~128 KBICE 또는 CPU ISAICE 있으면 무조건 ICE 사용
SSL/TLS 프록시다양QAT / CCP수천 연결의 핸드셰이크 + 벌크 암호화
배치 파일 암호화MB~GBQAT / CCPCPU 코어를 다른 작업에 활용
ℹ️

일반적인 경험칙: (1) 스토리지 암호화는 ICE가 있으면 항상 ICE 사용, (2) 네트워크 암호화는 10G 이상에서 NIC offload 고려, (3) 그 외 대부분의 경우 AES-NI/ARM CE만으로 충분합니다. QAT/CCP 같은 PCI 가속기는 SSL 프록시나 VPN 게이트웨이처럼 암호화가 주 워크로드인 경우에 도입 효과가 큽니다.

종합 비교

특성CPU ISAPCI 가속기NIC 인라인스토리지 ICE
지연 시간최저 (~ns)중간 (~μs)낮음없음 (HW)
처리량~10 GB/s/코어~100 Gbps라인 레이트라인 레이트
CPU 부하높음없음없음없음
알고리즘 범위모든 알고리즘넓음제한적AES-XTS
추가 비용없음가속기 카드지원 NICSoC 내장
설정 복잡도자동드라이버 설정NIC + xfrminlinecrypt 옵션
대표 사례dm-crypt, TLSSSL 프록시IPsec 게이트웨이Android FBE
💡

SmartNIC/DPU 오프로드: NVIDIA BlueField, AMD Pensando 같은 DPU는 NIC 인라인 오프로드와 PCI 가속기의 특성을 결합합니다. IPsec packet offload + OVS 룰 처리를 DPU에서 수행하여 호스트 CPU를 완전히 해방할 수 있습니다. 상세는 SmartNIC/DPU 암호화 오프로드를 참고하세요.

암호화 오프로드 결정 플로차트 암호화 워크로드 분석 스토리지 암호화? Yes 스토리지 ICE UFS/eMMC/NVMe No 네트워크 10G+? Yes NIC 오프로드 IPsec/kTLS No 대량 배치 처리? Yes PCI 가속기 QAT / CCP No CPU ISA 가속 AES-NI / ARM CE 대부분의 범용 워크로드는 CPU ISA 가속(AES-NI/ARM CE)만으로 충분 — 특수 요구사항에만 전용 가속기 도입
워크로드 특성에 따라 적합한 오프로드 방식을 단계적으로 결정합니다

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 세대폼 팩터대표 제품 / 플랫폼PCIePCI 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 폼 팩터 진화: 개별 카드 → 칩셋 내장 → CPU 다이 통합 Gen 1 — 개별 PCIe 카드 DH895xCC (8950 카드) PCIe 2.0 ×8 슬롯 장착 ~20 Gbps · 32 VF 외부 전원 필요 Gen 2 — 칩셋/SoC 내장 C62x (PCH) / C3xxx (SoC) 칩셋 or Atom SoC에 통합 ~50 Gbps · 48 VF (C62x) 카드(8960/8970)도 병행 Gen 4 — CPU 다이 통합 4xxx (SPR/EMR) — RCiEP CPU 패키지 내부 통합 ~200 Gbps/소켓 · 64 VF 최대 4 EP/CPU, 2서비스 Gen 5/6 — 최신 420xx/6xxx — RCiEP Xeon 6 / Diamond Rapids Gen5: 라이브 마이그레이션 Gen6: 3서비스 동시 세대별 핵심 차이 Gen 1 PCIe 슬롯 장착 별도 전원 필요 서버 간 이동 가능 Gen 2 칩셋 PCH에 통합 별도 전원 불필요 카드형도 병행 판매 Gen 4 CPU 다이에 직접 통합 RCiEP (PCIe 버스 불필요) SM2/SM3/SM4 지원 Gen 5/6 엔진 증가, 라이브 마이그레이션 Gen6: sym+asym+dc 동시 무선 모드(Wireless)
QAT는 개별 PCIe 카드에서 시작하여 칩셋 내장을 거쳐 CPU 다이 통합으로 진화하며, 세대마다 처리량과 기능이 크게 향상되었습니다

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 내부 하드웨어 블록 다이어그램 (Gen 4 기준) Intel Xeon Scalable CPU 패키지 (RCiEP — Root Complex Integrated Endpoint) 커널 Crypto API / DPDK QAT 드라이버 (PF) VF 0~15 VFIO (VM 패스스루) QATlib (유저) DPDK PMD (유저) Ring Pair 계층 — Request Ring(제출) + Response Ring(완료) PF당 Ring Pair 풀 | VF당 4개 Ring Pair 할당 | 메모리 매핑(MMIO) 기반 doorbell 쓰기 디스크립터: 입출력 버퍼 포인터 + 알고리즘 opcode + 키/IV 컨텍스트 주소 → AE에 DMA로 전달 중재기(Arbiter) — Ring Pair → Accelerator Engine 라운드로빈 할당 Accelerator Engine(AE) 풀 AE 0 | AE 1 | AE 2 | AE 3 | ... | AE N — 각 AE가 독립적으로 디스크립터 실행 (마이크로코드 기반) Gen1: ~2 AE | Gen2: ~10 AE | Gen4: 최대 16 AE (EP당) | Gen6: 더 확장 Cipher Slice AES(CBC/GCM/XTS), SM4, 3DES Auth Slice SHA(1/256/512), SM3, HMAC PKE Slice RSA, ECDSA, DH, SM2 Compression Slice Deflate, LZ4, LZ4s (dc 서비스) 서비스 구성: Gen4는 cy(대칭+비대칭) 또는 dc(압축) 중 최대 2서비스 조합 | Gen6는 sym+asym+dc 3서비스 동시 가능 sysfs 경로: /sys/bus/pci/devices/<BDF>/qat/cfg_services — "sym;asym" / "dc" / "sym;dc" 등
QAT는 Ring Pair → 중재기 → Accelerator Engine → Slice 4계층으로 구성되며, AE가 마이크로코드를 실행하여 각 Slice의 연산 유닛을 제어합니다

QAT Crypto 요청 처리 흐름 (소프트웨어 경로)

커널 Crypto API에서 QAT 하드웨어까지의 암호화 요청이 어떻게 전달되고 완료되는지를 소프트웨어 관점에서 추적합니다. 사용자 공간 또는 커널 서브시스템(IPsec, kTLS, dm-crypt)이 crypto_skcipher_encrypt() 같은 Crypto API를 호출하면, priority 기반으로 QAT 드라이버가 선택되고, Ring Pair를 통해 하드웨어에 요청이 전달됩니다.

QAT Crypto 요청 처리 흐름 (소프트웨어 관점) ① 호출자 IPsec · kTLS · dm-crypt · 사용자 ② Crypto API 디스패치 crypto_skcipher_encrypt() priority 4001 → qat_aes_cbc 선택 ③ QAT 드라이버 진입 qat_alg_skcipher_encrypt() 디스크립터 구성: opcode + 키 + IV + SG ④ Ring Pair 제출 adf_send_message() Request Ring에 디스크립터 기록 + doorbell Ring Full → -ENOSPC backlog 큐 또는 -EBUSY 반환 ⑤ HW 실행 Arbiter → AE → Slice (DMA) -EINPROGRESS 반환 (비동기) ⑥ 완료 처리 Response Ring 폴링 / 인터럽트 콜백 호출 → 호출자에 결과 전달 단계별 핵심 자료구조 · 함수 ① 호출자 → Crypto API struct skcipher_request *req crypto_alloc_skcipher("cbc(aes)", 0, 0) ② Crypto API 내부 crypto_alg_lookup() → priority 4001 선택 tfm→__crt_alg→cra_driver_name = "qat_aes_cbc" ③ QAT 드라이버 struct icp_qat_fw_la_bulk_req — FW 요청 구조체 qat_alg_skcipher_encrypt() → DMA 매핑 scatterlist → flat buffer 변환 (필요 시) ④ Ring Pair 제출 struct adf_etr_ring_data — 링 메타데이터 adf_send_message() → MMIO doorbell 쓰기 tail 포인터 갱신 → FW가 head에서 소비 ⑤ HW 처리 (CPU 관여 없음) AE 마이크로코드: 디스크립터 파싱 → Slice 할당 DMA read(입력) → 연산 → DMA write(출력) 결과 디스크립터를 Response Ring에 기록 ⑥ 완료 경로 (2가지) 폴링 모드: tasklet이 Response Ring tail 확인 인터럽트 모드: MSI-X → adf_isr → tasklet qat_alg_skcipher_encrypt_cb() → req→complete() DMA 언매핑 → skb/bio에 결과 기록 DPDK PMD: 유저 공간 폴링 (커널 우회)
Crypto API 호출부터 QAT HW 실행, 완료 콜백까지의 전체 소프트웨어 경로입니다. Ring이 포화되면 backlog 큐로 재시도하며, 완료는 폴링 또는 MSI-X 인터럽트로 감지합니다

커널 소스 분석: 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)
출시 연도201320172023 (SPR)2024 (GNR)2025~(CWF/DMR)
폼 팩터PCIe 카드PCH 내장 + 카드CPU 내장 (RCiEP)CPU 내장 (RCiEP)CPU 내장 (RCiEP)
대칭키 알고리즘AES, 3DES, DESAES, 3DESAES, SM4, 3DESAES, SM4, 3DESAES, SM4, 3DES
해시 알고리즘SHA-1/256/512SHA-1/256/512SHA-1/256/512, SM3SHA-1/256/512, SM3SHA-1/256/512, SM3
비대칭키 알고리즘RSA, DHRSA, DH, ECDSARSA, DH, ECDSA, SM2RSA, DH, ECDSA, SM2RSA, DH, ECDSA, SM2
압축DeflateDeflateDeflate, LZ4, LZ4sDeflate, LZ4, LZ4sDeflate, LZ4, LZ4s
동시 서비스11최대 2 (cy+dc)최대 2 (cy+dc)최대 3 (sym+asym+dc)
SR-IOV VF3216/PF (최대 48)16/PF (최대 64)16/PFTBD
라이브 마이그레이션Linux 6.10+지원 예정
KconfigQAT_DH895xCCQAT_C62X, QAT_C3XXXQAT_4XXXQAT_4XXXQAT_6XXX
커널 최소 버전4.x4.x5.186.86.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 TX 경로에서 QAT 암호화 오프로드 사용자 공간 sendfile() / write() kTLS TX (tls_sw) TLS 레코드 프레이밍 헤더 + 페이로드 + 태그 구성 Crypto API crypto_aead_encrypt() AES-128/256-GCM QAT HW AES-GCM 암호화 DMA 기반 · CPU 해방 TCP 전송 암호화된 레코드 kTLS 오프로드 방식 비교 TLS_SW (소프트웨어) CPU가 AES-NI로 암호화 sendfile 제로카피 지원 모든 NIC에서 동작 TLS_SW + QAT QAT가 Crypto API로 암호화 CPU 해방 + sendfile 지원 QAT 있으면 자동 선택 TLS_HW (NIC 인라인) NIC가 와이어 속도로 암호화 최저 지연 + 최고 처리량 특정 NIC만 지원 (mlx5 등)
kTLS TX 경로에서 QAT는 Crypto API를 경유하여 TLS 레코드를 암호화합니다. NIC 인라인(TLS_HW)과 달리 모든 NIC에서 동작하며, 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 사용 시 주의사항

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 생존 여부를 주기적으로 확인하고, 장애 감지 시 자동으로 디바이스를 리셋·재초기화하는 복구 경로를 제공합니다.

QAT 디바이스 상태 머신과 Heartbeat 복구 경로 STARTED 정상 동작 · 요청 처리 중 HB 정상 (매 500ms) HB 실패 HEARTBEAT_FAIL FW 무응답 감지 새 요청 거부 시작 리셋 시작 RESETTING adf_dev_reset() 진행 중 요청 -EIO 반환 RESTARTING FW 재로드 · Ring 재설정 Crypto API 재등록 복구 완료 → 정상 동작 재개 Heartbeat 메커니즘 상세 정상 경로 • adf_heartbeat_check_ctrs(): FW 카운터 변화 감시 (매 HB_TIMER 주기) • FW는 내부 카운터를 주기적으로 증가 → 드라이버가 이전 값과 비교 • 카운터 변화 있음 → 정상 · 타이머 재설정 장애 복구 경로 • 카운터 미변화 → adf_notify_fatal_error() → 이벤트 통지 • adf_dev_reset(): 모든 Ring 정리, VF 통지, FW 정지 • adf_dev_init() + adf_dev_start(): FW 재로드, Ring 재구성 • Crypto API에 알고리즘 재등록 → 새 요청 수용 가능 • 진행 중 요청: -EIO 반환 → 호출자가 S/W fallback 사용
QAT 드라이버는 Heartbeat 타이머로 FW 생존을 확인하며, 장애 시 자동으로 리셋 → 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_countersdebugfs transport를 node_exporter textfile collector로 주기적 수집
  • Ring Full 경보: full 카운터의 증가율이 임계값을 초과하면 알람. QAT EP 추가 또는 서비스 분리로 대응
  • Heartbeat 감시: qat/heartbeat_failed > 0이면 PagerDuty/Slack 알림. 자동 복구 후에도 원인 분석 필요
  • NUMA 검증: 신규 서버 프로비저닝 시 numactl --hardware와 QAT numa_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 인터페이스로 등록됩니다.

동기 (crypto_comp) 호출자 crypto_comp_compress() SW 구현 ← 블로킹 반환 비동기 (crypto_acomp) 호출자 crypto_acomp_compress() QAT HW 콜백 완료 ← 비블로킹 + DMA

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 가속을 적용할 수도 있습니다.

데이터 소스 파일/블록 I/O QAT 압축 (HW) deflate / lz4 ~10 GB/s 처리량 AES-GCM 암호화 QAT / AES-NI 인증 + 암호화 동시 네트워크 / 디스크 백업 스토리지 CPU: 제어 경로만 담당 (사용률 < 5%)
# ━━━ 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
QAT 인스턴스와 동시 요청 수: QAT 디바이스 하나에는 여러 개의 Acceleration Engine(AE)이 존재하며, 각 AE에 Ring Pair가 할당됩니다. 동시 압축 요청 수는 사용 가능한 Ring Pair 수에 비례합니다. 예를 들어 QAT C62x는 최대 16개 Ring Pair를 제공하며, 4xxx(Sapphire Rapids)는 최대 64개까지 지원합니다. 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 암호화 오프로드
암호화 가속기 폼 팩터 분류 개별 PCIe 카드 PCIe 슬롯에 장착 EOL QAT 8950/8960/8970 Marvell NITROX III/V (출시 중) Marvell LiquidSecurity 2 HSM 별도 PCIe 슬롯 · 서버 간 이동 칩셋/SoC 내장 PCH 또는 SoC 내부 통합 QAT C62x (Lewisburg PCH) QAT C3xxx (Atom Denverton) NXP CAAM, Marvell CPT HiSilicon SEC2, Qualcomm QCE 플랫폼에 기본 포함 CPU 다이 통합 CPU 패키지 내부 (RCiEP/MMIO) QAT Gen4/5/6 (Xeon RCiEP) AMD CCP/PSP (EPYC 내장) 최저 지연 (PCIe 버스 불필요) CPU 구매 시 자동 포함 별도 비용 없음 인라인 / 가상 NIC 내장 또는 VM 준가상화 NVIDIA CX-7 / BF-3 (NIC) Intel E810 (NIC) Samsung FMP (UFS 인라인) virtio-crypto (가상) 데이터 경로에 직접 위치 출시 상태 범례 (2025년 3월 확인 기준) 출시 중 — 현재 양산·판매 중. QAT Gen4/5, CCP(EPYC), CAAM(i.MX/LS), CPT v2/v3(OCTEON TX2/10), SEC2(Kunpeng) 출시 예정 — 실리콘 또는 드라이버 개발 중. QAT Gen6(6xxx, Linux 6.16), Marvell CN20K 단종 (EOL) — 신규 구매 불가 (커널 드라이버는 계속 지원). QAT 8950/8960(Gen1/2 카드), S5P SSS(Exynos 4/5), CPT v1(OCTEON TX)
암호화 가속기는 폼 팩터에 따라 개별 PCIe 카드, 칩셋/SoC 내장, CPU 다이 통합, 인라인/가상의 4가지로 분류되며, 최근 추세는 CPU 다이 통합과 인라인 오프로드 방향입니다

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)NaplesZen 12017. 6SEV단종
2세대 (7002)RomeZen 22019. 8SEV, SEV-ES출시 중
3세대 (7003)MilanZen 32021. 3SEV, SEV-ES, SEV-SNP출시 중
4세대 (9004)GenoaZen 42022. 11SEV, SEV-ES, SEV-SNP v2출시 중
5세대 (9005)TurinZen 52024. 10SEV, 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에 중간 결과를 저장하면서 처리됩니다.

AMD CCP 내부 아키텍처 AMD EPYC / Ryzen CPU 다이 Zen 코어 (최대 128C) Infinity Fabric / Data Fabric (MMIO 접근) CCP / PSP (Platform Security Processor) CQ 0 AES/SHA 범용 CQ 1 AES/SHA 범용 CQ 2~3 AES/SHA + RSA CQ 4 (PSP 전용) SEV/SEV-SNP LSB 전용 SRAM 암호 엔진 AES(CBC/GCM/XTS) · SHA(1/256/384/512) · SHA3 · RSA · ECC · 3DES SEV 메모리 암호화 엔진 AES-128-XEX (C-bit 기반) TRNG (SP 800-90) /dev/hwrng Deflate 엔진 zlib/gzip 압축 CCP는 PCIe 디바이스(PCI ID 1022:xxxx)로 노출되지만 물리적으로 CPU 다이에 통합됨 CQ 0~3: Crypto API 연동 (ccp-crypto) | CQ 4: PSP/SEV 전용 커맨드
CCP는 CPU 다이 내부에 5개 명령 큐, 암호 엔진, SEV 메모리 암호화 엔진, TRNG, 압축 엔진을 통합한 보안 코프로세서입니다

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개 하드웨어 큐
KconfigCONFIG_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 아키텍처 Kunpeng 920/930 SoC (ARM Cortex-A76 / TaiShan) 커널 Crypto API UACCE (유저스페이스) UADK 라이브러리 hisi_sec2 드라이버 (PF + VF) drivers/crypto/hisilicon/sec2/ 하드웨어 큐 쌍 (SQ/CQ) × 256 BD(Buffer Descriptor) 기반 — 큐당 독립 인터럽트 AES/SM4 엔진 ECB/CBC/XTS/GCM SHA/SM3 엔진 SHA-256/512 AEAD GCM/CCM 3DES 레거시 SMMU IOMMU 격리 VF별 독립 주소 공간 최대 100 Gbps (AES-256-XTS) · 256 HW 큐 · SR-IOV VF 지원 · UACCE 유저스페이스 직접 접근 관련 가속기: HPRE (RSA/ECC/DH), ZIP (압축), TRNG (난수) — 동일 SoC 내 독립 블록
SEC2는 커널 Crypto API와 UACCE 유저스페이스 두 경로를 모두 지원하며, 256개 하드웨어 큐로 대규모 병렬 처리가 가능합니다
# ━━━ 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 v1SE×16최대 16 VF~25 GbpsRSA-2048 10K엔터프라이즈 라우터단종
OCTEON TX2 (CN96xx)CPT v2AE×4, SE×30, IE×4최대 128 VF~100 GbpsRSA-2048 50K캐리어 라우터, NGFW출시 중
OCTEON TX2 (CN98xx)CPT v2AE×8, SE×46, IE×8최대 128 VF~140 GbpsRSA-2048 80K캐리어 코어 라우터출시 중
CN10K (CN106xx)CPT v3AE×8, SE×40, IE×8최대 256 VF~100 GbpsRSA-2048 60KDPU, 5G UPF, NGFW출시 중
OCTEON 10 DPUCPT v3AE×12, SE×48, IE×12최대 256 VF~200 GbpsRSA-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)이 독립된 명령 큐를 사용합니다.

OCTEON CPT 하드웨어 블록 다이어그램 OCTEON TX2 / CN10K SoC ARM N2 코어 (최대 36) SSO 이벤트 스케줄러 NIX (네트워크 I/O) NPA (버퍼 풀) ZIP / REE AMBA / CCN SoC 내부 인터커넥트 CPT (Crypto Processing Thread) CPT PF 리소스 관리, 엔진 할당 VF 0 커널 Crypto API VF 1 DPDK cryptodev VF N ... 인라인 IPsec NIX 직접 연동 명령 큐(Instruction Queue) 풀 VF당 최대 64 IQ — CPT_INST_S 디스크립터 제출 → 엔진 자동 할당 SE (Symmetric Engine) AES/SHA/HMAC — 최대 48개 AE (Asymmetric Engine) RSA/ECC/DH/SM2 — 최대 12개 IE (IPsec Engine) ESP 캡슐화 전담 — 최대 12개 완료 경로: Result Queue → SSO 이벤트 자동 생성 (또는 IRQ/폴링 콜백) CPT_RES_S 상태 코드 + 출력 데이터 DMA → 다음 파이프라인 스테이지로 자동 전달
CPT는 PF/VF 모델로 리소스를 격리하며, 3종 마이크로엔진(SE/AE/IE)이 명령 큐에서 디스크립터를 가져와 독립 실행합니다

CPT 명령 제출/완료 흐름

CPT의 모든 암호 연산은 CPT_INST_S(Instruction Structure) 디스크립터를 명령 큐(IQ)에 기록하는 방식으로 제출됩니다. 각 VF는 독립된 IQ를 보유하며, CPT 하드웨어가 빈 엔진을 자동으로 할당합니다. 완료 결과는 CPT_RES_S(Result Structure)로 전달되며, SSO 이벤트 또는 인터럽트/폴링 방식으로 통지됩니다.

CPT 명령 제출/완료 흐름 (Lookaside 모드) ① CPT_INST_S 빌드 opcode, 입출력 scatter/ gather 포인터, ctx 주소 ② IQ에 LMTST 쓰기 LMTST: 단일 캐시라인 원자적(atomic) 제출 ③ 엔진 할당·실행 SE/AE/IE 자동 선택 DMA로 데이터 처리 ④ 완료 CPT_RES_S 상태+결과 경로 A: SSO 이벤트 생성 CPU 무개입, 다음 스테이지 자동 전달 경로 B: IRQ / 폴링 커널 Crypto API 콜백 CPT_INST_S 구조 (128바이트) Word 0-1: 입력 scatter/gather 리스트 (dptr) Word 2-3: 출력 scatter/gather 리스트 (rptr) Word 4: CPT_INST_W4 — opcode, 입출력 길이 Word 5: ctx 포인터 (세션 키·IV·상태) Word 6: 태그(SSO) / 그룹 / 완료 통지 모드 Word 7: 결과 주소 (CPT_RES_S 기록 위치) LMTST(Load/Store Multiple Thread): ARM 캐시라인 단위 원자적 쓰기 — PCIe MMIO 대비 ~5배 빠른 제출 지연 SSO 경로(A)는 DPAA/이벤트 기반 파이프라인, IRQ 경로(B)는 커널 Crypto API 범용 사용
CPT_INST_S 디스크립터를 LMTST로 원자적 제출 → 엔진이 DMA 처리 → 결과를 SSO 이벤트 또는 IRQ로 전달합니다

CPT ↔ SSO 연동 (이벤트 드리븐 파이프라인)

OCTEON의 가장 강력한 특성은 CPT와 SSO(Schedule/Synchronize/Order) 이벤트 스케줄러의 하드웨어 직접 연동입니다. NGFW/IPsec 파이프라인에서 패킷이 암호화 처리를 거칠 때, CPU가 CPT 완료를 폴링하거나 인터럽트를 기다릴 필요 없이 CPT가 완료 이벤트를 SSO에 직접 제출합니다:

CPT ↔ SSO 이벤트 드리븐 IPsec 파이프라인 NIX RX 패킷 수신 WQE 생성 SSO Atomic 스케줄 → FW 코어 할당 방화벽 ACL / conntrack IPsec 필요 판단 CPT ESP 암호화/복호화 CPU 무개입 완료 → SSO 자동 CPT 완료 → SSO 이벤트 자동 생성 (CPU 무개입) 후처리 IPS / QoS NIX TX 패킷 송신 일반 SoC (잡 링 / IRQ 방식) CPU → 제출 → 대기(IRQ/폴링) → 완료 확인 → 다음 단계 CPU가 매 패킷마다 암호화 완료를 처리해야 함 OCTEON (CPT ↔ SSO 연동) CPU → 제출(SSO FWD) → [CPT 처리] → SSO가 자동 전달 CPU는 암호화 중 다른 패킷 처리 가능 — 파이프라인 효율 극대화
CPT 완료 시 SSO가 CPU 개입 없이 이벤트를 다음 스테이지로 전달하여, 기존 IRQ/폴링 방식 대비 파이프라인 효율이 크게 향상됩니다

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별로 독립된 암호 가속 인스턴스를 제공합니다.

NITROX V (CNN55XX) 내부 블록 다이어그램 PCIe 3.0 ×8 인터페이스 — SR-IOV PF/VF (최대 256 VF) DMA 엔진 + 명령 큐(Command Queue) — 호스트 메모리 ↔ NITROX 내부 SRAM 대칭키 코어 (SE) AES/3DES/SHA/SM4 — 최대 64코어 비대칭키 코어 (AE) RSA/ECDSA/DH/SM2 압축 엔진 (ZIP) Deflate/LZ4 — ~60 Gbps 마이크로코드(Firmware) — 호스트에서 PCIe DMA로 로딩 필요 (nrhf-se, nrhf-ae) NITROX V는 OCTEON CPT와 달리 독립 PCIe 디바이스로, x86/ARM 범용 서버에 장착 가능 (SoC 불필요)
NITROX V는 PCIe 카드 형태로, 내부에 대칭키·비대칭키·압축 전용 코어를 탑재하며, SR-IOV를 통해 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 버전잡 링DECOQI대칭키 처리량주요 용도출시 상태 (2025. 3 기준)
i.MX6 시리즈SEC 4.x2 JR2~3없음~300 MbpsIoT 게이트웨이, 산업용장기 공급 (~2036)
i.MX7 시리즈SEC 4.x2 JR2없음~300 Mbps웨어러블, 저전력 IoT장기 공급 (~2035)
i.MX8M 시리즈SEC 4.x3 JR3없음~1 Gbps멀티미디어, 엣지 AI출시 중
i.MX8X / i.MX8QXPSEC 5.x4 JR4없음~1.5 Gbps자동차(ADAS), 산업용출시 중
i.MX93SEC 5.x (EdgeLock)4 JR4+없음~2 Gbps자동차, 산업 IoT출시 중
i.MX95ELE (EdgeLock Enclave)없음~2 Gbps자동차, 산업 IoT출시 중
LS1012ASEC 5.x2 JR4있음~2.5 Gbps소형 라우터, CPE출시 중
LS1028ASEC 5.x4 JR6있음~5 GbpsTSN 스위치, 산업용출시 중
LS1043A/LS1046ASEC 5.x4 JR6~8있음~10 Gbps엔터프라이즈 라우터출시 중
LS1088ASEC 5.x4 JR8있음~10 Gbps네트워크 어플라이언스출시 중
LS2088A/LX2160ASEC 5.44 JR12~16있음~20 Gbps캐리어 등급 라우터출시 중

CAAM 하드웨어 블록 구조

CAAM은 내부적으로 잡 링(JR), QI(Queue Interface), DECO, 암호 코어의 4개 주요 블록으로 구성됩니다. 잡 링은 CPU가 디스크립터를 제출하는 일반적인 인터페이스이며, QI는 DPAA 프레임워크의 프레임 큐(Frame Queue)와 직접 연동하여 네트워크 패킷을 CPU 개입 없이 처리합니다.

CAAM 하드웨어 블록 다이어그램 NXP SoC (i.MX / Layerscape) CPU Core 0 CPU Core 1 CPU Core N DPAA / 네트워크 컨트롤러 AXI / SoC 내부 인터커넥트 CAAM (SEC 엔진) 잡 링 0~3 Input/Output Ring QI DPAA Frame Queue 컨트롤러 스케줄러·DMA RNG (TRNG) /dev/hwrng DECO(DEscriptor COntroller) 엔진 풀 DECO 0 | DECO 1 | DECO 2 | DECO 3 | ... | DECO N (SoC별 2~16개) AES 엔진 ECB/CBC/CTR/GCM/CCM SHA 엔진 SHA-1/256/512 PKHA RSA/ECC/DH DES/3DES 레거시 CRC 무결성 보안 메모리(Secure Memory) — 블랙 키·마스터 키·Blob 데이터 보호 영역 (외부 접근 차단)
CAAM 내부 블록 구조: 잡 링(CPU 인터페이스)과 QI(DPAA 인터페이스) 두 경로를 통해 DECO 엔진이 암호 연산을 수행합니다

잡 디스크립터와 링 메커니즘

CAAM의 모든 암호 연산은 잡 디스크립터(Job Descriptor)라는 명령어 시퀀스로 기술됩니다. 각 잡 링은 입력 링(Input Ring)출력 링(Output Ring)으로 구성된 한 쌍의 순환 버퍼(circular buffer)입니다. CPU가 디스크립터 포인터를 입력 링에 기록하고 도어벨(doorbell) 레지스터를 쓰면, CAAM은 빈 DECO에 디스크립터를 할당하여 실행합니다. 완료 후 결과 포인터가 출력 링에 기록되고 인터럽트가 발생합니다.

잡 디스크립터 제출/완료 흐름 ① CPU가 디스크립터 작성 CPU (caam_jr) 디스크립터 DMA 주소 입력 링 (Input Ring) 순환 버퍼, 최대 1024 슬롯 ③ 도어벨 Write ④ DECO 엔진 실행 디스크립터 fetch → DMA 입력 → 암호 연산 → DMA 출력 ⑤ 출력 링 (Output Ring) 완료 디스크립터 + 상태 코드 ⑥ IRQ → 콜백 crypto_request 완료 알림 잡 디스크립터 구조 ┌─ Header (알고리즘, 길이) ├─ Key 로드 명령 ├─ FIFO Load (입력 데이터 DMA) ├─ Operation (AES-CBC-ENC 등) └─ FIFO Store (출력 데이터 DMA) 전체 과정이 DMA 기반 — CPU는 디스크립터 제출·완료 콜백만 처리 (데이터 복사 없음)
CPU가 디스크립터를 입력 링에 기록하고 도어벨을 울리면, CAAM이 자체적으로 DMA를 통해 데이터를 처리하고 완료를 알립니다

QI(Queue Interface)와 DPAA 연동

Layerscape SoC에서 CAAM은 잡 링 외에 QI(Queue Interface) 경로를 제공합니다. QI는 DPAA(Data Path Acceleration Architecture)의 QMan(Queue Manager) 프레임 큐와 직접 연동되어, 네트워크 패킷이 CPU를 거치지 않고 CAAM으로 전달됩니다. IPsec ESP 처리에서 이 경로를 사용하면 CPU 오버헤드가 크게 줄어듭니다:

잡 링 경로 vs QI(DPAA) 경로 비교 잡 링 경로 (범용) NIC RX CPU (xfrm) 잡 링 CAAM CPU (콜백) TX QI 경로 (DPAA 네트워크) DPAA FMan QMan FQ CAAM QI QMan FQ TX CPU 개입 없음 — QMan이 CAAM에 직접 프레임 전달 잡 링 경로 QI 경로 CPU가 디스크립터 제출·콜백 처리 QMan FQ ↔ CAAM 직접 DMA 범용 (dm-crypt, AF_ALG 등) DPAA IPsec 특화 (Layerscape만)
잡 링 경로는 CPU가 관여하는 범용 인터페이스, QI 경로는 DPAA 프레임워크와 직접 연동하여 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)에 안전하게 보관할 수 있습니다:

/* 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 GbpsIPsec ESP 표준
SHA-256~700 Mbps~6 Gbps~14 GbpsHMAC 포함
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/sTLS 핸드셰이크
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/4412s5p-sssAES(ECB/CBC), SHA-1/256CRYPTO_DEV_S5P단종
Exynos 5250/5420s5p-sssAES(ECB/CBC/CTR), SHA-1/256, PRNGCRYPTO_DEV_S5P단종
Exynos 7420/8890exynos-rngPRNG (DRBG)CRYPTO_DEV_EXYNOS_RNG단종
Exynos 850/990FMP (UFS inline)AES-256-XTSUFS_EXYNOS_CRYPTO출시 중
Exynos 2200/2400/2500FMP (UFS inline)AES-256-XTSUFS_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 기준)
BroadcomBCM58xx SPUbcm-spuCRYPTO_DEV_BCM_SPUAES, SHA, 3DES, MD5SoC 내장출시 중
Allwinnersun8i/sun50i CEsun8i-ceCRYPTO_DEV_SUN8I_CEAES, SHA, PRNGSoC 내장출시 중
RockchipRK3288/3399/3568/3588rk3288-cryptoCRYPTO_DEV_ROCKCHIPAES, SHA, MD5SoC 내장출시 중
AmlogicGXL/G12/S4amlogic-gxlCRYPTO_DEV_AMLOGIC_GXLAES (CBC/ECB)SoC 내장출시 중
STMicroSTM32 CRYPstm32-crypCRYPTO_DEV_STM32_CRYPAES, DES, 3DESMCU 내장출시 중
Texas Instr.AM65x/J721E SA2ULsa2ulCRYPTO_DEV_SA2ULAES, SHA, HMACSoC 내장출시 중
NXPi.MX CAAMcaamCRYPTO_DEV_FSL_CAAMAES, SHA, RSA, RNGSoC 내장 (MMIO)출시 중
MicrochipATMEL AES/SHAatmel-aesCRYPTO_DEV_ATMEL_AESAES, SHASoC 내장출시 중
QualcommQCE (IPQ/SDM/SM)qceCRYPTO_DEV_QCEAES, DES, SHASoC 내장출시 중
MediaTekEIP-97 (MT7623 등)mtk-cryptoCRYPTO_DEV_MEDIATEKAES, SHA, HMACSoC 내장출시 중
ARMCryptoCell 7xxccreeCRYPTO_DEV_CCREEAES, SHA, RSA, ECC, TRNGSoC IP 블록출시 중
IntelKeembay OCSkeembay-ocs-aesCRYPTO_DEV_KEEMBAY_OCS_AESAES, SM4, SHASoC 내장출시 중
AspeedAST2500/2600 HACEaspeed-haceCRYPTO_DEV_ASPEED_HACESHA, HMACBMC SoC 내장출시 중
Inside SecureSafeXcel EIP-197safexcelCRYPTO_DEV_SAFEXCELAES, SHA, HMAC, AEADSoC 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 등)은 가상 머신 안에서도 투명하게 호스트의 가속기를 활용할 수 있습니다.

virtio-crypto 호스트-게스트 데이터 흐름 게스트 VM (Guest Kernel) dm-crypt / IPsec Crypto API virtio_crypto 드라이버 virtqueue dataq[0..N] + ctrlq VM Exit / vring 공유 메모리 (Guest ↔ Host) 호스트 (Host Kernel / QEMU) QEMU cryptodev 백엔드 경로 A: builtin 백엔드 QEMU 내부 S/W 구현 경로 B: vhost-user 백엔드 DPDK → QAT/CCP H/W 경로 C: VF 패스스루 SR-IOV VF 직접 할당
게스트의 virtio_crypto 드라이버가 virtqueue를 통해 호스트에 암호 요청을 전달하면, 호스트는 builtin/vhost-user/VF 패스스루 중 하나로 처리합니다
/* 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 가속을 사용하는 것이 가장 실용적입니다.

암호화 가속기 분류 체계 Crypto API 통합 인터페이스 CPU ISA 명령어 AES-NI, SHA-NI, ARM CE 최저 지연, 소량 데이터 최적 PCI 가속기 Intel QAT, AMD CCP 고처리량, 배치 처리 최적 SoC 임베디드 엔진 HiSilicon SEC2, NXP CAAM ARM 서버/임베디드 특화 가상 디바이스 virtio-crypto, vhost-user VM 환경 호스트 가속기 활용 모든 가속기는 동일한 Crypto API 인터페이스로 등록 → 사용자(dm-crypt, IPsec 등)는 구현을 몰라도 됨
4가지 유형의 가속기가 모두 Crypto API에 등록되어 동일한 인터페이스로 활용됩니다

AF_ALG 사용자 공간 인터페이스

AF_ALG는 커널 Crypto API를 사용자 공간에서 소켓 인터페이스로 접근할 수 있게 하는 주소 패밀리(Address Family)입니다. 하드웨어 가속기(AES-NI, ARM CE, QAT, CCP 등)가 등록한 알고리즘을 사용자 프로그램이 직접 활용할 수 있으므로, OpenSSL이나 별도 라이브러리 없이도 커널 수준의 최적화된 암호 연산을 수행할 수 있습니다.

AF_ALG 동작 구조

AF_ALG 사용자 공간 인터페이스 동작 구조 사용자 공간 (User Space) ① socket(AF_ALG) 알고리즘 선택 + bind ② setsockopt(ALG_SET_KEY) 키 설정 ③ accept → sendmsg/read 데이터 암복호화 커널 공간 (Kernel Space) algif_skcipher / algif_hash / algif_aead Crypto API (tfm 할당) crypto_skcipher_encrypt() 하드웨어 가속기 (자동 선택) AES-NI · ARM CE · QAT · CCP · SEC2 · CAAM ...
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_aeadAEAD (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 + cmsgcmsg(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 디스크의 잠금/해제, 범위 관리, 인증 절차를 정의합니다. 핵심 개념은 다음과 같습니다.

sedutil / 사용자앱 IOC_OPAL_* ioctl sed-opal 모듈 Block Layer NVMe / SATA Security Command SED 드라이브 (Opal 2.0) AES-256 HW 엔진 + MEK

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)가 가능합니다.

SED 비밀번호 분실 주의: SED/Opal 비밀번호를 분실하면 디스크의 데이터를 복구할 방법이 없습니다. 유일한 복구 방법은 드라이브 라벨에 인쇄된 PSID(Physical Security ID)를 사용한 공장 초기화(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 소프트웨어 키 저장소

특성HSMTPM소프트웨어 키스토어
키 저장 위치전용 하드웨어 (FIPS 인증)SoC/마더보드 내장 칩디스크/메모리
키 추출 가능 여부불가 (탬퍼 시 자동 삭제)불가 (제한적 연산만 지원)가능 (메모리 덤프 위험)
암호 연산 성능수만~수십만 TPS수십~수백 TPSCPU 의존
FIPS 인증 등급Level 2~4Level 1~2Level 1 (소프트웨어)
폼 팩터PCIe 카드 / 네트워크 어플라이언스 / USBSPI/I2C 칩 (2×3mm)해당 없음
비용수백~수천만 원수천~수만 원무료
주요 용도CA 루트키, 코드 서명, 결제, PKI플랫폼 무결성, Measured Boot개발/테스트
다중 테넌트파티션/슬롯으로 격리단일 소유자파일 권한

HSM 내부 아키텍처

HSM은 외부 환경과 완전히 격리된 보안 경계(Security Boundary) 내에서 동작합니다. 모든 암호화 연산은 전용 프로세서에서 수행되며, 키 자료(Key Material)는 보안 경계를 벗어나지 않습니다. 호스트 시스템은 PKCS#11, KMIP, 또는 벤더 전용 API를 통해 HSM에 연산을 요청하고 결과만 받습니다.

HSM 내부 아키텍처 호스트 시스템 애플리케이션 (OpenSSL, Java, nginx) PKCS#11 / KMIP / 벤더 API HSM 드라이버 (PCIe / USB / 네트워크) PCIe / USB / Network HSM 보안 경계 (Security Boundary) 탬퍼 감지/대응 (온도·전압·개봉·관통 센서 → 키 즉시 삭제) 보안 프로세서 대칭키 엔진 (AES, 3DES, SM4) 비대칭키 엔진 (RSA, ECC, SM2) 해시/HMAC (SHA-2/3, SM3) 키 저장소 (배터리 백업 SRAM) 마스터 키 (Master Key / KEK) 파티션별 키 슬롯 (래핑된 상태) 인증서 / 공개키 객체 TRNG (True RNG) 펌웨어 (서명 검증) Secure Boot Chain 감사 로그 (Audit Log) 변조 불가 기록 PKCS#11 연산 흐름 C_SignInit() 메커니즘+키 핸들 C_Sign(data) 데이터 → HSM 전송 HSM 내부 서명 수행 키 노출 없이 결과만 반환 키 생명주기 (Key Lifecycle) 생성 TRNG 기반 활성 서명/암호화 사용 백업 KEK 래핑 내보내기 폐기 제로화(Zeroize) 모든 키 자료는 보안 경계 내부에서만 평문 상태로 존재합니다 외부 백업 시 반드시 KEK(Key Encryption Key)로 래핑된 암호문으로 내보냅니다
HSM은 보안 경계 내부에 키 저장소·암호 엔진·TRNG·감사 로그를 통합하며, 키는 보안 경계를 벗어나지 않습니다

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 L320,000최대 100Ethernet (NTLS/TLS)PKCS#11 라이브러리
Thales Luna PCIe HSM 7PCIe 카드140-3 L320,000최대 20PCIe 3.0 x4커널 모듈 + PKCS#11
Entrust nShield Connect XC네트워크 어플라이언스(1U)140-2 L314,400다중 Security WorldEthernetPKCS#11 / JCE / CAPI
Utimaco CryptoServer Se Gen2PCIe 카드140-2 L315,000다중 펌웨어 파티션PCIe 3.0PKCS#11 / JCE
AWS CloudHSM클라우드 (전용 하드웨어)140-2 L3~1,100VPC 격리ENI (네트워크)PKCS#11 / OpenSSL
Azure Managed HSM클라우드 (전용 풀)140-2 L3가변구독 격리REST API / SDKaz CLI / SDK
YubiHSM 2USB (나노 크기)140-2 L3~100최대 16 인증 키USB 2.0PKCS#11 / yubihsm-shell
Nitrokey HSM 2USB 스마트카드CC EAL5+~50최대 48 키 슬롯USB (PC/SC)PKCS#11 (OpenSC)

Linux 커널과 HSM 연동

리눅스 커널은 HSM에 직접적으로 의존하지 않지만, 여러 서브시스템이 HSM과 연동됩니다. 커널 모듈 서명, 커널 키링(Keyring), PKCS#11을 통한 TLS 인증서 관리 등이 대표적입니다.

Linux와 HSM 연동 구조 사용자 공간 (User Space) OpenSSL ENGINE / PROVIDER GnuTLS / NSS PKCS#11 모듈 Java (JCE) SunPKCS11 Provider NGINX / HAProxy TLS 개인키 보호 HashiCorp Vault Auto-Unseal / 루트키 PKCS#11 표준 인터페이스 (libpkcs11.so / p11-kit) 커널 공간 (Kernel Space) 커널 키링 (Keyring) .builtin_trusted_keys 모듈 서명 검증 scripts/sign-file (빌드 시) IMA/EVM 파일 무결성 서명 dm-verity / dm-crypt 블록 디바이스 무결성/암호화 Linux Crypto API (crypto_register_alg / crypto_alloc_tfm) ioctl / syscall 하드웨어 PCIe HSM Luna, nShield, Utimaco USB HSM YubiHSM, Nitrokey 네트워크 HSM Luna Network, nShield 클라우드 HSM AWS / Azure / GCP TPM 2.0 Infineon, Nuvoton, STMicro
사용자 공간 애플리케이션은 PKCS#11을 통해 HSM에 접근하고, 커널은 모듈 서명·IMA·dm-verity 등에서 HSM 기반 키를 활용합니다

PKCS#11과 HSM 활용

PKCS#11(Cryptoki)은 OASIS(구 RSA Laboratories) 표준으로, 암호화 토큰(HSM, 스마트카드, TPM)에 대한 플랫폼 독립적 C API를 정의합니다. 리눅스에서 PKCS#11은 HSM과 소통하는 사실상의 표준 인터페이스이며, p11-kitp11-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)라 합니다. 이 과정은 다수의 인증된 참여자가 물리적으로 입회하여 진행하며, 전체 과정이 영상 녹화되고 공증됩니다. 키 세레모니는 다음 단계로 구성됩니다.

키 세레모니(Key Ceremony) 절차 1. 환경 준비 에어갭 시스템 부팅 HSM 초기화 (공장 상태) 2. 관리자 인증 M-of-N 스마트카드 삽입 다중 관리자 PIN 입력 3. 키 생성 HSM TRNG 기반 RSA/ECC 키 쌍 HSM 내부에서 생성 4. 루트 인증서 서명 자체 서명 루트 CA 생성 유효기간 20~30년 5. 백업 및 봉인 KEK 래핑 백업 → 금고 감사 로그 공증 M-of-N 분할 인증 (Quorum Authentication) 관리자 A 스마트카드 #1 + PIN 관리자 B 스마트카드 #2 + PIN 관리자 C 스마트카드 #3 + PIN ... 관리자 N 스마트카드 #N (대기) HSM 잠금 해제 M명 이상 인증 시에만 키 연산 허용 예: 5명 중 3명(3-of-5) 인증 필요 — 단일 관리자의 키 탈취로는 HSM 접근 불가
키 세레모니는 에어갭 환경에서 M-of-N 다중 관리자 인증을 거쳐 루트 키를 생성하며, 전 과정이 감사 로그로 기록됩니다

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 주요 활용 사례

HSM 운영 시 주의사항: HSM은 강력한 보안을 제공하지만, 잘못된 운영은 서비스 장애로 직결됩니다. (1) M-of-N 스마트카드를 모두 분실하면 HSM 키에 영구적으로 접근 불가합니다 — 반드시 지리적으로 분산 보관하세요. (2) HSM 펌웨어 업데이트는 키 백업 후 진행하며, 업데이트 실패 시 공장 초기화될 수 있습니다. (3) 네트워크 HSM은 mTLS(상호 TLS)로 통신을 보호하고, 접근 IP를 방화벽으로 제한하세요. (4) 감사 로그를 정기적으로 SIEM에 수집하여 비인가 접근 시도를 모니터링하세요.

암호화 하드웨어 가속과 관련된 다른 주제를 더 깊이 이해하고 싶다면 다음 문서를 참고하세요.

외부 참고 자료

커널 공식 문서

CPU ISA 확장 (AES-NI, ARM CE, SHA-NI)

Intel QAT

AMD CCP / PSP / SEV

NXP CAAM

Marvell OCTEON CPT

HiSilicon SEC / HPRE / ZIP

NIC 암호화 오프로드

SED/OPAL, HSM

일반 참고