|
10 | 10 | #include <linux/errno.h>
|
11 | 11 | #include <linux/kernel.h>
|
12 | 12 | #include <linux/module.h>
|
| 13 | +#include <linux/scatterlist.h> |
13 | 14 | #include <linux/seq_file.h>
|
14 | 15 | #include <linux/slab.h>
|
15 | 16 | #include <linux/string.h>
|
16 | 17 | #include <net/netlink.h>
|
17 | 18 |
|
18 | 19 | #include "internal.h"
|
19 | 20 |
|
| 21 | +struct crypto_akcipher_sync_data { |
| 22 | + struct crypto_akcipher *tfm; |
| 23 | + const void *src; |
| 24 | + void *dst; |
| 25 | + unsigned int slen; |
| 26 | + unsigned int dlen; |
| 27 | + |
| 28 | + struct akcipher_request *req; |
| 29 | + struct crypto_wait cwait; |
| 30 | + struct scatterlist sg; |
| 31 | + u8 *buf; |
| 32 | +}; |
| 33 | + |
20 | 34 | static int __maybe_unused crypto_akcipher_report(
|
21 | 35 | struct sk_buff *skb, struct crypto_alg *alg)
|
22 | 36 | {
|
@@ -186,5 +200,86 @@ int akcipher_register_instance(struct crypto_template *tmpl,
|
186 | 200 | }
|
187 | 201 | EXPORT_SYMBOL_GPL(akcipher_register_instance);
|
188 | 202 |
|
| 203 | +static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data) |
| 204 | +{ |
| 205 | + unsigned int reqsize = crypto_akcipher_reqsize(data->tfm); |
| 206 | + unsigned int mlen = max(data->slen, data->dlen); |
| 207 | + struct akcipher_request *req; |
| 208 | + struct scatterlist *sg; |
| 209 | + unsigned int len; |
| 210 | + u8 *buf; |
| 211 | + |
| 212 | + len = sizeof(*req) + reqsize + mlen; |
| 213 | + if (len < mlen) |
| 214 | + return -EOVERFLOW; |
| 215 | + |
| 216 | + req = kzalloc(len, GFP_KERNEL); |
| 217 | + if (!req) |
| 218 | + return -ENOMEM; |
| 219 | + |
| 220 | + data->req = req; |
| 221 | + |
| 222 | + buf = (u8 *)(req + 1) + reqsize; |
| 223 | + data->buf = buf; |
| 224 | + memcpy(buf, data->src, data->slen); |
| 225 | + |
| 226 | + sg = &data->sg; |
| 227 | + sg_init_one(sg, buf, mlen); |
| 228 | + akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen); |
| 229 | + |
| 230 | + crypto_init_wait(&data->cwait); |
| 231 | + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, |
| 232 | + crypto_req_done, &data->cwait); |
| 233 | + |
| 234 | + return 0; |
| 235 | +} |
| 236 | + |
| 237 | +static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, |
| 238 | + int err) |
| 239 | +{ |
| 240 | + err = crypto_wait_req(err, &data->cwait); |
| 241 | + memcpy(data->dst, data->buf, data->dlen); |
| 242 | + data->dlen = data->req->dst_len; |
| 243 | + kfree_sensitive(data->req); |
| 244 | + return err; |
| 245 | +} |
| 246 | + |
| 247 | +int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm, |
| 248 | + const void *src, unsigned int slen, |
| 249 | + void *dst, unsigned int dlen) |
| 250 | +{ |
| 251 | + struct crypto_akcipher_sync_data data = { |
| 252 | + .tfm = tfm, |
| 253 | + .src = src, |
| 254 | + .dst = dst, |
| 255 | + .slen = slen, |
| 256 | + .dlen = dlen, |
| 257 | + }; |
| 258 | + |
| 259 | + return crypto_akcipher_sync_prep(&data) ?: |
| 260 | + crypto_akcipher_sync_post(&data, |
| 261 | + crypto_akcipher_encrypt(data.req)); |
| 262 | +} |
| 263 | +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_encrypt); |
| 264 | + |
| 265 | +int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm, |
| 266 | + const void *src, unsigned int slen, |
| 267 | + void *dst, unsigned int dlen) |
| 268 | +{ |
| 269 | + struct crypto_akcipher_sync_data data = { |
| 270 | + .tfm = tfm, |
| 271 | + .src = src, |
| 272 | + .dst = dst, |
| 273 | + .slen = slen, |
| 274 | + .dlen = dlen, |
| 275 | + }; |
| 276 | + |
| 277 | + return crypto_akcipher_sync_prep(&data) ?: |
| 278 | + crypto_akcipher_sync_post(&data, |
| 279 | + crypto_akcipher_decrypt(data.req)) ?: |
| 280 | + data.dlen; |
| 281 | +} |
| 282 | +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt); |
| 283 | + |
189 | 284 | MODULE_LICENSE("GPL");
|
190 | 285 | MODULE_DESCRIPTION("Generic public key cipher type");
|
0 commit comments