1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers, 4 * derived from authenc.c 5 * 6 * Copyright (C) 2010 secunet Security Networks AG 7 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com> 8 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au> 9 */ 10 11 #include <crypto/internal/aead.h> 12 #include <crypto/internal/hash.h> 13 #include <crypto/internal/skcipher.h> 14 #include <crypto/authenc.h> 15 #include <crypto/null.h> 16 #include <crypto/scatterwalk.h> 17 #include <linux/err.h> 18 #include <linux/init.h> 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/rtnetlink.h> 22 #include <linux/slab.h> 23 #include <linux/spinlock.h> 24 25 struct authenc_esn_instance_ctx { 26 struct crypto_ahash_spawn auth; 27 struct crypto_skcipher_spawn enc; 28 }; 29 30 struct crypto_authenc_esn_ctx { 31 unsigned int reqoff; 32 struct crypto_ahash *auth; 33 struct crypto_skcipher *enc; 34 struct crypto_sync_skcipher *null; 35 }; 36 37 struct authenc_esn_request_ctx { 38 struct scatterlist src[2]; 39 struct scatterlist dst[2]; 40 char tail[]; 41 }; 42 43 static void authenc_esn_request_complete(struct aead_request *req, int err) 44 { 45 if (err != -EINPROGRESS) 46 aead_request_complete(req, err); 47 } 48 49 static int crypto_authenc_esn_setauthsize(struct crypto_aead *authenc_esn, 50 unsigned int authsize) 51 { 52 if (authsize > 0 && authsize < 4) 53 return -EINVAL; 54 55 return 0; 56 } 57 58 static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key, 59 unsigned int keylen) 60 { 61 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 62 struct crypto_ahash *auth = ctx->auth; 63 struct crypto_skcipher *enc = ctx->enc; 64 struct crypto_authenc_keys keys; 65 int err = -EINVAL; 66 67 if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 68 goto out; 69 70 crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); 71 crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) & 72 CRYPTO_TFM_REQ_MASK); 73 err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen); 74 if (err) 75 goto out; 76 77 crypto_skcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); 78 crypto_skcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) & 79 CRYPTO_TFM_REQ_MASK); 80 err = crypto_skcipher_setkey(enc, keys.enckey, keys.enckeylen); 81 out: 82 memzero_explicit(&keys, sizeof(keys)); 83 return err; 84 } 85 86 static int crypto_authenc_esn_genicv_tail(struct aead_request *req, 87 unsigned int flags) 88 { 89 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 90 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 91 u8 *hash = areq_ctx->tail; 92 unsigned int authsize = crypto_aead_authsize(authenc_esn); 93 unsigned int assoclen = req->assoclen; 94 unsigned int cryptlen = req->cryptlen; 95 struct scatterlist *dst = req->dst; 96 u32 tmp[2]; 97 98 /* Move high-order bits of sequence number back. */ 99 scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); 100 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); 101 scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); 102 103 scatterwalk_map_and_copy(hash, dst, assoclen + cryptlen, authsize, 1); 104 return 0; 105 } 106 107 static void authenc_esn_geniv_ahash_done(void *data, int err) 108 { 109 struct aead_request *req = data; 110 111 err = err ?: crypto_authenc_esn_genicv_tail(req, 0); 112 aead_request_complete(req, err); 113 } 114 115 static int crypto_authenc_esn_genicv(struct aead_request *req, 116 unsigned int flags) 117 { 118 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 119 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 120 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 121 struct crypto_ahash *auth = ctx->auth; 122 u8 *hash = areq_ctx->tail; 123 struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 124 unsigned int authsize = crypto_aead_authsize(authenc_esn); 125 unsigned int assoclen = req->assoclen; 126 unsigned int cryptlen = req->cryptlen; 127 struct scatterlist *dst = req->dst; 128 u32 tmp[2]; 129 130 if (!authsize) 131 return 0; 132 133 /* Move high-order bits of sequence number to the end. */ 134 scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); 135 scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); 136 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); 137 138 sg_init_table(areq_ctx->dst, 2); 139 dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); 140 141 ahash_request_set_tfm(ahreq, auth); 142 ahash_request_set_crypt(ahreq, dst, hash, assoclen + cryptlen); 143 ahash_request_set_callback(ahreq, flags, 144 authenc_esn_geniv_ahash_done, req); 145 146 return crypto_ahash_digest(ahreq) ?: 147 crypto_authenc_esn_genicv_tail(req, aead_request_flags(req)); 148 } 149 150 151 static void crypto_authenc_esn_encrypt_done(void *data, int err) 152 { 153 struct aead_request *areq = data; 154 155 if (!err) 156 err = crypto_authenc_esn_genicv(areq, 0); 157 158 authenc_esn_request_complete(areq, err); 159 } 160 161 static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len) 162 { 163 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 164 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 165 SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null); 166 167 skcipher_request_set_sync_tfm(skreq, ctx->null); 168 skcipher_request_set_callback(skreq, aead_request_flags(req), 169 NULL, NULL); 170 skcipher_request_set_crypt(skreq, req->src, req->dst, len, NULL); 171 172 return crypto_skcipher_encrypt(skreq); 173 } 174 175 static int crypto_authenc_esn_encrypt(struct aead_request *req) 176 { 177 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 178 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 179 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 180 struct skcipher_request *skreq = (void *)(areq_ctx->tail + 181 ctx->reqoff); 182 struct crypto_skcipher *enc = ctx->enc; 183 unsigned int assoclen = req->assoclen; 184 unsigned int cryptlen = req->cryptlen; 185 struct scatterlist *src, *dst; 186 int err; 187 188 sg_init_table(areq_ctx->src, 2); 189 src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen); 190 dst = src; 191 192 if (req->src != req->dst) { 193 err = crypto_authenc_esn_copy(req, assoclen); 194 if (err) 195 return err; 196 197 sg_init_table(areq_ctx->dst, 2); 198 dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen); 199 } 200 201 skcipher_request_set_tfm(skreq, enc); 202 skcipher_request_set_callback(skreq, aead_request_flags(req), 203 crypto_authenc_esn_encrypt_done, req); 204 skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv); 205 206 err = crypto_skcipher_encrypt(skreq); 207 if (err) 208 return err; 209 210 return crypto_authenc_esn_genicv(req, aead_request_flags(req)); 211 } 212 213 static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, 214 unsigned int flags) 215 { 216 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 217 unsigned int authsize = crypto_aead_authsize(authenc_esn); 218 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 219 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 220 struct skcipher_request *skreq = (void *)(areq_ctx->tail + 221 ctx->reqoff); 222 struct crypto_ahash *auth = ctx->auth; 223 u8 *ohash = areq_ctx->tail; 224 unsigned int cryptlen = req->cryptlen - authsize; 225 unsigned int assoclen = req->assoclen; 226 struct scatterlist *dst = req->dst; 227 u8 *ihash = ohash + crypto_ahash_digestsize(auth); 228 u32 tmp[2]; 229 230 if (!authsize) 231 goto decrypt; 232 233 /* Move high-order bits of sequence number back. */ 234 scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); 235 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); 236 scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); 237 238 if (crypto_memneq(ihash, ohash, authsize)) 239 return -EBADMSG; 240 241 decrypt: 242 243 sg_init_table(areq_ctx->dst, 2); 244 dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen); 245 246 skcipher_request_set_tfm(skreq, ctx->enc); 247 skcipher_request_set_callback(skreq, flags, 248 req->base.complete, req->base.data); 249 skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv); 250 251 return crypto_skcipher_decrypt(skreq); 252 } 253 254 static void authenc_esn_verify_ahash_done(void *data, int err) 255 { 256 struct aead_request *req = data; 257 258 err = err ?: crypto_authenc_esn_decrypt_tail(req, 0); 259 authenc_esn_request_complete(req, err); 260 } 261 262 static int crypto_authenc_esn_decrypt(struct aead_request *req) 263 { 264 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 265 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 266 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 267 struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 268 unsigned int authsize = crypto_aead_authsize(authenc_esn); 269 struct crypto_ahash *auth = ctx->auth; 270 u8 *ohash = areq_ctx->tail; 271 unsigned int assoclen = req->assoclen; 272 unsigned int cryptlen = req->cryptlen; 273 u8 *ihash = ohash + crypto_ahash_digestsize(auth); 274 struct scatterlist *dst = req->dst; 275 u32 tmp[2]; 276 int err; 277 278 cryptlen -= authsize; 279 280 if (req->src != dst) { 281 err = crypto_authenc_esn_copy(req, assoclen + cryptlen); 282 if (err) 283 return err; 284 } 285 286 scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen, 287 authsize, 0); 288 289 if (!authsize) 290 goto tail; 291 292 /* Move high-order bits of sequence number to the end. */ 293 scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); 294 scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); 295 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); 296 297 sg_init_table(areq_ctx->dst, 2); 298 dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); 299 300 ahash_request_set_tfm(ahreq, auth); 301 ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen); 302 ahash_request_set_callback(ahreq, aead_request_flags(req), 303 authenc_esn_verify_ahash_done, req); 304 305 err = crypto_ahash_digest(ahreq); 306 if (err) 307 return err; 308 309 tail: 310 return crypto_authenc_esn_decrypt_tail(req, aead_request_flags(req)); 311 } 312 313 static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm) 314 { 315 struct aead_instance *inst = aead_alg_instance(tfm); 316 struct authenc_esn_instance_ctx *ictx = aead_instance_ctx(inst); 317 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm); 318 struct crypto_ahash *auth; 319 struct crypto_skcipher *enc; 320 struct crypto_sync_skcipher *null; 321 int err; 322 323 auth = crypto_spawn_ahash(&ictx->auth); 324 if (IS_ERR(auth)) 325 return PTR_ERR(auth); 326 327 enc = crypto_spawn_skcipher(&ictx->enc); 328 err = PTR_ERR(enc); 329 if (IS_ERR(enc)) 330 goto err_free_ahash; 331 332 null = crypto_get_default_null_skcipher(); 333 err = PTR_ERR(null); 334 if (IS_ERR(null)) 335 goto err_free_skcipher; 336 337 ctx->auth = auth; 338 ctx->enc = enc; 339 ctx->null = null; 340 341 ctx->reqoff = 2 * crypto_ahash_digestsize(auth); 342 343 crypto_aead_set_reqsize( 344 tfm, 345 sizeof(struct authenc_esn_request_ctx) + 346 ctx->reqoff + 347 max_t(unsigned int, 348 crypto_ahash_reqsize(auth) + 349 sizeof(struct ahash_request), 350 sizeof(struct skcipher_request) + 351 crypto_skcipher_reqsize(enc))); 352 353 return 0; 354 355 err_free_skcipher: 356 crypto_free_skcipher(enc); 357 err_free_ahash: 358 crypto_free_ahash(auth); 359 return err; 360 } 361 362 static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm) 363 { 364 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm); 365 366 crypto_free_ahash(ctx->auth); 367 crypto_free_skcipher(ctx->enc); 368 crypto_put_default_null_skcipher(); 369 } 370 371 static void crypto_authenc_esn_free(struct aead_instance *inst) 372 { 373 struct authenc_esn_instance_ctx *ctx = aead_instance_ctx(inst); 374 375 crypto_drop_skcipher(&ctx->enc); 376 crypto_drop_ahash(&ctx->auth); 377 kfree(inst); 378 } 379 380 static int crypto_authenc_esn_create(struct crypto_template *tmpl, 381 struct rtattr **tb) 382 { 383 u32 mask; 384 struct aead_instance *inst; 385 struct authenc_esn_instance_ctx *ctx; 386 struct skcipher_alg_common *enc; 387 struct hash_alg_common *auth; 388 struct crypto_alg *auth_base; 389 int err; 390 391 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask); 392 if (err) 393 return err; 394 395 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 396 if (!inst) 397 return -ENOMEM; 398 ctx = aead_instance_ctx(inst); 399 400 err = crypto_grab_ahash(&ctx->auth, aead_crypto_instance(inst), 401 crypto_attr_alg_name(tb[1]), 0, mask); 402 if (err) 403 goto err_free_inst; 404 auth = crypto_spawn_ahash_alg(&ctx->auth); 405 auth_base = &auth->base; 406 407 err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), 408 crypto_attr_alg_name(tb[2]), 0, mask); 409 if (err) 410 goto err_free_inst; 411 enc = crypto_spawn_skcipher_alg_common(&ctx->enc); 412 413 err = -ENAMETOOLONG; 414 if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 415 "authencesn(%s,%s)", auth_base->cra_name, 416 enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME) 417 goto err_free_inst; 418 419 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 420 "authencesn(%s,%s)", auth_base->cra_driver_name, 421 enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 422 goto err_free_inst; 423 424 inst->alg.base.cra_priority = enc->base.cra_priority * 10 + 425 auth_base->cra_priority; 426 inst->alg.base.cra_blocksize = enc->base.cra_blocksize; 427 inst->alg.base.cra_alignmask = enc->base.cra_alignmask; 428 inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx); 429 430 inst->alg.ivsize = enc->ivsize; 431 inst->alg.chunksize = enc->chunksize; 432 inst->alg.maxauthsize = auth->digestsize; 433 434 inst->alg.init = crypto_authenc_esn_init_tfm; 435 inst->alg.exit = crypto_authenc_esn_exit_tfm; 436 437 inst->alg.setkey = crypto_authenc_esn_setkey; 438 inst->alg.setauthsize = crypto_authenc_esn_setauthsize; 439 inst->alg.encrypt = crypto_authenc_esn_encrypt; 440 inst->alg.decrypt = crypto_authenc_esn_decrypt; 441 442 inst->free = crypto_authenc_esn_free; 443 444 err = aead_register_instance(tmpl, inst); 445 if (err) { 446 err_free_inst: 447 crypto_authenc_esn_free(inst); 448 } 449 return err; 450 } 451 452 static struct crypto_template crypto_authenc_esn_tmpl = { 453 .name = "authencesn", 454 .create = crypto_authenc_esn_create, 455 .module = THIS_MODULE, 456 }; 457 458 static int __init crypto_authenc_esn_module_init(void) 459 { 460 return crypto_register_template(&crypto_authenc_esn_tmpl); 461 } 462 463 static void __exit crypto_authenc_esn_module_exit(void) 464 { 465 crypto_unregister_template(&crypto_authenc_esn_tmpl); 466 } 467 468 subsys_initcall(crypto_authenc_esn_module_init); 469 module_exit(crypto_authenc_esn_module_exit); 470 471 MODULE_LICENSE("GPL"); 472 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>"); 473 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers"); 474 MODULE_ALIAS_CRYPTO("authencesn"); 475
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.