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 sg_init_table(areq_ctx->src, 2); 173 src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen); 174 dst = src; 175 176 if (req->src != req->dst) { 177 memcpy_sglist(req->dst, req->src, assoclen); 178 sg_init_table(areq_ctx->dst, 2); 179 dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen); 180 } 181 182 skcipher_request_set_tfm(skreq, enc); 183 skcipher_request_set_callback(skreq, aead_request_flags(req), 184 crypto_authenc_esn_encrypt_done, req); 185 skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv); 186 187 err = crypto_skcipher_encrypt(skreq); 188 if (err) 189 return err; 190 191 return crypto_authenc_esn_genicv(req, aead_request_flags(req)); 192 } 193 194 static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, 195 unsigned int flags) 196 { 197 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 198 unsigned int authsize = crypto_aead_authsize(authenc_esn); 199 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 200 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 201 struct skcipher_request *skreq = (void *)(areq_ctx->tail + 202 ctx->reqoff); 203 struct crypto_ahash *auth = ctx->auth; 204 u8 *ohash = areq_ctx->tail; 205 unsigned int cryptlen = req->cryptlen - authsize; 206 unsigned int assoclen = req->assoclen; 207 struct scatterlist *dst = req->dst; 208 u8 *ihash = ohash + crypto_ahash_digestsize(auth); 209 u32 tmp[2]; 210 211 if (!authsize) 212 goto decrypt; 213 214 /* Move high-order bits of sequence number back. */ 215 scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); 216 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); 217 scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); 218 219 if (crypto_memneq(ihash, ohash, authsize)) 220 return -EBADMSG; 221 222 decrypt: 223 224 sg_init_table(areq_ctx->dst, 2); 225 dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen); 226 227 skcipher_request_set_tfm(skreq, ctx->enc); 228 skcipher_request_set_callback(skreq, flags, 229 req->base.complete, req->base.data); 230 skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv); 231 232 return crypto_skcipher_decrypt(skreq); 233 } 234 235 static void authenc_esn_verify_ahash_done(void *data, int err) 236 { 237 struct aead_request *req = data; 238 239 err = err ?: crypto_authenc_esn_decrypt_tail(req, 0); 240 authenc_esn_request_complete(req, err); 241 } 242 243 static int crypto_authenc_esn_decrypt(struct aead_request *req) 244 { 245 struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 246 struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 247 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 248 struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 249 unsigned int authsize = crypto_aead_authsize(authenc_esn); 250 struct crypto_ahash *auth = ctx->auth; 251 u8 *ohash = areq_ctx->tail; 252 unsigned int assoclen = req->assoclen; 253 unsigned int cryptlen = req->cryptlen; 254 u8 *ihash = ohash + crypto_ahash_digestsize(auth); 255 struct scatterlist *dst = req->dst; 256 u32 tmp[2]; 257 int err; 258 259 cryptlen -= authsize; 260 261 if (req->src != dst) 262 memcpy_sglist(dst, req->src, assoclen + cryptlen); 263 264 scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen, 265 authsize, 0); 266 267 if (!authsize) 268 goto tail; 269 270 /* Move high-order bits of sequence number to the end. */ 271 scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); 272 scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); 273 scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); 274 275 sg_init_table(areq_ctx->dst, 2); 276 dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); 277 278 ahash_request_set_tfm(ahreq, auth); 279 ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen); 280 ahash_request_set_callback(ahreq, aead_request_flags(req), 281 authenc_esn_verify_ahash_done, req); 282 283 err = crypto_ahash_digest(ahreq); 284 if (err) 285 return err; 286 287 tail: 288 return crypto_authenc_esn_decrypt_tail(req, aead_request_flags(req)); 289 } 290 291 static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm) 292 { 293 struct aead_instance *inst = aead_alg_instance(tfm); 294 struct authenc_esn_instance_ctx *ictx = aead_instance_ctx(inst); 295 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm); 296 struct crypto_ahash *auth; 297 struct crypto_skcipher *enc; 298 int err; 299 300 auth = crypto_spawn_ahash(&ictx->auth); 301 if (IS_ERR(auth)) 302 return PTR_ERR(auth); 303 304 enc = crypto_spawn_skcipher(&ictx->enc); 305 err = PTR_ERR(enc); 306 if (IS_ERR(enc)) 307 goto err_free_ahash; 308 309 ctx->auth = auth; 310 ctx->enc = enc; 311 312 ctx->reqoff = 2 * crypto_ahash_digestsize(auth); 313 314 crypto_aead_set_reqsize( 315 tfm, 316 sizeof(struct authenc_esn_request_ctx) + 317 ctx->reqoff + 318 max_t(unsigned int, 319 crypto_ahash_reqsize(auth) + 320 sizeof(struct ahash_request), 321 sizeof(struct skcipher_request) + 322 crypto_skcipher_reqsize(enc))); 323 324 return 0; 325 326 err_free_ahash: 327 crypto_free_ahash(auth); 328 return err; 329 } 330 331 static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm) 332 { 333 struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm); 334 335 crypto_free_ahash(ctx->auth); 336 crypto_free_skcipher(ctx->enc); 337 } 338 339 static void crypto_authenc_esn_free(struct aead_instance *inst) 340 { 341 struct authenc_esn_instance_ctx *ctx = aead_instance_ctx(inst); 342 343 crypto_drop_skcipher(&ctx->enc); 344 crypto_drop_ahash(&ctx->auth); 345 kfree(inst); 346 } 347 348 static int crypto_authenc_esn_create(struct crypto_template *tmpl, 349 struct rtattr **tb) 350 { 351 u32 mask; 352 struct aead_instance *inst; 353 struct authenc_esn_instance_ctx *ctx; 354 struct skcipher_alg_common *enc; 355 struct hash_alg_common *auth; 356 struct crypto_alg *auth_base; 357 int err; 358 359 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask); 360 if (err) 361 return err; 362 363 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 364 if (!inst) 365 return -ENOMEM; 366 ctx = aead_instance_ctx(inst); 367 368 err = crypto_grab_ahash(&ctx->auth, aead_crypto_instance(inst), 369 crypto_attr_alg_name(tb[1]), 0, mask); 370 if (err) 371 goto err_free_inst; 372 auth = crypto_spawn_ahash_alg(&ctx->auth); 373 auth_base = &auth->base; 374 375 err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst), 376 crypto_attr_alg_name(tb[2]), 0, mask); 377 if (err) 378 goto err_free_inst; 379 enc = crypto_spawn_skcipher_alg_common(&ctx->enc); 380 381 err = -ENAMETOOLONG; 382 if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 383 "authencesn(%s,%s)", auth_base->cra_name, 384 enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME) 385 goto err_free_inst; 386 387 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 388 "authencesn(%s,%s)", auth_base->cra_driver_name, 389 enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 390 goto err_free_inst; 391 392 inst->alg.base.cra_priority = enc->base.cra_priority * 10 + 393 auth_base->cra_priority; 394 inst->alg.base.cra_blocksize = enc->base.cra_blocksize; 395 inst->alg.base.cra_alignmask = enc->base.cra_alignmask; 396 inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx); 397 398 inst->alg.ivsize = enc->ivsize; 399 inst->alg.chunksize = enc->chunksize; 400 inst->alg.maxauthsize = auth->digestsize; 401 402 inst->alg.init = crypto_authenc_esn_init_tfm; 403 inst->alg.exit = crypto_authenc_esn_exit_tfm; 404 405 inst->alg.setkey = crypto_authenc_esn_setkey; 406 inst->alg.setauthsize = crypto_authenc_esn_setauthsize; 407 inst->alg.encrypt = crypto_authenc_esn_encrypt; 408 inst->alg.decrypt = crypto_authenc_esn_decrypt; 409 410 inst->free = crypto_authenc_esn_free; 411 412 err = aead_register_instance(tmpl, inst); 413 if (err) { 414 err_free_inst: 415 crypto_authenc_esn_free(inst); 416 } 417 return err; 418 } 419 420 static struct crypto_template crypto_authenc_esn_tmpl = { 421 .name = "authencesn", 422 .create = crypto_authenc_esn_create, 423 .module = THIS_MODULE, 424 }; 425 426 static int __init crypto_authenc_esn_module_init(void) 427 { 428 return crypto_register_template(&crypto_authenc_esn_tmpl); 429 } 430 431 static void __exit crypto_authenc_esn_module_exit(void) 432 { 433 crypto_unregister_template(&crypto_authenc_esn_tmpl); 434 } 435 436 module_init(crypto_authenc_esn_module_init); 437 module_exit(crypto_authenc_esn_module_exit); 438 439 MODULE_LICENSE("GPL"); 440 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>"); 441 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers"); 442 MODULE_ALIAS_CRYPTO("authencesn"); 443