Commit | Line | Data |
---|---|---|
20cc01ba HX |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * geniv: Shared IV generator code | |
4 | * | |
5 | * This file provides common code to IV generators such as seqiv. | |
6 | * | |
7 | * Copyright (c) 2007-2019 Herbert Xu <herbert@gondor.apana.org.au> | |
8 | */ | |
9 | ||
10 | #include <crypto/internal/geniv.h> | |
11 | #include <crypto/internal/rng.h> | |
12 | #include <crypto/null.h> | |
13 | #include <linux/err.h> | |
14 | #include <linux/kernel.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/rtnetlink.h> | |
17 | #include <linux/slab.h> | |
18 | ||
19 | static int aead_geniv_setkey(struct crypto_aead *tfm, | |
20 | const u8 *key, unsigned int keylen) | |
21 | { | |
22 | struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); | |
23 | ||
24 | return crypto_aead_setkey(ctx->child, key, keylen); | |
25 | } | |
26 | ||
27 | static int aead_geniv_setauthsize(struct crypto_aead *tfm, | |
28 | unsigned int authsize) | |
29 | { | |
30 | struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); | |
31 | ||
32 | return crypto_aead_setauthsize(ctx->child, authsize); | |
33 | } | |
34 | ||
0f8f6d86 EB |
35 | static void aead_geniv_free(struct aead_instance *inst) |
36 | { | |
37 | crypto_drop_aead(aead_instance_ctx(inst)); | |
38 | kfree(inst); | |
39 | } | |
40 | ||
20cc01ba HX |
41 | struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl, |
42 | struct rtattr **tb, u32 type, u32 mask) | |
43 | { | |
44 | const char *name; | |
45 | struct crypto_aead_spawn *spawn; | |
46 | struct crypto_attr_type *algt; | |
47 | struct aead_instance *inst; | |
48 | struct aead_alg *alg; | |
49 | unsigned int ivsize; | |
50 | unsigned int maxauthsize; | |
51 | int err; | |
52 | ||
53 | algt = crypto_get_attr_type(tb); | |
54 | if (IS_ERR(algt)) | |
55 | return ERR_CAST(algt); | |
56 | ||
57 | if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) | |
58 | return ERR_PTR(-EINVAL); | |
59 | ||
60 | name = crypto_attr_alg_name(tb[1]); | |
61 | if (IS_ERR(name)) | |
62 | return ERR_CAST(name); | |
63 | ||
64 | inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); | |
65 | if (!inst) | |
66 | return ERR_PTR(-ENOMEM); | |
67 | ||
68 | spawn = aead_instance_ctx(inst); | |
69 | ||
70 | /* Ignore async algorithms if necessary. */ | |
71 | mask |= crypto_requires_sync(algt->type, algt->mask); | |
72 | ||
cd900f0c EB |
73 | err = crypto_grab_aead(spawn, aead_crypto_instance(inst), |
74 | name, type, mask); | |
20cc01ba HX |
75 | if (err) |
76 | goto err_free_inst; | |
77 | ||
78 | alg = crypto_spawn_aead_alg(spawn); | |
79 | ||
80 | ivsize = crypto_aead_alg_ivsize(alg); | |
81 | maxauthsize = crypto_aead_alg_maxauthsize(alg); | |
82 | ||
83 | err = -EINVAL; | |
84 | if (ivsize < sizeof(u64)) | |
85 | goto err_drop_alg; | |
86 | ||
87 | err = -ENAMETOOLONG; | |
88 | if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, | |
89 | "%s(%s)", tmpl->name, alg->base.cra_name) >= | |
90 | CRYPTO_MAX_ALG_NAME) | |
91 | goto err_drop_alg; | |
92 | if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, | |
93 | "%s(%s)", tmpl->name, alg->base.cra_driver_name) >= | |
94 | CRYPTO_MAX_ALG_NAME) | |
95 | goto err_drop_alg; | |
96 | ||
97 | inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; | |
98 | inst->alg.base.cra_priority = alg->base.cra_priority; | |
99 | inst->alg.base.cra_blocksize = alg->base.cra_blocksize; | |
100 | inst->alg.base.cra_alignmask = alg->base.cra_alignmask; | |
101 | inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); | |
102 | ||
103 | inst->alg.setkey = aead_geniv_setkey; | |
104 | inst->alg.setauthsize = aead_geniv_setauthsize; | |
105 | ||
106 | inst->alg.ivsize = ivsize; | |
107 | inst->alg.maxauthsize = maxauthsize; | |
108 | ||
0f8f6d86 EB |
109 | inst->free = aead_geniv_free; |
110 | ||
20cc01ba HX |
111 | out: |
112 | return inst; | |
113 | ||
114 | err_drop_alg: | |
115 | crypto_drop_aead(spawn); | |
116 | err_free_inst: | |
117 | kfree(inst); | |
118 | inst = ERR_PTR(err); | |
119 | goto out; | |
120 | } | |
121 | EXPORT_SYMBOL_GPL(aead_geniv_alloc); | |
122 | ||
20cc01ba HX |
123 | int aead_init_geniv(struct crypto_aead *aead) |
124 | { | |
125 | struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead); | |
126 | struct aead_instance *inst = aead_alg_instance(aead); | |
127 | struct crypto_aead *child; | |
128 | int err; | |
129 | ||
130 | spin_lock_init(&ctx->lock); | |
131 | ||
132 | err = crypto_get_default_rng(); | |
133 | if (err) | |
134 | goto out; | |
135 | ||
136 | err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, | |
137 | crypto_aead_ivsize(aead)); | |
138 | crypto_put_default_rng(); | |
139 | if (err) | |
140 | goto out; | |
141 | ||
142 | ctx->sknull = crypto_get_default_null_skcipher(); | |
143 | err = PTR_ERR(ctx->sknull); | |
144 | if (IS_ERR(ctx->sknull)) | |
145 | goto out; | |
146 | ||
147 | child = crypto_spawn_aead(aead_instance_ctx(inst)); | |
148 | err = PTR_ERR(child); | |
149 | if (IS_ERR(child)) | |
150 | goto drop_null; | |
151 | ||
152 | ctx->child = child; | |
153 | crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) + | |
154 | sizeof(struct aead_request)); | |
155 | ||
156 | err = 0; | |
157 | ||
158 | out: | |
159 | return err; | |
160 | ||
161 | drop_null: | |
162 | crypto_put_default_null_skcipher(); | |
163 | goto out; | |
164 | } | |
165 | EXPORT_SYMBOL_GPL(aead_init_geniv); | |
166 | ||
167 | void aead_exit_geniv(struct crypto_aead *tfm) | |
168 | { | |
169 | struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm); | |
170 | ||
171 | crypto_free_aead(ctx->child); | |
172 | crypto_put_default_null_skcipher(); | |
173 | } | |
174 | EXPORT_SYMBOL_GPL(aead_exit_geniv); | |
175 | ||
176 | MODULE_LICENSE("GPL"); | |
177 | MODULE_DESCRIPTION("Shared IV generator code"); |