.. | .. |
---|
56 | 56 | * u8 *iv = data; |
---|
57 | 57 | * u8 *pt = data + crypto_skcipher_ivsize(tfm); |
---|
58 | 58 | * <ensure that pt contains the plaintext of size ptlen> |
---|
59 | | - * sg_init_one(&sg, ptdata, ptlen); |
---|
| 59 | + * sg_init_one(&sg, pt, ptlen); |
---|
60 | 60 | * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); |
---|
61 | 61 | * |
---|
62 | 62 | * ==> After encryption, data now contains full KW result as per SP800-38F. |
---|
.. | .. |
---|
70 | 70 | * u8 *iv = data; |
---|
71 | 71 | * u8 *ct = data + crypto_skcipher_ivsize(tfm); |
---|
72 | 72 | * unsigned int ctlen = datalen - crypto_skcipher_ivsize(tfm); |
---|
73 | | - * sg_init_one(&sg, ctdata, ctlen); |
---|
74 | | - * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); |
---|
| 73 | + * sg_init_one(&sg, ct, ctlen); |
---|
| 74 | + * skcipher_request_set_crypt(req, &sg, &sg, ctlen, iv); |
---|
75 | 75 | * |
---|
76 | 76 | * ==> After decryption (which hopefully does not return EBADMSG), the ct |
---|
77 | 77 | * pointer now points to the plaintext of size ctlen. |
---|
.. | .. |
---|
85 | 85 | #include <linux/crypto.h> |
---|
86 | 86 | #include <linux/scatterlist.h> |
---|
87 | 87 | #include <crypto/scatterwalk.h> |
---|
| 88 | +#include <crypto/internal/cipher.h> |
---|
88 | 89 | #include <crypto/internal/skcipher.h> |
---|
89 | | - |
---|
90 | | -struct crypto_kw_ctx { |
---|
91 | | - struct crypto_cipher *child; |
---|
92 | | -}; |
---|
93 | 90 | |
---|
94 | 91 | struct crypto_kw_block { |
---|
95 | 92 | #define SEMIBSIZE 8 |
---|
.. | .. |
---|
124 | 121 | } |
---|
125 | 122 | } |
---|
126 | 123 | |
---|
127 | | -static int crypto_kw_decrypt(struct blkcipher_desc *desc, |
---|
128 | | - struct scatterlist *dst, struct scatterlist *src, |
---|
129 | | - unsigned int nbytes) |
---|
| 124 | +static int crypto_kw_decrypt(struct skcipher_request *req) |
---|
130 | 125 | { |
---|
131 | | - struct crypto_blkcipher *tfm = desc->tfm; |
---|
132 | | - struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); |
---|
133 | | - struct crypto_cipher *child = ctx->child; |
---|
| 126 | + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
---|
| 127 | + struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); |
---|
134 | 128 | struct crypto_kw_block block; |
---|
135 | | - struct scatterlist *lsrc, *ldst; |
---|
136 | | - u64 t = 6 * ((nbytes) >> 3); |
---|
| 129 | + struct scatterlist *src, *dst; |
---|
| 130 | + u64 t = 6 * ((req->cryptlen) >> 3); |
---|
137 | 131 | unsigned int i; |
---|
138 | 132 | int ret = 0; |
---|
139 | 133 | |
---|
.. | .. |
---|
141 | 135 | * Require at least 2 semiblocks (note, the 3rd semiblock that is |
---|
142 | 136 | * required by SP800-38F is the IV. |
---|
143 | 137 | */ |
---|
144 | | - if (nbytes < (2 * SEMIBSIZE) || nbytes % SEMIBSIZE) |
---|
| 138 | + if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) |
---|
145 | 139 | return -EINVAL; |
---|
146 | 140 | |
---|
147 | 141 | /* Place the IV into block A */ |
---|
148 | | - memcpy(&block.A, desc->info, SEMIBSIZE); |
---|
| 142 | + memcpy(&block.A, req->iv, SEMIBSIZE); |
---|
149 | 143 | |
---|
150 | 144 | /* |
---|
151 | 145 | * src scatterlist is read-only. dst scatterlist is r/w. During the |
---|
152 | | - * first loop, lsrc points to src and ldst to dst. For any |
---|
153 | | - * subsequent round, the code operates on dst only. |
---|
| 146 | + * first loop, src points to req->src and dst to req->dst. For any |
---|
| 147 | + * subsequent round, the code operates on req->dst only. |
---|
154 | 148 | */ |
---|
155 | | - lsrc = src; |
---|
156 | | - ldst = dst; |
---|
| 149 | + src = req->src; |
---|
| 150 | + dst = req->dst; |
---|
157 | 151 | |
---|
158 | 152 | for (i = 0; i < 6; i++) { |
---|
159 | 153 | struct scatter_walk src_walk, dst_walk; |
---|
160 | | - unsigned int tmp_nbytes = nbytes; |
---|
| 154 | + unsigned int nbytes = req->cryptlen; |
---|
161 | 155 | |
---|
162 | | - while (tmp_nbytes) { |
---|
163 | | - /* move pointer by tmp_nbytes in the SGL */ |
---|
164 | | - crypto_kw_scatterlist_ff(&src_walk, lsrc, tmp_nbytes); |
---|
| 156 | + while (nbytes) { |
---|
| 157 | + /* move pointer by nbytes in the SGL */ |
---|
| 158 | + crypto_kw_scatterlist_ff(&src_walk, src, nbytes); |
---|
165 | 159 | /* get the source block */ |
---|
166 | 160 | scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, |
---|
167 | 161 | false); |
---|
.. | .. |
---|
170 | 164 | block.A ^= cpu_to_be64(t); |
---|
171 | 165 | t--; |
---|
172 | 166 | /* perform KW operation: decrypt block */ |
---|
173 | | - crypto_cipher_decrypt_one(child, (u8*)&block, |
---|
174 | | - (u8*)&block); |
---|
| 167 | + crypto_cipher_decrypt_one(cipher, (u8 *)&block, |
---|
| 168 | + (u8 *)&block); |
---|
175 | 169 | |
---|
176 | | - /* move pointer by tmp_nbytes in the SGL */ |
---|
177 | | - crypto_kw_scatterlist_ff(&dst_walk, ldst, tmp_nbytes); |
---|
| 170 | + /* move pointer by nbytes in the SGL */ |
---|
| 171 | + crypto_kw_scatterlist_ff(&dst_walk, dst, nbytes); |
---|
178 | 172 | /* Copy block->R into place */ |
---|
179 | 173 | scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, |
---|
180 | 174 | true); |
---|
181 | 175 | |
---|
182 | | - tmp_nbytes -= SEMIBSIZE; |
---|
| 176 | + nbytes -= SEMIBSIZE; |
---|
183 | 177 | } |
---|
184 | 178 | |
---|
185 | 179 | /* we now start to operate on the dst SGL only */ |
---|
186 | | - lsrc = dst; |
---|
187 | | - ldst = dst; |
---|
| 180 | + src = req->dst; |
---|
| 181 | + dst = req->dst; |
---|
188 | 182 | } |
---|
189 | 183 | |
---|
190 | 184 | /* Perform authentication check */ |
---|
.. | .. |
---|
196 | 190 | return ret; |
---|
197 | 191 | } |
---|
198 | 192 | |
---|
199 | | -static int crypto_kw_encrypt(struct blkcipher_desc *desc, |
---|
200 | | - struct scatterlist *dst, struct scatterlist *src, |
---|
201 | | - unsigned int nbytes) |
---|
| 193 | +static int crypto_kw_encrypt(struct skcipher_request *req) |
---|
202 | 194 | { |
---|
203 | | - struct crypto_blkcipher *tfm = desc->tfm; |
---|
204 | | - struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); |
---|
205 | | - struct crypto_cipher *child = ctx->child; |
---|
| 195 | + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
---|
| 196 | + struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); |
---|
206 | 197 | struct crypto_kw_block block; |
---|
207 | | - struct scatterlist *lsrc, *ldst; |
---|
| 198 | + struct scatterlist *src, *dst; |
---|
208 | 199 | u64 t = 1; |
---|
209 | 200 | unsigned int i; |
---|
210 | 201 | |
---|
.. | .. |
---|
214 | 205 | * This means that the dst memory must be one semiblock larger than src. |
---|
215 | 206 | * Also ensure that the given data is aligned to semiblock. |
---|
216 | 207 | */ |
---|
217 | | - if (nbytes < (2 * SEMIBSIZE) || nbytes % SEMIBSIZE) |
---|
| 208 | + if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) |
---|
218 | 209 | return -EINVAL; |
---|
219 | 210 | |
---|
220 | 211 | /* |
---|
.. | .. |
---|
225 | 216 | |
---|
226 | 217 | /* |
---|
227 | 218 | * src scatterlist is read-only. dst scatterlist is r/w. During the |
---|
228 | | - * first loop, lsrc points to src and ldst to dst. For any |
---|
229 | | - * subsequent round, the code operates on dst only. |
---|
| 219 | + * first loop, src points to req->src and dst to req->dst. For any |
---|
| 220 | + * subsequent round, the code operates on req->dst only. |
---|
230 | 221 | */ |
---|
231 | | - lsrc = src; |
---|
232 | | - ldst = dst; |
---|
| 222 | + src = req->src; |
---|
| 223 | + dst = req->dst; |
---|
233 | 224 | |
---|
234 | 225 | for (i = 0; i < 6; i++) { |
---|
235 | 226 | struct scatter_walk src_walk, dst_walk; |
---|
236 | | - unsigned int tmp_nbytes = nbytes; |
---|
| 227 | + unsigned int nbytes = req->cryptlen; |
---|
237 | 228 | |
---|
238 | | - scatterwalk_start(&src_walk, lsrc); |
---|
239 | | - scatterwalk_start(&dst_walk, ldst); |
---|
| 229 | + scatterwalk_start(&src_walk, src); |
---|
| 230 | + scatterwalk_start(&dst_walk, dst); |
---|
240 | 231 | |
---|
241 | | - while (tmp_nbytes) { |
---|
| 232 | + while (nbytes) { |
---|
242 | 233 | /* get the source block */ |
---|
243 | 234 | scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, |
---|
244 | 235 | false); |
---|
245 | 236 | |
---|
246 | 237 | /* perform KW operation: encrypt block */ |
---|
247 | | - crypto_cipher_encrypt_one(child, (u8 *)&block, |
---|
| 238 | + crypto_cipher_encrypt_one(cipher, (u8 *)&block, |
---|
248 | 239 | (u8 *)&block); |
---|
249 | 240 | /* perform KW operation: modify IV with counter */ |
---|
250 | 241 | block.A ^= cpu_to_be64(t); |
---|
.. | .. |
---|
254 | 245 | scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, |
---|
255 | 246 | true); |
---|
256 | 247 | |
---|
257 | | - tmp_nbytes -= SEMIBSIZE; |
---|
| 248 | + nbytes -= SEMIBSIZE; |
---|
258 | 249 | } |
---|
259 | 250 | |
---|
260 | 251 | /* we now start to operate on the dst SGL only */ |
---|
261 | | - lsrc = dst; |
---|
262 | | - ldst = dst; |
---|
| 252 | + src = req->dst; |
---|
| 253 | + dst = req->dst; |
---|
263 | 254 | } |
---|
264 | 255 | |
---|
265 | 256 | /* establish the IV for the caller to pick up */ |
---|
266 | | - memcpy(desc->info, &block.A, SEMIBSIZE); |
---|
| 257 | + memcpy(req->iv, &block.A, SEMIBSIZE); |
---|
267 | 258 | |
---|
268 | 259 | memzero_explicit(&block, sizeof(struct crypto_kw_block)); |
---|
269 | 260 | |
---|
270 | 261 | return 0; |
---|
271 | 262 | } |
---|
272 | 263 | |
---|
273 | | -static int crypto_kw_setkey(struct crypto_tfm *parent, const u8 *key, |
---|
274 | | - unsigned int keylen) |
---|
| 264 | +static int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb) |
---|
275 | 265 | { |
---|
276 | | - struct crypto_kw_ctx *ctx = crypto_tfm_ctx(parent); |
---|
277 | | - struct crypto_cipher *child = ctx->child; |
---|
| 266 | + struct skcipher_instance *inst; |
---|
| 267 | + struct crypto_alg *alg; |
---|
278 | 268 | int err; |
---|
279 | 269 | |
---|
280 | | - crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); |
---|
281 | | - crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & |
---|
282 | | - CRYPTO_TFM_REQ_MASK); |
---|
283 | | - err = crypto_cipher_setkey(child, key, keylen); |
---|
284 | | - crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & |
---|
285 | | - CRYPTO_TFM_RES_MASK); |
---|
286 | | - return err; |
---|
287 | | -} |
---|
| 270 | + inst = skcipher_alloc_instance_simple(tmpl, tb); |
---|
| 271 | + if (IS_ERR(inst)) |
---|
| 272 | + return PTR_ERR(inst); |
---|
288 | 273 | |
---|
289 | | -static int crypto_kw_init_tfm(struct crypto_tfm *tfm) |
---|
290 | | -{ |
---|
291 | | - struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); |
---|
292 | | - struct crypto_spawn *spawn = crypto_instance_ctx(inst); |
---|
293 | | - struct crypto_kw_ctx *ctx = crypto_tfm_ctx(tfm); |
---|
294 | | - struct crypto_cipher *cipher; |
---|
| 274 | + alg = skcipher_ialg_simple(inst); |
---|
295 | 275 | |
---|
296 | | - cipher = crypto_spawn_cipher(spawn); |
---|
297 | | - if (IS_ERR(cipher)) |
---|
298 | | - return PTR_ERR(cipher); |
---|
299 | | - |
---|
300 | | - ctx->child = cipher; |
---|
301 | | - return 0; |
---|
302 | | -} |
---|
303 | | - |
---|
304 | | -static void crypto_kw_exit_tfm(struct crypto_tfm *tfm) |
---|
305 | | -{ |
---|
306 | | - struct crypto_kw_ctx *ctx = crypto_tfm_ctx(tfm); |
---|
307 | | - |
---|
308 | | - crypto_free_cipher(ctx->child); |
---|
309 | | -} |
---|
310 | | - |
---|
311 | | -static struct crypto_instance *crypto_kw_alloc(struct rtattr **tb) |
---|
312 | | -{ |
---|
313 | | - struct crypto_instance *inst = NULL; |
---|
314 | | - struct crypto_alg *alg = NULL; |
---|
315 | | - int err; |
---|
316 | | - |
---|
317 | | - err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); |
---|
318 | | - if (err) |
---|
319 | | - return ERR_PTR(err); |
---|
320 | | - |
---|
321 | | - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, |
---|
322 | | - CRYPTO_ALG_TYPE_MASK); |
---|
323 | | - if (IS_ERR(alg)) |
---|
324 | | - return ERR_CAST(alg); |
---|
325 | | - |
---|
326 | | - inst = ERR_PTR(-EINVAL); |
---|
| 276 | + err = -EINVAL; |
---|
327 | 277 | /* Section 5.1 requirement for KW */ |
---|
328 | 278 | if (alg->cra_blocksize != sizeof(struct crypto_kw_block)) |
---|
329 | | - goto err; |
---|
| 279 | + goto out_free_inst; |
---|
330 | 280 | |
---|
331 | | - inst = crypto_alloc_instance("kw", alg); |
---|
332 | | - if (IS_ERR(inst)) |
---|
333 | | - goto err; |
---|
| 281 | + inst->alg.base.cra_blocksize = SEMIBSIZE; |
---|
| 282 | + inst->alg.base.cra_alignmask = 0; |
---|
| 283 | + inst->alg.ivsize = SEMIBSIZE; |
---|
334 | 284 | |
---|
335 | | - inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; |
---|
336 | | - inst->alg.cra_priority = alg->cra_priority; |
---|
337 | | - inst->alg.cra_blocksize = SEMIBSIZE; |
---|
338 | | - inst->alg.cra_alignmask = 0; |
---|
339 | | - inst->alg.cra_type = &crypto_blkcipher_type; |
---|
340 | | - inst->alg.cra_blkcipher.ivsize = SEMIBSIZE; |
---|
341 | | - inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; |
---|
342 | | - inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; |
---|
| 285 | + inst->alg.encrypt = crypto_kw_encrypt; |
---|
| 286 | + inst->alg.decrypt = crypto_kw_decrypt; |
---|
343 | 287 | |
---|
344 | | - inst->alg.cra_ctxsize = sizeof(struct crypto_kw_ctx); |
---|
| 288 | + err = skcipher_register_instance(tmpl, inst); |
---|
| 289 | + if (err) { |
---|
| 290 | +out_free_inst: |
---|
| 291 | + inst->free(inst); |
---|
| 292 | + } |
---|
345 | 293 | |
---|
346 | | - inst->alg.cra_init = crypto_kw_init_tfm; |
---|
347 | | - inst->alg.cra_exit = crypto_kw_exit_tfm; |
---|
348 | | - |
---|
349 | | - inst->alg.cra_blkcipher.setkey = crypto_kw_setkey; |
---|
350 | | - inst->alg.cra_blkcipher.encrypt = crypto_kw_encrypt; |
---|
351 | | - inst->alg.cra_blkcipher.decrypt = crypto_kw_decrypt; |
---|
352 | | - |
---|
353 | | -err: |
---|
354 | | - crypto_mod_put(alg); |
---|
355 | | - return inst; |
---|
356 | | -} |
---|
357 | | - |
---|
358 | | -static void crypto_kw_free(struct crypto_instance *inst) |
---|
359 | | -{ |
---|
360 | | - crypto_drop_spawn(crypto_instance_ctx(inst)); |
---|
361 | | - kfree(inst); |
---|
| 294 | + return err; |
---|
362 | 295 | } |
---|
363 | 296 | |
---|
364 | 297 | static struct crypto_template crypto_kw_tmpl = { |
---|
365 | 298 | .name = "kw", |
---|
366 | | - .alloc = crypto_kw_alloc, |
---|
367 | | - .free = crypto_kw_free, |
---|
| 299 | + .create = crypto_kw_create, |
---|
368 | 300 | .module = THIS_MODULE, |
---|
369 | 301 | }; |
---|
370 | 302 | |
---|
.. | .. |
---|
378 | 310 | crypto_unregister_template(&crypto_kw_tmpl); |
---|
379 | 311 | } |
---|
380 | 312 | |
---|
381 | | -module_init(crypto_kw_init); |
---|
| 313 | +subsys_initcall(crypto_kw_init); |
---|
382 | 314 | module_exit(crypto_kw_exit); |
---|
383 | 315 | |
---|
384 | 316 | MODULE_LICENSE("Dual BSD/GPL"); |
---|
385 | 317 | MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); |
---|
386 | 318 | MODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)"); |
---|
387 | 319 | MODULE_ALIAS_CRYPTO("kw"); |
---|
| 320 | +MODULE_IMPORT_NS(CRYPTO_INTERNAL); |
---|