← Documents Documentation/crypto/devel-algos.rst GitHub 원문 ↗

Linux 6.18.37 · Crypto

Developing Cipher Algorithms

Crypto transform 등록·해제, 단일·다중 블록 대칭 암호와 HASH 구현 구조체, callback 호출 순서, ScatterWalk 및 request resource 계약을 설명합니다.

Source pathDocumentation/crypto/devel-algos.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

devel-algos.rst:1-238

알고리즘 개발자는 일반 transform, CIPHER, SKCIPHER, SHASH, AHASH 각각의 등록 함수와 `struct crypto_alg`, `cipher_alg`, `skcipher_alg`, `shash_alg`, `ahash_alg` callback 계약을 맞춰야 합니다.

이 문서에서 중요한 안전 규칙은 진행 중인 연산 사이에 key를 바꾸지 않는 것, unaligned request의 realignment 비용을 고려하는 것, HASH request가 final 없이 포기될 수 있으므로 init·update 뒤에 정리되지 않은 resource를 남기지 않는 것입니다. 원문의 네 ASCII 호출 흐름은 구조화 도식으로 다시 구성했습니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 Developing Cipher Algorithms
2 ============================
3
4 Registering And Unregistering Transformation
5 --------------------------------------------
6
7 There are three distinct types of registration functions in the Crypto
8 API. One is used to register a generic cryptographic transformation,
9 while the other two are specific to HASH transformations and
10 COMPRESSion. We will discuss the latter two in a separate chapter, here
11 we will only look at the generic ones.
12
13 Before discussing the register functions, the data structure to be
14 filled with each, struct crypto_alg, must be considered -- see below
15 for a description of this data structure.
16
17 The generic registration functions can be found in
18 include/linux/crypto.h and their definition can be seen below. The
19 former function registers a single transformation, while the latter
20 works on an array of transformation descriptions. The latter is useful
21 when registering transformations in bulk, for example when a driver
22 implements multiple transformations.
23
24 ::
25
26 int crypto_register_alg(struct crypto_alg *alg);
27 int crypto_register_algs(struct crypto_alg *algs, int count);
28
29
30 The counterparts to those functions are listed below.
31
32 ::
33
34 void crypto_unregister_alg(struct crypto_alg *alg);
35 void crypto_unregister_algs(struct crypto_alg *algs, int count);
36
37
38 The registration functions return 0 on success, or a negative errno
39 value on failure. crypto_register_algs() succeeds only if it
40 successfully registered all the given algorithms; if it fails partway
41 through, then any changes are rolled back.
42
43 The unregistration functions always succeed, so they don't have a
44 return value. Don't try to unregister algorithms that aren't
45 currently registered.
46
47 Single-Block Symmetric Ciphers [CIPHER]
48 ---------------------------------------
49
50 Example of transformations: aes, serpent, ...
51
52 This section describes the simplest of all transformation
53 implementations, that being the CIPHER type used for symmetric ciphers.
54 The CIPHER type is used for transformations which operate on exactly one
55 block at a time and there are no dependencies between blocks at all.
56
57 Registration specifics
58 ~~~~~~~~~~~~~~~~~~~~~~
59
60 The registration of [CIPHER] algorithm is specific in that struct
61 crypto_alg field .cra_type is empty. The .cra_u.cipher has to be
62 filled in with proper callbacks to implement this transformation.
63
64 See struct cipher_alg below.
65
66 Cipher Definition With struct cipher_alg
67 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68
69 Struct cipher_alg defines a single block cipher.
70
71 Here are schematics of how these functions are called when operated from
72 other part of the kernel. Note that the .cia_setkey() call might happen
73 before or after any of these schematics happen, but must not happen
74 during any of these are in-flight.
75
76 ::
77
78 KEY ---. PLAINTEXT ---.
79 v v
80 .cia_setkey() -> .cia_encrypt()
81 |
82 '-----> CIPHERTEXT
83
84
85 Please note that a pattern where .cia_setkey() is called multiple times
86 is also valid:
87
88 ::
89
90
91 KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --.
92 v v v v
93 .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()
94 | |
95 '---> CIPHERTEXT1 '---> CIPHERTEXT2
96
97
98 Multi-Block Ciphers
99 -------------------
100
101 Example of transformations: cbc(aes), chacha20, ...
102
103 This section describes the multi-block cipher transformation
104 implementations. The multi-block ciphers are used for transformations
105 which operate on scatterlists of data supplied to the transformation
106 functions. They output the result into a scatterlist of data as well.
107
108 Registration Specifics
109 ~~~~~~~~~~~~~~~~~~~~~~
110
111 The registration of multi-block cipher algorithms is one of the most
112 standard procedures throughout the crypto API.
113
114 Note, if a cipher implementation requires a proper alignment of data,
115 the caller should use the functions of crypto_skcipher_alignmask() to
116 identify a memory alignment mask. The kernel crypto API is able to
117 process requests that are unaligned. This implies, however, additional
118 overhead as the kernel crypto API needs to perform the realignment of
119 the data which may imply moving of data.
120
121 Cipher Definition With struct skcipher_alg
122 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123
124 Struct skcipher_alg defines a multi-block cipher, or more generally, a
125 length-preserving symmetric cipher algorithm.
126
127 Scatterlist handling
128 ~~~~~~~~~~~~~~~~~~~~
129
130 Some drivers will want to use the Generic ScatterWalk in case the
131 hardware needs to be fed separate chunks of the scatterlist which
132 contains the plaintext and will contain the ciphertext. Please refer
133 to the ScatterWalk interface offered by the Linux kernel scatter /
134 gather list implementation.
135
136 Hashing [HASH]
137 --------------
138
139 Example of transformations: crc32, md5, sha1, sha256,...
140
141 Registering And Unregistering The Transformation
142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143
144 There are multiple ways to register a HASH transformation, depending on
145 whether the transformation is synchronous [SHASH] or asynchronous
146 [AHASH] and the amount of HASH transformations we are registering. You
147 can find the prototypes defined in include/crypto/internal/hash.h:
148
149 ::
150
151 int crypto_register_ahash(struct ahash_alg *alg);
152
153 int crypto_register_shash(struct shash_alg *alg);
154 int crypto_register_shashes(struct shash_alg *algs, int count);
155
156
157 The respective counterparts for unregistering the HASH transformation
158 are as follows:
159
160 ::
161
162 void crypto_unregister_ahash(struct ahash_alg *alg);
163
164 void crypto_unregister_shash(struct shash_alg *alg);
165 void crypto_unregister_shashes(struct shash_alg *algs, int count);
166
167
168 Cipher Definition With struct shash_alg and ahash_alg
169 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170
171 Here are schematics of how these functions are called when operated from
172 other part of the kernel. Note that the .setkey() call might happen
173 before or after any of these schematics happen, but must not happen
174 during any of these are in-flight. Please note that calling .init()
175 followed immediately by .final() is also a perfectly valid
176 transformation.
177
178 ::
179
180 I) DATA -----------.
181 v
182 .init() -> .update() -> .final() ! .update() might not be called
183 ^ | | at all in this scenario.
184 '----' '---> HASH
185
186 II) DATA -----------.-----------.
187 v v
188 .init() -> .update() -> .finup() ! .update() may not be called
189 ^ | | at all in this scenario.
190 '----' '---> HASH
191
192 III) DATA -----------.
193 v
194 .digest() ! The entire process is handled
195 | by the .digest() call.
196 '---------------> HASH
197
198
199 Here is a schematic of how the .export()/.import() functions are called
200 when used from another part of the kernel.
201
202 ::
203
204 KEY--. DATA--.
205 v v ! .update() may not be called
206 .setkey() -> .init() -> .update() -> .export() at all in this scenario.
207 ^ | |
208 '-----' '--> PARTIAL_HASH
209
210 ----------- other transformations happen here -----------
211
212 PARTIAL_HASH--. DATA1--.
213 v v
214 .import -> .update() -> .final() ! .update() may not be called
215 ^ | | at all in this scenario.
216 '----' '--> HASH1
217
218 PARTIAL_HASH--. DATA2-.
219 v v
220 .import -> .finup()
221 |
222 '---------------> HASH2
223
224 Note that it is perfectly legal to "abandon" a request object:
225 - call .init() and then (as many times) .update()
226 - _not_ call any of .final(), .finup() or .export() at any point in future
227
228 In other words implementations should mind the resource allocation and clean-up.
229 No resources related to request objects should remain allocated after a call
230 to .init() or .update(), since there might be no chance to free them.
231
232
233 Specifics Of Asynchronous HASH Transformation
234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235
236 Some of the drivers will want to use the Generic ScatterWalk in case the
237 implementation needs to be fed separate chunks of the scatterlist which
238 contains the input data.
239

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

