| .. | .. |
|---|
| 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); |
|---|