-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ima: digital signature verification using asymmetric keys
Asymmetric keys were introduced in linux-3.7 to verify the signature on signed kernel modules. The asymmetric keys infrastructure abstracts the signature verification from the crypto details. This patch adds IMA/EVM signature verification using asymmetric keys. Support for additional signature verification methods can now be delegated to the asymmetric key infrastructure. Although the module signature header and the IMA/EVM signature header could use the same format, to minimize the signature length and save space in the extended attribute, this patch defines a new IMA/EVM header format. The main difference is that the key identifier is a sha1[12 - 19] hash of the key modulus and exponent, similar to the current implementation. The only purpose of the key identifier is to identify the corresponding key in the kernel keyring. ima-evm-utils was updated to support the new signature format. While asymmetric signature verification functionality supports many different hash algorithms, the hash used in this patch is calculated during the IMA collection phase, based on the configured algorithm. The default algorithm is sha1, but for backwards compatibility md5 is supported. Due to this current limitation, signatures should be generated using a sha1 hash algorithm. Changes in this patch: - Functionality has been moved to separate source file in order to get rid of in source #ifdefs. - keyid is derived according to the RFC 3280. It does not require to assign IMA/EVM specific "description" when loading X509 certificate. Kernel asymmetric key subsystem automatically generate the description. Also loading a certificate does not require using of ima-evm-utils and can be done using keyctl only. - keyid size is reduced to 32 bits to save xattr space. Key search is done using partial match functionality of asymmetric_key_match(). - Kconfig option title was changed Signed-off-by: Dmitry Kasatkin <[email protected]> Acked-by: David Howells <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
- Loading branch information
Dmitry Kasatkin
authored and
Mimi Zohar
committed
Feb 7, 2013
1 parent
50af554
commit e075125
Showing
5 changed files
with
150 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Copyright (C) 2013 Intel Corporation | ||
* | ||
* Author: | ||
* Dmitry Kasatkin <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 2 of the License. | ||
* | ||
*/ | ||
|
||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
|
||
#include <linux/err.h> | ||
#include <linux/key-type.h> | ||
#include <crypto/public_key.h> | ||
#include <keys/asymmetric-type.h> | ||
|
||
#include "integrity.h" | ||
|
||
/* | ||
* signature format v2 - for using with asymmetric keys | ||
*/ | ||
struct signature_v2_hdr { | ||
uint8_t version; /* signature format version */ | ||
uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */ | ||
uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/ | ||
uint16_t sig_size; /* signature size */ | ||
uint8_t sig[0]; /* signature payload */ | ||
} __packed; | ||
|
||
/* | ||
* Request an asymmetric key. | ||
*/ | ||
static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | ||
{ | ||
struct key *key; | ||
char name[12]; | ||
|
||
sprintf(name, "id:%x", keyid); | ||
|
||
pr_debug("key search: \"%s\"\n", name); | ||
|
||
if (keyring) { | ||
/* search in specific keyring */ | ||
key_ref_t kref; | ||
kref = keyring_search(make_key_ref(keyring, 1), | ||
&key_type_asymmetric, name); | ||
if (IS_ERR(kref)) | ||
key = ERR_CAST(kref); | ||
else | ||
key = key_ref_to_ptr(kref); | ||
} else { | ||
key = request_key(&key_type_asymmetric, name, NULL); | ||
} | ||
|
||
if (IS_ERR(key)) { | ||
pr_warn("Request for unknown key '%s' err %ld\n", | ||
name, PTR_ERR(key)); | ||
switch (PTR_ERR(key)) { | ||
/* Hide some search errors */ | ||
case -EACCES: | ||
case -ENOTDIR: | ||
case -EAGAIN: | ||
return ERR_PTR(-ENOKEY); | ||
default: | ||
return key; | ||
} | ||
} | ||
|
||
pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key)); | ||
|
||
return key; | ||
} | ||
|
||
int asymmetric_verify(struct key *keyring, const char *sig, | ||
int siglen, const char *data, int datalen) | ||
{ | ||
struct public_key_signature pks; | ||
struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; | ||
struct key *key; | ||
int ret = -ENOMEM; | ||
|
||
if (siglen <= sizeof(*hdr)) | ||
return -EBADMSG; | ||
|
||
siglen -= sizeof(*hdr); | ||
|
||
if (siglen != __be16_to_cpu(hdr->sig_size)) | ||
return -EBADMSG; | ||
|
||
if (hdr->hash_algo >= PKEY_HASH__LAST) | ||
return -ENOPKG; | ||
|
||
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); | ||
if (IS_ERR(key)) | ||
return PTR_ERR(key); | ||
|
||
memset(&pks, 0, sizeof(pks)); | ||
|
||
pks.pkey_hash_algo = hdr->hash_algo; | ||
pks.digest = (u8 *)data; | ||
pks.digest_size = datalen; | ||
pks.nr_mpi = 1; | ||
pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); | ||
|
||
if (pks.rsa.s) | ||
ret = verify_signature(key, &pks); | ||
|
||
mpi_free(pks.rsa.s); | ||
key_put(key); | ||
pr_debug("%s() = %d\n", __func__, ret); | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters