Skip to content

Commit f1f2f61

Browse files
committed
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "The major feature in this time is IMA support for measuring and appraising appended file signatures. In addition are a couple of bug fixes and code cleanup to use struct_size(). In addition to the PE/COFF and IMA xattr signatures, the kexec kernel image may be signed with an appended signature, using the same scripts/sign-file tool that is used to sign kernel modules. Similarly, the initramfs may contain an appended signature. This contained a lot of refactoring of the existing appended signature verification code, so that IMA could retain the existing framework of calculating the file hash once, storing it in the IMA measurement list and extending the TPM, verifying the file's integrity based on a file hash or signature (eg. xattrs), and adding an audit record containing the file hash, all based on policy. (The IMA support for appended signatures patch set was posted and reviewed 11 times.) The support for appended signature paves the way for adding other signature verification methods, such as fs-verity, based on a single system-wide policy. The file hash used for verifying the signature and the signature, itself, can be included in the IMA measurement list" * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: ima_api: Use struct_size() in kzalloc() ima: use struct_size() in kzalloc() sefltest/ima: support appended signatures (modsig) ima: Fix use after free in ima_read_modsig() MODSIGN: make new include file self contained ima: fix freeing ongoing ahash_request ima: always return negative code for error ima: Store the measurement again when appraising a modsig ima: Define ima-modsig template ima: Collect modsig ima: Implement support for module-style appended signatures ima: Factor xattr_verify() out of ima_appraise_measurement() ima: Add modsig appraise_type option for module-style appended signatures integrity: Select CONFIG_KEYS instead of depending on it PKCS#7: Introduce pkcs7_get_digest() PKCS#7: Refactor verify_pkcs7_signature() MODSIGN: Export module signature definitions ima: initialize the "template" field with the default template
2 parents 298fb76 + 2a7f0e5 commit f1f2f61

32 files changed

+871
-203
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Description:
3737
euid:= decimal value
3838
fowner:= decimal value
3939
lsm: are LSM specific
40-
option: appraise_type:= [imasig]
40+
option: appraise_type:= [imasig] [imasig|modsig]
4141
template:= name of a defined IMA template type
4242
(eg, ima-ng). Only valid when action is "measure".
4343
pcr:= decimal value
@@ -105,3 +105,7 @@ Description:
105105

106106
measure func=KEXEC_KERNEL_CHECK pcr=4
107107
measure func=KEXEC_INITRAMFS_CHECK pcr=5
108+
109+
Example of appraise rule allowing modsig appended signatures:
110+
111+
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig

Documentation/security/IMA-templates.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ descriptors by adding their identifier to the format string
6868
- 'd-ng': the digest of the event, calculated with an arbitrary hash
6969
algorithm (field format: [<hash algo>:]digest, where the digest
7070
prefix is shown only if the hash algorithm is not SHA1 or MD5);
71+
- 'd-modsig': the digest of the event without the appended modsig;
7172
- 'n-ng': the name of the event, without size limitations;
7273
- 'sig': the file signature;
74+
- 'modsig' the appended file signature;
7375
- 'buf': the buffer data that was used to generate the hash without size limitations;
7476

7577

@@ -79,6 +81,7 @@ Below, there is the list of defined template descriptors:
7981
- "ima-ng" (default): its format is ``d-ng|n-ng``;
8082
- "ima-sig": its format is ``d-ng|n-ng|sig``;
8183
- "ima-buf": its format is ``d-ng|n-ng|buf``;
84+
- "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
8285

8386

8487
Use

arch/s390/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ config ARCH_HAS_KEXEC_PURGATORY
556556

557557
config KEXEC_VERIFY_SIG
558558
bool "Verify kernel signature during kexec_file_load() syscall"
559-
depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION
559+
depends on KEXEC_FILE && MODULE_SIG_FORMAT
560560
help
561561
This option makes kernel signature verification mandatory for
562562
the kexec_file_load() syscall.

arch/s390/kernel/machine_kexec_file.c

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <linux/elf.h>
1111
#include <linux/errno.h>
1212
#include <linux/kexec.h>
13-
#include <linux/module.h>
13+
#include <linux/module_signature.h>
1414
#include <linux/verification.h>
1515
#include <asm/boot_data.h>
1616
#include <asm/ipl.h>
@@ -23,28 +23,6 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
2323
};
2424

