1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* Instantiate a public key crypto key from an X.509 Certificate
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define pr_fmt(fmt) "X.509: "fmt
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <keys/asymmetric-subtype.h>
13*4882a593Smuzhiyun #include <keys/asymmetric-parser.h>
14*4882a593Smuzhiyun #include <keys/system_keyring.h>
15*4882a593Smuzhiyun #include <crypto/hash.h>
16*4882a593Smuzhiyun #include "asymmetric_keys.h"
17*4882a593Smuzhiyun #include "x509_parser.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * Set up the signature parameters in an X.509 certificate. This involves
21*4882a593Smuzhiyun * digesting the signed data and extracting the signature.
22*4882a593Smuzhiyun */
x509_get_sig_params(struct x509_certificate * cert)23*4882a593Smuzhiyun int x509_get_sig_params(struct x509_certificate *cert)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun struct public_key_signature *sig = cert->sig;
26*4882a593Smuzhiyun struct crypto_shash *tfm;
27*4882a593Smuzhiyun struct shash_desc *desc;
28*4882a593Smuzhiyun size_t desc_size;
29*4882a593Smuzhiyun int ret;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun pr_devel("==>%s()\n", __func__);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun sig->data = cert->tbs;
34*4882a593Smuzhiyun sig->data_size = cert->tbs_size;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (!cert->pub->pkey_algo)
37*4882a593Smuzhiyun cert->unsupported_key = true;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun if (!sig->pkey_algo)
40*4882a593Smuzhiyun cert->unsupported_sig = true;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* We check the hash if we can - even if we can't then verify it */
43*4882a593Smuzhiyun if (!sig->hash_algo) {
44*4882a593Smuzhiyun cert->unsupported_sig = true;
45*4882a593Smuzhiyun return 0;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
49*4882a593Smuzhiyun if (!sig->s)
50*4882a593Smuzhiyun return -ENOMEM;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun sig->s_size = cert->raw_sig_size;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* Allocate the hashing algorithm we're going to need and find out how
55*4882a593Smuzhiyun * big the hash operational data will be.
56*4882a593Smuzhiyun */
57*4882a593Smuzhiyun tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
58*4882a593Smuzhiyun if (IS_ERR(tfm)) {
59*4882a593Smuzhiyun if (PTR_ERR(tfm) == -ENOENT) {
60*4882a593Smuzhiyun cert->unsupported_sig = true;
61*4882a593Smuzhiyun return 0;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun return PTR_ERR(tfm);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
67*4882a593Smuzhiyun sig->digest_size = crypto_shash_digestsize(tfm);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun ret = -ENOMEM;
70*4882a593Smuzhiyun sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
71*4882a593Smuzhiyun if (!sig->digest)
72*4882a593Smuzhiyun goto error;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun desc = kzalloc(desc_size, GFP_KERNEL);
75*4882a593Smuzhiyun if (!desc)
76*4882a593Smuzhiyun goto error;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun desc->tfm = tfm;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
81*4882a593Smuzhiyun if (ret < 0)
82*4882a593Smuzhiyun goto error_2;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs");
85*4882a593Smuzhiyun if (ret == -EKEYREJECTED) {
86*4882a593Smuzhiyun pr_err("Cert %*phN is blacklisted\n",
87*4882a593Smuzhiyun sig->digest_size, sig->digest);
88*4882a593Smuzhiyun cert->blacklisted = true;
89*4882a593Smuzhiyun ret = 0;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun error_2:
93*4882a593Smuzhiyun kfree(desc);
94*4882a593Smuzhiyun error:
95*4882a593Smuzhiyun crypto_free_shash(tfm);
96*4882a593Smuzhiyun pr_devel("<==%s() = %d\n", __func__, ret);
97*4882a593Smuzhiyun return ret;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * Check for self-signedness in an X.509 cert and if found, check the signature
102*4882a593Smuzhiyun * immediately if we can.
103*4882a593Smuzhiyun */
x509_check_for_self_signed(struct x509_certificate * cert)104*4882a593Smuzhiyun int x509_check_for_self_signed(struct x509_certificate *cert)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun int ret = 0;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun pr_devel("==>%s()\n", __func__);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (cert->raw_subject_size != cert->raw_issuer_size ||
111*4882a593Smuzhiyun memcmp(cert->raw_subject, cert->raw_issuer,
112*4882a593Smuzhiyun cert->raw_issuer_size) != 0)
113*4882a593Smuzhiyun goto not_self_signed;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
116*4882a593Smuzhiyun /* If the AKID is present it may have one or two parts. If
117*4882a593Smuzhiyun * both are supplied, both must match.
118*4882a593Smuzhiyun */
119*4882a593Smuzhiyun bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
120*4882a593Smuzhiyun bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if (!a && !b)
123*4882a593Smuzhiyun goto not_self_signed;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun ret = -EKEYREJECTED;
126*4882a593Smuzhiyun if (((a && !b) || (b && !a)) &&
127*4882a593Smuzhiyun cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
128*4882a593Smuzhiyun goto out;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun ret = -EKEYREJECTED;
132*4882a593Smuzhiyun if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
133*4882a593Smuzhiyun goto out;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun ret = public_key_verify_signature(cert->pub, cert->sig);
136*4882a593Smuzhiyun if (ret < 0) {
137*4882a593Smuzhiyun if (ret == -ENOPKG) {
138*4882a593Smuzhiyun cert->unsupported_sig = true;
139*4882a593Smuzhiyun ret = 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun goto out;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun pr_devel("Cert Self-signature verified");
145*4882a593Smuzhiyun cert->self_signed = true;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun out:
148*4882a593Smuzhiyun pr_devel("<==%s() = %d\n", __func__, ret);
149*4882a593Smuzhiyun return ret;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun not_self_signed:
152*4882a593Smuzhiyun pr_devel("<==%s() = 0 [not]\n", __func__);
153*4882a593Smuzhiyun return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun * Attempt to parse a data blob for a key as an X509 certificate.
158*4882a593Smuzhiyun */
x509_key_preparse(struct key_preparsed_payload * prep)159*4882a593Smuzhiyun static int x509_key_preparse(struct key_preparsed_payload *prep)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct asymmetric_key_ids *kids;
162*4882a593Smuzhiyun struct x509_certificate *cert;
163*4882a593Smuzhiyun const char *q;
164*4882a593Smuzhiyun size_t srlen, sulen;
165*4882a593Smuzhiyun char *desc = NULL, *p;
166*4882a593Smuzhiyun int ret;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun cert = x509_cert_parse(prep->data, prep->datalen);
169*4882a593Smuzhiyun if (IS_ERR(cert))
170*4882a593Smuzhiyun return PTR_ERR(cert);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun pr_devel("Cert Issuer: %s\n", cert->issuer);
173*4882a593Smuzhiyun pr_devel("Cert Subject: %s\n", cert->subject);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (cert->unsupported_key) {
176*4882a593Smuzhiyun ret = -ENOPKG;
177*4882a593Smuzhiyun goto error_free_cert;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
181*4882a593Smuzhiyun pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun cert->pub->id_type = "X509";
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (cert->unsupported_sig) {
186*4882a593Smuzhiyun public_key_signature_free(cert->sig);
187*4882a593Smuzhiyun cert->sig = NULL;
188*4882a593Smuzhiyun } else {
189*4882a593Smuzhiyun pr_devel("Cert Signature: %s + %s\n",
190*4882a593Smuzhiyun cert->sig->pkey_algo, cert->sig->hash_algo);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Don't permit addition of blacklisted keys */
194*4882a593Smuzhiyun ret = -EKEYREJECTED;
195*4882a593Smuzhiyun if (cert->blacklisted)
196*4882a593Smuzhiyun goto error_free_cert;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* Propose a description */
199*4882a593Smuzhiyun sulen = strlen(cert->subject);
200*4882a593Smuzhiyun if (cert->raw_skid) {
201*4882a593Smuzhiyun srlen = cert->raw_skid_size;
202*4882a593Smuzhiyun q = cert->raw_skid;
203*4882a593Smuzhiyun } else {
204*4882a593Smuzhiyun srlen = cert->raw_serial_size;
205*4882a593Smuzhiyun q = cert->raw_serial;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun ret = -ENOMEM;
209*4882a593Smuzhiyun desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
210*4882a593Smuzhiyun if (!desc)
211*4882a593Smuzhiyun goto error_free_cert;
212*4882a593Smuzhiyun p = memcpy(desc, cert->subject, sulen);
213*4882a593Smuzhiyun p += sulen;
214*4882a593Smuzhiyun *p++ = ':';
215*4882a593Smuzhiyun *p++ = ' ';
216*4882a593Smuzhiyun p = bin2hex(p, q, srlen);
217*4882a593Smuzhiyun *p = 0;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
220*4882a593Smuzhiyun if (!kids)
221*4882a593Smuzhiyun goto error_free_desc;
222*4882a593Smuzhiyun kids->id[0] = cert->id;
223*4882a593Smuzhiyun kids->id[1] = cert->skid;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* We're pinning the module by being linked against it */
226*4882a593Smuzhiyun __module_get(public_key_subtype.owner);
227*4882a593Smuzhiyun prep->payload.data[asym_subtype] = &public_key_subtype;
228*4882a593Smuzhiyun prep->payload.data[asym_key_ids] = kids;
229*4882a593Smuzhiyun prep->payload.data[asym_crypto] = cert->pub;
230*4882a593Smuzhiyun prep->payload.data[asym_auth] = cert->sig;
231*4882a593Smuzhiyun prep->description = desc;
232*4882a593Smuzhiyun prep->quotalen = 100;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* We've finished with the certificate */
235*4882a593Smuzhiyun cert->pub = NULL;
236*4882a593Smuzhiyun cert->id = NULL;
237*4882a593Smuzhiyun cert->skid = NULL;
238*4882a593Smuzhiyun cert->sig = NULL;
239*4882a593Smuzhiyun desc = NULL;
240*4882a593Smuzhiyun ret = 0;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun error_free_desc:
243*4882a593Smuzhiyun kfree(desc);
244*4882a593Smuzhiyun error_free_cert:
245*4882a593Smuzhiyun x509_free_certificate(cert);
246*4882a593Smuzhiyun return ret;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun static struct asymmetric_key_parser x509_key_parser = {
250*4882a593Smuzhiyun .owner = THIS_MODULE,
251*4882a593Smuzhiyun .name = "x509",
252*4882a593Smuzhiyun .parse = x509_key_preparse,
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /*
256*4882a593Smuzhiyun * Module stuff
257*4882a593Smuzhiyun */
x509_key_init(void)258*4882a593Smuzhiyun static int __init x509_key_init(void)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun return register_asymmetric_key_parser(&x509_key_parser);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
x509_key_exit(void)263*4882a593Smuzhiyun static void __exit x509_key_exit(void)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun unregister_asymmetric_key_parser(&x509_key_parser);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun module_init(x509_key_init);
269*4882a593Smuzhiyun module_exit(x509_key_exit);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun MODULE_DESCRIPTION("X.509 certificate parser");
272*4882a593Smuzhiyun MODULE_AUTHOR("Red Hat, Inc.");
273*4882a593Smuzhiyun MODULE_LICENSE("GPL");
274