1 /* Instantiate a public key crypto key from an X.509 Certificate
3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
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"
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
,
36 * Check the signature on a certificate using the provided public key
38 static int x509_check_signature(const struct public_key
*pub
,
39 const struct x509_certificate
*cert
)
41 struct public_key_signature
*sig
;
42 struct crypto_shash
*tfm
;
43 struct shash_desc
*desc
;
44 size_t digest_size
, desc_size
;
47 pr_devel("==>%s()\n", __func__
);
49 /* Allocate the hashing algorithm we're going to need and find out how
50 * big the hash operational data will be.
52 tfm
= crypto_alloc_shash(pkey_hash_algo
[cert
->sig_hash_algo
], 0, 0);
54 return (PTR_ERR(tfm
) == -ENOENT
) ? -ENOPKG
: PTR_ERR(tfm
);
56 desc_size
= crypto_shash_descsize(tfm
) + sizeof(*desc
);
57 digest_size
= crypto_shash_digestsize(tfm
);
59 /* We allocate the hash operational data storage on the end of our
63 sig
= kzalloc(sizeof(*sig
) + desc_size
+ digest_size
, GFP_KERNEL
);
67 sig
->pkey_hash_algo
= cert
->sig_hash_algo
;
68 sig
->digest
= (u8
*)sig
+ sizeof(*sig
) + desc_size
;
69 sig
->digest_size
= digest_size
;
71 desc
= (void *)sig
+ sizeof(*sig
);
73 desc
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
75 ret
= crypto_shash_init(desc
);
80 sig
->rsa
.s
= mpi_read_raw_data(cert
->sig
, cert
->sig_size
);
84 ret
= crypto_shash_finup(desc
, cert
->tbs
, cert
->tbs_size
, sig
->digest
);
88 ret
= pub
->algo
->verify_signature(pub
, sig
);
90 pr_debug("Cert Verification: %d\n", ret
);
97 crypto_free_shash(tfm
);
99 pr_devel("<==%s() = %d\n", __func__
, ret
);
104 * Attempt to parse a data blob for a key as an X509 certificate.
106 static int x509_key_preparse(struct key_preparsed_payload
*prep
)
108 struct x509_certificate
*cert
;
114 cert
= x509_cert_parse(prep
->data
, prep
->datalen
);
116 return PTR_ERR(cert
);
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
]);
133 if (!cert
->fingerprint
|| !cert
->authority
) {
134 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
137 goto error_free_cert
;
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
156 pr_warn("Cert %s is not yet valid\n", cert
->fingerprint
);
158 goto error_free_cert
;
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
172 pr_warn("Cert %s has expired\n", cert
->fingerprint
);
174 goto error_free_cert
;
177 cert
->pub
->algo
= x509_public_key_algorithms
[cert
->pkey_algo
];
178 cert
->pub
->id_type
= PKEY_ID_X509
;
180 /* Check the signature on the key */
181 if (strcmp(cert
->fingerprint
, cert
->authority
) == 0) {
182 ret
= x509_check_signature(cert
->pub
, cert
);
184 goto error_free_cert
;
187 /* Propose a description */
188 sulen
= strlen(cert
->subject
);
189 srlen
= strlen(cert
->fingerprint
);
191 desc
= kmalloc(sulen
+ 2 + srlen
+ 1, GFP_KERNEL
);
193 goto error_free_cert
;
194 memcpy(desc
, cert
->subject
, sulen
);
196 desc
[sulen
+ 1] = ' ';
197 memcpy(desc
+ sulen
+ 2, cert
->fingerprint
, srlen
);
198 desc
[sulen
+ 2 + srlen
] = 0;
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;
208 /* We've finished with the certificate */
210 cert
->fingerprint
= NULL
;
215 x509_free_certificate(cert
);
219 static struct asymmetric_key_parser x509_key_parser
= {
220 .owner
= THIS_MODULE
,
222 .parse
= x509_key_preparse
,
228 static int __init
x509_key_init(void)
230 return register_asymmetric_key_parser(&x509_key_parser
);
233 static void __exit
x509_key_exit(void)
235 unregister_asymmetric_key_parser(&x509_key_parser
);
238 module_init(x509_key_init
);
239 module_exit(x509_key_exit
);