2525
#ifdef CONFIG_KEXEC_VERIFY_SIG
26-
/*
27-
* Module signature information block.
28-
*
29-
* The constituents of the signature section are, in order:
30-
*
31-
* - Signer's name
32-
* - Key identifier
33-
* - Signature data
34-
* - Information block
35-
*/
36-
struct module_signature {
37-
u8 algo; /* Public-key crypto algorithm [0] */
38-
u8 hash; /* Digest algorithm [0] */
39-
u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
40-
u8 signer_len; /* Length of signer's name [0] */
41-
u8 key_id_len; /* Length of key identifier [0] */
42-
u8 __pad[3];
43-
__be32 sig_len; /* Length of signature data */
44-
};
45-
46-
#define PKEY_ID_PKCS7 2
47-
4826
int s390_verify_sig(const char *kernel, unsigned long kernel_len)
4927
{
5028
const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;

certs/system_keyring.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -190,33 +190,27 @@ late_initcall(load_system_certificate_list);
190190
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
191191

192192
/**
193-
* verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
193+
* verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
194194
* @data: The data to be verified (NULL if expecting internal data).
195195
* @len: Size of @data.
196-
* @raw_pkcs7: The PKCS#7 message that is the signature.
197-
* @pkcs7_len: The size of @raw_pkcs7.
196+
* @pkcs7: The PKCS#7 message that is the signature.
198197
* @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
199198
* (void *)1UL for all trusted keys).
200199
* @usage: The use to which the key is being put.
201200
* @view_content: Callback to gain access to content.
202201
* @ctx: Context for callback.
203202
*/
204-
int verify_pkcs7_signature(const void *data, size_t len,
205-
const void *raw_pkcs7, size_t pkcs7_len,
206-
struct key *trusted_keys,
207-
enum key_being_used_for usage,
208-
int (*view_content)(void *ctx,
209-
const void *data, size_t len,
210-
size_t asn1hdrlen),
211-
void *ctx)
203+
int verify_pkcs7_message_sig(const void *data, size_t len,
204+
struct pkcs7_message *pkcs7,
205+
struct key *trusted_keys,
206+
enum key_being_used_for usage,
207+
int (*view_content)(void *ctx,
208+
const void *data, size_t len,
209+
size_t asn1hdrlen),
210+
void *ctx)
212211
{
213-
struct pkcs7_message *pkcs7;
214212
int ret;
215213

216-
pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
217-
if (IS_ERR(pkcs7))
218-
return PTR_ERR(pkcs7);
219-
220214
/* The data should be detached - so we need to supply it. */
221215
if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
222216
pr_err("PKCS#7 signature with non-detached data\n");
@@ -269,6 +263,41 @@ int verify_pkcs7_signature(const void *data, size_t len,
269263
}
270264

271265
error:
266+
pr_devel("<==%s() = %d\n", __func__, ret);
267+
return ret;
268+
}
269+
270+
/**
271+
* verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
272+
* @data: The data to be verified (NULL if expecting internal data).
273+
* @len: Size of @data.
274+
* @raw_pkcs7: The PKCS#7 message that is the signature.
275+
* @pkcs7_len: The size of @raw_pkcs7.
276+
* @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
277+
* (void *)1UL for all trusted keys).
278+
* @usage: The use to which the key is being put.
279+
* @view_content: Callback to gain access to content.
280+
* @ctx: Context for callback.
281+
*/
282+
int verify_pkcs7_signature(const void *data, size_t len,
283+
const void *raw_pkcs7, size_t pkcs7_len,
284+
struct key *trusted_keys,
285+
enum key_being_used_for usage,
286+
int (*view_content)(void *ctx,
287+
const void *data, size_t len,
288+
size_t asn1hdrlen),
289+
void *ctx)
290+
{
291+
struct pkcs7_message *pkcs7;
292+
int ret;
293+
294+
pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
295+
if (IS_ERR(pkcs7))
296+
return PTR_ERR(pkcs7);
297+
298+
ret = verify_pkcs7_message_sig(data, len, pkcs7, trusted_keys, usage,
299+
view_content, ctx);
300+
272301
pkcs7_free_message(pkcs7);
273302
pr_devel("<==%s() = %d\n", __func__, ret);
274303
return ret;

crypto/asymmetric_keys/pkcs7_verify.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/err.h>
1313
#include <linux/asn1.h>
1414
#include <crypto/hash.h>
15+
#include <crypto/hash_info.h>
1516
#include <crypto/public_key.h>
1617
#include "pkcs7_parser.h"
1718

@@ -29,6 +30,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
2930

3031
kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
3132

33+
/* The digest was calculated already. */
34+
if (sig->digest)
35+
return 0;
36+
3237
if (!sinfo->sig->hash_algo)
3338
return -ENOPKG;
3439

@@ -117,6 +122,34 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
117122
return ret;
118123
}
119124

125+
int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len,
126+
enum hash_algo *hash_algo)
127+
{
128+
struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
129+
int i, ret;
130+
131+
/*
132+
* This function doesn't support messages with more than one signature.
133+
*/
134+
if (sinfo == NULL || sinfo->next != NULL)
135+
return -EBADMSG;
136+
137+
ret = pkcs7_digest(pkcs7, sinfo);
138+
if (ret)
139+
return ret;
140+
141+
*buf = sinfo->sig->digest;
142+
*len = sinfo->sig->digest_size;
143+
144+
for (i = 0; i < HASH_ALGO__LAST; i++)
145+
if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) {
146+
*hash_algo = i;
147+
break;
148+
}
149+
150+
return 0;
151+
}
152+
120153
/*
121154
* Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7
122155
* uses the issuer's name and the issuing certificate serial number for

include/crypto/pkcs7.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define _CRYPTO_PKCS7_H
1010

1111
#include <linux/verification.h>
12+
#include <linux/hash_info.h>
1213
#include <crypto/public_key.h>
1314

1415
struct key;
@@ -40,4 +41,7 @@ extern int pkcs7_verify(struct pkcs7_message *pkcs7,
4041
extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
4142
const void *data, size_t datalen);
4243

44+
extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf,
45+
u32 *len, enum hash_algo *hash_algo);
46+
4347
#endif /* _CRYPTO_PKCS7_H */

