Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
64724cfc
Commit
64724cfc
authored
Jul 22, 2014
by
David Howells
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'integrity/next-with-keys' into keys-next
Signed-off-by:
David Howells
<
dhowells@redhat.com
>
parents
6204e002
7d2ce232
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
225 additions
and
25 deletions
+225
-25
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+5
-0
crypto/asymmetric_keys/asymmetric_keys.h
crypto/asymmetric_keys/asymmetric_keys.h
+2
-0
crypto/asymmetric_keys/asymmetric_type.c
crypto/asymmetric_keys/asymmetric_type.c
+32
-19
crypto/asymmetric_keys/x509_public_key.c
crypto/asymmetric_keys/x509_public_key.c
+108
-1
include/keys/system_keyring.h
include/keys/system_keyring.h
+9
-1
include/linux/key.h
include/linux/key.h
+1
-0
kernel/system_keyring.c
kernel/system_keyring.c
+1
-0
security/integrity/digsig.c
security/integrity/digsig.c
+28
-0
security/integrity/ima/Kconfig
security/integrity/ima/Kconfig
+10
-0
security/integrity/ima/ima.h
security/integrity/ima/ima.h
+12
-0
security/integrity/ima/ima_main.c
security/integrity/ima/ima_main.c
+8
-2
security/integrity/integrity.h
security/integrity/integrity.h
+5
-0
security/keys/keyctl.c
security/keys/keyctl.c
+4
-2
No files found.
Documentation/kernel-parameters.txt
View file @
64724cfc
...
...
@@ -566,6 +566,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
possible to determine what the correct size should be.
This option provides an override for these situations.
ca_keys= [KEYS] This parameter identifies a specific key(s) on
the system trusted keyring to be used for certificate
trust validation.
format: { id:<keyid> | builtin }
ccw_timeout_log [S390]
See Documentation/s390/CommonIO for details.
...
...
crypto/asymmetric_keys/asymmetric_keys.h
View file @
64724cfc
...
...
@@ -9,6 +9,8 @@
* 2 of the Licence, or (at your option) any later version.
*/
int
asymmetric_keyid_match
(
const
char
*
kid
,
const
char
*
id
);
static
inline
const
char
*
asymmetric_key_id
(
const
struct
key
*
key
)
{
return
key
->
type_data
.
p
[
1
];
...
...
crypto/asymmetric_keys/asymmetric_type.c
View file @
64724cfc
...
...
@@ -22,6 +22,35 @@ MODULE_LICENSE("GPL");
static
LIST_HEAD
(
asymmetric_key_parsers
);
static
DECLARE_RWSEM
(
asymmetric_key_parsers_sem
);
/*
* Match asymmetric key id with partial match
* @id: key id to match in a form "id:<id>"
*/
int
asymmetric_keyid_match
(
const
char
*
kid
,
const
char
*
id
)
{
size_t
idlen
,
kidlen
;
if
(
!
kid
||
!
id
)
return
0
;
/* make it possible to use id as in the request: "id:<id>" */
if
(
strncmp
(
id
,
"id:"
,
3
)
==
0
)
id
+=
3
;
/* Anything after here requires a partial match on the ID string */
idlen
=
strlen
(
id
);
kidlen
=
strlen
(
kid
);
if
(
idlen
>
kidlen
)
return
0
;
kid
+=
kidlen
-
idlen
;
if
(
strcasecmp
(
id
,
kid
)
!=
0
)
return
0
;
return
1
;
}
EXPORT_SYMBOL_GPL
(
asymmetric_keyid_match
);
/*
* Match asymmetric keys on (part of) their name
* We have some shorthand methods for matching keys. We allow:
...
...
@@ -34,9 +63,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
{
const
struct
asymmetric_key_subtype
*
subtype
=
asymmetric_key_subtype
(
key
);
const
char
*
spec
=
description
;
const
char
*
id
,
*
kid
;
const
char
*
id
;
ptrdiff_t
speclen
;
size_t
idlen
,
kidlen
;
if
(
!
subtype
||
!
spec
||
!*
spec
)
return
0
;
...
...
@@ -55,23 +83,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
speclen
=
id
-
spec
;
id
++
;
/* Anything after here requires a partial match on the ID string */
kid
=
asymmetric_key_id
(
key
);
if
(
!
kid
)
return
0
;
idlen
=
strlen
(
id
);
kidlen
=
strlen
(
kid
);
if
(
idlen
>
kidlen
)
return
0
;
kid
+=
kidlen
-
idlen
;
if
(
strcasecmp
(
id
,
kid
)
!=
0
)
return
0
;
if
(
speclen
==
2
&&
memcmp
(
spec
,
"id"
,
2
)
==
0
)
return
1
;
if
(
speclen
==
2
&&
memcmp
(
spec
,
"id"
,
2
)
==
0
)
return
asymmetric_keyid_match
(
asymmetric_key_id
(
key
),
id
);
if
(
speclen
==
subtype
->
name_len
&&
memcmp
(
spec
,
subtype
->
name
,
speclen
)
==
0
)
...
...
crypto/asymmetric_keys/x509_public_key.c
View file @
64724cfc
...
...
@@ -18,11 +18,80 @@
#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
bool
use_builtin_keys
;
static
char
*
ca_keyid
;
#ifndef MODULE
static
int
__init
ca_keys_setup
(
char
*
str
)
{
if
(
!
str
)
/* default system keyring */
return
1
;
if
(
strncmp
(
str
,
"id:"
,
3
)
==
0
)
ca_keyid
=
str
;
/* owner key 'id:xxxxxx' */
else
if
(
strcmp
(
str
,
"builtin"
)
==
0
)
use_builtin_keys
=
true
;
return
1
;
}
__setup
(
"ca_keys="
,
ca_keys_setup
);
#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
);
}
/*
* Set up the signature parameters in an X.509 certificate. This involves
* digesting the signed data and extracting the signature.
...
...
@@ -102,6 +171,40 @@ int x509_check_signature(const struct public_key *pub,
}
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
)
{
struct
key
*
key
;
int
ret
=
1
;
if
(
!
trust_keyring
)
return
-
EOPNOTSUPP
;
if
(
ca_keyid
&&
!
asymmetric_keyid_match
(
cert
->
authority
,
ca_keyid
))
return
-
EPERM
;
key
=
x509_request_asymmetric_key
(
trust_keyring
,
cert
->
issuer
,
strlen
(
cert
->
issuer
),
cert
->
authority
,
strlen
(
cert
->
authority
));
if
(
!
IS_ERR
(
key
))
{
if
(
!
use_builtin_keys
||
test_bit
(
KEY_FLAG_BUILTIN
,
&
key
->
flags
))
ret
=
x509_check_signature
(
key
->
payload
.
data
,
cert
);
key_put
(
key
);
}
return
ret
;
}
/*
* Attempt to parse a data blob for a key as an X509 certificate.
*/
...
...
@@ -155,9 +258,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
/* 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
);
ret
=
x509_check_signature
(
cert
->
pub
,
cert
);
/* self-signed */
if
(
ret
<
0
)
goto
error_free_cert
;
}
else
if
(
!
prep
->
trusted
)
{
ret
=
x509_validate_trust
(
cert
,
get_system_trusted_keyring
());
if
(
!
ret
)
prep
->
trusted
=
1
;
}
/* Propose a description */
...
...
include/keys/system_keyring.h
View file @
64724cfc
...
...
@@ -17,7 +17,15 @@
#include <linux/key.h>
extern
struct
key
*
system_trusted_keyring
;
static
inline
struct
key
*
get_system_trusted_keyring
(
void
)
{
return
system_trusted_keyring
;
}
#else
static
inline
struct
key
*
get_system_trusted_keyring
(
void
)
{
return
NULL
;
}
#endif
#endif
/* _KEYS_SYSTEM_KEYRING_H */
include/linux/key.h
View file @
64724cfc
...
...
@@ -170,6 +170,7 @@ struct key {
#define KEY_FLAG_INVALIDATED 7
/* set if key has been invalidated */
#define KEY_FLAG_TRUSTED 8
/* set if key is trusted */
#define KEY_FLAG_TRUSTED_ONLY 9
/* set if keyring only accepts links to trusted keys */
#define KEY_FLAG_BUILTIN 10
/* set if key is builtin */
/* the key type and key description string
* - the desc is used to match a key against search criteria
...
...
kernel/system_keyring.c
View file @
64724cfc
...
...
@@ -89,6 +89,7 @@ static __init int load_system_certificate_list(void)
pr_err
(
"Problem loading in-kernel X.509 certificate (%ld)
\n
"
,
PTR_ERR
(
key
));
}
else
{
set_bit
(
KEY_FLAG_BUILTIN
,
&
key_ref_to_ptr
(
key
)
->
flags
);
pr_notice
(
"Loaded X.509 cert '%s'
\n
"
,
key_ref_to_ptr
(
key
)
->
description
);
key_ref_put
(
key
);
...
...
security/integrity/digsig.c
View file @
64724cfc
...
...
@@ -13,7 +13,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/rbtree.h>
#include <linux/cred.h>
#include <linux/key-type.h>
#include <linux/digsig.h>
...
...
@@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX];
static
const
char
*
keyring_name
[
INTEGRITY_KEYRING_MAX
]
=
{
"_evm"
,
"_module"
,
#ifndef CONFIG_IMA_TRUSTED_KEYRING
"_ima"
,
#else
".ima"
,
#endif
};
int
integrity_digsig_verify
(
const
unsigned
int
id
,
const
char
*
sig
,
int
siglen
,
...
...
@@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return
-
EOPNOTSUPP
;
}
int
integrity_init_keyring
(
const
unsigned
int
id
)
{
const
struct
cred
*
cred
=
current_cred
();
int
err
=
0
;
keyring
[
id
]
=
keyring_alloc
(
keyring_name
[
id
],
KUIDT_INIT
(
0
),
KGIDT_INIT
(
0
),
cred
,
((
KEY_POS_ALL
&
~
KEY_POS_SETATTR
)
|
KEY_USR_VIEW
|
KEY_USR_READ
|
KEY_USR_WRITE
|
KEY_USR_SEARCH
),
KEY_ALLOC_NOT_IN_QUOTA
,
NULL
);
if
(
!
IS_ERR
(
keyring
[
id
]))
set_bit
(
KEY_FLAG_TRUSTED_ONLY
,
&
keyring
[
id
]
->
flags
);
else
{
err
=
PTR_ERR
(
keyring
[
id
]);
pr_info
(
"Can't allocate %s keyring (%d)
\n
"
,
keyring_name
[
id
],
err
);
keyring
[
id
]
=
NULL
;
}
return
err
;
}
security/integrity/ima/Kconfig
View file @
64724cfc
...
...
@@ -123,3 +123,13 @@ config IMA_APPRAISE
For more information on integrity appraisal refer to:
<http://linux-ima.sourceforge.net>
If unsure, say N.
config IMA_TRUSTED_KEYRING
bool "Require all keys on the .ima keyring be signed"
depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
select KEYS_DEBUG_PROC_KEYS
default y
help
This option requires that all keys added to the .ima
keyring be signed by a key on the system trusted keyring.
security/integrity/ima/ima.h
View file @
64724cfc
...
...
@@ -249,4 +249,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
return
-
EINVAL
;
}
#endif
/* CONFIG_IMA_LSM_RULES */
#ifdef CONFIG_IMA_TRUSTED_KEYRING
static
inline
int
ima_init_keyring
(
const
unsigned
int
id
)
{
return
integrity_init_keyring
(
id
);
}
#else
static
inline
int
ima_init_keyring
(
const
unsigned
int
id
)
{
return
0
;
}
#endif
/* CONFIG_IMA_TRUSTED_KEYRING */
#endif
security/integrity/ima/ima_main.c
View file @
64724cfc
...
...
@@ -325,8 +325,14 @@ static int __init init_ima(void)
hash_setup
(
CONFIG_IMA_DEFAULT_HASH
);
error
=
ima_init
();
if
(
!
error
)
ima_initialized
=
1
;
if
(
error
)
goto
out
;
error
=
ima_init_keyring
(
INTEGRITY_KEYRING_IMA
);
if
(
error
)
goto
out
;
ima_initialized
=
1
;
out:
return
error
;
}
...
...
security/integrity/integrity.h
View file @
64724cfc
...
...
@@ -124,6 +124,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
int
integrity_digsig_verify
(
const
unsigned
int
id
,
const
char
*
sig
,
int
siglen
,
const
char
*
digest
,
int
digestlen
);
int
integrity_init_keyring
(
const
unsigned
int
id
);
#else
static
inline
int
integrity_digsig_verify
(
const
unsigned
int
id
,
...
...
@@ -133,6 +134,10 @@ static inline int integrity_digsig_verify(const unsigned int id,
return
-
EOPNOTSUPP
;
}
static
inline
int
integrity_init_keyring
(
const
unsigned
int
id
)
{
return
0
;
}
#endif
/* CONFIG_INTEGRITY_SIGNATURE */
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
...
...
security/keys/keyctl.c
View file @
64724cfc
...
...
@@ -37,8 +37,6 @@ static int key_get_type_from_user(char *type,
return
ret
;
if
(
ret
==
0
||
ret
>=
len
)
return
-
EINVAL
;
if
(
type
[
0
]
==
'.'
)
return
-
EPERM
;
type
[
len
-
1
]
=
'\0'
;
return
0
;
}
...
...
@@ -86,6 +84,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
if
(
!*
description
)
{
kfree
(
description
);
description
=
NULL
;
}
else
if
((
description
[
0
]
==
'.'
)
&&
(
strncmp
(
type
,
"keyring"
,
7
)
==
0
))
{
ret
=
-
EPERM
;
goto
error2
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment