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 <keys/system_keyring.h>
22 #include <crypto/hash.h>
23 #include "asymmetric_keys.h"
24 #include "public_key.h"
25 #include "x509_parser.h"
27 static bool use_builtin_keys
;
28 static char *ca_keyid
;
31 static int __init
ca_keys_setup(char *str
)
33 if (!str
) /* default system keyring */
36 if (strncmp(str
, "id:", 3) == 0)
37 ca_keyid
= str
; /* owner key 'id:xxxxxx' */
38 else if (strcmp(str
, "builtin") == 0)
39 use_builtin_keys
= true;
43 __setup("ca_keys=", ca_keys_setup
);
47 * x509_request_asymmetric_key - Request a key by X.509 certificate params.
48 * @keyring: The keys to search.
49 * @subject: The name of the subject to whom the key belongs.
50 * @key_id: The subject key ID as a hex string.
52 * Find a key in the given keyring by subject name and key ID. These might,
53 * for instance, be the issuer name and the authority key ID of an X.509
54 * certificate that needs to be verified.
56 struct key
*x509_request_asymmetric_key(struct key
*keyring
,
61 size_t subject_len
= strlen(subject
), key_id_len
= strlen(key_id
);
64 /* Construct an identifier "<subjname>:<keyid>". */
65 id
= kmalloc(subject_len
+ 2 + key_id_len
+ 1, GFP_KERNEL
);
67 return ERR_PTR(-ENOMEM
);
69 memcpy(id
, subject
, subject_len
);
70 id
[subject_len
+ 0] = ':';
71 id
[subject_len
+ 1] = ' ';
72 memcpy(id
+ subject_len
+ 2, key_id
, key_id_len
);
73 id
[subject_len
+ 2 + key_id_len
] = 0;
75 pr_debug("Look up: \"%s\"\n", id
);
77 key
= keyring_search(make_key_ref(keyring
, 1),
78 &key_type_asymmetric
, id
);
80 pr_debug("Request for key '%s' err %ld\n", id
, PTR_ERR(key
));
84 switch (PTR_ERR(key
)) {
85 /* Hide some search errors */
89 return ERR_PTR(-ENOKEY
);
95 pr_devel("<==%s() = 0 [%x]\n", __func__
,
96 key_serial(key_ref_to_ptr(key
)));
97 return key_ref_to_ptr(key
);
99 EXPORT_SYMBOL_GPL(x509_request_asymmetric_key
);
102 * Set up the signature parameters in an X.509 certificate. This involves
103 * digesting the signed data and extracting the signature.
105 int x509_get_sig_params(struct x509_certificate
*cert
)
107 struct crypto_shash
*tfm
;
108 struct shash_desc
*desc
;
109 size_t digest_size
, desc_size
;
113 pr_devel("==>%s()\n", __func__
);
118 cert
->sig
.rsa
.s
= mpi_read_raw_data(cert
->raw_sig
, cert
->raw_sig_size
);
119 if (!cert
->sig
.rsa
.s
)
121 cert
->sig
.nr_mpi
= 1;
123 /* Allocate the hashing algorithm we're going to need and find out how
124 * big the hash operational data will be.
126 tfm
= crypto_alloc_shash(hash_algo_name
[cert
->sig
.pkey_hash_algo
], 0, 0);
128 return (PTR_ERR(tfm
) == -ENOENT
) ? -ENOPKG
: PTR_ERR(tfm
);
130 desc_size
= crypto_shash_descsize(tfm
) + sizeof(*desc
);
131 digest_size
= crypto_shash_digestsize(tfm
);
133 /* We allocate the hash operational data storage on the end of the
134 * digest storage space.
137 digest
= kzalloc(digest_size
+ desc_size
, GFP_KERNEL
);
141 cert
->sig
.digest
= digest
;
142 cert
->sig
.digest_size
= digest_size
;
144 desc
= digest
+ digest_size
;
146 desc
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
148 ret
= crypto_shash_init(desc
);
152 ret
= crypto_shash_finup(desc
, cert
->tbs
, cert
->tbs_size
, digest
);
154 crypto_free_shash(tfm
);
155 pr_devel("<==%s() = %d\n", __func__
, ret
);
158 EXPORT_SYMBOL_GPL(x509_get_sig_params
);
161 * Check the signature on a certificate using the provided public key
163 int x509_check_signature(const struct public_key
*pub
,
164 struct x509_certificate
*cert
)
168 pr_devel("==>%s()\n", __func__
);
170 ret
= x509_get_sig_params(cert
);
174 ret
= public_key_verify_signature(pub
, &cert
->sig
);
175 pr_debug("Cert Verification: %d\n", ret
);
178 EXPORT_SYMBOL_GPL(x509_check_signature
);
181 * Check the new certificate against the ones in the trust keyring. If one of
182 * those is the signing key and validates the new certificate, then mark the
183 * new certificate as being trusted.
185 * Return 0 if the new certificate was successfully validated, 1 if we couldn't
186 * find a matching parent certificate in the trusted list and an error if there
187 * is a matching certificate but the signature check fails.
189 static int x509_validate_trust(struct x509_certificate
*cert
,
190 struct key
*trust_keyring
)
198 if (ca_keyid
&& !asymmetric_keyid_match(cert
->authority
, ca_keyid
))
201 key
= x509_request_asymmetric_key(trust_keyring
,
202 cert
->issuer
, cert
->authority
);
204 if (!use_builtin_keys
205 || test_bit(KEY_FLAG_BUILTIN
, &key
->flags
))
206 ret
= x509_check_signature(key
->payload
.data
, cert
);
213 * Attempt to parse a data blob for a key as an X509 certificate.
215 static int x509_key_preparse(struct key_preparsed_payload
*prep
)
217 struct x509_certificate
*cert
;
222 cert
= x509_cert_parse(prep
->data
, prep
->datalen
);
224 return PTR_ERR(cert
);
226 pr_devel("Cert Issuer: %s\n", cert
->issuer
);
227 pr_devel("Cert Subject: %s\n", cert
->subject
);
229 if (cert
->pub
->pkey_algo
>= PKEY_ALGO__LAST
||
230 cert
->sig
.pkey_algo
>= PKEY_ALGO__LAST
||
231 cert
->sig
.pkey_hash_algo
>= PKEY_HASH__LAST
||
232 !pkey_algo
[cert
->pub
->pkey_algo
] ||
233 !pkey_algo
[cert
->sig
.pkey_algo
] ||
234 !hash_algo_name
[cert
->sig
.pkey_hash_algo
]) {
236 goto error_free_cert
;
239 pr_devel("Cert Key Algo: %s\n", pkey_algo_name
[cert
->pub
->pkey_algo
]);
240 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
241 cert
->valid_from
.tm_year
+ 1900, cert
->valid_from
.tm_mon
+ 1,
242 cert
->valid_from
.tm_mday
, cert
->valid_from
.tm_hour
,
243 cert
->valid_from
.tm_min
, cert
->valid_from
.tm_sec
);
244 pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n",
245 cert
->valid_to
.tm_year
+ 1900, cert
->valid_to
.tm_mon
+ 1,
246 cert
->valid_to
.tm_mday
, cert
->valid_to
.tm_hour
,
247 cert
->valid_to
.tm_min
, cert
->valid_to
.tm_sec
);
248 pr_devel("Cert Signature: %s + %s\n",
249 pkey_algo_name
[cert
->sig
.pkey_algo
],
250 hash_algo_name
[cert
->sig
.pkey_hash_algo
]);
252 if (!cert
->fingerprint
) {
253 pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
256 goto error_free_cert
;
259 cert
->pub
->algo
= pkey_algo
[cert
->pub
->pkey_algo
];
260 cert
->pub
->id_type
= PKEY_ID_X509
;
262 /* Check the signature on the key if it appears to be self-signed */
263 if (!cert
->authority
||
264 strcmp(cert
->fingerprint
, cert
->authority
) == 0) {
265 ret
= x509_check_signature(cert
->pub
, cert
); /* self-signed */
267 goto error_free_cert
;
268 } else if (!prep
->trusted
) {
269 ret
= x509_validate_trust(cert
, get_system_trusted_keyring());
274 /* Propose a description */
275 sulen
= strlen(cert
->subject
);
276 srlen
= strlen(cert
->fingerprint
);
278 desc
= kmalloc(sulen
+ 2 + srlen
+ 1, GFP_KERNEL
);
280 goto error_free_cert
;
281 memcpy(desc
, cert
->subject
, sulen
);
283 desc
[sulen
+ 1] = ' ';
284 memcpy(desc
+ sulen
+ 2, cert
->fingerprint
, srlen
);
285 desc
[sulen
+ 2 + srlen
] = 0;
287 /* We're pinning the module by being linked against it */
288 __module_get(public_key_subtype
.owner
);
289 prep
->type_data
[0] = &public_key_subtype
;
290 prep
->type_data
[1] = cert
->fingerprint
;
291 prep
->payload
[0] = cert
->pub
;
292 prep
->description
= desc
;
293 prep
->quotalen
= 100;
295 /* We've finished with the certificate */
297 cert
->fingerprint
= NULL
;
302 x509_free_certificate(cert
);
306 static struct asymmetric_key_parser x509_key_parser
= {
307 .owner
= THIS_MODULE
,
309 .parse
= x509_key_preparse
,
315 static int __init
x509_key_init(void)
317 return register_asymmetric_key_parser(&x509_key_parser
);
320 static void __exit
x509_key_exit(void)
322 unregister_asymmetric_key_parser(&x509_key_parser
);
325 module_init(x509_key_init
);
326 module_exit(x509_key_exit
);
328 MODULE_DESCRIPTION("X.509 certificate parser");
329 MODULE_LICENSE("GPL");