summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-04-06 11:14:24 -0400
committerDavid Howells <dhowells@redhat.com>2016-04-06 11:14:24 -0400
commite68503bd6836ba765dc8e0ee77ea675fedc07e41 (patch)
tree31ebec81d2f52adc89796dd063468235bfd1cc0e /crypto
parentad3043fda39db0361d9601685356db4512e914be (diff)
KEYS: Generalise system_verify_data() to provide access to internal content
Generalise system_verify_data() to provide access to internal content through a callback. This allows all the PKCS#7 stuff to be hidden inside this function and removed from the PE file parser and the PKCS#7 test key. If external content is not required, NULL should be passed as data to the function. If the callback is not required, that can be set to NULL. The function is now called verify_pkcs7_signature() to contrast with verify_pefile_signature() and the definitions of both have been moved into linux/verification.h along with the key_being_used_for enum. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asymmetric_keys/Kconfig4
-rw-r--r--crypto/asymmetric_keys/mscode_parser.c21
-rw-r--r--crypto/asymmetric_keys/pkcs7_key_type.c72
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c21
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c40
-rw-r--r--crypto/asymmetric_keys/verify_pefile.h5
6 files changed, 59 insertions, 104 deletions
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 91a7e047a765..f7d2ef9789d8 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -40,8 +40,7 @@ config PKCS7_MESSAGE_PARSER
40 40
41config PKCS7_TEST_KEY 41config PKCS7_TEST_KEY
42 tristate "PKCS#7 testing key type" 42 tristate "PKCS#7 testing key type"
43 depends on PKCS7_MESSAGE_PARSER 43 depends on SYSTEM_DATA_VERIFICATION
44 select SYSTEM_TRUSTED_KEYRING
45 help 44 help
46 This option provides a type of key that can be loaded up from a 45 This option provides a type of key that can be loaded up from a
47 PKCS#7 message - provided the message is signed by a trusted key. If 46 PKCS#7 message - provided the message is signed by a trusted key. If
@@ -54,6 +53,7 @@ config PKCS7_TEST_KEY
54config SIGNED_PE_FILE_VERIFICATION 53config SIGNED_PE_FILE_VERIFICATION
55 bool "Support for PE file signature verification" 54 bool "Support for PE file signature verification"
56 depends on PKCS7_MESSAGE_PARSER=y 55 depends on PKCS7_MESSAGE_PARSER=y
56 depends on SYSTEM_DATA_VERIFICATION
57 select ASN1 57 select ASN1
58 select OID_REGISTRY 58 select OID_REGISTRY
59 help 59 help
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
index 3242cbfaeaa2..6a76d5c70ef6 100644
--- a/crypto/asymmetric_keys/mscode_parser.c
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -21,19 +21,13 @@
21/* 21/*
22 * Parse a Microsoft Individual Code Signing blob 22 * Parse a Microsoft Individual Code Signing blob
23 */ 23 */
24int mscode_parse(struct pefile_context *ctx) 24int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
25 size_t asn1hdrlen)
25{ 26{
26 const void *content_data; 27 struct pefile_context *ctx = _ctx;
27 size_t data_len;
28 int ret;
29
30 ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
31
32 if (ret) {
33 pr_debug("PKCS#7 message does not contain data\n");
34 return ret;
35 }
36 28
29 content_data -= asn1hdrlen;
30 data_len += asn1hdrlen;
37 pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len), 31 pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
38 content_data); 32 content_data);
39 33
@@ -129,7 +123,6 @@ int mscode_note_digest(void *context, size_t hdrlen,
129{ 123{
130 struct pefile_context *ctx = context; 124 struct pefile_context *ctx = context;
131 125
132 ctx->digest = value; 126 ctx->digest = kmemdup(value, vlen, GFP_KERNEL);
133 ctx->digest_len = vlen; 127 return ctx->digest ? 0 : -ENOMEM;
134 return 0;
135} 128}
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
index e2d0edbbc71a..ab9bf5363ecd 100644
--- a/crypto/asymmetric_keys/pkcs7_key_type.c
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -13,12 +13,9 @@
13#include <linux/key.h> 13#include <linux/key.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/verification.h>
16#include <linux/key-type.h> 17#include <linux/key-type.h>
17#include <keys/asymmetric-type.h>
18#include <crypto/pkcs7.h>
19#include <keys/user-type.h> 18#include <keys/user-type.h>
20#include <keys/system_keyring.h>
21#include "pkcs7_parser.h"
22 19
23MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
24MODULE_DESCRIPTION("PKCS#7 testing key type"); 21MODULE_DESCRIPTION("PKCS#7 testing key type");
@@ -29,60 +26,47 @@ MODULE_PARM_DESC(pkcs7_usage,
29 "Usage to specify when verifying the PKCS#7 message"); 26 "Usage to specify when verifying the PKCS#7 message");
30 27
31/* 28/*
32 * Preparse a PKCS#7 wrapped and validated data blob. 29 * Retrieve the PKCS#7 message content.
33 */ 30 */
34static int pkcs7_preparse(struct key_preparsed_payload *prep) 31static int pkcs7_view_content(void *ctx, const void *data, size_t len,
32 size_t asn1hdrlen)
35{ 33{
36 enum key_being_used_for usage = pkcs7_usage; 34 struct key_preparsed_payload *prep = ctx;
37 struct pkcs7_message *pkcs7; 35 const void *saved_prep_data;
38 const void *data, *saved_prep_data; 36 size_t saved_prep_datalen;
39 size_t datalen, saved_prep_datalen;
40 bool trusted;
41 int ret; 37 int ret;
42 38
43 kenter("");
44
45 if (usage >= NR__KEY_BEING_USED_FOR) {
46 pr_err("Invalid usage type %d\n", usage);
47 return -EINVAL;
48 }
49
50 saved_prep_data = prep->data; 39 saved_prep_data = prep->data;
51 saved_prep_datalen = prep->datalen; 40 saved_prep_datalen = prep->datalen;
52 pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
53 if (IS_ERR(pkcs7)) {
54 ret = PTR_ERR(pkcs7);
55 goto error;
56 }
57
58 ret = pkcs7_verify(pkcs7, usage);
59 if (ret < 0)
60 goto error_free;
61
62 ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
63 if (ret < 0)
64 goto error_free;
65 if (!trusted)
66 pr_warn("PKCS#7 message doesn't chain back to a trusted key\n");
67
68 ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false);
69 if (ret < 0)
70 goto error_free;
71
72 prep->data = data; 41 prep->data = data;
73 prep->datalen = datalen; 42 prep->datalen = len;
43
74 ret = user_preparse(prep); 44 ret = user_preparse(prep);
45
75 prep->data = saved_prep_data; 46 prep->data = saved_prep_data;
76 prep->datalen = saved_prep_datalen; 47 prep->datalen = saved_prep_datalen;
77
78error_free:
79 pkcs7_free_message(pkcs7);
80error:
81 kleave(" = %d", ret);
82 return ret; 48 return ret;
83} 49}
84 50
85/* 51/*
52 * Preparse a PKCS#7 wrapped and validated data blob.
53 */
54static int pkcs7_preparse(struct key_preparsed_payload *prep)
55{
56 enum key_being_used_for usage = pkcs7_usage;
57
58 if (usage >= NR__KEY_BEING_USED_FOR) {
59 pr_err("Invalid usage type %d\n", usage);
60 return -EINVAL;
61 }
62
63 return verify_pkcs7_signature(NULL, 0,
64 prep->data, prep->datalen,
65 NULL, -ENOKEY, usage,
66 pkcs7_view_content, prep);
67}
68
69/*
86 * user defined keys take an arbitrary string as the description and an 70 * user defined keys take an arbitrary string as the description and an
87 * arbitrary blob of data as the payload 71 * arbitrary blob of data as the payload
88 */ 72 */
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 835701613125..af4cd8649117 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -168,24 +168,25 @@ EXPORT_SYMBOL_GPL(pkcs7_parse_message);
168 * @pkcs7: The preparsed PKCS#7 message to access 168 * @pkcs7: The preparsed PKCS#7 message to access
169 * @_data: Place to return a pointer to the data 169 * @_data: Place to return a pointer to the data
170 * @_data_len: Place to return the data length 170 * @_data_len: Place to return the data length
171 * @want_wrapper: True if the ASN.1 object header should be included in the data 171 * @_headerlen: Size of ASN.1 header not included in _data
172 * 172 *
173 * Get access to the data content of the PKCS#7 message, including, optionally, 173 * Get access to the data content of the PKCS#7 message. The size of the
174 * the header of the ASN.1 object that contains it. Returns -ENODATA if the 174 * header of the ASN.1 object that contains it is also provided and can be used
175 * data object was missing from the message. 175 * to adjust *_data and *_data_len to get the entire object.
176 *
177 * Returns -ENODATA if the data object was missing from the message.
176 */ 178 */
177int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, 179int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
178 const void **_data, size_t *_data_len, 180 const void **_data, size_t *_data_len,
179 bool want_wrapper) 181 size_t *_headerlen)
180{ 182{
181 size_t wrapper;
182
183 if (!pkcs7->data) 183 if (!pkcs7->data)
184 return -ENODATA; 184 return -ENODATA;
185 185
186 wrapper = want_wrapper ? pkcs7->data_hdrlen : 0; 186 *_data = pkcs7->data;
187 *_data = pkcs7->data - wrapper; 187 *_data_len = pkcs7->data_len;
188 *_data_len = pkcs7->data_len + wrapper; 188 if (_headerlen)
189 *_headerlen = pkcs7->data_hdrlen;
189 return 0; 190 return 0;
190} 191}
191EXPORT_SYMBOL_GPL(pkcs7_get_content_data); 192EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 7e8c2338ae25..265351075b0e 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -16,7 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/pe.h> 17#include <linux/pe.h>
18#include <linux/asn1.h> 18#include <linux/asn1.h>
19#include <crypto/pkcs7.h> 19#include <linux/verification.h>
20#include <crypto/hash.h> 20#include <crypto/hash.h>
21#include "verify_pefile.h" 21#include "verify_pefile.h"
22 22
@@ -392,9 +392,8 @@ error_no_desc:
392 * verify_pefile_signature - Verify the signature on a PE binary image 392 * verify_pefile_signature - Verify the signature on a PE binary image
393 * @pebuf: Buffer containing the PE binary image 393 * @pebuf: Buffer containing the PE binary image
394 * @pelen: Length of the binary image 394 * @pelen: Length of the binary image
395 * @trust_keyring: Signing certificates to use as starting points 395 * @trust_keys: Signing certificate(s) to use as starting points
396 * @usage: The use to which the key is being put. 396 * @usage: The use to which the key is being put.
397 * @_trusted: Set to true if trustworth, false otherwise
398 * 397 *
399 * Validate that the certificate chain inside the PKCS#7 message inside the PE 398 * Validate that the certificate chain inside the PKCS#7 message inside the PE
400 * binary image intersects keys we already know and trust. 399 * binary image intersects keys we already know and trust.
@@ -418,14 +417,10 @@ error_no_desc:
418 * May also return -ENOMEM. 417 * May also return -ENOMEM.
419 */ 418 */
420int verify_pefile_signature(const void *pebuf, unsigned pelen, 419int verify_pefile_signature(const void *pebuf, unsigned pelen,
421 struct key *trusted_keyring, 420 struct key *trusted_keys,
422 enum key_being_used_for usage, 421 enum key_being_used_for usage)
423 bool *_trusted)
424{ 422{
425 struct pkcs7_message *pkcs7;
426 struct pefile_context ctx; 423 struct pefile_context ctx;
427 const void *data;
428 size_t datalen;
429 int ret; 424 int ret;
430 425
431 kenter(""); 426 kenter("");
@@ -439,19 +434,10 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
439 if (ret < 0) 434 if (ret < 0)
440 return ret; 435 return ret;
441 436
442 pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len); 437 ret = verify_pkcs7_signature(NULL, 0,
443 if (IS_ERR(pkcs7)) 438 pebuf + ctx.sig_offset, ctx.sig_len,
444 return PTR_ERR(pkcs7); 439 trusted_keys, -EKEYREJECTED, usage,
445 ctx.pkcs7 = pkcs7; 440 mscode_parse, &ctx);
446
447 ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false);
448 if (ret < 0 || datalen == 0) {
449 pr_devel("PKCS#7 message does not contain data\n");
450 ret = -EBADMSG;
451 goto error;
452 }
453
454 ret = mscode_parse(&ctx);
455 if (ret < 0) 441 if (ret < 0)
456 goto error; 442 goto error;
457 443
@@ -462,16 +448,8 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
462 * contents. 448 * contents.
463 */ 449 */
464 ret = pefile_digest_pe(pebuf, pelen, &ctx); 450 ret = pefile_digest_pe(pebuf, pelen, &ctx);
465 if (ret < 0)
466 goto error;
467
468 ret = pkcs7_verify(pkcs7, usage);
469 if (ret < 0)
470 goto error;
471
472 ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted);
473 451
474error: 452error:
475 pkcs7_free_message(ctx.pkcs7); 453 kfree(ctx.digest);
476 return ret; 454 return ret;
477} 455}
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h
index a133eb81a492..cd4d20930728 100644
--- a/crypto/asymmetric_keys/verify_pefile.h
+++ b/crypto/asymmetric_keys/verify_pefile.h
@@ -9,7 +9,6 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12#include <linux/verify_pefile.h>
13#include <crypto/pkcs7.h> 12#include <crypto/pkcs7.h>
14#include <crypto/hash_info.h> 13#include <crypto/hash_info.h>
15 14
@@ -23,7 +22,6 @@ struct pefile_context {
23 unsigned sig_offset; 22 unsigned sig_offset;
24 unsigned sig_len; 23 unsigned sig_len;
25 const struct section_header *secs; 24 const struct section_header *secs;
26 struct pkcs7_message *pkcs7;
27 25
28 /* PKCS#7 MS Individual Code Signing content */ 26 /* PKCS#7 MS Individual Code Signing content */
29 const void *digest; /* Digest */ 27 const void *digest; /* Digest */
@@ -39,4 +37,5 @@ struct pefile_context {
39/* 37/*
40 * mscode_parser.c 38 * mscode_parser.c
41 */ 39 */
42extern int mscode_parse(struct pefile_context *ctx); 40extern int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
41 size_t asn1hdrlen);