암호 알고리즘 개발

1-3

암호 알고리즘 개발

Transform 등록과 등록 해제

4-46

Transform 등록과 등록 해제

Crypto API에는 서로 다른 세 종류의 등록 함수가 있습니다. 하나는 일반 암호 transform을 등록하고 나머지 두 종류는 HASH transform과 COMPRESSion 전용입니다. 뒤의 두 종류는 별도 장에서 다루며 여기서는 일반 등록 함수만 설명합니다.

등록 함수를 논의하기 전에 각 함수에 채워 전달할 `struct crypto_alg` data 구조를 고려해야 합니다. 이 구조는 아래에서 설명합니다.

일반 등록 함수는 `include/linux/crypto.h`에 있습니다. 첫 함수는 transform 하나를 등록하고 둘째 함수는 transform description 배열을 처리합니다. Driver가 여러 transform을 구현하여 한꺼번에 등록할 때 둘째 함수가 유용합니다.

::

       int crypto_register_alg(struct crypto_alg *alg);
       int crypto_register_algs(struct crypto_alg *algs, int count);

대응하는 등록 해제 함수는 다음과 같습니다.

::

       void crypto_unregister_alg(struct crypto_alg *alg);
       void crypto_unregister_algs(struct crypto_alg *algs, int count);

등록 함수는 성공하면 0, 실패하면 음수 errno를 반환합니다. `crypto_register_algs()`는 주어진 모든 알고리즘을 등록해야 성공하며, 중간에 실패하면 이미 적용한 변경도 rollback합니다.

