Skip to content

Commit d43de6c

Browse files
committed
akcipher: Move the RSA DER encoding check to the crypto layer
Move the RSA EMSA-PKCS1-v1_5 encoding from the asymmetric-key public_key subtype to the rsa crypto module's pkcs1pad template. This means that the public_key subtype no longer has any dependencies on public key type. To make this work, the following changes have been made: (1) The rsa pkcs1pad template is now used for RSA keys. This strips off the padding and returns just the message hash. (2) In a previous patch, the pkcs1pad template gained an optional second parameter that, if given, specifies the hash used. We now give this, and pkcs1pad checks the encoded message E(M) for the EMSA-PKCS1-v1_5 encoding and verifies that the correct digest OID is present. (3) The crypto driver in crypto/asymmetric_keys/rsa.c is now reduced to something that doesn't care about what the encryption actually does and and has been merged into public_key.c. (4) CONFIG_PUBLIC_KEY_ALGO_RSA is gone. Module signing must set CONFIG_CRYPTO_RSA=y instead. Thoughts: (*) Should the encoding style (eg. raw, EMSA-PKCS1-v1_5) also be passed to the padding template? Should there be multiple padding templates registered that share most of the code? Signed-off-by: David Howells <[email protected]> Signed-off-by: Tadeusz Struk <[email protected]> Acked-by: Herbert Xu <[email protected]>
1 parent a49de37 commit d43de6c

File tree

7 files changed

+95
-246
lines changed

7 files changed

+95
-246
lines changed

crypto/asymmetric_keys/Kconfig

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,13 @@ if ASYMMETRIC_KEY_TYPE
1212
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
1313
tristate "Asymmetric public-key crypto algorithm subtype"
1414
select MPILIB
15-
select PUBLIC_KEY_ALGO_RSA
1615
select CRYPTO_HASH_INFO
1716
help
1817
This option provides support for asymmetric public key type handling.
1918
If signature generation and/or verification are to be used,
2019
appropriate hash algorithms (such as SHA-1) must be available.
2120
ENOPKG will be reported if the requisite algorithm is unavailable.
2221

23-
config PUBLIC_KEY_ALGO_RSA
24-
tristate "RSA public-key algorithm"
25-
select CRYPTO_RSA
26-
help
27-
This option enables support for the RSA algorithm (PKCS#1, RFC3447).
28-
2922
config X509_CERTIFICATE_PARSER
3023
tristate "X.509 certificate parser"
3124
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE

crypto/asymmetric_keys/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
77
asymmetric_keys-y := asymmetric_type.o signature.o
88

99
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
10-
obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
1110

1211
#
1312
# X.509 Certificate handling

crypto/asymmetric_keys/public_key.c

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
#include <linux/kernel.h>
1818
#include <linux/slab.h>
1919
#include <linux/seq_file.h>
20+
#include <linux/scatterlist.h>
2021
#include <keys/asymmetric-subtype.h>
2122
#include <crypto/public_key.h>
23+
#include <crypto/akcipher.h>
2224

2325
MODULE_LICENSE("GPL");
2426

@@ -35,12 +37,6 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
3537
};
3638
EXPORT_SYMBOL_GPL(pkey_id_type_name);
3739

38-
static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey,
39-
const struct public_key_signature *sig) = {
40-
NULL,
41-
rsa_verify_signature
42-
};
43-
4440
/*
4541
* Provide a part of a description of the key for /proc/keys.
4642
*/
@@ -68,24 +64,110 @@ void public_key_destroy(void *payload)
6864
}
6965
EXPORT_SYMBOL_GPL(public_key_destroy);
7066

67+
struct public_key_completion {
68+
struct completion completion;
69+
int err;
70+
};
71+
72+
static void public_key_verify_done(struct crypto_async_request *req, int err)
73+
{
74+
struct public_key_completion *compl = req->data;
75+
76+
if (err == -EINPROGRESS)
77+
return;
78+
79+
compl->err = err;
80+
complete(&compl->completion);
81+
}
82+
7183
/*
7284
* Verify a signature using a public key.
7385
*/
7486
int public_key_verify_signature(const struct public_key *pkey,
7587
const struct public_key_signature *sig)
7688
{
89+
struct public_key_completion compl;
90+
struct crypto_akcipher *tfm;
91+
struct akcipher_request *req;
92+
struct scatterlist sig_sg, digest_sg;
93+
const char *alg_name;
94+
char alg_name_buf[CRYPTO_MAX_ALG_NAME];
95+
void *output;
96+
unsigned int outlen;
97+
int ret = -ENOMEM;
98+
99+
pr_devel("==>%s()\n", __func__);
100+
77101
BUG_ON(!pkey);
78102
BUG_ON(!sig);
79103
BUG_ON(!sig->digest);
80104
BUG_ON(!sig->s);
81105

82-
if (pkey->pkey_algo >= PKEY_ALGO__LAST)
83-
return -ENOPKG;
106+
alg_name = pkey_algo_name[sig->pkey_algo];
107+
if (sig->pkey_algo == PKEY_ALGO_RSA) {
108+
/* The data wangled by the RSA algorithm is typically padded
109+
* and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
110+
* sec 8.2].
111+
*/
112+
if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME,
113+
"pkcs1pad(rsa,%s)",
114+
hash_algo_name[sig->pkey_hash_algo]
115+
) >= CRYPTO_MAX_ALG_NAME)
116+
return -EINVAL;
117+
alg_name = alg_name_buf;
118+
}
119+
120+
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
121+
if (IS_ERR(tfm))
122+
return PTR_ERR(tfm);
123+
124+
req = akcipher_request_alloc(tfm, GFP_KERNEL);
125+
if (!req)
126+
goto error_free_tfm;
127+
128+
ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
129+
if (ret)
130+
goto error_free_req;
131+
132+
outlen = crypto_akcipher_maxsize(tfm);
133+
output = kmalloc(outlen, GFP_KERNEL);
134+
if (!output)
135+
goto error_free_req;
136+
137+
sg_init_one(&sig_sg, sig->s, sig->s_size);
138+
sg_init_one(&digest_sg, output, outlen);
139+
akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size,
140+
outlen);
141+
init_completion(&compl.completion);
142+
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
143+
CRYPTO_TFM_REQ_MAY_SLEEP,
144+
public_key_verify_done, &compl);
145+
146+
/* Perform the verification calculation. This doesn't actually do the
147+
* verification, but rather calculates the hash expected by the
148+
* signature and returns that to us.
149+
*/
150+
ret = crypto_akcipher_verify(req);
151+
if (ret == -EINPROGRESS) {
152+
wait_for_completion(&compl.completion);
153+
ret = compl.err;
154+
}
155+
if (ret < 0)
156+
goto out_free_output;
84157

85-
if (!alg_verify[pkey->pkey_algo])
86-
return -ENOPKG;
158+
/* Do the actual verification step. */
159+
if (req->dst_len != sig->digest_size ||
160+
memcmp(sig->digest, output, sig->digest_size) != 0)
161+
ret = -EKEYREJECTED;
87162

88-
return alg_verify[pkey->pkey_algo](pkey, sig);
163+
out_free_output:
164+
kfree(output);
165+
error_free_req:
166+
akcipher_request_free(req);
167+
error_free_tfm:
168+
crypto_free_akcipher(tfm);
169+
pr_devel("<==%s() = %d\n", __func__, ret);
170+
return ret;
89171
}
90172
EXPORT_SYMBOL_GPL(public_key_verify_signature);
91173

crypto/asymmetric_keys/rsa.c

Lines changed: 0 additions & 224 deletions
This file was deleted.

0 commit comments

Comments
 (0)