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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/modctl.h>
28 #include <sys/cmn_err.h>
29 #include <sys/note.h>
30 #include <sys/crypto/common.h>
31 #include <sys/crypto/spi.h>
32 #include <sys/strsun.h>
33 #include <sys/systm.h>
34 #include <sys/sysmacros.h>
35
36 #include <sys/sha1.h>
37 #include <sha1/sha1_impl.h>
38
39 /*
40 * The sha1 module is created with two modlinkages:
41 * - a modlmisc that allows consumers to directly call the entry points
42 * SHA1Init, SHA1Update, and SHA1Final.
43 * - a modlcrypto that allows the module to register with the Kernel
44 * Cryptographic Framework (KCF) as a software provider for the SHA1
45 * mechanisms.
46 */
47
48 static struct modlmisc modlmisc = {
49 &mod_miscops,
50 "SHA1 Message-Digest Algorithm"
51 };
52
53 static struct modlcrypto modlcrypto = {
54 &mod_cryptoops,
55 "SHA1 Kernel SW Provider 1.1"
56 };
57
58 static struct modlinkage modlinkage = {
59 MODREV_1, { &modlmisc, &modlcrypto, NULL }
60 };
61
62
63 /*
64 * Macros to access the SHA1 or SHA1-HMAC contexts from a context passed
65 * by KCF to one of the entry points.
66 */
67
68 #define PROV_SHA1_CTX(ctx) ((sha1_ctx_t *)(ctx)->cc_provider_private)
69 #define PROV_SHA1_HMAC_CTX(ctx) ((sha1_hmac_ctx_t *)(ctx)->cc_provider_private)
70
71 /* to extract the digest length passed as mechanism parameter */
72 #define PROV_SHA1_GET_DIGEST_LEN(m, len) { \
73 if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \
74 (len) = (uint32_t)*((ulong_t *)(void *)mechanism->cm_param); \
75 else { \
76 ulong_t tmp_ulong; \
77 bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \
78 (len) = (uint32_t)tmp_ulong; \
79 } \
80 }
81
82 #define PROV_SHA1_DIGEST_KEY(ctx, key, len, digest) { \
83 SHA1Init(ctx); \
84 SHA1Update(ctx, key, len); \
85 SHA1Final(digest, ctx); \
86 }
87
88 /*
89 * Mechanism info structure passed to KCF during registration.
90 */
91 static crypto_mech_info_t sha1_mech_info_tab[] = {
92 /* SHA1 */
93 {SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE,
94 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
95 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
96 /* SHA1-HMAC */
97 {SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE,
98 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
99 SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
100 CRYPTO_KEYSIZE_UNIT_IN_BYTES},
101 /* SHA1-HMAC GENERAL */
102 {SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE,
103 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
104 SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
105 CRYPTO_KEYSIZE_UNIT_IN_BYTES}
106 };
107
108 static void sha1_provider_status(crypto_provider_handle_t, uint_t *);
109
110 static crypto_control_ops_t sha1_control_ops = {
111 sha1_provider_status
112 };
113
114 static int sha1_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
115 crypto_req_handle_t);
116 static int sha1_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
117 crypto_req_handle_t);
118 static int sha1_digest_update(crypto_ctx_t *, crypto_data_t *,
119 crypto_req_handle_t);
120 static int sha1_digest_final(crypto_ctx_t *, crypto_data_t *,
121 crypto_req_handle_t);
122 static int sha1_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
123 crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
124 crypto_req_handle_t);
125
126 static crypto_digest_ops_t sha1_digest_ops = {
127 sha1_digest_init,
128 sha1_digest,
129 sha1_digest_update,
130 NULL,
131 sha1_digest_final,
132 sha1_digest_atomic
133 };
134
135 static int sha1_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
136 crypto_spi_ctx_template_t, crypto_req_handle_t);
137 static int sha1_mac_update(crypto_ctx_t *, crypto_data_t *,
138 crypto_req_handle_t);
139 static int sha1_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
140 static int sha1_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
141 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
142 crypto_spi_ctx_template_t, crypto_req_handle_t);
143 static int sha1_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
144 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
145 crypto_spi_ctx_template_t, crypto_req_handle_t);
146
147 static crypto_mac_ops_t sha1_mac_ops = {
148 sha1_mac_init,
149 NULL,
150 sha1_mac_update,
151 sha1_mac_final,
152 sha1_mac_atomic,
153 sha1_mac_verify_atomic
154 };
155
156 static int sha1_create_ctx_template(crypto_provider_handle_t,
157 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
158 size_t *, crypto_req_handle_t);
159 static int sha1_free_context(crypto_ctx_t *);
160
161 static crypto_ctx_ops_t sha1_ctx_ops = {
162 sha1_create_ctx_template,
163 sha1_free_context
164 };
165
166 static crypto_ops_t sha1_crypto_ops = {
167 .co_control_ops = &sha1_control_ops,
168 .co_digest_ops = &sha1_digest_ops,
169 .co_mac_ops = &sha1_mac_ops,
170 .co_ctx_ops = &sha1_ctx_ops
171 };
172
173 static crypto_provider_info_t sha1_prov_info = {{{{
174 CRYPTO_SPI_VERSION_4,
175 "SHA1 Software Provider",
176 CRYPTO_SW_PROVIDER,
177 {&modlinkage},
178 NULL,
179 &sha1_crypto_ops,
180 sizeof (sha1_mech_info_tab)/sizeof (crypto_mech_info_t),
181 sha1_mech_info_tab
182 }}}};
183
184 static crypto_kcf_provider_handle_t sha1_prov_handle = NULL;
185
186 int
187 _init()
188 {
189 int ret;
190
191 if ((ret = mod_install(&modlinkage)) != 0)
192 return (ret);
193
194 /*
195 * Register with KCF. If the registration fails, log do not uninstall
196 * the module, since the functionality provided by misc/sha1 should
197 * still be available.
198 */
199 (void) crypto_register_provider(&sha1_prov_info, &sha1_prov_handle);
200
201 return (0);
202 }
203
204 int
205 _info(struct modinfo *modinfop)
206 {
207 return (mod_info(&modlinkage, modinfop));
208 }
209
210 /*
211 * KCF software provider control entry points.
212 */
213 /* ARGSUSED */
214 static void
215 sha1_provider_status(crypto_provider_handle_t provider, uint_t *status)
216 {
217 *status = CRYPTO_PROVIDER_READY;
218 }
219
220 /*
221 * KCF software provider digest entry points.
222 */
223
224 static int
225 sha1_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
226 crypto_req_handle_t req)
227 {
228 if (mechanism->cm_type != SHA1_MECH_INFO_TYPE)
229 return (CRYPTO_MECHANISM_INVALID);
230
231 /*
232 * Allocate and initialize SHA1 context.
233 */
234 ctx->cc_provider_private = kmem_alloc(sizeof (sha1_ctx_t),
235 crypto_kmflag(req));
236 if (ctx->cc_provider_private == NULL)
237 return (CRYPTO_HOST_MEMORY);
238
239 PROV_SHA1_CTX(ctx)->sc_mech_type = SHA1_MECH_INFO_TYPE;
240 SHA1Init(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
241
242 return (CRYPTO_SUCCESS);
243 }
244
245 /*
246 * Helper SHA1 digest update function for uio data.
247 */
248 static int
249 sha1_digest_update_uio(SHA1_CTX *sha1_ctx, crypto_data_t *data)
250 {
251 off_t offset = data->cd_offset;
252 size_t length = data->cd_length;
253 uint_t vec_idx;
254 size_t cur_len;
255
256 /* we support only kernel buffer */
257 if (data->cd_uio->uio_segflg != UIO_SYSSPACE)
258 return (CRYPTO_ARGUMENTS_BAD);
259
260 /*
261 * Jump to the first iovec containing data to be
262 * digested.
263 */
264 for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt &&
265 offset >= data->cd_uio->uio_iov[vec_idx].iov_len;
266 offset -= data->cd_uio->uio_iov[vec_idx++].iov_len)
267 ;
268 if (vec_idx == data->cd_uio->uio_iovcnt) {
269 /*
270 * The caller specified an offset that is larger than the
271 * total size of the buffers it provided.
272 */
273 return (CRYPTO_DATA_LEN_RANGE);
274 }
275
276 /*
277 * Now do the digesting on the iovecs.
278 */
279 while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) {
280 cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len -
281 offset, length);
282
283 SHA1Update(sha1_ctx,
284 (uint8_t *)data->cd_uio->uio_iov[vec_idx].iov_base + offset,
285 cur_len);
286
287 length -= cur_len;
288 vec_idx++;
289 offset = 0;
290 }
291
292 if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) {
293 /*
294 * The end of the specified iovec's was reached but
295 * the length requested could not be processed, i.e.
296 * The caller requested to digest more data than it provided.
297 */
298 return (CRYPTO_DATA_LEN_RANGE);
299 }
300
301 return (CRYPTO_SUCCESS);
302 }
303
304 /*
305 * Helper SHA1 digest final function for uio data.
306 * digest_len is the length of the desired digest. If digest_len
307 * is smaller than the default SHA1 digest length, the caller
308 * must pass a scratch buffer, digest_scratch, which must
309 * be at least SHA1_DIGEST_LENGTH bytes.
310 */
311 static int
312 sha1_digest_final_uio(SHA1_CTX *sha1_ctx, crypto_data_t *digest,
313 ulong_t digest_len, uchar_t *digest_scratch)
314 {
315 off_t offset = digest->cd_offset;
316 uint_t vec_idx;
317
318 /* we support only kernel buffer */
319 if (digest->cd_uio->uio_segflg != UIO_SYSSPACE)
320 return (CRYPTO_ARGUMENTS_BAD);
321
322 /*
323 * Jump to the first iovec containing ptr to the digest to
324 * be returned.
325 */
326 for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len &&
327 vec_idx < digest->cd_uio->uio_iovcnt;
328 offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len)
329 ;
330 if (vec_idx == digest->cd_uio->uio_iovcnt) {
331 /*
332 * The caller specified an offset that is
333 * larger than the total size of the buffers
334 * it provided.
335 */
336 return (CRYPTO_DATA_LEN_RANGE);
337 }
338
339 if (offset + digest_len <=
340 digest->cd_uio->uio_iov[vec_idx].iov_len) {
341 /*
342 * The computed SHA1 digest will fit in the current
343 * iovec.
344 */
345 if (digest_len != SHA1_DIGEST_LENGTH) {
346 /*
347 * The caller requested a short digest. Digest
348 * into a scratch buffer and return to
349 * the user only what was requested.
350 */
351 SHA1Final(digest_scratch, sha1_ctx);
352 bcopy(digest_scratch, (uchar_t *)digest->
353 cd_uio->uio_iov[vec_idx].iov_base + offset,
354 digest_len);
355 } else {
356 SHA1Final((uchar_t *)digest->
357 cd_uio->uio_iov[vec_idx].iov_base + offset,
358 sha1_ctx);
359 }
360 } else {
361 /*
362 * The computed digest will be crossing one or more iovec's.
363 * This is bad performance-wise but we need to support it.
364 * Allocate a small scratch buffer on the stack and
365 * copy it piece meal to the specified digest iovec's.
366 */
367 uchar_t digest_tmp[SHA1_DIGEST_LENGTH];
368 off_t scratch_offset = 0;
369 size_t length = digest_len;
370 size_t cur_len;
371
372 SHA1Final(digest_tmp, sha1_ctx);
373
374 while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) {
375 cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len -
376 offset, length);
377 bcopy(digest_tmp + scratch_offset,
378 digest->cd_uio->uio_iov[vec_idx].iov_base + offset,
379 cur_len);
380
381 length -= cur_len;
382 vec_idx++;
383 scratch_offset += cur_len;
384 offset = 0;
385 }
386
387 if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) {
388 /*
389 * The end of the specified iovec's was reached but
390 * the length requested could not be processed, i.e.
391 * The caller requested to digest more data than it
392 * provided.
393 */
394 return (CRYPTO_DATA_LEN_RANGE);
395 }
396 }
397
398 return (CRYPTO_SUCCESS);
399 }
400
401 /*
402 * Helper SHA1 digest update for mblk's.
403 */
404 static int
405 sha1_digest_update_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *data)
406 {
407 off_t offset = data->cd_offset;
408 size_t length = data->cd_length;
409 mblk_t *mp;
410 size_t cur_len;
411
412 /*
413 * Jump to the first mblk_t containing data to be digested.
414 */
415 for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
416 offset -= MBLKL(mp), mp = mp->b_cont)
417 ;
418 if (mp == NULL) {
419 /*
420 * The caller specified an offset that is larger than the
421 * total size of the buffers it provided.
422 */
423 return (CRYPTO_DATA_LEN_RANGE);
424 }
425
426 /*
427 * Now do the digesting on the mblk chain.
428 */
429 while (mp != NULL && length > 0) {
430 cur_len = MIN(MBLKL(mp) - offset, length);
431 SHA1Update(sha1_ctx, mp->b_rptr + offset, cur_len);
432 length -= cur_len;
433 offset = 0;
434 mp = mp->b_cont;
435 }
436
437 if (mp == NULL && length > 0) {
438 /*
439 * The end of the mblk was reached but the length requested
440 * could not be processed, i.e. The caller requested
441 * to digest more data than it provided.
442 */
443 return (CRYPTO_DATA_LEN_RANGE);
444 }
445
446 return (CRYPTO_SUCCESS);
447 }
448
449 /*
450 * Helper SHA1 digest final for mblk's.
451 * digest_len is the length of the desired digest. If digest_len
452 * is smaller than the default SHA1 digest length, the caller
453 * must pass a scratch buffer, digest_scratch, which must
454 * be at least SHA1_DIGEST_LENGTH bytes.
455 */
456 static int
457 sha1_digest_final_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *digest,
458 ulong_t digest_len, uchar_t *digest_scratch)
459 {
460 off_t offset = digest->cd_offset;
461 mblk_t *mp;
462
463 /*
464 * Jump to the first mblk_t that will be used to store the digest.
465 */
466 for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp);
467 offset -= MBLKL(mp), mp = mp->b_cont)
468 ;
469 if (mp == NULL) {
470 /*
471 * The caller specified an offset that is larger than the
472 * total size of the buffers it provided.
473 */
474 return (CRYPTO_DATA_LEN_RANGE);
475 }
476
477 if (offset + digest_len <= MBLKL(mp)) {
478 /*
479 * The computed SHA1 digest will fit in the current mblk.
480 * Do the SHA1Final() in-place.
481 */
482 if (digest_len != SHA1_DIGEST_LENGTH) {
483 /*
484 * The caller requested a short digest. Digest
485 * into a scratch buffer and return to
486 * the user only what was requested.
487 */
488 SHA1Final(digest_scratch, sha1_ctx);
489 bcopy(digest_scratch, mp->b_rptr + offset, digest_len);
490 } else {
491 SHA1Final(mp->b_rptr + offset, sha1_ctx);
492 }
493 } else {
494 /*
495 * The computed digest will be crossing one or more mblk's.
496 * This is bad performance-wise but we need to support it.
497 * Allocate a small scratch buffer on the stack and
498 * copy it piece meal to the specified digest iovec's.
499 */
500 uchar_t digest_tmp[SHA1_DIGEST_LENGTH];
501 off_t scratch_offset = 0;
502 size_t length = digest_len;
503 size_t cur_len;
504
505 SHA1Final(digest_tmp, sha1_ctx);
506
507 while (mp != NULL && length > 0) {
508 cur_len = MIN(MBLKL(mp) - offset, length);
509 bcopy(digest_tmp + scratch_offset,
510 mp->b_rptr + offset, cur_len);
511
512 length -= cur_len;
513 mp = mp->b_cont;
514 scratch_offset += cur_len;
515 offset = 0;
516 }
517
518 if (mp == NULL && length > 0) {
519 /*
520 * The end of the specified mblk was reached but
521 * the length requested could not be processed, i.e.
522 * The caller requested to digest more data than it
523 * provided.
524 */
525 return (CRYPTO_DATA_LEN_RANGE);
526 }
527 }
528
529 return (CRYPTO_SUCCESS);
530 }
531
532 /* ARGSUSED */
533 static int
534 sha1_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
535 crypto_req_handle_t req)
536 {
537 int ret = CRYPTO_SUCCESS;
538
539 ASSERT(ctx->cc_provider_private != NULL);
540
541 /*
542 * We need to just return the length needed to store the output.
543 * We should not destroy the context for the following cases.
544 */
545 if ((digest->cd_length == 0) ||
546 (digest->cd_length < SHA1_DIGEST_LENGTH)) {
547 digest->cd_length = SHA1_DIGEST_LENGTH;
548 return (CRYPTO_BUFFER_TOO_SMALL);
549 }
550
551 /*
552 * Do the SHA1 update on the specified input data.
553 */
554 switch (data->cd_format) {
555 case CRYPTO_DATA_RAW:
556 SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
557 (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
558 data->cd_length);
559 break;
560 case CRYPTO_DATA_UIO:
561 ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
562 data);
563 break;
564 case CRYPTO_DATA_MBLK:
565 ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
566 data);
567 break;
568 default:
569 ret = CRYPTO_ARGUMENTS_BAD;
570 }
571
572 if (ret != CRYPTO_SUCCESS) {
573 /* the update failed, free context and bail */
574 kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
575 ctx->cc_provider_private = NULL;
576 digest->cd_length = 0;
577 return (ret);
578 }
579
580 /*
581 * Do a SHA1 final, must be done separately since the digest
582 * type can be different than the input data type.
583 */
584 switch (digest->cd_format) {
585 case CRYPTO_DATA_RAW:
586 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
587 digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
588 break;
589 case CRYPTO_DATA_UIO:
590 ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
591 digest, SHA1_DIGEST_LENGTH, NULL);
592 break;
593 case CRYPTO_DATA_MBLK:
594 ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
595 digest, SHA1_DIGEST_LENGTH, NULL);
596 break;
597 default:
598 ret = CRYPTO_ARGUMENTS_BAD;
599 }
600
601 /* all done, free context and return */
602
603 if (ret == CRYPTO_SUCCESS) {
604 digest->cd_length = SHA1_DIGEST_LENGTH;
605 } else {
606 digest->cd_length = 0;
607 }
608
609 kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
610 ctx->cc_provider_private = NULL;
611 return (ret);
612 }
613
614 /* ARGSUSED */
615 static int
616 sha1_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
617 crypto_req_handle_t req)
618 {
619 int ret = CRYPTO_SUCCESS;
620
621 ASSERT(ctx->cc_provider_private != NULL);
622
623 /*
624 * Do the SHA1 update on the specified input data.
625 */
626 switch (data->cd_format) {
627 case CRYPTO_DATA_RAW:
628 SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
629 (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
630 data->cd_length);
631 break;
632 case CRYPTO_DATA_UIO:
633 ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
634 data);
635 break;
636 case CRYPTO_DATA_MBLK:
637 ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
638 data);
639 break;
640 default:
641 ret = CRYPTO_ARGUMENTS_BAD;
642 }
643
644 return (ret);
645 }
646
647 /* ARGSUSED */
648 static int
649 sha1_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
650 crypto_req_handle_t req)
651 {
652 int ret = CRYPTO_SUCCESS;
653
654 ASSERT(ctx->cc_provider_private != NULL);
655
656 /*
657 * We need to just return the length needed to store the output.
658 * We should not destroy the context for the following cases.
659 */
660 if ((digest->cd_length == 0) ||
661 (digest->cd_length < SHA1_DIGEST_LENGTH)) {
662 digest->cd_length = SHA1_DIGEST_LENGTH;
663 return (CRYPTO_BUFFER_TOO_SMALL);
664 }
665
666 /*
667 * Do a SHA1 final.
668 */
669 switch (digest->cd_format) {
670 case CRYPTO_DATA_RAW:
671 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
672 digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
673 break;
674 case CRYPTO_DATA_UIO:
675 ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
676 digest, SHA1_DIGEST_LENGTH, NULL);
677 break;
678 case CRYPTO_DATA_MBLK:
679 ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
680 digest, SHA1_DIGEST_LENGTH, NULL);
681 break;
682 default:
683 ret = CRYPTO_ARGUMENTS_BAD;
684 }
685
686 /* all done, free context and return */
687
688 if (ret == CRYPTO_SUCCESS) {
689 digest->cd_length = SHA1_DIGEST_LENGTH;
690 } else {
691 digest->cd_length = 0;
692 }
693
694 kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
695 ctx->cc_provider_private = NULL;
696
697 return (ret);
698 }
699
700 /* ARGSUSED */
701 static int
702 sha1_digest_atomic(crypto_provider_handle_t provider,
703 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
704 crypto_data_t *data, crypto_data_t *digest,
705 crypto_req_handle_t req)
706 {
707 int ret = CRYPTO_SUCCESS;
708 SHA1_CTX sha1_ctx;
709
710 if (mechanism->cm_type != SHA1_MECH_INFO_TYPE)
711 return (CRYPTO_MECHANISM_INVALID);
712
713 /*
714 * Do the SHA1 init.
715 */
716 SHA1Init(&sha1_ctx);
717
718 /*
719 * Do the SHA1 update on the specified input data.
720 */
721 switch (data->cd_format) {
722 case CRYPTO_DATA_RAW:
723 SHA1Update(&sha1_ctx,
724 (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
725 data->cd_length);
726 break;
727 case CRYPTO_DATA_UIO:
728 ret = sha1_digest_update_uio(&sha1_ctx, data);
729 break;
730 case CRYPTO_DATA_MBLK:
731 ret = sha1_digest_update_mblk(&sha1_ctx, data);
732 break;
733 default:
734 ret = CRYPTO_ARGUMENTS_BAD;
735 }
736
737 if (ret != CRYPTO_SUCCESS) {
738 /* the update failed, bail */
739 digest->cd_length = 0;
740 return (ret);
741 }
742
743 /*
744 * Do a SHA1 final, must be done separately since the digest
745 * type can be different than the input data type.
746 */
747 switch (digest->cd_format) {
748 case CRYPTO_DATA_RAW:
749 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
750 digest->cd_offset, &sha1_ctx);
751 break;
752 case CRYPTO_DATA_UIO:
753 ret = sha1_digest_final_uio(&sha1_ctx, digest,
754 SHA1_DIGEST_LENGTH, NULL);
755 break;
756 case CRYPTO_DATA_MBLK:
757 ret = sha1_digest_final_mblk(&sha1_ctx, digest,
758 SHA1_DIGEST_LENGTH, NULL);
759 break;
760 default:
761 ret = CRYPTO_ARGUMENTS_BAD;
762 }
763
764 if (ret == CRYPTO_SUCCESS) {
765 digest->cd_length = SHA1_DIGEST_LENGTH;
766 } else {
767 digest->cd_length = 0;
768 }
769
770 return (ret);
771 }
772
773 /*
774 * KCF software provider mac entry points.
775 *
776 * SHA1 HMAC is: SHA1(key XOR opad, SHA1(key XOR ipad, text))
777 *
778 * Init:
779 * The initialization routine initializes what we denote
780 * as the inner and outer contexts by doing
781 * - for inner context: SHA1(key XOR ipad)
782 * - for outer context: SHA1(key XOR opad)
783 *
784 * Update:
785 * Each subsequent SHA1 HMAC update will result in an
786 * update of the inner context with the specified data.
787 *
788 * Final:
789 * The SHA1 HMAC final will do a SHA1 final operation on the
790 * inner context, and the resulting digest will be used
791 * as the data for an update on the outer context. Last
792 * but not least, a SHA1 final on the outer context will
793 * be performed to obtain the SHA1 HMAC digest to return
794 * to the user.
795 */
796
797 /*
798 * Initialize a SHA1-HMAC context.
799 */
800 static void
801 sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
802 {
803 uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK];
804 uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK];
805 uint_t i;
806
807 bzero(ipad, SHA1_HMAC_BLOCK_SIZE);
808 bzero(opad, SHA1_HMAC_BLOCK_SIZE);
809
810 bcopy(keyval, ipad, length_in_bytes);
811 bcopy(keyval, opad, length_in_bytes);
812
813 /* XOR key with ipad (0x36) and opad (0x5c) */
814 for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) {
815 ipad[i] ^= 0x36363636;
816 opad[i] ^= 0x5c5c5c5c;
817 }
818
819 /* perform SHA1 on ipad */
820 SHA1Init(&ctx->hc_icontext);
821 SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE);
822
823 /* perform SHA1 on opad */
824 SHA1Init(&ctx->hc_ocontext);
825 SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE);
826 }
827
828 /*
829 */
830 static int
831 sha1_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
832 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
833 crypto_req_handle_t req)
834 {
835 int ret = CRYPTO_SUCCESS;
836 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
837
838 if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
839 mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
840 return (CRYPTO_MECHANISM_INVALID);
841
842 /* Add support for key by attributes (RFE 4706552) */
843 if (key->ck_format != CRYPTO_KEY_RAW)
844 return (CRYPTO_ARGUMENTS_BAD);
845
846 ctx->cc_provider_private = kmem_alloc(sizeof (sha1_hmac_ctx_t),
847 crypto_kmflag(req));
848 if (ctx->cc_provider_private == NULL)
849 return (CRYPTO_HOST_MEMORY);
850
851 if (ctx_template != NULL) {
852 /* reuse context template */
853 bcopy(ctx_template, PROV_SHA1_HMAC_CTX(ctx),
854 sizeof (sha1_hmac_ctx_t));
855 } else {
856 /* no context template, compute context */
857 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
858 uchar_t digested_key[SHA1_DIGEST_LENGTH];
859 sha1_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
860
861 /*
862 * Hash the passed-in key to get a smaller key.
863 * The inner context is used since it hasn't been
864 * initialized yet.
865 */
866 PROV_SHA1_DIGEST_KEY(&hmac_ctx->hc_icontext,
867 key->ck_data, keylen_in_bytes, digested_key);
868 sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx),
869 digested_key, SHA1_DIGEST_LENGTH);
870 } else {
871 sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx),
872 key->ck_data, keylen_in_bytes);
873 }
874 }
875
876 /*
877 * Get the mechanism parameters, if applicable.
878 */
879 PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
880 if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
881 if (mechanism->cm_param == NULL ||
882 mechanism->cm_param_len != sizeof (ulong_t))
883 ret = CRYPTO_MECHANISM_PARAM_INVALID;
884 PROV_SHA1_GET_DIGEST_LEN(mechanism,
885 PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len);
886 if (PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len >
887 SHA1_DIGEST_LENGTH)
888 ret = CRYPTO_MECHANISM_PARAM_INVALID;
889 }
890
891 if (ret != CRYPTO_SUCCESS) {
892 bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
893 kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
894 ctx->cc_provider_private = NULL;
895 }
896
897 return (ret);
898 }
899
900 /* ARGSUSED */
901 static int
902 sha1_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
903 {
904 int ret = CRYPTO_SUCCESS;
905
906 ASSERT(ctx->cc_provider_private != NULL);
907
908 /*
909 * Do a SHA1 update of the inner context using the specified
910 * data.
911 */
912 switch (data->cd_format) {
913 case CRYPTO_DATA_RAW:
914 SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_icontext,
915 (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
916 data->cd_length);
917 break;
918 case CRYPTO_DATA_UIO:
919 ret = sha1_digest_update_uio(
920 &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data);
921 break;
922 case CRYPTO_DATA_MBLK:
923 ret = sha1_digest_update_mblk(
924 &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data);
925 break;
926 default:
927 ret = CRYPTO_ARGUMENTS_BAD;
928 }
929
930 return (ret);
931 }
932
933 /* ARGSUSED */
934 static int
935 sha1_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
936 {
937 int ret = CRYPTO_SUCCESS;
938 uchar_t digest[SHA1_DIGEST_LENGTH];
939 uint32_t digest_len = SHA1_DIGEST_LENGTH;
940
941 ASSERT(ctx->cc_provider_private != NULL);
942
943 if (PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type ==
944 SHA1_HMAC_GEN_MECH_INFO_TYPE)
945 digest_len = PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len;
946
947 /*
948 * We need to just return the length needed to store the output.
949 * We should not destroy the context for the following cases.
950 */
951 if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
952 mac->cd_length = digest_len;
953 return (CRYPTO_BUFFER_TOO_SMALL);
954 }
955
956 /*
957 * Do a SHA1 final on the inner context.
958 */
959 SHA1Final(digest, &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext);
960
961 /*
962 * Do a SHA1 update on the outer context, feeding the inner
963 * digest as data.
964 */
965 SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, digest,
966 SHA1_DIGEST_LENGTH);
967
968 /*
969 * Do a SHA1 final on the outer context, storing the computing
970 * digest in the users buffer.
971 */
972 switch (mac->cd_format) {
973 case CRYPTO_DATA_RAW:
974 if (digest_len != SHA1_DIGEST_LENGTH) {
975 /*
976 * The caller requested a short digest. Digest
977 * into a scratch buffer and return to
978 * the user only what was requested.
979 */
980 SHA1Final(digest,
981 &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext);
982 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
983 mac->cd_offset, digest_len);
984 } else {
985 SHA1Final((unsigned char *)mac->cd_raw.iov_base +
986 mac->cd_offset,
987 &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext);
988 }
989 break;
990 case CRYPTO_DATA_UIO:
991 ret = sha1_digest_final_uio(
992 &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac,
993 digest_len, digest);
994 break;
995 case CRYPTO_DATA_MBLK:
996 ret = sha1_digest_final_mblk(
997 &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac,
998 digest_len, digest);
999 break;
1000 default:
1001 ret = CRYPTO_ARGUMENTS_BAD;
1002 }
1003
1004 if (ret == CRYPTO_SUCCESS) {
1005 mac->cd_length = digest_len;
1006 } else {
1007 mac->cd_length = 0;
1008 }
1009
1010 bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
1011 kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
1012 ctx->cc_provider_private = NULL;
1013
1014 return (ret);
1015 }
1016
1017 #define SHA1_MAC_UPDATE(data, ctx, ret) { \
1018 switch (data->cd_format) { \
1019 case CRYPTO_DATA_RAW: \
1020 SHA1Update(&(ctx).hc_icontext, \
1021 (uint8_t *)data->cd_raw.iov_base + \
1022 data->cd_offset, data->cd_length); \
1023 break; \
1024 case CRYPTO_DATA_UIO: \
1025 ret = sha1_digest_update_uio(&(ctx).hc_icontext, data); \
1026 break; \
1027 case CRYPTO_DATA_MBLK: \
1028 ret = sha1_digest_update_mblk(&(ctx).hc_icontext, \
1029 data); \
1030 break; \
1031 default: \
1032 ret = CRYPTO_ARGUMENTS_BAD; \
1033 } \
1034 }
1035
1036 /* ARGSUSED */
1037 static int
1038 sha1_mac_atomic(crypto_provider_handle_t provider,
1039 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1040 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1041 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1042 {
1043 int ret = CRYPTO_SUCCESS;
1044 uchar_t digest[SHA1_DIGEST_LENGTH];
1045 sha1_hmac_ctx_t sha1_hmac_ctx;
1046 uint32_t digest_len = SHA1_DIGEST_LENGTH;
1047 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1048
1049 if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
1050 mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
1051 return (CRYPTO_MECHANISM_INVALID);
1052
1053 /* Add support for key by attributes (RFE 4706552) */
1054 if (key->ck_format != CRYPTO_KEY_RAW)
1055 return (CRYPTO_ARGUMENTS_BAD);
1056
1057 if (ctx_template != NULL) {
1058 /* reuse context template */
1059 bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1060 } else {
1061 /* no context template, initialize context */
1062 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1063 /*
1064 * Hash the passed-in key to get a smaller key.
1065 * The inner context is used since it hasn't been
1066 * initialized yet.
1067 */
1068 PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext,
1069 key->ck_data, keylen_in_bytes, digest);
1070 sha1_mac_init_ctx(&sha1_hmac_ctx, digest,
1071 SHA1_DIGEST_LENGTH);
1072 } else {
1073 sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data,
1074 keylen_in_bytes);
1075 }
1076 }
1077
1078 /* get the mechanism parameters, if applicable */
1079 if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
1080 if (mechanism->cm_param == NULL ||
1081 mechanism->cm_param_len != sizeof (ulong_t)) {
1082 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1083 goto bail;
1084 }
1085 PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len);
1086 if (digest_len > SHA1_DIGEST_LENGTH) {
1087 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1088 goto bail;
1089 }
1090 }
1091
1092 /* do a SHA1 update of the inner context using the specified data */
1093 SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret);
1094 if (ret != CRYPTO_SUCCESS)
1095 /* the update failed, free context and bail */
1096 goto bail;
1097
1098 /*
1099 * Do a SHA1 final on the inner context.
1100 */
1101 SHA1Final(digest, &sha1_hmac_ctx.hc_icontext);
1102
1103 /*
1104 * Do an SHA1 update on the outer context, feeding the inner
1105 * digest as data.
1106 */
1107 SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH);
1108
1109 /*
1110 * Do a SHA1 final on the outer context, storing the computed
1111 * digest in the users buffer.
1112 */
1113 switch (mac->cd_format) {
1114 case CRYPTO_DATA_RAW:
1115 if (digest_len != SHA1_DIGEST_LENGTH) {
1116 /*
1117 * The caller requested a short digest. Digest
1118 * into a scratch buffer and return to
1119 * the user only what was requested.
1120 */
1121 SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext);
1122 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
1123 mac->cd_offset, digest_len);
1124 } else {
1125 SHA1Final((unsigned char *)mac->cd_raw.iov_base +
1126 mac->cd_offset, &sha1_hmac_ctx.hc_ocontext);
1127 }
1128 break;
1129 case CRYPTO_DATA_UIO:
1130 ret = sha1_digest_final_uio(&sha1_hmac_ctx.hc_ocontext, mac,
1131 digest_len, digest);
1132 break;
1133 case CRYPTO_DATA_MBLK:
1134 ret = sha1_digest_final_mblk(&sha1_hmac_ctx.hc_ocontext, mac,
1135 digest_len, digest);
1136 break;
1137 default:
1138 ret = CRYPTO_ARGUMENTS_BAD;
1139 }
1140
1141 if (ret == CRYPTO_SUCCESS) {
1142 mac->cd_length = digest_len;
1143 } else {
1144 mac->cd_length = 0;
1145 }
1146 /* Extra paranoia: zeroize the context on the stack */
1147 bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1148
1149 return (ret);
1150 bail:
1151 bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1152 mac->cd_length = 0;
1153 return (ret);
1154 }
1155
1156 /* ARGSUSED */
1157 static int
1158 sha1_mac_verify_atomic(crypto_provider_handle_t provider,
1159 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1160 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1161 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1162 {
1163 int ret = CRYPTO_SUCCESS;
1164 uchar_t digest[SHA1_DIGEST_LENGTH];
1165 sha1_hmac_ctx_t sha1_hmac_ctx;
1166 uint32_t digest_len = SHA1_DIGEST_LENGTH;
1167 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1168
1169 if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
1170 mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
1171 return (CRYPTO_MECHANISM_INVALID);
1172
1173 /* Add support for key by attributes (RFE 4706552) */
1174 if (key->ck_format != CRYPTO_KEY_RAW)
1175 return (CRYPTO_ARGUMENTS_BAD);
1176
1177 if (ctx_template != NULL) {
1178 /* reuse context template */
1179 bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1180 } else {
1181 /* no context template, initialize context */
1182 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1183 /*
1184 * Hash the passed-in key to get a smaller key.
1185 * The inner context is used since it hasn't been
1186 * initialized yet.
1187 */
1188 PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext,
1189 key->ck_data, keylen_in_bytes, digest);
1190 sha1_mac_init_ctx(&sha1_hmac_ctx, digest,
1191 SHA1_DIGEST_LENGTH);
1192 } else {
1193 sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data,
1194 keylen_in_bytes);
1195 }
1196 }
1197
1198 /* get the mechanism parameters, if applicable */
1199 if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
1200 if (mechanism->cm_param == NULL ||
1201 mechanism->cm_param_len != sizeof (ulong_t)) {
1202 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1203 goto bail;
1204 }
1205 PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len);
1206 if (digest_len > SHA1_DIGEST_LENGTH) {
1207 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1208 goto bail;
1209 }
1210 }
1211
1212 if (mac->cd_length != digest_len) {
1213 ret = CRYPTO_INVALID_MAC;
1214 goto bail;
1215 }
1216
1217 /* do a SHA1 update of the inner context using the specified data */
1218 SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret);
1219 if (ret != CRYPTO_SUCCESS)
1220 /* the update failed, free context and bail */
1221 goto bail;
1222
1223 /* do a SHA1 final on the inner context */
1224 SHA1Final(digest, &sha1_hmac_ctx.hc_icontext);
1225
1226 /*
1227 * Do an SHA1 update on the outer context, feeding the inner
1228 * digest as data.
1229 */
1230 SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH);
1231
1232 /*
1233 * Do a SHA1 final on the outer context, storing the computed
1234 * digest in the users buffer.
1235 */
1236 SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext);
1237
1238 /*
1239 * Compare the computed digest against the expected digest passed
1240 * as argument.
1241 */
1242
1243 switch (mac->cd_format) {
1244
1245 case CRYPTO_DATA_RAW:
1246 if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
1247 mac->cd_offset, digest_len) != 0)
1248 ret = CRYPTO_INVALID_MAC;
1249 break;
1250
1251 case CRYPTO_DATA_UIO: {
1252 off_t offset = mac->cd_offset;
1253 uint_t vec_idx;
1254 off_t scratch_offset = 0;
1255 size_t length = digest_len;
1256 size_t cur_len;
1257
1258 /* we support only kernel buffer */
1259 if (mac->cd_uio->uio_segflg != UIO_SYSSPACE)
1260 return (CRYPTO_ARGUMENTS_BAD);
1261
1262 /* jump to the first iovec containing the expected digest */
1263 for (vec_idx = 0;
1264 offset >= mac->cd_uio->uio_iov[vec_idx].iov_len &&
1265 vec_idx < mac->cd_uio->uio_iovcnt;
1266 offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len)
1267 ;
1268 if (vec_idx == mac->cd_uio->uio_iovcnt) {
1269 /*
1270 * The caller specified an offset that is
1271 * larger than the total size of the buffers
1272 * it provided.
1273 */
1274 ret = CRYPTO_DATA_LEN_RANGE;
1275 break;
1276 }
1277
1278 /* do the comparison of computed digest vs specified one */
1279 while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) {
1280 cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len -
1281 offset, length);
1282
1283 if (bcmp(digest + scratch_offset,
1284 mac->cd_uio->uio_iov[vec_idx].iov_base + offset,
1285 cur_len) != 0) {
1286 ret = CRYPTO_INVALID_MAC;
1287 break;
1288 }
1289
1290 length -= cur_len;
1291 vec_idx++;
1292 scratch_offset += cur_len;
1293 offset = 0;
1294 }
1295 break;
1296 }
1297
1298 case CRYPTO_DATA_MBLK: {
1299 off_t offset = mac->cd_offset;
1300 mblk_t *mp;
1301 off_t scratch_offset = 0;
1302 size_t length = digest_len;
1303 size_t cur_len;
1304
1305 /* jump to the first mblk_t containing the expected digest */
1306 for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp);
1307 offset -= MBLKL(mp), mp = mp->b_cont)
1308 ;
1309 if (mp == NULL) {
1310 /*
1311 * The caller specified an offset that is larger than
1312 * the total size of the buffers it provided.
1313 */
1314 ret = CRYPTO_DATA_LEN_RANGE;
1315 break;
1316 }
1317
1318 while (mp != NULL && length > 0) {
1319 cur_len = MIN(MBLKL(mp) - offset, length);
1320 if (bcmp(digest + scratch_offset,
1321 mp->b_rptr + offset, cur_len) != 0) {
1322 ret = CRYPTO_INVALID_MAC;
1323 break;
1324 }
1325
1326 length -= cur_len;
1327 mp = mp->b_cont;
1328 scratch_offset += cur_len;
1329 offset = 0;
1330 }
1331 break;
1332 }
1333
1334 default:
1335 ret = CRYPTO_ARGUMENTS_BAD;
1336 }
1337
1338 bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1339 return (ret);
1340 bail:
1341 bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1342 mac->cd_length = 0;
1343 return (ret);
1344 }
1345
1346 /*
1347 * KCF software provider context management entry points.
1348 */
1349
1350 /* ARGSUSED */
1351 static int
1352 sha1_create_ctx_template(crypto_provider_handle_t provider,
1353 crypto_mechanism_t *mechanism, crypto_key_t *key,
1354 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
1355 crypto_req_handle_t req)
1356 {
1357 sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl;
1358 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1359
1360 if ((mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE) &&
1361 (mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)) {
1362 return (CRYPTO_MECHANISM_INVALID);
1363 }
1364
1365 /* Add support for key by attributes (RFE 4706552) */
1366 if (key->ck_format != CRYPTO_KEY_RAW)
1367 return (CRYPTO_ARGUMENTS_BAD);
1368
1369 /*
1370 * Allocate and initialize SHA1 context.
1371 */
1372 sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t),
1373 crypto_kmflag(req));
1374 if (sha1_hmac_ctx_tmpl == NULL)
1375 return (CRYPTO_HOST_MEMORY);
1376
1377 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1378 uchar_t digested_key[SHA1_DIGEST_LENGTH];
1379
1380 /*
1381 * Hash the passed-in key to get a smaller key.
1382 * The inner context is used since it hasn't been
1383 * initialized yet.
1384 */
1385 PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx_tmpl->hc_icontext,
1386 key->ck_data, keylen_in_bytes, digested_key);
1387 sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, digested_key,
1388 SHA1_DIGEST_LENGTH);
1389 } else {
1390 sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, key->ck_data,
1391 keylen_in_bytes);
1392 }
1393
1394 sha1_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
1395 *ctx_template = (crypto_spi_ctx_template_t)sha1_hmac_ctx_tmpl;
1396 *ctx_template_size = sizeof (sha1_hmac_ctx_t);
1397
1398
1399 return (CRYPTO_SUCCESS);
1400 }
1401
1402 static int
1403 sha1_free_context(crypto_ctx_t *ctx)
1404 {
1405 uint_t ctx_len;
1406 sha1_mech_type_t mech_type;
1407
1408 if (ctx->cc_provider_private == NULL)
1409 return (CRYPTO_SUCCESS);
1410
1411 /*
1412 * We have to free either SHA1 or SHA1-HMAC contexts, which
1413 * have different lengths.
1414 */
1415
1416 mech_type = PROV_SHA1_CTX(ctx)->sc_mech_type;
1417 if (mech_type == SHA1_MECH_INFO_TYPE)
1418 ctx_len = sizeof (sha1_ctx_t);
1419 else {
1420 ASSERT(mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
1421 mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE);
1422 ctx_len = sizeof (sha1_hmac_ctx_t);
1423 }
1424
1425 bzero(ctx->cc_provider_private, ctx_len);
1426 kmem_free(ctx->cc_provider_private, ctx_len);
1427 ctx->cc_provider_private = NULL;
1428
1429 return (CRYPTO_SUCCESS);
1430 }