등록 해제 함수는 항상 성공하므로 반환값이 없습니다. 현재 등록되지 않은 알고리즘의 등록을 해제하려고 해서는 안 됩니다.

단일 블록 대칭 암호와 등록

47-65

단일 블록 대칭 암호 [CIPHER]

Transform 예: `aes`, `serpent` 등

이 절은 가장 단순한 transform 구현인 대칭 암호용 CIPHER type을 설명합니다. CIPHER type은 정확히 한 블록씩 처리하고 블록 사이 dependency가 전혀 없는 transform에 사용합니다.

등록 세부 사항

[CIPHER] 알고리즘을 등록할 때는 `struct crypto_alg`의 `.cra_type` field를 비워 둡니다. 이 transform을 구현하는 적절한 callback으로 `.cra_u.cipher`를 채워야 합니다.

아래의 `struct cipher_alg` 설명을 참조하십시오.

struct cipher_alg 정의와 호출 흐름

66-97

`struct cipher_alg`을 사용하는 cipher 정의

`struct cipher_alg`은 단일 블록 암호를 정의합니다.

다음 구조도는 커널의 다른 부분에서 이 함수들이 호출되는 방식을 보여 줍니다. `.cia_setkey()`는 구조도 흐름 전이나 후에 호출할 수 있지만, 어떤 연산이 진행 중일 때 호출해서는 안 됩니다.

단일 블록 암호 호출
KEY.cia_setkey().cia_encrypt(PLAINTEXT)CIPHERTEXT

Key 설정 후 plaintext 한 블록을 암호화하여 ciphertext를 만듭니다.

`.cia_setkey()`를 여러 번 호출하는 pattern도 유효합니다.

여러 key를 순차적으로 사용하는 호출
KEY1.cia_setkey().cia_encrypt(PLAINTEXT1)CIPHERTEXT1KEY2.cia_setkey().cia_encrypt(PLAINTEXT2)CIPHERTEXT2

각 key 설정은 대응하는 암호화가 끝난 뒤 다음 key로 교체됩니다.

다중 블록 암호

98-135

다중 블록 암호

Transform 예: `cbc(aes)`, `chacha20` 등

