]> git.proxmox.com Git - mirror_zfs.git/blob - module/icp/io/skein_mod.c
Add convenience wrappers for common uio usage
[mirror_zfs.git] / module / icp / io / skein_mod.c
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://opensource.org/licenses/CDDL-1.0.
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 /*
23 * Copyright 2013 Saso Kiselkov. All rights reserved.
24 */
25
26 #include <sys/modctl.h>
27 #include <sys/crypto/common.h>
28 #include <sys/crypto/spi.h>
29 #include <sys/sysmacros.h>
30 #define SKEIN_MODULE_IMPL
31 #include <sys/skein.h>
32
33 /*
34 * Like the sha2 module, we create the skein module with two modlinkages:
35 * - modlmisc to allow direct calls to Skein_* API functions.
36 * - modlcrypto to integrate well into the Kernel Crypto Framework (KCF).
37 */
38 static struct modlmisc modlmisc = {
39 &mod_cryptoops,
40 "Skein Message-Digest Algorithm"
41 };
42
43 static struct modlcrypto modlcrypto = {
44 &mod_cryptoops,
45 "Skein Kernel SW Provider"
46 };
47
48 static struct modlinkage modlinkage = {
49 MODREV_1, {&modlmisc, &modlcrypto, NULL}
50 };
51
52 static crypto_mech_info_t skein_mech_info_tab[] = {
53 {CKM_SKEIN_256, SKEIN_256_MECH_INFO_TYPE,
54 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
55 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
56 {CKM_SKEIN_256_MAC, SKEIN_256_MAC_MECH_INFO_TYPE,
57 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX,
58 CRYPTO_KEYSIZE_UNIT_IN_BYTES},
59 {CKM_SKEIN_512, SKEIN_512_MECH_INFO_TYPE,
60 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
61 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
62 {CKM_SKEIN_512_MAC, SKEIN_512_MAC_MECH_INFO_TYPE,
63 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX,
64 CRYPTO_KEYSIZE_UNIT_IN_BYTES},
65 {CKM_SKEIN1024, SKEIN1024_MECH_INFO_TYPE,
66 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
67 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
68 {CKM_SKEIN1024_MAC, SKEIN1024_MAC_MECH_INFO_TYPE,
69 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX,
70 CRYPTO_KEYSIZE_UNIT_IN_BYTES}
71 };
72
73 static void skein_provider_status(crypto_provider_handle_t, uint_t *);
74
75 static crypto_control_ops_t skein_control_ops = {
76 skein_provider_status
77 };
78
79 static int skein_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
80 crypto_req_handle_t);
81 static int skein_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
82 crypto_req_handle_t);
83 static int skein_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
84 static int skein_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
85 static int skein_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
86 crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
87 crypto_req_handle_t);
88
89 static crypto_digest_ops_t skein_digest_ops = {
90 .digest_init = skein_digest_init,
91 .digest = skein_digest,
92 .digest_update = skein_update,
93 .digest_key = NULL,
94 .digest_final = skein_final,
95 .digest_atomic = skein_digest_atomic
96 };
97
98 static int skein_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
99 crypto_spi_ctx_template_t, crypto_req_handle_t);
100 static int skein_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
101 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
102 crypto_spi_ctx_template_t, crypto_req_handle_t);
103
104 static crypto_mac_ops_t skein_mac_ops = {
105 .mac_init = skein_mac_init,
106 .mac = NULL,
107 .mac_update = skein_update, /* using regular digest update is OK here */
108 .mac_final = skein_final, /* using regular digest final is OK here */
109 .mac_atomic = skein_mac_atomic,
110 .mac_verify_atomic = NULL
111 };
112
113 static int skein_create_ctx_template(crypto_provider_handle_t,
114 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
115 size_t *, crypto_req_handle_t);
116 static int skein_free_context(crypto_ctx_t *);
117
118 static crypto_ctx_ops_t skein_ctx_ops = {
119 .create_ctx_template = skein_create_ctx_template,
120 .free_context = skein_free_context
121 };
122
123 static crypto_ops_t skein_crypto_ops = {{{{{
124 &skein_control_ops,
125 &skein_digest_ops,
126 NULL,
127 &skein_mac_ops,
128 NULL,
129 NULL,
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 NULL,
135 NULL,
136 NULL,
137 &skein_ctx_ops,
138 }}}}};
139
140 static crypto_provider_info_t skein_prov_info = {{{{
141 CRYPTO_SPI_VERSION_1,
142 "Skein Software Provider",
143 CRYPTO_SW_PROVIDER,
144 NULL,
145 &skein_crypto_ops,
146 sizeof (skein_mech_info_tab) / sizeof (crypto_mech_info_t),
147 skein_mech_info_tab
148 }}}};
149
150 static crypto_kcf_provider_handle_t skein_prov_handle = 0;
151
152 typedef struct skein_ctx {
153 skein_mech_type_t sc_mech_type;
154 size_t sc_digest_bitlen;
155 /*LINTED(E_ANONYMOUS_UNION_DECL)*/
156 union {
157 Skein_256_Ctxt_t sc_256;
158 Skein_512_Ctxt_t sc_512;
159 Skein1024_Ctxt_t sc_1024;
160 };
161 } skein_ctx_t;
162 #define SKEIN_CTX(_ctx_) ((skein_ctx_t *)((_ctx_)->cc_provider_private))
163 #define SKEIN_CTX_LVALUE(_ctx_) (_ctx_)->cc_provider_private
164 #define SKEIN_OP(_skein_ctx, _op, ...) \
165 do { \
166 skein_ctx_t *sc = (_skein_ctx); \
167 switch (sc->sc_mech_type) { \
168 case SKEIN_256_MECH_INFO_TYPE: \
169 case SKEIN_256_MAC_MECH_INFO_TYPE: \
170 (void) Skein_256_ ## _op(&sc->sc_256, __VA_ARGS__);\
171 break; \
172 case SKEIN_512_MECH_INFO_TYPE: \
173 case SKEIN_512_MAC_MECH_INFO_TYPE: \
174 (void) Skein_512_ ## _op(&sc->sc_512, __VA_ARGS__);\
175 break; \
176 case SKEIN1024_MECH_INFO_TYPE: \
177 case SKEIN1024_MAC_MECH_INFO_TYPE: \
178 (void) Skein1024_ ## _op(&sc->sc_1024, __VA_ARGS__);\
179 break; \
180 } \
181 _NOTE(CONSTCOND) \
182 } while (0)
183
184 static int
185 skein_get_digest_bitlen(const crypto_mechanism_t *mechanism, size_t *result)
186 {
187 if (mechanism->cm_param != NULL) {
188 /*LINTED(E_BAD_PTR_CAST_ALIGN)*/
189 skein_param_t *param = (skein_param_t *)mechanism->cm_param;
190
191 if (mechanism->cm_param_len != sizeof (*param) ||
192 param->sp_digest_bitlen == 0) {
193 return (CRYPTO_MECHANISM_PARAM_INVALID);
194 }
195 *result = param->sp_digest_bitlen;
196 } else {
197 switch (mechanism->cm_type) {
198 case SKEIN_256_MECH_INFO_TYPE:
199 *result = 256;
200 break;
201 case SKEIN_512_MECH_INFO_TYPE:
202 *result = 512;
203 break;
204 case SKEIN1024_MECH_INFO_TYPE:
205 *result = 1024;
206 break;
207 default:
208 return (CRYPTO_MECHANISM_INVALID);
209 }
210 }
211 return (CRYPTO_SUCCESS);
212 }
213
214 int
215 skein_mod_init(void)
216 {
217 int error;
218
219 if ((error = mod_install(&modlinkage)) != 0)
220 return (error);
221
222 /*
223 * Try to register with KCF - failure shouldn't unload us, since we
224 * still may want to continue providing misc/skein functionality.
225 */
226 (void) crypto_register_provider(&skein_prov_info, &skein_prov_handle);
227
228 return (0);
229 }
230
231 int
232 skein_mod_fini(void)
233 {
234 int ret;
235
236 if (skein_prov_handle != 0) {
237 if ((ret = crypto_unregister_provider(skein_prov_handle)) !=
238 CRYPTO_SUCCESS) {
239 cmn_err(CE_WARN,
240 "skein _fini: crypto_unregister_provider() "
241 "failed (0x%x)", ret);
242 return (EBUSY);
243 }
244 skein_prov_handle = 0;
245 }
246
247 return (mod_remove(&modlinkage));
248 }
249
250 /*
251 * KCF software provider control entry points.
252 */
253 /* ARGSUSED */
254 static void
255 skein_provider_status(crypto_provider_handle_t provider, uint_t *status)
256 {
257 *status = CRYPTO_PROVIDER_READY;
258 }
259
260 /*
261 * General Skein hashing helper functions.
262 */
263
264 /*
265 * Performs an Update on a context with uio input data.
266 */
267 static int
268 skein_digest_update_uio(skein_ctx_t *ctx, const crypto_data_t *data)
269 {
270 off_t offset = data->cd_offset;
271 size_t length = data->cd_length;
272 uint_t vec_idx = 0;
273 size_t cur_len;
274 uio_t *uio = data->cd_uio;
275
276 /* we support only kernel buffer */
277 if (uio_segflg(uio) != UIO_SYSSPACE)
278 return (CRYPTO_ARGUMENTS_BAD);
279
280 /*
281 * Jump to the first iovec containing data to be
282 * digested.
283 */
284 offset = uio_index_at_offset(uio, offset, &vec_idx);
285 if (vec_idx == uio_iovcnt(uio)) {
286 /*
287 * The caller specified an offset that is larger than the
288 * total size of the buffers it provided.
289 */
290 return (CRYPTO_DATA_LEN_RANGE);
291 }
292
293 /*
294 * Now do the digesting on the iovecs.
295 */
296 while (vec_idx < uio_iovcnt(uio) && length > 0) {
297 cur_len = MIN(uio_iovlen(uio, vec_idx) - offset, length);
298 SKEIN_OP(ctx, Update, (uint8_t *)uio_iovbase(uio, vec_idx)
299 + offset, cur_len);
300 length -= cur_len;
301 vec_idx++;
302 offset = 0;
303 }
304
305 if (vec_idx == uio_iovcnt(uio) && length > 0) {
306 /*
307 * The end of the specified iovec's was reached but
308 * the length requested could not be processed, i.e.
309 * The caller requested to digest more data than it provided.
310 */
311 return (CRYPTO_DATA_LEN_RANGE);
312 }
313
314 return (CRYPTO_SUCCESS);
315 }
316
317 /*
318 * Performs a Final on a context and writes to a uio digest output.
319 */
320 static int
321 skein_digest_final_uio(skein_ctx_t *ctx, crypto_data_t *digest,
322 crypto_req_handle_t req)
323 {
324 off_t offset = digest->cd_offset;
325 uint_t vec_idx = 0;
326 uio_t *uio = digest->cd_uio;
327
328 /* we support only kernel buffer */
329 if (uio_segflg(uio) != UIO_SYSSPACE)
330 return (CRYPTO_ARGUMENTS_BAD);
331
332 /*
333 * Jump to the first iovec containing ptr to the digest to be returned.
334 */
335 offset = uio_index_at_offset(uio, offset, &vec_idx);
336 if (vec_idx == uio_iovcnt(uio)) {
337 /*
338 * The caller specified an offset that is larger than the
339 * total size of the buffers it provided.
340 */
341 return (CRYPTO_DATA_LEN_RANGE);
342 }
343 if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <=
344 uio_iovlen(uio, vec_idx)) {
345 /* The computed digest will fit in the current iovec. */
346 SKEIN_OP(ctx, Final,
347 (uchar_t *)uio_iovbase(uio, vec_idx) + offset);
348 } else {
349 uint8_t *digest_tmp;
350 off_t scratch_offset = 0;
351 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen);
352 size_t cur_len;
353
354 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES(
355 ctx->sc_digest_bitlen), crypto_kmflag(req));
356 if (digest_tmp == NULL)
357 return (CRYPTO_HOST_MEMORY);
358 SKEIN_OP(ctx, Final, digest_tmp);
359 while (vec_idx < uio_iovcnt(uio) && length > 0) {
360 cur_len = MIN(uio_iovlen(uio, vec_idx) - offset,
361 length);
362 bcopy(digest_tmp + scratch_offset,
363 uio_iovbase(uio, vec_idx) + offset, cur_len);
364
365 length -= cur_len;
366 vec_idx++;
367 scratch_offset += cur_len;
368 offset = 0;
369 }
370 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen));
371
372 if (vec_idx == uio_iovcnt(uio) && length > 0) {
373 /*
374 * The end of the specified iovec's was reached but
375 * the length requested could not be processed, i.e.
376 * The caller requested to digest more data than it
377 * provided.
378 */
379 return (CRYPTO_DATA_LEN_RANGE);
380 }
381 }
382
383 return (CRYPTO_SUCCESS);
384 }
385
386 /*
387 * KCF software provider digest entry points.
388 */
389
390 /*
391 * Initializes a skein digest context to the configuration in `mechanism'.
392 * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param
393 * field may contain a skein_param_t structure indicating the length of the
394 * digest the algorithm should produce. Otherwise the default output lengths
395 * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes
396 * for Skein-1024).
397 */
398 static int
399 skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
400 crypto_req_handle_t req)
401 {
402 int error = CRYPTO_SUCCESS;
403
404 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type))
405 return (CRYPTO_MECHANISM_INVALID);
406
407 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)),
408 crypto_kmflag(req));
409 if (SKEIN_CTX(ctx) == NULL)
410 return (CRYPTO_HOST_MEMORY);
411
412 SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type;
413 error = skein_get_digest_bitlen(mechanism,
414 &SKEIN_CTX(ctx)->sc_digest_bitlen);
415 if (error != CRYPTO_SUCCESS)
416 goto errout;
417 SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen);
418
419 return (CRYPTO_SUCCESS);
420 errout:
421 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
422 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
423 SKEIN_CTX_LVALUE(ctx) = NULL;
424 return (error);
425 }
426
427 /*
428 * Executes a skein_update and skein_digest on a pre-initialized crypto
429 * context in a single step. See the documentation to these functions to
430 * see what to pass here.
431 */
432 static int
433 skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
434 crypto_req_handle_t req)
435 {
436 int error = CRYPTO_SUCCESS;
437
438 ASSERT(SKEIN_CTX(ctx) != NULL);
439
440 if (digest->cd_length <
441 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) {
442 digest->cd_length =
443 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
444 return (CRYPTO_BUFFER_TOO_SMALL);
445 }
446
447 error = skein_update(ctx, data, req);
448 if (error != CRYPTO_SUCCESS) {
449 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
450 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
451 SKEIN_CTX_LVALUE(ctx) = NULL;
452 digest->cd_length = 0;
453 return (error);
454 }
455 error = skein_final(ctx, digest, req);
456
457 return (error);
458 }
459
460 /*
461 * Performs a skein Update with the input message in `data' (successive calls
462 * can push more data). This is used both for digest and MAC operation.
463 * Supported input data formats are raw, uio and mblk.
464 */
465 /*ARGSUSED*/
466 static int
467 skein_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
468 {
469 int error = CRYPTO_SUCCESS;
470
471 ASSERT(SKEIN_CTX(ctx) != NULL);
472
473 switch (data->cd_format) {
474 case CRYPTO_DATA_RAW:
475 SKEIN_OP(SKEIN_CTX(ctx), Update,
476 (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
477 data->cd_length);
478 break;
479 case CRYPTO_DATA_UIO:
480 error = skein_digest_update_uio(SKEIN_CTX(ctx), data);
481 break;
482 default:
483 error = CRYPTO_ARGUMENTS_BAD;
484 }
485
486 return (error);
487 }
488
489 /*
490 * Performs a skein Final, writing the output to `digest'. This is used both
491 * for digest and MAC operation.
492 * Supported output digest formats are raw, uio and mblk.
493 */
494 /*ARGSUSED*/
495 static int
496 skein_final(crypto_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req)
497 {
498 int error = CRYPTO_SUCCESS;
499
500 ASSERT(SKEIN_CTX(ctx) != NULL);
501
502 if (digest->cd_length <
503 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) {
504 digest->cd_length =
505 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
506 return (CRYPTO_BUFFER_TOO_SMALL);
507 }
508
509 switch (digest->cd_format) {
510 case CRYPTO_DATA_RAW:
511 SKEIN_OP(SKEIN_CTX(ctx), Final,
512 (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset);
513 break;
514 case CRYPTO_DATA_UIO:
515 error = skein_digest_final_uio(SKEIN_CTX(ctx), digest, req);
516 break;
517 default:
518 error = CRYPTO_ARGUMENTS_BAD;
519 }
520
521 if (error == CRYPTO_SUCCESS)
522 digest->cd_length =
523 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
524 else
525 digest->cd_length = 0;
526
527 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
528 kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx))));
529 SKEIN_CTX_LVALUE(ctx) = NULL;
530
531 return (error);
532 }
533
534 /*
535 * Performs a full skein digest computation in a single call, configuring the
536 * algorithm according to `mechanism', reading the input to be digested from
537 * `data' and writing the output to `digest'.
538 * Supported input/output formats are raw, uio and mblk.
539 */
540 /*ARGSUSED*/
541 static int
542 skein_digest_atomic(crypto_provider_handle_t provider,
543 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
544 crypto_data_t *data, crypto_data_t *digest, crypto_req_handle_t req)
545 {
546 int error;
547 skein_ctx_t skein_ctx;
548 crypto_ctx_t ctx;
549 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx;
550
551 /* Init */
552 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type))
553 return (CRYPTO_MECHANISM_INVALID);
554 skein_ctx.sc_mech_type = mechanism->cm_type;
555 error = skein_get_digest_bitlen(mechanism, &skein_ctx.sc_digest_bitlen);
556 if (error != CRYPTO_SUCCESS)
557 goto out;
558 SKEIN_OP(&skein_ctx, Init, skein_ctx.sc_digest_bitlen);
559
560 if ((error = skein_update(&ctx, data, digest)) != CRYPTO_SUCCESS)
561 goto out;
562 if ((error = skein_final(&ctx, data, digest)) != CRYPTO_SUCCESS)
563 goto out;
564
565 out:
566 if (error == CRYPTO_SUCCESS)
567 digest->cd_length =
568 CRYPTO_BITS2BYTES(skein_ctx.sc_digest_bitlen);
569 else
570 digest->cd_length = 0;
571 bzero(&skein_ctx, sizeof (skein_ctx));
572
573 return (error);
574 }
575
576 /*
577 * Helper function that builds a Skein MAC context from the provided
578 * mechanism and key.
579 */
580 static int
581 skein_mac_ctx_build(skein_ctx_t *ctx, crypto_mechanism_t *mechanism,
582 crypto_key_t *key)
583 {
584 int error;
585
586 if (!VALID_SKEIN_MAC_MECH(mechanism->cm_type))
587 return (CRYPTO_MECHANISM_INVALID);
588 if (key->ck_format != CRYPTO_KEY_RAW)
589 return (CRYPTO_ARGUMENTS_BAD);
590 ctx->sc_mech_type = mechanism->cm_type;
591 error = skein_get_digest_bitlen(mechanism, &ctx->sc_digest_bitlen);
592 if (error != CRYPTO_SUCCESS)
593 return (error);
594 SKEIN_OP(ctx, InitExt, ctx->sc_digest_bitlen, 0, key->ck_data,
595 CRYPTO_BITS2BYTES(key->ck_length));
596
597 return (CRYPTO_SUCCESS);
598 }
599
600 /*
601 * KCF software provide mac entry points.
602 */
603 /*
604 * Initializes a skein MAC context. You may pass a ctx_template, in which
605 * case the template will be reused to make initialization more efficient.
606 * Otherwise a new context will be constructed. The mechanism cm_type must
607 * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you
608 * may pass a skein_param_t in cm_param to configure the length of the
609 * digest. The key must be in raw format.
610 */
611 static int
612 skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
613 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
614 crypto_req_handle_t req)
615 {
616 int error;
617
618 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)),
619 crypto_kmflag(req));
620 if (SKEIN_CTX(ctx) == NULL)
621 return (CRYPTO_HOST_MEMORY);
622
623 if (ctx_template != NULL) {
624 bcopy(ctx_template, SKEIN_CTX(ctx),
625 sizeof (*SKEIN_CTX(ctx)));
626 } else {
627 error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key);
628 if (error != CRYPTO_SUCCESS)
629 goto errout;
630 }
631
632 return (CRYPTO_SUCCESS);
633 errout:
634 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
635 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
636 return (error);
637 }
638
639 /*
640 * The MAC update and final calls are reused from the regular digest code.
641 */
642
643 /*ARGSUSED*/
644 /*
645 * Same as skein_digest_atomic, performs an atomic Skein MAC operation in
646 * one step. All the same properties apply to the arguments of this
647 * function as to those of the partial operations above.
648 */
649 static int
650 skein_mac_atomic(crypto_provider_handle_t provider,
651 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
652 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
653 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
654 {
655 /* faux crypto context just for skein_digest_{update,final} */
656 int error;
657 crypto_ctx_t ctx;
658 skein_ctx_t skein_ctx;
659 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx;
660
661 if (ctx_template != NULL) {
662 bcopy(ctx_template, &skein_ctx, sizeof (skein_ctx));
663 } else {
664 error = skein_mac_ctx_build(&skein_ctx, mechanism, key);
665 if (error != CRYPTO_SUCCESS)
666 goto errout;
667 }
668
669 if ((error = skein_update(&ctx, data, req)) != CRYPTO_SUCCESS)
670 goto errout;
671 if ((error = skein_final(&ctx, mac, req)) != CRYPTO_SUCCESS)
672 goto errout;
673
674 return (CRYPTO_SUCCESS);
675 errout:
676 bzero(&skein_ctx, sizeof (skein_ctx));
677 return (error);
678 }
679
680 /*
681 * KCF software provider context management entry points.
682 */
683
684 /*
685 * Constructs a context template for the Skein MAC algorithm. The same
686 * properties apply to the arguments of this function as to those of
687 * skein_mac_init.
688 */
689 /*ARGSUSED*/
690 static int
691 skein_create_ctx_template(crypto_provider_handle_t provider,
692 crypto_mechanism_t *mechanism, crypto_key_t *key,
693 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
694 crypto_req_handle_t req)
695 {
696 int error;
697 skein_ctx_t *ctx_tmpl;
698
699 ctx_tmpl = kmem_alloc(sizeof (*ctx_tmpl), crypto_kmflag(req));
700 if (ctx_tmpl == NULL)
701 return (CRYPTO_HOST_MEMORY);
702 error = skein_mac_ctx_build(ctx_tmpl, mechanism, key);
703 if (error != CRYPTO_SUCCESS)
704 goto errout;
705 *ctx_template = ctx_tmpl;
706 *ctx_template_size = sizeof (*ctx_tmpl);
707
708 return (CRYPTO_SUCCESS);
709 errout:
710 bzero(ctx_tmpl, sizeof (*ctx_tmpl));
711 kmem_free(ctx_tmpl, sizeof (*ctx_tmpl));
712 return (error);
713 }
714
715 /*
716 * Frees a skein context in a parent crypto context.
717 */
718 static int
719 skein_free_context(crypto_ctx_t *ctx)
720 {
721 if (SKEIN_CTX(ctx) != NULL) {
722 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
723 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
724 SKEIN_CTX_LVALUE(ctx) = NULL;
725 }
726
727 return (CRYPTO_SUCCESS);
728 }