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
;
113 cert
= x509_cert_parse(prep
->data
, prep
->datalen
);
115 return PTR_ERR(cert
);
117 pr_devel("Cert Issuer: %s\n", cert
->issuer
);
118 pr_devel("Cert Subject: %s\n", cert
->subject
);
119 pr_devel("Cert Key Algo: %s\n", pkey_algo
[cert
->pkey_algo
]);
120 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
121 cert
->valid_from
.tm_year
+ 1900, cert
->valid_from
.tm_mon
+ 1,
122 cert
->valid_from
.tm_mday
, cert
->valid_from
.tm_hour
,
123 cert
->valid_from
.tm_min
, cert
->valid_from
.tm_sec
);
124 pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n",
125 cert
->valid_to
.tm_year
+ 1900, cert
->valid_to
.tm_mon
+ 1,
126 cert
->valid_to
.tm_mday
, cert
->valid_to
.tm_hour
,
127 cert
->valid_to
.tm_min
, cert
->valid_to
.tm_sec
);
128 pr_devel("Cert Signature: %s + %s\n",
129 pkey_algo
[cert
->sig_pkey_algo
],
130 pkey_hash_algo
[cert
->sig_hash_algo
]);
132 if (!cert
->fingerprint
|| !cert
->authority
) {
133 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
136 goto error_free_cert
;
139 cert
->pub
->algo
= x509_public_key_algorithms
[cert
->pkey_algo
];
140 cert
->pub
->id_type
= PKEY_ID_X509
;
142 /* Check the signature on the key */
143 if (strcmp(cert
->fingerprint
, cert
->authority
) == 0) {
144 ret
= x509_check_signature(cert
->pub
, cert
);
146 goto error_free_cert
;
149 /* Propose a description */
150 sulen
= strlen(cert
->subject
);
151 srlen
= strlen(cert
->fingerprint
);
153 desc
= kmalloc(sulen
+ 2 + srlen
+ 1, GFP_KERNEL
);
155 goto error_free_cert
;
156 memcpy(desc
, cert
->subject
, sulen
);
158 desc
[sulen
+ 1] = ' ';
159 memcpy(desc
+ sulen
+ 2, cert
->fingerprint
, srlen
);
160 desc
[sulen
+ 2 + srlen
] = 0;
162 /* We're pinning the module by being linked against it */
163 __module_get(public_key_subtype
.owner
);
164 prep
->type_data
[0] = &public_key_subtype
;
165 prep
->type_data
[1] = cert
->fingerprint
;
166 prep
->payload
= cert
->pub
;
167 prep
->description
= desc
;
168 prep
->quotalen
= 100;
170 /* We've finished with the certificate */
172 cert
->fingerprint
= NULL
;
177 x509_free_certificate(cert
);
181 static struct asymmetric_key_parser x509_key_parser
= {
182 .owner
= THIS_MODULE
,
184 .parse
= x509_key_preparse
,
190 static int __init
x509_key_init(void)
192 return register_asymmetric_key_parser(&x509_key_parser
);
195 static void __exit
x509_key_exit(void)
197 unregister_asymmetric_key_parser(&x509_key_parser
);
200 module_init(x509_key_init
);
201 module_exit(x509_key_exit
);