Skip to content

Commit 6cb8815

Browse files
committed
crypto: sig - Add interface for sign/verify
Split out the sign/verify functionality from the existing akcipher interface. Most algorithms in akcipher either support encryption and decryption, or signing and verify. Only one supports both. As a signature algorithm may not support encryption at all, these two should be spearated. For now sig is simply a wrapper around akcipher as all algorithms remain unchanged. This is a first step and allows users to start allocating sig instead of akcipher. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent addde1f commit 6cb8815

File tree

8 files changed

+385
-18
lines changed

8 files changed

+385
-18
lines changed

crypto/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ config CRYPTO_AEAD2
7272
tristate
7373
select CRYPTO_ALGAPI2
7474

75+
config CRYPTO_SIG
76+
tristate
77+
select CRYPTO_SIG2
78+
select CRYPTO_ALGAPI
79+
80+
config CRYPTO_SIG2
81+
tristate
82+
select CRYPTO_ALGAPI2
83+
7584
config CRYPTO_SKCIPHER
7685
tristate
7786
select CRYPTO_SKCIPHER2
@@ -143,6 +152,7 @@ config CRYPTO_MANAGER2
143152
select CRYPTO_ACOMP2
144153
select CRYPTO_AEAD2
145154
select CRYPTO_AKCIPHER2
155+
select CRYPTO_SIG2
146156
select CRYPTO_HASH2
147157
select CRYPTO_KPP2
148158
select CRYPTO_RNG2

crypto/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ crypto_hash-y += shash.o
2525
obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
2626

2727
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
28+
obj-$(CONFIG_CRYPTO_SIG2) += sig.o
2829
obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
2930

3031
dh_generic-y := dh.o

crypto/akcipher.c

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,7 @@
1818

1919
#include "internal.h"
2020

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-
};
21+
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
3322

3423
static int __maybe_unused crypto_akcipher_report(
3524
struct sk_buff *skb, struct crypto_alg *alg)
@@ -119,7 +108,7 @@ static const struct crypto_type crypto_akcipher_type = {
119108
.report_stat = crypto_akcipher_report_stat,
120109
#endif
121110
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
122-
.maskset = CRYPTO_ALG_TYPE_MASK,
111+
.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
123112
.type = CRYPTO_ALG_TYPE_AKCIPHER,
124113
.tfmsize = offsetof(struct crypto_akcipher, base),
125114
};
@@ -200,7 +189,7 @@ int akcipher_register_instance(struct crypto_template *tmpl,
200189
}
201190
EXPORT_SYMBOL_GPL(akcipher_register_instance);
202191

203-
static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
192+
int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
204193
{
205194
unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
206195
unsigned int mlen = max(data->slen, data->dlen);
@@ -223,7 +212,7 @@ static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
223212
data->buf = buf;
224213
memcpy(buf, data->src, data->slen);
225214

226-
sg = &data->sg;
215+
sg = data->sg;
227216
sg_init_one(sg, buf, mlen);
228217
akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
229218

@@ -233,16 +222,17 @@ static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
233222

234223
return 0;
235224
}
225+
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
236226

237-
static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
238-
int err)
227+
int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
239228
{
240229
err = crypto_wait_req(err, &data->cwait);
241230
memcpy(data->dst, data->buf, data->dlen);
242231
data->dlen = data->req->dst_len;
243232
kfree_sensitive(data->req);
244233
return err;
245234
}
235+
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post);
246236

247237
int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
248238
const void *src, unsigned int slen,
@@ -281,5 +271,34 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
281271
}
282272
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
283273

274+
static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm)
275+
{
276+
struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
277+
278+
crypto_free_akcipher(*ctx);
279+
}
280+
281+
int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm)
282+
{
283+
struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
284+
struct crypto_alg *calg = tfm->__crt_alg;
285+
struct crypto_akcipher *akcipher;
286+
287+
if (!crypto_mod_get(calg))
288+
return -EAGAIN;
289+
290+
akcipher = crypto_create_tfm(calg, &crypto_akcipher_type);
291+
if (IS_ERR(akcipher)) {
292+
crypto_mod_put(calg);
293+
return PTR_ERR(akcipher);
294+
}
295+
296+
*ctx = akcipher;
297+
tfm->exit = crypto_exit_akcipher_ops_sig;
298+
299+
return 0;
300+
}
301+
EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig);
302+
284303
MODULE_LICENSE("GPL");
285304
MODULE_DESCRIPTION("Generic public key cipher type");

crypto/internal.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
#include <linux/numa.h>
1919
#include <linux/refcount.h>
2020
#include <linux/rwsem.h>
21+
#include <linux/scatterlist.h>
2122
#include <linux/sched.h>
2223
#include <linux/types.h>
2324

25+
struct akcipher_request;
26+
struct crypto_akcipher;
2427
struct crypto_instance;
2528
struct crypto_template;
2629

@@ -32,6 +35,19 @@ struct crypto_larval {
3235
bool test_started;
3336
};
3437