include/linux/module.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@
2626
#include <linux/percpu.h>
2727
#include <asm/module.h>
2828

29-
/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
30-
#define MODULE_SIG_STRING "~Module signature appended~\n"
31-
3229
/* Not Yet Implemented */
3330
#define MODULE_SUPPORTED_DEVICE(name)
3431

include/linux/module_signature.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Module signature handling.
4+
*
5+
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6+
* Written by David Howells ([email protected])
7+
*/
8+
9+
#ifndef _LINUX_MODULE_SIGNATURE_H
10+
#define _LINUX_MODULE_SIGNATURE_H
11+
12+
#include <linux/types.h>
13+
14+
/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
15+
#define MODULE_SIG_STRING "~Module signature appended~\n"
16+
17+
enum pkey_id_type {
18+
PKEY_ID_PGP, /* OpenPGP generated key ID */
19+
PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
20+
PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
21+
};
22+
23+
/*
24+
* Module signature information block.
25+
*
26+
* The constituents of the signature section are, in order:
27+
*
28+
* - Signer's name
29+
* - Key identifier
30+
* - Signature data
31+
* - Information block
32+
*/
33+
struct module_signature {
34+
u8 algo; /* Public-key crypto algorithm [0] */
35+
u8 hash; /* Digest algorithm [0] */
36+
u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
37+
u8 signer_len; /* Length of signer's name [0] */
38+
u8 key_id_len; /* Length of key identifier [0] */
39+
u8 __pad[3];
40+
__be32 sig_len; /* Length of signature data */
41+
};
42+
43+
int mod_check_sig(const struct module_signature *ms, size_t file_len,
44+
const char *name);
45+
46+
#endif /* _LINUX_MODULE_SIGNATURE_H */

include/linux/verification.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
3232
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
3333

3434
struct key;
35+
struct pkcs7_message;
3536

3637
extern int verify_pkcs7_signature(const void *data, size_t len,
3738
const void *raw_pkcs7, size_t pkcs7_len,
@@ -41,6 +42,15 @@ extern int verify_pkcs7_signature(const void *data, size_t len,
4142
const void *data, size_t len,
4243
size_t asn1hdrlen),
4344
void *ctx);
45+
extern int verify_pkcs7_message_sig(const void *data, size_t len,
46+
struct pkcs7_message *pkcs7,
47+
struct key *trusted_keys,
48+
enum key_being_used_for usage,
49+
int (*view_content)(void *ctx,
50+
const void *data,
51+
size_t len,
52+
size_t asn1hdrlen),
53+
void *ctx);
4454

4555
#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION
4656
extern int verify_pefile_signature(const void *pebuf, unsigned pelen,

0 commit comments

Comments
 (0)