1 /* 2 * Authenc: Simple AEAD wrapper for IPsec 3 * 4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 */ 12 13 #include <crypto/algapi.h> 14 #include <linux/err.h> 15 #include <linux/init.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/slab.h> 19 #include <linux/spinlock.h> 20 21 #include "scatterwalk.h" 22 23 struct authenc_instance_ctx { 24 struct crypto_spawn auth; 25 struct crypto_spawn enc; 26 27 unsigned int authsize; 28 unsigned int enckeylen; 29 }; 30 31 struct crypto_authenc_ctx { 32 spinlock_t auth_lock; 33 struct crypto_hash *auth; 34 struct crypto_ablkcipher *enc; 35 }; 36 37 static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, 38 unsigned int keylen) 39 { 40 struct authenc_instance_ctx *ictx = 41 crypto_instance_ctx(crypto_aead_alg_instance(authenc)); 42 unsigned int enckeylen = ictx->enckeylen; 43 unsigned int authkeylen; 44 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 45 struct crypto_hash *auth = ctx->auth; 46 struct crypto_ablkcipher *enc = ctx->enc; 47 int err = -EINVAL; 48 49 if (keylen < enckeylen) { 50 crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); 51 goto out; 52 } 53 authkeylen = keylen - enckeylen; 54 55 crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); 56 crypto_hash_set_flags(auth, crypto_aead_get_flags(authenc) & 57 CRYPTO_TFM_REQ_MASK); 58 err = crypto_hash_setkey(auth, key, authkeylen); 59 crypto_aead_set_flags(authenc, crypto_hash_get_flags(auth) & 60 CRYPTO_TFM_RES_MASK); 61 62 if (err) 63 goto out; 64 65 crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); 66 crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) & 67 CRYPTO_TFM_REQ_MASK); 68 err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen); 69 crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) & 70 CRYPTO_TFM_RES_MASK); 71 72 out: 73 return err; 74 } 75 76 static int crypto_authenc_hash(struct aead_request *req) 77 { 78 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 79 struct authenc_instance_ctx *ictx = 80 crypto_instance_ctx(crypto_aead_alg_instance(authenc)); 81 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 82 struct crypto_hash *auth = ctx->auth; 83 struct hash_desc desc = { 84 .tfm = auth, 85 }; 86 u8 *hash = aead_request_ctx(req); 87 struct scatterlist *dst; 88 unsigned int cryptlen; 89 int err; 90 91 hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), 92 crypto_hash_alignmask(auth) + 1); 93 94 spin_lock_bh(&ctx->auth_lock); 95 err = crypto_hash_init(&desc); 96 if (err) 97 goto auth_unlock; 98 99 err = crypto_hash_update(&desc, req->assoc, req->assoclen); 100 if (err) 101 goto auth_unlock; 102 103 cryptlen = req->cryptlen; 104 dst = req->dst; 105 err = crypto_hash_update(&desc, dst, cryptlen); 106 if (err) 107 goto auth_unlock; 108 109 err = crypto_hash_final(&desc, hash); 110 auth_unlock: 111 spin_unlock_bh(&ctx->auth_lock); 112 113 if (err) 114 return err; 115 116 scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1); 117 return 0; 118 } 119 120 static void crypto_authenc_encrypt_done(struct crypto_async_request *req, 121 int err) 122 { 123 if (!err) 124 err = crypto_authenc_hash(req->data); 125 126 aead_request_complete(req->data, err); 127 } 128 129 static int crypto_authenc_encrypt(struct aead_request *req) 130 { 131 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 132 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 133 struct ablkcipher_request *abreq = aead_request_ctx(req); 134 int err; 135 136 ablkcipher_request_set_tfm(abreq, ctx->enc); 137 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 138 crypto_authenc_encrypt_done, req); 139 ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 140 req->iv); 141 142 err = crypto_ablkcipher_encrypt(abreq); 143 if (err) 144 return err; 145 146 return crypto_authenc_hash(req); 147 } 148 149 static int crypto_authenc_verify(struct aead_request *req) 150 { 151 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 152 struct authenc_instance_ctx *ictx = 153 crypto_instance_ctx(crypto_aead_alg_instance(authenc)); 154 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 155 struct crypto_hash *auth = ctx->auth; 156 struct hash_desc desc = { 157 .tfm = auth, 158 .flags = aead_request_flags(req), 159 }; 160 u8 *ohash = aead_request_ctx(req); 161 u8 *ihash; 162 struct scatterlist *src; 163 unsigned int cryptlen; 164 unsigned int authsize; 165 int err; 166 167 ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), 168 crypto_hash_alignmask(auth) + 1); 169 ihash = ohash + crypto_hash_digestsize(auth); 170 171 spin_lock_bh(&ctx->auth_lock); 172 err = crypto_hash_init(&desc); 173 if (err) 174 goto auth_unlock; 175 176 err = crypto_hash_update(&desc, req->assoc, req->assoclen); 177 if (err) 178 goto auth_unlock; 179 180 cryptlen = req->cryptlen; 181 src = req->src; 182 err = crypto_hash_update(&desc, src, cryptlen); 183 if (err) 184 goto auth_unlock; 185 186 err = crypto_hash_final(&desc, ohash); 187 auth_unlock: 188 spin_unlock_bh(&ctx->auth_lock); 189 190 if (err) 191 return err; 192 193 authsize = ictx->authsize; 194 scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); 195 return memcmp(ihash, ohash, authsize) ? -EINVAL : 0; 196 } 197 198 static void crypto_authenc_decrypt_done(struct crypto_async_request *req, 199 int err) 200 { 201 aead_request_complete(req->data, err); 202 } 203 204 static int crypto_authenc_decrypt(struct aead_request *req) 205 { 206 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 207 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 208 struct ablkcipher_request *abreq = aead_request_ctx(req); 209 int err; 210 211 err = crypto_authenc_verify(req); 212 if (err) 213 return err; 214 215 ablkcipher_request_set_tfm(abreq, ctx->enc); 216 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 217 crypto_authenc_decrypt_done, req); 218 ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 219 req->iv); 220 221 return crypto_ablkcipher_decrypt(abreq); 222 } 223 224 static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) 225 { 226 struct crypto_instance *inst = (void *)tfm->__crt_alg; 227 struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst); 228 struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); 229 struct crypto_hash *auth; 230 struct crypto_ablkcipher *enc; 231 unsigned int digestsize; 232 int err; 233 234 auth = crypto_spawn_hash(&ictx->auth); 235 if (IS_ERR(auth)) 236 return PTR_ERR(auth); 237 238 err = -EINVAL; 239 digestsize = crypto_hash_digestsize(auth); 240 if (ictx->authsize > digestsize) 241 goto err_free_hash; 242 243 enc = crypto_spawn_ablkcipher(&ictx->enc); 244 err = PTR_ERR(enc); 245 if (IS_ERR(enc)) 246 goto err_free_hash; 247 248 ctx->auth = auth; 249 ctx->enc = enc; 250 tfm->crt_aead.reqsize = max_t(unsigned int, 251 (crypto_hash_alignmask(auth) & 252 ~(crypto_tfm_ctx_alignment() - 1)) + 253 digestsize * 2, 254 sizeof(struct ablkcipher_request) + 255 crypto_ablkcipher_reqsize(enc)); 256 257 spin_lock_init(&ctx->auth_lock); 258 259 return 0; 260 261 err_free_hash: 262 crypto_free_hash(auth); 263 return err; 264 } 265 266 static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm) 267 { 268 struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); 269 270 crypto_free_hash(ctx->auth); 271 crypto_free_ablkcipher(ctx->enc); 272 } 273 274 static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) 275 { 276 struct crypto_instance *inst; 277 struct crypto_alg *auth; 278 struct crypto_alg *enc; 279 struct authenc_instance_ctx *ctx; 280 unsigned int authsize; 281 unsigned int enckeylen; 282 int err; 283 284 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); 285 if (err) 286 return ERR_PTR(err); 287 288 auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, 289 CRYPTO_ALG_TYPE_HASH_MASK); 290 if (IS_ERR(auth)) 291 return ERR_PTR(PTR_ERR(auth)); 292 293 err = crypto_attr_u32(tb[2], &authsize); 294 inst = ERR_PTR(err); 295 if (err) 296 goto out_put_auth; 297 298 enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER, 299 CRYPTO_ALG_TYPE_MASK); 300 inst = ERR_PTR(PTR_ERR(enc)); 301 if (IS_ERR(enc)) 302 goto out_put_auth; 303 304 err = crypto_attr_u32(tb[4], &enckeylen); 305 if (err) 306 goto out_put_enc; 307 308 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 309 err = -ENOMEM; 310 if (!inst) 311 goto out_put_enc; 312 313 err = -ENAMETOOLONG; 314 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 315 "authenc(%s,%u,%s,%u)", auth->cra_name, authsize, 316 enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) 317 goto err_free_inst; 318 319 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 320 "authenc(%s,%u,%s,%u)", auth->cra_driver_name, 321 authsize, enc->cra_driver_name, enckeylen) >= 322 CRYPTO_MAX_ALG_NAME) 323 goto err_free_inst; 324 325 ctx = crypto_instance_ctx(inst); 326 ctx->authsize = authsize; 327 ctx->enckeylen = enckeylen; 328 329 err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); 330 if (err) 331 goto err_free_inst; 332 333 err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK); 334 if (err) 335 goto err_drop_auth; 336 337 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; 338 inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; 339 inst->alg.cra_blocksize = enc->cra_blocksize; 340 inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask); 341 inst->alg.cra_type = &crypto_aead_type; 342 343 inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize; 344 inst->alg.cra_aead.authsize = authsize; 345 346 inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); 347 348 inst->alg.cra_init = crypto_authenc_init_tfm; 349 inst->alg.cra_exit = crypto_authenc_exit_tfm; 350 351 inst->alg.cra_aead.setkey = crypto_authenc_setkey; 352 inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; 353 inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; 354 355 out: 356 crypto_mod_put(enc); 357 out_put_auth: 358 crypto_mod_put(auth); 359 return inst; 360 361 err_drop_auth: 362 crypto_drop_spawn(&ctx->auth); 363 err_free_inst: 364 kfree(inst); 365 out_put_enc: 366 inst = ERR_PTR(err); 367 goto out; 368 } 369 370 static void crypto_authenc_free(struct crypto_instance *inst) 371 { 372 struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); 373 374 crypto_drop_spawn(&ctx->enc); 375 crypto_drop_spawn(&ctx->auth); 376 kfree(inst); 377 } 378 379 static struct crypto_template crypto_authenc_tmpl = { 380 .name = "authenc", 381 .alloc = crypto_authenc_alloc, 382 .free = crypto_authenc_free, 383 .module = THIS_MODULE, 384 }; 385 386 static int __init crypto_authenc_module_init(void) 387 { 388 return crypto_register_template(&crypto_authenc_tmpl); 389 } 390 391 static void __exit crypto_authenc_module_exit(void) 392 { 393 crypto_unregister_template(&crypto_authenc_tmpl); 394 } 395 396 module_init(crypto_authenc_module_init); 397 module_exit(crypto_authenc_module_exit); 398 399 MODULE_LICENSE("GPL"); 400 MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); 401