You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"In this patchset, we finally get an SELinux update, with Paul Moore
taking over as maintainer of that code.
Also a significant update for the Keys subsystem, as well as
maintenance updates to Smack, IMA, TPM, and Apparmor"
and since I wanted to know more about the updates to key handling,
here's the explanation from David Howells on that:
"Okay. There are a number of separate bits. I'll go over the big bits
and the odd important other bit, most of the smaller bits are just
fixes and cleanups. If you want the small bits accounting for, I can
do that too.
(1) Keyring capacity expansion.
KEYS: Consolidate the concept of an 'index key' for key access
KEYS: Introduce a search context structure
KEYS: Search for auth-key by name rather than target key ID
Add a generic associative array implementation.
KEYS: Expand the capacity of a keyring
Several of the patches are providing an expansion of the capacity of a
keyring. Currently, the maximum size of a keyring payload is one page.
Subtract a small header and then divide up into pointers, that only gives
you ~500 pointers on an x86_64 box. However, since the NFS idmapper uses
a keyring to store ID mapping data, that has proven to be insufficient to
the cause.
Whatever data structure I use to handle the keyring payload, it can only
store pointers to keys, not the keys themselves because several keyrings
may point to a single key. This precludes inserting, say, and rb_node
struct into the key struct for this purpose.
I could make an rbtree of records such that each record has an rb_node
and a key pointer, but that would use four words of space per key stored
in the keyring. It would, however, be able to use much existing code.
I selected instead a non-rebalancing radix-tree type approach as that
could have a better space-used/key-pointer ratio. I could have used the
radix tree implementation that we already have and insert keys into it by
their serial numbers, but that means any sort of search must iterate over
the whole radix tree. Further, its nodes are a bit on the capacious side
for what I want - especially given that key serial numbers are randomly
allocated, thus leaving a lot of empty space in the tree.
So what I have is an associative array that internally is a radix-tree
with 16 pointers per node where the index key is constructed from the key
type pointer and the key description. This means that an exact lookup by
type+description is very fast as this tells us how to navigate directly to
the target key.
I made the data structure general in lib/assoc_array.c as far as it is
concerned, its index key is just a sequence of bits that leads to a
pointer. It's possible that someone else will be able to make use of it
also. FS-Cache might, for example.
(2) Mark keys as 'trusted' and keyrings as 'trusted only'.
KEYS: verify a certificate is signed by a 'trusted' key
KEYS: Make the system 'trusted' keyring viewable by userspace
KEYS: Add a 'trusted' flag and a 'trusted only' flag
KEYS: Separate the kernel signature checking keyring from module signing
These patches allow keys carrying asymmetric public keys to be marked as
being 'trusted' and allow keyrings to be marked as only permitting the
addition or linkage of trusted keys.
Keys loaded from hardware during kernel boot or compiled into the kernel
during build are marked as being trusted automatically. New keys can be
loaded at runtime with add_key(). They are checked against the system
keyring contents and if their signatures can be validated with keys that
are already marked trusted, then they are marked trusted also and can
thus be added into the master keyring.
Patches from Mimi Zohar make this usable with the IMA keyrings also.
(3) Remove the date checks on the key used to validate a module signature.
X.509: Remove certificate date checks
It's not reasonable to reject a signature just because the key that it was
generated with is no longer valid datewise - especially if the kernel
hasn't yet managed to set the system clock when the first module is
loaded - so just remove those checks.
(4) Make it simpler to deal with additional X.509 being loaded into the kernel.
KEYS: Load *.x509 files into kernel keyring
KEYS: Have make canonicalise the paths of the X.509 certs better to deduplicate
The builder of the kernel now just places files with the extension ".x509"
into the kernel source or build trees and they're concatenated by the
kernel build and stuffed into the appropriate section.
(5) Add support for userspace kerberos to use keyrings.
KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches
KEYS: Implement a big key type that can save to tmpfs
Fedora went to, by default, storing kerberos tickets and tokens in tmpfs.
We looked at storing it in keyrings instead as that confers certain
advantages such as tickets being automatically deleted after a certain
amount of time and the ability for the kernel to get at these tokens more
easily.
To make this work, two things were needed:
(a) A way for the tickets to persist beyond the lifetime of all a user's
sessions so that cron-driven processes can still use them.
The problem is that a user's session keyrings are deleted when the
session that spawned them logs out and the user's user keyring is
deleted when the UID is deleted (typically when the last log out
happens), so neither of these places is suitable.
I've added a system keyring into which a 'persistent' keyring is
created for each UID on request. Each time a user requests their
persistent keyring, the expiry time on it is set anew. If the user
doesn't ask for it for, say, three days, the keyring is automatically
expired and garbage collected using the existing gc. All the kerberos
tokens it held are then also gc'd.
(b) A key type that can hold really big tickets (up to 1MB in size).
The problem is that Active Directory can return huge tickets with lots
of auxiliary data attached. We don't, however, want to eat up huge
tracts of unswappable kernel space for this, so if the ticket is
greater than a certain size, we create a swappable shmem file and dump
the contents in there and just live with the fact we then have an
inode and a dentry overhead. If the ticket is smaller than that, we
slap it in a kmalloc()'d buffer"
* 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (121 commits)
KEYS: Fix keyring content gc scanner
KEYS: Fix error handling in big_key instantiation
KEYS: Fix UID check in keyctl_get_persistent()
KEYS: The RSA public key algorithm needs to select MPILIB
ima: define '_ima' as a builtin 'trusted' keyring
ima: extend the measurement list to include the file signature
kernel/system_certificate.S: use real contents instead of macro GLOBAL()
KEYS: fix error return code in big_key_instantiate()
KEYS: Fix keyring quota misaccounting on key replacement and unlink
KEYS: Fix a race between negating a key and reading the error set
KEYS: Make BIG_KEYS boolean
apparmor: remove the "task" arg from may_change_ptraced_domain()
apparmor: remove parent task info from audit logging
apparmor: remove tsk field from the apparmor_audit_struct
apparmor: fix capability to not use the current task, during reporting
Smack: Ptrace access check mode
ima: provide hash algo info in the xattr
ima: enable support for larger default filedata hash algorithms
ima: define kernel parameter 'ima_template=' to change configured default
ima: add Kconfig default measurement list template
...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ adi,adt7461 +/-1C TDM Extended Temp Range I.C
|
||||
adt7461 +/-1C TDM Extended Temp Range I.C
|
||||
at,24c08 i2c serial eeprom (24cxx)
|
||||
atmel,24c02 i2c serial eeprom (24cxx)
|
||||
atmel,at97sc3204t i2c trusted platform module (TPM)
|
||||
catalyst,24c32 i2c serial eeprom
|
||||
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
|
||||
dallas,ds1338 I2C RTC with 56-Byte NV RAM
|
||||
@@ -44,6 +45,7 @@ mc,rv3029c2 Real Time Clock Module with I2C-Bus
|
||||
national,lm75 I2C TEMP SENSOR
|
||||
national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
|
||||
national,lm92 ±0.33°C Accurate, 12-Bit + Sign Temperature Sensor and Thermal Window Comparator with Two-Wire Interface
|
||||
nuvoton,npct501 i2c trusted platform module (TPM)
|
||||
nxp,pca9556 Octal SMBus and I2C registered interface
|
||||
nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset
|
||||
nxp,pcf8563 Real-time clock/calendar
|
||||
@@ -61,3 +63,4 @@ taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface
|
||||
ti,tsc2003 I2C Touch-Screen Controller
|
||||
ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
ti,tmp275 Digital Temperature Sensor
|
||||
winbond,wpct301 i2c trusted platform module (TPM)
|
||||
|
||||
@@ -1190,15 +1190,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
owned by uid=0.
|
||||
|
||||
ima_hash= [IMA]
|
||||
Format: { "sha1" | "md5" }
|
||||
Format: { md5 | sha1 | rmd160 | sha256 | sha384
|
||||
| sha512 | ... }
|
||||
default: "sha1"
|
||||
|
||||
The list of supported hash algorithms is defined
|
||||
in crypto/hash_info.h.
|
||||
|
||||
ima_tcb [IMA]
|
||||
Load a policy which meets the needs of the Trusted
|
||||
Computing Base. This means IMA will measure all
|
||||
programs exec'd, files mmap'd for exec, and all files
|
||||
opened for read by uid=0.
|
||||
|
||||
ima_template= [IMA]
|
||||
Select one of defined IMA measurements template formats.
|
||||
Formats: { "ima" | "ima-ng" }
|
||||
Default: "ima-ng"
|
||||
|
||||
init= [KNL]
|
||||
Format: <full_path>
|
||||
Run specified binary instead of /sbin/init as init
|
||||
|
||||
@@ -22,3 +22,5 @@ keys.txt
|
||||
- description of the kernel key retention service.
|
||||
tomoyo.txt
|
||||
- documentation on the TOMOYO Linux Security Module.
|
||||
IMA-templates.txt
|
||||
- documentation on the template management mechanism for IMA.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
IMA Template Management Mechanism
|
||||
|
||||
|
||||
==== INTRODUCTION ====
|
||||
|
||||
The original 'ima' template is fixed length, containing the filedata hash
|
||||
and pathname. The filedata hash is limited to 20 bytes (md5/sha1).
|
||||
The pathname is a null terminated string, limited to 255 characters.
|
||||
To overcome these limitations and to add additional file metadata, it is
|
||||
necessary to extend the current version of IMA by defining additional
|
||||
templates. For example, information that could be possibly reported are
|
||||
the inode UID/GID or the LSM labels either of the inode and of the process
|
||||
that is accessing it.
|
||||
|
||||
However, the main problem to introduce this feature is that, each time
|
||||
a new template is defined, the functions that generate and display
|
||||
the measurements list would include the code for handling a new format
|
||||
and, thus, would significantly grow over the time.
|
||||
|
||||
The proposed solution solves this problem by separating the template
|
||||
management from the remaining IMA code. The core of this solution is the
|
||||
definition of two new data structures: a template descriptor, to determine
|
||||
which information should be included in the measurement list; a template
|
||||
field, to generate and display data of a given type.
|
||||
|
||||
Managing templates with these structures is very simple. To support
|
||||
a new data type, developers define the field identifier and implement
|
||||
two functions, init() and show(), respectively to generate and display
|
||||
measurement entries. Defining a new template descriptor requires
|
||||
specifying the template format, a string of field identifiers separated
|
||||
by the '|' character. While in the current implementation it is possible
|
||||
to define new template descriptors only by adding their definition in the
|
||||
template specific code (ima_template.c), in a future version it will be
|
||||
possible to register a new template on a running kernel by supplying to IMA
|
||||
the desired format string. In this version, IMA initializes at boot time
|
||||
all defined template descriptors by translating the format into an array
|
||||
of template fields structures taken from the set of the supported ones.
|
||||
|
||||
After the initialization step, IMA will call ima_alloc_init_template()
|
||||
(new function defined within the patches for the new template management
|
||||
mechanism) to generate a new measurement entry by using the template
|
||||
descriptor chosen through the kernel configuration or through the newly
|
||||
introduced 'ima_template=' kernel command line parameter. It is during this
|
||||
phase that the advantages of the new architecture are clearly shown:
|
||||
the latter function will not contain specific code to handle a given template
|
||||
but, instead, it simply calls the init() method of the template fields
|
||||
associated to the chosen template descriptor and store the result (pointer
|
||||
to allocated data and data length) in the measurement entry structure.
|
||||
|
||||
The same mechanism is employed to display measurements entries.
|
||||
The functions ima[_ascii]_measurements_show() retrieve, for each entry,
|
||||
the template descriptor used to produce that entry and call the show()
|
||||
method for each item of the array of template fields structures.
|
||||
|
||||
|
||||
|
||||
==== SUPPORTED TEMPLATE FIELDS AND DESCRIPTORS ====
|
||||
|
||||
In the following, there is the list of supported template fields
|
||||
('<identifier>': description), that can be used to define new template
|
||||
descriptors by adding their identifier to the format string
|
||||
(support for more data types will be added later):
|
||||
|
||||
- 'd': the digest of the event (i.e. the digest of a measured file),
|
||||
calculated with the SHA1 or MD5 hash algorithm;
|
||||
- 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
|
||||
- 'd-ng': the digest of the event, calculated with an arbitrary hash
|
||||
algorithm (field format: [<hash algo>:]digest, where the digest
|
||||
prefix is shown only if the hash algorithm is not SHA1 or MD5);
|
||||
- 'n-ng': the name of the event, without size limitations.
|
||||
|
||||
|
||||
Below, there is the list of defined template descriptors:
|
||||
- "ima": its format is 'd|n';
|
||||
- "ima-ng" (default): its format is 'd-ng|n-ng'.
|
||||
|
||||
|
||||
|
||||
==== USE ====
|
||||
|
||||
To specify the template descriptor to be used to generate measurement entries,
|
||||
currently the following methods are supported:
|
||||
|
||||
- select a template descriptor among those supported in the kernel
|
||||
configuration ('ima-ng' is the default choice);
|
||||
- specify a template descriptor name from the kernel command line through
|
||||
the 'ima_template=' parameter.
|
||||
@@ -865,15 +865,14 @@ encountered:
|
||||
calling processes has a searchable link to the key from one of its
|
||||
keyrings. There are three functions for dealing with these:
|
||||
|
||||
key_ref_t make_key_ref(const struct key *key,
|
||||
unsigned long possession);
|
||||
key_ref_t make_key_ref(const struct key *key, bool possession);
|
||||
|
||||
struct key *key_ref_to_ptr(const key_ref_t key_ref);
|
||||
|
||||
unsigned long is_key_possessed(const key_ref_t key_ref);
|
||||
bool is_key_possessed(const key_ref_t key_ref);
|
||||
|
||||
The first function constructs a key reference from a key pointer and
|
||||
possession information (which must be 0 or 1 and not any other value).
|
||||
possession information (which must be true or false).
|
||||
|
||||
The second function retrieves the key pointer from a reference and the
|
||||
third retrieves the possession flag.
|
||||
@@ -961,14 +960,17 @@ payload contents" for more information.
|
||||
the argument will not be parsed.
|
||||
|
||||
|
||||
(*) Extra references can be made to a key by calling the following function:
|
||||
(*) Extra references can be made to a key by calling one of the following
|
||||
functions:
|
||||
|
||||
struct key *__key_get(struct key *key);
|
||||
struct key *key_get(struct key *key);
|
||||
|
||||
These need to be disposed of by calling key_put() when they've been
|
||||
finished with. The key pointer passed in will be returned. If the pointer
|
||||
is NULL or CONFIG_KEYS is not set then the key will not be dereferenced and
|
||||
no increment will take place.
|
||||
Keys so references will need to be disposed of by calling key_put() when
|
||||
they've been finished with. The key pointer passed in will be returned.
|
||||
|
||||
In the case of key_get(), if the pointer is NULL or CONFIG_KEYS is not set
|
||||
then the key will not be dereferenced and no increment will take place.
|
||||
|
||||
|
||||
(*) A key's serial number can be obtained by calling:
|
||||
|
||||
+3
-1
@@ -7515,9 +7515,10 @@ SELINUX SECURITY MODULE
|
||||
M: Stephen Smalley <sds@tycho.nsa.gov>
|
||||
M: James Morris <james.l.morris@oracle.com>
|
||||
M: Eric Paris <eparis@parisplace.org>
|
||||
M: Paul Moore <paul@paul-moore.com>
|
||||
L: selinux@tycho.nsa.gov (subscribers-only, general discussion)
|
||||
W: http://selinuxproject.org
|
||||
T: git git://git.infradead.org/users/eparis/selinux.git
|
||||
T: git git://git.infradead.org/users/pcmoore/selinux
|
||||
S: Supported
|
||||
F: include/linux/selinux*
|
||||
F: security/selinux/
|
||||
@@ -8664,6 +8665,7 @@ F: drivers/media/usb/tm6000/
|
||||
TPM DEVICE DRIVER
|
||||
M: Leonidas Da Silva Barbosa <leosilva@linux.vnet.ibm.com>
|
||||
M: Ashley Lai <ashley@ashleylai.com>
|
||||
M: Peter Huewe <peterhuewe@gmx.de>
|
||||
M: Rajiv Andrade <mail@srajiv.net>
|
||||
W: http://tpmdd.sourceforge.net
|
||||
M: Marcel Selhorst <tpmdd@selhorst.net>
|
||||
|
||||
@@ -1402,6 +1402,9 @@ config CRYPTO_USER_API_SKCIPHER
|
||||
This option enables the user-spaces interface for symmetric
|
||||
key cipher algorithms.
|
||||
|
||||
config CRYPTO_HASH_INFO
|
||||
bool
|
||||
|
||||
source "drivers/crypto/Kconfig"
|
||||
source crypto/asymmetric_keys/Kconfig
|
||||
|
||||
|
||||
@@ -104,3 +104,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
|
||||
obj-$(CONFIG_XOR_BLOCKS) += xor.o
|
||||
obj-$(CONFIG_ASYNC_CORE) += async_tx/
|
||||
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
|
||||
obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
|
||||
|
||||
@@ -12,6 +12,8 @@ if ASYMMETRIC_KEY_TYPE
|
||||
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
tristate "Asymmetric public-key crypto algorithm subtype"
|
||||
select MPILIB
|
||||
select PUBLIC_KEY_ALGO_RSA
|
||||
select CRYPTO_HASH_INFO
|
||||
help
|
||||
This option provides support for asymmetric public key type handling.
|
||||
If signature generation and/or verification are to be used,
|
||||
@@ -20,8 +22,8 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
|
||||
config PUBLIC_KEY_ALGO_RSA
|
||||
tristate "RSA public-key algorithm"
|
||||
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
select MPILIB_EXTRA
|
||||
select MPILIB
|
||||
help
|
||||
This option enables support for the RSA algorithm (PKCS#1, RFC3447).
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ struct key_type key_type_asymmetric = {
|
||||
.match = asymmetric_key_match,
|
||||
.destroy = asymmetric_key_destroy,
|
||||
.describe = asymmetric_key_describe,
|
||||
.def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(key_type_asymmetric);
|
||||
|
||||
|
||||
@@ -22,29 +22,25 @@
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
const char *const pkey_algo[PKEY_ALGO__LAST] = {
|
||||
const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
|
||||
[PKEY_ALGO_DSA] = "DSA",
|
||||
[PKEY_ALGO_RSA] = "RSA",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pkey_algo_name);
|
||||
|
||||
const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
|
||||
#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
|
||||
defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
|
||||
[PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pkey_algo);
|
||||
|
||||
const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
|
||||
[PKEY_HASH_MD4] = "md4",
|
||||
[PKEY_HASH_MD5] = "md5",
|
||||
[PKEY_HASH_SHA1] = "sha1",
|
||||
[PKEY_HASH_RIPE_MD_160] = "rmd160",
|
||||
[PKEY_HASH_SHA256] = "sha256",
|
||||
[PKEY_HASH_SHA384] = "sha384",
|
||||
[PKEY_HASH_SHA512] = "sha512",
|
||||
[PKEY_HASH_SHA224] = "sha224",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pkey_hash_algo);
|
||||
|
||||
const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = {
|
||||
const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
|
||||
[PKEY_ID_PGP] = "PGP",
|
||||
[PKEY_ID_X509] = "X509",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pkey_id_type);
|
||||
EXPORT_SYMBOL_GPL(pkey_id_type_name);
|
||||
|
||||
/*
|
||||
* Provide a part of a description of the key for /proc/keys.
|
||||
@@ -56,7 +52,7 @@ static void public_key_describe(const struct key *asymmetric_key,
|
||||
|
||||
if (key)
|
||||
seq_printf(m, "%s.%s",
|
||||
pkey_id_type[key->id_type], key->algo->name);
|
||||
pkey_id_type_name[key->id_type], key->algo->name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -78,21 +74,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy);
|
||||
/*
|
||||
* Verify a signature using a public key.
|
||||
*/
|
||||
static int public_key_verify_signature(const struct key *key,
|
||||
const struct public_key_signature *sig)
|
||||
int public_key_verify_signature(const struct public_key *pk,
|
||||
const struct public_key_signature *sig)
|
||||
{
|
||||
const struct public_key *pk = key->payload.data;
|
||||
const struct public_key_algorithm *algo;
|
||||
|
||||
if (!pk->algo->verify_signature)
|
||||
BUG_ON(!pk);
|
||||
BUG_ON(!pk->mpi[0]);
|
||||
BUG_ON(!pk->mpi[1]);
|
||||
BUG_ON(!sig);
|
||||
BUG_ON(!sig->digest);
|
||||
BUG_ON(!sig->mpi[0]);
|
||||
|
||||
algo = pk->algo;
|
||||
if (!algo) {
|
||||
if (pk->pkey_algo >= PKEY_ALGO__LAST)
|
||||
return -ENOPKG;
|
||||
algo = pkey_algo[pk->pkey_algo];
|
||||
if (!algo)
|
||||
return -ENOPKG;
|
||||
}
|
||||
|
||||
if (!algo->verify_signature)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (sig->nr_mpi != pk->algo->n_sig_mpi) {
|
||||
if (sig->nr_mpi != algo->n_sig_mpi) {
|
||||
pr_debug("Signature has %u MPI not %u\n",
|
||||
sig->nr_mpi, pk->algo->n_sig_mpi);
|
||||
sig->nr_mpi, algo->n_sig_mpi);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return pk->algo->verify_signature(pk, sig);
|
||||
return algo->verify_signature(pk, sig);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(public_key_verify_signature);
|
||||
|
||||
static int public_key_verify_signature_2(const struct key *key,
|
||||
const struct public_key_signature *sig)
|
||||
{
|
||||
const struct public_key *pk = key->payload.data;
|
||||
return public_key_verify_signature(pk, sig);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,6 +123,6 @@ struct asymmetric_key_subtype public_key_subtype = {
|
||||
.name = "public_key",
|
||||
.describe = public_key_describe,
|
||||
.destroy = public_key_destroy,
|
||||
.verify_signature = public_key_verify_signature,
|
||||
.verify_signature = public_key_verify_signature_2,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(public_key_subtype);
|
||||
|
||||
@@ -28,3 +28,9 @@ struct public_key_algorithm {
|
||||
};
|
||||
|
||||
extern const struct public_key_algorithm RSA_public_key_algorithm;
|
||||
|
||||
/*
|
||||
* public_key.c
|
||||
*/
|
||||
extern int public_key_verify_signature(const struct public_key *pk,
|
||||
const struct public_key_signature *sig);
|
||||
|
||||
@@ -73,13 +73,13 @@ static const struct {
|
||||
size_t size;
|
||||
} RSA_ASN1_templates[PKEY_HASH__LAST] = {
|
||||
#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
|
||||
[PKEY_HASH_MD5] = _(MD5),
|
||||
[PKEY_HASH_SHA1] = _(SHA1),
|
||||
[PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160),
|
||||
[PKEY_HASH_SHA256] = _(SHA256),
|
||||
[PKEY_HASH_SHA384] = _(SHA384),
|
||||
[PKEY_HASH_SHA512] = _(SHA512),
|
||||
[PKEY_HASH_SHA224] = _(SHA224),
|
||||
[HASH_ALGO_MD5] = _(MD5),
|
||||
[HASH_ALGO_SHA1] = _(SHA1),
|
||||
[HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160),
|
||||
[HASH_ALGO_SHA256] = _(SHA256),
|
||||
[HASH_ALGO_SHA384] = _(SHA384),
|
||||
[HASH_ALGO_SHA512] = _(SHA512),
|
||||
[HASH_ALGO_SHA224] = _(SHA224),
|
||||
#undef _
|
||||
};
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert)
|
||||
kfree(cert->subject);
|
||||
kfree(cert->fingerprint);
|
||||
kfree(cert->authority);
|
||||
kfree(cert->sig.digest);
|
||||
mpi_free(cert->sig.rsa.s);
|
||||
kfree(cert);
|
||||
}
|
||||
}
|
||||
@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
|
||||
return -ENOPKG; /* Unsupported combination */
|
||||
|
||||
case OID_md4WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_MD5;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
|
||||
case OID_sha1WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_SHA1;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
|
||||
case OID_sha256WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_SHA256;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
|
||||
case OID_sha384WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_SHA384;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
|
||||
case OID_sha512WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_SHA512;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
|
||||
case OID_sha224WithRSAEncryption:
|
||||
ctx->cert->sig_hash_algo = PKEY_HASH_SHA224;
|
||||
ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->cert->sig = value;
|
||||
ctx->cert->sig_size = vlen;
|
||||
ctx->cert->raw_sig = value;
|
||||
ctx->cert->raw_sig_size = vlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -343,8 +345,9 @@ int x509_extract_key_data(void *context, size_t hdrlen,
|
||||
if (ctx->last_oid != OID_rsaEncryption)
|
||||
return -ENOPKG;
|
||||
|
||||
/* There seems to be an extraneous 0 byte on the front of the data */
|
||||
ctx->cert->pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
|
||||
|
||||
/* Discard the BIT STRING metadata */
|
||||
ctx->key = value + 1;
|
||||
ctx->key_size = vlen - 1;
|
||||
return 0;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* 2 of the Licence, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <crypto/public_key.h>
|
||||
|
||||
struct x509_certificate {
|
||||
@@ -20,13 +21,11 @@ struct x509_certificate {
|
||||
char *authority; /* Authority key fingerprint as hex */
|
||||
struct tm valid_from;
|
||||
struct tm valid_to;
|
||||
enum pkey_algo pkey_algo : 8; /* Public key algorithm */
|
||||
enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */
|
||||
enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */
|
||||
const void *tbs; /* Signed data */
|
||||
size_t tbs_size; /* Size of signed data */
|
||||
const void *sig; /* Signature data */
|
||||
size_t sig_size; /* Size of sigature */
|
||||
unsigned tbs_size; /* Size of signed data */
|
||||
unsigned raw_sig_size; /* Size of sigature */
|
||||
const void *raw_sig; /* Signature data */
|
||||
struct public_key_signature sig; /* Signature parameters */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -34,3 +33,10 @@ struct x509_certificate {
|
||||
*/
|
||||
extern void x509_free_certificate(struct x509_certificate *cert);
|
||||
extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
|
||||
|
||||
/*
|
||||
* x509_public_key.c
|
||||
*/
|
||||
extern int x509_get_sig_params(struct x509_certificate *cert);
|
||||
extern int x509_check_signature(const struct public_key *pub,
|
||||
struct x509_certificate *cert);
|
||||
|
||||
@@ -18,87 +18,164 @@
|
||||
#include <linux/asn1_decoder.h>
|
||||
#include <keys/asymmetric-subtype.h>
|
||||
#include <keys/asymmetric-parser.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "asymmetric_keys.h"
|
||||
#include "public_key.h"
|
||||
#include "x509_parser.h"
|
||||
|
||||
static const
|
||||
struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = {
|
||||
[PKEY_ALGO_DSA] = NULL,
|
||||
#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
|
||||
defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
|
||||
[PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
* Find a key in the given keyring by issuer and authority.
|
||||
*/
|
||||
static struct key *x509_request_asymmetric_key(
|
||||
struct key *keyring,
|
||||
const char *signer, size_t signer_len,
|
||||
const char *authority, size_t auth_len)
|
||||
{
|
||||
key_ref_t key;
|
||||
char *id;
|
||||
|
||||
/* Construct an identifier. */
|
||||
id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
|
||||
if (!id)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(id, signer, signer_len);
|
||||
id[signer_len + 0] = ':';
|
||||
id[signer_len + 1] = ' ';
|
||||
memcpy(id + signer_len + 2, authority, auth_len);
|
||||
id[signer_len + 2 + auth_len] = 0;
|
||||
|
||||
pr_debug("Look up: \"%s\"\n", id);
|
||||
|
||||
key = keyring_search(make_key_ref(keyring, 1),
|
||||
&key_type_asymmetric, id);
|
||||
if (IS_ERR(key))
|
||||
pr_debug("Request for module key '%s' err %ld\n",
|
||||
id, PTR_ERR(key));
|
||||
kfree(id);
|
||||
|
||||
if (IS_ERR(key)) {
|
||||
switch (PTR_ERR(key)) {
|
||||
/* Hide some search errors */
|
||||
case -EACCES:
|
||||
case -ENOTDIR:
|
||||
case -EAGAIN:
|
||||
return ERR_PTR(-ENOKEY);
|
||||
default:
|
||||
return ERR_CAST(key);
|
||||
}
|
||||
}
|
||||
|
||||
pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
|
||||
return key_ref_to_ptr(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the signature on a certificate using the provided public key
|
||||
* Set up the signature parameters in an X.509 certificate. This involves
|
||||
* digesting the signed data and extracting the signature.
|
||||
*/
|
||||
static int x509_check_signature(const struct public_key *pub,
|
||||
const struct x509_certificate *cert)
|
||||
int x509_get_sig_params(struct x509_certificate *cert)
|
||||
{
|
||||
struct public_key_signature *sig;
|
||||
struct crypto_shash *tfm;
|
||||
struct shash_desc *desc;
|
||||
size_t digest_size, desc_size;
|
||||
void *digest;
|
||||
int ret;
|
||||
|
||||
pr_devel("==>%s()\n", __func__);
|
||||
|
||||
|
||||
if (cert->sig.rsa.s)
|
||||
return 0;
|
||||
|
||||
cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
|
||||
if (!cert->sig.rsa.s)
|
||||
return -ENOMEM;
|
||||
cert->sig.nr_mpi = 1;
|
||||
|
||||
/* Allocate the hashing algorithm we're going to need and find out how
|
||||
* big the hash operational data will be.
|
||||
*/
|
||||
tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0);
|
||||
tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
|
||||
if (IS_ERR(tfm))
|
||||
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
|
||||
|
||||
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
|
||||
digest_size = crypto_shash_digestsize(tfm);
|
||||
|
||||
/* We allocate the hash operational data storage on the end of our
|
||||
* context data.
|
||||
/* We allocate the hash operational data storage on the end of the
|
||||
* digest storage space.
|
||||
*/
|
||||
ret = -ENOMEM;
|
||||
sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL);
|
||||
if (!sig)
|
||||
goto error_no_sig;
|
||||
digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
|
||||
if (!digest)
|
||||
goto error;
|
||||
|
||||
sig->pkey_hash_algo = cert->sig_hash_algo;
|
||||
sig->digest = (u8 *)sig + sizeof(*sig) + desc_size;
|
||||
sig->digest_size = digest_size;
|
||||
cert->sig.digest = digest;
|
||||
cert->sig.digest_size = digest_size;
|
||||
|
||||
desc = (void *)sig + sizeof(*sig);
|
||||
desc->tfm = tfm;
|
||||
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
desc = digest + digest_size;
|
||||
desc->tfm = tfm;
|
||||
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
ret = crypto_shash_init(desc);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = -ENOMEM;
|
||||
sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size);
|
||||
if (!sig->rsa.s)
|
||||
goto error;
|
||||
|
||||
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
|
||||
if (ret < 0)
|
||||
goto error_mpi;
|
||||
|
||||
ret = pub->algo->verify_signature(pub, sig);
|
||||
|
||||
pr_debug("Cert Verification: %d\n", ret);
|
||||
|
||||
error_mpi:
|
||||
mpi_free(sig->rsa.s);
|
||||
might_sleep();
|
||||
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
|
||||
error:
|
||||
kfree(sig);
|
||||
error_no_sig:
|
||||
crypto_free_shash(tfm);
|
||||
|
||||
pr_devel("<==%s() = %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x509_get_sig_params);
|
||||
|
||||
/*
|
||||
* Check the signature on a certificate using the provided public key
|
||||
*/
|
||||
int x509_check_signature(const struct public_key *pub,
|
||||
struct x509_certificate *cert)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pr_devel("==>%s()\n", __func__);
|
||||
|
||||
ret = x509_get_sig_params(cert);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = public_key_verify_signature(pub, &cert->sig);
|
||||
pr_debug("Cert Verification: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x509_check_signature);
|
||||
|
||||
/*
|
||||
* Check the new certificate against the ones in the trust keyring. If one of
|
||||
* those is the signing key and validates the new certificate, then mark the
|
||||
* new certificate as being trusted.
|
||||
*
|
||||
* Return 0 if the new certificate was successfully validated, 1 if we couldn't
|
||||
* find a matching parent certificate in the trusted list and an error if there
|
||||
* is a matching certificate but the signature check fails.
|
||||
*/
|
||||
static int x509_validate_trust(struct x509_certificate *cert,
|
||||
struct key *trust_keyring)
|
||||
{
|
||||
const struct public_key *pk;
|
||||
struct key *key;
|
||||
int ret = 1;
|
||||
|
||||
key = x509_request_asymmetric_key(trust_keyring,
|
||||
cert->issuer, strlen(cert->issuer),
|
||||
cert->authority,
|
||||
strlen(cert->authority));
|
||||
if (!IS_ERR(key)) {
|
||||
pk = key->payload.data;
|
||||
ret = x509_check_signature(pk, cert);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse a data blob for a key as an X509 certificate.
|
||||
@@ -106,7 +183,6 @@ error_no_sig:
|
||||
static int x509_key_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct x509_certificate *cert;
|
||||
struct tm now;
|
||||
size_t srlen, sulen;
|
||||
char *desc = NULL;
|
||||
int ret;
|
||||
@@ -117,7 +193,18 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
|
||||
|
||||
pr_devel("Cert Issuer: %s\n", cert->issuer);
|
||||
pr_devel("Cert Subject: %s\n", cert->subject);
|
||||
pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]);
|
||||
|
||||
if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
|
||||
cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
|
||||
cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
|
||||
!pkey_algo[cert->pub->pkey_algo] ||
|
||||
!pkey_algo[cert->sig.pkey_algo] ||
|
||||
!hash_algo_name[cert->sig.pkey_hash_algo]) {
|
||||
ret = -ENOPKG;
|
||||
goto error_free_cert;
|
||||
}
|
||||
|
||||
pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
|
||||
pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
|
||||
cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
|
||||
cert->valid_from.tm_mday, cert->valid_from.tm_hour,
|
||||
@@ -127,61 +214,29 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
|
||||
cert->valid_to.tm_mday, cert->valid_to.tm_hour,
|
||||
cert->valid_to.tm_min, cert->valid_to.tm_sec);
|
||||
pr_devel("Cert Signature: %s + %s\n",
|
||||
pkey_algo[cert->sig_pkey_algo],
|
||||
pkey_hash_algo[cert->sig_hash_algo]);
|
||||
pkey_algo_name[cert->sig.pkey_algo],
|
||||
hash_algo_name[cert->sig.pkey_hash_algo]);
|
||||
|
||||
if (!cert->fingerprint || !cert->authority) {
|
||||
pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
|
||||
if (!cert->fingerprint) {
|
||||
pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
|
||||
cert->subject);
|
||||
ret = -EKEYREJECTED;
|
||||
goto error_free_cert;
|
||||
}
|
||||
|
||||
time_to_tm(CURRENT_TIME.tv_sec, 0, &now);
|
||||
pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n",
|
||||
now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
|
||||
now.tm_hour, now.tm_min, now.tm_sec);
|
||||
if (now.tm_year < cert->valid_from.tm_year ||
|
||||
(now.tm_year == cert->valid_from.tm_year &&
|
||||
(now.tm_mon < cert->valid_from.tm_mon ||
|
||||
(now.tm_mon == cert->valid_from.tm_mon &&
|
||||
(now.tm_mday < cert->valid_from.tm_mday ||
|
||||
(now.tm_mday == cert->valid_from.tm_mday &&
|
||||
(now.tm_hour < cert->valid_from.tm_hour ||
|
||||
(now.tm_hour == cert->valid_from.tm_hour &&
|
||||
(now.tm_min < cert->valid_from.tm_min ||
|
||||
(now.tm_min == cert->valid_from.tm_min &&
|
||||
(now.tm_sec < cert->valid_from.tm_sec
|
||||
))))))))))) {
|
||||
pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
|
||||
ret = -EKEYREJECTED;
|
||||
goto error_free_cert;
|
||||
}
|
||||
if (now.tm_year > cert->valid_to.tm_year ||
|
||||
(now.tm_year == cert->valid_to.tm_year &&
|
||||
(now.tm_mon > cert->valid_to.tm_mon ||
|
||||
(now.tm_mon == cert->valid_to.tm_mon &&
|
||||
(now.tm_mday > cert->valid_to.tm_mday ||
|
||||
(now.tm_mday == cert->valid_to.tm_mday &&
|
||||
(now.tm_hour > cert->valid_to.tm_hour ||
|
||||
(now.tm_hour == cert->valid_to.tm_hour &&
|
||||
(now.tm_min > cert->valid_to.tm_min ||
|
||||
(now.tm_min == cert->valid_to.tm_min &&
|
||||
(now.tm_sec > cert->valid_to.tm_sec
|
||||
))))))))))) {
|
||||
pr_warn("Cert %s has expired\n", cert->fingerprint);
|
||||
ret = -EKEYEXPIRED;
|
||||
goto error_free_cert;
|
||||
}
|
||||
|
||||
cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
|
||||
cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
|
||||
cert->pub->id_type = PKEY_ID_X509;
|
||||
|
||||
/* Check the signature on the key */
|
||||
if (strcmp(cert->fingerprint, cert->authority) == 0) {
|
||||
ret = x509_check_signature(cert->pub, cert);
|
||||
/* Check the signature on the key if it appears to be self-signed */
|
||||
if (!cert->authority ||
|
||||
strcmp(cert->fingerprint, cert->authority) == 0) {
|
||||
ret = x509_check_signature(cert->pub, cert); /* self-signed */
|
||||
if (ret < 0)
|
||||
goto error_free_cert;
|
||||
} else {
|
||||
ret = x509_validate_trust(cert, system_trusted_keyring);
|
||||
if (!ret)
|
||||
prep->trusted = 1;
|
||||
}
|
||||
|
||||
/* Propose a description */
|
||||
@@ -237,3 +292,6 @@ static void __exit x509_key_exit(void)
|
||||
|
||||
module_init(x509_key_init);
|
||||
module_exit(x509_key_exit);
|
||||
|
||||
MODULE_DESCRIPTION("X.509 certificate parser");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Hash Info: Hash algorithms information
|
||||
*
|
||||
* Copyright (c) 2013 Dmitry Kasatkin <d.kasatkin@samsung.com>
|
||||
*
|
||||
* 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; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
const char *const hash_algo_name[HASH_ALGO__LAST] = {
|
||||
[HASH_ALGO_MD4] = "md4",
|
||||
[HASH_ALGO_MD5] = "md5",
|
||||
[HASH_ALGO_SHA1] = "sha1",
|
||||
[HASH_ALGO_RIPE_MD_160] = "rmd160",
|
||||
[HASH_ALGO_SHA256] = "sha256",
|
||||
[HASH_ALGO_SHA384] = "sha384",
|
||||
[HASH_ALGO_SHA512] = "sha512",
|
||||
[HASH_ALGO_SHA224] = "sha224",
|
||||
[HASH_ALGO_RIPE_MD_128] = "rmd128",
|
||||
[HASH_ALGO_RIPE_MD_256] = "rmd256",
|
||||
[HASH_ALGO_RIPE_MD_320] = "rmd320",
|
||||
[HASH_ALGO_WP_256] = "wp256",
|
||||
[HASH_ALGO_WP_384] = "wp384",
|
||||
[HASH_ALGO_WP_512] = "wp512",
|
||||
[HASH_ALGO_TGR_128] = "tgr128",
|
||||
[HASH_ALGO_TGR_160] = "tgr160",
|
||||
[HASH_ALGO_TGR_192] = "tgr192",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(hash_algo_name);
|
||||
|
||||
const int hash_digest_size[HASH_ALGO__LAST] = {
|
||||
[HASH_ALGO_MD4] = MD5_DIGEST_SIZE,
|
||||
[HASH_ALGO_MD5] = MD5_DIGEST_SIZE,
|
||||
[HASH_ALGO_SHA1] = SHA1_DIGEST_SIZE,
|
||||
[HASH_ALGO_RIPE_MD_160] = RMD160_DIGEST_SIZE,
|
||||
[HASH_ALGO_SHA256] = SHA256_DIGEST_SIZE,
|
||||
[HASH_ALGO_SHA384] = SHA384_DIGEST_SIZE,
|
||||
[HASH_ALGO_SHA512] = SHA512_DIGEST_SIZE,
|
||||
[HASH_ALGO_SHA224] = SHA224_DIGEST_SIZE,
|
||||
[HASH_ALGO_RIPE_MD_128] = RMD128_DIGEST_SIZE,
|
||||
[HASH_ALGO_RIPE_MD_256] = RMD256_DIGEST_SIZE,
|
||||
[HASH_ALGO_RIPE_MD_320] = RMD320_DIGEST_SIZE,
|
||||
[HASH_ALGO_WP_256] = WP256_DIGEST_SIZE,
|
||||
[HASH_ALGO_WP_384] = WP384_DIGEST_SIZE,
|
||||
[HASH_ALGO_WP_512] = WP512_DIGEST_SIZE,
|
||||
[HASH_ALGO_TGR_128] = TGR128_DIGEST_SIZE,
|
||||
[HASH_ALGO_TGR_160] = TGR160_DIGEST_SIZE,
|
||||
[HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(hash_digest_size);
|
||||
@@ -33,6 +33,15 @@ config TCG_TIS
|
||||
from within Linux. To compile this driver as a module, choose
|
||||
M here; the module will be called tpm_tis.
|
||||
|
||||
config TCG_TIS_I2C_ATMEL
|
||||
tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)"
|
||||
depends on I2C
|
||||
---help---
|
||||
If you have an Atmel I2C TPM security chip say Yes and it will be
|
||||
accessible from within Linux.
|
||||
To compile this driver as a module, choose M here; the module will
|
||||
be called tpm_tis_i2c_atmel.
|
||||
|
||||
config TCG_TIS_I2C_INFINEON
|
||||
tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
|
||||
depends on I2C
|
||||
@@ -42,7 +51,17 @@ config TCG_TIS_I2C_INFINEON
|
||||
Specification 0.20 say Yes and it will be accessible from within
|
||||
Linux.
|
||||
To compile this driver as a module, choose M here; the module
|
||||
will be called tpm_tis_i2c_infineon.
|
||||
will be called tpm_i2c_infineon.
|
||||
|
||||
config TCG_TIS_I2C_NUVOTON
|
||||
tristate "TPM Interface Specification 1.2 Interface (I2C - Nuvoton)"
|
||||
depends on I2C
|
||||
---help---
|
||||
If you have a TPM security chip with an I2C interface from
|
||||
Nuvoton Technology Corp. say Yes and it will be accessible
|
||||
from within Linux.
|
||||
To compile this driver as a module, choose M here; the module
|
||||
will be called tpm_i2c_nuvoton.
|
||||
|
||||
config TCG_NSC
|
||||
tristate "National Semiconductor TPM Interface"
|
||||
@@ -82,14 +101,14 @@ config TCG_IBMVTPM
|
||||
as a module, choose M here; the module will be called tpm_ibmvtpm.
|
||||
|
||||
config TCG_ST33_I2C
|
||||
tristate "STMicroelectronics ST33 I2C TPM"
|
||||
depends on I2C
|
||||
depends on GPIOLIB
|
||||
---help---
|
||||
If you have a TPM security chip from STMicroelectronics working with
|
||||
an I2C bus say Yes and it will be accessible from within Linux.
|
||||
To compile this driver as a module, choose M here; the module will be
|
||||
called tpm_stm_st33_i2c.
|
||||
tristate "STMicroelectronics ST33 I2C TPM"
|
||||
depends on I2C
|
||||
depends on GPIOLIB
|
||||
---help---
|
||||
If you have a TPM security chip from STMicroelectronics working with
|
||||
an I2C bus say Yes and it will be accessible from within Linux.
|
||||
To compile this driver as a module, choose M here; the module will be
|
||||
called tpm_stm_st33_i2c.
|
||||
|
||||
config TCG_XEN
|
||||
tristate "XEN TPM Interface"
|
||||
|
||||
@@ -2,17 +2,20 @@
|
||||
# Makefile for the kernel tpm device drivers.
|
||||
#
|
||||
obj-$(CONFIG_TCG_TPM) += tpm.o
|
||||
tpm-y := tpm-interface.o
|
||||
tpm-$(CONFIG_ACPI) += tpm_ppi.o
|
||||
|
||||
ifdef CONFIG_ACPI
|
||||
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
|
||||
tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
|
||||
tpm-y += tpm_eventlog.o tpm_acpi.o
|
||||
else
|
||||
ifdef CONFIG_TCG_IBMVTPM
|
||||
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
|
||||
tpm_bios-objs += tpm_eventlog.o tpm_of.o
|
||||
tpm-y += tpm_eventlog.o tpm_of.o
|
||||
endif
|
||||
endif
|
||||
obj-$(CONFIG_TCG_TIS) += tpm_tis.o
|
||||
obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
|
||||
obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
|
||||
obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
|
||||
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
|
||||
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
|
||||
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user