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 <crypto/hash.h> 22 #include "asymmetric_keys.h" 23 #include "public_key.h" 24 #include "x509_parser.h" 25 26 static const 27 struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { 28 [PKEY_ALGO_DSA] = NULL, 29 #if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ 30 defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) 31 [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, 32 #endif 33 }; 34 35 /* 36 * Check the signature on a certificate using the provided public key 37 */ 38 static int x509_check_signature(const struct public_key *pub, 39 const struct x509_certificate *cert) 40 { 41 struct public_key_signature *sig; 42 struct crypto_shash *tfm; 43 struct shash_desc *desc; 44 size_t digest_size, desc_size; 45 int ret; 46 47 pr_devel("==>%s()\n", __func__); 48 49 /* Allocate the hashing algorithm we're going to need and find out how 50 * big the hash operational data will be. 51 */ 52 tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); 53 if (IS_ERR(tfm)) 54 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 55 56 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 57 digest_size = crypto_shash_digestsize(tfm); 58 59 /* We allocate the hash operational data storage on the end of our 60 * context data. 61 */ 62 ret = -ENOMEM; 63 sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); 64 if (!sig) 65 goto error_no_sig; 66 67 sig->pkey_hash_algo = cert->sig_hash_algo; 68 sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; 69 sig->digest_size = digest_size; 70 71 desc = (void *)sig + sizeof(*sig); 72 desc->tfm = tfm; 73 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 74 75 ret = crypto_shash_init(desc); 76 if (ret < 0) 77 goto error; 78 79 ret = -ENOMEM; 80 sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); 81 if (!sig->rsa.s) 82 goto error; 83 84 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); 85 if (ret < 0) 86 goto error_mpi; 87 88 ret = pub->algo->verify_signature(pub, sig); 89 90 pr_debug("Cert Verification: %d\n", ret); 91 92 error_mpi: 93 mpi_free(sig->rsa.s); 94 error: 95 kfree(sig); 96 error_no_sig: 97 crypto_free_shash(tfm); 98 99 pr_devel("<==%s() = %d\n", __func__, ret); 100 return ret; 101 } 102 103 /* 104 * Attempt to parse a data blob for a key as an X509 certificate. 105 */ 106 static int x509_key_preparse(struct key_preparsed_payload *prep) 107 { 108 struct x509_certificate *cert; 109 struct tm now; 110 size_t srlen, sulen; 111 char *desc = NULL; 112 int ret; 113 114 cert = x509_cert_parse(prep->data, prep->datalen); 115 if (IS_ERR(cert)) 116 return PTR_ERR(cert); 117 118 pr_devel("Cert Issuer: %s\n", cert->issuer); 119 pr_devel("Cert Subject: %s\n", cert->subject); 120 pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); 121 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", 122 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, 123 cert->valid_from.tm_mday, cert->valid_from.tm_hour, 124 cert->valid_from.tm_min, cert->valid_from.tm_sec); 125 pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", 126 cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, 127 cert->valid_to.tm_mday, cert->valid_to.tm_hour, 128 cert->valid_to.tm_min, cert->valid_to.tm_sec); 129 pr_devel("Cert Signature: %s + %s\n", 130 pkey_algo[cert->sig_pkey_algo], 131 pkey_hash_algo[cert->sig_hash_algo]); 132 133 if (!cert->fingerprint || !cert->authority) { 134 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", 135 cert->subject); 136 ret = -EKEYREJECTED; 137 goto error_free_cert; 138 } 139 140 time_to_tm(CURRENT_TIME.tv_sec, 0, &now); 141 pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", 142 now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, 143 now.tm_hour, now.tm_min, now.tm_sec); 144 if (now.tm_year < cert->valid_from.tm_year || 145 (now.tm_year == cert->valid_from.tm_year && 146 (now.tm_mon < cert->valid_from.tm_mon || 147 (now.tm_mon == cert->valid_from.tm_mon && 148 (now.tm_mday < cert->valid_from.tm_mday || 149 (now.tm_mday == cert->valid_from.tm_mday && 150 (now.tm_hour < cert->valid_from.tm_hour || 151 (now.tm_hour == cert->valid_from.tm_hour && 152 (now.tm_min < cert->valid_from.tm_min || 153 (now.tm_min == cert->valid_from.tm_min && 154 (now.tm_sec < cert->valid_from.tm_sec 155 ))))))))))) { 156 pr_warn("Cert %s is not yet valid\n", cert->fingerprint); 157 ret = -EKEYREJECTED; 158 goto error_free_cert; 159 } 160 if (now.tm_year > cert->valid_to.tm_year || 161 (now.tm_year == cert->valid_to.tm_year && 162 (now.tm_mon > cert->valid_to.tm_mon || 163 (now.tm_mon == cert->valid_to.tm_mon && 164 (now.tm_mday > cert->valid_to.tm_mday || 165 (now.tm_mday == cert->valid_to.tm_mday && 166 (now.tm_hour > cert->valid_to.tm_hour || 167 (now.tm_hour == cert->valid_to.tm_hour && 168 (now.tm_min > cert->valid_to.tm_min || 169 (now.tm_min == cert->valid_to.tm_min && 170 (now.tm_sec > cert->valid_to.tm_sec 171 ))))))))))) { 172 pr_warn("Cert %s has expired\n", cert->fingerprint); 173 ret = -EKEYEXPIRED; 174 goto error_free_cert; 175 } 176 177 cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; 178 cert->pub->id_type = PKEY_ID_X509; 179 180 /* Check the signature on the key */ 181 if (strcmp(cert->fingerprint, cert->authority) == 0) { 182 ret = x509_check_signature(cert->pub, cert); 183 if (ret < 0) 184 goto error_free_cert; 185 } 186 187 /* Propose a description */ 188 sulen = strlen(cert->subject); 189 srlen = strlen(cert->fingerprint); 190 ret = -ENOMEM; 191 desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); 192 if (!desc) 193 goto error_free_cert; 194 memcpy(desc, cert->subject, sulen); 195 desc[sulen] = ':'; 196 desc[sulen + 1] = ' '; 197 memcpy(desc + sulen + 2, cert->fingerprint, srlen); 198 desc[sulen + 2 + srlen] = 0; 199 200 /* We're pinning the module by being linked against it */ 201 __module_get(public_key_subtype.owner); 202 prep->type_data[0] = &public_key_subtype; 203 prep->type_data[1] = cert->fingerprint; 204 prep->payload = cert->pub; 205 prep->description = desc; 206 prep->quotalen = 100; 207 208 /* We've finished with the certificate */ 209 cert->pub = NULL; 210 cert->fingerprint = NULL; 211 desc = NULL; 212 ret = 0; 213 214 error_free_cert: 215 x509_free_certificate(cert); 216 return ret; 217 } 218 219 static struct asymmetric_key_parser x509_key_parser = { 220 .owner = THIS_MODULE, 221 .name = "x509", 222 .parse = x509_key_preparse, 223 }; 224 225 /* 226 * Module stuff 227 */ 228 static int __init x509_key_init(void) 229 { 230 return register_asymmetric_key_parser(&x509_key_parser); 231 } 232 233 static void __exit x509_key_exit(void) 234 { 235 unregister_asymmetric_key_parser(&x509_key_parser); 236 } 237 238 module_init(x509_key_init); 239 module_exit(x509_key_exit); 240