Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers

ESP with separate encryption/authentication algorithms needs a special
treatment for the associated data. This patch add a new algorithm that
handles esp with extended sequence numbers.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Steffen Klassert and committed by
David S. Miller
a5079d08 27b61ae2

+836 -1
+1 -1
crypto/Makefile
··· 78 78 obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o 79 79 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o 80 80 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o 81 - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o 81 + obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o 82 82 obj-$(CONFIG_CRYPTO_LZO) += lzo.o 83 83 obj-$(CONFIG_CRYPTO_RNG2) += rng.o 84 84 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
+835
crypto/authencesn.c
··· 1 + /* 2 + * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers, 3 + * derived from authenc.c 4 + * 5 + * Copyright (C) 2010 secunet Security Networks AG 6 + * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the Free 10 + * Software Foundation; either version 2 of the License, or (at your option) 11 + * any later version. 12 + * 13 + */ 14 + 15 + #include <crypto/aead.h> 16 + #include <crypto/internal/hash.h> 17 + #include <crypto/internal/skcipher.h> 18 + #include <crypto/authenc.h> 19 + #include <crypto/scatterwalk.h> 20 + #include <linux/err.h> 21 + #include <linux/init.h> 22 + #include <linux/kernel.h> 23 + #include <linux/module.h> 24 + #include <linux/rtnetlink.h> 25 + #include <linux/slab.h> 26 + #include <linux/spinlock.h> 27 + 28 + struct authenc_esn_instance_ctx { 29 + struct crypto_ahash_spawn auth; 30 + struct crypto_skcipher_spawn enc; 31 + }; 32 + 33 + struct crypto_authenc_esn_ctx { 34 + unsigned int reqoff; 35 + struct crypto_ahash *auth; 36 + struct crypto_ablkcipher *enc; 37 + }; 38 + 39 + struct authenc_esn_request_ctx { 40 + unsigned int cryptlen; 41 + unsigned int headlen; 42 + unsigned int trailen; 43 + struct scatterlist *sg; 44 + struct scatterlist hsg[2]; 45 + struct scatterlist tsg[1]; 46 + struct scatterlist cipher[2]; 47 + crypto_completion_t complete; 48 + crypto_completion_t update_complete; 49 + crypto_completion_t update_complete2; 50 + char tail[]; 51 + }; 52 + 53 + static void authenc_esn_request_complete(struct aead_request *req, int err) 54 + { 55 + if (err != -EINPROGRESS) 56 + aead_request_complete(req, err); 57 + } 58 + 59 + static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key, 60 + unsigned int keylen) 61 + { 62 + unsigned int authkeylen; 63 + unsigned int enckeylen; 64 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 65 + struct crypto_ahash *auth = ctx->auth; 66 + struct crypto_ablkcipher *enc = ctx->enc; 67 + struct rtattr *rta = (void *)key; 68 + struct crypto_authenc_key_param *param; 69 + int err = -EINVAL; 70 + 71 + if (!RTA_OK(rta, keylen)) 72 + goto badkey; 73 + if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) 74 + goto badkey; 75 + if (RTA_PAYLOAD(rta) < sizeof(*param)) 76 + goto badkey; 77 + 78 + param = RTA_DATA(rta); 79 + enckeylen = be32_to_cpu(param->enckeylen); 80 + 81 + key += RTA_ALIGN(rta->rta_len); 82 + keylen -= RTA_ALIGN(rta->rta_len); 83 + 84 + if (keylen < enckeylen) 85 + goto badkey; 86 + 87 + authkeylen = keylen - enckeylen; 88 + 89 + crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); 90 + crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) & 91 + CRYPTO_TFM_REQ_MASK); 92 + err = crypto_ahash_setkey(auth, key, authkeylen); 93 + crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) & 94 + CRYPTO_TFM_RES_MASK); 95 + 96 + if (err) 97 + goto out; 98 + 99 + crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); 100 + crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) & 101 + CRYPTO_TFM_REQ_MASK); 102 + err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen); 103 + crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) & 104 + CRYPTO_TFM_RES_MASK); 105 + 106 + out: 107 + return err; 108 + 109 + badkey: 110 + crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN); 111 + goto out; 112 + } 113 + 114 + static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq, 115 + int err) 116 + { 117 + struct aead_request *req = areq->data; 118 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 119 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 120 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 121 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 122 + 123 + if (err) 124 + goto out; 125 + 126 + ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result, 127 + areq_ctx->cryptlen); 128 + ahash_request_set_callback(ahreq, aead_request_flags(req) & 129 + CRYPTO_TFM_REQ_MAY_SLEEP, 130 + areq_ctx->update_complete2, req); 131 + 132 + err = crypto_ahash_update(ahreq); 133 + if (err) 134 + goto out; 135 + 136 + ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result, 137 + areq_ctx->trailen); 138 + ahash_request_set_callback(ahreq, aead_request_flags(req) & 139 + CRYPTO_TFM_REQ_MAY_SLEEP, 140 + areq_ctx->complete, req); 141 + 142 + err = crypto_ahash_finup(ahreq); 143 + if (err) 144 + goto out; 145 + 146 + scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg, 147 + areq_ctx->cryptlen, 148 + crypto_aead_authsize(authenc_esn), 1); 149 + 150 + out: 151 + authenc_esn_request_complete(req, err); 152 + } 153 + 154 + static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq, 155 + int err) 156 + { 157 + struct aead_request *req = areq->data; 158 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 159 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 160 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 161 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 162 + 163 + if (err) 164 + goto out; 165 + 166 + ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result, 167 + areq_ctx->trailen); 168 + ahash_request_set_callback(ahreq, aead_request_flags(req) & 169 + CRYPTO_TFM_REQ_MAY_SLEEP, 170 + areq_ctx->complete, req); 171 + 172 + err = crypto_ahash_finup(ahreq); 173 + if (err) 174 + goto out; 175 + 176 + scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg, 177 + areq_ctx->cryptlen, 178 + crypto_aead_authsize(authenc_esn), 1); 179 + 180 + out: 181 + authenc_esn_request_complete(req, err); 182 + } 183 + 184 + 185 + static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq, 186 + int err) 187 + { 188 + struct aead_request *req = areq->data; 189 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 190 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 191 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 192 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 193 + 194 + if (err) 195 + goto out; 196 + 197 + scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg, 198 + areq_ctx->cryptlen, 199 + crypto_aead_authsize(authenc_esn), 1); 200 + 201 + out: 202 + aead_request_complete(req, err); 203 + } 204 + 205 + 206 + static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq, 207 + int err) 208 + { 209 + u8 *ihash; 210 + unsigned int authsize; 211 + struct ablkcipher_request *abreq; 212 + struct aead_request *req = areq->data; 213 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 214 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 215 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 216 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 217 + unsigned int cryptlen = req->cryptlen; 218 + 219 + if (err) 220 + goto out; 221 + 222 + ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result, 223 + areq_ctx->cryptlen); 224 + 225 + ahash_request_set_callback(ahreq, 226 + aead_request_flags(req) & 227 + CRYPTO_TFM_REQ_MAY_SLEEP, 228 + areq_ctx->update_complete2, req); 229 + 230 + err = crypto_ahash_update(ahreq); 231 + if (err) 232 + goto out; 233 + 234 + ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result, 235 + areq_ctx->trailen); 236 + ahash_request_set_callback(ahreq, aead_request_flags(req) & 237 + CRYPTO_TFM_REQ_MAY_SLEEP, 238 + areq_ctx->complete, req); 239 + 240 + err = crypto_ahash_finup(ahreq); 241 + if (err) 242 + goto out; 243 + 244 + authsize = crypto_aead_authsize(authenc_esn); 245 + cryptlen -= authsize; 246 + ihash = ahreq->result + authsize; 247 + scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, 248 + authsize, 0); 249 + 250 + err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0; 251 + if (err) 252 + goto out; 253 + 254 + abreq = aead_request_ctx(req); 255 + ablkcipher_request_set_tfm(abreq, ctx->enc); 256 + ablkcipher_request_set_callback(abreq, aead_request_flags(req), 257 + req->base.complete, req->base.data); 258 + ablkcipher_request_set_crypt(abreq, req->src, req->dst, 259 + cryptlen, req->iv); 260 + 261 + err = crypto_ablkcipher_decrypt(abreq); 262 + 263 + out: 264 + authenc_esn_request_complete(req, err); 265 + } 266 + 267 + static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq, 268 + int err) 269 + { 270 + u8 *ihash; 271 + unsigned int authsize; 272 + struct ablkcipher_request *abreq; 273 + struct aead_request *req = areq->data; 274 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 275 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 276 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 277 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 278 + unsigned int cryptlen = req->cryptlen; 279 + 280 + if (err) 281 + goto out; 282 + 283 + ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result, 284 + areq_ctx->trailen); 285 + ahash_request_set_callback(ahreq, aead_request_flags(req) & 286 + CRYPTO_TFM_REQ_MAY_SLEEP, 287 + areq_ctx->complete, req); 288 + 289 + err = crypto_ahash_finup(ahreq); 290 + if (err) 291 + goto out; 292 + 293 + authsize = crypto_aead_authsize(authenc_esn); 294 + cryptlen -= authsize; 295 + ihash = ahreq->result + authsize; 296 + scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, 297 + authsize, 0); 298 + 299 + err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0; 300 + if (err) 301 + goto out; 302 + 303 + abreq = aead_request_ctx(req); 304 + ablkcipher_request_set_tfm(abreq, ctx->enc); 305 + ablkcipher_request_set_callback(abreq, aead_request_flags(req), 306 + req->base.complete, req->base.data); 307 + ablkcipher_request_set_crypt(abreq, req->src, req->dst, 308 + cryptlen, req->iv); 309 + 310 + err = crypto_ablkcipher_decrypt(abreq); 311 + 312 + out: 313 + authenc_esn_request_complete(req, err); 314 + } 315 + 316 + 317 + static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq, 318 + int err) 319 + { 320 + u8 *ihash; 321 + unsigned int authsize; 322 + struct ablkcipher_request *abreq; 323 + struct aead_request *req = areq->data; 324 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 325 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 326 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 327 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 328 + unsigned int cryptlen = req->cryptlen; 329 + 330 + if (err) 331 + goto out; 332 + 333 + authsize = crypto_aead_authsize(authenc_esn); 334 + cryptlen -= authsize; 335 + ihash = ahreq->result + authsize; 336 + scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, 337 + authsize, 0); 338 + 339 + err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0; 340 + if (err) 341 + goto out; 342 + 343 + abreq = aead_request_ctx(req); 344 + ablkcipher_request_set_tfm(abreq, ctx->enc); 345 + ablkcipher_request_set_callback(abreq, aead_request_flags(req), 346 + req->base.complete, req->base.data); 347 + ablkcipher_request_set_crypt(abreq, req->src, req->dst, 348 + cryptlen, req->iv); 349 + 350 + err = crypto_ablkcipher_decrypt(abreq); 351 + 352 + out: 353 + authenc_esn_request_complete(req, err); 354 + } 355 + 356 + static u8 *crypto_authenc_esn_ahash(struct aead_request *req, 357 + unsigned int flags) 358 + { 359 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 360 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 361 + struct crypto_ahash *auth = ctx->auth; 362 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 363 + struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff); 364 + u8 *hash = areq_ctx->tail; 365 + int err; 366 + 367 + hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth), 368 + crypto_ahash_alignmask(auth) + 1); 369 + 370 + ahash_request_set_tfm(ahreq, auth); 371 + 372 + err = crypto_ahash_init(ahreq); 373 + if (err) 374 + return ERR_PTR(err); 375 + 376 + ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen); 377 + ahash_request_set_callback(ahreq, aead_request_flags(req) & flags, 378 + areq_ctx->update_complete, req); 379 + 380 + err = crypto_ahash_update(ahreq); 381 + if (err) 382 + return ERR_PTR(err); 383 + 384 + ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen); 385 + ahash_request_set_callback(ahreq, aead_request_flags(req) & flags, 386 + areq_ctx->update_complete2, req); 387 + 388 + err = crypto_ahash_update(ahreq); 389 + if (err) 390 + return ERR_PTR(err); 391 + 392 + ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash, 393 + areq_ctx->trailen); 394 + ahash_request_set_callback(ahreq, aead_request_flags(req) & flags, 395 + areq_ctx->complete, req); 396 + 397 + err = crypto_ahash_finup(ahreq); 398 + if (err) 399 + return ERR_PTR(err); 400 + 401 + return hash; 402 + } 403 + 404 + static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv, 405 + unsigned int flags) 406 + { 407 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 408 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 409 + struct scatterlist *dst = req->dst; 410 + struct scatterlist *assoc = req->assoc; 411 + struct scatterlist *cipher = areq_ctx->cipher; 412 + struct scatterlist *hsg = areq_ctx->hsg; 413 + struct scatterlist *tsg = areq_ctx->tsg; 414 + struct scatterlist *assoc1; 415 + struct scatterlist *assoc2; 416 + unsigned int ivsize = crypto_aead_ivsize(authenc_esn); 417 + unsigned int cryptlen = req->cryptlen; 418 + struct page *dstp; 419 + u8 *vdst; 420 + u8 *hash; 421 + 422 + dstp = sg_page(dst); 423 + vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset; 424 + 425 + if (ivsize) { 426 + sg_init_table(cipher, 2); 427 + sg_set_buf(cipher, iv, ivsize); 428 + scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2); 429 + dst = cipher; 430 + cryptlen += ivsize; 431 + } 432 + 433 + if (sg_is_last(assoc)) 434 + return -EINVAL; 435 + 436 + assoc1 = assoc + 1; 437 + if (sg_is_last(assoc1)) 438 + return -EINVAL; 439 + 440 + assoc2 = assoc + 2; 441 + if (!sg_is_last(assoc2)) 442 + return -EINVAL; 443 + 444 + sg_init_table(hsg, 2); 445 + sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset); 446 + sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset); 447 + 448 + sg_init_table(tsg, 1); 449 + sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset); 450 + 451 + areq_ctx->cryptlen = cryptlen; 452 + areq_ctx->headlen = assoc->length + assoc2->length; 453 + areq_ctx->trailen = assoc1->length; 454 + areq_ctx->sg = dst; 455 + 456 + areq_ctx->complete = authenc_esn_geniv_ahash_done; 457 + areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done; 458 + areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2; 459 + 460 + hash = crypto_authenc_esn_ahash(req, flags); 461 + if (IS_ERR(hash)) 462 + return PTR_ERR(hash); 463 + 464 + scatterwalk_map_and_copy(hash, dst, cryptlen, 465 + crypto_aead_authsize(authenc_esn), 1); 466 + return 0; 467 + } 468 + 469 + 470 + static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req, 471 + int err) 472 + { 473 + struct aead_request *areq = req->data; 474 + 475 + if (!err) { 476 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq); 477 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 478 + struct ablkcipher_request *abreq = aead_request_ctx(areq); 479 + u8 *iv = (u8 *)(abreq + 1) + 480 + crypto_ablkcipher_reqsize(ctx->enc); 481 + 482 + err = crypto_authenc_esn_genicv(areq, iv, 0); 483 + } 484 + 485 + authenc_esn_request_complete(areq, err); 486 + } 487 + 488 + static int crypto_authenc_esn_encrypt(struct aead_request *req) 489 + { 490 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 491 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 492 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 493 + struct crypto_ablkcipher *enc = ctx->enc; 494 + struct scatterlist *dst = req->dst; 495 + unsigned int cryptlen = req->cryptlen; 496 + struct ablkcipher_request *abreq = (void *)(areq_ctx->tail 497 + + ctx->reqoff); 498 + u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc); 499 + int err; 500 + 501 + ablkcipher_request_set_tfm(abreq, enc); 502 + ablkcipher_request_set_callback(abreq, aead_request_flags(req), 503 + crypto_authenc_esn_encrypt_done, req); 504 + ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv); 505 + 506 + memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn)); 507 + 508 + err = crypto_ablkcipher_encrypt(abreq); 509 + if (err) 510 + return err; 511 + 512 + return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP); 513 + } 514 + 515 + static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req, 516 + int err) 517 + { 518 + struct aead_request *areq = req->data; 519 + 520 + if (!err) { 521 + struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); 522 + 523 + err = crypto_authenc_esn_genicv(areq, greq->giv, 0); 524 + } 525 + 526 + authenc_esn_request_complete(areq, err); 527 + } 528 + 529 + static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req) 530 + { 531 + struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req); 532 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 533 + struct aead_request *areq = &req->areq; 534 + struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); 535 + u8 *iv = req->giv; 536 + int err; 537 + 538 + skcipher_givcrypt_set_tfm(greq, ctx->enc); 539 + skcipher_givcrypt_set_callback(greq, aead_request_flags(areq), 540 + crypto_authenc_esn_givencrypt_done, areq); 541 + skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen, 542 + areq->iv); 543 + skcipher_givcrypt_set_giv(greq, iv, req->seq); 544 + 545 + err = crypto_skcipher_givencrypt(greq); 546 + if (err) 547 + return err; 548 + 549 + return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP); 550 + } 551 + 552 + static int crypto_authenc_esn_verify(struct aead_request *req) 553 + { 554 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 555 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 556 + u8 *ohash; 557 + u8 *ihash; 558 + unsigned int authsize; 559 + 560 + areq_ctx->complete = authenc_esn_verify_ahash_done; 561 + areq_ctx->update_complete = authenc_esn_verify_ahash_update_done; 562 + 563 + ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP); 564 + if (IS_ERR(ohash)) 565 + return PTR_ERR(ohash); 566 + 567 + authsize = crypto_aead_authsize(authenc_esn); 568 + ihash = ohash + authsize; 569 + scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen, 570 + authsize, 0); 571 + return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0; 572 + } 573 + 574 + static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv, 575 + unsigned int cryptlen) 576 + { 577 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 578 + struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req); 579 + struct scatterlist *src = req->src; 580 + struct scatterlist *assoc = req->assoc; 581 + struct scatterlist *cipher = areq_ctx->cipher; 582 + struct scatterlist *hsg = areq_ctx->hsg; 583 + struct scatterlist *tsg = areq_ctx->tsg; 584 + struct scatterlist *assoc1; 585 + struct scatterlist *assoc2; 586 + unsigned int ivsize = crypto_aead_ivsize(authenc_esn); 587 + struct page *srcp; 588 + u8 *vsrc; 589 + 590 + srcp = sg_page(src); 591 + vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset; 592 + 593 + if (ivsize) { 594 + sg_init_table(cipher, 2); 595 + sg_set_buf(cipher, iv, ivsize); 596 + scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2); 597 + src = cipher; 598 + cryptlen += ivsize; 599 + } 600 + 601 + if (sg_is_last(assoc)) 602 + return -EINVAL; 603 + 604 + assoc1 = assoc + 1; 605 + if (sg_is_last(assoc1)) 606 + return -EINVAL; 607 + 608 + assoc2 = assoc + 2; 609 + if (!sg_is_last(assoc2)) 610 + return -EINVAL; 611 + 612 + sg_init_table(hsg, 2); 613 + sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset); 614 + sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset); 615 + 616 + sg_init_table(tsg, 1); 617 + sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset); 618 + 619 + areq_ctx->cryptlen = cryptlen; 620 + areq_ctx->headlen = assoc->length + assoc2->length; 621 + areq_ctx->trailen = assoc1->length; 622 + areq_ctx->sg = src; 623 + 624 + areq_ctx->complete = authenc_esn_verify_ahash_done; 625 + areq_ctx->update_complete = authenc_esn_verify_ahash_update_done; 626 + areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2; 627 + 628 + return crypto_authenc_esn_verify(req); 629 + } 630 + 631 + static int crypto_authenc_esn_decrypt(struct aead_request *req) 632 + { 633 + struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req); 634 + struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn); 635 + struct ablkcipher_request *abreq = aead_request_ctx(req); 636 + unsigned int cryptlen = req->cryptlen; 637 + unsigned int authsize = crypto_aead_authsize(authenc_esn); 638 + u8 *iv = req->iv; 639 + int err; 640 + 641 + if (cryptlen < authsize) 642 + return -EINVAL; 643 + cryptlen -= authsize; 644 + 645 + err = crypto_authenc_esn_iverify(req, iv, cryptlen); 646 + if (err) 647 + return err; 648 + 649 + ablkcipher_request_set_tfm(abreq, ctx->enc); 650 + ablkcipher_request_set_callback(abreq, aead_request_flags(req), 651 + req->base.complete, req->base.data); 652 + ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv); 653 + 654 + return crypto_ablkcipher_decrypt(abreq); 655 + } 656 + 657 + static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm) 658 + { 659 + struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); 660 + struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst); 661 + struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm); 662 + struct crypto_ahash *auth; 663 + struct crypto_ablkcipher *enc; 664 + int err; 665 + 666 + auth = crypto_spawn_ahash(&ictx->auth); 667 + if (IS_ERR(auth)) 668 + return PTR_ERR(auth); 669 + 670 + enc = crypto_spawn_skcipher(&ictx->enc); 671 + err = PTR_ERR(enc); 672 + if (IS_ERR(enc)) 673 + goto err_free_ahash; 674 + 675 + ctx->auth = auth; 676 + ctx->enc = enc; 677 + 678 + ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) + 679 + crypto_ahash_alignmask(auth), 680 + crypto_ahash_alignmask(auth) + 1) + 681 + crypto_ablkcipher_ivsize(enc); 682 + 683 + tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) + 684 + ctx->reqoff + 685 + max_t(unsigned int, 686 + crypto_ahash_reqsize(auth) + 687 + sizeof(struct ahash_request), 688 + sizeof(struct skcipher_givcrypt_request) + 689 + crypto_ablkcipher_reqsize(enc)); 690 + 691 + return 0; 692 + 693 + err_free_ahash: 694 + crypto_free_ahash(auth); 695 + return err; 696 + } 697 + 698 + static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm) 699 + { 700 + struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm); 701 + 702 + crypto_free_ahash(ctx->auth); 703 + crypto_free_ablkcipher(ctx->enc); 704 + } 705 + 706 + static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb) 707 + { 708 + struct crypto_attr_type *algt; 709 + struct crypto_instance *inst; 710 + struct hash_alg_common *auth; 711 + struct crypto_alg *auth_base; 712 + struct crypto_alg *enc; 713 + struct authenc_esn_instance_ctx *ctx; 714 + const char *enc_name; 715 + int err; 716 + 717 + algt = crypto_get_attr_type(tb); 718 + err = PTR_ERR(algt); 719 + if (IS_ERR(algt)) 720 + return ERR_PTR(err); 721 + 722 + if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) 723 + return ERR_PTR(-EINVAL); 724 + 725 + auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, 726 + CRYPTO_ALG_TYPE_AHASH_MASK); 727 + if (IS_ERR(auth)) 728 + return ERR_CAST(auth); 729 + 730 + auth_base = &auth->base; 731 + 732 + enc_name = crypto_attr_alg_name(tb[2]); 733 + err = PTR_ERR(enc_name); 734 + if (IS_ERR(enc_name)) 735 + goto out_put_auth; 736 + 737 + inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 738 + err = -ENOMEM; 739 + if (!inst) 740 + goto out_put_auth; 741 + 742 + ctx = crypto_instance_ctx(inst); 743 + 744 + err = crypto_init_ahash_spawn(&ctx->auth, auth, inst); 745 + if (err) 746 + goto err_free_inst; 747 + 748 + crypto_set_skcipher_spawn(&ctx->enc, inst); 749 + err = crypto_grab_skcipher(&ctx->enc, enc_name, 0, 750 + crypto_requires_sync(algt->type, 751 + algt->mask)); 752 + if (err) 753 + goto err_drop_auth; 754 + 755 + enc = crypto_skcipher_spawn_alg(&ctx->enc); 756 + 757 + err = -ENAMETOOLONG; 758 + if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 759 + "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >= 760 + CRYPTO_MAX_ALG_NAME) 761 + goto err_drop_enc; 762 + 763 + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 764 + "authencesn(%s,%s)", auth_base->cra_driver_name, 765 + enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 766 + goto err_drop_enc; 767 + 768 + inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD; 769 + inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC; 770 + inst->alg.cra_priority = enc->cra_priority * 771 + 10 + auth_base->cra_priority; 772 + inst->alg.cra_blocksize = enc->cra_blocksize; 773 + inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask; 774 + inst->alg.cra_type = &crypto_aead_type; 775 + 776 + inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize; 777 + inst->alg.cra_aead.maxauthsize = auth->digestsize; 778 + 779 + inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx); 780 + 781 + inst->alg.cra_init = crypto_authenc_esn_init_tfm; 782 + inst->alg.cra_exit = crypto_authenc_esn_exit_tfm; 783 + 784 + inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey; 785 + inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt; 786 + inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt; 787 + inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt; 788 + 789 + out: 790 + crypto_mod_put(auth_base); 791 + return inst; 792 + 793 + err_drop_enc: 794 + crypto_drop_skcipher(&ctx->enc); 795 + err_drop_auth: 796 + crypto_drop_ahash(&ctx->auth); 797 + err_free_inst: 798 + kfree(inst); 799 + out_put_auth: 800 + inst = ERR_PTR(err); 801 + goto out; 802 + } 803 + 804 + static void crypto_authenc_esn_free(struct crypto_instance *inst) 805 + { 806 + struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst); 807 + 808 + crypto_drop_skcipher(&ctx->enc); 809 + crypto_drop_ahash(&ctx->auth); 810 + kfree(inst); 811 + } 812 + 813 + static struct crypto_template crypto_authenc_esn_tmpl = { 814 + .name = "authencesn", 815 + .alloc = crypto_authenc_esn_alloc, 816 + .free = crypto_authenc_esn_free, 817 + .module = THIS_MODULE, 818 + }; 819 + 820 + static int __init crypto_authenc_esn_module_init(void) 821 + { 822 + return crypto_register_template(&crypto_authenc_esn_tmpl); 823 + } 824 + 825 + static void __exit crypto_authenc_esn_module_exit(void) 826 + { 827 + crypto_unregister_template(&crypto_authenc_esn_tmpl); 828 + } 829 + 830 + module_init(crypto_authenc_esn_module_init); 831 + module_exit(crypto_authenc_esn_module_exit); 832 + 833 + MODULE_LICENSE("GPL"); 834 + MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>"); 835 + MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");