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