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 = req->dst; 88 unsigned int cryptlen = req->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 err = crypto_hash_update(&desc, dst, cryptlen); 104 if (err) 105 goto auth_unlock; 106 107 err = crypto_hash_final(&desc, hash); 108 auth_unlock: 109 spin_unlock_bh(&ctx->auth_lock); 110 111 if (err) 112 return err; 113 114 scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1); 115 return 0; 116 } 117 118 static void crypto_authenc_encrypt_done(struct crypto_async_request *req, 119 int err) 120 { 121 if (!err) 122 err = crypto_authenc_hash(req->data); 123 124 aead_request_complete(req->data, err); 125 } 126 127 static int crypto_authenc_encrypt(struct aead_request *req) 128 { 129 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 130 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 131 struct ablkcipher_request *abreq = aead_request_ctx(req); 132 int err; 133 134 ablkcipher_request_set_tfm(abreq, ctx->enc); 135 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 136 crypto_authenc_encrypt_done, req); 137 ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 138 req->iv); 139 140 err = crypto_ablkcipher_encrypt(abreq); 141 if (err) 142 return err; 143 144 return crypto_authenc_hash(req); 145 } 146 147 static int crypto_authenc_verify(struct aead_request *req) 148 { 149 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 150 struct authenc_instance_ctx *ictx = 151 crypto_instance_ctx(crypto_aead_alg_instance(authenc)); 152 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 153 struct crypto_hash *auth = ctx->auth; 154 struct hash_desc desc = { 155 .tfm = auth, 156 .flags = aead_request_flags(req), 157 }; 158 u8 *ohash = aead_request_ctx(req); 159 u8 *ihash; 160 struct scatterlist *src = req->src; 161 unsigned int cryptlen = req->cryptlen; 162 unsigned int authsize; 163 int err; 164 165 ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), 166 crypto_hash_alignmask(auth) + 1); 167 ihash = ohash + crypto_hash_digestsize(auth); 168 169 spin_lock_bh(&ctx->auth_lock); 170 err = crypto_hash_init(&desc); 171 if (err) 172 goto auth_unlock; 173 174 err = crypto_hash_update(&desc, req->assoc, req->assoclen); 175 if (err) 176 goto auth_unlock; 177 178 err = crypto_hash_update(&desc, src, cryptlen); 179 if (err) 180 goto auth_unlock; 181 182 err = crypto_hash_final(&desc, ohash); 183 auth_unlock: 184 spin_unlock_bh(&ctx->auth_lock); 185 186 if (err) 187 return err; 188 189 authsize = ictx->authsize; 190 scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); 191 return memcmp(ihash, ohash, authsize) ? -EINVAL : 0; 192 } 193 194 static void crypto_authenc_decrypt_done(struct crypto_async_request *req, 195 int err) 196 { 197 aead_request_complete(req->data, err); 198 } 199 200 static int crypto_authenc_decrypt(struct aead_request *req) 201 { 202 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 203 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 204 struct ablkcipher_request *abreq = aead_request_ctx(req); 205 int err; 206 207 err = crypto_authenc_verify(req); 208 if (err) 209 return err; 210 211 ablkcipher_request_set_tfm(abreq, ctx->enc); 212 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 213 crypto_authenc_decrypt_done, req); 214 ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 215 req->iv); 216 217 return crypto_ablkcipher_decrypt(abreq); 218 } 219 220 static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) 221 { 222 struct crypto_instance *inst = (void *)tfm->__crt_alg; 223 struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst); 224 struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); 225 struct crypto_hash *auth; 226 struct crypto_ablkcipher *enc; 227 unsigned int digestsize; 228 int err; 229 230 auth = crypto_spawn_hash(&ictx->auth); 231 if (IS_ERR(auth)) 232 return PTR_ERR(auth); 233 234 err = -EINVAL; 235 digestsize = crypto_hash_digestsize(auth); 236 if (ictx->authsize > digestsize) 237 goto err_free_hash; 238 239 enc = crypto_spawn_ablkcipher(&ictx->enc); 240 err = PTR_ERR(enc); 241 if (IS_ERR(enc)) 242 goto err_free_hash; 243 244 ctx->auth = auth; 245 ctx->enc = enc; 246 tfm->crt_aead.reqsize = max_t(unsigned int, 247 (crypto_hash_alignmask(auth) & 248 ~(crypto_tfm_ctx_alignment() - 1)) + 249 digestsize * 2, 250 sizeof(struct ablkcipher_request) + 251 crypto_ablkcipher_reqsize(enc)); 252 253 spin_lock_init(&ctx->auth_lock); 254 255 return 0; 256 257 err_free_hash: 258 crypto_free_hash(auth); 259 return err; 260 } 261 262 static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm) 263 { 264 struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); 265 266 crypto_free_hash(ctx->auth); 267 crypto_free_ablkcipher(ctx->enc); 268 } 269 270 static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) 271 { 272 struct crypto_instance *inst; 273 struct crypto_alg *auth; 274 struct crypto_alg *enc; 275 struct authenc_instance_ctx *ctx; 276 unsigned int authsize; 277 unsigned int enckeylen; 278 int err; 279 280 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); 281 if (err) 282 return ERR_PTR(err); 283 284 auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, 285 CRYPTO_ALG_TYPE_HASH_MASK); 286 if (IS_ERR(auth)) 287 return ERR_PTR(PTR_ERR(auth)); 288 289 err = crypto_attr_u32(tb[2], &authsize); 290 inst = ERR_PTR(err); 291 if (err) 292 goto out_put_auth; 293 294 enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER, 295 CRYPTO_ALG_TYPE_MASK); 296 inst = ERR_PTR(PTR_ERR(enc)); 297 if (IS_ERR(enc)) 298 goto out_put_auth; 299 300 err = crypto_attr_u32(tb[4], &enckeylen); 301 if (err) 302 goto out_put_enc; 303 304 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 305 err = -ENOMEM; 306 if (!inst) 307 goto out_put_enc; 308 309 err = -ENAMETOOLONG; 310 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 311 "authenc(%s,%u,%s,%u)", auth->cra_name, authsize, 312 enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) 313 goto err_free_inst; 314 315 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 316 "authenc(%s,%u,%s,%u)", auth->cra_driver_name, 317 authsize, enc->cra_driver_name, enckeylen) >= 318 CRYPTO_MAX_ALG_NAME) 319 goto err_free_inst; 320 321 ctx = crypto_instance_ctx(inst); 322 ctx->authsize = authsize; 323 ctx->enckeylen = enckeylen; 324 325 err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); 326 if (err) 327 goto err_free_inst; 328 329 err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK); 330 if (err) 331 goto err_drop_auth; 332 333 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; 334 inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; 335 inst->alg.cra_blocksize = enc->cra_blocksize; 336 inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask); 337 inst->alg.cra_type = &crypto_aead_type; 338 339 inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize; 340 inst->alg.cra_aead.authsize = authsize; 341 342 inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); 343 344 inst->alg.cra_init = crypto_authenc_init_tfm; 345 inst->alg.cra_exit = crypto_authenc_exit_tfm; 346 347 inst->alg.cra_aead.setkey = crypto_authenc_setkey; 348 inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; 349 inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; 350 351 out: 352 crypto_mod_put(enc); 353 out_put_auth: 354 crypto_mod_put(auth); 355 return inst; 356 357 err_drop_auth: 358 crypto_drop_spawn(&ctx->auth); 359 err_free_inst: 360 kfree(inst); 361 out_put_enc: 362 inst = ERR_PTR(err); 363 goto out; 364 } 365 366 static void crypto_authenc_free(struct crypto_instance *inst) 367 { 368 struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); 369 370 crypto_drop_spawn(&ctx->enc); 371 crypto_drop_spawn(&ctx->auth); 372 kfree(inst); 373 } 374 375 static struct crypto_template crypto_authenc_tmpl = { 376 .name = "authenc", 377 .alloc = crypto_authenc_alloc, 378 .free = crypto_authenc_free, 379 .module = THIS_MODULE, 380 }; 381 382 static int __init crypto_authenc_module_init(void) 383 { 384 return crypto_register_template(&crypto_authenc_tmpl); 385 } 386 387 static void __exit crypto_authenc_module_exit(void) 388 { 389 crypto_unregister_template(&crypto_authenc_tmpl); 390 } 391 392 module_init(crypto_authenc_module_init); 393 module_exit(crypto_authenc_module_exit); 394 395 MODULE_LICENSE("GPL"); 396 MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); 397