mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Highlights:
IMA:
- provide ">" and "<" operators for fowner/uid/euid rules
KEYS:
- add a system blacklist keyring
- add KEYCTL_RESTRICT_KEYRING, exposes keyring link restriction
functionality to userland via keyctl()
LSM:
- harden LSM API with __ro_after_init
- add prlmit security hook, implement for SELinux
- revive security_task_alloc hook
TPM:
- implement contextual TPM command 'spaces'"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (98 commits)
tpm: Fix reference count to main device
tpm_tis: convert to using locality callbacks
tpm: fix handling of the TPM 2.0 event logs
tpm_crb: remove a cruft constant
keys: select CONFIG_CRYPTO when selecting DH / KDF
apparmor: Make path_max parameter readonly
apparmor: fix parameters so that the permission test is bypassed at boot
apparmor: fix invalid reference to index variable of iterator line 836
apparmor: use SHASH_DESC_ON_STACK
security/apparmor/lsm.c: set debug messages
apparmor: fix boolreturn.cocci warnings
Smack: Use GFP_KERNEL for smk_netlbl_mls().
smack: fix double free in smack_parse_opts_str()
KEYS: add SP800-56A KDF support for DH
KEYS: Keyring asymmetric key restrict method with chaining
KEYS: Restrict asymmetric key linkage using a specific keychain
KEYS: Add a lookup_restriction function for the asymmetric key type
KEYS: Add KEYCTL_RESTRICT_KEYRING
KEYS: Consistent ordering for __key_link_begin and restrict check
KEYS: Add an optional lookup_restriction hook to key_type
...
This commit is contained in:
@@ -311,3 +311,54 @@ Functions are provided to register and unregister parsers:
|
||||
|
||||
Parsers may not have the same name. The names are otherwise only used for
|
||||
displaying in debugging messages.
|
||||
|
||||
|
||||
=========================
|
||||
KEYRING LINK RESTRICTIONS
|
||||
=========================
|
||||
|
||||
Keyrings created from userspace using add_key can be configured to check the
|
||||
signature of the key being linked.
|
||||
|
||||
Several restriction methods are available:
|
||||
|
||||
(1) Restrict using the kernel builtin trusted keyring
|
||||
|
||||
- Option string used with KEYCTL_RESTRICT_KEYRING:
|
||||
- "builtin_trusted"
|
||||
|
||||
The kernel builtin trusted keyring will be searched for the signing
|
||||
key. The ca_keys kernel parameter also affects which keys are used for
|
||||
signature verification.
|
||||
|
||||
(2) Restrict using the kernel builtin and secondary trusted keyrings
|
||||
|
||||
- Option string used with KEYCTL_RESTRICT_KEYRING:
|
||||
- "builtin_and_secondary_trusted"
|
||||
|
||||
The kernel builtin and secondary trusted keyrings will be searched for the
|
||||
signing key. The ca_keys kernel parameter also affects which keys are used
|
||||
for signature verification.
|
||||
|
||||
(3) Restrict using a separate key or keyring
|
||||
|
||||
- Option string used with KEYCTL_RESTRICT_KEYRING:
|
||||
- "key_or_keyring:<key or keyring serial number>[:chain]"
|
||||
|
||||
Whenever a key link is requested, the link will only succeed if the key
|
||||
being linked is signed by one of the designated keys. This key may be
|
||||
specified directly by providing a serial number for one asymmetric key, or
|
||||
a group of keys may be searched for the signing key by providing the
|
||||
serial number for a keyring.
|
||||
|
||||
When the "chain" option is provided at the end of the string, the keys
|
||||
within the destination keyring will also be searched for signing keys.
|
||||
This allows for verification of certificate chains by adding each
|
||||
cert in order (starting closest to the root) to one keyring.
|
||||
|
||||
In all of these cases, if the signing key is found the signature of the key to
|
||||
be linked will be verified using the signing key. The requested key is added
|
||||
to the keyring only if the signature is successfully verified. -ENOKEY is
|
||||
returned if the parent certificate could not be found, or -EKEYREJECTED is
|
||||
returned if the signature check fails or the key is blacklisted. Other errors
|
||||
may be returned if the signature check could not be performed.
|
||||
|
||||
@@ -827,7 +827,7 @@ The keyctl syscall functions are:
|
||||
|
||||
long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
|
||||
char *buffer, size_t buflen,
|
||||
void *reserved);
|
||||
struct keyctl_kdf_params *kdf);
|
||||
|
||||
The params struct contains serial numbers for three keys:
|
||||
|
||||
@@ -844,18 +844,61 @@ The keyctl syscall functions are:
|
||||
public key. If the base is the remote public key, the result is
|
||||
the shared secret.
|
||||
|
||||
The reserved argument must be set to NULL.
|
||||
If the parameter kdf is NULL, the following applies:
|
||||
|
||||
The buffer length must be at least the length of the prime, or zero.
|
||||
- The buffer length must be at least the length of the prime, or zero.
|
||||
|
||||
If the buffer length is nonzero, the length of the result is
|
||||
returned when it is successfully calculated and copied in to the
|
||||
buffer. When the buffer length is zero, the minimum required
|
||||
buffer length is returned.
|
||||
- If the buffer length is nonzero, the length of the result is
|
||||
returned when it is successfully calculated and copied in to the
|
||||
buffer. When the buffer length is zero, the minimum required
|
||||
buffer length is returned.
|
||||
|
||||
The kdf parameter allows the caller to apply a key derivation function
|
||||
(KDF) on the Diffie-Hellman computation where only the result
|
||||
of the KDF is returned to the caller. The KDF is characterized with
|
||||
struct keyctl_kdf_params as follows:
|
||||
|
||||
- char *hashname specifies the NUL terminated string identifying
|
||||
the hash used from the kernel crypto API and applied for the KDF
|
||||
operation. The KDF implemenation complies with SP800-56A as well
|
||||
as with SP800-108 (the counter KDF).
|
||||
|
||||
- char *otherinfo specifies the OtherInfo data as documented in
|
||||
SP800-56A section 5.8.1.2. The length of the buffer is given with
|
||||
otherinfolen. The format of OtherInfo is defined by the caller.
|
||||
The otherinfo pointer may be NULL if no OtherInfo shall be used.
|
||||
|
||||
This function will return error EOPNOTSUPP if the key type is not
|
||||
supported, error ENOKEY if the key could not be found, or error
|
||||
EACCES if the key is not readable by the caller.
|
||||
EACCES if the key is not readable by the caller. In addition, the
|
||||
function will return EMSGSIZE when the parameter kdf is non-NULL
|
||||
and either the buffer length or the OtherInfo length exceeds the
|
||||
allowed length.
|
||||
|
||||
(*) Restrict keyring linkage
|
||||
|
||||
long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring,
|
||||
const char *type, const char *restriction);
|
||||
|
||||
An existing keyring can restrict linkage of additional keys by evaluating
|
||||
the contents of the key according to a restriction scheme.
|
||||
|
||||
"keyring" is the key ID for an existing keyring to apply a restriction
|
||||
to. It may be empty or may already have keys linked. Existing linked keys
|
||||
will remain in the keyring even if the new restriction would reject them.
|
||||
|
||||
"type" is a registered key type.
|
||||
|
||||
"restriction" is a string describing how key linkage is to be restricted.
|
||||
The format varies depending on the key type, and the string is passed to
|
||||
the lookup_restriction() function for the requested type. It may specify
|
||||
a method and relevant data for the restriction such as signature
|
||||
verification or constraints on key payload. If the requested key type is
|
||||
later unregistered, no keys may be added to the keyring after the key type
|
||||
is removed.
|
||||
|
||||
To apply a keyring restriction the process must have Set Attribute
|
||||
permission and the keyring must not be previously restricted.
|
||||
|
||||
===============
|
||||
KERNEL SERVICES
|
||||
@@ -1032,10 +1075,7 @@ payload contents" for more information.
|
||||
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
|
||||
const struct cred *cred,
|
||||
key_perm_t perm,
|
||||
int (*restrict_link)(struct key *,
|
||||
const struct key_type *,
|
||||
unsigned long,
|
||||
const union key_payload *),
|
||||
struct key_restriction *restrict_link,
|
||||
unsigned long flags,
|
||||
struct key *dest);
|
||||
|
||||
@@ -1047,20 +1087,23 @@ payload contents" for more information.
|
||||
KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
|
||||
towards the user's quota). Error ENOMEM can also be returned.
|
||||
|
||||
If restrict_link not NULL, it should point to a function that will be
|
||||
called each time an attempt is made to link a key into the new keyring.
|
||||
This function is called to check whether a key may be added into the keying
|
||||
or not. Callers of key_create_or_update() within the kernel can pass
|
||||
KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using
|
||||
this is to manage rings of cryptographic keys that are set up when the
|
||||
kernel boots where userspace is also permitted to add keys - provided they
|
||||
can be verified by a key the kernel already has.
|
||||
If restrict_link is not NULL, it should point to a structure that contains
|
||||
the function that will be called each time an attempt is made to link a
|
||||
key into the new keyring. The structure may also contain a key pointer
|
||||
and an associated key type. The function is called to check whether a key
|
||||
may be added into the keyring or not. The key type is used by the garbage
|
||||
collector to clean up function or data pointers in this structure if the
|
||||
given key type is unregistered. Callers of key_create_or_update() within
|
||||
the kernel can pass KEY_ALLOC_BYPASS_RESTRICTION to suppress the check.
|
||||
An example of using this is to manage rings of cryptographic keys that are
|
||||
set up when the kernel boots where userspace is also permitted to add keys
|
||||
- provided they can be verified by a key the kernel already has.
|
||||
|
||||
When called, the restriction function will be passed the keyring being
|
||||
added to, the key flags value and the type and payload of the key being
|
||||
added. Note that when a new key is being created, this is called between
|
||||
payload preparsing and actual key creation. The function should return 0
|
||||
to allow the link or an error to reject it.
|
||||
added to, the key type, the payload of the key being added, and data to be
|
||||
used in the restriction check. Note that when a new key is being created,
|
||||
this is called between payload preparsing and actual key creation. The
|
||||
function should return 0 to allow the link or an error to reject it.
|
||||
|
||||
A convenience function, restrict_link_reject, exists to always return
|
||||
-EPERM to in this case.
|
||||
@@ -1445,6 +1488,15 @@ The structure has a number of fields, some of which are mandatory:
|
||||
The authorisation key.
|
||||
|
||||
|
||||
(*) struct key_restriction *(*lookup_restriction)(const char *params);
|
||||
|
||||
This optional method is used to enable userspace configuration of keyring
|
||||
restrictions. The restriction parameter string (not including the key type
|
||||
name) is passed in, and this method returns a pointer to a key_restriction
|
||||
structure containing the relevant functions and data to evaluate each
|
||||
attempted key link operation. If there is no match, -EINVAL is returned.
|
||||
|
||||
|
||||
============================
|
||||
REQUEST-KEY CALLBACK SERVICE
|
||||
============================
|
||||
|
||||
@@ -64,4 +64,22 @@ config SECONDARY_TRUSTED_KEYRING
|
||||
those keys are not blacklisted and are vouched for by a key built
|
||||
into the kernel or already in the secondary trusted keyring.
|
||||
|
||||
config SYSTEM_BLACKLIST_KEYRING
|
||||
bool "Provide system-wide ring of blacklisted keys"
|
||||
depends on KEYS
|
||||
help
|
||||
Provide a system keyring to which blacklisted keys can be added.
|
||||
Keys in the keyring are considered entirely untrusted. Keys in this
|
||||
keyring are used by the module signature checking to reject loading
|
||||
of modules signed with a blacklisted key.
|
||||
|
||||
config SYSTEM_BLACKLIST_HASH_LIST
|
||||
string "Hashes to be preloaded into the system blacklist keyring"
|
||||
depends on SYSTEM_BLACKLIST_KEYRING
|
||||
help
|
||||
If set, this option should be the filename of a list of hashes in the
|
||||
form "<hash>", "<hash>", ... . This will be included into a C
|
||||
wrapper to incorporate the list into the kernel. Each <hash> should
|
||||
be a string of hex digits.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
|
||||
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
|
||||
ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
|
||||
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
|
||||
else
|
||||
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/* System hash blacklist.
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the Licence, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "blacklist: "fmt
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/key.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include "blacklist.h"
|
||||
|
||||
static struct key *blacklist_keyring;
|
||||
|
||||
/*
|
||||
* The description must be a type prefix, a colon and then an even number of
|
||||
* hex digits. The hash is kept in the description.
|
||||
*/
|
||||
static int blacklist_vet_description(const char *desc)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
if (*desc == ':')
|
||||
return -EINVAL;
|
||||
for (; *desc; desc++)
|
||||
if (*desc == ':')
|
||||
goto found_colon;
|
||||
return -EINVAL;
|
||||
|
||||
found_colon:
|
||||
desc++;
|
||||
for (; *desc; desc++) {
|
||||
if (!isxdigit(*desc))
|
||||
return -EINVAL;
|
||||
n++;
|
||||
}
|
||||
|
||||
if (n == 0 || n & 1)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The hash to be blacklisted is expected to be in the description. There will
|
||||
* be no payload.
|
||||
*/
|
||||
static int blacklist_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
if (prep->datalen > 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blacklist_free_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
}
|
||||
|
||||
static void blacklist_describe(const struct key *key, struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, key->description);
|
||||
}
|
||||
|
||||
static struct key_type key_type_blacklist = {
|
||||
.name = "blacklist",
|
||||
.vet_description = blacklist_vet_description,
|
||||
.preparse = blacklist_preparse,
|
||||
.free_preparse = blacklist_free_preparse,
|
||||
.instantiate = generic_key_instantiate,
|
||||
.describe = blacklist_describe,
|
||||
};
|
||||
|
||||
/**
|
||||
* mark_hash_blacklisted - Add a hash to the system blacklist
|
||||
* @hash - The hash as a hex string with a type prefix (eg. "tbs:23aa429783")
|
||||
*/
|
||||
int mark_hash_blacklisted(const char *hash)
|
||||
{
|
||||
key_ref_t key;
|
||||
|
||||
key = key_create_or_update(make_key_ref(blacklist_keyring, true),
|
||||
"blacklist",
|
||||
hash,
|
||||
NULL,
|
||||
0,
|
||||
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||
KEY_USR_VIEW),
|
||||
KEY_ALLOC_NOT_IN_QUOTA |
|
||||
KEY_ALLOC_BUILT_IN);
|
||||
if (IS_ERR(key)) {
|
||||
pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key));
|
||||
return PTR_ERR(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_hash_blacklisted - Determine if a hash is blacklisted
|
||||
* @hash: The hash to be checked as a binary blob
|
||||
* @hash_len: The length of the binary hash
|
||||
* @type: Type of hash
|
||||
*/
|
||||
int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
|
||||
{
|
||||
key_ref_t kref;
|
||||
size_t type_len = strlen(type);
|
||||
char *buffer, *p;
|
||||
int ret = 0;
|
||||
|
||||
buffer = kmalloc(type_len + 1 + hash_len * 2 + 1, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
p = memcpy(buffer, type, type_len);
|
||||
p += type_len;
|
||||
*p++ = ':';
|
||||
bin2hex(p, hash, hash_len);
|
||||
p += hash_len * 2;
|
||||
*p = 0;
|
||||
|
||||
kref = keyring_search(make_key_ref(blacklist_keyring, true),
|
||||
&key_type_blacklist, buffer);
|
||||
if (!IS_ERR(kref)) {
|
||||
key_ref_put(kref);
|
||||
ret = -EKEYREJECTED;
|
||||
}
|
||||
|
||||
kfree(buffer);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(is_hash_blacklisted);
|
||||
|
||||
/*
|
||||
* Intialise the blacklist
|
||||
*/
|
||||
static int __init blacklist_init(void)
|
||||
{
|
||||
const char *const *bl;
|
||||
|
||||
if (register_key_type(&key_type_blacklist) < 0)
|
||||
panic("Can't allocate system blacklist key type\n");
|
||||
|
||||
blacklist_keyring =
|
||||
keyring_alloc(".blacklist",
|
||||
KUIDT_INIT(0), KGIDT_INIT(0),
|
||||
current_cred(),
|
||||
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||
KEY_USR_VIEW | KEY_USR_READ |
|
||||
KEY_USR_SEARCH,
|
||||
KEY_ALLOC_NOT_IN_QUOTA |
|
||||
KEY_FLAG_KEEP,
|
||||
NULL, NULL);
|
||||
if (IS_ERR(blacklist_keyring))
|
||||
panic("Can't allocate system blacklist keyring\n");
|
||||
|
||||
for (bl = blacklist_hashes; *bl; bl++)
|
||||
if (mark_hash_blacklisted(*bl) < 0)
|
||||
pr_err("- blacklisting failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be initialised before we try and load the keys into the keyring.
|
||||
*/
|
||||
device_initcall(blacklist_init);
|
||||
@@ -0,0 +1,3 @@
|
||||
#include <linux/kernel.h>
|
||||
|
||||
extern const char __initdata *const blacklist_hashes[];
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "blacklist.h"
|
||||
|
||||
const char __initdata *const blacklist_hashes[] = {
|
||||
#include CONFIG_SYSTEM_BLACKLIST_HASH_LIST
|
||||
, NULL
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "blacklist.h"
|
||||
|
||||
const char __initdata *const blacklist_hashes[] = {
|
||||
NULL
|
||||
};
|
||||
+31
-8
@@ -14,6 +14,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/pkcs7.h>
|
||||
@@ -32,11 +33,13 @@ extern __initconst const unsigned long system_certificate_list_size;
|
||||
* Restrict the addition of keys into a keyring based on the key-to-be-added
|
||||
* being vouched for by a key in the built in system keyring.
|
||||
*/
|
||||
int restrict_link_by_builtin_trusted(struct key *keyring,
|
||||
int restrict_link_by_builtin_trusted(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload)
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key)
|
||||
{
|
||||
return restrict_link_by_signature(builtin_trusted_keys, type, payload);
|
||||
return restrict_link_by_signature(dest_keyring, type, payload,
|
||||
builtin_trusted_keys);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
|
||||
@@ -49,20 +52,40 @@ int restrict_link_by_builtin_trusted(struct key *keyring,
|
||||
* keyrings.
|
||||
*/
|
||||
int restrict_link_by_builtin_and_secondary_trusted(
|
||||
struct key *keyring,
|
||||
struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload)
|
||||
const union key_payload *payload,
|
||||
struct key *restrict_key)
|
||||
{
|
||||
/* If we have a secondary trusted keyring, then that contains a link
|
||||
* through to the builtin keyring and the search will follow that link.
|
||||
*/
|
||||
if (type == &key_type_keyring &&
|
||||
keyring == secondary_trusted_keys &&
|
||||
dest_keyring == secondary_trusted_keys &&
|
||||
payload == &builtin_trusted_keys->payload)
|
||||
/* Allow the builtin keyring to be added to the secondary */
|
||||
return 0;
|
||||
|
||||
return restrict_link_by_signature(secondary_trusted_keys, type, payload);
|
||||
return restrict_link_by_signature(dest_keyring, type, payload,
|
||||
secondary_trusted_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a struct key_restriction for the "builtin and secondary trust"
|
||||
* keyring. Only for use in system_trusted_keyring_init().
|
||||
*/
|
||||
static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
|
||||
{
|
||||
struct key_restriction *restriction;
|
||||
|
||||
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
|
||||
|
||||
if (!restriction)
|
||||
panic("Can't allocate secondary trusted keyring restriction\n");
|
||||
|
||||
restriction->check = restrict_link_by_builtin_and_secondary_trusted;
|
||||
|
||||
return restriction;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -91,7 +114,7 @@ static __init int system_trusted_keyring_init(void)
|
||||
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
|
||||
KEY_USR_WRITE),
|
||||
KEY_ALLOC_NOT_IN_QUOTA,
|
||||
restrict_link_by_builtin_and_secondary_trusted,
|
||||
get_builtin_and_secondary_restriction(),
|
||||
NULL);
|
||||
if (IS_ERR(secondary_trusted_keys))
|
||||
panic("Can't allocate secondary trusted keyring\n");
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include "asymmetric_keys.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -451,15 +452,100 @@ static void asymmetric_key_destroy(struct key *key)
|
||||
asymmetric_key_free_kids(kids);
|
||||
}
|
||||
|
||||
static struct key_restriction *asymmetric_restriction_alloc(
|
||||
key_restrict_link_func_t check,
|
||||
struct key *key)
|
||||
{
|
||||
struct key_restriction *keyres =
|
||||
kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
|
||||
|
||||
if (!keyres)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
keyres->check = check;
|
||||
keyres->key = key;
|
||||
keyres->keytype = &key_type_asymmetric;
|
||||
|
||||
return keyres;
|
||||
}
|
||||
|
||||
/*
|
||||
* look up keyring restrict functions for asymmetric keys
|
||||
*/
|
||||
static struct key_restriction *asymmetric_lookup_restriction(
|
||||
const char *restriction)
|
||||
{
|
||||
char *restrict_method;
|
||||
char *parse_buf;
|
||||
char *next;
|
||||
struct key_restriction *ret = ERR_PTR(-EINVAL);
|
||||
|
||||
if (strcmp("builtin_trusted", restriction) == 0)
|
||||
return asymmetric_restriction_alloc(
|
||||
restrict_link_by_builtin_trusted, NULL);
|
||||
|
||||
if (strcmp("builtin_and_secondary_trusted", restriction) == 0)
|
||||
return asymmetric_restriction_alloc(
|
||||
restrict_link_by_builtin_and_secondary_trusted, NULL);
|
||||
|
||||
parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
|
||||
if (!parse_buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
next = parse_buf;
|
||||
restrict_method = strsep(&next, ":");
|
||||
|
||||
if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
|
||||
char *key_text;
|
||||
key_serial_t serial;
|
||||
struct key *key;
|
||||
key_restrict_link_func_t link_fn =
|
||||
restrict_link_by_key_or_keyring;
|
||||
bool allow_null_key = false;
|
||||
|
||||
key_text = strsep(&next, ":");
|
||||
|
||||
if (next) {
|
||||
if (strcmp(next, "chain") != 0)
|
||||
goto out;
|
||||
|
||||
link_fn = restrict_link_by_key_or_keyring_chain;
|
||||
allow_null_key = true;
|
||||
}
|
||||
|
||||
if (kstrtos32(key_text, 0, &serial) < 0)
|
||||
goto out;
|
||||
|
||||
if ((serial == 0) && allow_null_key) {
|
||||
key = NULL;
|
||||
} else {
|
||||
key = key_lookup(serial);
|
||||
if (IS_ERR(key)) {
|
||||
ret = ERR_CAST(key);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = asymmetric_restriction_alloc(link_fn, key);
|
||||
if (IS_ERR(ret))
|
||||
key_put(key);
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(parse_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct key_type key_type_asymmetric = {
|
||||
.name = "asymmetric",
|
||||
.preparse = asymmetric_key_preparse,
|
||||
.free_preparse = asymmetric_key_free_preparse,
|
||||
.instantiate = generic_key_instantiate,
|
||||
.match_preparse = asymmetric_key_match_preparse,
|
||||
.match_free = asymmetric_key_match_free,
|
||||
.destroy = asymmetric_key_destroy,
|
||||
.describe = asymmetric_key_describe,
|
||||
.name = "asymmetric",
|
||||
.preparse = asymmetric_key_preparse,
|
||||
.free_preparse = asymmetric_key_free_preparse,
|
||||
.instantiate = generic_key_instantiate,
|
||||
.match_preparse = asymmetric_key_match_preparse,
|
||||
.match_free = asymmetric_key_match_free,
|
||||
.destroy = asymmetric_key_destroy,
|
||||
.describe = asymmetric_key_describe,
|
||||
.lookup_restriction = asymmetric_lookup_restriction,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(key_type_asymmetric);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ struct pkcs7_signed_info {
|
||||
struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
|
||||
unsigned index;
|
||||
bool unsupported_crypto; /* T if not usable due to missing crypto */
|
||||
bool blacklisted;
|
||||
|
||||
/* Message digest - the digest of the Content Data (or NULL) */
|
||||
const void *msgdigest;
|
||||
|
||||
@@ -190,6 +190,18 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
|
||||
x509->subject,
|
||||
x509->raw_serial_size, x509->raw_serial);
|
||||
x509->seen = true;
|
||||
|
||||
if (x509->blacklisted) {
|
||||
/* If this cert is blacklisted, then mark everything
|
||||
* that depends on this as blacklisted too.
|
||||
*/
|
||||
sinfo->blacklisted = true;
|
||||
for (p = sinfo->signer; p != x509; p = p->signer)
|
||||
p->blacklisted = true;
|
||||
pr_debug("- blacklisted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x509->unsupported_key)
|
||||
goto unsupported_crypto_in_x509;
|
||||
|
||||
@@ -357,17 +369,19 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
|
||||
*
|
||||
* (*) -EBADMSG if some part of the message was invalid, or:
|
||||
*
|
||||
* (*) -ENOPKG if none of the signature chains are verifiable because suitable
|
||||
* crypto modules couldn't be found, or:
|
||||
* (*) 0 if no signature chains were found to be blacklisted or to contain
|
||||
* unsupported crypto, or:
|
||||
*
|
||||
* (*) 0 if all the signature chains that don't incur -ENOPKG can be verified
|
||||
* (note that a signature chain may be of zero length), or:
|
||||
* (*) -EKEYREJECTED if a blacklisted key was encountered, or:
|
||||
*
|
||||
* (*) -ENOPKG if none of the signature chains are verifiable because suitable
|
||||
* crypto modules couldn't be found.
|
||||
*/
|
||||
int pkcs7_verify(struct pkcs7_message *pkcs7,
|
||||
enum key_being_used_for usage)
|
||||
{
|
||||
struct pkcs7_signed_info *sinfo;
|
||||
int enopkg = -ENOPKG;
|
||||
int actual_ret = -ENOPKG;
|
||||
int ret;
|
||||
|
||||
kenter("");
|
||||
@@ -412,6 +426,8 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
|
||||
|
||||
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
|
||||
ret = pkcs7_verify_one(pkcs7, sinfo);
|
||||
if (sinfo->blacklisted && actual_ret == -ENOPKG)
|
||||
actual_ret = -EKEYREJECTED;
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOPKG) {
|
||||
sinfo->unsupported_crypto = true;
|
||||
@@ -420,11 +436,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
|
||||
kleave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
enopkg = 0;
|
||||
actual_ret = 0;
|
||||
}
|
||||
|
||||
kleave(" = %d", enopkg);
|
||||
return enopkg;
|
||||
kleave(" = %d", actual_ret);
|
||||
return actual_ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkcs7_verify);
|
||||
|
||||
|
||||
@@ -56,9 +56,10 @@ __setup("ca_keys=", ca_keys_setup);
|
||||
|
||||
/**
|
||||
* restrict_link_by_signature - Restrict additions to a ring of public keys
|
||||
* @trust_keyring: A ring of keys that can be used to vouch for the new cert.
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @trust_keyring: A ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* 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
|
||||
@@ -69,9 +70,10 @@ __setup("ca_keys=", ca_keys_setup);
|
||||
* signature check fails or the key is blacklisted and some other error if
|
||||
* there is a matching certificate but the signature check cannot be performed.
|
||||
*/
|
||||
int restrict_link_by_signature(struct key *trust_keyring,
|
||||
int restrict_link_by_signature(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload)
|
||||
const union key_payload *payload,
|
||||
struct key *trust_keyring)
|
||||
{
|
||||
const struct public_key_signature *sig;
|
||||
struct key *key;
|
||||
@@ -106,3 +108,156 @@ int restrict_link_by_signature(struct key *trust_keyring,
|
||||
key_put(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool match_either_id(const struct asymmetric_key_ids *pair,
|
||||
const struct asymmetric_key_id *single)
|
||||
{
|
||||
return (asymmetric_key_id_same(pair->id[0], single) ||
|
||||
asymmetric_key_id_same(pair->id[1], single));
|
||||
}
|
||||
|
||||
static int key_or_keyring_common(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trusted, bool check_dest)
|
||||
{
|
||||
const struct public_key_signature *sig;
|
||||
struct key *key = NULL;
|
||||
int ret;
|
||||
|
||||
pr_devel("==>%s()\n", __func__);
|
||||
|
||||
if (!dest_keyring)
|
||||
return -ENOKEY;
|
||||
else if (dest_keyring->type != &key_type_keyring)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!trusted && !check_dest)
|
||||
return -ENOKEY;
|
||||
|
||||
if (type != &key_type_asymmetric)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sig = payload->data[asym_auth];
|
||||
if (!sig->auth_ids[0] && !sig->auth_ids[1])
|
||||
return -ENOKEY;
|
||||
|
||||
if (trusted) {
|
||||
if (trusted->type == &key_type_keyring) {
|
||||
/* See if we have a key that signed this one. */
|
||||
key = find_asymmetric_key(trusted, sig->auth_ids[0],
|
||||
sig->auth_ids[1], false);
|
||||
if (IS_ERR(key))
|
||||
key = NULL;
|
||||
} else if (trusted->type == &key_type_asymmetric) {
|
||||
const struct asymmetric_key_ids *signer_ids;
|
||||
|
||||
signer_ids = asymmetric_key_ids(trusted);
|
||||
|
||||
/*
|
||||
* The auth_ids come from the candidate key (the
|
||||
* one that is being considered for addition to
|
||||
* dest_keyring) and identify the key that was
|
||||
* used to sign.
|
||||
*
|
||||
* The signer_ids are identifiers for the
|
||||
* signing key specified for dest_keyring.
|
||||
*
|
||||
* The first auth_id is the preferred id, and
|
||||
* the second is the fallback. If only one
|
||||
* auth_id is present, it may match against
|
||||
* either signer_id. If two auth_ids are
|
||||
* present, the first auth_id must match one
|
||||
* signer_id and the second auth_id must match
|
||||
* the second signer_id.
|
||||
*/
|
||||
if (!sig->auth_ids[0] || !sig->auth_ids[1]) {
|
||||
const struct asymmetric_key_id *auth_id;
|
||||
|
||||
auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];
|
||||
if (match_either_id(signer_ids, auth_id))
|
||||
key = __key_get(trusted);
|
||||
|
||||
} else if (asymmetric_key_id_same(signer_ids->id[1],
|
||||
sig->auth_ids[1]) &&
|
||||
match_either_id(signer_ids,
|
||||
sig->auth_ids[0])) {
|
||||
key = __key_get(trusted);
|
||||
}
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_dest && !key) {
|
||||
/* See if the destination has a key that signed this one. */
|
||||
key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],
|
||||
sig->auth_ids[1], false);
|
||||
if (IS_ERR(key))
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
if (!key)
|
||||
return -ENOKEY;
|
||||
|
||||
ret = key_validate(key);
|
||||
if (ret == 0)
|
||||
ret = verify_signature(key, sig);
|
||||
|
||||
key_put(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* restrict_link_by_key_or_keyring - Restrict additions to a ring of public
|
||||
* keys using the restrict_key information stored in the ring.
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @trusted: A key or ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* Check the new certificate only against the key or keys passed in the data
|
||||
* parameter. If one of those is the signing key and validates the new
|
||||
* certificate, then mark the new certificate as being ok to link.
|
||||
*
|
||||
* Returns 0 if the new certificate was accepted, -ENOKEY if we
|
||||
* couldn't find a matching parent certificate in the trusted list,
|
||||
* -EKEYREJECTED if the signature check fails, and some other error if
|
||||
* there is a matching certificate but the signature check cannot be
|
||||
* performed.
|
||||
*/
|
||||
int restrict_link_by_key_or_keyring(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trusted)
|
||||
{
|
||||
return key_or_keyring_common(dest_keyring, type, payload, trusted,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of
|
||||
* public keys using the restrict_key information stored in the ring.
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @trusted: A key or ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* Check the new certificate only against the key or keys passed in the data
|
||||
* parameter. If one of those is the signing key and validates the new
|
||||
* certificate, then mark the new certificate as being ok to link.
|
||||
*
|
||||
* Returns 0 if the new certificate was accepted, -ENOKEY if we
|
||||
* couldn't find a matching parent certificate in the trusted list,
|
||||
* -EKEYREJECTED if the signature check fails, and some other error if
|
||||
* there is a matching certificate but the signature check cannot be
|
||||
* performed.
|
||||
*/
|
||||
int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trusted)
|
||||
{
|
||||
return key_or_keyring_common(dest_keyring, type, payload, trusted,
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ struct x509_certificate {
|
||||
bool self_signed; /* T if self-signed (check unsupported_sig too) */
|
||||
bool unsupported_key; /* T if key uses unsupported crypto */
|
||||
bool unsupported_sig; /* T if signature uses unsupported crypto */
|
||||
bool blacklisted;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -84,6 +84,16 @@ int x509_get_sig_params(struct x509_certificate *cert)
|
||||
goto error_2;
|
||||
might_sleep();
|
||||
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
|
||||
if (ret < 0)
|
||||
goto error_2;
|
||||
|
||||
ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs");
|
||||
if (ret == -EKEYREJECTED) {
|
||||
pr_err("Cert %*phN is blacklisted\n",
|
||||
sig->digest_size, sig->digest);
|
||||
cert->blacklisted = true;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
error_2:
|
||||
kfree(desc);
|
||||
@@ -186,6 +196,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
|
||||
cert->sig->pkey_algo, cert->sig->hash_algo);
|
||||
}
|
||||
|
||||
/* Don't permit addition of blacklisted keys */
|
||||
ret = -EKEYREJECTED;
|
||||
if (cert->blacklisted)
|
||||
goto error_free_cert;
|
||||
|
||||
/* Propose a description */
|
||||
sulen = strlen(cert->subject);
|
||||
if (cert->raw_skid) {
|
||||
|
||||
@@ -6,6 +6,7 @@ menuconfig TCG_TPM
|
||||
tristate "TPM Hardware Support"
|
||||
depends on HAS_IOMEM
|
||||
select SECURITYFS
|
||||
select CRYPTO
|
||||
select CRYPTO_HASH_INFO
|
||||
---help---
|
||||
If you have a TPM security chip in your system, which
|
||||
@@ -135,7 +136,7 @@ config TCG_XEN
|
||||
|
||||
config TCG_CRB
|
||||
tristate "TPM 2.0 CRB Interface"
|
||||
depends on X86 && ACPI
|
||||
depends on ACPI
|
||||
---help---
|
||||
If you have a TPM security chip that is compliant with the
|
||||
TCG CRB 2.0 TPM specification say Yes and it will be accessible
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#
|
||||
obj-$(CONFIG_TCG_TPM) += tpm.o
|
||||
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
|
||||
tpm1_eventlog.o tpm2_eventlog.o
|
||||
tpm-dev-common.o tpmrm-dev.o tpm1_eventlog.o tpm2_eventlog.o \
|
||||
tpm2-space.o
|
||||
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
|
||||
tpm-$(CONFIG_OF) += tpm_of.o
|
||||
obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
|
||||
|
||||
@@ -111,6 +111,13 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
|
||||
.recv = st33zp24_i2c_recv,
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
|
||||
{ "lpcpd-gpios", &lpcpd_gpios, 1 },
|
||||
{},
|
||||
};
|
||||
|
||||
static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
|
||||
{
|
||||
struct tpm_chip *chip = i2c_get_clientdata(client);
|
||||
@@ -118,10 +125,14 @@ static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
|
||||
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
|
||||
struct gpio_desc *gpiod_lpcpd;
|
||||
struct device *dev = &client->dev;
|
||||
int ret;
|
||||
|
||||
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get LPCPD GPIO from ACPI */
|
||||
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
|
||||
GPIOD_OUT_HIGH);
|
||||
gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpiod_lpcpd)) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to retrieve lpcpd-gpios from acpi.\n");
|
||||
@@ -268,8 +279,14 @@ static int st33zp24_i2c_probe(struct i2c_client *client,
|
||||
static int st33zp24_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tpm_chip *chip = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
return st33zp24_remove(chip);
|
||||
ret = st33zp24_remove(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id st33zp24_i2c_id[] = {
|
||||
|
||||
@@ -230,6 +230,13 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
|
||||
.recv = st33zp24_spi_recv,
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
|
||||
{ "lpcpd-gpios", &lpcpd_gpios, 1 },
|
||||
{},
|
||||
};
|
||||
|
||||
static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
|
||||
{
|
||||
struct tpm_chip *chip = spi_get_drvdata(spi_dev);
|
||||
@@ -237,10 +244,14 @@ static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
|
||||
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
|
||||
struct gpio_desc *gpiod_lpcpd;
|
||||
struct device *dev = &spi_dev->dev;
|
||||
int ret;
|
||||
|
||||
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get LPCPD GPIO from ACPI */
|
||||
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
|
||||
GPIOD_OUT_HIGH);
|
||||
gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpiod_lpcpd)) {
|
||||
dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
|
||||
phy->io_lpcpd = -1;
|
||||
@@ -385,8 +396,14 @@ static int st33zp24_spi_probe(struct spi_device *dev)
|
||||
static int st33zp24_spi_remove(struct spi_device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = spi_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
return st33zp24_remove(chip);
|
||||
ret = st33zp24_remove(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&dev->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id st33zp24_spi_id[] = {
|
||||
|
||||
@@ -117,9 +117,9 @@ static u8 st33zp24_status(struct tpm_chip *chip)
|
||||
/*
|
||||
* check_locality if the locality is active
|
||||
* @param: chip, the tpm chip description
|
||||
* @return: the active locality or -EACCESS.
|
||||
* @return: true if LOCALITY0 is active, otherwise false
|
||||
*/
|
||||
static int check_locality(struct tpm_chip *chip)
|
||||
static bool check_locality(struct tpm_chip *chip)
|
||||
{
|
||||
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
|
||||
u8 data;
|
||||
@@ -129,9 +129,9 @@ static int check_locality(struct tpm_chip *chip)
|
||||
if (status && (data &
|
||||
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
|
||||
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
|
||||
return tpm_dev->locality;
|
||||
return true;
|
||||
|
||||
return -EACCES;
|
||||
return false;
|
||||
} /* check_locality() */
|
||||
|
||||
/*
|
||||
@@ -146,7 +146,7 @@ static int request_locality(struct tpm_chip *chip)
|
||||
long ret;
|
||||
u8 data;
|
||||
|
||||
if (check_locality(chip) == tpm_dev->locality)
|
||||
if (check_locality(chip))
|
||||
return tpm_dev->locality;
|
||||
|
||||
data = TPM_ACCESS_REQUEST_USE;
|
||||
@@ -158,7 +158,7 @@ static int request_locality(struct tpm_chip *chip)
|
||||
|
||||
/* Request locality is usually effective after the request */
|
||||
do {
|
||||
if (check_locality(chip) >= 0)
|
||||
if (check_locality(chip))
|
||||
return tpm_dev->locality;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user