다중 블록 암호 transform은 함수에 제공된 data scatterlist에서 연산하고 결과도 data scatterlist에 출력합니다.

등록 세부 사항

다중 블록 암호 알고리즘 등록은 Crypto API 전반에서 사용하는 가장 표준적인 절차 중 하나입니다.

암호 구현에 특정 data alignment가 필요하면 호출자는 `crypto_skcipher_alignmask()` 계열 함수로 memory alignment mask를 확인해야 합니다. 커널 Crypto API는 정렬되지 않은 request도 처리할 수 있지만 data를 옮길 수 있는 realignment 작업이 필요하므로 추가 overhead가 생깁니다.

`struct skcipher_alg`을 사용하는 cipher 정의

`struct skcipher_alg`은 다중 블록 암호, 더 일반적으로는 길이를 보존하는 대칭 암호 알고리즘을 정의합니다.

Scatterlist 처리

Hardware에 plaintext가 들어 있고 ciphertext가 들어갈 scatterlist를 분리된 chunk로 공급해야 하는 driver는 Generic ScatterWalk를 사용할 수 있습니다. Linux kernel scatter/gather list 구현이 제공하는 ScatterWalk interface를 참조하십시오.

HASH 등록과 등록 해제

136-167

Hashing [HASH]

Transform 예: `crc32`, `md5`, `sha1`, `sha256` 등

Transform 등록과 등록 해제

HASH transform을 등록하는 방법은 동기 [SHASH]인지 비동기 [AHASH]인지와 등록할 HASH transform 수에 따라 여러 가지입니다. Prototype은 `include/crypto/internal/hash.h`에 정의되어 있습니다.

::

       int crypto_register_ahash(struct ahash_alg *alg);

       int crypto_register_shash(struct shash_alg *alg);
       int crypto_register_shashes(struct shash_alg *algs, int count);

대응하는 HASH transform 등록 해제 함수는 다음과 같습니다.

::

       void crypto_unregister_ahash(struct ahash_alg *alg);

       void crypto_unregister_shash(struct shash_alg *alg);
       void crypto_unregister_shashes(struct shash_alg *algs, int count);

struct shash_alg·ahash_alg 정의와 호출 흐름

168-232

`struct shash_alg`과 `ahash_alg`을 사용하는 cipher 정의

다음 구조도는 커널의 다른 부분에서 함수가 호출되는 방식을 보여 줍니다. `.setkey()`는 이러한 흐름 전이나 후에 호출할 수 있지만 진행 중에는 호출할 수 없습니다. `.init()` 직후 `.final()`을 호출하는 것도 완전히 유효한 transform입니다.

HASH 계산 호출 방식
DATA.init().update() (0회 이상).final()HASH
DATA.init().update() (0회 이상).finup()HASH
DATA.digest()HASH

Update는 0회 이상 호출할 수 있으며 digest는 전체 과정을 한 번에 수행합니다.

다음 구조도는 커널의 다른 부분에서 `.export()`와 `.import()`를 사용하는 방식을 보여 줍니다.

부분 HASH export·import
KEY.setkey().init().update() (0회 이상).export()PARTIAL_HASH
PARTIAL_HASH.import().update() (0회 이상).final()HASH1
PARTIAL_HASH.import().finup()HASH2

부분 상태를 export한 뒤 여러 후속 transform에서 import하여 서로 다른 hash를 완성할 수 있습니다.

Request 객체를 포기하는 것도 완전히 허용됩니다.

  • `.init()`을 호출한 뒤 `.update()`를 원하는 횟수만큼 호출합니다.
  • 이후 어느 시점에도 `.final()`, `.finup()`, `.export()`를 호출하지 않을 수 있습니다.

따라서 구현은 resource 할당과 정리를 주의해야 합니다. 해제할 기회가 없을 수 있으므로 `.init()` 또는 `.update()` 반환 후 request 객체 관련 resource가 할당된 채 남아서는 안 됩니다.

비동기 HASH transform 세부 사항

233-238

비동기 HASH transform 세부 사항

구현에 input data scatterlist를 분리된 chunk로 공급해야 하는 driver는 Generic ScatterWalk를 사용할 수 있습니다.