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