Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/crypto/akcipher.c
54331 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Public Key Encryption
4
*
5
* Copyright (c) 2015, Intel Corporation
6
* Authors: Tadeusz Struk <[email protected]>
7
*/
8
#include <crypto/internal/akcipher.h>
9
#include <linux/cryptouser.h>
10
#include <linux/errno.h>
11
#include <linux/kernel.h>
12
#include <linux/module.h>
13
#include <linux/scatterlist.h>
14
#include <linux/seq_file.h>
15
#include <linux/slab.h>
16
#include <linux/string.h>
17
#include <net/netlink.h>
18
19
#include "internal.h"
20
21
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
22
23
struct crypto_akcipher_sync_data {
24
struct crypto_akcipher *tfm;
25
const void *src;
26
void *dst;
27
unsigned int slen;
28
unsigned int dlen;
29
30
struct akcipher_request *req;
31
struct crypto_wait cwait;
32
struct scatterlist sg;
33
u8 *buf;
34
};
35
36
static int __maybe_unused crypto_akcipher_report(
37
struct sk_buff *skb, struct crypto_alg *alg)
38
{
39
struct crypto_report_akcipher rakcipher;
40
41
memset(&rakcipher, 0, sizeof(rakcipher));
42
43
strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
44
45
return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
46
sizeof(rakcipher), &rakcipher);
47
}
48
49
static void __maybe_unused crypto_akcipher_show(struct seq_file *m,
50
struct crypto_alg *alg)
51
{
52
seq_puts(m, "type : akcipher\n");
53
}
54
55
static void crypto_akcipher_exit_tfm(struct crypto_tfm *tfm)
56
{
57
struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm);
58
struct akcipher_alg *alg = crypto_akcipher_alg(akcipher);
59
60
alg->exit(akcipher);
61
}
62
63
static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm)
64
{
65
struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm);
66
struct akcipher_alg *alg = crypto_akcipher_alg(akcipher);
67
68
if (alg->exit)
69
akcipher->base.exit = crypto_akcipher_exit_tfm;
70
71
if (alg->init)
72
return alg->init(akcipher);
73
74
return 0;
75
}
76
77
static void crypto_akcipher_free_instance(struct crypto_instance *inst)
78
{
79
struct akcipher_instance *akcipher = akcipher_instance(inst);
80
81
akcipher->free(akcipher);
82
}
83
84
static const struct crypto_type crypto_akcipher_type = {
85
.extsize = crypto_alg_extsize,
86
.init_tfm = crypto_akcipher_init_tfm,
87
.free = crypto_akcipher_free_instance,
88
#ifdef CONFIG_PROC_FS
89
.show = crypto_akcipher_show,
90
#endif
91
#if IS_ENABLED(CONFIG_CRYPTO_USER)
92
.report = crypto_akcipher_report,
93
#endif
94
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
95
.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
96
.type = CRYPTO_ALG_TYPE_AKCIPHER,
97
.tfmsize = offsetof(struct crypto_akcipher, base),
98
.algsize = offsetof(struct akcipher_alg, base),
99
};
100
101
int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn,
102
struct crypto_instance *inst,
103
const char *name, u32 type, u32 mask)
104
{
105
spawn->base.frontend = &crypto_akcipher_type;
106
return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
107
}
108
EXPORT_SYMBOL_GPL(crypto_grab_akcipher);
109
110
struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type,
111
u32 mask)
112
{
113
return crypto_alloc_tfm(alg_name, &crypto_akcipher_type, type, mask);
114
}
115
EXPORT_SYMBOL_GPL(crypto_alloc_akcipher);
116
117
static void akcipher_prepare_alg(struct akcipher_alg *alg)
118
{
119
struct crypto_alg *base = &alg->base;
120
121
base->cra_type = &crypto_akcipher_type;
122
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
123
base->cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER;
124
}
125
126
static int akcipher_default_op(struct akcipher_request *req)
127
{
128
return -ENOSYS;
129
}
130
131
static int akcipher_default_set_key(struct crypto_akcipher *tfm,
132
const void *key, unsigned int keylen)
133
{
134
return -ENOSYS;
135
}
136
137
int crypto_register_akcipher(struct akcipher_alg *alg)
138
{
139
struct crypto_alg *base = &alg->base;
140
141
if (!alg->encrypt)
142
alg->encrypt = akcipher_default_op;
143
if (!alg->decrypt)
144
alg->decrypt = akcipher_default_op;
145
if (!alg->set_priv_key)
146
alg->set_priv_key = akcipher_default_set_key;
147
148
akcipher_prepare_alg(alg);
149
return crypto_register_alg(base);
150
}
151
EXPORT_SYMBOL_GPL(crypto_register_akcipher);
152
153
void crypto_unregister_akcipher(struct akcipher_alg *alg)
154
{
155
crypto_unregister_alg(&alg->base);
156
}
157
EXPORT_SYMBOL_GPL(crypto_unregister_akcipher);
158
159
int akcipher_register_instance(struct crypto_template *tmpl,
160
struct akcipher_instance *inst)
161
{
162
if (WARN_ON(!inst->free))
163
return -EINVAL;
164
akcipher_prepare_alg(&inst->alg);
165
return crypto_register_instance(tmpl, akcipher_crypto_instance(inst));
166
}
167
EXPORT_SYMBOL_GPL(akcipher_register_instance);
168
169
static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
170
{
171
unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
172
struct akcipher_request *req;
173
struct scatterlist *sg;
174
unsigned int mlen;
175
unsigned int len;
176
u8 *buf;
177
178
mlen = max(data->slen, data->dlen);
179
180
len = sizeof(*req) + reqsize + mlen;
181
if (len < mlen)
182
return -EOVERFLOW;
183
184
req = kzalloc(len, GFP_KERNEL);
185
if (!req)
186
return -ENOMEM;
187
188
data->req = req;
189
akcipher_request_set_tfm(req, data->tfm);
190
191
buf = (u8 *)(req + 1) + reqsize;
192
data->buf = buf;
193
memcpy(buf, data->src, data->slen);
194
195
sg = &data->sg;
196
sg_init_one(sg, buf, mlen);
197
akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
198
199
crypto_init_wait(&data->cwait);
200
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
201
crypto_req_done, &data->cwait);
202
203
return 0;
204
}
205
206
static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
207
int err)
208
{
209
err = crypto_wait_req(err, &data->cwait);
210
memcpy(data->dst, data->buf, data->dlen);
211
data->dlen = data->req->dst_len;
212
kfree_sensitive(data->req);
213
return err;
214
}
215
216
int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
217
const void *src, unsigned int slen,
218
void *dst, unsigned int dlen)
219
{
220
struct crypto_akcipher_sync_data data = {
221
.tfm = tfm,
222
.src = src,
223
.dst = dst,
224
.slen = slen,
225
.dlen = dlen,
226
};
227
228
return crypto_akcipher_sync_prep(&data) ?:
229
crypto_akcipher_sync_post(&data,
230
crypto_akcipher_encrypt(data.req));
231
}
232
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_encrypt);
233
234
int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
235
const void *src, unsigned int slen,
236
void *dst, unsigned int dlen)
237
{
238
struct crypto_akcipher_sync_data data = {
239
.tfm = tfm,
240
.src = src,
241
.dst = dst,
242
.slen = slen,
243
.dlen = dlen,
244
};
245
246
return crypto_akcipher_sync_prep(&data) ?:
247
crypto_akcipher_sync_post(&data,
248
crypto_akcipher_decrypt(data.req)) ?:
249
data.dlen;
250
}
251
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
252
253
MODULE_LICENSE("GPL");
254
MODULE_DESCRIPTION("Generic public key cipher type");
255
256