]>
Commit | Line | Data |
---|---|---|
e28facde SM |
1 | /* |
2 | * Key Wrapping: RFC3394 / NIST SP800-38F | |
3 | * | |
4 | * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de> | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, and the entire permission notice in its entirety, | |
11 | * including the disclaimer of warranties. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. The name of the author may not be used to endorse or promote | |
16 | * products derived from this software without specific prior | |
17 | * written permission. | |
18 | * | |
19 | * ALTERNATIVELY, this product may be distributed under the terms of | |
20 | * the GNU General Public License, in which case the provisions of the GPL2 | |
21 | * are required INSTEAD OF the above restrictions. (This clause is | |
22 | * necessary due to a potential bad interaction between the GPL and | |
23 | * the restrictions contained in a BSD-style copyright.) | |
24 | * | |
25 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
26 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
27 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
28 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
31 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
32 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
35 | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH | |
36 | * DAMAGE. | |
37 | */ | |
38 | ||
39 | /* | |
40 | * Note for using key wrapping: | |
41 | * | |
42 | * * The result of the encryption operation is the ciphertext starting | |
43 | * with the 2nd semiblock. The first semiblock is provided as the IV. | |
44 | * The IV used to start the encryption operation is the default IV. | |
45 | * | |
46 | * * The input for the decryption is the first semiblock handed in as an | |
47 | * IV. The ciphertext is the data starting with the 2nd semiblock. The | |
48 | * return code of the decryption operation will be EBADMSG in case an | |
49 | * integrity error occurs. | |
50 | * | |
51 | * To obtain the full result of an encryption as expected by SP800-38F, the | |
52 | * caller must allocate a buffer of plaintext + 8 bytes: | |
53 | * | |
54 | * unsigned int datalen = ptlen + crypto_skcipher_ivsize(tfm); | |
55 | * u8 data[datalen]; | |
56 | * u8 *iv = data; | |
57 | * u8 *pt = data + crypto_skcipher_ivsize(tfm); | |
58 | * <ensure that pt contains the plaintext of size ptlen> | |
6b611d98 | 59 | * sg_init_one(&sg, pt, ptlen); |
e28facde SM |
60 | * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); |
61 | * | |
62 | * ==> After encryption, data now contains full KW result as per SP800-38F. | |
63 | * | |
64 | * In case of decryption, ciphertext now already has the expected length | |
65 | * and must be segmented appropriately: | |
66 | * | |
67 | * unsigned int datalen = CTLEN; | |
68 | * u8 data[datalen]; | |
69 | * <ensure that data contains full ciphertext> | |
70 | * u8 *iv = data; | |
71 | * u8 *ct = data + crypto_skcipher_ivsize(tfm); | |
72 | * unsigned int ctlen = datalen - crypto_skcipher_ivsize(tfm); | |
6b611d98 EB |
73 | * sg_init_one(&sg, ct, ctlen); |
74 | * skcipher_request_set_crypt(req, &sg, &sg, ctlen, iv); | |
e28facde SM |
75 | * |
76 | * ==> After decryption (which hopefully does not return EBADMSG), the ct | |
77 | * pointer now points to the plaintext of size ctlen. | |
78 | * | |
79 | * Note 2: KWP is not implemented as this would defy in-place operation. | |
80 | * If somebody wants to wrap non-aligned data, he should simply pad | |
81 | * the input with zeros to fill it up to the 8 byte boundary. | |
82 | */ | |
83 | ||
84 | #include <linux/module.h> | |
85 | #include <linux/crypto.h> | |
86 | #include <linux/scatterlist.h> | |
87 | #include <crypto/scatterwalk.h> | |
88 | #include <crypto/internal/skcipher.h> | |
89 | ||
e28facde SM |
90 | struct crypto_kw_block { |
91 | #define SEMIBSIZE 8 | |
9e49451d SM |
92 | __be64 A; |
93 | __be64 R; | |
e28facde SM |
94 | }; |
95 | ||
e28facde SM |
96 | /* |
97 | * Fast forward the SGL to the "end" length minus SEMIBSIZE. | |
98 | * The start in the SGL defined by the fast-forward is returned with | |
99 | * the walk variable | |
100 | */ | |
101 | static void crypto_kw_scatterlist_ff(struct scatter_walk *walk, | |
102 | struct scatterlist *sg, | |
103 | unsigned int end) | |
104 | { | |
105 | unsigned int skip = 0; | |
106 | ||
107 | /* The caller should only operate on full SEMIBLOCKs. */ | |
108 | BUG_ON(end < SEMIBSIZE); | |
109 | ||
110 | skip = end - SEMIBSIZE; | |
111 | while (sg) { | |
112 | if (sg->length > skip) { | |
113 | scatterwalk_start(walk, sg); | |
114 | scatterwalk_advance(walk, skip); | |
115 | break; | |
116 | } else | |
117 | skip -= sg->length; | |
118 | ||
119 | sg = sg_next(sg); | |
120 | } | |
121 | } | |
122 | ||
6b611d98 | 123 | static int crypto_kw_decrypt(struct skcipher_request *req) |
e28facde | 124 | { |
6b611d98 EB |
125 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
126 | struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); | |
9e49451d | 127 | struct crypto_kw_block block; |
6b611d98 EB |
128 | struct scatterlist *src, *dst; |
129 | u64 t = 6 * ((req->cryptlen) >> 3); | |
9e49451d | 130 | unsigned int i; |
e28facde SM |
131 | int ret = 0; |
132 | ||
133 | /* | |
134 | * Require at least 2 semiblocks (note, the 3rd semiblock that is | |
135 | * required by SP800-38F is the IV. | |
136 | */ | |
6b611d98 | 137 | if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) |
e28facde SM |
138 | return -EINVAL; |
139 | ||
140 | /* Place the IV into block A */ | |
6b611d98 | 141 | memcpy(&block.A, req->iv, SEMIBSIZE); |
e28facde SM |
142 | |
143 | /* | |
144 | * src scatterlist is read-only. dst scatterlist is r/w. During the | |
6b611d98 EB |
145 | * first loop, src points to req->src and dst to req->dst. For any |
146 | * subsequent round, the code operates on req->dst only. | |
e28facde | 147 | */ |
6b611d98 EB |
148 | src = req->src; |
149 | dst = req->dst; | |
e28facde SM |
150 | |
151 | for (i = 0; i < 6; i++) { | |
e28facde | 152 | struct scatter_walk src_walk, dst_walk; |
6b611d98 | 153 | unsigned int nbytes = req->cryptlen; |
e28facde | 154 | |
6b611d98 EB |
155 | while (nbytes) { |
156 | /* move pointer by nbytes in the SGL */ | |
157 | crypto_kw_scatterlist_ff(&src_walk, src, nbytes); | |
e28facde | 158 | /* get the source block */ |
9e49451d | 159 | scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, |
e28facde SM |
160 | false); |
161 | ||
e28facde | 162 | /* perform KW operation: modify IV with counter */ |
9e49451d | 163 | block.A ^= cpu_to_be64(t); |
e28facde SM |
164 | t--; |
165 | /* perform KW operation: decrypt block */ | |
6b611d98 EB |
166 | crypto_cipher_decrypt_one(cipher, (u8 *)&block, |
167 | (u8 *)&block); | |
e28facde | 168 | |
6b611d98 EB |
169 | /* move pointer by nbytes in the SGL */ |
170 | crypto_kw_scatterlist_ff(&dst_walk, dst, nbytes); | |
e28facde | 171 | /* Copy block->R into place */ |
9e49451d | 172 | scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, |
e28facde SM |
173 | true); |
174 | ||
6b611d98 | 175 | nbytes -= SEMIBSIZE; |
e28facde SM |
176 | } |
177 | ||
178 | /* we now start to operate on the dst SGL only */ | |
6b611d98 EB |
179 | src = req->dst; |
180 | dst = req->dst; | |
e28facde SM |
181 | } |
182 | ||
183 | /* Perform authentication check */ | |
c9683276 | 184 | if (block.A != cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL)) |
e28facde SM |
185 | ret = -EBADMSG; |
186 | ||
9e49451d | 187 | memzero_explicit(&block, sizeof(struct crypto_kw_block)); |
e28facde SM |
188 | |
189 | return ret; | |
190 | } | |
191 | ||
6b611d98 | 192 | static int crypto_kw_encrypt(struct skcipher_request *req) |
e28facde | 193 | { |
6b611d98 EB |
194 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
195 | struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); | |
9e49451d | 196 | struct crypto_kw_block block; |
6b611d98 | 197 | struct scatterlist *src, *dst; |
9e49451d SM |
198 | u64 t = 1; |
199 | unsigned int i; | |
e28facde SM |
200 | |
201 | /* | |
202 | * Require at least 2 semiblocks (note, the 3rd semiblock that is | |
203 | * required by SP800-38F is the IV that occupies the first semiblock. | |
204 | * This means that the dst memory must be one semiblock larger than src. | |
205 | * Also ensure that the given data is aligned to semiblock. | |
206 | */ | |
6b611d98 | 207 | if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) |
e28facde SM |
208 | return -EINVAL; |
209 | ||
210 | /* | |
211 | * Place the predefined IV into block A -- for encrypt, the caller | |
212 | * does not need to provide an IV, but he needs to fetch the final IV. | |
213 | */ | |
c9683276 | 214 | block.A = cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL); |
e28facde SM |
215 | |
216 | /* | |
217 | * src scatterlist is read-only. dst scatterlist is r/w. During the | |
6b611d98 EB |
218 | * first loop, src points to req->src and dst to req->dst. For any |
219 | * subsequent round, the code operates on req->dst only. | |
e28facde | 220 | */ |
6b611d98 EB |
221 | src = req->src; |
222 | dst = req->dst; | |
e28facde SM |
223 | |
224 | for (i = 0; i < 6; i++) { | |
e28facde | 225 | struct scatter_walk src_walk, dst_walk; |
6b611d98 | 226 | unsigned int nbytes = req->cryptlen; |
e28facde | 227 | |
6b611d98 EB |
228 | scatterwalk_start(&src_walk, src); |
229 | scatterwalk_start(&dst_walk, dst); | |
e28facde | 230 | |
6b611d98 | 231 | while (nbytes) { |
e28facde | 232 | /* get the source block */ |
9e49451d | 233 | scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, |
e28facde SM |
234 | false); |
235 | ||
236 | /* perform KW operation: encrypt block */ | |
6b611d98 | 237 | crypto_cipher_encrypt_one(cipher, (u8 *)&block, |
9e49451d | 238 | (u8 *)&block); |
e28facde | 239 | /* perform KW operation: modify IV with counter */ |
9e49451d | 240 | block.A ^= cpu_to_be64(t); |
e28facde SM |
241 | t++; |
242 | ||
243 | /* Copy block->R into place */ | |
9e49451d | 244 | scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, |
e28facde SM |
245 | true); |
246 | ||
6b611d98 | 247 | nbytes -= SEMIBSIZE; |
e28facde SM |
248 | } |
249 | ||
250 | /* we now start to operate on the dst SGL only */ | |
6b611d98 EB |
251 | src = req->dst; |
252 | dst = req->dst; | |
e28facde SM |
253 | } |
254 | ||
255 | /* establish the IV for the caller to pick up */ | |
6b611d98 | 256 | memcpy(req->iv, &block.A, SEMIBSIZE); |
e28facde | 257 | |
9e49451d | 258 | memzero_explicit(&block, sizeof(struct crypto_kw_block)); |
e28facde SM |
259 | |
260 | return 0; | |
261 | } | |
262 | ||
6b611d98 | 263 | static int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb) |
e28facde | 264 | { |
6b611d98 EB |
265 | struct skcipher_instance *inst; |
266 | struct crypto_alg *alg; | |
e28facde SM |
267 | int err; |
268 | ||
b3c16bfc | 269 | inst = skcipher_alloc_instance_simple(tmpl, tb); |
6b611d98 EB |
270 | if (IS_ERR(inst)) |
271 | return PTR_ERR(inst); | |
e28facde | 272 | |
b3c16bfc HX |
273 | alg = skcipher_ialg_simple(inst); |
274 | ||
6b611d98 | 275 | err = -EINVAL; |
e28facde SM |
276 | /* Section 5.1 requirement for KW */ |
277 | if (alg->cra_blocksize != sizeof(struct crypto_kw_block)) | |
6b611d98 | 278 | goto out_free_inst; |
e28facde | 279 | |
6b611d98 EB |
280 | inst->alg.base.cra_blocksize = SEMIBSIZE; |
281 | inst->alg.base.cra_alignmask = 0; | |
282 | inst->alg.ivsize = SEMIBSIZE; | |
e28facde | 283 | |
6b611d98 EB |
284 | inst->alg.encrypt = crypto_kw_encrypt; |
285 | inst->alg.decrypt = crypto_kw_decrypt; | |
e28facde | 286 | |
6b611d98 | 287 | err = skcipher_register_instance(tmpl, inst); |
b3c16bfc | 288 | if (err) { |
6b611d98 | 289 | out_free_inst: |
b3c16bfc HX |
290 | inst->free(inst); |
291 | } | |
292 | ||
6b611d98 | 293 | return err; |
e28facde SM |
294 | } |
295 | ||
296 | static struct crypto_template crypto_kw_tmpl = { | |
297 | .name = "kw", | |
6b611d98 | 298 | .create = crypto_kw_create, |
e28facde SM |
299 | .module = THIS_MODULE, |
300 | }; | |
301 | ||
302 | static int __init crypto_kw_init(void) | |
303 | { | |
304 | return crypto_register_template(&crypto_kw_tmpl); | |
305 | } | |
306 | ||
307 | static void __exit crypto_kw_exit(void) | |
308 | { | |
309 | crypto_unregister_template(&crypto_kw_tmpl); | |
310 | } | |
311 | ||
c4741b23 | 312 | subsys_initcall(crypto_kw_init); |
e28facde SM |
313 | module_exit(crypto_kw_exit); |
314 | ||
315 | MODULE_LICENSE("Dual BSD/GPL"); | |
316 | MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); | |
317 | MODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)"); | |
318 | MODULE_ALIAS_CRYPTO("kw"); |