이 페이지에는 Android 6.0 이상에서 제공하는 키 저장소의 암호화 기능에 관한 정보가 포함되어 있습니다.
암호화 프리미티브
키 저장소는 다음과 같은 작업 카테고리를 제공합니다.
- 키 생성
- 비대칭 키 가져오기 및 내보내기(키 래핑 없음)
- 원본 대칭 키 가져오기(키 래핑 없음)
- 적절한 패딩 모드를 사용한 비대칭 암호화 및 복호화
- 다이제스트 및 적절한 패딩 모드를 사용한 비대칭 서명 및 인증
- AEAD 모드와 같은 적절한 모드로 대칭 암호화 및 복호화
- 대칭 메시지 인증 코드 생성 및 확인
목적, 모드 및 패딩과 같은 프로토콜 요소와 액세스 제어 제약 조건은 키를 생성하거나 가져올 때 지정되고 키에 영구적으로 결합하므로 키는 다른 방식으로 사용될 수 없습니다.
위의 목록 외에도 Keymaster 구현에서 제공하지만 API로 노출되지 않는 서비스가 하나 더 있는데, 바로 랜덤 숫자 생성 서비스입니다. 이 서비스는 키 생성, 초기화 벡터(IV), 랜덤 패딩 및 임의성이 필요한 보안 프로토콜의 기타 요소를 위해 내부적으로 사용됩니다.
필수 프리미티브
모든 Keymaster 구현은 다음을 제공합니다.
- RSA
- 2048, 3072 및 4096비트 키 지원
- 공개 지수 F4 지원(2^16+1)
- RSA 서명용 패딩 모드:
- RSASSA-PSS(
PaddingMode::RSA_PSS
) - RSASSA-PKCS1-v1_5(
PaddingMode::RSA_PKCS1_1_5_SIGN
)
- RSASSA-PSS(
- RSA 서명용 다이제스트 모드:
- SHA-256
- RSA 암호화/복호화용 패딩 모드:
- 패딩되지 않음
- RSAES-OAEP(
PaddingMode::RSA_OAEP
) - RSAES-PKCS1-v1_5(
PaddingMode::RSA_PKCS1_1_5_ENCRYPT
)
- ECDSA
- NIST P-224, P-256, P-384 및 P-521 곡선을 사용하여 224, 256, 384 및 521비트 키 지원이 각각 지원됩니다.
- ECDSA용 다이제스트 모드:
- 다이제스트 없음(지원 중단됨, 향후 삭제될 예정)
- SHA-256
- AES
- 128 및 256비트 키가 지원됩니다.
- CBC, CTR, ECB 및 GCM. GCM 구현에서는 96비트보다 작은 태그 또는 길이가 96비트가 아닌 nonce는 사용할 수 없습니다.
- 패딩 모드
PaddingMode::NONE
과PaddingMode::PKCS7
은 CBC 및 ECB 모드에 지원됩니다. 패딩이 없는 경우 입력이 블록 크기의 배수가 아니면 CBC 또는 ECB 모드 암호화는 실패합니다.
- HMAC SHA-256(키 크기는 최소 32바이트까지)
Keymaster 구현에는 SHA1 및 SHA2군의 다른 함수(SHA-224, SHA384 및 SHA512)를 사용하는 것이 적극 권장됩니다. 키 저장소는 하드웨어 Keymaster 구현에서 SHA를 제공하지 않으면 소프트웨어로 제공합니다.
일부 프리미티브는 다른 시스템과의 상호운용성에도 좋습니다.
- RSA용 더 작은 키 크기
- RSA용 임의 공개 지수
키 액세스 제어
기기에서 추출할 수 없는 하드웨어 기반 키는 공격자가 마음대로 사용할 수 있다면(유출될 수 있는 키보다 안전하다고 하더라도) 보안을 강화하지 못합니다. 따라서 키 저장소에서 액세스 제어를 시행하는 것이 중요합니다.
액세스 제어는 태그/값 쌍의 '승인 목록'으로 정의됩니다. 승인 태그는 32비트 정수이며 값은 다양한 유형입니다. 일부 태그는 여러 값을 지정하기 위해 반복될 수 있습니다. 태그를 반복할 수 있는지는 태그 관련 문서에 지정되어 있습니다. 키가 생성되면 호출자가 승인 목록을 지정합니다. 키 저장소의 기반이 되는 Keymaster 구현은 목록을 수정하여 일부 추가 정보(예: 키의 롤백 보호 여부)를 지정하고 반환된 키 blob에 인코딩된 '최종' 승인 목록을 반환합니다. 최종 승인 목록이 수정되면 암호화 작업에 키를 사용하려는 시도는 실패합니다.
Keymaster 2 및 이전 버전에는 가능한 태그 집합이 열거형 keymaster_authorization_tag_t
에 정의되어 있고 이는 확장될 수도 있지만, 영구적으로 고정되어 있습니다.
이름의 접두어는 KM_TAG
입니다. 태그 ID의 상위 4개 비트는 유형을 나타내는 데 사용됩니다.
Keymaster 3에서는 접두어가 KM_TAG
에서 Tag::
로 변경되었습니다.
가능한 유형은 다음과 같습니다.
ENUM
: 많은 태그의 값은 열거형으로 정의됩니다. 예를 들어, TAG::PURPOSE
의 가능한 값은 enum keymaster_purpose_t
에 정의되어 있습니다.
ENUM_REP
: 승인 목록에서 태그가 반복될 수 있다는 점을 제외하고 ENUM
과 동일합니다. 반복은 여러 개의 승인된 값을 나타냅니다. 예를 들어 암호화 키에는 KeyPurpose::ENCRYPT
와 KeyPurpose::DECRYPT
가 있을 수 있습니다.
UINT
: 부호 없는 32비트 정수입니다. 예:
TAG::KEY_SIZE
UINT_REP
: 승인 목록에서 태그가 반복될 수 있다는 점을 제외하고 UINT
과 동일합니다. 반복은 여러 개의 승인된 값을 나타냅니다.
ULONG
: 부호 없는 64비트 정수입니다. 예:
TAG::RSA_PUBLIC_EXPONENT
ULONG_REP
: 승인 목록에서 태그가 반복될 수 있다는 점을 제외하고 ULONG
과 동일합니다. 반복은 여러 개의 승인된 값을 나타냅니다.
DATE
: 날짜/시간 값이며 1970년 1월 1일 이후의 밀리초로 표시됩니다.
예: TAG::PRIVKEY_EXPIRE_DATETIME
BOOL
: true 또는 false입니다. BOOL
유형의 태그는 태그가 없으면 'false'로, 태그가 있으면 'true'로 간주합니다. 예: TAG::ROLLBACK_RESISTANT
BIGNUM
: 임의 길이의 정수이며 big-endian 순서의 바이트 배열로 표현됩니다. 예:
TAG::RSA_PUBLIC_EXPONENT
BYTES
: 일련의 바이트입니다. 예:
TAG::ROOT_OF_TRUST
하드웨어 대 소프트웨어 시행
모든 보안 하드웨어 구현이 동일한 기능을 포함하는 것은 아닙니다. Keymaster는 다양한 접근 방식을 지원하기 위해 보안 및 비보안 액세스 제어 시행 또는 하드웨어 및 소프트웨어 시행을 각각 구별합니다.
모든 구현은 다음을 포함합니다.
- 모든 승인의 정확한 일치(시행 아님)를 실행합니다. 키 blob의 승인 목록은 순서 지정을 포함하여 키 생성 중에 반환된 승인과 정확하게 일치합니다. 불일치가 있으면 오류 진단이 발생합니다.
- 시맨틱 값이 시행되는 승인을 선언합니다.
하드웨어 시행 승인을 선언하는 API 메커니즘은 keymaster_key_characteristics_t
구조에 있습니다. 이 메커니즘은 승인 목록을 hw_enforced
와 sw_enforced
, 두 개의 하위 목록으로 나눕니다. 시행할 수 있는 승인에 따라 적절한 값을 각 목록에 배치하는 것은 보안 하드웨어의 책임입니다.
또한, 키 저장소는 승인의 보안 하드웨어 시행 여부와 관계없이 모든 승인의 소프트웨어 기반 시행을 구현합니다.
예를 들어, 키 만료를 지원하지 않는 TrustZone 기반 구현을 가정해 보겠습니다. 만료일이 있는 키를 계속 만들 수 있습니다. 키의 승인 목록에는 만료일과 함께 TAG::ORIGINATION_EXPIRE_DATETIME
태그가 포함됩니다. 키 특성에 관해 키 저장소에 요청하면 요청은 이 태그가 sw_enforced
목록에 있는 것을 발견하고 보안 하드웨어는 만료 요구사항을 시행하지 않습니다. 하지만 만료 후에 키를 사용하려고 시도하면 키 저장소에서 거부합니다.
그런 다음 기기가 만료를 지원하는 보안 하드웨어를 사용하여 업그레이드되면 키 특성에 관한 요청은 hw_enforced
목록에서 TAG::ORIGINATION_EXPIRE_DATETIME
을 찾으며 만료 후에 키를 사용하려고 하는 시도는 키 저장소를 회피하거나 우회하더라도 실패합니다.
키가 하드웨어의 지원을 받는지 여부를 결정하는 방법에 관한 자세한 내용은 키 증명을 참조하세요.
암호화 메시지 생성 승인
TAG::ALGORITHM
, TAG::KEY_SIZE
, TAG::BLOCK_MODE
, TAG::PADDING
, TAG::CALLER_NONCE
, TAG::DIGEST
태그는 연결된 키를 사용하는 작업의 암호화 특성을 정의하는 데 사용됩니다.
TAG::PADDING
, TAG::DIGEST
, PaddingMode::BLOCK_MODE
는 반복이 가능하며 이는 여러 개의 값이 단일 키에 연결될 수 있고 사용되는 값이 작업 시간에 지정된다는 것을 의미합니다.
목적
키에는 TAG::PURPOSE
태그와 함께 하나 이상의 승인 항목으로 표현되는 연관된 목적의 집합이 있으며, 이 태그는 사용 방법을 정의합니다. 목적은 다음과 같습니다.
KeyPurpose::ENCRYPT
KeyPurpose::DECRYPT
KeyPurpose::SIGN
KeyPurpose::VERIFY
모든 키는 이러한 목적의 하위 집합을 가질 수 있습니다. 일부 조합은 보안 문제를 일으킬 수 있습니다. 예를 들어, 암호화 및 서명에 모두 사용할 수 있는 RSA 키를 사용하면 공격자가 시스템을 통해 임의의 데이터를 복호화하여 서명을 생성할 수 있습니다.
가져오기 및 내보내기
Keymaster는 X.509 형식의 공개 키 내보내기와 다음 항목의 가져오기를 지원합니다.
- DER로 인코딩된 PKCS#8 형식의 공개 키와 비공개 키 쌍(비밀번호 기반 암호화 없음)
- 원시 바이트로서의 대칭 키
가져온 키를 안전하게 생성된 키와 구별하기 위해 TAG::ORIGIN
이 적절한 키 승인 목록에 포함됩니다. 예를 들어, 보안 하드웨어에서 키가 생성되었다면 KeyOrigin::GENERATED
값을 가진 TAG::ORIGIN
을 키 특성의 hw_enforced
목록에서 찾을 수 있지만 보안 하드웨어에 가져온 키는 KeyOrigin::IMPORTED
값을 갖습니다.
사용자 인증
안전한 Keymaster 구현은 사용자 인증을 구현하지 않지만, 사용자 인증을 구현한 다른 신뢰할 수 있는 앱에 의존합니다. 이러한 앱이 구현하는 인터페이스는 게이트키퍼 페이지를 참조하세요.
사용자 인증 요구사항은 두 개의 태그 집합을 통해 지정됩니다. 첫 번째 집합은 키를 사용할 수 있는 사용자를 나타냅니다.
TAG::ALL_USERS
는 모든 사용자가 키를 사용할 수 있다는 것을 나타냅니다. 이 태그가 있다면TAG::USER_ID
와TAG::USER_SECURE_ID
는 없습니다.TAG::USER_ID
는 승인된 사용자의 ID를 지정하는 숫자 값을 가집니다. 이는 애플리케이션 UID가 아닌 멀티 사용자를 위한 Android 사용자 ID이며 비보안 소프트웨어에서만 시행됩니다. 이 태그가 있다면TAG::ALL_USERS
는 없습니다.TAG::USER_SECURE_ID
에는 키의 사용을 잠금 해제하기 위해 보안 인증 토큰에 제공된 보안 사용자 ID를 지정하는 64비트 숫자 값이 있습니다. 키가 반복되는 경우 보안 인증 토큰에 값이 제공된다면 키를 사용할 수 있습니다.
두 번째 집합은 사용자 인증의 필요 여부와 시기를 나타냅니다.
아래의 두 태그 모두 집합에 없지만 TAG::USER_SECURE_ID
가 있다면, 키를 사용할 때마다 인증해야 합니다.
NO_AUTHENTICATION_REQUIRED
는TAG::USER_ID
에서 지정한 사용자로 실행하고 있는 앱만 키를 사용할 수 있더라도 사용자 인증이 필요하지 않음을 나타냅니다.TAG::AUTH_TIMEOUT
은 키 사용을 승인하기 위해 사용자 인증을 갱신해야 하는 시간을 초 단위로 지정하는 숫자 값입니다. 이는 비공개/보안 비밀 키 연산에만 적용됩니다. 공개 키 연산에는 인증이 필요하지 않습니다. 시간 제한은 재부팅에 이어서 적용되지 않습니다. 재부팅 후에는 모든 키가 '인증되지 않음' 상태가 됩니다. 인증이 부팅당 한 번 필요하다는 것을 나타내기 위해 시간 제한을 매우 큰 값으로 설정할 수 있습니다(2^32초는 136년이며 Android 기기는 그보다 자주 재부팅될 것으로 추측됨).
클라이언트 결합
클라이언트 결합은 특정 클라이언트 애플리케이션과 키의 결합을 의미하며 선택적 클라이언트 ID와 일부 선택적 클라이언트 데이터를 통해 실행됩니다(각각 TAG::APPLICATION_ID
와 TAG::APPLICATION_DATA
임). 키 저장소는 이러한 값을 불투명 blob으로 취급하여 키 생성/가져오기 중에 표시되는 동일한 blob이 사용할 때마다 표시되고 바이트 단위로 동일해야 합니다. 클라이언트 결합 데이터는 Keymaster에서 반환하지 않습니다. 호출자는 키를 사용하기 위해 이를 알고 있어야 합니다.
이 기능은 애플리케이션에 노출되지 않습니다.
만료일
키 저장소는 날짜별로 키 사용을 제한하도록 지원합니다. 키의 유효 기간 시작일과 만료일은 키와 연결될 수 있고 Keymaster는 현재 날짜/시간이 유효한 범위에서 벗어나면 키 연산 실행을 거부합니다. 키의 유효 범위는 TAG::ACTIVE_DATETIME
, TAG::ORIGINATION_EXPIRE_DATETIME
및 TAG::USAGE_EXPIRE_DATETIME
태그로 지정됩니다. '시작'과 '사용'은 키를 사용하여 새 암호문/서명 등을 '시작'하는지 또는 기존의 암호문/서명 등을 '사용'하는지로 구분합니다. 이 구분은 애플리케이션에 노출되지 않습니다.
TAG::ACTIVE_DATETIME
, TAG::ORIGINATION_EXPIRE_DATETIME
, 및 TAG::USAGE_EXPIRE_DATETIME
태그는 선택사항입니다. 태그가 없는 키는 항상 메시지를 복호화/확인하는 데 사용될 수 있다고 가정합니다.
실제 시간은 비보안 환경에서 제공되기 때문에 만료 관련 태그가 하드웨어 시행 목록에 있을 가능성은 거의 없습니다. 만료를 하드웨어에서 시행하려면 신뢰할 수 있는 원격 시간 서버를 사용하는 챌린지 응답 프로토콜을 통하는 것 등의 방법으로 보안 환경에서 신뢰할 수 있는 시간과 날짜를 얻을 수 있어야 합니다.
신뢰할 수 있는 루트 결합
키 저장소는 시작 시 Keymaster 보안 하드웨어에 제공되는 비트 문자열인 신뢰할 수 있는 루트에 키를 결합해야 하며 부트로더에서 하는 것이 좋습니다. 이 비트 문자열은 Keymaster에서 관리하는 모든 키에 암호학적으로 결합합니다.
신뢰할 수 있는 루트는 부팅 이미지의 서명을 확인하는 데 사용되는 공개 키와 기기의 잠금 상태로 구성됩니다. 공개 키가 변경되어 다른 시스템 이미지가 사용되거나 잠금 상태가 변경되면 이전의 신뢰할 수 있는 루트를 복원하지 않고 키에서 서명한 시스템이 부팅되지 않은 경우 이전 시스템에서 생성된 Keymaster 보호 키는 사용할 수 없습니다. 목표는 공격자가 설치한 운영체제에서 Keymaster 키를 사용할 수 없도록 하여 소프트웨어 시행 키 액세스 제어의 값을 증가시키는 것입니다.
독립형 키
일부 Keymaster 보안 하드웨어는 키 자료를 내부적으로 저장하고 암호화된 키 자료가 아닌 핸들을 반환하도록 선택할 수 있습니다. 혹은 다른 비보안 또는 보안 환경 시스템 구성요소를 사용할 수 있을 때까지 키를 사용할 수 없는 경우도 있습니다. Keymaster HAL을 사용하면 호출자가 TAG::STANDALONE
태그를 통해 키를 '독립형'으로 요청할 수 있으며 이는 blob과 실행 중인 Keymaster 시스템 외에 다른 리소스가 필요하지 않다는 의미입니다. 키와 연결된 태그를 검사하여 키가 독립형인지 확인할 수 있습니다. 현재 다음 두 개의 값만 정의되어 있습니다.
KeyBlobUsageRequirements::STANDALONE
KeyBlobUsageRequirements::REQUIRES_FILE_SYSTEM
이 기능은 애플리케이션에 노출되지 않습니다.
속도
생성 시 최대 사용 속도는 TAG::MIN_SECONDS_BETWEEN_OPS
로 지정할 수 있습니다.
TrustZone 구현은 TAG::MIN_SECONDS_BETWEEN_OPS
초 이내에 작업이 수행되었다면 해당 키로 암호화 작업을 실행하지 않습니다.
속도 제한을 구현하는 간단한 방법은 키 ID와 마지막 사용 타임스탬프로 구성된 표를 사용하는 것입니다. 이 표의 크기는 제한될 수 있지만, 최소 16개 항목을 수용합니다. 표가 가득 차고 항목이 업데이트 또는 삭제될 수 없는 경우 보안 하드웨어 구현은 '오류가 발생하지 않도록' 항목 중 하나가 만료될 때까지 모든 속도 제한 키 연산을 거부하는 것이 좋습니다. 모든 항목은 재부팅 시 만료될 수 있습니다.
TAG::MAX_USES_PER_BOOT
를 사용하여 키를 부팅당 n번 사용하도록 제한할 수도 있습니다. 이렇게 하려면 최소 4개의 키를 수용하고 오류도 발생하지 않는 추적 표도 필요합니다. 애플리케이션은 부팅당 제한되는 키를 만들 수 없습니다. 이 기능은 키 저장소를 통해 노출되지 않으며 시스템 작업을 위해 예약되어 있습니다.
이 기능은 애플리케이션에 노출되지 않습니다.
랜덤 숫자 생성기 다시 시도하기
보안 하드웨어는 키 자료와 초기화 벡터(IV)를 위한 랜덤 숫자를 생성하며 하드웨어 랜덤 숫자 생성기가 항상 완전히 신뢰할 수 있는 것은 아니므로 Keymaster HAL은 인터페이스를 제공하여 클라이언트가 생성된 랜덤 숫자에 혼합될 추가 엔트로피를 제공할 수 있도록 합니다.
하드웨어 랜덤 숫자 생성기를 기본 시드 소스로 사용합니다. 외부 API를 통해 제공된 시드 데이터는 숫자 생성에 사용되는 임의성의 유일한 소스일 수 없습니다. 또한, 시드 소스 중 하나라도 예측할 수 없다면 사용된 혼합 연산은 랜덤 출력이 예측할 수 없는지 확인해야 합니다.
이 기능은 애플리케이션에 노출되지 않지만, 정기적으로 자바 SecureRandom 인스턴스에서 가져온 추가 엔트로피를 보안 하드웨어에 제공하는 프레임워크에서 사용합니다.