xref: /linux/crypto/asymmetric_keys/public_key.c (revision 825e587af2e90e9b953849f3347a01d8f383d577)
1a9681bf3SDavid Howells /* In-software asymmetric public-key crypto subtype
2a9681bf3SDavid Howells  *
3a9681bf3SDavid Howells  * See Documentation/crypto/asymmetric-keys.txt
4a9681bf3SDavid Howells  *
5a9681bf3SDavid Howells  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6a9681bf3SDavid Howells  * Written by David Howells (dhowells@redhat.com)
7a9681bf3SDavid Howells  *
8a9681bf3SDavid Howells  * This program is free software; you can redistribute it and/or
9a9681bf3SDavid Howells  * modify it under the terms of the GNU General Public Licence
10a9681bf3SDavid Howells  * as published by the Free Software Foundation; either version
11a9681bf3SDavid Howells  * 2 of the Licence, or (at your option) any later version.
12a9681bf3SDavid Howells  */
13a9681bf3SDavid Howells 
14a9681bf3SDavid Howells #define pr_fmt(fmt) "PKEY: "fmt
15a9681bf3SDavid Howells #include <linux/module.h>
16a9681bf3SDavid Howells #include <linux/export.h>
17a9681bf3SDavid Howells #include <linux/kernel.h>
18a9681bf3SDavid Howells #include <linux/slab.h>
19a9681bf3SDavid Howells #include <linux/seq_file.h>
20a9681bf3SDavid Howells #include <keys/asymmetric-subtype.h>
21a9681bf3SDavid Howells #include "public_key.h"
22a9681bf3SDavid Howells 
23a9681bf3SDavid Howells MODULE_LICENSE("GPL");
24a9681bf3SDavid Howells 
259abc4e66SDavid Howells const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
26a9681bf3SDavid Howells 	[PKEY_ALGO_DSA]		= "DSA",
27a9681bf3SDavid Howells 	[PKEY_ALGO_RSA]		= "RSA",
28a9681bf3SDavid Howells };
299abc4e66SDavid Howells EXPORT_SYMBOL_GPL(pkey_algo_name);
30a9681bf3SDavid Howells 
31206ce59aSDavid Howells const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
32206ce59aSDavid Howells #if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
33206ce59aSDavid Howells 	defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
34206ce59aSDavid Howells 	[PKEY_ALGO_RSA]		= &RSA_public_key_algorithm,
35206ce59aSDavid Howells #endif
36206ce59aSDavid Howells };
37206ce59aSDavid Howells EXPORT_SYMBOL_GPL(pkey_algo);
38206ce59aSDavid Howells 
399abc4e66SDavid Howells const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
40a9681bf3SDavid Howells 	[PKEY_ID_PGP]		= "PGP",
41a9681bf3SDavid Howells 	[PKEY_ID_X509]		= "X509",
42a9681bf3SDavid Howells };
439abc4e66SDavid Howells EXPORT_SYMBOL_GPL(pkey_id_type_name);
44a9681bf3SDavid Howells 
45a9681bf3SDavid Howells /*
46a9681bf3SDavid Howells  * Provide a part of a description of the key for /proc/keys.
47a9681bf3SDavid Howells  */
48a9681bf3SDavid Howells static void public_key_describe(const struct key *asymmetric_key,
49a9681bf3SDavid Howells 				struct seq_file *m)
50a9681bf3SDavid Howells {
51a9681bf3SDavid Howells 	struct public_key *key = asymmetric_key->payload.data;
52a9681bf3SDavid Howells 
53a9681bf3SDavid Howells 	if (key)
54a9681bf3SDavid Howells 		seq_printf(m, "%s.%s",
559abc4e66SDavid Howells 			   pkey_id_type_name[key->id_type], key->algo->name);
56a9681bf3SDavid Howells }
57a9681bf3SDavid Howells 
58a9681bf3SDavid Howells /*
59a9681bf3SDavid Howells  * Destroy a public key algorithm key.
60a9681bf3SDavid Howells  */
61a9681bf3SDavid Howells void public_key_destroy(void *payload)
62a9681bf3SDavid Howells {
63a9681bf3SDavid Howells 	struct public_key *key = payload;
64a9681bf3SDavid Howells 	int i;
65a9681bf3SDavid Howells 
66a9681bf3SDavid Howells 	if (key) {
67a9681bf3SDavid Howells 		for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
68a9681bf3SDavid Howells 			mpi_free(key->mpi[i]);
69a9681bf3SDavid Howells 		kfree(key);
70a9681bf3SDavid Howells 	}
71a9681bf3SDavid Howells }
72a9681bf3SDavid Howells EXPORT_SYMBOL_GPL(public_key_destroy);
73a9681bf3SDavid Howells 
74a9681bf3SDavid Howells /*
75a9681bf3SDavid Howells  * Verify a signature using a public key.
76a9681bf3SDavid Howells  */
77*3d167d68SDavid Howells int public_key_verify_signature(const struct public_key *pk,
78a9681bf3SDavid Howells 				const struct public_key_signature *sig)
79a9681bf3SDavid Howells {
80*3d167d68SDavid Howells 	const struct public_key_algorithm *algo;
81a9681bf3SDavid Howells 
82*3d167d68SDavid Howells 	BUG_ON(!pk);
83*3d167d68SDavid Howells 	BUG_ON(!pk->mpi[0]);
84*3d167d68SDavid Howells 	BUG_ON(!pk->mpi[1]);
85*3d167d68SDavid Howells 	BUG_ON(!sig);
86*3d167d68SDavid Howells 	BUG_ON(!sig->digest);
87*3d167d68SDavid Howells 	BUG_ON(!sig->mpi[0]);
88*3d167d68SDavid Howells 
89*3d167d68SDavid Howells 	algo = pk->algo;
90*3d167d68SDavid Howells 	if (!algo) {
91*3d167d68SDavid Howells 		if (pk->pkey_algo >= PKEY_ALGO__LAST)
92*3d167d68SDavid Howells 			return -ENOPKG;
93*3d167d68SDavid Howells 		algo = pkey_algo[pk->pkey_algo];
94*3d167d68SDavid Howells 		if (!algo)
95*3d167d68SDavid Howells 			return -ENOPKG;
96*3d167d68SDavid Howells 	}
97*3d167d68SDavid Howells 
98*3d167d68SDavid Howells 	if (!algo->verify_signature)
99a9681bf3SDavid Howells 		return -ENOTSUPP;
100a9681bf3SDavid Howells 
101*3d167d68SDavid Howells 	if (sig->nr_mpi != algo->n_sig_mpi) {
102a9681bf3SDavid Howells 		pr_debug("Signature has %u MPI not %u\n",
103*3d167d68SDavid Howells 			 sig->nr_mpi, algo->n_sig_mpi);
104a9681bf3SDavid Howells 		return -EINVAL;
105a9681bf3SDavid Howells 	}
106a9681bf3SDavid Howells 
107*3d167d68SDavid Howells 	return algo->verify_signature(pk, sig);
108*3d167d68SDavid Howells }
109*3d167d68SDavid Howells EXPORT_SYMBOL_GPL(public_key_verify_signature);
110*3d167d68SDavid Howells 
111*3d167d68SDavid Howells static int public_key_verify_signature_2(const struct key *key,
112*3d167d68SDavid Howells 					 const struct public_key_signature *sig)
113*3d167d68SDavid Howells {
114*3d167d68SDavid Howells 	const struct public_key *pk = key->payload.data;
115*3d167d68SDavid Howells 	return public_key_verify_signature(pk, sig);
116a9681bf3SDavid Howells }
117a9681bf3SDavid Howells 
118a9681bf3SDavid Howells /*
119a9681bf3SDavid Howells  * Public key algorithm asymmetric key subtype
120a9681bf3SDavid Howells  */
121a9681bf3SDavid Howells struct asymmetric_key_subtype public_key_subtype = {
122a9681bf3SDavid Howells 	.owner			= THIS_MODULE,
123a9681bf3SDavid Howells 	.name			= "public_key",
124a9681bf3SDavid Howells 	.describe		= public_key_describe,
125a9681bf3SDavid Howells 	.destroy		= public_key_destroy,
126*3d167d68SDavid Howells 	.verify_signature	= public_key_verify_signature_2,
127a9681bf3SDavid Howells };
128a9681bf3SDavid Howells EXPORT_SYMBOL_GPL(public_key_subtype);
129