1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* Signature verification with an asymmetric key |
3 | * |
4 | * See Documentation/crypto/asymmetric-keys.rst |
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(objp: sig->auth_ids[i]); |
30 | kfree(objp: sig->s); |
31 | kfree(objp: sig->digest); |
32 | kfree(objp: sig); |
33 | } |
34 | } |
35 | EXPORT_SYMBOL_GPL(public_key_signature_free); |
36 | |
37 | /** |
38 | * query_asymmetric_key - Get information about an asymmetric 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, in: data, out: 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, in: enc, out: 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. "sha512"). |
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, in: data, out: 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 | |