38+
struct crypto_akcipher_sync_data {
39+
struct crypto_akcipher *tfm;
40+
const void *src;
41+
void *dst;
42+
unsigned int slen;
43+
unsigned int dlen;
44+
45+
struct akcipher_request *req;
46+
struct crypto_wait cwait;
47+
struct scatterlist sg[2];
48+
u8 *buf;
49+
};
50+
3551
enum {
3652
CRYPTOA_UNSPEC,
3753
CRYPTOA_ALG,
@@ -111,6 +127,10 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
111127
void *crypto_clone_tfm(const struct crypto_type *frontend,
112128
struct crypto_tfm *otfm);
113129

130+
int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data);
131+
int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err);
132+
int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm);
133+
114134
static inline void *crypto_create_tfm(struct crypto_alg *alg,
115135
const struct crypto_type *frontend)
116136
{

crypto/sig.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Public Key Signature Algorithm
4+
*
5+
* Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
6+
*/
7+
8+
#include <crypto/akcipher.h>
9+
#include <crypto/internal/sig.h>
10+
#include <linux/cryptouser.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/string.h>
16+
#include <net/netlink.h>
17+
18+
#include "internal.h"
19+
20+
#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e
21+
22+
static const struct crypto_type crypto_sig_type;
23+
24+
static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm)
25+
{
26+
return container_of(tfm, struct crypto_sig, base);
27+
}
28+
29+
static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
30+
{
31+
if (tfm->__crt_alg->cra_type != &crypto_sig_type)
32+
return crypto_init_akcipher_ops_sig(tfm);
33+
34+
return 0;
35+
}
36+
37+
static void __maybe_unused crypto_sig_show(struct seq_file *m,
38+
struct crypto_alg *alg)
39+
{
40+
seq_puts(m, "type : sig\n");
41+
}
42+
43+
static int __maybe_unused crypto_sig_report(struct sk_buff *skb,
44+
struct crypto_alg *alg)
45+
{
46+
struct crypto_report_akcipher rsig = {};
47+
48+
strscpy(rsig.type, "sig", sizeof(rsig.type));
49+
50+
return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig);
51+
}
52+
53+
static int __maybe_unused crypto_sig_report_stat(struct sk_buff *skb,
54+
struct crypto_alg *alg)
55+
{
56+
struct crypto_stat_akcipher rsig = {};
57+
58+
strscpy(rsig.type, "sig", sizeof(rsig.type));
59+
60+
return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER, sizeof(rsig), &rsig);
61+
}
62+
63+
static const struct crypto_type crypto_sig_type = {
64+
.extsize = crypto_alg_extsize,
65+
.init_tfm = crypto_sig_init_tfm,
66+
#ifdef CONFIG_PROC_FS
67+
.show = crypto_sig_show,
68+
#endif
69+
#if IS_ENABLED(CONFIG_CRYPTO_USER)
70+
.report = crypto_sig_report,
71+
#endif
72+
#ifdef CONFIG_CRYPTO_STATS
73+
.report_stat = crypto_sig_report_stat,
74+
#endif
75+
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
76+
.maskset = CRYPTO_ALG_TYPE_SIG_MASK,
77+
.type = CRYPTO_ALG_TYPE_SIG,
78+
.tfmsize = offsetof(struct crypto_sig, base),
79+
};
80+
81+
struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)
82+
{
83+
return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask);
84+
}
85+
EXPORT_SYMBOL_GPL(crypto_alloc_sig);
86+
87+
int crypto_sig_maxsize(struct crypto_sig *tfm)
88+
{
89+
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
90+
91+
return crypto_akcipher_maxsize(*ctx);
92+
}
93+
EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
94+
95+
int crypto_sig_sign(struct crypto_sig *tfm,
96+
const void *src, unsigned int slen,
97+
void *dst, unsigned int dlen)
98+
{
99+
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
100+
struct crypto_akcipher_sync_data data = {
101+
.tfm = *ctx,
102+
.src = src,
103+
.dst = dst,
104+
.slen = slen,
105+
.dlen = dlen,
106+
};
107+
108+
return crypto_akcipher_sync_prep(&data) ?:
109+
crypto_akcipher_sync_post(&data,
110+
crypto_akcipher_sign(data.req));
111+
}
112+
EXPORT_SYMBOL_GPL(crypto_sig_sign);
113+
114+
int crypto_sig_verify(struct crypto_sig *tfm,
115+
const void *src, unsigned int slen,
116+
const void *digest, unsigned int dlen)
117+
{
118+
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
119+
struct crypto_akcipher_sync_data data = {
120+
.tfm = *ctx,
121+
.src = src,
122+
.slen = slen,
123+
.dlen = dlen,
124+
};
125+
int err;
126+
127+
err = crypto_akcipher_sync_prep(&data);
128+
if (err)
129+
return err;
130+
131+
sg_init_table(data.sg, 2);
132+
sg_set_buf(&data.sg[0], src, slen);
133+
sg_set_buf(&data.sg[1], digest, dlen);
134+
135+
return crypto_akcipher_sync_post(&data,
136+
crypto_akcipher_verify(data.req));
137+
}
138+
EXPORT_SYMBOL_GPL(crypto_sig_verify);
139+
140+
int crypto_sig_set_pubkey(struct crypto_sig *tfm,
141+
const void *key, unsigned int keylen)
142+
{
143+
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
144+
145+
return crypto_akcipher_set_pub_key(*ctx, key, keylen);
146+
}
147+
EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
148+
149+
int crypto_sig_set_privkey(struct crypto_sig *tfm,
150+
const void *key, unsigned int keylen)
151+
{
152+
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
153+
154+
return crypto_akcipher_set_priv_key(*ctx, key, keylen);
155+
}
156+
EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
157+
158+
MODULE_LICENSE("GPL");
159+
MODULE_DESCRIPTION("Public Key Signature Algorithms");

include/crypto/internal/sig.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Public Key Signature Algorithm
4+
*
5+
* Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
6+
*/
7+
#ifndef _CRYPTO_INTERNAL_SIG_H
8+
#define _CRYPTO_INTERNAL_SIG_H
9+
10+
#include <crypto/algapi.h>
11+
#include <crypto/sig.h>
12+
13+
static inline void *crypto_sig_ctx(struct crypto_sig *tfm)
14+
{
15+
return crypto_tfm_ctx(&tfm->base);
16+
}
17+
#endif

0 commit comments

Comments
 (0)