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