Commit | Line | Data |
---|---|---|
6cb8815f HX |
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 | ||
6cb8815f HX |
8 | #include <crypto/internal/sig.h> |
9 | #include <linux/cryptouser.h> | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
6cb8815f HX |
12 | #include <linux/seq_file.h> |
13 | #include <linux/string.h> | |
14 | #include <net/netlink.h> | |
15 | ||
16 | #include "internal.h" | |
17 | ||
18 | #define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e | |
19 | ||
65c4c93c LW |
20 | static void crypto_sig_exit_tfm(struct crypto_tfm *tfm) |
21 | { | |
22 | struct crypto_sig *sig = __crypto_sig_tfm(tfm); | |
23 | struct sig_alg *alg = crypto_sig_alg(sig); | |
24 | ||
25 | alg->exit(sig); | |
26 | } | |
27 | ||
6cb8815f HX |
28 | static int crypto_sig_init_tfm(struct crypto_tfm *tfm) |
29 | { | |
65c4c93c LW |
30 | struct crypto_sig *sig = __crypto_sig_tfm(tfm); |
31 | struct sig_alg *alg = crypto_sig_alg(sig); | |
32 | ||
33 | if (alg->exit) | |
34 | sig->base.exit = crypto_sig_exit_tfm; | |
35 | ||
36 | if (alg->init) | |
37 | return alg->init(sig); | |
38 | ||
6cb8815f HX |
39 | return 0; |
40 | } | |
41 | ||
65c4c93c LW |
42 | static void crypto_sig_free_instance(struct crypto_instance *inst) |
43 | { | |
44 | struct sig_instance *sig = sig_instance(inst); | |
45 | ||
46 | sig->free(sig); | |
47 | } | |
48 | ||
6cb8815f HX |
49 | static void __maybe_unused crypto_sig_show(struct seq_file *m, |
50 | struct crypto_alg *alg) | |
51 | { | |
52 | seq_puts(m, "type : sig\n"); | |
53 | } | |
54 | ||
55 | static int __maybe_unused crypto_sig_report(struct sk_buff *skb, | |
56 | struct crypto_alg *alg) | |
57 | { | |
65c4c93c | 58 | struct crypto_report_sig rsig = {}; |
6cb8815f HX |
59 | |
60 | strscpy(rsig.type, "sig", sizeof(rsig.type)); | |
61 | ||
65c4c93c | 62 | return nla_put(skb, CRYPTOCFGA_REPORT_SIG, sizeof(rsig), &rsig); |
6cb8815f HX |
63 | } |
64 | ||
6cb8815f HX |
65 | static const struct crypto_type crypto_sig_type = { |
66 | .extsize = crypto_alg_extsize, | |
67 | .init_tfm = crypto_sig_init_tfm, | |
65c4c93c | 68 | .free = crypto_sig_free_instance, |
6cb8815f HX |
69 | #ifdef CONFIG_PROC_FS |
70 | .show = crypto_sig_show, | |
71 | #endif | |
72 | #if IS_ENABLED(CONFIG_CRYPTO_USER) | |
73 | .report = crypto_sig_report, | |
6cb8815f HX |
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 | { | |
65c4c93c LW |
89 | struct sig_alg *alg = crypto_sig_alg(tfm); |
90 | ||
91 | return alg->max_size(tfm); | |
6cb8815f HX |
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 | { | |
65c4c93c LW |
99 | struct sig_alg *alg = crypto_sig_alg(tfm); |
100 | ||
101 | return alg->sign(tfm, src, slen, dst, dlen); | |
6cb8815f HX |
102 | } |
103 | EXPORT_SYMBOL_GPL(crypto_sig_sign); | |
104 | ||
105 | int crypto_sig_verify(struct crypto_sig *tfm, | |
106 | const void *src, unsigned int slen, | |
107 | const void *digest, unsigned int dlen) | |
108 | { | |
65c4c93c LW |
109 | struct sig_alg *alg = crypto_sig_alg(tfm); |
110 | ||
111 | return alg->verify(tfm, src, slen, digest, dlen); | |
6cb8815f HX |
112 | } |
113 | EXPORT_SYMBOL_GPL(crypto_sig_verify); | |
114 | ||
115 | int crypto_sig_set_pubkey(struct crypto_sig *tfm, | |
116 | const void *key, unsigned int keylen) | |
117 | { | |
65c4c93c LW |
118 | struct sig_alg *alg = crypto_sig_alg(tfm); |
119 | ||
120 | return alg->set_pub_key(tfm, key, keylen); | |
6cb8815f HX |
121 | } |
122 | EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey); | |
123 | ||
124 | int crypto_sig_set_privkey(struct crypto_sig *tfm, | |
125 | const void *key, unsigned int keylen) | |
126 | { | |
65c4c93c LW |
127 | struct sig_alg *alg = crypto_sig_alg(tfm); |
128 | ||
129 | return alg->set_priv_key(tfm, key, keylen); | |
6cb8815f HX |
130 | } |
131 | EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); | |
132 | ||
65c4c93c LW |
133 | static void sig_prepare_alg(struct sig_alg *alg) |
134 | { | |
135 | struct crypto_alg *base = &alg->base; | |
136 | ||
137 | base->cra_type = &crypto_sig_type; | |
138 | base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; | |
139 | base->cra_flags |= CRYPTO_ALG_TYPE_SIG; | |
140 | } | |
141 | ||
142 | static int sig_default_sign(struct crypto_sig *tfm, | |
143 | const void *src, unsigned int slen, | |
144 | void *dst, unsigned int dlen) | |
145 | { | |
146 | return -ENOSYS; | |
147 | } | |
148 | ||
149 | static int sig_default_verify(struct crypto_sig *tfm, | |
150 | const void *src, unsigned int slen, | |
151 | const void *dst, unsigned int dlen) | |
152 | { | |
153 | return -ENOSYS; | |
154 | } | |
155 | ||
156 | static int sig_default_set_key(struct crypto_sig *tfm, | |
157 | const void *key, unsigned int keylen) | |
158 | { | |
159 | return -ENOSYS; | |
160 | } | |
161 | ||
162 | int crypto_register_sig(struct sig_alg *alg) | |
163 | { | |
164 | struct crypto_alg *base = &alg->base; | |
165 | ||
166 | if (!alg->sign) | |
167 | alg->sign = sig_default_sign; | |
168 | if (!alg->verify) | |
169 | alg->verify = sig_default_verify; | |
170 | if (!alg->set_priv_key) | |
171 | alg->set_priv_key = sig_default_set_key; | |
172 | if (!alg->set_pub_key) | |
173 | return -EINVAL; | |
174 | if (!alg->max_size) | |
175 | return -EINVAL; | |
176 | ||
177 | sig_prepare_alg(alg); | |
178 | return crypto_register_alg(base); | |
179 | } | |
180 | EXPORT_SYMBOL_GPL(crypto_register_sig); | |
181 | ||
182 | void crypto_unregister_sig(struct sig_alg *alg) | |
183 | { | |
184 | crypto_unregister_alg(&alg->base); | |
185 | } | |
186 | EXPORT_SYMBOL_GPL(crypto_unregister_sig); | |
187 | ||
188 | int sig_register_instance(struct crypto_template *tmpl, | |
189 | struct sig_instance *inst) | |
190 | { | |
191 | if (WARN_ON(!inst->free)) | |
192 | return -EINVAL; | |
193 | sig_prepare_alg(&inst->alg); | |
194 | return crypto_register_instance(tmpl, sig_crypto_instance(inst)); | |
195 | } | |
196 | EXPORT_SYMBOL_GPL(sig_register_instance); | |
197 | ||
198 | int crypto_grab_sig(struct crypto_sig_spawn *spawn, | |
199 | struct crypto_instance *inst, | |
200 | const char *name, u32 type, u32 mask) | |
201 | { | |
202 | spawn->base.frontend = &crypto_sig_type; | |
203 | return crypto_grab_spawn(&spawn->base, inst, name, type, mask); | |
204 | } | |
205 | EXPORT_SYMBOL_GPL(crypto_grab_sig); | |
206 | ||
6cb8815f HX |
207 | MODULE_LICENSE("GPL"); |
208 | MODULE_DESCRIPTION("Public Key Signature Algorithms"); |