1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/errno.h>
26 #include <sys/types.h>
27 #include <sys/kmem.h>
28 #include <sys/sysmacros.h>
29 #include <sys/crypto/common.h>
30 #include <sys/crypto/impl.h>
31 #include <sys/crypto/api.h>
32 #include <sys/crypto/spi.h>
33 #include <sys/crypto/sched_impl.h>
34
35 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
36 #define CRYPTO_MAC_OFFSET(f) offsetof(crypto_mac_ops_t, f)
37
38 /*
39 * Message authentication codes routines.
40 */
41
42 /*
43 * The following are the possible returned values common to all the routines
44 * below. The applicability of some of these return values depends on the
45 * presence of the arguments.
46 *
47 * CRYPTO_SUCCESS: The operation completed successfully.
48 * CRYPTO_QUEUED: A request was submitted successfully. The callback
49 * routine will be called when the operation is done.
50 * CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or
51 * CRYPTO_INVALID_MECH for problems with the 'mech'.
52 * CRYPTO_INVALID_DATA for bogus 'data'
53 * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
54 * CRYPTO_INVALID_CONTEXT: Not a valid context.
55 * CRYPTO_BUSY: Cannot process the request now. Schedule a
56 * crypto_bufcall(), or try later.
57 * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is
58 * capable of a function or a mechanism.
59 * CRYPTO_INVALID_KEY: bogus 'key' argument.
60 * CRYPTO_INVALID_MAC: bogus 'mac' argument.
61 */
62
63 /*
64 * crypto_mac_prov()
65 *
66 * Arguments:
67 * mech: crypto_mechanism_t pointer.
68 * mech_type is a valid value previously returned by
69 * crypto_mech2id();
70 * When the mech's parameter is not NULL, its definition depends
71 * on the standard definition of the mechanism.
72 * key: pointer to a crypto_key_t structure.
73 * data: The message to compute the MAC for.
74 * mac: Storage for the MAC. The length needed depends on the mechanism.
75 * tmpl: a crypto_ctx_template_t, opaque template of a context of a
76 * MAC with the 'mech' using 'key'. 'tmpl' is created by
77 * a previous call to crypto_create_ctx_template().
78 * cr: crypto_call_req_t calling conditions and call back info.
79 *
80 * Description:
81 * Asynchronously submits a request for, or synchronously performs a
82 * single-part message authentication of 'data' with the mechanism
83 * 'mech', using * the key 'key', on the specified provider with
84 * the specified session id.
85 * When complete and successful, 'mac' will contain the message
86 * authentication code.
87 *
88 * Context:
89 * Process or interrupt, according to the semantics dictated by the 'crq'.
90 *
91 * Returns:
92 * See comment in the beginning of the file.
93 */
94 int
crypto_mac_prov(crypto_provider_t provider,crypto_session_id_t sid,crypto_mechanism_t * mech,crypto_data_t * data,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * mac,crypto_call_req_t * crq)95 crypto_mac_prov(crypto_provider_t provider, crypto_session_id_t sid,
96 crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key,
97 crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq)
98 {
99 kcf_req_params_t params;
100 kcf_provider_desc_t *pd = provider;
101 kcf_provider_desc_t *real_provider = pd;
102 int rv;
103
104 ASSERT(KCF_PROV_REFHELD(pd));
105
106 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
107 rv = kcf_get_hardware_provider(mech->cm_type, key,
108 CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
109 CRYPTO_FG_MAC_ATOMIC);
110
111 if (rv != CRYPTO_SUCCESS)
112 return (rv);
113 }
114
115 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key,
116 data, mac, tmpl);
117 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE);
118 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
119 KCF_PROV_REFRELE(real_provider);
120
121 return (rv);
122 }
123
124 /*
125 * Same as crypto_mac_prov(), but relies on the KCF scheduler to choose
126 * a provider. See crypto_mac() comments for more information.
127 */
128 int
crypto_mac(crypto_mechanism_t * mech,crypto_data_t * data,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * mac,crypto_call_req_t * crq)129 crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data,
130 crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac,
131 crypto_call_req_t *crq)
132 {
133 int error;
134 kcf_mech_entry_t *me;
135 kcf_req_params_t params;
136 kcf_provider_desc_t *pd;
137 kcf_ctx_template_t *ctx_tmpl;
138 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
139 kcf_prov_tried_t *list = NULL;
140
141 retry:
142 /* The pd is returned held */
143 if ((pd = kcf_get_mech_provider(mech->cm_type, key, &me, &error,
144 list, CRYPTO_FG_MAC_ATOMIC, data->cd_length)) == NULL) {
145 if (list != NULL)
146 kcf_free_triedlist(list);
147 return (error);
148 }
149
150 /*
151 * For SW providers, check the validity of the context template
152 * It is very rare that the generation number mis-matches, so
153 * is acceptable to fail here, and let the consumer recover by
154 * freeing this tmpl and create a new one for the key and new SW
155 * provider
156 */
157 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
158 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
159 if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
160 if (list != NULL)
161 kcf_free_triedlist(list);
162 KCF_PROV_REFRELE(pd);
163 return (CRYPTO_OLD_CTX_TEMPLATE);
164 } else {
165 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
166 }
167 }
168
169 /* The fast path for SW providers. */
170 if (CHECK_FASTPATH(crq, pd)) {
171 crypto_mechanism_t lmech;
172
173 lmech = *mech;
174 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
175
176 error = KCF_PROV_MAC_ATOMIC(pd, pd->pd_sid, &lmech, key, data,
177 mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq));
178 KCF_PROV_INCRSTATS(pd, error);
179 } else {
180 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
181 (pd->pd_flags & CRYPTO_HMAC_NO_UPDATE) &&
182 (data->cd_length > pd->pd_hmac_limit)) {
183 /*
184 * XXX - We need a check to see if this is indeed
185 * a HMAC. So far, all kernel clients use
186 * this interface only for HMAC. So, this is fine
187 * for now.
188 */
189 error = CRYPTO_BUFFER_TOO_BIG;
190 } else {
191 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC,
192 pd->pd_sid, mech, key, data, mac, spi_ctx_tmpl);
193
194 error = kcf_submit_request(pd, NULL, crq, ¶ms,
195 KCF_ISDUALREQ(crq));
196 }
197 }
198
199 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
200 IS_RECOVERABLE(error)) {
201 /* Add pd to the linked list of providers tried. */
202 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
203 goto retry;
204 }
205
206 if (list != NULL)
207 kcf_free_triedlist(list);
208
209 KCF_PROV_REFRELE(pd);
210 return (error);
211 }
212
213 /*
214 * Single part operation to compute the MAC corresponding to the specified
215 * 'data' and to verify that it matches the MAC specified by 'mac'.
216 * The other arguments are the same as the function crypto_mac_prov().
217 */
218 int
crypto_mac_verify_prov(crypto_provider_t provider,crypto_session_id_t sid,crypto_mechanism_t * mech,crypto_data_t * data,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * mac,crypto_call_req_t * crq)219 crypto_mac_verify_prov(crypto_provider_t provider, crypto_session_id_t sid,
220 crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key,
221 crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq)
222 {
223 kcf_req_params_t params;
224 kcf_provider_desc_t *pd = provider;
225 kcf_provider_desc_t *real_provider = pd;
226 int rv;
227
228 ASSERT(KCF_PROV_REFHELD(pd));
229
230 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
231 rv = kcf_get_hardware_provider(mech->cm_type, key,
232 CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
233 CRYPTO_FG_MAC_ATOMIC);
234
235 if (rv != CRYPTO_SUCCESS)
236 return (rv);
237 }
238
239 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech,
240 key, data, mac, tmpl);
241 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE);
242 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
243 KCF_PROV_REFRELE(real_provider);
244
245 return (rv);
246 }
247
248 /*
249 * Same as crypto_mac_verify_prov(), but relies on the KCF scheduler to choose
250 * a provider. See crypto_mac_verify_prov() comments for more information.
251 */
252 int
crypto_mac_verify(crypto_mechanism_t * mech,crypto_data_t * data,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * mac,crypto_call_req_t * crq)253 crypto_mac_verify(crypto_mechanism_t *mech, crypto_data_t *data,
254 crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac,
255 crypto_call_req_t *crq)
256 {
257 int error;
258 kcf_mech_entry_t *me;
259 kcf_req_params_t params;
260 kcf_provider_desc_t *pd;
261 kcf_ctx_template_t *ctx_tmpl;
262 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
263 kcf_prov_tried_t *list = NULL;
264
265 retry:
266 /* The pd is returned held */
267 if ((pd = kcf_get_mech_provider(mech->cm_type, key, &me, &error,
268 list, CRYPTO_FG_MAC_ATOMIC, data->cd_length)) == NULL) {
269 if (list != NULL)
270 kcf_free_triedlist(list);
271 return (error);
272 }
273
274 /*
275 * For SW providers, check the validity of the context template
276 * It is very rare that the generation number mis-matches, so
277 * is acceptable to fail here, and let the consumer recover by
278 * freeing this tmpl and create a new one for the key and new SW
279 * provider
280 */
281 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
282 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
283 if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
284 if (list != NULL)
285 kcf_free_triedlist(list);
286 KCF_PROV_REFRELE(pd);
287 return (CRYPTO_OLD_CTX_TEMPLATE);
288 } else {
289 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
290 }
291 }
292
293 /* The fast path for SW providers. */
294 if (CHECK_FASTPATH(crq, pd)) {
295 crypto_mechanism_t lmech;
296
297 lmech = *mech;
298 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
299
300 error = KCF_PROV_MAC_VERIFY_ATOMIC(pd, pd->pd_sid, &lmech, key,
301 data, mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq));
302 KCF_PROV_INCRSTATS(pd, error);
303 } else {
304 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
305 (pd->pd_flags & CRYPTO_HMAC_NO_UPDATE) &&
306 (data->cd_length > pd->pd_hmac_limit)) {
307 /* see comments in crypto_mac() */
308 error = CRYPTO_BUFFER_TOO_BIG;
309 } else {
310 KCF_WRAP_MAC_OPS_PARAMS(¶ms,
311 KCF_OP_MAC_VERIFY_ATOMIC, pd->pd_sid, mech,
312 key, data, mac, spi_ctx_tmpl);
313
314 error = kcf_submit_request(pd, NULL, crq, ¶ms,
315 KCF_ISDUALREQ(crq));
316 }
317 }
318
319 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
320 IS_RECOVERABLE(error)) {
321 /* Add pd to the linked list of providers tried. */
322 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
323 goto retry;
324 }
325
326 if (list != NULL)
327 kcf_free_triedlist(list);
328
329 KCF_PROV_REFRELE(pd);
330 return (error);
331 }
332
333
334 /*
335 * crypto_mac_init_prov()
336 *
337 * Arguments:
338 * pd: pointer to the descriptor of the provider to use for this
339 * operation.
340 * sid: provider session id.
341 * mech: crypto_mechanism_t pointer.
342 * mech_type is a valid value previously returned by
343 * crypto_mech2id();
344 * When the mech's parameter is not NULL, its definition depends
345 * on the standard definition of the mechanism.
346 * key: pointer to a crypto_key_t structure.
347 * tmpl: a crypto_ctx_template_t, opaque template of a context of a
348 * MAC with the 'mech' using 'key'. 'tmpl' is created by
349 * a previous call to crypto_create_ctx_template().
350 * ctxp: Pointer to a crypto_context_t.
351 * cr: crypto_call_req_t calling conditions and call back info.
352 *
353 * Description:
354 * Asynchronously submits a request for, or synchronously performs the
355 * initialization of a MAC operation on the specified provider with
356 * the specified session.
357 * When possible and applicable, will internally use the pre-computed MAC
358 * context from the context template, tmpl.
359 * When complete and successful, 'ctxp' will contain a crypto_context_t
360 * valid for later calls to mac_update() and mac_final().
361 * The caller should hold a reference on the specified provider
362 * descriptor before calling this function.
363 *
364 * Context:
365 * Process or interrupt, according to the semantics dictated by the 'cr'.
366 *
367 * Returns:
368 * See comment in the beginning of the file.
369 */
370 int
crypto_mac_init_prov(crypto_provider_t provider,crypto_session_id_t sid,crypto_mechanism_t * mech,crypto_key_t * key,crypto_spi_ctx_template_t tmpl,crypto_context_t * ctxp,crypto_call_req_t * crq)371 crypto_mac_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
372 crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl,
373 crypto_context_t *ctxp, crypto_call_req_t *crq)
374 {
375 int rv;
376 crypto_ctx_t *ctx;
377 kcf_req_params_t params;
378 kcf_provider_desc_t *pd = provider;
379 kcf_provider_desc_t *real_provider = pd;
380
381 ASSERT(KCF_PROV_REFHELD(pd));
382
383 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
384 rv = kcf_get_hardware_provider(mech->cm_type, key,
385 CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
386 CRYPTO_FG_MAC);
387
388 if (rv != CRYPTO_SUCCESS)
389 return (rv);
390 }
391
392 /* Allocate and initialize the canonical context */
393 if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
394 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
395 KCF_PROV_REFRELE(real_provider);
396 return (CRYPTO_HOST_MEMORY);
397 }
398
399 /* The fast path for SW providers. */
400 if (CHECK_FASTPATH(crq, pd)) {
401 crypto_mechanism_t lmech;
402
403 lmech = *mech;
404 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
405 rv = KCF_PROV_MAC_INIT(real_provider, ctx, &lmech, key, tmpl,
406 KCF_SWFP_RHNDL(crq));
407 KCF_PROV_INCRSTATS(pd, rv);
408 } else {
409 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, mech, key,
410 NULL, NULL, tmpl);
411 rv = kcf_submit_request(real_provider, ctx, crq, ¶ms,
412 B_FALSE);
413 }
414
415 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
416 KCF_PROV_REFRELE(real_provider);
417
418 if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
419 *ctxp = (crypto_context_t)ctx;
420 else {
421 /* Release the hold done in kcf_new_ctx(). */
422 KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
423 }
424
425 return (rv);
426 }
427
428 /*
429 * Same as crypto_mac_init_prov(), but relies on the KCF scheduler to
430 * choose a provider. See crypto_mac_init_prov() comments for more
431 * information.
432 */
433 int
crypto_mac_init(crypto_mechanism_t * mech,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_context_t * ctxp,crypto_call_req_t * crq)434 crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key,
435 crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
436 crypto_call_req_t *crq)
437 {
438 int error;
439 kcf_mech_entry_t *me;
440 kcf_provider_desc_t *pd;
441 kcf_ctx_template_t *ctx_tmpl;
442 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
443 kcf_prov_tried_t *list = NULL;
444
445 retry:
446 /* The pd is returned held */
447 if ((pd = kcf_get_mech_provider(mech->cm_type, key, &me, &error,
448 list, CRYPTO_FG_MAC, 0)) == NULL) {
449 if (list != NULL)
450 kcf_free_triedlist(list);
451 return (error);
452 }
453
454 /*
455 * For SW providers, check the validity of the context template
456 * It is very rare that the generation number mis-matches, so
457 * is acceptable to fail here, and let the consumer recover by
458 * freeing this tmpl and create a new one for the key and new SW
459 * provider
460 */
461
462 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
463 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
464 if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
465 if (list != NULL)
466 kcf_free_triedlist(list);
467 KCF_PROV_REFRELE(pd);
468 return (CRYPTO_OLD_CTX_TEMPLATE);
469 } else {
470 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
471 }
472 }
473
474 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
475 (pd->pd_flags & CRYPTO_HMAC_NO_UPDATE)) {
476 /*
477 * The hardware provider has limited HMAC support.
478 * So, we fallback early here to using a software provider.
479 *
480 * XXX - need to enhance to do the fallback later in
481 * crypto_mac_update() if the size of accumulated input data
482 * exceeds the maximum size digestable by hardware provider.
483 */
484 error = CRYPTO_BUFFER_TOO_BIG;
485 } else {
486 error = crypto_mac_init_prov(pd, pd->pd_sid, mech, key,
487 spi_ctx_tmpl, ctxp, crq);
488 }
489 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
490 IS_RECOVERABLE(error)) {
491 /* Add pd to the linked list of providers tried. */
492 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
493 goto retry;
494 }
495
496 if (list != NULL)
497 kcf_free_triedlist(list);
498
499 KCF_PROV_REFRELE(pd);
500 return (error);
501 }
502
503 /*
504 * crypto_mac_update()
505 *
506 * Arguments:
507 * context: A crypto_context_t initialized by mac_init().
508 * data: The message part to be MAC'ed
509 * cr: crypto_call_req_t calling conditions and call back info.
510 *
511 * Description:
512 * Asynchronously submits a request for, or synchronously performs a
513 * part of a MAC operation.
514 *
515 * Context:
516 * Process or interrupt, according to the semantics dictated by the 'cr'.
517 *
518 * Returns:
519 * See comment in the beginning of the file.
520 */
521 int
crypto_mac_update(crypto_context_t context,crypto_data_t * data,crypto_call_req_t * cr)522 crypto_mac_update(crypto_context_t context, crypto_data_t *data,
523 crypto_call_req_t *cr)
524 {
525 crypto_ctx_t *ctx = (crypto_ctx_t *)context;
526 kcf_context_t *kcf_ctx;
527 kcf_provider_desc_t *pd;
528 kcf_req_params_t params;
529 int rv;
530
531 if ((ctx == NULL) ||
532 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
533 ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
534 return (CRYPTO_INVALID_CONTEXT);
535 }
536
537 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
538
539 /* The fast path for SW providers. */
540 if (CHECK_FASTPATH(cr, pd)) {
541 rv = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL);
542 KCF_PROV_INCRSTATS(pd, rv);
543 } else {
544 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_UPDATE,
545 ctx->cc_session, NULL, NULL, data, NULL, NULL);
546 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
547 }
548
549 return (rv);
550 }
551
552 /*
553 * crypto_mac_final()
554 *
555 * Arguments:
556 * context: A crypto_context_t initialized by mac_init().
557 * mac: Storage for the message authentication code.
558 * cr: crypto_call_req_t calling conditions and call back info.
559 *
560 * Description:
561 * Asynchronously submits a request for, or synchronously performs a
562 * part of a message authentication operation.
563 *
564 * Context:
565 * Process or interrupt, according to the semantics dictated by the 'cr'.
566 *
567 * Returns:
568 * See comment in the beginning of the file.
569 */
570 int
crypto_mac_final(crypto_context_t context,crypto_data_t * mac,crypto_call_req_t * cr)571 crypto_mac_final(crypto_context_t context, crypto_data_t *mac,
572 crypto_call_req_t *cr)
573 {
574 crypto_ctx_t *ctx = (crypto_ctx_t *)context;
575 kcf_context_t *kcf_ctx;
576 kcf_provider_desc_t *pd;
577 kcf_req_params_t params;
578 int rv;
579
580 if ((ctx == NULL) ||
581 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
582 ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
583 return (CRYPTO_INVALID_CONTEXT);
584 }
585
586 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
587
588 /* The fast path for SW providers. */
589 if (CHECK_FASTPATH(cr, pd)) {
590 rv = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL);
591 KCF_PROV_INCRSTATS(pd, rv);
592 } else {
593 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_FINAL,
594 ctx->cc_session, NULL, NULL, NULL, mac, NULL);
595 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
596 }
597
598 /* Release the hold done in kcf_new_ctx() during init step. */
599 KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx);
600 return (rv);
601 }
602
603 /*
604 * See comments for crypto_mac_update() and crypto_mac_final().
605 */
606 int
crypto_mac_single(crypto_context_t context,crypto_data_t * data,crypto_data_t * mac,crypto_call_req_t * cr)607 crypto_mac_single(crypto_context_t context, crypto_data_t *data,
608 crypto_data_t *mac, crypto_call_req_t *cr)
609 {
610 crypto_ctx_t *ctx = (crypto_ctx_t *)context;
611 kcf_context_t *kcf_ctx;
612 kcf_provider_desc_t *pd;
613 int error;
614 kcf_req_params_t params;
615
616
617 if ((ctx == NULL) ||
618 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
619 ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
620 return (CRYPTO_INVALID_CONTEXT);
621 }
622
623
624 /* The fast path for SW providers. */
625 if (CHECK_FASTPATH(cr, pd)) {
626 error = KCF_PROV_MAC(pd, ctx, data, mac, NULL);
627 KCF_PROV_INCRSTATS(pd, error);
628 } else {
629 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid,
630 NULL, NULL, data, mac, NULL);
631 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
632 }
633
634 /* Release the hold done in kcf_new_ctx() during init step. */
635 KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
636 return (error);
637 }
638