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 27static bool use_builtin_keys; 28static struct asymmetric_key_id *ca_keyid; 29 30#ifndef MODULE 31static struct { 32 struct asymmetric_key_id id; 33 unsigned char data[10]; 34} cakey; 35 36static int __init ca_keys_setup(char *str) 37{ 38 if (!str) /* default system keyring */ 39 return 1; 40 41 if (strncmp(str, "id:", 3) == 0) { 42 struct asymmetric_key_id *p = &cakey.id; 43 size_t hexlen = (strlen(str) - 3) / 2; 44 int ret; 45 46 if (hexlen == 0 || hexlen > sizeof(cakey.data)) { 47 pr_err("Missing or invalid ca_keys id\n"); 48 return 1; 49 } 50 51 ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); 52 if (ret < 0) 53 pr_err("Unparsable ca_keys id hex string\n"); 54 else 55 ca_keyid = p; /* owner key 'id:xxxxxx' */ 56 } else if (strcmp(str, "builtin") == 0) { 57 use_builtin_keys = true; 58 } 59 60 return 1; 61} 62__setup("ca_keys=", ca_keys_setup); 63#endif 64 65/** 66 * x509_request_asymmetric_key - Request a key by X.509 certificate params. 67 * @keyring: The keys to search. 68 * @kid: The key ID. 69 * @partial: Use partial match if true, exact if false. 70 * 71 * Find a key in the given keyring by subject name and key ID. These might, 72 * for instance, be the issuer name and the authority key ID of an X.509 73 * certificate that needs to be verified. 74 */ 75struct key *x509_request_asymmetric_key(struct key *keyring, 76 const struct asymmetric_key_id *kid, 77 bool partial) 78{ 79 key_ref_t key; 80 char *id, *p; 81 82 /* Construct an identifier "id:<keyid>". */ 83 p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); 84 if (!id) 85 return ERR_PTR(-ENOMEM); 86 87 if (partial) { 88 *p++ = 'i'; 89 *p++ = 'd'; 90 } else { 91 *p++ = 'e'; 92 *p++ = 'x'; 93 } 94 *p++ = ':'; 95 p = bin2hex(p, kid->data, kid->len); 96 *p = 0; 97 98 pr_debug("Look up: \"%s\"\n", id); 99 100 key = keyring_search(make_key_ref(keyring, 1), 101 &key_type_asymmetric, id); 102 if (IS_ERR(key)) 103 pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key)); 104 kfree(id); 105 106 if (IS_ERR(key)) { 107 switch (PTR_ERR(key)) { 108 /* Hide some search errors */ 109 case -EACCES: 110 case -ENOTDIR: 111 case -EAGAIN: 112 return ERR_PTR(-ENOKEY); 113 default: 114 return ERR_CAST(key); 115 } 116 } 117 118 pr_devel("<==%s() = 0 [%x]\n", __func__, 119 key_serial(key_ref_to_ptr(key))); 120 return key_ref_to_ptr(key); 121} 122EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); 123 124/* 125 * Set up the signature parameters in an X.509 certificate. This involves 126 * digesting the signed data and extracting the signature. 127 */ 128int x509_get_sig_params(struct x509_certificate *cert) 129{ 130 struct crypto_shash *tfm; 131 struct shash_desc *desc; 132 size_t digest_size, desc_size; 133 void *digest; 134 int ret; 135 136 pr_devel("==>%s()\n", __func__); 137 138 if (cert->unsupported_crypto) 139 return -ENOPKG; 140 if (cert->sig.rsa.s) 141 return 0; 142 143 cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); 144 if (!cert->sig.rsa.s) 145 return -ENOMEM; 146 cert->sig.nr_mpi = 1; 147 148 /* Allocate the hashing algorithm we're going to need and find out how 149 * big the hash operational data will be. 150 */ 151 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); 152 if (IS_ERR(tfm)) { 153 if (PTR_ERR(tfm) == -ENOENT) { 154 cert->unsupported_crypto = true; 155 return -ENOPKG; 156 } 157 return PTR_ERR(tfm); 158 } 159 160 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 161 digest_size = crypto_shash_digestsize(tfm); 162 163 /* We allocate the hash operational data storage on the end of the 164 * digest storage space. 165 */ 166 ret = -ENOMEM; 167 digest = kzalloc(digest_size + desc_size, GFP_KERNEL); 168 if (!digest) 169 goto error; 170 171 cert->sig.digest = digest; 172 cert->sig.digest_size = digest_size; 173 174 desc = digest + digest_size; 175 desc->tfm = tfm; 176 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 177 178 ret = crypto_shash_init(desc); 179 if (ret < 0) 180 goto error; 181 might_sleep(); 182 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); 183error: 184 crypto_free_shash(tfm); 185 pr_devel("<==%s() = %d\n", __func__, ret); 186 return ret; 187} 188EXPORT_SYMBOL_GPL(x509_get_sig_params); 189 190/* 191 * Check the signature on a certificate using the provided public key 192 */ 193int x509_check_signature(const struct public_key *pub, 194 struct x509_certificate *cert) 195{ 196 int ret; 197 198 pr_devel("==>%s()\n", __func__); 199 200 ret = x509_get_sig_params(cert); 201 if (ret < 0) 202 return ret; 203 204 ret = public_key_verify_signature(pub, &cert->sig); 205 if (ret == -ENOPKG) 206 cert->unsupported_crypto = true; 207 pr_debug("Cert Verification: %d\n", ret); 208 return ret; 209} 210EXPORT_SYMBOL_GPL(x509_check_signature); 211 212/* 213 * Check the new certificate against the ones in the trust keyring. If one of 214 * those is the signing key and validates the new certificate, then mark the 215 * new certificate as being trusted. 216 * 217 * Return 0 if the new certificate was successfully validated, 1 if we couldn't 218 * find a matching parent certificate in the trusted list and an error if there 219 * is a matching certificate but the signature check fails. 220 */ 221static int x509_validate_trust(struct x509_certificate *cert, 222 struct key *trust_keyring) 223{ 224 struct key *key; 225 int ret = 1; 226 227 if (!trust_keyring) 228 return -EOPNOTSUPP; 229 230 if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) 231 return -EPERM; 232 233 key = x509_request_asymmetric_key(trust_keyring, cert->akid_skid, 234 false); 235 if (!IS_ERR(key)) { 236 if (!use_builtin_keys 237 || test_bit(KEY_FLAG_BUILTIN, &key->flags)) 238 ret = x509_check_signature(key->payload.data, cert); 239 key_put(key); 240 } 241 return ret; 242} 243 244/* 245 * Attempt to parse a data blob for a key as an X509 certificate. 246 */ 247static int x509_key_preparse(struct key_preparsed_payload *prep) 248{ 249 struct asymmetric_key_ids *kids; 250 struct x509_certificate *cert; 251 const char *q; 252 size_t srlen, sulen; 253 char *desc = NULL, *p; 254 int ret; 255 256 cert = x509_cert_parse(prep->data, prep->datalen); 257 if (IS_ERR(cert)) 258 return PTR_ERR(cert); 259 260 pr_devel("Cert Issuer: %s\n", cert->issuer); 261 pr_devel("Cert Subject: %s\n", cert->subject); 262 263 if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || 264 cert->sig.pkey_algo >= PKEY_ALGO__LAST || 265 cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || 266 !pkey_algo[cert->pub->pkey_algo] || 267 !pkey_algo[cert->sig.pkey_algo] || 268 !hash_algo_name[cert->sig.pkey_hash_algo]) { 269 ret = -ENOPKG; 270 goto error_free_cert; 271 } 272 273 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); 274 pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); 275 pr_devel("Cert Signature: %s + %s\n", 276 pkey_algo_name[cert->sig.pkey_algo], 277 hash_algo_name[cert->sig.pkey_hash_algo]); 278 279 cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; 280 cert->pub->id_type = PKEY_ID_X509; 281 282 /* Check the signature on the key if it appears to be self-signed */ 283 if (!cert->akid_skid || 284 asymmetric_key_id_same(cert->skid, cert->akid_skid)) { 285 ret = x509_check_signature(cert->pub, cert); /* self-signed */ 286 if (ret < 0) 287 goto error_free_cert; 288 } else if (!prep->trusted) { 289 ret = x509_validate_trust(cert, get_system_trusted_keyring()); 290 if (!ret) 291 prep->trusted = 1; 292 } 293 294 /* Propose a description */ 295 sulen = strlen(cert->subject); 296 if (cert->raw_skid) { 297 srlen = cert->raw_skid_size; 298 q = cert->raw_skid; 299 } else { 300 srlen = cert->raw_serial_size; 301 q = cert->raw_serial; 302 } 303 304 ret = -ENOMEM; 305 desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); 306 if (!desc) 307 goto error_free_cert; 308 p = memcpy(desc, cert->subject, sulen); 309 p += sulen; 310 *p++ = ':'; 311 *p++ = ' '; 312 p = bin2hex(p, q, srlen); 313 *p = 0; 314 315 kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL); 316 if (!kids) 317 goto error_free_desc; 318 kids->id[0] = cert->id; 319 kids->id[1] = cert->skid; 320 321 /* We're pinning the module by being linked against it */ 322 __module_get(public_key_subtype.owner); 323 prep->type_data[0] = &public_key_subtype; 324 prep->type_data[1] = kids; 325 prep->payload[0] = cert->pub; 326 prep->description = desc; 327 prep->quotalen = 100; 328 329 /* We've finished with the certificate */ 330 cert->pub = NULL; 331 cert->id = NULL; 332 cert->skid = NULL; 333 desc = NULL; 334 ret = 0; 335 336error_free_desc: 337 kfree(desc); 338error_free_cert: 339 x509_free_certificate(cert); 340 return ret; 341} 342 343static struct asymmetric_key_parser x509_key_parser = { 344 .owner = THIS_MODULE, 345 .name = "x509", 346 .parse = x509_key_preparse, 347}; 348 349/* 350 * Module stuff 351 */ 352static int __init x509_key_init(void) 353{ 354 return register_asymmetric_key_parser(&x509_key_parser); 355} 356 357static void __exit x509_key_exit(void) 358{ 359 unregister_asymmetric_key_parser(&x509_key_parser); 360} 361 362module_init(x509_key_init); 363module_exit(x509_key_exit); 364 365MODULE_DESCRIPTION("X.509 certificate parser"); 366MODULE_LICENSE("GPL"); 367