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