xref: /openbmc/linux/crypto/asymmetric_keys/x509_public_key.c (revision 6c2dc5ae4ab719a61d19e8cef082226410b04ff8)
1c26fd69fSDavid Howells /* Instantiate a public key crypto key from an X.509 Certificate
2c26fd69fSDavid Howells  *
3c26fd69fSDavid Howells  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4c26fd69fSDavid Howells  * Written by David Howells (dhowells@redhat.com)
5c26fd69fSDavid Howells  *
6c26fd69fSDavid Howells  * This program is free software; you can redistribute it and/or
7c26fd69fSDavid Howells  * modify it under the terms of the GNU General Public Licence
8c26fd69fSDavid Howells  * as published by the Free Software Foundation; either version
9c26fd69fSDavid Howells  * 2 of the Licence, or (at your option) any later version.
10c26fd69fSDavid Howells  */
11c26fd69fSDavid Howells 
12c26fd69fSDavid Howells #define pr_fmt(fmt) "X.509: "fmt
13c26fd69fSDavid Howells #include <linux/module.h>
14c26fd69fSDavid Howells #include <linux/kernel.h>
15c26fd69fSDavid Howells #include <linux/slab.h>
16c26fd69fSDavid Howells #include <keys/asymmetric-subtype.h>
17c26fd69fSDavid Howells #include <keys/asymmetric-parser.h>
183be4beafSMimi Zohar #include <keys/system_keyring.h>
19c26fd69fSDavid Howells #include <crypto/hash.h>
20c26fd69fSDavid Howells #include "asymmetric_keys.h"
21c26fd69fSDavid Howells #include "x509_parser.h"
22c26fd69fSDavid Howells 
2332c4741cSDmitry Kasatkin static bool use_builtin_keys;
2446963b77SDavid Howells static struct asymmetric_key_id *ca_keyid;
25ffb70f61SDmitry Kasatkin 
26ffb70f61SDmitry Kasatkin #ifndef MODULE
27f2b3dee4SMimi Zohar static struct {
28f2b3dee4SMimi Zohar 	struct asymmetric_key_id id;
29f2b3dee4SMimi Zohar 	unsigned char data[10];
30f2b3dee4SMimi Zohar } cakey;
31f2b3dee4SMimi Zohar 
32ffb70f61SDmitry Kasatkin static int __init ca_keys_setup(char *str)
33ffb70f61SDmitry Kasatkin {
34ffb70f61SDmitry Kasatkin 	if (!str)		/* default system keyring */
35ffb70f61SDmitry Kasatkin 		return 1;
36ffb70f61SDmitry Kasatkin 
3746963b77SDavid Howells 	if (strncmp(str, "id:", 3) == 0) {
38f2b3dee4SMimi Zohar 		struct asymmetric_key_id *p = &cakey.id;
39f2b3dee4SMimi Zohar 		size_t hexlen = (strlen(str) - 3) / 2;
40f2b3dee4SMimi Zohar 		int ret;
41f2b3dee4SMimi Zohar 
42f2b3dee4SMimi Zohar 		if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
43f2b3dee4SMimi Zohar 			pr_err("Missing or invalid ca_keys id\n");
44f2b3dee4SMimi Zohar 			return 1;
45f2b3dee4SMimi Zohar 		}
46f2b3dee4SMimi Zohar 
47f2b3dee4SMimi Zohar 		ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
48f2b3dee4SMimi Zohar 		if (ret < 0)
49f2b3dee4SMimi Zohar 			pr_err("Unparsable ca_keys id hex string\n");
50f2b3dee4SMimi Zohar 		else
5146963b77SDavid Howells 			ca_keyid = p;	/* owner key 'id:xxxxxx' */
5246963b77SDavid Howells 	} else if (strcmp(str, "builtin") == 0) {
5332c4741cSDmitry Kasatkin 		use_builtin_keys = true;
5446963b77SDavid Howells 	}
55ffb70f61SDmitry Kasatkin 
56ffb70f61SDmitry Kasatkin 	return 1;
57ffb70f61SDmitry Kasatkin }
58ffb70f61SDmitry Kasatkin __setup("ca_keys=", ca_keys_setup);
59ffb70f61SDmitry Kasatkin #endif
60ffb70f61SDmitry Kasatkin 
615ce43ad2SDavid Howells /**
625ce43ad2SDavid Howells  * x509_request_asymmetric_key - Request a key by X.509 certificate params.
635ce43ad2SDavid Howells  * @keyring: The keys to search.
644573b64aSDavid Howells  * @id: The issuer & serialNumber to look for or NULL.
654573b64aSDavid Howells  * @skid: The subjectKeyIdentifier to look for or NULL.
66f1b731dbSDmitry Kasatkin  * @partial: Use partial match if true, exact if false.
675ce43ad2SDavid Howells  *
684573b64aSDavid Howells  * Find a key in the given keyring by identifier.  The preferred identifier is
694573b64aSDavid Howells  * the issuer + serialNumber and the fallback identifier is the
704573b64aSDavid Howells  * subjectKeyIdentifier.  If both are given, the lookup is by the former, but
714573b64aSDavid Howells  * the latter must also match.
723be4beafSMimi Zohar  */
735ce43ad2SDavid Howells struct key *x509_request_asymmetric_key(struct key *keyring,
744573b64aSDavid Howells 					const struct asymmetric_key_id *id,
754573b64aSDavid Howells 					const struct asymmetric_key_id *skid,
76f1b731dbSDmitry Kasatkin 					bool partial)
773be4beafSMimi Zohar {
784573b64aSDavid Howells 	struct key *key;
794573b64aSDavid Howells 	key_ref_t ref;
804573b64aSDavid Howells 	const char *lookup;
814573b64aSDavid Howells 	char *req, *p;
824573b64aSDavid Howells 	int len;
834573b64aSDavid Howells 
844573b64aSDavid Howells 	if (id) {
854573b64aSDavid Howells 		lookup = id->data;
864573b64aSDavid Howells 		len = id->len;
874573b64aSDavid Howells 	} else {
884573b64aSDavid Howells 		lookup = skid->data;
894573b64aSDavid Howells 		len = skid->len;
904573b64aSDavid Howells 	}
913be4beafSMimi Zohar 
9246963b77SDavid Howells 	/* Construct an identifier "id:<keyid>". */
934573b64aSDavid Howells 	p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
944573b64aSDavid Howells 	if (!req)
953be4beafSMimi Zohar 		return ERR_PTR(-ENOMEM);
963be4beafSMimi Zohar 
97f1b731dbSDmitry Kasatkin 	if (partial) {
9846963b77SDavid Howells 		*p++ = 'i';
9946963b77SDavid Howells 		*p++ = 'd';
100f1b731dbSDmitry Kasatkin 	} else {
101f1b731dbSDmitry Kasatkin 		*p++ = 'e';
102f1b731dbSDmitry Kasatkin 		*p++ = 'x';
103f1b731dbSDmitry Kasatkin 	}
10446963b77SDavid Howells 	*p++ = ':';
1054573b64aSDavid Howells 	p = bin2hex(p, lookup, len);
10646963b77SDavid Howells 	*p = 0;
1073be4beafSMimi Zohar 
1084573b64aSDavid Howells 	pr_debug("Look up: \"%s\"\n", req);
1093be4beafSMimi Zohar 
1104573b64aSDavid Howells 	ref = keyring_search(make_key_ref(keyring, 1),
1114573b64aSDavid Howells 			     &key_type_asymmetric, req);
1124573b64aSDavid Howells 	if (IS_ERR(ref))
1134573b64aSDavid Howells 		pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
1144573b64aSDavid Howells 	kfree(req);
1153be4beafSMimi Zohar 
1164573b64aSDavid Howells 	if (IS_ERR(ref)) {
1174573b64aSDavid Howells 		switch (PTR_ERR(ref)) {
1183be4beafSMimi Zohar 			/* Hide some search errors */
1193be4beafSMimi Zohar 		case -EACCES:
1203be4beafSMimi Zohar 		case -ENOTDIR:
1213be4beafSMimi Zohar 		case -EAGAIN:
1223be4beafSMimi Zohar 			return ERR_PTR(-ENOKEY);
1233be4beafSMimi Zohar 		default:
1244573b64aSDavid Howells 			return ERR_CAST(ref);
1253be4beafSMimi Zohar 		}
1263be4beafSMimi Zohar 	}
1273be4beafSMimi Zohar 
1284573b64aSDavid Howells 	key = key_ref_to_ptr(ref);
1294573b64aSDavid Howells 	if (id && skid) {
1304573b64aSDavid Howells 		const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
1314573b64aSDavid Howells 		if (!kids->id[1]) {
1324573b64aSDavid Howells 			pr_debug("issuer+serial match, but expected SKID missing\n");
1334573b64aSDavid Howells 			goto reject;
1344573b64aSDavid Howells 		}
1354573b64aSDavid Howells 		if (!asymmetric_key_id_same(skid, kids->id[1])) {
1364573b64aSDavid Howells 			pr_debug("issuer+serial match, but SKID does not\n");
1374573b64aSDavid Howells 			goto reject;
1384573b64aSDavid Howells 		}
1394573b64aSDavid Howells 	}
1404573b64aSDavid Howells 
1414573b64aSDavid Howells 	pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
1424573b64aSDavid Howells 	return key;
1434573b64aSDavid Howells 
1444573b64aSDavid Howells reject:
1454573b64aSDavid Howells 	key_put(key);
1464573b64aSDavid Howells 	return ERR_PTR(-EKEYREJECTED);
1473be4beafSMimi Zohar }
148cf5b50fdSDavid Howells EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
1493be4beafSMimi Zohar 
150c26fd69fSDavid Howells /*
151b426beb6SDavid Howells  * Set up the signature parameters in an X.509 certificate.  This involves
152b426beb6SDavid Howells  * digesting the signed data and extracting the signature.
153c26fd69fSDavid Howells  */
154b426beb6SDavid Howells int x509_get_sig_params(struct x509_certificate *cert)
155c26fd69fSDavid Howells {
15677d0910dSDavid Howells 	struct public_key_signature *sig = cert->sig;
157c26fd69fSDavid Howells 	struct crypto_shash *tfm;
158c26fd69fSDavid Howells 	struct shash_desc *desc;
15977d0910dSDavid Howells 	size_t desc_size;
160c26fd69fSDavid Howells 	int ret;
161c26fd69fSDavid Howells 
162c26fd69fSDavid Howells 	pr_devel("==>%s()\n", __func__);
163c26fd69fSDavid Howells 
164*6c2dc5aeSDavid Howells 	if (!cert->pub->pkey_algo)
165*6c2dc5aeSDavid Howells 		cert->unsupported_key = true;
166*6c2dc5aeSDavid Howells 
167*6c2dc5aeSDavid Howells 	if (!sig->pkey_algo)
168*6c2dc5aeSDavid Howells 		cert->unsupported_sig = true;
169*6c2dc5aeSDavid Howells 
170*6c2dc5aeSDavid Howells 	/* We check the hash if we can - even if we can't then verify it */
171*6c2dc5aeSDavid Howells 	if (!sig->hash_algo) {
172*6c2dc5aeSDavid Howells 		cert->unsupported_sig = true;
173b426beb6SDavid Howells 		return 0;
174*6c2dc5aeSDavid Howells 	}
175b426beb6SDavid Howells 
17677d0910dSDavid Howells 	sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
17777d0910dSDavid Howells 	if (!sig->s)
178b426beb6SDavid Howells 		return -ENOMEM;
179db6c43bdSTadeusz Struk 
18077d0910dSDavid Howells 	sig->s_size = cert->raw_sig_size;
181b426beb6SDavid Howells 
182c26fd69fSDavid Howells 	/* Allocate the hashing algorithm we're going to need and find out how
183c26fd69fSDavid Howells 	 * big the hash operational data will be.
184c26fd69fSDavid Howells 	 */
18577d0910dSDavid Howells 	tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
18641559420SDavid Howells 	if (IS_ERR(tfm)) {
18741559420SDavid Howells 		if (PTR_ERR(tfm) == -ENOENT) {
188*6c2dc5aeSDavid Howells 			cert->unsupported_sig = true;
189*6c2dc5aeSDavid Howells 			return 0;
19041559420SDavid Howells 		}
19141559420SDavid Howells 		return PTR_ERR(tfm);
19241559420SDavid Howells 	}
193c26fd69fSDavid Howells 
194c26fd69fSDavid Howells 	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
19577d0910dSDavid Howells 	sig->digest_size = crypto_shash_digestsize(tfm);
196c26fd69fSDavid Howells 
197c26fd69fSDavid Howells 	ret = -ENOMEM;
19877d0910dSDavid Howells 	sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
19977d0910dSDavid Howells 	if (!sig->digest)
200b426beb6SDavid Howells 		goto error;
201c26fd69fSDavid Howells 
20277d0910dSDavid Howells 	desc = kzalloc(desc_size, GFP_KERNEL);
20377d0910dSDavid Howells 	if (!desc)
20477d0910dSDavid Howells 		goto error;
205c26fd69fSDavid Howells 
206c26fd69fSDavid Howells 	desc->tfm = tfm;
207c26fd69fSDavid Howells 	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
208c26fd69fSDavid Howells 
209c26fd69fSDavid Howells 	ret = crypto_shash_init(desc);
210c26fd69fSDavid Howells 	if (ret < 0)
21177d0910dSDavid Howells 		goto error_2;
212b426beb6SDavid Howells 	might_sleep();
21377d0910dSDavid Howells 	ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
21477d0910dSDavid Howells 
21577d0910dSDavid Howells error_2:
21677d0910dSDavid Howells 	kfree(desc);
217c26fd69fSDavid Howells error:
218c26fd69fSDavid Howells 	crypto_free_shash(tfm);
219c26fd69fSDavid Howells 	pr_devel("<==%s() = %d\n", __func__, ret);
220c26fd69fSDavid Howells 	return ret;
221c26fd69fSDavid Howells }
222b426beb6SDavid Howells 
223b426beb6SDavid Howells /*
224*6c2dc5aeSDavid Howells  * Check for self-signedness in an X.509 cert and if found, check the signature
225*6c2dc5aeSDavid Howells  * immediately if we can.
226b426beb6SDavid Howells  */
227*6c2dc5aeSDavid Howells int x509_check_for_self_signed(struct x509_certificate *cert)
228b426beb6SDavid Howells {
229*6c2dc5aeSDavid Howells 	int ret = 0;
230b426beb6SDavid Howells 
231b426beb6SDavid Howells 	pr_devel("==>%s()\n", __func__);
232b426beb6SDavid Howells 
233*6c2dc5aeSDavid Howells 	if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
234*6c2dc5aeSDavid Howells 		/* If the AKID is present it may have one or two parts.  If
235*6c2dc5aeSDavid Howells 		 * both are supplied, both must match.
236*6c2dc5aeSDavid Howells 		 */
237*6c2dc5aeSDavid Howells 		bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
238*6c2dc5aeSDavid Howells 		bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
239*6c2dc5aeSDavid Howells 
240*6c2dc5aeSDavid Howells 		if (!a && !b)
241*6c2dc5aeSDavid Howells 			goto not_self_signed;
242*6c2dc5aeSDavid Howells 
243*6c2dc5aeSDavid Howells 		ret = -EKEYREJECTED;
244*6c2dc5aeSDavid Howells 		if (((a && !b) || (b && !a)) &&
245*6c2dc5aeSDavid Howells 		    cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
246*6c2dc5aeSDavid Howells 			goto out;
247*6c2dc5aeSDavid Howells 	}
248*6c2dc5aeSDavid Howells 
249*6c2dc5aeSDavid Howells 	ret = public_key_verify_signature(cert->pub, cert->sig);
250*6c2dc5aeSDavid Howells 	if (ret < 0) {
251*6c2dc5aeSDavid Howells 		if (ret == -ENOPKG) {
252*6c2dc5aeSDavid Howells 			cert->unsupported_sig = true;
253*6c2dc5aeSDavid Howells 			ret = 0;
254*6c2dc5aeSDavid Howells 		}
255*6c2dc5aeSDavid Howells 		goto out;
256*6c2dc5aeSDavid Howells 	}
257*6c2dc5aeSDavid Howells 
258*6c2dc5aeSDavid Howells 	pr_devel("Cert Self-signature verified");
259*6c2dc5aeSDavid Howells 	cert->self_signed = true;
260*6c2dc5aeSDavid Howells 
261*6c2dc5aeSDavid Howells out:
262*6c2dc5aeSDavid Howells 	pr_devel("<==%s() = %d\n", __func__, ret);
263b426beb6SDavid Howells 	return ret;
264b426beb6SDavid Howells 
265*6c2dc5aeSDavid Howells not_self_signed:
266*6c2dc5aeSDavid Howells 	pr_devel("<==%s() = 0 [not]\n", __func__);
267*6c2dc5aeSDavid Howells 	return 0;
268b426beb6SDavid Howells }
269c26fd69fSDavid Howells 
270c26fd69fSDavid Howells /*
2713be4beafSMimi Zohar  * Check the new certificate against the ones in the trust keyring.  If one of
2723be4beafSMimi Zohar  * those is the signing key and validates the new certificate, then mark the
2733be4beafSMimi Zohar  * new certificate as being trusted.
2743be4beafSMimi Zohar  *
2753be4beafSMimi Zohar  * Return 0 if the new certificate was successfully validated, 1 if we couldn't
2763be4beafSMimi Zohar  * find a matching parent certificate in the trusted list and an error if there
2773be4beafSMimi Zohar  * is a matching certificate but the signature check fails.
2783be4beafSMimi Zohar  */
2793be4beafSMimi Zohar static int x509_validate_trust(struct x509_certificate *cert,
2803be4beafSMimi Zohar 			       struct key *trust_keyring)
2813be4beafSMimi Zohar {
28277d0910dSDavid Howells 	struct public_key_signature *sig = cert->sig;
2833be4beafSMimi Zohar 	struct key *key;
2843be4beafSMimi Zohar 	int ret = 1;
2853be4beafSMimi Zohar 
286*6c2dc5aeSDavid Howells 	if (!sig->auth_ids[0] && !sig->auth_ids[1])
287*6c2dc5aeSDavid Howells 		return 1;
288*6c2dc5aeSDavid Howells 
2893be4beafSMimi Zohar 	if (!trust_keyring)
2903be4beafSMimi Zohar 		return -EOPNOTSUPP;
29177d0910dSDavid Howells 	if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
292ffb70f61SDmitry Kasatkin 		return -EPERM;
293*6c2dc5aeSDavid Howells 	if (cert->unsupported_sig)
294*6c2dc5aeSDavid Howells 		return -ENOPKG;
295ffb70f61SDmitry Kasatkin 
2964573b64aSDavid Howells 	key = x509_request_asymmetric_key(trust_keyring,
29777d0910dSDavid Howells 					  sig->auth_ids[0], sig->auth_ids[1],
298f1b731dbSDmitry Kasatkin 					  false);
299*6c2dc5aeSDavid Howells 	if (IS_ERR(key))
300*6c2dc5aeSDavid Howells 		return PTR_ERR(key);
301*6c2dc5aeSDavid Howells 
302*6c2dc5aeSDavid Howells 	if (!use_builtin_keys ||
303*6c2dc5aeSDavid Howells 	    test_bit(KEY_FLAG_BUILTIN, &key->flags)) {
304*6c2dc5aeSDavid Howells 		ret = public_key_verify_signature(
305*6c2dc5aeSDavid Howells 			key->payload.data[asym_crypto], cert->sig);
306*6c2dc5aeSDavid Howells 		if (ret == -ENOPKG)
307*6c2dc5aeSDavid Howells 			cert->unsupported_sig = true;
3083be4beafSMimi Zohar 	}
309*6c2dc5aeSDavid Howells 	key_put(key);
3103be4beafSMimi Zohar 	return ret;
3113be4beafSMimi Zohar }
3123be4beafSMimi Zohar 
3133be4beafSMimi Zohar /*
314c26fd69fSDavid Howells  * Attempt to parse a data blob for a key as an X509 certificate.
315c26fd69fSDavid Howells  */
316c26fd69fSDavid Howells static int x509_key_preparse(struct key_preparsed_payload *prep)
317c26fd69fSDavid Howells {
31846963b77SDavid Howells 	struct asymmetric_key_ids *kids;
319c26fd69fSDavid Howells 	struct x509_certificate *cert;
32046963b77SDavid Howells 	const char *q;
321c26fd69fSDavid Howells 	size_t srlen, sulen;
32246963b77SDavid Howells 	char *desc = NULL, *p;
323c26fd69fSDavid Howells 	int ret;
324c26fd69fSDavid Howells 
325c26fd69fSDavid Howells 	cert = x509_cert_parse(prep->data, prep->datalen);
326c26fd69fSDavid Howells 	if (IS_ERR(cert))
327c26fd69fSDavid Howells 		return PTR_ERR(cert);
328c26fd69fSDavid Howells 
329c26fd69fSDavid Howells 	pr_devel("Cert Issuer: %s\n", cert->issuer);
330c26fd69fSDavid Howells 	pr_devel("Cert Subject: %s\n", cert->subject);
3312ecdb23bSDavid Howells 
332*6c2dc5aeSDavid Howells 	if (cert->unsupported_key) {
3332ecdb23bSDavid Howells 		ret = -ENOPKG;
3342ecdb23bSDavid Howells 		goto error_free_cert;
3352ecdb23bSDavid Howells 	}
3362ecdb23bSDavid Howells 
3374e8ae72aSDavid Howells 	pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
338fd19a3d1SDavid Howells 	pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
339c26fd69fSDavid Howells 
3404e8ae72aSDavid Howells 	cert->pub->id_type = "X509";
341c26fd69fSDavid Howells 
342*6c2dc5aeSDavid Howells 	/* See if we can derive the trustability of this certificate.
343*6c2dc5aeSDavid Howells 	 *
344*6c2dc5aeSDavid Howells 	 * When it comes to self-signed certificates, we cannot evaluate
345*6c2dc5aeSDavid Howells 	 * trustedness except by the fact that we obtained it from a trusted
346*6c2dc5aeSDavid Howells 	 * location.  So we just rely on x509_validate_trust() failing in this
347*6c2dc5aeSDavid Howells 	 * case.
348*6c2dc5aeSDavid Howells 	 *
349*6c2dc5aeSDavid Howells 	 * Note that there's a possibility of a self-signed cert matching a
350*6c2dc5aeSDavid Howells 	 * cert that we have (most likely a duplicate that we already trust) -
351*6c2dc5aeSDavid Howells 	 * in which case it will be marked trusted.
352*6c2dc5aeSDavid Howells 	 */
353*6c2dc5aeSDavid Howells 	if (cert->unsupported_sig || cert->self_signed) {
354*6c2dc5aeSDavid Howells 		public_key_signature_free(cert->sig);
355*6c2dc5aeSDavid Howells 		cert->sig = NULL;
356*6c2dc5aeSDavid Howells 	} else {
357*6c2dc5aeSDavid Howells 		pr_devel("Cert Signature: %s + %s\n",
358*6c2dc5aeSDavid Howells 			 cert->sig->pkey_algo, cert->sig->hash_algo);
359*6c2dc5aeSDavid Howells 
3603be4beafSMimi Zohar 		ret = x509_validate_trust(cert, get_system_trusted_keyring());
36141c89b64SPetko Manolov 		if (ret)
36241c89b64SPetko Manolov 			ret = x509_validate_trust(cert, get_ima_mok_keyring());
363*6c2dc5aeSDavid Howells 		if (ret == -EKEYREJECTED)
364*6c2dc5aeSDavid Howells 			goto error_free_cert;
3653be4beafSMimi Zohar 		if (!ret)
366*6c2dc5aeSDavid Howells 			prep->trusted = true;
367c26fd69fSDavid Howells 	}
368c26fd69fSDavid Howells 
369c26fd69fSDavid Howells 	/* Propose a description */
370c26fd69fSDavid Howells 	sulen = strlen(cert->subject);
371dd2f6c44SDavid Howells 	if (cert->raw_skid) {
372dd2f6c44SDavid Howells 		srlen = cert->raw_skid_size;
373dd2f6c44SDavid Howells 		q = cert->raw_skid;
374dd2f6c44SDavid Howells 	} else {
37546963b77SDavid Howells 		srlen = cert->raw_serial_size;
37646963b77SDavid Howells 		q = cert->raw_serial;
377dd2f6c44SDavid Howells 	}
37846963b77SDavid Howells 
379c26fd69fSDavid Howells 	ret = -ENOMEM;
38046963b77SDavid Howells 	desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
381c26fd69fSDavid Howells 	if (!desc)
382c26fd69fSDavid Howells 		goto error_free_cert;
38346963b77SDavid Howells 	p = memcpy(desc, cert->subject, sulen);
38446963b77SDavid Howells 	p += sulen;
38546963b77SDavid Howells 	*p++ = ':';
38646963b77SDavid Howells 	*p++ = ' ';
38746963b77SDavid Howells 	p = bin2hex(p, q, srlen);
38846963b77SDavid Howells 	*p = 0;
38946963b77SDavid Howells 
39046963b77SDavid Howells 	kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
39146963b77SDavid Howells 	if (!kids)
39246963b77SDavid Howells 		goto error_free_desc;
39346963b77SDavid Howells 	kids->id[0] = cert->id;
39446963b77SDavid Howells 	kids->id[1] = cert->skid;
395c26fd69fSDavid Howells 
396c26fd69fSDavid Howells 	/* We're pinning the module by being linked against it */
397c26fd69fSDavid Howells 	__module_get(public_key_subtype.owner);
398146aa8b1SDavid Howells 	prep->payload.data[asym_subtype] = &public_key_subtype;
399146aa8b1SDavid Howells 	prep->payload.data[asym_key_ids] = kids;
400146aa8b1SDavid Howells 	prep->payload.data[asym_crypto] = cert->pub;
40177d0910dSDavid Howells 	prep->payload.data[asym_auth] = cert->sig;
402c26fd69fSDavid Howells 	prep->description = desc;
403c26fd69fSDavid Howells 	prep->quotalen = 100;
404c26fd69fSDavid Howells 
405c26fd69fSDavid Howells 	/* We've finished with the certificate */
406c26fd69fSDavid Howells 	cert->pub = NULL;
40746963b77SDavid Howells 	cert->id = NULL;
40846963b77SDavid Howells 	cert->skid = NULL;
40977d0910dSDavid Howells 	cert->sig = NULL;
410c26fd69fSDavid Howells 	desc = NULL;
411c26fd69fSDavid Howells 	ret = 0;
412c26fd69fSDavid Howells 
41346963b77SDavid Howells error_free_desc:
41446963b77SDavid Howells 	kfree(desc);
415c26fd69fSDavid Howells error_free_cert:
416c26fd69fSDavid Howells 	x509_free_certificate(cert);
417c26fd69fSDavid Howells 	return ret;
418c26fd69fSDavid Howells }
419c26fd69fSDavid Howells 
420c26fd69fSDavid Howells static struct asymmetric_key_parser x509_key_parser = {
421c26fd69fSDavid Howells 	.owner	= THIS_MODULE,
422c26fd69fSDavid Howells 	.name	= "x509",
423c26fd69fSDavid Howells 	.parse	= x509_key_preparse,
424c26fd69fSDavid Howells };
425c26fd69fSDavid Howells 
426c26fd69fSDavid Howells /*
427c26fd69fSDavid Howells  * Module stuff
428c26fd69fSDavid Howells  */
429c26fd69fSDavid Howells static int __init x509_key_init(void)
430c26fd69fSDavid Howells {
431c26fd69fSDavid Howells 	return register_asymmetric_key_parser(&x509_key_parser);
432c26fd69fSDavid Howells }
433c26fd69fSDavid Howells 
434c26fd69fSDavid Howells static void __exit x509_key_exit(void)
435c26fd69fSDavid Howells {
436c26fd69fSDavid Howells 	unregister_asymmetric_key_parser(&x509_key_parser);
437c26fd69fSDavid Howells }
438c26fd69fSDavid Howells 
439c26fd69fSDavid Howells module_init(x509_key_init);
440c26fd69fSDavid Howells module_exit(x509_key_exit);
441e19aaa7dSKonstantin Khlebnikov 
442e19aaa7dSKonstantin Khlebnikov MODULE_DESCRIPTION("X.509 certificate parser");
443e19aaa7dSKonstantin Khlebnikov MODULE_LICENSE("GPL");
444