Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KEYS: verify a certificate is signed by a 'trusted' key

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.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: David Howells <dhowells@redhat.com>

authored by

Mimi Zohar and committed by
David Howells
09fbc473 af34cb0c

+80 -1
+80 -1
crypto/asymmetric_keys/x509_public_key.c
··· 18 18 #include <linux/asn1_decoder.h> 19 19 #include <keys/asymmetric-subtype.h> 20 20 #include <keys/asymmetric-parser.h> 21 + #include <keys/system_keyring.h> 21 22 #include <crypto/hash.h> 22 23 #include "asymmetric_keys.h" 23 24 #include "public_key.h" 24 25 #include "x509_parser.h" 26 + 27 + /* 28 + * Find a key in the given keyring by issuer and authority. 29 + */ 30 + static struct key *x509_request_asymmetric_key( 31 + struct key *keyring, 32 + const char *signer, size_t signer_len, 33 + const char *authority, size_t auth_len) 34 + { 35 + key_ref_t key; 36 + char *id; 37 + 38 + /* Construct an identifier. */ 39 + id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); 40 + if (!id) 41 + return ERR_PTR(-ENOMEM); 42 + 43 + memcpy(id, signer, signer_len); 44 + id[signer_len + 0] = ':'; 45 + id[signer_len + 1] = ' '; 46 + memcpy(id + signer_len + 2, authority, auth_len); 47 + id[signer_len + 2 + auth_len] = 0; 48 + 49 + pr_debug("Look up: \"%s\"\n", id); 50 + 51 + key = keyring_search(make_key_ref(keyring, 1), 52 + &key_type_asymmetric, id); 53 + if (IS_ERR(key)) 54 + pr_debug("Request for module key '%s' err %ld\n", 55 + id, PTR_ERR(key)); 56 + kfree(id); 57 + 58 + if (IS_ERR(key)) { 59 + switch (PTR_ERR(key)) { 60 + /* Hide some search errors */ 61 + case -EACCES: 62 + case -ENOTDIR: 63 + case -EAGAIN: 64 + return ERR_PTR(-ENOKEY); 65 + default: 66 + return ERR_CAST(key); 67 + } 68 + } 69 + 70 + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); 71 + return key_ref_to_ptr(key); 72 + } 25 73 26 74 /* 27 75 * Set up the signature parameters in an X.509 certificate. This involves ··· 151 103 EXPORT_SYMBOL_GPL(x509_check_signature); 152 104 153 105 /* 106 + * Check the new certificate against the ones in the trust keyring. If one of 107 + * those is the signing key and validates the new certificate, then mark the 108 + * new certificate as being trusted. 109 + * 110 + * Return 0 if the new certificate was successfully validated, 1 if we couldn't 111 + * find a matching parent certificate in the trusted list and an error if there 112 + * is a matching certificate but the signature check fails. 113 + */ 114 + static int x509_validate_trust(struct x509_certificate *cert, 115 + struct key *trust_keyring) 116 + { 117 + const struct public_key *pk; 118 + struct key *key; 119 + int ret = 1; 120 + 121 + key = x509_request_asymmetric_key(trust_keyring, 122 + cert->issuer, strlen(cert->issuer), 123 + cert->authority, 124 + strlen(cert->authority)); 125 + if (!IS_ERR(key)) { 126 + pk = key->payload.data; 127 + ret = x509_check_signature(pk, cert); 128 + } 129 + return ret; 130 + } 131 + 132 + /* 154 133 * Attempt to parse a data blob for a key as an X509 certificate. 155 134 */ 156 135 static int x509_key_preparse(struct key_preparsed_payload *prep) ··· 230 155 /* Check the signature on the key if it appears to be self-signed */ 231 156 if (!cert->authority || 232 157 strcmp(cert->fingerprint, cert->authority) == 0) { 233 - ret = x509_check_signature(cert->pub, cert); 158 + ret = x509_check_signature(cert->pub, cert); /* self-signed */ 234 159 if (ret < 0) 235 160 goto error_free_cert; 161 + } else { 162 + ret = x509_validate_trust(cert, system_trusted_keyring); 163 + if (!ret) 164 + prep->trusted = 1; 236 165 } 237 166 238 167 /* Propose a description */