Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
0004  *                 derived from authenc.c
0005  *
0006  * Copyright (C) 2010 secunet Security Networks AG
0007  * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
0008  * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
0009  */
0010 
0011 #include <crypto/internal/aead.h>
0012 #include <crypto/internal/hash.h>
0013 #include <crypto/internal/skcipher.h>
0014 #include <crypto/authenc.h>
0015 #include <crypto/null.h>
0016 #include <crypto/scatterwalk.h>
0017 #include <linux/err.h>
0018 #include <linux/init.h>
0019 #include <linux/kernel.h>
0020 #include <linux/module.h>
0021 #include <linux/rtnetlink.h>
0022 #include <linux/slab.h>
0023 #include <linux/spinlock.h>
0024 
0025 struct authenc_esn_instance_ctx {
0026     struct crypto_ahash_spawn auth;
0027     struct crypto_skcipher_spawn enc;
0028 };
0029 
0030 struct crypto_authenc_esn_ctx {
0031     unsigned int reqoff;
0032     struct crypto_ahash *auth;
0033     struct crypto_skcipher *enc;
0034     struct crypto_sync_skcipher *null;
0035 };
0036 
0037 struct authenc_esn_request_ctx {
0038     struct scatterlist src[2];
0039     struct scatterlist dst[2];
0040     char tail[];
0041 };
0042 
0043 static void authenc_esn_request_complete(struct aead_request *req, int err)
0044 {
0045     if (err != -EINPROGRESS)
0046         aead_request_complete(req, err);
0047 }
0048 
0049 static int crypto_authenc_esn_setauthsize(struct crypto_aead *authenc_esn,
0050                       unsigned int authsize)
0051 {
0052     if (authsize > 0 && authsize < 4)
0053         return -EINVAL;
0054 
0055     return 0;
0056 }
0057 
0058 static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
0059                      unsigned int keylen)
0060 {
0061     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0062     struct crypto_ahash *auth = ctx->auth;
0063     struct crypto_skcipher *enc = ctx->enc;
0064     struct crypto_authenc_keys keys;
0065     int err = -EINVAL;
0066 
0067     if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
0068         goto out;
0069 
0070     crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
0071     crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
0072                      CRYPTO_TFM_REQ_MASK);
0073     err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
0074     if (err)
0075         goto out;
0076 
0077     crypto_skcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
0078     crypto_skcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
0079                      CRYPTO_TFM_REQ_MASK);
0080     err = crypto_skcipher_setkey(enc, keys.enckey, keys.enckeylen);
0081 out:
0082     memzero_explicit(&keys, sizeof(keys));
0083     return err;
0084 }
0085 
0086 static int crypto_authenc_esn_genicv_tail(struct aead_request *req,
0087                       unsigned int flags)
0088 {
0089     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0090     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0091     struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
0092     struct crypto_ahash *auth = ctx->auth;
0093     u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
0094                  crypto_ahash_alignmask(auth) + 1);
0095     unsigned int authsize = crypto_aead_authsize(authenc_esn);
0096     unsigned int assoclen = req->assoclen;
0097     unsigned int cryptlen = req->cryptlen;
0098     struct scatterlist *dst = req->dst;
0099     u32 tmp[2];
0100 
0101     /* Move high-order bits of sequence number back. */
0102     scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
0103     scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
0104     scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
0105 
0106     scatterwalk_map_and_copy(hash, dst, assoclen + cryptlen, authsize, 1);
0107     return 0;
0108 }
0109 
0110 static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
0111                      int err)
0112 {
0113     struct aead_request *req = areq->data;
0114 
0115     err = err ?: crypto_authenc_esn_genicv_tail(req, 0);
0116     aead_request_complete(req, err);
0117 }
0118 
0119 static int crypto_authenc_esn_genicv(struct aead_request *req,
0120                      unsigned int flags)
0121 {
0122     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0123     struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
0124     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0125     struct crypto_ahash *auth = ctx->auth;
0126     u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
0127                  crypto_ahash_alignmask(auth) + 1);
0128     struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
0129     unsigned int authsize = crypto_aead_authsize(authenc_esn);
0130     unsigned int assoclen = req->assoclen;
0131     unsigned int cryptlen = req->cryptlen;
0132     struct scatterlist *dst = req->dst;
0133     u32 tmp[2];
0134 
0135     if (!authsize)
0136         return 0;
0137 
0138     /* Move high-order bits of sequence number to the end. */
0139     scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
0140     scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
0141     scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
0142 
0143     sg_init_table(areq_ctx->dst, 2);
0144     dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
0145 
0146     ahash_request_set_tfm(ahreq, auth);
0147     ahash_request_set_crypt(ahreq, dst, hash, assoclen + cryptlen);
0148     ahash_request_set_callback(ahreq, flags,
0149                    authenc_esn_geniv_ahash_done, req);
0150 
0151     return crypto_ahash_digest(ahreq) ?:
0152            crypto_authenc_esn_genicv_tail(req, aead_request_flags(req));
0153 }
0154 
0155 
0156 static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
0157                         int err)
0158 {
0159     struct aead_request *areq = req->data;
0160 
0161     if (!err)
0162         err = crypto_authenc_esn_genicv(areq, 0);
0163 
0164     authenc_esn_request_complete(areq, err);
0165 }
0166 
0167 static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
0168 {
0169     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0170     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0171     SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
0172 
0173     skcipher_request_set_sync_tfm(skreq, ctx->null);
0174     skcipher_request_set_callback(skreq, aead_request_flags(req),
0175                       NULL, NULL);
0176     skcipher_request_set_crypt(skreq, req->src, req->dst, len, NULL);
0177 
0178     return crypto_skcipher_encrypt(skreq);
0179 }
0180 
0181 static int crypto_authenc_esn_encrypt(struct aead_request *req)
0182 {
0183     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0184     struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
0185     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0186     struct skcipher_request *skreq = (void *)(areq_ctx->tail +
0187                           ctx->reqoff);
0188     struct crypto_skcipher *enc = ctx->enc;
0189     unsigned int assoclen = req->assoclen;
0190     unsigned int cryptlen = req->cryptlen;
0191     struct scatterlist *src, *dst;
0192     int err;
0193 
0194     sg_init_table(areq_ctx->src, 2);
0195     src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen);
0196     dst = src;
0197 
0198     if (req->src != req->dst) {
0199         err = crypto_authenc_esn_copy(req, assoclen);
0200         if (err)
0201             return err;
0202 
0203         sg_init_table(areq_ctx->dst, 2);
0204         dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen);
0205     }
0206 
0207     skcipher_request_set_tfm(skreq, enc);
0208     skcipher_request_set_callback(skreq, aead_request_flags(req),
0209                       crypto_authenc_esn_encrypt_done, req);
0210     skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
0211 
0212     err = crypto_skcipher_encrypt(skreq);
0213     if (err)
0214         return err;
0215 
0216     return crypto_authenc_esn_genicv(req, aead_request_flags(req));
0217 }
0218 
0219 static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
0220                        unsigned int flags)
0221 {
0222     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0223     unsigned int authsize = crypto_aead_authsize(authenc_esn);
0224     struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
0225     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0226     struct skcipher_request *skreq = (void *)(areq_ctx->tail +
0227                           ctx->reqoff);
0228     struct crypto_ahash *auth = ctx->auth;
0229     u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
0230                   crypto_ahash_alignmask(auth) + 1);
0231     unsigned int cryptlen = req->cryptlen - authsize;
0232     unsigned int assoclen = req->assoclen;
0233     struct scatterlist *dst = req->dst;
0234     u8 *ihash = ohash + crypto_ahash_digestsize(auth);
0235     u32 tmp[2];
0236 
0237     if (!authsize)
0238         goto decrypt;
0239 
0240     /* Move high-order bits of sequence number back. */
0241     scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
0242     scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
0243     scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
0244 
0245     if (crypto_memneq(ihash, ohash, authsize))
0246         return -EBADMSG;
0247 
0248 decrypt:
0249 
0250     sg_init_table(areq_ctx->dst, 2);
0251     dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
0252 
0253     skcipher_request_set_tfm(skreq, ctx->enc);
0254     skcipher_request_set_callback(skreq, flags,
0255                       req->base.complete, req->base.data);
0256     skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
0257 
0258     return crypto_skcipher_decrypt(skreq);
0259 }
0260 
0261 static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
0262                       int err)
0263 {
0264     struct aead_request *req = areq->data;
0265 
0266     err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
0267     authenc_esn_request_complete(req, err);
0268 }
0269 
0270 static int crypto_authenc_esn_decrypt(struct aead_request *req)
0271 {
0272     struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
0273     struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
0274     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
0275     struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
0276     unsigned int authsize = crypto_aead_authsize(authenc_esn);
0277     struct crypto_ahash *auth = ctx->auth;
0278     u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
0279                   crypto_ahash_alignmask(auth) + 1);
0280     unsigned int assoclen = req->assoclen;
0281     unsigned int cryptlen = req->cryptlen;
0282     u8 *ihash = ohash + crypto_ahash_digestsize(auth);
0283     struct scatterlist *dst = req->dst;
0284     u32 tmp[2];
0285     int err;
0286 
0287     cryptlen -= authsize;
0288 
0289     if (req->src != dst) {
0290         err = crypto_authenc_esn_copy(req, assoclen + cryptlen);
0291         if (err)
0292             return err;
0293     }
0294 
0295     scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
0296                  authsize, 0);
0297 
0298     if (!authsize)
0299         goto tail;
0300 
0301     /* Move high-order bits of sequence number to the end. */
0302     scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
0303     scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
0304     scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
0305 
0306     sg_init_table(areq_ctx->dst, 2);
0307     dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
0308 
0309     ahash_request_set_tfm(ahreq, auth);
0310     ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
0311     ahash_request_set_callback(ahreq, aead_request_flags(req),
0312                    authenc_esn_verify_ahash_done, req);
0313 
0314     err = crypto_ahash_digest(ahreq);
0315     if (err)
0316         return err;
0317 
0318 tail:
0319     return crypto_authenc_esn_decrypt_tail(req, aead_request_flags(req));
0320 }
0321 
0322 static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
0323 {
0324     struct aead_instance *inst = aead_alg_instance(tfm);
0325     struct authenc_esn_instance_ctx *ictx = aead_instance_ctx(inst);
0326     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
0327     struct crypto_ahash *auth;
0328     struct crypto_skcipher *enc;
0329     struct crypto_sync_skcipher *null;
0330     int err;
0331 
0332     auth = crypto_spawn_ahash(&ictx->auth);
0333     if (IS_ERR(auth))
0334         return PTR_ERR(auth);
0335 
0336     enc = crypto_spawn_skcipher(&ictx->enc);
0337     err = PTR_ERR(enc);
0338     if (IS_ERR(enc))
0339         goto err_free_ahash;
0340 
0341     null = crypto_get_default_null_skcipher();
0342     err = PTR_ERR(null);
0343     if (IS_ERR(null))
0344         goto err_free_skcipher;
0345 
0346     ctx->auth = auth;
0347     ctx->enc = enc;
0348     ctx->null = null;
0349 
0350     ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth),
0351                 crypto_ahash_alignmask(auth) + 1);
0352 
0353     crypto_aead_set_reqsize(
0354         tfm,
0355         sizeof(struct authenc_esn_request_ctx) +
0356         ctx->reqoff +
0357         max_t(unsigned int,
0358               crypto_ahash_reqsize(auth) +
0359               sizeof(struct ahash_request),
0360               sizeof(struct skcipher_request) +
0361               crypto_skcipher_reqsize(enc)));
0362 
0363     return 0;
0364 
0365 err_free_skcipher:
0366     crypto_free_skcipher(enc);
0367 err_free_ahash:
0368     crypto_free_ahash(auth);
0369     return err;
0370 }
0371 
0372 static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm)
0373 {
0374     struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
0375 
0376     crypto_free_ahash(ctx->auth);
0377     crypto_free_skcipher(ctx->enc);
0378     crypto_put_default_null_skcipher();
0379 }
0380 
0381 static void crypto_authenc_esn_free(struct aead_instance *inst)
0382 {
0383     struct authenc_esn_instance_ctx *ctx = aead_instance_ctx(inst);
0384 
0385     crypto_drop_skcipher(&ctx->enc);
0386     crypto_drop_ahash(&ctx->auth);
0387     kfree(inst);
0388 }
0389 
0390 static int crypto_authenc_esn_create(struct crypto_template *tmpl,
0391                      struct rtattr **tb)
0392 {
0393     u32 mask;
0394     struct aead_instance *inst;
0395     struct authenc_esn_instance_ctx *ctx;
0396     struct hash_alg_common *auth;
0397     struct crypto_alg *auth_base;
0398     struct skcipher_alg *enc;
0399     int err;
0400 
0401     err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
0402     if (err)
0403         return err;
0404 
0405     inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
0406     if (!inst)
0407         return -ENOMEM;
0408     ctx = aead_instance_ctx(inst);
0409 
0410     err = crypto_grab_ahash(&ctx->auth, aead_crypto_instance(inst),
0411                 crypto_attr_alg_name(tb[1]), 0, mask);
0412     if (err)
0413         goto err_free_inst;
0414     auth = crypto_spawn_ahash_alg(&ctx->auth);
0415     auth_base = &auth->base;
0416 
0417     err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst),
0418                    crypto_attr_alg_name(tb[2]), 0, mask);
0419     if (err)
0420         goto err_free_inst;
0421     enc = crypto_spawn_skcipher_alg(&ctx->enc);
0422 
0423     err = -ENAMETOOLONG;
0424     if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
0425              "authencesn(%s,%s)", auth_base->cra_name,
0426              enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
0427         goto err_free_inst;
0428 
0429     if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
0430              "authencesn(%s,%s)", auth_base->cra_driver_name,
0431              enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
0432         goto err_free_inst;
0433 
0434     inst->alg.base.cra_priority = enc->base.cra_priority * 10 +
0435                       auth_base->cra_priority;
0436     inst->alg.base.cra_blocksize = enc->base.cra_blocksize;
0437     inst->alg.base.cra_alignmask = auth_base->cra_alignmask |
0438                        enc->base.cra_alignmask;
0439     inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
0440 
0441     inst->alg.ivsize = crypto_skcipher_alg_ivsize(enc);
0442     inst->alg.chunksize = crypto_skcipher_alg_chunksize(enc);
0443     inst->alg.maxauthsize = auth->digestsize;
0444 
0445     inst->alg.init = crypto_authenc_esn_init_tfm;
0446     inst->alg.exit = crypto_authenc_esn_exit_tfm;
0447 
0448     inst->alg.setkey = crypto_authenc_esn_setkey;
0449     inst->alg.setauthsize = crypto_authenc_esn_setauthsize;
0450     inst->alg.encrypt = crypto_authenc_esn_encrypt;
0451     inst->alg.decrypt = crypto_authenc_esn_decrypt;
0452 
0453     inst->free = crypto_authenc_esn_free;
0454 
0455     err = aead_register_instance(tmpl, inst);
0456     if (err) {
0457 err_free_inst:
0458         crypto_authenc_esn_free(inst);
0459     }
0460     return err;
0461 }
0462 
0463 static struct crypto_template crypto_authenc_esn_tmpl = {
0464     .name = "authencesn",
0465     .create = crypto_authenc_esn_create,
0466     .module = THIS_MODULE,
0467 };
0468 
0469 static int __init crypto_authenc_esn_module_init(void)
0470 {
0471     return crypto_register_template(&crypto_authenc_esn_tmpl);
0472 }
0473 
0474 static void __exit crypto_authenc_esn_module_exit(void)
0475 {
0476     crypto_unregister_template(&crypto_authenc_esn_tmpl);
0477 }
0478 
0479 subsys_initcall(crypto_authenc_esn_module_init);
0480 module_exit(crypto_authenc_esn_module_exit);
0481 
0482 MODULE_LICENSE("GPL");
0483 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
0484 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
0485 MODULE_ALIAS_CRYPTO("authencesn");