Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/icp/api/kcf_mac.c
48531 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
/*
23
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24
* Use is subject to license terms.
25
*/
26
27
#include <sys/zfs_context.h>
28
#include <sys/crypto/common.h>
29
#include <sys/crypto/impl.h>
30
#include <sys/crypto/api.h>
31
#include <sys/crypto/spi.h>
32
#include <sys/crypto/sched_impl.h>
33
34
/*
35
* Message authentication codes routines.
36
*/
37
38
/*
39
* The following are the possible returned values common to all the routines
40
* below. The applicability of some of these return values depends on the
41
* presence of the arguments.
42
*
43
* CRYPTO_SUCCESS: The operation completed successfully.
44
* CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or
45
* CRYPTO_INVALID_MECH for problems with the 'mech'.
46
* CRYPTO_INVALID_DATA for bogus 'data'
47
* CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
48
* CRYPTO_INVALID_CONTEXT: Not a valid context.
49
* CRYPTO_BUSY: Cannot process the request now. Try later.
50
* CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is
51
* capable of a function or a mechanism.
52
* CRYPTO_INVALID_KEY: bogus 'key' argument.
53
* CRYPTO_INVALID_MAC: bogus 'mac' argument.
54
*/
55
56
/*
57
* crypto_mac_prov()
58
*
59
* Arguments:
60
* mech: crypto_mechanism_t pointer.
61
* mech_type is a valid value previously returned by
62
* crypto_mech2id();
63
* When the mech's parameter is not NULL, its definition depends
64
* on the standard definition of the mechanism.
65
* key: pointer to a crypto_key_t structure.
66
* data: The message to compute the MAC for.
67
* mac: Storage for the MAC. The length needed depends on the mechanism.
68
* tmpl: a crypto_ctx_template_t, opaque template of a context of a
69
* MAC with the 'mech' using 'key'. 'tmpl' is created by
70
* a previous call to crypto_create_ctx_template().
71
*
72
* Description:
73
* Asynchronously submits a request for, or synchronously performs a
74
* single-part message authentication of 'data' with the mechanism
75
* 'mech', using * the key 'key', on the specified provider with
76
* the specified session id.
77
* When complete and successful, 'mac' will contain the message
78
* authentication code.
79
* Relies on the KCF scheduler to choose a provider.
80
*
81
* Returns:
82
* See comment in the beginning of the file.
83
*/
84
int
85
crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data,
86
crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac)
87
{
88
int error;
89
kcf_mech_entry_t *me;
90
kcf_provider_desc_t *pd;
91
kcf_ctx_template_t *ctx_tmpl;
92
crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
93
kcf_prov_tried_t *list = NULL;
94
95
retry:
96
/* The pd is returned held */
97
if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
98
list, CRYPTO_FG_MAC_ATOMIC)) == NULL) {
99
if (list != NULL)
100
kcf_free_triedlist(list);
101
return (error);
102
}
103
104
if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))
105
spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
106
107
crypto_mechanism_t lmech = *mech;
108
KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
109
error = KCF_PROV_MAC_ATOMIC(pd, &lmech, key, data,
110
mac, spi_ctx_tmpl);
111
112
if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {
113
/* Add pd to the linked list of providers tried. */
114
if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)
115
goto retry;
116
}
117
118
if (list != NULL)
119
kcf_free_triedlist(list);
120
121
KCF_PROV_REFRELE(pd);
122
return (error);
123
}
124
125
/*
126
* crypto_mac_init_prov()
127
*
128
* Arguments:
129
* pd: pointer to the descriptor of the provider to use for this
130
* operation.
131
* mech: crypto_mechanism_t pointer.
132
* mech_type is a valid value previously returned by
133
* crypto_mech2id();
134
* When the mech's parameter is not NULL, its definition depends
135
* on the standard definition of the mechanism.
136
* key: pointer to a crypto_key_t structure.
137
* tmpl: a crypto_ctx_template_t, opaque template of a context of a
138
* MAC with the 'mech' using 'key'. 'tmpl' is created by
139
* a previous call to crypto_create_ctx_template().
140
* ctxp: Pointer to a crypto_context_t.
141
*
142
* Description:
143
* Asynchronously submits a request for, or synchronously performs the
144
* initialization of a MAC operation on the specified provider with
145
* the specified session.
146
* When possible and applicable, will internally use the pre-computed MAC
147
* context from the context template, tmpl.
148
* When complete and successful, 'ctxp' will contain a crypto_context_t
149
* valid for later calls to mac_update() and mac_final().
150
* The caller should hold a reference on the specified provider
151
* descriptor before calling this function.
152
*
153
* Returns:
154
* See comment in the beginning of the file.
155
*/
156
static int
157
crypto_mac_init_prov(kcf_provider_desc_t *pd,
158
crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl,
159
crypto_context_t *ctxp)
160
{
161
int rv;
162
crypto_ctx_t *ctx;
163
kcf_provider_desc_t *real_provider = pd;
164
165
ASSERT(KCF_PROV_REFHELD(pd));
166
167
/* Allocate and initialize the canonical context */
168
if ((ctx = kcf_new_ctx(real_provider)) == NULL)
169
return (CRYPTO_HOST_MEMORY);
170
171
crypto_mechanism_t lmech = *mech;
172
KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
173
rv = KCF_PROV_MAC_INIT(real_provider, ctx, &lmech, key, tmpl);
174
175
if (rv == CRYPTO_SUCCESS)
176
*ctxp = (crypto_context_t)ctx;
177
else {
178
/* Release the hold done in kcf_new_ctx(). */
179
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
180
}
181
182
return (rv);
183
}
184
185
/*
186
* Same as crypto_mac_init_prov(), but relies on the KCF scheduler to
187
* choose a provider. See crypto_mac_init_prov() comments for more
188
* information.
189
*/
190
int
191
crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key,
192
crypto_ctx_template_t tmpl, crypto_context_t *ctxp)
193
{
194
int error;
195
kcf_mech_entry_t *me;
196
kcf_provider_desc_t *pd;
197
kcf_ctx_template_t *ctx_tmpl;
198
crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
199
kcf_prov_tried_t *list = NULL;
200
201
retry:
202
/* The pd is returned held */
203
if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
204
list, CRYPTO_FG_MAC)) == NULL) {
205
if (list != NULL)
206
kcf_free_triedlist(list);
207
return (error);
208
}
209
210
/*
211
* Check the validity of the context template
212
* It is very rare that the generation number mis-matches, so
213
* is acceptable to fail here, and let the consumer recover by
214
* freeing this tmpl and create a new one for the key and new provider
215
*/
216
217
if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))
218
spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
219
220
error = crypto_mac_init_prov(pd, mech, key,
221
spi_ctx_tmpl, ctxp);
222
if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {
223
/* Add pd to the linked list of providers tried. */
224
if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)
225
goto retry;
226
}
227
228
if (list != NULL)
229
kcf_free_triedlist(list);
230
231
KCF_PROV_REFRELE(pd);
232
return (error);
233
}
234
235
/*
236
* crypto_mac_update()
237
*
238
* Arguments:
239
* context: A crypto_context_t initialized by mac_init().
240
* data: The message part to be MAC'ed
241
*
242
* Description:
243
* Synchronously performs a part of a MAC operation.
244
*
245
* Returns:
246
* See comment in the beginning of the file.
247
*/
248
int
249
crypto_mac_update(crypto_context_t context, crypto_data_t *data)
250
{
251
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
252
kcf_context_t *kcf_ctx;
253
kcf_provider_desc_t *pd;
254
255
if ((ctx == NULL) ||
256
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
257
((pd = kcf_ctx->kc_prov_desc) == NULL)) {
258
return (CRYPTO_INVALID_CONTEXT);
259
}
260
261
return (KCF_PROV_MAC_UPDATE(pd, ctx, data));
262
}
263
264
/*
265
* crypto_mac_final()
266
*
267
* Arguments:
268
* context: A crypto_context_t initialized by mac_init().
269
* mac: Storage for the message authentication code.
270
*
271
* Description:
272
* Synchronously performs a part of a message authentication operation.
273
*
274
* Returns:
275
* See comment in the beginning of the file.
276
*/
277
int
278
crypto_mac_final(crypto_context_t context, crypto_data_t *mac)
279
{
280
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
281
kcf_context_t *kcf_ctx;
282
kcf_provider_desc_t *pd;
283
284
if ((ctx == NULL) ||
285
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
286
((pd = kcf_ctx->kc_prov_desc) == NULL)) {
287
return (CRYPTO_INVALID_CONTEXT);
288
}
289
290
int rv = KCF_PROV_MAC_FINAL(pd, ctx, mac);
291
292
/* Release the hold done in kcf_new_ctx() during init step. */
293
KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx);
294
return (rv);
295
}
296
297
#if defined(_KERNEL)
298
EXPORT_SYMBOL(crypto_mac);
299
EXPORT_SYMBOL(crypto_mac_init);
300
EXPORT_SYMBOL(crypto_mac_update);
301
EXPORT_SYMBOL(crypto_mac_final);
302
#endif
303
304