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

[CRYPTO] aead: Add aead_geniv_alloc/aead_geniv_free

This patch creates the infrastructure to help the construction of IV
generator templates that wrap around AEAD algorithms by adding an IV
generator to them. This is useful for AEAD algorithms with no built-in
IV generator or to replace their built-in generator.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+297 -7
+211 -5
crypto/aead.c
··· 12 12 * 13 13 */ 14 14 15 - #include <crypto/algapi.h> 16 - #include <linux/errno.h> 15 + #include <crypto/internal/aead.h> 16 + #include <linux/err.h> 17 17 #include <linux/init.h> 18 18 #include <linux/kernel.h> 19 19 #include <linux/module.h> 20 20 #include <linux/slab.h> 21 21 #include <linux/seq_file.h> 22 + 23 + #include "internal.h" 22 24 23 25 static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, 24 26 unsigned int keylen) ··· 57 55 58 56 int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 59 57 { 58 + struct aead_tfm *crt = crypto_aead_crt(tfm); 60 59 int err; 61 60 62 61 if (authsize > crypto_aead_alg(tfm)->maxauthsize) 63 62 return -EINVAL; 64 63 65 64 if (crypto_aead_alg(tfm)->setauthsize) { 66 - err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize); 65 + err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize); 67 66 if (err) 68 67 return err; 69 68 } 70 69 71 - crypto_aead_crt(tfm)->authsize = authsize; 70 + crypto_aead_crt(crt->base)->authsize = authsize; 71 + crt->authsize = authsize; 72 72 return 0; 73 73 } 74 74 EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); ··· 94 90 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 95 91 return -EINVAL; 96 92 97 - crt->setkey = setkey; 93 + crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ? 94 + alg->setkey : setkey; 98 95 crt->encrypt = alg->encrypt; 99 96 crt->decrypt = alg->decrypt; 100 97 crt->givencrypt = alg->givencrypt ?: no_givcrypt; 101 98 crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; 99 + crt->base = __crypto_aead_cast(tfm); 102 100 crt->ivsize = alg->ivsize; 103 101 crt->authsize = alg->maxauthsize; 104 102 ··· 117 111 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 118 112 seq_printf(m, "ivsize : %u\n", aead->ivsize); 119 113 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 114 + seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>"); 120 115 } 121 116 122 117 const struct crypto_type crypto_aead_type = { ··· 128 121 #endif 129 122 }; 130 123 EXPORT_SYMBOL_GPL(crypto_aead_type); 124 + 125 + static int aead_null_givencrypt(struct aead_givcrypt_request *req) 126 + { 127 + return crypto_aead_encrypt(&req->areq); 128 + } 129 + 130 + static int aead_null_givdecrypt(struct aead_givcrypt_request *req) 131 + { 132 + return crypto_aead_decrypt(&req->areq); 133 + } 134 + 135 + static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 136 + { 137 + struct aead_alg *alg = &tfm->__crt_alg->cra_aead; 138 + struct aead_tfm *crt = &tfm->crt_aead; 139 + 140 + if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 141 + return -EINVAL; 142 + 143 + crt->setkey = setkey; 144 + crt->encrypt = alg->encrypt; 145 + crt->decrypt = alg->decrypt; 146 + if (!alg->ivsize) { 147 + crt->givencrypt = aead_null_givencrypt; 148 + crt->givdecrypt = aead_null_givdecrypt; 149 + } 150 + crt->base = __crypto_aead_cast(tfm); 151 + crt->ivsize = alg->ivsize; 152 + crt->authsize = alg->maxauthsize; 153 + 154 + return 0; 155 + } 156 + 157 + static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) 158 + __attribute__ ((unused)); 159 + static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) 160 + { 161 + struct aead_alg *aead = &alg->cra_aead; 162 + 163 + seq_printf(m, "type : nivaead\n"); 164 + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 165 + seq_printf(m, "ivsize : %u\n", aead->ivsize); 166 + seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 167 + seq_printf(m, "geniv : %s\n", aead->geniv); 168 + } 169 + 170 + const struct crypto_type crypto_nivaead_type = { 171 + .ctxsize = crypto_aead_ctxsize, 172 + .init = crypto_init_nivaead_ops, 173 + #ifdef CONFIG_PROC_FS 174 + .show = crypto_nivaead_show, 175 + #endif 176 + }; 177 + EXPORT_SYMBOL_GPL(crypto_nivaead_type); 178 + 179 + static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn, 180 + const char *name, u32 type, u32 mask) 181 + { 182 + struct crypto_alg *alg; 183 + int err; 184 + 185 + type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 186 + type |= CRYPTO_ALG_TYPE_AEAD; 187 + mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV; 188 + 189 + alg = crypto_alg_mod_lookup(name, type, mask); 190 + if (IS_ERR(alg)) 191 + return PTR_ERR(alg); 192 + 193 + err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); 194 + crypto_mod_put(alg); 195 + return err; 196 + } 197 + 198 + struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, 199 + struct rtattr **tb, u32 type, 200 + u32 mask) 201 + { 202 + const char *name; 203 + struct crypto_aead_spawn *spawn; 204 + struct crypto_attr_type *algt; 205 + struct crypto_instance *inst; 206 + struct crypto_alg *alg; 207 + int err; 208 + 209 + algt = crypto_get_attr_type(tb); 210 + err = PTR_ERR(algt); 211 + if (IS_ERR(algt)) 212 + return ERR_PTR(err); 213 + 214 + if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) & 215 + algt->mask) 216 + return ERR_PTR(-EINVAL); 217 + 218 + name = crypto_attr_alg_name(tb[1]); 219 + err = PTR_ERR(name); 220 + if (IS_ERR(name)) 221 + return ERR_PTR(err); 222 + 223 + inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 224 + if (!inst) 225 + return ERR_PTR(-ENOMEM); 226 + 227 + spawn = crypto_instance_ctx(inst); 228 + 229 + /* Ignore async algorithms if necessary. */ 230 + mask |= crypto_requires_sync(algt->type, algt->mask); 231 + 232 + crypto_set_aead_spawn(spawn, inst); 233 + err = crypto_grab_nivaead(spawn, name, type, mask); 234 + if (err) 235 + goto err_free_inst; 236 + 237 + alg = crypto_aead_spawn_alg(spawn); 238 + 239 + err = -EINVAL; 240 + if (!alg->cra_aead.ivsize) 241 + goto err_drop_alg; 242 + 243 + /* 244 + * This is only true if we're constructing an algorithm with its 245 + * default IV generator. For the default generator we elide the 246 + * template name and double-check the IV generator. 247 + */ 248 + if (algt->mask & CRYPTO_ALG_GENIV) { 249 + if (strcmp(tmpl->name, alg->cra_aead.geniv)) 250 + goto err_drop_alg; 251 + 252 + memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); 253 + memcpy(inst->alg.cra_driver_name, alg->cra_driver_name, 254 + CRYPTO_MAX_ALG_NAME); 255 + } else { 256 + err = -ENAMETOOLONG; 257 + if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 258 + "%s(%s)", tmpl->name, alg->cra_name) >= 259 + CRYPTO_MAX_ALG_NAME) 260 + goto err_drop_alg; 261 + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 262 + "%s(%s)", tmpl->name, alg->cra_driver_name) >= 263 + CRYPTO_MAX_ALG_NAME) 264 + goto err_drop_alg; 265 + } 266 + 267 + inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV; 268 + inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; 269 + inst->alg.cra_priority = alg->cra_priority; 270 + inst->alg.cra_blocksize = alg->cra_blocksize; 271 + inst->alg.cra_alignmask = alg->cra_alignmask; 272 + inst->alg.cra_type = &crypto_aead_type; 273 + 274 + inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; 275 + inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; 276 + inst->alg.cra_aead.geniv = alg->cra_aead.geniv; 277 + 278 + inst->alg.cra_aead.setkey = alg->cra_aead.setkey; 279 + inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize; 280 + inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt; 281 + inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt; 282 + 283 + out: 284 + return inst; 285 + 286 + err_drop_alg: 287 + crypto_drop_aead(spawn); 288 + err_free_inst: 289 + kfree(inst); 290 + inst = ERR_PTR(err); 291 + goto out; 292 + } 293 + EXPORT_SYMBOL_GPL(aead_geniv_alloc); 294 + 295 + void aead_geniv_free(struct crypto_instance *inst) 296 + { 297 + crypto_drop_aead(crypto_instance_ctx(inst)); 298 + kfree(inst); 299 + } 300 + EXPORT_SYMBOL_GPL(aead_geniv_free); 301 + 302 + int aead_geniv_init(struct crypto_tfm *tfm) 303 + { 304 + struct crypto_instance *inst = (void *)tfm->__crt_alg; 305 + struct crypto_aead *aead; 306 + 307 + aead = crypto_spawn_aead(crypto_instance_ctx(inst)); 308 + if (IS_ERR(aead)) 309 + return PTR_ERR(aead); 310 + 311 + tfm->crt_aead.base = aead; 312 + tfm->crt_aead.reqsize += crypto_aead_reqsize(aead); 313 + 314 + return 0; 315 + } 316 + EXPORT_SYMBOL_GPL(aead_geniv_init); 317 + 318 + void aead_geniv_exit(struct crypto_tfm *tfm) 319 + { 320 + crypto_free_aead(tfm->crt_aead.base); 321 + } 322 + EXPORT_SYMBOL_GPL(aead_geniv_exit); 131 323 132 324 MODULE_LICENSE("GPL"); 133 325 MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
+77
include/crypto/internal/aead.h
··· 1 + /* 2 + * AEAD: Authenticated Encryption with Associated Data 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 + #ifndef _CRYPTO_INTERNAL_AEAD_H 14 + #define _CRYPTO_INTERNAL_AEAD_H 15 + 16 + #include <crypto/aead.h> 17 + #include <crypto/algapi.h> 18 + #include <linux/types.h> 19 + 20 + struct rtattr; 21 + 22 + struct crypto_aead_spawn { 23 + struct crypto_spawn base; 24 + }; 25 + 26 + extern const struct crypto_type crypto_nivaead_type; 27 + 28 + static inline void crypto_set_aead_spawn( 29 + struct crypto_aead_spawn *spawn, struct crypto_instance *inst) 30 + { 31 + crypto_set_spawn(&spawn->base, inst); 32 + } 33 + 34 + static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn) 35 + { 36 + crypto_drop_spawn(&spawn->base); 37 + } 38 + 39 + static inline struct crypto_alg *crypto_aead_spawn_alg( 40 + struct crypto_aead_spawn *spawn) 41 + { 42 + return spawn->base.alg; 43 + } 44 + 45 + static inline struct crypto_aead *crypto_spawn_aead( 46 + struct crypto_aead_spawn *spawn) 47 + { 48 + return __crypto_aead_cast( 49 + crypto_spawn_tfm(&spawn->base, CRYPTO_ALG_TYPE_AEAD, 50 + CRYPTO_ALG_TYPE_MASK)); 51 + } 52 + 53 + struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, 54 + struct rtattr **tb, u32 type, 55 + u32 mask); 56 + void aead_geniv_free(struct crypto_instance *inst); 57 + int aead_geniv_init(struct crypto_tfm *tfm); 58 + void aead_geniv_exit(struct crypto_tfm *tfm); 59 + 60 + static inline struct crypto_aead *aead_geniv_base(struct crypto_aead *geniv) 61 + { 62 + return crypto_aead_crt(geniv)->base; 63 + } 64 + 65 + static inline void *aead_givcrypt_reqctx(struct aead_givcrypt_request *req) 66 + { 67 + return aead_request_ctx(&req->areq); 68 + } 69 + 70 + static inline void aead_givcrypt_complete(struct aead_givcrypt_request *req, 71 + int err) 72 + { 73 + aead_request_complete(&req->areq, err); 74 + } 75 + 76 + #endif /* _CRYPTO_INTERNAL_AEAD_H */ 77 +
+9 -2
include/linux/crypto.h
··· 206 206 int (*givencrypt)(struct aead_givcrypt_request *req); 207 207 int (*givdecrypt)(struct aead_givcrypt_request *req); 208 208 209 + const char *geniv; 210 + 209 211 unsigned int ivsize; 210 212 unsigned int maxauthsize; 211 213 }; ··· 355 353 int (*decrypt)(struct aead_request *req); 356 354 int (*givencrypt)(struct aead_givcrypt_request *req); 357 355 int (*givdecrypt)(struct aead_givcrypt_request *req); 356 + 357 + struct crypto_aead *base; 358 + 358 359 unsigned int ivsize; 359 360 unsigned int authsize; 360 361 unsigned int reqsize; ··· 786 781 static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key, 787 782 unsigned int keylen) 788 783 { 789 - return crypto_aead_crt(tfm)->setkey(tfm, key, keylen); 784 + struct aead_tfm *crt = crypto_aead_crt(tfm); 785 + 786 + return crt->setkey(crt->base, key, keylen); 790 787 } 791 788 792 789 int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize); ··· 816 809 static inline void aead_request_set_tfm(struct aead_request *req, 817 810 struct crypto_aead *tfm) 818 811 { 819 - req->base.tfm = crypto_aead_tfm(tfm); 812 + req->base.tfm = crypto_aead_tfm(crypto_aead_crt(tfm)->base); 820 813 } 821 814 822 815 static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,