aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/api.c')
-rw-r--r--crypto/api.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/crypto/api.c b/crypto/api.c
index 0906cedd4521..0444d242e985 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -55,6 +55,11 @@ void crypto_mod_put(struct crypto_alg *alg)
55} 55}
56EXPORT_SYMBOL_GPL(crypto_mod_put); 56EXPORT_SYMBOL_GPL(crypto_mod_put);
57 57
58static inline int crypto_is_test_larval(struct crypto_larval *larval)
59{
60 return larval->alg.cra_driver_name[0];
61}
62
58static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, 63static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
59 u32 mask) 64 u32 mask)
60{ 65{
@@ -71,6 +76,7 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
71 continue; 76 continue;
72 77
73 if (crypto_is_larval(q) && 78 if (crypto_is_larval(q) &&
79 !crypto_is_test_larval((struct crypto_larval *)q) &&
74 ((struct crypto_larval *)q)->mask != mask) 80 ((struct crypto_larval *)q)->mask != mask)
75 continue; 81 continue;
76 82
@@ -104,10 +110,8 @@ static void crypto_larval_destroy(struct crypto_alg *alg)
104 kfree(larval); 110 kfree(larval);
105} 111}
106 112
107static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, 113struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
108 u32 mask)
109{ 114{
110 struct crypto_alg *alg;
111 struct crypto_larval *larval; 115 struct crypto_larval *larval;
112 116
113 larval = kzalloc(sizeof(*larval), GFP_KERNEL); 117 larval = kzalloc(sizeof(*larval), GFP_KERNEL);
@@ -119,10 +123,25 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
119 larval->alg.cra_priority = -1; 123 larval->alg.cra_priority = -1;
120 larval->alg.cra_destroy = crypto_larval_destroy; 124 larval->alg.cra_destroy = crypto_larval_destroy;
121 125
122 atomic_set(&larval->alg.cra_refcnt, 2);
123 strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); 126 strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
124 init_completion(&larval->completion); 127 init_completion(&larval->completion);
125 128
129 return larval;
130}
131EXPORT_SYMBOL_GPL(crypto_larval_alloc);
132
133static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
134 u32 mask)
135{
136 struct crypto_alg *alg;
137 struct crypto_larval *larval;
138
139 larval = crypto_larval_alloc(name, type, mask);
140 if (IS_ERR(larval))
141 return ERR_CAST(larval);
142
143 atomic_set(&larval->alg.cra_refcnt, 2);
144
126 down_write(&crypto_alg_sem); 145 down_write(&crypto_alg_sem);
127 alg = __crypto_alg_lookup(name, type, mask); 146 alg = __crypto_alg_lookup(name, type, mask);
128 if (!alg) { 147 if (!alg) {
@@ -152,14 +171,23 @@ EXPORT_SYMBOL_GPL(crypto_larval_kill);
152static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) 171static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
153{ 172{
154 struct crypto_larval *larval = (void *)alg; 173 struct crypto_larval *larval = (void *)alg;
174 long timeout;
175
176 timeout = wait_for_completion_interruptible_timeout(
177 &larval->completion, 60 * HZ);
155 178
156 wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ);
157 alg = larval->adult; 179 alg = larval->adult;
158 if (alg) { 180 if (timeout < 0)
159 if (!crypto_mod_get(alg)) 181 alg = ERR_PTR(-EINTR);
160 alg = ERR_PTR(-EAGAIN); 182 else if (!timeout)
161 } else 183 alg = ERR_PTR(-ETIMEDOUT);
184 else if (!alg)
162 alg = ERR_PTR(-ENOENT); 185 alg = ERR_PTR(-ENOENT);
186 else if (crypto_is_test_larval(larval) &&
187 !(alg->cra_flags & CRYPTO_ALG_TESTED))
188 alg = ERR_PTR(-EAGAIN);
189 else if (!crypto_mod_get(alg))
190 alg = ERR_PTR(-EAGAIN);
163 crypto_mod_put(&larval->alg); 191 crypto_mod_put(&larval->alg);
164 192
165 return alg; 193 return alg;
@@ -192,25 +220,40 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
192 if (alg) 220 if (alg)
193 return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; 221 return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
194 222
195 return crypto_larval_alloc(name, type, mask); 223 return crypto_larval_add(name, type, mask);
196} 224}
197EXPORT_SYMBOL_GPL(crypto_larval_lookup); 225EXPORT_SYMBOL_GPL(crypto_larval_lookup);
198 226
227int crypto_probing_notify(unsigned long val, void *v)
228{
229 int ok;
230
231 ok = blocking_notifier_call_chain(&crypto_chain, val, v);
232 if (ok == NOTIFY_DONE) {
233 request_module("cryptomgr");
234 ok = blocking_notifier_call_chain(&crypto_chain, val, v);
235 }
236
237 return ok;
238}
239EXPORT_SYMBOL_GPL(crypto_probing_notify);
240
199struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) 241struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
200{ 242{
201 struct crypto_alg *alg; 243 struct crypto_alg *alg;
202 struct crypto_alg *larval; 244 struct crypto_alg *larval;
203 int ok; 245 int ok;
204 246
247 if (!(mask & CRYPTO_ALG_TESTED)) {
248 type |= CRYPTO_ALG_TESTED;
249 mask |= CRYPTO_ALG_TESTED;
250 }
251
205 larval = crypto_larval_lookup(name, type, mask); 252 larval = crypto_larval_lookup(name, type, mask);
206 if (IS_ERR(larval) || !crypto_is_larval(larval)) 253 if (IS_ERR(larval) || !crypto_is_larval(larval))
207 return larval; 254 return larval;
208 255
209 ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); 256 ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval);
210 if (ok == NOTIFY_DONE) {
211 request_module("cryptomgr");
212 ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval);
213 }
214 257
215 if (ok == NOTIFY_STOP) 258 if (ok == NOTIFY_STOP)
216 alg = crypto_larval_wait(larval); 259 alg = crypto_larval_wait(larval);