1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Signature verification with an asymmetric key
3  *
4  * See Documentation/crypto/asymmetric-keys.txt
5  *
6  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
7  * Written by David Howells (dhowells@redhat.com)
8  */
9 
10 #define pr_fmt(fmt) "SIG: "fmt
11 #include <keys/asymmetric-subtype.h>
12 #include <linux/export.h>
13 #include <linux/err.h>
14 #include <linux/slab.h>
15 #include <linux/keyctl.h>
16 #include <crypto/public_key.h>
17 #include <keys/user-type.h>
18 #include "asymmetric_keys.h"
19 
20 /*
21  * Destroy a public key signature.
22  */
23 void public_key_signature_free(struct public_key_signature *sig)
24 {
25 	int i;
26 
27 	if (sig) {
28 		for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++)
29 			kfree(sig->auth_ids[i]);
30 		kfree(sig->s);
31 		kfree(sig->digest);
32 		kfree(sig);
33 	}
34 }
35 EXPORT_SYMBOL_GPL(public_key_signature_free);
36 
37 /**
38  * query_asymmetric_key - Get information about an aymmetric key.
39  * @params: Various parameters.
40  * @info: Where to put the information.
41  */
42 int query_asymmetric_key(const struct kernel_pkey_params *params,
43 			 struct kernel_pkey_query *info)
44 {
45 	const struct asymmetric_key_subtype *subtype;
46 	struct key *key = params->key;
47 	int ret;
48 
49 	pr_devel("==>%s()\n", __func__);
50 
51 	if (key->type != &key_type_asymmetric)
52 		return -EINVAL;
53 	subtype = asymmetric_key_subtype(key);
54 	if (!subtype ||
55 	    !key->payload.data[0])
56 		return -EINVAL;
57 	if (!subtype->query)
58 		return -ENOTSUPP;
59 
60 	ret = subtype->query(params, info);
61 
62 	pr_devel("<==%s() = %d\n", __func__, ret);
63 	return ret;
64 }
65 EXPORT_SYMBOL_GPL(query_asymmetric_key);
66 
67 /**
68  * encrypt_blob - Encrypt data using an asymmetric key
69  * @params: Various parameters
70  * @data: Data blob to be encrypted, length params->data_len
71  * @enc: Encrypted data buffer, length params->enc_len
72  *
73  * Encrypt the specified data blob using the private key specified by
74  * params->key.  The encrypted data is wrapped in an encoding if
75  * params->encoding is specified (eg. "pkcs1").
76  *
77  * Returns the length of the data placed in the encrypted data buffer or an
78  * error.
79  */
80 int encrypt_blob(struct kernel_pkey_params *params,
81 		 const void *data, void *enc)
82 {
83 	params->op = kernel_pkey_encrypt;
84 	return asymmetric_key_eds_op(params, data, enc);
85 }
86 EXPORT_SYMBOL_GPL(encrypt_blob);
87 
88 /**
89  * decrypt_blob - Decrypt data using an asymmetric key
90  * @params: Various parameters
91  * @enc: Encrypted data to be decrypted, length params->enc_len
92  * @data: Decrypted data buffer, length params->data_len
93  *
94  * Decrypt the specified data blob using the private key specified by
95  * params->key.  The decrypted data is wrapped in an encoding if
96  * params->encoding is specified (eg. "pkcs1").
97  *
98  * Returns the length of the data placed in the decrypted data buffer or an
99  * error.
100  */
101 int decrypt_blob(struct kernel_pkey_params *params,
102 		 const void *enc, void *data)
103 {
104 	params->op = kernel_pkey_decrypt;
105 	return asymmetric_key_eds_op(params, enc, data);
106 }
107 EXPORT_SYMBOL_GPL(decrypt_blob);
108 
109 /**
110  * create_signature - Sign some data using an asymmetric key
111  * @params: Various parameters
112  * @data: Data blob to be signed, length params->data_len
113  * @enc: Signature buffer, length params->enc_len
114  *
115  * Sign the specified data blob using the private key specified by params->key.
116  * The signature is wrapped in an encoding if params->encoding is specified
117  * (eg. "pkcs1").  If the encoding needs to know the digest type, this can be
118  * passed through params->hash_algo (eg. "sha1").
119  *
120  * Returns the length of the data placed in the signature buffer or an error.
121  */
122 int create_signature(struct kernel_pkey_params *params,
123 		     const void *data, void *enc)
124 {
125 	params->op = kernel_pkey_sign;
126 	return asymmetric_key_eds_op(params, data, enc);
127 }
128 EXPORT_SYMBOL_GPL(create_signature);
129 
130 /**
131  * verify_signature - Initiate the use of an asymmetric key to verify a signature
132  * @key: The asymmetric key to verify against
133  * @sig: The signature to check
134  *
135  * Returns 0 if successful or else an error.
136  */
137 int verify_signature(const struct key *key,
138 		     const struct public_key_signature *sig)
139 {
140 	const struct asymmetric_key_subtype *subtype;
141 	int ret;
142 
143 	pr_devel("==>%s()\n", __func__);
144 
145 	if (key->type != &key_type_asymmetric)
146 		return -EINVAL;
147 	subtype = asymmetric_key_subtype(key);
148 	if (!subtype ||
149 	    !key->payload.data[0])
150 		return -EINVAL;
151 	if (!subtype->verify_signature)
152 		return -ENOTSUPP;
153 
154 	ret = subtype->verify_signature(key, sig);
155 
156 	pr_devel("<==%s() = %d\n", __func__, ret);
157 	return ret;
158 }
159 EXPORT_SYMBOL_GPL(verify_signature);
160