Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/crypto/asymmetric_keys/public_key.c
51589 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* In-software asymmetric public-key crypto subtype
3
*
4
* See Documentation/crypto/asymmetric-keys.rst
5
*
6
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
7
* Written by David Howells ([email protected])
8
*/
9
10
#define pr_fmt(fmt) "PKEY: "fmt
11
#include <crypto/akcipher.h>
12
#include <crypto/public_key.h>
13
#include <crypto/sig.h>
14
#include <keys/asymmetric-subtype.h>
15
#include <linux/asn1.h>
16
#include <linux/err.h>
17
#include <linux/kernel.h>
18
#include <linux/module.h>
19
#include <linux/seq_file.h>
20
#include <linux/slab.h>
21
#include <linux/string.h>
22
23
MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
24
MODULE_AUTHOR("Red Hat, Inc.");
25
MODULE_LICENSE("GPL");
26
27
/*
28
* Provide a part of a description of the key for /proc/keys.
29
*/
30
static void public_key_describe(const struct key *asymmetric_key,
31
struct seq_file *m)
32
{
33
struct public_key *key = asymmetric_key->payload.data[asym_crypto];
34
35
if (key)
36
seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
37
}
38
39
/*
40
* Destroy a public key algorithm key.
41
*/
42
void public_key_free(struct public_key *key)
43
{
44
if (key) {
45
kfree_sensitive(key->key);
46
kfree(key->params);
47
kfree(key);
48
}
49
}
50
EXPORT_SYMBOL_GPL(public_key_free);
51
52
/*
53
* Destroy a public key algorithm key.
54
*/
55
static void public_key_destroy(void *payload0, void *payload3)
56
{
57
public_key_free(payload0);
58
public_key_signature_free(payload3);
59
}
60
61
/*
62
* Given a public_key, and an encoding and hash_algo to be used for signing
63
* and/or verification with that key, determine the name of the corresponding
64
* akcipher algorithm. Also check that encoding and hash_algo are allowed.
65
*/
66
static int
67
software_key_determine_akcipher(const struct public_key *pkey,
68
const char *encoding, const char *hash_algo,
69
char alg_name[CRYPTO_MAX_ALG_NAME], bool *sig,
70
enum kernel_pkey_operation op)
71
{
72
int n;
73
74
*sig = true;
75
76
if (!encoding)
77
return -EINVAL;
78
79
if (strcmp(pkey->pkey_algo, "rsa") == 0) {
80
/*
81
* RSA signatures usually use EMSA-PKCS1-1_5 [RFC3447 sec 8.2].
82
*/
83
if (strcmp(encoding, "pkcs1") == 0) {
84
*sig = op == kernel_pkey_sign ||
85
op == kernel_pkey_verify;
86
if (!*sig) {
87
/*
88
* For encrypt/decrypt, hash_algo is not used
89
* but allowed to be set for historic reasons.
90
*/
91
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
92
"pkcs1pad(%s)",
93
pkey->pkey_algo);
94
} else {
95
if (!hash_algo)
96
hash_algo = "none";
97
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
98
"pkcs1(%s,%s)",
99
pkey->pkey_algo, hash_algo);
100
}
101
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
102
}
103
if (strcmp(encoding, "raw") != 0)
104
return -EINVAL;
105
/*
106
* Raw RSA cannot differentiate between different hash
107
* algorithms.
108
*/
109
if (hash_algo)
110
return -EINVAL;
111
*sig = false;
112
} else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
113
if (strcmp(encoding, "x962") != 0 &&
114
strcmp(encoding, "p1363") != 0)
115
return -EINVAL;
116
/*
117
* ECDSA signatures are taken over a raw hash, so they don't
118
* differentiate between different hash algorithms. That means
119
* that the verifier should hard-code a specific hash algorithm.
120
* Unfortunately, in practice ECDSA is used with multiple SHAs,
121
* so we have to allow all of them and not just one.
122
*/
123
if (!hash_algo)
124
return -EINVAL;
125
if (strcmp(hash_algo, "sha1") != 0 &&
126
strcmp(hash_algo, "sha224") != 0 &&
127
strcmp(hash_algo, "sha256") != 0 &&
128
strcmp(hash_algo, "sha384") != 0 &&
129
strcmp(hash_algo, "sha512") != 0 &&
130
strcmp(hash_algo, "sha3-256") != 0 &&
131
strcmp(hash_algo, "sha3-384") != 0 &&
132
strcmp(hash_algo, "sha3-512") != 0)
133
return -EINVAL;
134
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
135
encoding, pkey->pkey_algo);
136
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
137
} else if (strcmp(pkey->pkey_algo, "ecrdsa") == 0) {
138
if (strcmp(encoding, "raw") != 0)
139
return -EINVAL;
140
if (!hash_algo)
141
return -EINVAL;
142
if (strcmp(hash_algo, "streebog256") != 0 &&
143
strcmp(hash_algo, "streebog512") != 0)
144
return -EINVAL;
145
} else if (strcmp(pkey->pkey_algo, "mldsa44") == 0 ||
146
strcmp(pkey->pkey_algo, "mldsa65") == 0 ||
147
strcmp(pkey->pkey_algo, "mldsa87") == 0) {
148
if (strcmp(encoding, "raw") != 0)
149
return -EINVAL;
150
if (!hash_algo)
151
return -EINVAL;
152
if (strcmp(hash_algo, "none") != 0 &&
153
strcmp(hash_algo, "sha512") != 0)
154
return -EINVAL;
155
} else {
156
/* Unknown public key algorithm */
157
return -ENOPKG;
158
}
159
if (strscpy(alg_name, pkey->pkey_algo, CRYPTO_MAX_ALG_NAME) < 0)
160
return -EINVAL;
161
return 0;
162
}
163
164
static u8 *pkey_pack_u32(u8 *dst, u32 val)
165
{
166
memcpy(dst, &val, sizeof(val));
167
return dst + sizeof(val);
168
}
169
170
/*
171
* Query information about a key.
172
*/
173
static int software_key_query(const struct kernel_pkey_params *params,
174
struct kernel_pkey_query *info)
175
{
176
struct public_key *pkey = params->key->payload.data[asym_crypto];
177
char alg_name[CRYPTO_MAX_ALG_NAME];
178
u8 *key, *ptr;
179
int ret, len;
180
bool issig;
181
182
ret = software_key_determine_akcipher(pkey, params->encoding,
183
params->hash_algo, alg_name,
184
&issig, kernel_pkey_sign);
185
if (ret < 0)
186
return ret;
187
188
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
189
GFP_KERNEL);
190
if (!key)
191
return -ENOMEM;
192
193
memcpy(key, pkey->key, pkey->keylen);
194
ptr = key + pkey->keylen;
195
ptr = pkey_pack_u32(ptr, pkey->algo);
196
ptr = pkey_pack_u32(ptr, pkey->paramlen);
197
memcpy(ptr, pkey->params, pkey->paramlen);
198
199
memset(info, 0, sizeof(*info));
200
201
if (issig) {
202
struct crypto_sig *sig;
203
204
sig = crypto_alloc_sig(alg_name, 0, 0);
205
if (IS_ERR(sig)) {
206
ret = PTR_ERR(sig);
207
goto error_free_key;
208
}
209
210
if (pkey->key_is_private)
211
ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
212
else
213
ret = crypto_sig_set_pubkey(sig, key, pkey->keylen);
214
if (ret < 0)
215
goto error_free_sig;
216
217
len = crypto_sig_keysize(sig);
218
info->key_size = len;
219
info->max_sig_size = crypto_sig_maxsize(sig);
220
info->max_data_size = crypto_sig_digestsize(sig);
221
222
info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
223
if (pkey->key_is_private)
224
info->supported_ops |= KEYCTL_SUPPORTS_SIGN;
225
226
if (strcmp(params->encoding, "pkcs1") == 0) {
227
info->max_enc_size = len / BITS_PER_BYTE;
228
info->max_dec_size = len / BITS_PER_BYTE;
229
230
info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT;
231
if (pkey->key_is_private)
232
info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT;
233
}
234
235
error_free_sig:
236
crypto_free_sig(sig);
237
} else {
238
struct crypto_akcipher *tfm;
239
240
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
241
if (IS_ERR(tfm)) {
242
ret = PTR_ERR(tfm);
243
goto error_free_key;
244
}
245
246
if (pkey->key_is_private)
247
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
248
else
249
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
250
if (ret < 0)
251
goto error_free_akcipher;
252
253
len = crypto_akcipher_maxsize(tfm);
254
info->key_size = len * BITS_PER_BYTE;
255
info->max_sig_size = len;
256
info->max_data_size = len;
257
info->max_enc_size = len;
258
info->max_dec_size = len;
259
260
info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
261
if (pkey->key_is_private)
262
info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT;
263
264
error_free_akcipher:
265
crypto_free_akcipher(tfm);
266
}
267
268
error_free_key:
269
kfree_sensitive(key);
270
pr_devel("<==%s() = %d\n", __func__, ret);
271
return ret;
272
}
273
274
/*
275
* Do encryption, decryption and signing ops.
276
*/
277
static int software_key_eds_op(struct kernel_pkey_params *params,
278
const void *in, void *out)
279
{
280
const struct public_key *pkey = params->key->payload.data[asym_crypto];
281
char alg_name[CRYPTO_MAX_ALG_NAME];
282
struct crypto_akcipher *tfm;
283
struct crypto_sig *sig;
284
char *key, *ptr;
285
bool issig;
286
int ret;
287
288
pr_devel("==>%s()\n", __func__);
289
290
ret = software_key_determine_akcipher(pkey, params->encoding,
291
params->hash_algo, alg_name,
292
&issig, params->op);
293
if (ret < 0)
294
return ret;
295
296
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
297
GFP_KERNEL);
298
if (!key)
299
return -ENOMEM;
300
301
memcpy(key, pkey->key, pkey->keylen);
302
ptr = key + pkey->keylen;
303
ptr = pkey_pack_u32(ptr, pkey->algo);
304
ptr = pkey_pack_u32(ptr, pkey->paramlen);
305
memcpy(ptr, pkey->params, pkey->paramlen);
306
307
if (issig) {
308
sig = crypto_alloc_sig(alg_name, 0, 0);
309
if (IS_ERR(sig)) {
310
ret = PTR_ERR(sig);
311
goto error_free_key;
312
}
313
314
if (pkey->key_is_private)
315
ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
316
else
317
ret = crypto_sig_set_pubkey(sig, key, pkey->keylen);
318
if (ret)
319
goto error_free_tfm;
320
} else {
321
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
322
if (IS_ERR(tfm)) {
323
ret = PTR_ERR(tfm);
324
goto error_free_key;
325
}
326
327
if (pkey->key_is_private)
328
ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
329
else
330
ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
331
if (ret)
332
goto error_free_tfm;
333
}
334
335
ret = -EINVAL;
336
337
/* Perform the encryption calculation. */
338
switch (params->op) {
339
case kernel_pkey_encrypt:
340
if (issig)
341
break;
342
ret = crypto_akcipher_sync_encrypt(tfm, in, params->in_len,
343
out, params->out_len);
344
break;
345
case kernel_pkey_decrypt:
346
if (issig)
347
break;
348
ret = crypto_akcipher_sync_decrypt(tfm, in, params->in_len,
349
out, params->out_len);
350
break;
351
case kernel_pkey_sign:
352
if (!issig)
353
break;
354
ret = crypto_sig_sign(sig, in, params->in_len,
355
out, params->out_len);
356
break;
357
default:
358
BUG();
359
}
360
361
if (!issig && ret == 0)
362
ret = crypto_akcipher_maxsize(tfm);
363
364
error_free_tfm:
365
if (issig)
366
crypto_free_sig(sig);
367
else
368
crypto_free_akcipher(tfm);
369
error_free_key:
370
kfree_sensitive(key);
371
pr_devel("<==%s() = %d\n", __func__, ret);
372
return ret;
373
}
374
375
/*
376
* Verify a signature using a public key.
377
*/
378
int public_key_verify_signature(const struct public_key *pkey,
379
const struct public_key_signature *sig)
380
{
381
char alg_name[CRYPTO_MAX_ALG_NAME];
382
struct crypto_sig *tfm;
383
char *key, *ptr;
384
bool issig;
385
int ret;
386
387
pr_devel("==>%s()\n", __func__);
388
389
BUG_ON(!pkey);
390
BUG_ON(!sig);
391
BUG_ON(!sig->s);
392
393
/*
394
* If the signature specifies a public key algorithm, it *must* match
395
* the key's actual public key algorithm.
396
*
397
* Small exception: ECDSA signatures don't specify the curve, but ECDSA
398
* keys do. So the strings can mismatch slightly in that case:
399
* "ecdsa-nist-*" for the key, but "ecdsa" for the signature.
400
*/
401
if (sig->pkey_algo) {
402
if (strcmp(pkey->pkey_algo, sig->pkey_algo) != 0 &&
403
(strncmp(pkey->pkey_algo, "ecdsa-", 6) != 0 ||
404
strcmp(sig->pkey_algo, "ecdsa") != 0))
405
return -EKEYREJECTED;
406
}
407
408
ret = software_key_determine_akcipher(pkey, sig->encoding,
409
sig->hash_algo, alg_name,
410
&issig, kernel_pkey_verify);
411
if (ret < 0)
412
return ret;
413
414
tfm = crypto_alloc_sig(alg_name, 0, 0);
415
if (IS_ERR(tfm))
416
return PTR_ERR(tfm);
417
418
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
419
GFP_KERNEL);
420
if (!key) {
421
ret = -ENOMEM;
422
goto error_free_tfm;
423
}
424
425
memcpy(key, pkey->key, pkey->keylen);
426
ptr = key + pkey->keylen;
427
ptr = pkey_pack_u32(ptr, pkey->algo);
428
ptr = pkey_pack_u32(ptr, pkey->paramlen);
429
memcpy(ptr, pkey->params, pkey->paramlen);
430
431
if (pkey->key_is_private)
432
ret = crypto_sig_set_privkey(tfm, key, pkey->keylen);
433
else
434
ret = crypto_sig_set_pubkey(tfm, key, pkey->keylen);
435
if (ret)
436
goto error_free_key;
437
438
ret = crypto_sig_verify(tfm, sig->s, sig->s_size, sig->m, sig->m_size);
439
440
error_free_key:
441
kfree_sensitive(key);
442
error_free_tfm:
443
crypto_free_sig(tfm);
444
pr_devel("<==%s() = %d\n", __func__, ret);
445
if (WARN_ON_ONCE(ret > 0))
446
ret = -EINVAL;
447
return ret;
448
}
449
EXPORT_SYMBOL_GPL(public_key_verify_signature);
450
451
static int public_key_verify_signature_2(const struct key *key,
452
const struct public_key_signature *sig)
453
{
454
const struct public_key *pk = key->payload.data[asym_crypto];
455
return public_key_verify_signature(pk, sig);
456
}
457
458
/*
459
* Public key algorithm asymmetric key subtype
460
*/
461
struct asymmetric_key_subtype public_key_subtype = {
462
.owner = THIS_MODULE,
463
.name = "public_key",
464
.name_len = sizeof("public_key") - 1,
465
.describe = public_key_describe,
466
.destroy = public_key_destroy,
467
.query = software_key_query,
468
.eds_op = software_key_eds_op,
469
.verify_signature = public_key_verify_signature_2,
470
};
471
EXPORT_SYMBOL_GPL(public_key_subtype);
472
473