1 /* Instantiate a public key crypto key from an X.509 Certificate 2 * 3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12 #define pr_fmt(fmt) "X.509: "fmt 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/slab.h> 16 #include <linux/err.h> 17 #include <linux/mpi.h> 18 #include <linux/asn1_decoder.h> 19 #include <keys/asymmetric-subtype.h> 20 #include <keys/asymmetric-parser.h> 21 #include <keys/system_keyring.h> 22 #include <crypto/hash.h> 23 #include "asymmetric_keys.h" 24 #include "public_key.h" 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 } 73 74 /* 75 * Set up the signature parameters in an X.509 certificate. This involves 76 * digesting the signed data and extracting the signature. 77 */ 78 int x509_get_sig_params(struct x509_certificate *cert) 79 { 80 struct crypto_shash *tfm; 81 struct shash_desc *desc; 82 size_t digest_size, desc_size; 83 void *digest; 84 int ret; 85 86 pr_devel("==>%s()\n", __func__); 87 88 if (cert->sig.rsa.s) 89 return 0; 90 91 cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); 92 if (!cert->sig.rsa.s) 93 return -ENOMEM; 94 cert->sig.nr_mpi = 1; 95 96 /* Allocate the hashing algorithm we're going to need and find out how 97 * big the hash operational data will be. 98 */ 99 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); 100 if (IS_ERR(tfm)) 101 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 102 103 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 104 digest_size = crypto_shash_digestsize(tfm); 105 106 /* We allocate the hash operational data storage on the end of the 107 * digest storage space. 108 */ 109 ret = -ENOMEM; 110 digest = kzalloc(digest_size + desc_size, GFP_KERNEL); 111 if (!digest) 112 goto error; 113 114 cert->sig.digest = digest; 115 cert->sig.digest_size = digest_size; 116 117 desc = digest + digest_size; 118 desc->tfm = tfm; 119 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 120 121 ret = crypto_shash_init(desc); 122 if (ret < 0) 123 goto error; 124 might_sleep(); 125 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); 126 error: 127 crypto_free_shash(tfm); 128 pr_devel("<==%s() = %d\n", __func__, ret); 129 return ret; 130 } 131 EXPORT_SYMBOL_GPL(x509_get_sig_params); 132 133 /* 134 * Check the signature on a certificate using the provided public key 135 */ 136 int x509_check_signature(const struct public_key *pub, 137 struct x509_certificate *cert) 138 { 139 int ret; 140 141 pr_devel("==>%s()\n", __func__); 142 143 ret = x509_get_sig_params(cert); 144 if (ret < 0) 145 return ret; 146 147 ret = public_key_verify_signature(pub, &cert->sig); 148 pr_debug("Cert Verification: %d\n", ret); 149 return ret; 150 } 151 EXPORT_SYMBOL_GPL(x509_check_signature); 152 153 /* 154 * Check the new certificate against the ones in the trust keyring. If one of 155 * those is the signing key and validates the new certificate, then mark the 156 * new certificate as being trusted. 157 * 158 * Return 0 if the new certificate was successfully validated, 1 if we couldn't 159 * find a matching parent certificate in the trusted list and an error if there 160 * is a matching certificate but the signature check fails. 161 */ 162 static int x509_validate_trust(struct x509_certificate *cert, 163 struct key *trust_keyring) 164 { 165 const struct public_key *pk; 166 struct key *key; 167 int ret = 1; 168 169 key = x509_request_asymmetric_key(trust_keyring, 170 cert->issuer, strlen(cert->issuer), 171 cert->authority, 172 strlen(cert->authority)); 173 if (!IS_ERR(key)) { 174 pk = key->payload.data; 175 ret = x509_check_signature(pk, cert); 176 } 177 return ret; 178 } 179 180 /* 181 * Attempt to parse a data blob for a key as an X509 certificate. 182 */ 183 static int x509_key_preparse(struct key_preparsed_payload *prep) 184 { 185 struct x509_certificate *cert; 186 size_t srlen, sulen; 187 char *desc = NULL; 188 int ret; 189 190 cert = x509_cert_parse(prep->data, prep->datalen); 191 if (IS_ERR(cert)) 192 return PTR_ERR(cert); 193 194 pr_devel("Cert Issuer: %s\n", cert->issuer); 195 pr_devel("Cert Subject: %s\n", cert->subject); 196 197 if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || 198 cert->sig.pkey_algo >= PKEY_ALGO__LAST || 199 cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || 200 !pkey_algo[cert->pub->pkey_algo] || 201 !pkey_algo[cert->sig.pkey_algo] || 202 !hash_algo_name[cert->sig.pkey_hash_algo]) { 203 ret = -ENOPKG; 204 goto error_free_cert; 205 } 206 207 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); 208 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", 209 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, 210 cert->valid_from.tm_mday, cert->valid_from.tm_hour, 211 cert->valid_from.tm_min, cert->valid_from.tm_sec); 212 pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", 213 cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, 214 cert->valid_to.tm_mday, cert->valid_to.tm_hour, 215 cert->valid_to.tm_min, cert->valid_to.tm_sec); 216 pr_devel("Cert Signature: %s + %s\n", 217 pkey_algo_name[cert->sig.pkey_algo], 218 hash_algo_name[cert->sig.pkey_hash_algo]); 219 220 if (!cert->fingerprint) { 221 pr_warn("Cert for '%s' must have a SubjKeyId extension\n", 222 cert->subject); 223 ret = -EKEYREJECTED; 224 goto error_free_cert; 225 } 226 227 cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; 228 cert->pub->id_type = PKEY_ID_X509; 229 230 /* Check the signature on the key if it appears to be self-signed */ 231 if (!cert->authority || 232 strcmp(cert->fingerprint, cert->authority) == 0) { 233 ret = x509_check_signature(cert->pub, cert); /* self-signed */ 234 if (ret < 0) 235 goto error_free_cert; 236 } else { 237 ret = x509_validate_trust(cert, system_trusted_keyring); 238 if (!ret) 239 prep->trusted = 1; 240 } 241 242 /* Propose a description */ 243 sulen = strlen(cert->subject); 244 srlen = strlen(cert->fingerprint); 245 ret = -ENOMEM; 246 desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); 247 if (!desc) 248 goto error_free_cert; 249 memcpy(desc, cert->subject, sulen); 250 desc[sulen] = ':'; 251 desc[sulen + 1] = ' '; 252 memcpy(desc + sulen + 2, cert->fingerprint, srlen); 253 desc[sulen + 2 + srlen] = 0; 254 255 /* We're pinning the module by being linked against it */ 256 __module_get(public_key_subtype.owner); 257 prep->type_data[0] = &public_key_subtype; 258 prep->type_data[1] = cert->fingerprint; 259 prep->payload = cert->pub; 260 prep->description = desc; 261 prep->quotalen = 100; 262 263 /* We've finished with the certificate */ 264 cert->pub = NULL; 265 cert->fingerprint = NULL; 266 desc = NULL; 267 ret = 0; 268 269 error_free_cert: 270 x509_free_certificate(cert); 271 return ret; 272 } 273 274 static struct asymmetric_key_parser x509_key_parser = { 275 .owner = THIS_MODULE, 276 .name = "x509", 277 .parse = x509_key_preparse, 278 }; 279 280 /* 281 * Module stuff 282 */ 283 static int __init x509_key_init(void) 284 { 285 return register_asymmetric_key_parser(&x509_key_parser); 286 } 287 288 static void __exit x509_key_exit(void) 289 { 290 unregister_asymmetric_key_parser(&x509_key_parser); 291 } 292 293 module_init(x509_key_init); 294 module_exit(x509_key_exit); 295 296 MODULE_DESCRIPTION("X.509 certificate parser"); 297 MODULE_LICENSE("GPL"); 298