요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
=============================================
Asymmetric / Public-key Cryptography Key Type
=============================================
.. Contents:
- Overview.
- Key identification.
- Accessing asymmetric keys.
- Signature verification.
- Asymmetric key subtypes.
- Instantiation data parsers.
- Keyring link restrictions.
Overview
========
The "asymmetric" key type is designed to be a container for the keys used in
public-key cryptography, without imposing any particular restrictions on the
form or mechanism of the cryptography or form of the key.
The asymmetric key is given a subtype that defines what sort of data is
associated with the key and provides operations to describe and destroy it.
However, no requirement is made that the key data actually be stored in the
key.
A completely in-kernel key retention and operation subtype can be defined, but
it would also be possible to provide access to cryptographic hardware (such as
a TPM) that might be used to both retain the relevant key and perform
operations using that key. In such a case, the asymmetric key would then
merely be an interface to the TPM driver.
Also provided is the concept of a data parser. Data parsers are responsible
for extracting information from the blobs of data passed to the instantiation
function. The first data parser that recognises the blob gets to set the
subtype of the key and define the operations that can be done on that key.
A data parser may interpret the data blob as containing the bits representing a
key, or it may interpret it as a reference to a key held somewhere else in the
system (for example, a TPM).
Key Identification
==================
If a key is added with an empty name, the instantiation data parsers are given
the opportunity to pre-parse a key and to determine the description the key
should be given from the content of the key.
This can then be used to refer to the key, either by complete match or by
partial match. The key type may also use other criteria to refer to a key.
The asymmetric key type's match function can then perform a wider range of
comparisons than just the straightforward comparison of the description with
the criterion string:
1) If the criterion string is of the form "id:<hexdigits>" then the match
function will examine a key's fingerprint to see if the hex digits given
after the "id:" match the tail. For instance::
keyctl search @s asymmetric id:5acc2142
will match a key with fingerprint::
1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142
2) If the criterion string is of the form "<subtype>:<hexdigits>" then the
match will match the ID as in (1), but with the added restriction that
only keys of the specified subtype (e.g. tpm) will be matched. For
instance::
keyctl search @s asymmetric tpm:5acc2142
Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
displayed, along with the subtype::
1a39e171 I----- 1 perm 3f010000 0 0 asymmetric modsign.0: DSA 5acc2142 []
Accessing Asymmetric Keys
=========================
For general access to asymmetric keys from within the kernel, the following
inclusion is required::
#include <crypto/public_key.h>
This gives access to functions for dealing with asymmetric / public keys.
Three enums are defined there for representing public-key cryptography
algorithms::
enum pkey_algo
digest algorithms used by those::
enum pkey_hash_algo
and key identifier representations::
enum pkey_id_type
Note that the key type representation types are required because key
identifiers from different standards aren't necessarily compatible. For
instance, PGP generates key identifiers by hashing the key data plus some
PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers.
The operations defined upon a key are:
1) Signature verification.
Other operations are possible (such as encryption) with the same key data
required for verification, but not currently supported, and others
(eg. decryption and signature generation) require extra key data.
Signature Verification
----------------------
An operation is provided to perform cryptographic signature verification, using
an asymmetric key to provide or to provide access to the public key::
int verify_signature(const struct key *key,
const struct public_key_signature *sig);
The caller must have already obtained the key from some source and can then use
it to check the signature. The caller must have parsed the signature and
transferred the relevant bits to the structure pointed to by sig::
struct public_key_signature {
u8 *digest;
u8 digest_size;
enum pkey_hash_algo pkey_hash_algo : 8;
u8 nr_mpi;
union {
MPI mpi[2];
...
};
};
The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that
make up the actual signature must be stored in sig->mpi[] and the count of MPIs
placed in sig->nr_mpi.
In addition, the data must have been digested by the caller and the resulting
hash must be pointed to by sig->digest and the size of the hash be placed in
sig->digest_size.
The function will return 0 upon success or -EKEYREJECTED if the signature
doesn't match.
The function may also return -ENOTSUPP if an unsupported public-key algorithm
or public-key/hash algorithm combination is specified or the key doesn't
support the operation; -EBADMSG or -ERANGE if some of the parameters have weird
data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned
if the key argument is the wrong type or is incompletely set up.
Asymmetric Key Subtypes
=======================
Asymmetric keys have a subtype that defines the set of operations that can be
performed on that key and that determines what data is attached as the key
payload. The payload format is entirely at the whim of the subtype.
The subtype is selected by the key data parser and the parser must initialise
the data required for it. The asymmetric key retains a reference on the
subtype module.
The subtype definition structure can be found in::
#include <keys/asymmetric-subtype.h>
and looks like the following::
struct asymmetric_key_subtype {
struct module *owner;
const char *name;
void (*describe)(const struct key *key, struct seq_file *m);
void (*destroy)(void *payload);
int (*query)(const struct kernel_pkey_params *params,
struct kernel_pkey_query *info);
int (*eds_op)(struct kernel_pkey_params *params,
const void *in, void *out);
int (*verify_signature)(const struct key *key,
const struct public_key_signature *sig);
};
Asymmetric keys point to this with their payload[asym_subtype] member.
The owner and name fields should be set to the owning module and the name of
the subtype. Currently, the name is only used for print statements.
There are a number of operations defined by the subtype:
1) describe().
Mandatory. This allows the subtype to display something in /proc/keys
against the key. For instance the name of the public key algorithm type
could be displayed. The key type will display the tail of the key
identity string after this.
2) destroy().
Mandatory. This should free the memory associated with the key. The
asymmetric key will look after freeing the fingerprint and releasing the
reference on the subtype module.
3) query().
Mandatory. This is a function for querying the capabilities of a key.
4) eds_op().
Optional. This is the entry point for the encryption, decryption and
signature creation operations (which are distinguished by the operation ID
in the parameter struct). The subtype may do anything it likes to
implement an operation, including offloading to hardware.
5) verify_signature().
Optional. This is the entry point for signature verification. The
subtype may do anything it likes to implement an operation, including
offloading to hardware.
Instantiation Data Parsers
==========================
The asymmetric key type doesn't generally want to store or to deal with a raw
blob of data that holds the key data. It would have to parse it and error
check it each time it wanted to use it. Further, the contents of the blob may
have various checks that can be performed on it (eg. self-signatures, validity
dates) and may contain useful data about the key (identifiers, capabilities).
Also, the blob may represent a pointer to some hardware containing the key
rather than the key itself.
Examples of blob formats for which parsers could be implemented include:
- OpenPGP packet stream [RFC 4880].
- X.509 ASN.1 stream.
- Pointer to TPM key.
- Pointer to UEFI key.
- PKCS#8 private key [RFC 5208].
- PKCS#5 encrypted private key [RFC 2898].
During key instantiation each parser in the list is tried until one doesn't
return -EBADMSG.
The parser definition structure can be found in::
#include <keys/asymmetric-parser.h>
and looks like the following::
struct asymmetric_key_parser {
struct module *owner;
const char *name;
int (*parse)(struct key_preparsed_payload *prep);
};
The owner and name fields should be set to the owning module and the name of
the parser.
There is currently only a single operation defined by the parser, and it is
mandatory:
1) parse().
This is called to preparse the key from the key creation and update paths.
In particular, it is called during the key creation _before_ a key is
allocated, and as such, is permitted to provide the key's description in
the case that the caller declines to do so.
The caller passes a pointer to the following struct with all of the fields
cleared, except for data, datalen and quotalen [see
Documentation/security/keys/core.rst]::
struct key_preparsed_payload {
char *description;
void *payload[4];
const void *data;
size_t datalen;
size_t quotalen;
};
The instantiation data is in a blob pointed to by data and is datalen in
size. The parse() function is not permitted to change these two values at
all, and shouldn't change any of the other values _unless_ they are
recognise the blob format and will not return -EBADMSG to indicate it is
not theirs.
If the parser is happy with the blob, it should propose a description for
the key and attach it to ->description, ->payload[asym_subtype] should be
set to point to the subtype to be used, ->payload[asym_crypto] should be
set to point to the initialised data for that subtype,
->payload[asym_key_ids] should point to one or more hex fingerprints and
quotalen should be updated to indicate how much quota this key should
account for.
When clearing up, the data attached to ->payload[asym_key_ids] and
->description will be kfree()'d and the data attached to
->payload[asm_crypto] will be passed to the subtype's ->destroy() method
to be disposed of. A module reference for the subtype pointed to by
->payload[asym_subtype] will be put.
If the data format is not recognised, -EBADMSG should be returned. If it
is recognised, but the key cannot for some reason be set up, some other
negative error code should be returned. On success, 0 should be returned.
The key's fingerprint string may be partially matched upon. For a
public-key algorithm such as RSA and DSA this will likely be a printable
hex version of the key's fingerprint.
Functions are provided to register and unregister parsers::
int register_asymmetric_key_parser(struct asymmetric_key_parser *parser);
void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype);
Parsers may not have the same name. The names are otherwise only used for
displaying in debugging messages.
Keyring Link Restrictions
=========================
Keyrings created from userspace using add_key can be configured to check the
signature of the key being linked. Keys without a valid signature are not
allowed to link.
Several restriction methods are available:
1) Restrict using the kernel builtin trusted keyring
- Option string used with KEYCTL_RESTRICT_KEYRING:
- "builtin_trusted"
The kernel builtin trusted keyring will be searched for the signing key.
If the builtin trusted keyring is not configured, all links will be
rejected. The ca_keys kernel parameter also affects which keys are used
for signature verification.
2) Restrict using the kernel builtin and secondary trusted keyrings
- Option string used with KEYCTL_RESTRICT_KEYRING:
- "builtin_and_secondary_trusted"
The kernel builtin and secondary trusted keyrings will be searched for the
signing key. If the secondary trusted keyring is not configured, this
restriction will behave like the "builtin_trusted" option. The ca_keys
kernel parameter also affects which keys are used for signature
verification.
3) Restrict using a separate key or keyring
- Option string used with KEYCTL_RESTRICT_KEYRING:
- "key_or_keyring:<key or keyring serial number>[:chain]"
Whenever a key link is requested, the link will only succeed if the key
being linked is signed by one of the designated keys. This key may be
specified directly by providing a serial number for one asymmetric key, or
a group of keys may be searched for the signing key by providing the
serial number for a keyring.
When the "chain" option is provided at the end of the string, the keys
within the destination keyring will also be searched for signing keys.
This allows for verification of certificate chains by adding each
certificate in order (starting closest to the root) to a keyring. For
instance, one keyring can be populated with links to a set of root
certificates, with a separate, restricted keyring set up for each
certificate chain to be validated::
# Create and populate a keyring for root certificates
root_id=`keyctl add keyring root-certs "" @s`
keyctl padd asymmetric "" $root_id < root1.cert
keyctl padd asymmetric "" $root_id < root2.cert
# Create and restrict a keyring for the certificate chain
chain_id=`keyctl add keyring chain "" @s`
keyctl restrict_keyring $chain_id asymmetric key_or_keyring:$root_id:chain
# Attempt to add each certificate in the chain, starting with the
# certificate closest to the root.
keyctl padd asymmetric "" $chain_id < intermediateA.cert
keyctl padd asymmetric "" $chain_id < intermediateB.cert
keyctl padd asymmetric "" $chain_id < end-entity.cert
If the final end-entity certificate is successfully added to the "chain"
keyring, we can be certain that it has a valid signing chain going back to
one of the root certificates.
A single keyring can be used to verify a chain of signatures by
restricting the keyring after linking the root certificate::
# Create a keyring for the certificate chain and add the root
chain2_id=`keyctl add keyring chain2 "" @s`
keyctl padd asymmetric "" $chain2_id < root1.cert
# Restrict the keyring that already has root1.cert linked. The cert
# will remain linked by the keyring.
keyctl restrict_keyring $chain2_id asymmetric key_or_keyring:0:chain
# Attempt to add each certificate in the chain, starting with the
# certificate closest to the root.
keyctl padd asymmetric "" $chain2_id < intermediateA.cert
keyctl padd asymmetric "" $chain2_id < intermediateB.cert
keyctl padd asymmetric "" $chain2_id < end-entity.cert
If the final end-entity certificate is successfully added to the "chain2"
keyring, we can be certain that there is a valid signing chain going back
to the root certificate that was added before the keyring was restricted.
In all of these cases, if the signing key is found the signature of the key to
be linked will be verified using the signing key. The requested key is added
to the keyring only if the signature is successfully verified. -ENOKEY is
returned if the parent certificate could not be found, or -EKEYREJECTED is
returned if the signature check fails or the key is blacklisted. Other errors
may be returned if the signature check could not be performed.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
비대칭·공개 키 암호화 key type
1-17SPDX 라이선스 식별자: `GPL-2.0`
비대칭·공개 키 암호화 key type
문서 내용은 다음과 같습니다.
- 개요
- 키 식별
- 비대칭 키 접근과 서명 검증
- 비대칭 키 subtype
- 인스턴스화 데이터 parser
- keyring link 제한
개요
18-45개요
`asymmetric` key type은 암호 형식이나 메커니즘 또는 키 형식에 특정 제약을 두지 않으면서 공개 키 암호화에 쓰이는 키를 담는 container로 설계되었습니다.
비대칭 키에는 어떤 종류의 데이터가 키와 연관되는지 정의하고 이를 설명·폐기하는 연산을 제공하는 subtype이 지정됩니다. 그러나 실제 키 데이터가 key 객체 안에 저장되어야 한다는 요구 사항은 없습니다.
키 보관과 연산을 완전히 커널 안에서 수행하는 subtype을 정의할 수도 있고, 관련 키를 보관하면서 그 키로 연산까지 수행하는 TPM 같은 암호화 하드웨어에 대한 접근을 제공할 수도 있습니다. 후자의 경우 비대칭 키는 TPM driver의 인터페이스 역할만 합니다.
Data parser 개념도 제공됩니다. Data parser는 인스턴스화 함수에 전달된 data blob에서 정보를 추출합니다. Blob을 가장 먼저 인식한 parser가 키의 subtype을 설정하고 해당 키에서 수행할 수 있는 연산을 정의합니다.
Data parser는 blob을 키 자체를 나타내는 bit가 들어 있는 데이터로 해석할 수도 있고, 시스템의 다른 위치에 보관된 키에 대한 참조로 해석할 수도 있습니다. 예를 들어 TPM의 키를 가리킬 수 있습니다.
키 식별
46-82키 식별
빈 이름으로 키를 추가하면 인스턴스화 data parser가 키를 미리 parse하고 키 내용으로부터 부여할 description을 결정할 기회를 얻습니다.
이 description은 완전 일치 또는 부분 일치로 키를 참조하는 데 사용할 수 있습니다. Key type은 다른 기준을 사용해 키를 참조할 수도 있습니다.
비대칭 key type의 match 함수는 description과 criterion 문자열을 단순 비교하는 것보다 넓은 범위의 비교를 수행할 수 있습니다.
1. Criterion 문자열이 `id:<hexdigits>` 형식이면 match 함수는 키 fingerprint의 끝부분이 `id:` 뒤의 16진수와 일치하는지 검사합니다. 예를 들면 다음과 같습니다.
keyctl search @s asymmetric id:5acc2142
이 명령은 다음 fingerprint를 가진 키와 일치합니다.
1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142
2. Criterion 문자열이 `<subtype>:<hexdigits>` 형식이면 1번과 같은 방식으로 ID를 일치시키되 지정된 subtype의 키, 예를 들어 `tpm` 키만 대상으로 제한합니다.
keyctl search @s asymmetric tpm:5acc2142
`/proc/keys`에는 키 fingerprint의 마지막 8개 16진수와 subtype이 함께 표시됩니다.
1a39e171 I----- 1 perm 3f010000 0 0 asymmetric modsign.0: DSA 5acc2142 []
비대칭 키 접근
83-118비대칭 키 접근
커널 내부에서 비대칭 키에 일반적으로 접근하려면 다음 header를 포함해야 합니다.
#include <crypto/public_key.h>
이 header는 비대칭·공개 키를 다루는 함수에 대한 접근을 제공합니다. 공개 키 암호화 알고리즘을 표현하는 enum은 다음과 같습니다.
enum pkey_algo
해당 알고리즘이 사용하는 digest 알고리즘 enum은 다음과 같습니다.
enum pkey_hash_algo
키 식별자 표현 enum은 다음과 같습니다.
enum pkey_id_type
표준마다 키 식별자가 반드시 호환되는 것은 아니므로 key type 표현 유형이 필요합니다. 예를 들어 PGP는 키 데이터와 PGP 전용 metadata를 함께 hash하여 키 식별자를 만들지만 X.509는 임의의 certificate 식별자를 가집니다.
현재 키에 정의된 연산은 서명 검증입니다.
검증에 필요한 것과 같은 키 데이터로 암호화 같은 다른 연산도 가능하지만 현재 지원하지 않습니다. 복호화와 서명 생성 같은 연산에는 추가 키 데이터가 필요합니다.
서명 검증
119-160서명 검증
비대칭 키를 통해 공개 키를 제공하거나 공개 키에 접근하여 암호학적 서명을 검증하는 연산이 제공됩니다.
int verify_signature(const struct key *key,
const struct public_key_signature *sig);
호출자는 어떤 source에서든 키를 미리 얻어야 하며 그 키로 서명을 검사할 수 있습니다. 또한 서명을 parse하고 관련 bit를 `sig`가 가리키는 구조체에 옮겨야 합니다.
struct public_key_signature {
u8 *digest;
u8 digest_size;
enum pkey_hash_algo pkey_hash_algo : 8;
u8 nr_mpi;
union {
MPI mpi[2];
...
};
};
사용한 알고리즘은 `sig->pkey_hash_algo`에 기록해야 합니다. 실제 서명을 이루는 모든 MPI는 `sig->mpi[]`에 저장하고 MPI 개수는 `sig->nr_mpi`에 넣어야 합니다.
호출자는 데이터의 digest도 미리 계산해야 합니다. 결과 hash는 `sig->digest`가 가리키게 하고 hash 크기는 `sig->digest_size`에 넣습니다.
함수는 성공하면 0을 반환하고 서명이 일치하지 않으면 `-EKEYREJECTED`를 반환합니다.
지원하지 않는 공개 키 알고리즘 또는 공개 키·hash 알고리즘 조합을 지정했거나 키가 연산을 지원하지 않으면 `-ENOTSUPP`를 반환할 수 있습니다. 일부 매개변수 데이터가 잘못되면 `-EBADMSG` 또는 `-ERANGE`, 메모리를 할당할 수 없으면 `-ENOMEM`, key 인수의 type이 잘못되었거나 설정이 불완전하면 `-EINVAL`을 반환할 수 있습니다.
비대칭 키 subtype
161-228비대칭 키 subtype
비대칭 키의 subtype은 해당 키에서 수행할 수 있는 연산 집합과 key payload에 연결되는 데이터를 결정합니다. Payload 형식은 subtype이 전적으로 결정합니다.
Subtype은 key data parser가 선택하며 parser가 subtype에 필요한 데이터를 초기화해야 합니다. 비대칭 키는 subtype module의 참조를 유지합니다.
Subtype 정의 구조체는 다음 header에 있습니다.
#include <keys/asymmetric-subtype.h>
구조체의 형태는 다음과 같습니다.
struct asymmetric_key_subtype {
struct module *owner;
const char *name;
void (*describe)(const struct key *key, struct seq_file *m);
void (*destroy)(void *payload);
int (*query)(const struct kernel_pkey_params *params,
struct kernel_pkey_query *info);
int (*eds_op)(struct kernel_pkey_params *params,
const void *in, void *out);
int (*verify_signature)(const struct key *key,
const struct public_key_signature *sig);
};
비대칭 키는 `payload[asym_subtype]` member로 이 구조체를 가리킵니다.
`owner`와 `name` field에는 소유 module과 subtype 이름을 설정해야 합니다. 현재 이름은 출력문에서만 사용됩니다.
Subtype에는 다음 연산이 정의됩니다.
- `describe()`는 필수입니다. Subtype이 키에 관해 `/proc/keys`에 정보를 표시하게 하며, 공개 키 알고리즘 type 이름 등을 보여 줄 수 있습니다. Key type은 그 뒤에 키 identity 문자열의 끝부분을 표시합니다.
- `destroy()`는 필수입니다. 키와 연결된 메모리를 해제해야 합니다. 비대칭 key type이 fingerprint 해제와 subtype module 참조 반환을 처리합니다.
- `query()`는 필수이며 키의 capability를 조회합니다.
- `eds_op()`는 선택 사항이며 encryption, decryption, signature 생성 연산의 진입점입니다. 연산은 parameter 구조체의 operation ID로 구분합니다. Hardware offload를 포함하여 subtype이 원하는 방식으로 구현할 수 있습니다.
- `verify_signature()`는 선택 사항이며 서명 검증의 진입점입니다. Hardware offload를 포함하여 subtype이 원하는 방식으로 구현할 수 있습니다.
인스턴스화 data parser
229-328인스턴스화 data parser
비대칭 key type은 일반적으로 키 데이터를 담은 raw blob을 직접 저장하거나 처리하지 않습니다. 그렇게 하면 사용할 때마다 parse와 error 검사를 해야 합니다. Blob에는 self-signature와 validity date 같은 검사 대상이 있을 수 있고 identifier와 capability처럼 유용한 키 정보가 들어 있을 수도 있습니다.
Blob은 키 자체가 아니라 키를 담은 hardware를 가리키는 pointer를 나타낼 수도 있습니다.
Parser를 구현할 수 있는 blob 형식의 예는 다음과 같습니다.
- OpenPGP packet stream [RFC 4880]
- X.509 ASN.1 stream
- TPM key를 가리키는 pointer
- UEFI key를 가리키는 pointer
- PKCS#8 private key [RFC 5208]
- PKCS#5 encrypted private key [RFC 2898]
키를 인스턴스화할 때 목록의 각 parser를 차례로 시도하여 `-EBADMSG`가 아닌 값을 반환하는 parser를 찾습니다.
Parser 정의 구조체는 다음 header에 있습니다.
#include <keys/asymmetric-parser.h>
구조체의 형태는 다음과 같습니다.
struct asymmetric_key_parser {
struct module *owner;
const char *name;
int (*parse)(struct key_preparsed_payload *prep);
};
`owner`와 `name` field에는 소유 module과 parser 이름을 설정해야 합니다.
현재 parser에 정의된 연산은 필수인 `parse()` 하나뿐입니다. 이 함수는 키 생성 및 갱신 경로에서 키를 preparse할 때 호출됩니다. 특히 key 객체를 할당하기 전 키 생성 중에 호출되므로, 호출자가 description을 제공하지 않은 경우 키 description을 제안할 수 있습니다.
호출자는 `data`, `datalen`, `quotalen`을 제외한 모든 field가 초기화된 다음 구조체의 pointer를 전달합니다. 관련 설명은 `Documentation/security/keys/core.rst`에 있습니다.
struct key_preparsed_payload {
char *description;
void *payload[4];
const void *data;
size_t datalen;
size_t quotalen;
};
인스턴스화 데이터는 `data`가 가리키는 `datalen` 크기의 blob입니다. `parse()`는 두 값을 변경할 수 없습니다. 또한 blob 형식을 인식하여 자신의 데이터가 아님을 뜻하는 `-EBADMSG`를 반환하지 않을 경우가 아니라면 다른 값도 변경해서는 안 됩니다.
Parser가 blob을 받아들이면 키 description을 제안하여 `->description`에 연결해야 합니다. `->payload[asym_subtype]`은 사용할 subtype, `->payload[asym_crypto]`는 해당 subtype용으로 초기화한 데이터, `->payload[asym_key_ids]`는 하나 이상의 16진수 fingerprint를 가리켜야 합니다. `quotalen`은 이 키가 차지할 quota를 나타내도록 갱신해야 합니다.
정리할 때 `->payload[asym_key_ids]`와 `->description`의 데이터는 `kfree()`로 해제됩니다. 원문에서 `->payload[asm_crypto]`로 표기된 데이터는 subtype의 `->destroy()` method에 전달되어 폐기됩니다. `->payload[asym_subtype]`이 가리키는 subtype의 module 참조도 반환됩니다.
Data 형식을 인식하지 못하면 `-EBADMSG`를 반환해야 합니다. 형식은 인식했지만 어떤 이유로 키를 설정할 수 없으면 다른 음수 error code를 반환하고, 성공하면 0을 반환합니다.
키 fingerprint 문자열은 부분 일치가 가능합니다. RSA와 DSA 같은 공개 키 알고리즘에서는 보통 키 fingerprint를 출력 가능한 16진수로 나타냅니다.
Parser를 등록하고 등록 해제하는 함수가 제공됩니다.
int register_asymmetric_key_parser(struct asymmetric_key_parser *parser);
void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype);
Parser는 같은 이름을 사용할 수 없습니다. 그 밖에는 이름이 debugging message 표시에만 사용됩니다.
Keyring link 제한
329-424Keyring link 제한
사용자 공간에서 `add_key`로 만든 keyring은 link할 키의 서명을 검사하도록 구성할 수 있습니다. 유효한 서명이 없는 키는 link할 수 없습니다.
다음과 같은 제한 방법을 사용할 수 있습니다.
1. 커널 builtin trusted keyring으로 제한합니다. `KEYCTL_RESTRICT_KEYRING`에 사용하는 option 문자열은 `builtin_trusted`입니다. 서명 키를 kernel builtin trusted keyring에서 검색합니다. 이 keyring이 구성되지 않았으면 모든 link를 거부합니다. `ca_keys` kernel parameter도 서명 검증에 사용할 키에 영향을 줍니다.
2. 커널 builtin 및 secondary trusted keyring으로 제한합니다. Option 문자열은 `builtin_and_secondary_trusted`입니다. 두 trusted keyring에서 서명 키를 검색합니다. Secondary trusted keyring이 구성되지 않았으면 `builtin_trusted`처럼 동작합니다. `ca_keys` kernel parameter도 서명 검증 키에 영향을 줍니다.
3. 별도의 key 또는 keyring으로 제한합니다. Option 문자열은 `key_or_keyring:<key or keyring serial number>[:chain]`입니다. Key link 요청은 link 대상 키가 지정된 키 중 하나로 서명되었을 때만 성공합니다. 비대칭 키 하나의 serial number를 직접 지정하거나 keyring serial number를 제공하여 키 집합에서 서명 키를 검색할 수 있습니다.
문자열 끝에 `chain` option을 붙이면 destination keyring 안의 키도 서명 키 검색 대상이 됩니다. 따라서 root에 가장 가까운 certificate부터 순서대로 keyring에 추가하여 certificate chain을 검증할 수 있습니다. 예를 들어 root certificate 집합을 담은 keyring과 검증할 certificate chain마다 별도로 제한된 keyring을 구성할 수 있습니다.
# Create and populate a keyring for root certificates
root_id=`keyctl add keyring root-certs "" @s`
keyctl padd asymmetric "" $root_id < root1.cert
keyctl padd asymmetric "" $root_id < root2.cert
# Create and restrict a keyring for the certificate chain
chain_id=`keyctl add keyring chain "" @s`
keyctl restrict_keyring $chain_id asymmetric key_or_keyring:$root_id:chain
# Attempt to add each certificate in the chain, starting with the
# certificate closest to the root.
keyctl padd asymmetric "" $chain_id < intermediateA.cert
keyctl padd asymmetric "" $chain_id < intermediateB.cert
keyctl padd asymmetric "" $chain_id < end-entity.cert
마지막 end-entity certificate가 `chain` keyring에 성공적으로 추가되면 root certificate 중 하나까지 이어지는 유효한 서명 chain이 있음을 확신할 수 있습니다.
Root certificate를 link한 다음 keyring을 제한하면 하나의 keyring만으로도 서명 chain을 검증할 수 있습니다.
# Create a keyring for the certificate chain and add the root
chain2_id=`keyctl add keyring chain2 "" @s`
keyctl padd asymmetric "" $chain2_id < root1.cert
# Restrict the keyring that already has root1.cert linked. The cert
# will remain linked by the keyring.
keyctl restrict_keyring $chain2_id asymmetric key_or_keyring:0:chain
# Attempt to add each certificate in the chain, starting with the
# certificate closest to the root.
keyctl padd asymmetric "" $chain2_id < intermediateA.cert
keyctl padd asymmetric "" $chain2_id < intermediateB.cert
keyctl padd asymmetric "" $chain2_id < end-entity.cert
마지막 end-entity certificate가 `chain2` keyring에 성공적으로 추가되면 keyring 제한 전에 추가한 root certificate까지 이어지는 유효한 서명 chain이 있음을 확신할 수 있습니다.
모든 방법에서 서명 키를 찾으면 그 키로 link 대상 키의 서명을 검증합니다. 서명 검증에 성공한 경우에만 요청한 키를 keyring에 추가합니다. Parent certificate를 찾지 못하면 `-ENOKEY`, 서명 검사가 실패하거나 키가 blacklist에 있으면 `-EKEYREJECTED`를 반환합니다. 서명 검사를 수행할 수 없는 경우 다른 error가 반환될 수 있습니다.
요약과 해설
asymmetric-keys.rst:1-424이 문서는 Linux key retention service에서 공개 키를 표현하는 `asymmetric` key type을 설명합니다. 실제 키가 커널 payload에 있을 수도 있고 TPM 같은 hardware에 있을 수도 있으며, parser와 subtype이 데이터 형식과 연산을 분리합니다.
실무적으로는 fingerprint 기반 키 검색, `verify_signature()`의 입력과 error, subtype·parser callback 계약, `KEYCTL_RESTRICT_KEYRING`으로 trusted key와 certificate chain을 강제하는 방법이 핵심입니다. 모든 C 선언과 keyctl 명령은 원문 그대로 보존했습니다.