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