Messages in this thread |  | | Date | Mon, 09 Jun 2014 17:57:55 +0300 | From | Dmitry Kasatkin <> | Subject | Re: [RFC PATCH v5 2/4] KEYS: verify a certificate is signed by a 'trusted' key |
| |
On 09/06/14 16:48, Mimi Zohar wrote: > On Mon, 2014-06-09 at 16:13 +0300, Dmitry Kasatkin wrote: >> On 07/06/14 00:50, Dmitry Kasatkin wrote: >>> On 3 June 2014 20:58, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote: >>>> Only public keys, with certificates signed by an existing >>>> 'trusted' key on the system trusted keyring, should be added >>>> to a trusted keyring. This patch adds support for verifying >>>> a certificate's signature. >>>> >>>> This is derived from David Howells pkcs7_request_asymmetric_key() patch. >>>> >>>> Changelog: >>>> - define get_system_trusted_keyring() to fix kbuild issues >>>> >>>> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> >>>> Signed-off-by: David Howells <dhowells@redhat.com> >>> Acked-by: me >>> >>> >>>> --- >>>> crypto/asymmetric_keys/x509_public_key.c | 84 +++++++++++++++++++++++++++++++- >>>> include/keys/system_keyring.h | 10 +++- >>>> 2 files changed, 92 insertions(+), 2 deletions(-) >>>> >>>> diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c >>>> index 382ef0d..1af8a30 100644 >>>> --- a/crypto/asymmetric_keys/x509_public_key.c >>>> +++ b/crypto/asymmetric_keys/x509_public_key.c >>>> @@ -18,12 +18,60 @@ >>>> #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" >>>> >>>> /* >>>> + * 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. >>>> */ >>>> @@ -103,6 +151,36 @@ 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) >>>> +{ >>>> + const struct public_key *pk; >>>> + struct key *key; >>>> + int ret = 1; >>>> + >>>> + if (!trust_keyring) >>>> + return -EOPNOTSUPP; >>>> + >>>> + 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);
I suspect that key_put(key) is missing here...
>>>> + } >>>> + return ret; >>>> +} >>>> + >>>> +/* >>>> * Attempt to parse a data blob for a key as an X509 certificate. >>>> */ >>>> static int x509_key_preparse(struct key_preparsed_payload *prep) >>>> @@ -155,9 +233,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 { >>>> + ret = x509_validate_trust(cert, get_system_trusted_keyring()); >>>> + if (!ret) >>>> + prep->trusted = 1; >> Actually this can be like this >> >>>> + } else if (!prep->trusted) >>>> + ret = x509_validate_trust(cert, >> get_system_trusted_keyring()); >>>> + if (!ret) >>>> + prep->trusted = 1; >>>> } > Fine > > Mimi > >>>> /* Propose a description */ >>>> diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h >>>> index 8dabc39..72665eb 100644 >>>> --- a/include/keys/system_keyring.h >>>> +++ b/include/keys/system_keyring.h >>>> @@ -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 */ >>>> -- >>>> 1.8.1.4 >>>> >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in >>>> the body of a message to majordomo@vger.kernel.org >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > -- > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
|  |