md5.c (673007c6) md5.c (734b6a94)
1/*
2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Cleaned-up and optimized version of MD5, based on the reference
8 * implementation provided in RFC 1321. See RSA Copyright information
9 * below.
1/*
2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Cleaned-up and optimized version of MD5, based on the reference
8 * implementation provided in RFC 1321. See RSA Copyright information
9 * below.
10 *
11 * NOTE: All compiler data was gathered with SC4.2, and verified with SC5.x,
12 * as used to build Solaris 2.7. Hopefully the compiler behavior won't
13 * change for the worse in subsequent Solaris builds.
14 */
15
16#pragma ident "%Z%%M% %I% %E% SMI"
17
18/*
19 * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
20 */
21

--- 23 unchanged lines hidden (view full) ---

45#include <sys/types.h>
46#include <sys/md5.h>
47#include <sys/md5_consts.h> /* MD5_CONST() optimization */
48#include "md5_byteswap.h"
49#if !defined(_KERNEL) || defined(_BOOT)
50#include <strings.h>
51#endif /* !_KERNEL || _BOOT */
52
10 */
11
12#pragma ident "%Z%%M% %I% %E% SMI"
13
14/*
15 * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
16 */
17

--- 23 unchanged lines hidden (view full) ---

41#include <sys/types.h>
42#include <sys/md5.h>
43#include <sys/md5_consts.h> /* MD5_CONST() optimization */
44#include "md5_byteswap.h"
45#if !defined(_KERNEL) || defined(_BOOT)
46#include <strings.h>
47#endif /* !_KERNEL || _BOOT */
48
53#if defined(_KERNEL) && !defined(_BOOT)
54
55/*
56 * In kernel module, the md5 module is created with two modlinkages:
57 * - a modlmisc that allows consumers to directly call the entry points
58 * MD5Init, MD5Update, and MD5Final.
59 * - a modlcrypto that allows the module to register with the Kernel
60 * Cryptographic Framework (KCF) as a software provider for the MD5
61 * mechanisms.
62 */
63
49#ifdef _KERNEL
64#include <sys/systm.h>
50#include <sys/systm.h>
65#include <sys/modctl.h>
66#include <sys/cmn_err.h>
67#include <sys/ddi.h>
68#include <sys/crypto/common.h>
69#include <sys/crypto/spi.h>
70#include <sys/sysmacros.h>
71#include <sys/strsun.h>
72#include <sys/note.h>
51#endif /* _KERNEL */
73
52
74extern struct mod_ops mod_miscops;
75extern struct mod_ops mod_cryptoops;
76
77/*
78 * Module linkage information for the kernel.
79 */
80
81static struct modlmisc modlmisc = {
82 &mod_miscops,
83 "MD5 Message-Digest Algorithm"
84};
85
86static struct modlcrypto modlcrypto = {
87 &mod_cryptoops,
88 "MD5 Kernel SW Provider 1.23"
89};
90
91static struct modlinkage modlinkage = {
92 MODREV_1,
93 (void *)&modlmisc,
94 (void *)&modlcrypto,
95 NULL
96};
97
98/*
99 * CSPI information (entry points, provider info, etc.)
100 */
101
102typedef enum md5_mech_type {
103 MD5_MECH_INFO_TYPE, /* SUN_CKM_MD5 */
104 MD5_HMAC_MECH_INFO_TYPE, /* SUN_CKM_MD5_HMAC */
105 MD5_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_MD5_HMAC_GENERAL */
106} md5_mech_type_t;
107
108#define MD5_DIGEST_LENGTH 16 /* MD5 digest length in bytes */
109#define MD5_HMAC_BLOCK_SIZE 64 /* MD5 block size */
110#define MD5_HMAC_MIN_KEY_LEN 8 /* MD5-HMAC min key length in bits */
111#define MD5_HMAC_MAX_KEY_LEN INT_MAX /* MD5-HMAC max key length in bits */
112#define MD5_HMAC_INTS_PER_BLOCK (MD5_HMAC_BLOCK_SIZE/sizeof (uint32_t))
113
114/*
115 * Context for MD5 mechanism.
116 */
117typedef struct md5_ctx {
118 md5_mech_type_t mc_mech_type; /* type of context */
119 MD5_CTX mc_md5_ctx; /* MD5 context */
120} md5_ctx_t;
121
122/*
123 * Context for MD5-HMAC and MD5-HMAC-GENERAL mechanisms.
124 */
125typedef struct md5_hmac_ctx {
126 md5_mech_type_t hc_mech_type; /* type of context */
127 uint32_t hc_digest_len; /* digest len in bytes */
128 MD5_CTX hc_icontext; /* inner MD5 context */
129 MD5_CTX hc_ocontext; /* outer MD5 context */
130} md5_hmac_ctx_t;
131
132/*
133 * Macros to access the MD5 or MD5-HMAC contexts from a context passed
134 * by KCF to one of the entry points.
135 */
136
137#define PROV_MD5_CTX(ctx) ((md5_ctx_t *)(ctx)->cc_provider_private)
138#define PROV_MD5_HMAC_CTX(ctx) ((md5_hmac_ctx_t *)(ctx)->cc_provider_private)
139/* to extract the digest length passed as mechanism parameter */
140
141#define PROV_MD5_GET_DIGEST_LEN(m, len) { \
142 if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \
143 (len) = (uint32_t)*((ulong_t *)mechanism->cm_param); \
144 else { \
145 ulong_t tmp_ulong; \
146 bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \
147 (len) = (uint32_t)tmp_ulong; \
148 } \
149}
150
151#define PROV_MD5_DIGEST_KEY(ctx, key, len, digest) { \
152 MD5Init(ctx); \
153 MD5Update(ctx, key, len); \
154 MD5Final(digest, ctx); \
155}
156
157/*
158 * Mechanism info structure passed to KCF during registration.
159 */
160static crypto_mech_info_t md5_mech_info_tab[] = {
161 /* MD5 */
162 {SUN_CKM_MD5, MD5_MECH_INFO_TYPE,
163 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
164 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
165 /* MD5-HMAC */
166 {SUN_CKM_MD5_HMAC, MD5_HMAC_MECH_INFO_TYPE,
167 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
168 MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
169 CRYPTO_KEYSIZE_UNIT_IN_BITS},
170 /* MD5-HMAC GENERAL */
171 {SUN_CKM_MD5_HMAC_GENERAL, MD5_HMAC_GEN_MECH_INFO_TYPE,
172 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
173 MD5_HMAC_MIN_KEY_LEN, MD5_HMAC_MAX_KEY_LEN,
174 CRYPTO_KEYSIZE_UNIT_IN_BITS}
175};
176
177static void md5_provider_status(crypto_provider_handle_t, uint_t *);
178
179static crypto_control_ops_t md5_control_ops = {
180 md5_provider_status
181};
182
183static int md5_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
184 crypto_req_handle_t);
185static int md5_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
186 crypto_req_handle_t);
187static int md5_digest_update(crypto_ctx_t *, crypto_data_t *,
188 crypto_req_handle_t);
189static int md5_digest_final(crypto_ctx_t *, crypto_data_t *,
190 crypto_req_handle_t);
191static int md5_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
192 crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
193 crypto_req_handle_t);
194
195static crypto_digest_ops_t md5_digest_ops = {
196 md5_digest_init,
197 md5_digest,
198 md5_digest_update,
199 NULL,
200 md5_digest_final,
201 md5_digest_atomic
202};
203
204static int md5_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
205 crypto_spi_ctx_template_t, crypto_req_handle_t);
206static int md5_mac_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
207static int md5_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
208static int md5_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
209 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
210 crypto_spi_ctx_template_t, crypto_req_handle_t);
211static int md5_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
212 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
213 crypto_spi_ctx_template_t, crypto_req_handle_t);
214
215static crypto_mac_ops_t md5_mac_ops = {
216 md5_mac_init,
217 NULL,
218 md5_mac_update,
219 md5_mac_final,
220 md5_mac_atomic,
221 md5_mac_verify_atomic
222};
223
224static int md5_create_ctx_template(crypto_provider_handle_t,
225 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
226 size_t *, crypto_req_handle_t);
227static int md5_free_context(crypto_ctx_t *);
228
229static crypto_ctx_ops_t md5_ctx_ops = {
230 md5_create_ctx_template,
231 md5_free_context
232};
233
234static crypto_ops_t md5_crypto_ops = {
235 &md5_control_ops,
236 &md5_digest_ops,
237 NULL,
238 &md5_mac_ops,
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 NULL,
248 &md5_ctx_ops
249};
250
251static crypto_provider_info_t md5_prov_info = {
252 CRYPTO_SPI_VERSION_1,
253 "MD5 Software Provider",
254 CRYPTO_SW_PROVIDER,
255 {&modlinkage},
256 NULL,
257 &md5_crypto_ops,
258 sizeof (md5_mech_info_tab)/sizeof (crypto_mech_info_t),
259 md5_mech_info_tab
260};
261
262static crypto_kcf_provider_handle_t md5_prov_handle = NULL;
263
264int
265_init(void)
266{
267 int ret;
268
269 if ((ret = mod_install(&modlinkage)) != 0)
270 return (ret);
271
272 /*
273 * Register with KCF. If the registration fails, log an
274 * error but do not uninstall the module, since the functionality
275 * provided by misc/md5 should still be available.
276 */
277 if ((ret = crypto_register_provider(&md5_prov_info,
278 &md5_prov_handle)) != CRYPTO_SUCCESS)
279 cmn_err(CE_WARN, "md5 _init: "
280 "crypto_register_provider() failed (0x%x)", ret);
281
282 return (0);
283}
284
285int
286_fini(void)
287{
288 int ret;
289
290 /*
291 * Unregister from KCF if previous registration succeeded.
292 */
293 if (md5_prov_handle != NULL) {
294 if ((ret = crypto_unregister_provider(md5_prov_handle)) !=
295 CRYPTO_SUCCESS) {
296 cmn_err(CE_WARN, "md5 _fini: "
297 "crypto_unregister_provider() failed (0x%x)", ret);
298 return (EBUSY);
299 }
300 md5_prov_handle = NULL;
301 }
302
303 return (mod_remove(&modlinkage));
304}
305
306int
307_info(struct modinfo *modinfop)
308{
309 return (mod_info(&modlinkage, modinfop));
310}
311#endif /* _KERNEL && !_BOOT */
312
313static void Encode(uint8_t *, uint32_t *, size_t);
53static void Encode(uint8_t *, const uint32_t *, size_t);
314static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *,
315 const uint8_t [64]);
316
317static uint8_t PADDING[64] = { 0x80, /* all zeros */ };
318
319/*
320 * F, G, H and I are the basic MD5 functions.
321 */

--- 335 unchanged lines hidden (view full) ---

657 * win, although the amount it wins by seems to vary quite a bit.
658 */
659
660 register uint32_t x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7;
661 register uint32_t x_8, x_9, x_10, x_11, x_12, x_13, x_14, x_15;
662#ifdef sun4v
663 unsigned long long *md5_consts64;
664
54static void MD5Transform(uint32_t, uint32_t, uint32_t, uint32_t, MD5_CTX *,
55 const uint8_t [64]);
56
57static uint8_t PADDING[64] = { 0x80, /* all zeros */ };
58
59/*
60 * F, G, H and I are the basic MD5 functions.
61 */

--- 335 unchanged lines hidden (view full) ---

397 * win, although the amount it wins by seems to vary quite a bit.
398 */
399
400 register uint32_t x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7;
401 register uint32_t x_8, x_9, x_10, x_11, x_12, x_13, x_14, x_15;
402#ifdef sun4v
403 unsigned long long *md5_consts64;
404
405 /* LINTED E_BAD_PTR_CAST_ALIGN */
665 md5_consts64 = (unsigned long long *) md5_consts;
666#endif /* sun4v */
667
668 /*
669 * general optimization:
670 *
671 * the compiler (at least SC4.2/5.x) generates better code if
672 * variable use is localized. in this case, swapping the integers in

--- 60 unchanged lines hidden (view full) ---

733 x_1 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 1);
734 x_0 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 0);
735#endif /* sun4v */
736 } else
737#endif
738 {
739
740#ifdef sun4v
406 md5_consts64 = (unsigned long long *) md5_consts;
407#endif /* sun4v */
408
409 /*
410 * general optimization:
411 *
412 * the compiler (at least SC4.2/5.x) generates better code if
413 * variable use is localized. in this case, swapping the integers in

--- 60 unchanged lines hidden (view full) ---

474 x_1 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 1);
475 x_0 = LOAD_LITTLE_32(ctx->buf_un.buf32 + 0);
476#endif /* sun4v */
477 } else
478#endif
479 {
480
481#ifdef sun4v
482 /* LINTED E_BAD_PTR_CAST_ALIGN */
741 x_15 = LOAD_LITTLE_32_f(block);
483 x_15 = LOAD_LITTLE_32_f(block);
484 /* LINTED E_BAD_PTR_CAST_ALIGN */
742 x_14 = LOAD_LITTLE_32_e(block);
485 x_14 = LOAD_LITTLE_32_e(block);
486 /* LINTED E_BAD_PTR_CAST_ALIGN */
743 x_13 = LOAD_LITTLE_32_d(block);
487 x_13 = LOAD_LITTLE_32_d(block);
488 /* LINTED E_BAD_PTR_CAST_ALIGN */
744 x_12 = LOAD_LITTLE_32_c(block);
489 x_12 = LOAD_LITTLE_32_c(block);
490 /* LINTED E_BAD_PTR_CAST_ALIGN */
745 x_11 = LOAD_LITTLE_32_b(block);
491 x_11 = LOAD_LITTLE_32_b(block);
492 /* LINTED E_BAD_PTR_CAST_ALIGN */
746 x_10 = LOAD_LITTLE_32_a(block);
493 x_10 = LOAD_LITTLE_32_a(block);
494 /* LINTED E_BAD_PTR_CAST_ALIGN */
747 x_9 = LOAD_LITTLE_32_9(block);
495 x_9 = LOAD_LITTLE_32_9(block);
496 /* LINTED E_BAD_PTR_CAST_ALIGN */
748 x_8 = LOAD_LITTLE_32_8(block);
497 x_8 = LOAD_LITTLE_32_8(block);
498 /* LINTED E_BAD_PTR_CAST_ALIGN */
749 x_7 = LOAD_LITTLE_32_7(block);
499 x_7 = LOAD_LITTLE_32_7(block);
500 /* LINTED E_BAD_PTR_CAST_ALIGN */
750 x_6 = LOAD_LITTLE_32_6(block);
501 x_6 = LOAD_LITTLE_32_6(block);
502 /* LINTED E_BAD_PTR_CAST_ALIGN */
751 x_5 = LOAD_LITTLE_32_5(block);
503 x_5 = LOAD_LITTLE_32_5(block);
504 /* LINTED E_BAD_PTR_CAST_ALIGN */
752 x_4 = LOAD_LITTLE_32_4(block);
505 x_4 = LOAD_LITTLE_32_4(block);
506 /* LINTED E_BAD_PTR_CAST_ALIGN */
753 x_3 = LOAD_LITTLE_32_3(block);
507 x_3 = LOAD_LITTLE_32_3(block);
508 /* LINTED E_BAD_PTR_CAST_ALIGN */
754 x_2 = LOAD_LITTLE_32_2(block);
509 x_2 = LOAD_LITTLE_32_2(block);
510 /* LINTED E_BAD_PTR_CAST_ALIGN */
755 x_1 = LOAD_LITTLE_32_1(block);
511 x_1 = LOAD_LITTLE_32_1(block);
512 /* LINTED E_BAD_PTR_CAST_ALIGN */
756 x_0 = LOAD_LITTLE_32_0(block);
757#else
513 x_0 = LOAD_LITTLE_32_0(block);
514#else
515 /* LINTED E_BAD_PTR_CAST_ALIGN */
758 x_15 = LOAD_LITTLE_32(block + 60);
516 x_15 = LOAD_LITTLE_32(block + 60);
517 /* LINTED E_BAD_PTR_CAST_ALIGN */
759 x_14 = LOAD_LITTLE_32(block + 56);
518 x_14 = LOAD_LITTLE_32(block + 56);
519 /* LINTED E_BAD_PTR_CAST_ALIGN */
760 x_13 = LOAD_LITTLE_32(block + 52);
520 x_13 = LOAD_LITTLE_32(block + 52);
521 /* LINTED E_BAD_PTR_CAST_ALIGN */
761 x_12 = LOAD_LITTLE_32(block + 48);
522 x_12 = LOAD_LITTLE_32(block + 48);
523 /* LINTED E_BAD_PTR_CAST_ALIGN */
762 x_11 = LOAD_LITTLE_32(block + 44);
524 x_11 = LOAD_LITTLE_32(block + 44);
525 /* LINTED E_BAD_PTR_CAST_ALIGN */
763 x_10 = LOAD_LITTLE_32(block + 40);
526 x_10 = LOAD_LITTLE_32(block + 40);
527 /* LINTED E_BAD_PTR_CAST_ALIGN */
764 x_9 = LOAD_LITTLE_32(block + 36);
528 x_9 = LOAD_LITTLE_32(block + 36);
529 /* LINTED E_BAD_PTR_CAST_ALIGN */
765 x_8 = LOAD_LITTLE_32(block + 32);
530 x_8 = LOAD_LITTLE_32(block + 32);
531 /* LINTED E_BAD_PTR_CAST_ALIGN */
766 x_7 = LOAD_LITTLE_32(block + 28);
532 x_7 = LOAD_LITTLE_32(block + 28);
533 /* LINTED E_BAD_PTR_CAST_ALIGN */
767 x_6 = LOAD_LITTLE_32(block + 24);
534 x_6 = LOAD_LITTLE_32(block + 24);
535 /* LINTED E_BAD_PTR_CAST_ALIGN */
768 x_5 = LOAD_LITTLE_32(block + 20);
536 x_5 = LOAD_LITTLE_32(block + 20);
537 /* LINTED E_BAD_PTR_CAST_ALIGN */
769 x_4 = LOAD_LITTLE_32(block + 16);
538 x_4 = LOAD_LITTLE_32(block + 16);
539 /* LINTED E_BAD_PTR_CAST_ALIGN */
770 x_3 = LOAD_LITTLE_32(block + 12);
540 x_3 = LOAD_LITTLE_32(block + 12);
541 /* LINTED E_BAD_PTR_CAST_ALIGN */
771 x_2 = LOAD_LITTLE_32(block + 8);
542 x_2 = LOAD_LITTLE_32(block + 8);
543 /* LINTED E_BAD_PTR_CAST_ALIGN */
772 x_1 = LOAD_LITTLE_32(block + 4);
544 x_1 = LOAD_LITTLE_32(block + 4);
545 /* LINTED E_BAD_PTR_CAST_ALIGN */
773 x_0 = LOAD_LITTLE_32(block + 0);
774#endif /* sun4v */
775 }
776
777 /* round 1 */
778 FF(a, b, c, d, x_0, MD5_SHIFT_11, MD5_CONST_e(0)); /* 1 */
779 FF(d, a, b, c, x_1, MD5_SHIFT_12, MD5_CONST_o(1)); /* 2 */
780 FF(c, d, a, b, x_2, MD5_SHIFT_13, MD5_CONST_e(2)); /* 3 */

--- 75 unchanged lines hidden (view full) ---

856 * this out if everything is kept in registers
857 */
858
859 x_0 = x_1 = x_2 = x_3 = x_4 = x_5 = x_6 = x_7 = x_8 = 0;
860 x_9 = x_10 = x_11 = x_12 = x_13 = x_14 = x_15 = 0;
861}
862
863/*
546 x_0 = LOAD_LITTLE_32(block + 0);
547#endif /* sun4v */
548 }
549
550 /* round 1 */
551 FF(a, b, c, d, x_0, MD5_SHIFT_11, MD5_CONST_e(0)); /* 1 */
552 FF(d, a, b, c, x_1, MD5_SHIFT_12, MD5_CONST_o(1)); /* 2 */
553 FF(c, d, a, b, x_2, MD5_SHIFT_13, MD5_CONST_e(2)); /* 3 */

--- 75 unchanged lines hidden (view full) ---

629 * this out if everything is kept in registers
630 */
631
632 x_0 = x_1 = x_2 = x_3 = x_4 = x_5 = x_6 = x_7 = x_8 = 0;
633 x_9 = x_10 = x_11 = x_12 = x_13 = x_14 = x_15 = 0;
634}
635
636/*
864 * devpro compiler optimization:
865 *
866 * the compiler can generate better code if it knows that `input' and
867 * `output' do not point to the same source. there is no portable
868 * way to tell the compiler this, but the devpro compiler recognizes the
869 * `_Restrict' keyword to indicate this condition. use it if possible.
870 */
871
872#if defined(__RESTRICT) && !defined(__GNUC__)
873#define restrict _Restrict
874#else
875#define restrict /* nothing */
876#endif
877
878/*
879 * Encode()
880 *
881 * purpose: to convert a list of numbers from big endian to little endian
882 * input: uint8_t * : place to store the converted little endian numbers
883 * uint32_t * : place to get numbers to convert from
884 * size_t : the length of the input in bytes
885 * output: void
886 */
887
888static void
637 * Encode()
638 *
639 * purpose: to convert a list of numbers from big endian to little endian
640 * input: uint8_t * : place to store the converted little endian numbers
641 * uint32_t * : place to get numbers to convert from
642 * size_t : the length of the input in bytes
643 * output: void
644 */
645
646static void
889Encode(uint8_t *restrict output, uint32_t *restrict input, size_t input_len)
647Encode(uint8_t *_RESTRICT_KYWD output, const uint32_t *_RESTRICT_KYWD input,
648 size_t input_len)
890{
891 size_t i, j;
892
893 for (i = 0, j = 0; j < input_len; i++, j += sizeof (uint32_t)) {
894
895#ifdef _LITTLE_ENDIAN
896
897#ifdef _MD5_CHECK_ALIGNMENT
898 if ((uintptr_t)output & 0x3) /* Not 4-byte aligned */
899 bcopy(input + i, output + j, 4);
900 else *(uint32_t *)(output + j) = input[i];
901#else
649{
650 size_t i, j;
651
652 for (i = 0, j = 0; j < input_len; i++, j += sizeof (uint32_t)) {
653
654#ifdef _LITTLE_ENDIAN
655
656#ifdef _MD5_CHECK_ALIGNMENT
657 if ((uintptr_t)output & 0x3) /* Not 4-byte aligned */
658 bcopy(input + i, output + j, 4);
659 else *(uint32_t *)(output + j) = input[i];
660#else
661 /*LINTED E_BAD_PTR_CAST_ALIGN*/
902 *(uint32_t *)(output + j) = input[i];
903#endif /* _MD5_CHECK_ALIGNMENT */
904
905#else /* big endian -- will work on little endian, but slowly */
906
907 output[j] = input[i] & 0xff;
908 output[j + 1] = (input[i] >> 8) & 0xff;
909 output[j + 2] = (input[i] >> 16) & 0xff;
910 output[j + 3] = (input[i] >> 24) & 0xff;
911#endif
912 }
913}
662 *(uint32_t *)(output + j) = input[i];
663#endif /* _MD5_CHECK_ALIGNMENT */
664
665#else /* big endian -- will work on little endian, but slowly */
666
667 output[j] = input[i] & 0xff;
668 output[j + 1] = (input[i] >> 8) & 0xff;
669 output[j + 2] = (input[i] >> 16) & 0xff;
670 output[j + 3] = (input[i] >> 24) & 0xff;
671#endif
672 }
673}
914
915#if defined(_KERNEL) && !defined(_BOOT)
916
917/*
918 * KCF software provider control entry points.
919 */
920/* ARGSUSED */
921static void
922md5_provider_status(crypto_provider_handle_t provider, uint_t *status)
923{
924 *status = CRYPTO_PROVIDER_READY;
925}
926
927/*
928 * KCF software provider digest entry points.
929 */
930
931static int
932md5_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
933 crypto_req_handle_t req)
934{
935 if (mechanism->cm_type != MD5_MECH_INFO_TYPE)
936 return (CRYPTO_MECHANISM_INVALID);
937
938 /*
939 * Allocate and initialize MD5 context.
940 */
941 ctx->cc_provider_private = kmem_alloc(sizeof (md5_ctx_t),
942 crypto_kmflag(req));
943 if (ctx->cc_provider_private == NULL)
944 return (CRYPTO_HOST_MEMORY);
945
946 PROV_MD5_CTX(ctx)->mc_mech_type = MD5_MECH_INFO_TYPE;
947 MD5Init(&PROV_MD5_CTX(ctx)->mc_md5_ctx);
948
949 return (CRYPTO_SUCCESS);
950}
951
952/*
953 * Helper MD5 digest update function for uio data.
954 */
955static int
956md5_digest_update_uio(MD5_CTX *md5_ctx, crypto_data_t *data)
957{
958 off_t offset = data->cd_offset;
959 size_t length = data->cd_length;
960 uint_t vec_idx;
961 size_t cur_len;
962
963 /* we support only kernel buffer */
964 if (data->cd_uio->uio_segflg != UIO_SYSSPACE)
965 return (CRYPTO_ARGUMENTS_BAD);
966
967 /*
968 * Jump to the first iovec containing data to be
969 * digested.
970 */
971 for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt &&
972 offset >= data->cd_uio->uio_iov[vec_idx].iov_len;
973 offset -= data->cd_uio->uio_iov[vec_idx++].iov_len);
974 if (vec_idx == data->cd_uio->uio_iovcnt) {
975 /*
976 * The caller specified an offset that is larger than the
977 * total size of the buffers it provided.
978 */
979 return (CRYPTO_DATA_LEN_RANGE);
980 }
981
982 /*
983 * Now do the digesting on the iovecs.
984 */
985 while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) {
986 cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len -
987 offset, length);
988
989 MD5Update(md5_ctx, data->cd_uio->uio_iov[vec_idx].iov_base +
990 offset, cur_len);
991
992 length -= cur_len;
993 vec_idx++;
994 offset = 0;
995 }
996
997 if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) {
998 /*
999 * The end of the specified iovec's was reached but
1000 * the length requested could not be processed, i.e.
1001 * The caller requested to digest more data than it provided.
1002 */
1003 return (CRYPTO_DATA_LEN_RANGE);
1004 }
1005
1006 return (CRYPTO_SUCCESS);
1007}
1008
1009/*
1010 * Helper MD5 digest final function for uio data.
1011 * digest_len is the length of the desired digest. If digest_len
1012 * is smaller than the default MD5 digest length, the caller
1013 * must pass a scratch buffer, digest_scratch, which must
1014 * be at least MD5_DIGEST_LENGTH bytes.
1015 */
1016static int
1017md5_digest_final_uio(MD5_CTX *md5_ctx, crypto_data_t *digest,
1018 ulong_t digest_len, uchar_t *digest_scratch)
1019{
1020 off_t offset = digest->cd_offset;
1021 uint_t vec_idx;
1022
1023 /* we support only kernel buffer */
1024 if (digest->cd_uio->uio_segflg != UIO_SYSSPACE)
1025 return (CRYPTO_ARGUMENTS_BAD);
1026
1027 /*
1028 * Jump to the first iovec containing ptr to the digest to
1029 * be returned.
1030 */
1031 for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len &&
1032 vec_idx < digest->cd_uio->uio_iovcnt;
1033 offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len);
1034 if (vec_idx == digest->cd_uio->uio_iovcnt) {
1035 /*
1036 * The caller specified an offset that is
1037 * larger than the total size of the buffers
1038 * it provided.
1039 */
1040 return (CRYPTO_DATA_LEN_RANGE);
1041 }
1042
1043 if (offset + digest_len <=
1044 digest->cd_uio->uio_iov[vec_idx].iov_len) {
1045 /*
1046 * The computed MD5 digest will fit in the current
1047 * iovec.
1048 */
1049 if (digest_len != MD5_DIGEST_LENGTH) {
1050 /*
1051 * The caller requested a short digest. Digest
1052 * into a scratch buffer and return to
1053 * the user only what was requested.
1054 */
1055 MD5Final(digest_scratch, md5_ctx);
1056 bcopy(digest_scratch, (uchar_t *)digest->
1057 cd_uio->uio_iov[vec_idx].iov_base + offset,
1058 digest_len);
1059 } else {
1060 MD5Final((uchar_t *)digest->
1061 cd_uio->uio_iov[vec_idx].iov_base + offset,
1062 md5_ctx);
1063 }
1064 } else {
1065 /*
1066 * The computed digest will be crossing one or more iovec's.
1067 * This is bad performance-wise but we need to support it.
1068 * Allocate a small scratch buffer on the stack and
1069 * copy it piece meal to the specified digest iovec's.
1070 */
1071 uchar_t digest_tmp[MD5_DIGEST_LENGTH];
1072 off_t scratch_offset = 0;
1073 size_t length = digest_len;
1074 size_t cur_len;
1075
1076 MD5Final(digest_tmp, md5_ctx);
1077
1078 while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) {
1079 cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len -
1080 offset, length);
1081 bcopy(digest_tmp + scratch_offset,
1082 digest->cd_uio->uio_iov[vec_idx].iov_base + offset,
1083 cur_len);
1084
1085 length -= cur_len;
1086 vec_idx++;
1087 scratch_offset += cur_len;
1088 offset = 0;
1089 }
1090
1091 if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) {
1092 /*
1093 * The end of the specified iovec's was reached but
1094 * the length requested could not be processed, i.e.
1095 * The caller requested to digest more data than it
1096 * provided.
1097 */
1098 return (CRYPTO_DATA_LEN_RANGE);
1099 }
1100 }
1101
1102 return (CRYPTO_SUCCESS);
1103}
1104
1105/*
1106 * Helper MD5 digest update for mblk's.
1107 */
1108static int
1109md5_digest_update_mblk(MD5_CTX *md5_ctx, crypto_data_t *data)
1110{
1111 off_t offset = data->cd_offset;
1112 size_t length = data->cd_length;
1113 mblk_t *mp;
1114 size_t cur_len;
1115
1116 /*
1117 * Jump to the first mblk_t containing data to be digested.
1118 */
1119 for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
1120 offset -= MBLKL(mp), mp = mp->b_cont);
1121 if (mp == NULL) {
1122 /*
1123 * The caller specified an offset that is larger than the
1124 * total size of the buffers it provided.
1125 */
1126 return (CRYPTO_DATA_LEN_RANGE);
1127 }
1128
1129 /*
1130 * Now do the digesting on the mblk chain.
1131 */
1132 while (mp != NULL && length > 0) {
1133 cur_len = MIN(MBLKL(mp) - offset, length);
1134 MD5Update(md5_ctx, mp->b_rptr + offset, cur_len);
1135 length -= cur_len;
1136 offset = 0;
1137 mp = mp->b_cont;
1138 }
1139
1140 if (mp == NULL && length > 0) {
1141 /*
1142 * The end of the mblk was reached but the length requested
1143 * could not be processed, i.e. The caller requested
1144 * to digest more data than it provided.
1145 */
1146 return (CRYPTO_DATA_LEN_RANGE);
1147 }
1148
1149 return (CRYPTO_SUCCESS);
1150}
1151
1152/*
1153 * Helper MD5 digest final for mblk's.
1154 * digest_len is the length of the desired digest. If digest_len
1155 * is smaller than the default MD5 digest length, the caller
1156 * must pass a scratch buffer, digest_scratch, which must
1157 * be at least MD5_DIGEST_LENGTH bytes.
1158 */
1159static int
1160md5_digest_final_mblk(MD5_CTX *md5_ctx, crypto_data_t *digest,
1161 ulong_t digest_len, uchar_t *digest_scratch)
1162{
1163 off_t offset = digest->cd_offset;
1164 mblk_t *mp;
1165
1166 /*
1167 * Jump to the first mblk_t that will be used to store the digest.
1168 */
1169 for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp);
1170 offset -= MBLKL(mp), mp = mp->b_cont);
1171 if (mp == NULL) {
1172 /*
1173 * The caller specified an offset that is larger than the
1174 * total size of the buffers it provided.
1175 */
1176 return (CRYPTO_DATA_LEN_RANGE);
1177 }
1178
1179 if (offset + digest_len <= MBLKL(mp)) {
1180 /*
1181 * The computed MD5 digest will fit in the current mblk.
1182 * Do the MD5Final() in-place.
1183 */
1184 if (digest_len != MD5_DIGEST_LENGTH) {
1185 /*
1186 * The caller requested a short digest. Digest
1187 * into a scratch buffer and return to
1188 * the user only what was requested.
1189 */
1190 MD5Final(digest_scratch, md5_ctx);
1191 bcopy(digest_scratch, mp->b_rptr + offset, digest_len);
1192 } else {
1193 MD5Final(mp->b_rptr + offset, md5_ctx);
1194 }
1195 } else {
1196 /*
1197 * The computed digest will be crossing one or more mblk's.
1198 * This is bad performance-wise but we need to support it.
1199 * Allocate a small scratch buffer on the stack and
1200 * copy it piece meal to the specified digest iovec's.
1201 */
1202 uchar_t digest_tmp[MD5_DIGEST_LENGTH];
1203 off_t scratch_offset = 0;
1204 size_t length = digest_len;
1205 size_t cur_len;
1206
1207 MD5Final(digest_tmp, md5_ctx);
1208
1209 while (mp != NULL && length > 0) {
1210 cur_len = MIN(MBLKL(mp) - offset, length);
1211 bcopy(digest_tmp + scratch_offset,
1212 mp->b_rptr + offset, cur_len);
1213
1214 length -= cur_len;
1215 mp = mp->b_cont;
1216 scratch_offset += cur_len;
1217 offset = 0;
1218 }
1219
1220 if (mp == NULL && length > 0) {
1221 /*
1222 * The end of the specified mblk was reached but
1223 * the length requested could not be processed, i.e.
1224 * The caller requested to digest more data than it
1225 * provided.
1226 */
1227 return (CRYPTO_DATA_LEN_RANGE);
1228 }
1229 }
1230
1231 return (CRYPTO_SUCCESS);
1232}
1233
1234/* ARGSUSED */
1235static int
1236md5_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
1237 crypto_req_handle_t req)
1238{
1239 int ret = CRYPTO_SUCCESS;
1240
1241 ASSERT(ctx->cc_provider_private != NULL);
1242
1243 /*
1244 * We need to just return the length needed to store the output.
1245 * We should not destroy the context for the following cases.
1246 */
1247 if ((digest->cd_length == 0) ||
1248 (digest->cd_length < MD5_DIGEST_LENGTH)) {
1249 digest->cd_length = MD5_DIGEST_LENGTH;
1250 return (CRYPTO_BUFFER_TOO_SMALL);
1251 }
1252
1253 /*
1254 * Do the MD5 update on the specified input data.
1255 */
1256 switch (data->cd_format) {
1257 case CRYPTO_DATA_RAW:
1258 MD5Update(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1259 data->cd_raw.iov_base + data->cd_offset,
1260 data->cd_length);
1261 break;
1262 case CRYPTO_DATA_UIO:
1263 ret = md5_digest_update_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1264 data);
1265 break;
1266 case CRYPTO_DATA_MBLK:
1267 ret = md5_digest_update_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1268 data);
1269 break;
1270 default:
1271 ret = CRYPTO_ARGUMENTS_BAD;
1272 }
1273
1274 if (ret != CRYPTO_SUCCESS) {
1275 /* the update failed, free context and bail */
1276 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t));
1277 ctx->cc_provider_private = NULL;
1278 digest->cd_length = 0;
1279 return (ret);
1280 }
1281
1282 /*
1283 * Do an MD5 final, must be done separately since the digest
1284 * type can be different than the input data type.
1285 */
1286 switch (digest->cd_format) {
1287 case CRYPTO_DATA_RAW:
1288 MD5Final((unsigned char *)digest->cd_raw.iov_base +
1289 digest->cd_offset, &PROV_MD5_CTX(ctx)->mc_md5_ctx);
1290 break;
1291 case CRYPTO_DATA_UIO:
1292 ret = md5_digest_final_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1293 digest, MD5_DIGEST_LENGTH, NULL);
1294 break;
1295 case CRYPTO_DATA_MBLK:
1296 ret = md5_digest_final_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1297 digest, MD5_DIGEST_LENGTH, NULL);
1298 break;
1299 default:
1300 ret = CRYPTO_ARGUMENTS_BAD;
1301 }
1302
1303 /* all done, free context and return */
1304
1305 if (ret == CRYPTO_SUCCESS) {
1306 digest->cd_length = MD5_DIGEST_LENGTH;
1307 } else {
1308 digest->cd_length = 0;
1309 }
1310
1311 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t));
1312 ctx->cc_provider_private = NULL;
1313 return (ret);
1314}
1315
1316/* ARGSUSED */
1317static int
1318md5_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
1319 crypto_req_handle_t req)
1320{
1321 int ret = CRYPTO_SUCCESS;
1322
1323 ASSERT(ctx->cc_provider_private != NULL);
1324
1325 /*
1326 * Do the MD5 update on the specified input data.
1327 */
1328 switch (data->cd_format) {
1329 case CRYPTO_DATA_RAW:
1330 MD5Update(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1331 data->cd_raw.iov_base + data->cd_offset,
1332 data->cd_length);
1333 break;
1334 case CRYPTO_DATA_UIO:
1335 ret = md5_digest_update_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1336 data);
1337 break;
1338 case CRYPTO_DATA_MBLK:
1339 ret = md5_digest_update_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1340 data);
1341 break;
1342 default:
1343 ret = CRYPTO_ARGUMENTS_BAD;
1344 }
1345
1346 return (ret);
1347}
1348
1349/* ARGSUSED */
1350static int
1351md5_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
1352 crypto_req_handle_t req)
1353{
1354 int ret = CRYPTO_SUCCESS;
1355
1356 ASSERT(ctx->cc_provider_private != NULL);
1357
1358 /*
1359 * We need to just return the length needed to store the output.
1360 * We should not destroy the context for the following cases.
1361 */
1362 if ((digest->cd_length == 0) ||
1363 (digest->cd_length < MD5_DIGEST_LENGTH)) {
1364 digest->cd_length = MD5_DIGEST_LENGTH;
1365 return (CRYPTO_BUFFER_TOO_SMALL);
1366 }
1367
1368 /*
1369 * Do an MD5 final.
1370 */
1371 switch (digest->cd_format) {
1372 case CRYPTO_DATA_RAW:
1373 MD5Final((unsigned char *)digest->cd_raw.iov_base +
1374 digest->cd_offset, &PROV_MD5_CTX(ctx)->mc_md5_ctx);
1375 break;
1376 case CRYPTO_DATA_UIO:
1377 ret = md5_digest_final_uio(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1378 digest, MD5_DIGEST_LENGTH, NULL);
1379 break;
1380 case CRYPTO_DATA_MBLK:
1381 ret = md5_digest_final_mblk(&PROV_MD5_CTX(ctx)->mc_md5_ctx,
1382 digest, MD5_DIGEST_LENGTH, NULL);
1383 break;
1384 default:
1385 ret = CRYPTO_ARGUMENTS_BAD;
1386 }
1387
1388 /* all done, free context and return */
1389
1390 if (ret == CRYPTO_SUCCESS) {
1391 digest->cd_length = MD5_DIGEST_LENGTH;
1392 } else {
1393 digest->cd_length = 0;
1394 }
1395
1396 kmem_free(ctx->cc_provider_private, sizeof (md5_ctx_t));
1397 ctx->cc_provider_private = NULL;
1398
1399 return (ret);
1400}
1401
1402/* ARGSUSED */
1403static int
1404md5_digest_atomic(crypto_provider_handle_t provider,
1405 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1406 crypto_data_t *data, crypto_data_t *digest,
1407 crypto_req_handle_t req)
1408{
1409 int ret = CRYPTO_SUCCESS;
1410 MD5_CTX md5_ctx;
1411
1412 if (mechanism->cm_type != MD5_MECH_INFO_TYPE)
1413 return (CRYPTO_MECHANISM_INVALID);
1414
1415 /*
1416 * Do the MD5 init.
1417 */
1418 MD5Init(&md5_ctx);
1419
1420 /*
1421 * Do the MD5 update on the specified input data.
1422 */
1423 switch (data->cd_format) {
1424 case CRYPTO_DATA_RAW:
1425 MD5Update(&md5_ctx, data->cd_raw.iov_base + data->cd_offset,
1426 data->cd_length);
1427 break;
1428 case CRYPTO_DATA_UIO:
1429 ret = md5_digest_update_uio(&md5_ctx, data);
1430 break;
1431 case CRYPTO_DATA_MBLK:
1432 ret = md5_digest_update_mblk(&md5_ctx, data);
1433 break;
1434 default:
1435 ret = CRYPTO_ARGUMENTS_BAD;
1436 }
1437
1438 if (ret != CRYPTO_SUCCESS) {
1439 /* the update failed, bail */
1440 digest->cd_length = 0;
1441 return (ret);
1442 }
1443
1444 /*
1445 * Do an MD5 final, must be done separately since the digest
1446 * type can be different than the input data type.
1447 */
1448 switch (digest->cd_format) {
1449 case CRYPTO_DATA_RAW:
1450 MD5Final((unsigned char *)digest->cd_raw.iov_base +
1451 digest->cd_offset, &md5_ctx);
1452 break;
1453 case CRYPTO_DATA_UIO:
1454 ret = md5_digest_final_uio(&md5_ctx, digest,
1455 MD5_DIGEST_LENGTH, NULL);
1456 break;
1457 case CRYPTO_DATA_MBLK:
1458 ret = md5_digest_final_mblk(&md5_ctx, digest,
1459 MD5_DIGEST_LENGTH, NULL);
1460 break;
1461 default:
1462 ret = CRYPTO_ARGUMENTS_BAD;
1463 }
1464
1465 if (ret == CRYPTO_SUCCESS) {
1466 digest->cd_length = MD5_DIGEST_LENGTH;
1467 } else {
1468 digest->cd_length = 0;
1469 }
1470
1471 return (ret);
1472}
1473
1474/*
1475 * KCF software provider mac entry points.
1476 *
1477 * MD5 HMAC is: MD5(key XOR opad, MD5(key XOR ipad, text))
1478 *
1479 * Init:
1480 * The initialization routine initializes what we denote
1481 * as the inner and outer contexts by doing
1482 * - for inner context: MD5(key XOR ipad)
1483 * - for outer context: MD5(key XOR opad)
1484 *
1485 * Update:
1486 * Each subsequent MD5 HMAC update will result in an
1487 * update of the inner context with the specified data.
1488 *
1489 * Final:
1490 * The MD5 HMAC final will do a MD5 final operation on the
1491 * inner context, and the resulting digest will be used
1492 * as the data for an update on the outer context. Last
1493 * but not least, an MD5 final on the outer context will
1494 * be performed to obtain the MD5 HMAC digest to return
1495 * to the user.
1496 */
1497
1498/*
1499 * Initialize a MD5-HMAC context.
1500 */
1501static void
1502md5_mac_init_ctx(md5_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
1503{
1504 uint32_t ipad[MD5_HMAC_INTS_PER_BLOCK];
1505 uint32_t opad[MD5_HMAC_INTS_PER_BLOCK];
1506 uint_t i;
1507
1508 bzero(ipad, MD5_HMAC_BLOCK_SIZE);
1509 bzero(opad, MD5_HMAC_BLOCK_SIZE);
1510
1511 bcopy(keyval, ipad, length_in_bytes);
1512 bcopy(keyval, opad, length_in_bytes);
1513
1514 /* XOR key with ipad (0x36) and opad (0x5c) */
1515 for (i = 0; i < MD5_HMAC_INTS_PER_BLOCK; i++) {
1516 ipad[i] ^= 0x36363636;
1517 opad[i] ^= 0x5c5c5c5c;
1518 }
1519
1520 /* perform MD5 on ipad */
1521 MD5Init(&ctx->hc_icontext);
1522 MD5Update(&ctx->hc_icontext, ipad, MD5_HMAC_BLOCK_SIZE);
1523
1524 /* perform MD5 on opad */
1525 MD5Init(&ctx->hc_ocontext);
1526 MD5Update(&ctx->hc_ocontext, opad, MD5_HMAC_BLOCK_SIZE);
1527}
1528
1529/*
1530 * Initializes a multi-part MAC operation.
1531 */
1532static int
1533md5_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
1534 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
1535 crypto_req_handle_t req)
1536{
1537 int ret = CRYPTO_SUCCESS;
1538 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1539
1540 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE &&
1541 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE)
1542 return (CRYPTO_MECHANISM_INVALID);
1543
1544 /* Add support for key by attributes (RFE 4706552) */
1545 if (key->ck_format != CRYPTO_KEY_RAW)
1546 return (CRYPTO_ARGUMENTS_BAD);
1547
1548 ctx->cc_provider_private = kmem_alloc(sizeof (md5_hmac_ctx_t),
1549 crypto_kmflag(req));
1550 if (ctx->cc_provider_private == NULL)
1551 return (CRYPTO_HOST_MEMORY);
1552
1553 if (ctx_template != NULL) {
1554 /* reuse context template */
1555 bcopy(ctx_template, PROV_MD5_HMAC_CTX(ctx),
1556 sizeof (md5_hmac_ctx_t));
1557 } else {
1558 /* no context template, compute context */
1559 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) {
1560 uchar_t digested_key[MD5_DIGEST_LENGTH];
1561 md5_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
1562
1563 /*
1564 * Hash the passed-in key to get a smaller key.
1565 * The inner context is used since it hasn't been
1566 * initialized yet.
1567 */
1568 PROV_MD5_DIGEST_KEY(&hmac_ctx->hc_icontext,
1569 key->ck_data, keylen_in_bytes, digested_key);
1570 md5_mac_init_ctx(PROV_MD5_HMAC_CTX(ctx),
1571 digested_key, MD5_DIGEST_LENGTH);
1572 } else {
1573 md5_mac_init_ctx(PROV_MD5_HMAC_CTX(ctx),
1574 key->ck_data, keylen_in_bytes);
1575 }
1576 }
1577
1578 /*
1579 * Get the mechanism parameters, if applicable.
1580 */
1581 PROV_MD5_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
1582 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) {
1583 if (mechanism->cm_param == NULL ||
1584 mechanism->cm_param_len != sizeof (ulong_t))
1585 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1586 PROV_MD5_GET_DIGEST_LEN(mechanism,
1587 PROV_MD5_HMAC_CTX(ctx)->hc_digest_len);
1588 if (PROV_MD5_HMAC_CTX(ctx)->hc_digest_len >
1589 MD5_DIGEST_LENGTH)
1590 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1591 }
1592
1593 if (ret != CRYPTO_SUCCESS) {
1594 bzero(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t));
1595 kmem_free(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t));
1596 ctx->cc_provider_private = NULL;
1597 }
1598
1599 return (ret);
1600}
1601
1602
1603/* ARGSUSED */
1604static int
1605md5_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
1606{
1607 int ret = CRYPTO_SUCCESS;
1608
1609 ASSERT(ctx->cc_provider_private != NULL);
1610
1611 /*
1612 * Do an MD5 update of the inner context using the specified
1613 * data.
1614 */
1615 switch (data->cd_format) {
1616 case CRYPTO_DATA_RAW:
1617 MD5Update(&PROV_MD5_HMAC_CTX(ctx)->hc_icontext,
1618 data->cd_raw.iov_base + data->cd_offset,
1619 data->cd_length);
1620 break;
1621 case CRYPTO_DATA_UIO:
1622 ret = md5_digest_update_uio(
1623 &PROV_MD5_HMAC_CTX(ctx)->hc_icontext, data);
1624 break;
1625 case CRYPTO_DATA_MBLK:
1626 ret = md5_digest_update_mblk(
1627 &PROV_MD5_HMAC_CTX(ctx)->hc_icontext, data);
1628 break;
1629 default:
1630 ret = CRYPTO_ARGUMENTS_BAD;
1631 }
1632
1633 return (ret);
1634}
1635
1636/* ARGSUSED */
1637static int
1638md5_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
1639{
1640 int ret = CRYPTO_SUCCESS;
1641 uchar_t digest[MD5_DIGEST_LENGTH];
1642 uint32_t digest_len = MD5_DIGEST_LENGTH;
1643
1644 ASSERT(ctx->cc_provider_private != NULL);
1645
1646 if (PROV_MD5_HMAC_CTX(ctx)->hc_mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE)
1647 digest_len = PROV_MD5_HMAC_CTX(ctx)->hc_digest_len;
1648
1649 /*
1650 * We need to just return the length needed to store the output.
1651 * We should not destroy the context for the following cases.
1652 */
1653 if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
1654 mac->cd_length = digest_len;
1655 return (CRYPTO_BUFFER_TOO_SMALL);
1656 }
1657
1658 /*
1659 * Do an MD5 final on the inner context.
1660 */
1661 MD5Final(digest, &PROV_MD5_HMAC_CTX(ctx)->hc_icontext);
1662
1663 /*
1664 * Do an MD5 update on the outer context, feeding the inner
1665 * digest as data.
1666 */
1667 MD5Update(&PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, digest,
1668 MD5_DIGEST_LENGTH);
1669
1670 /*
1671 * Do an MD5 final on the outer context, storing the computing
1672 * digest in the users buffer.
1673 */
1674 switch (mac->cd_format) {
1675 case CRYPTO_DATA_RAW:
1676 if (digest_len != MD5_DIGEST_LENGTH) {
1677 /*
1678 * The caller requested a short digest. Digest
1679 * into a scratch buffer and return to
1680 * the user only what was requested.
1681 */
1682 MD5Final(digest,
1683 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext);
1684 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
1685 mac->cd_offset, digest_len);
1686 } else {
1687 MD5Final((unsigned char *)mac->cd_raw.iov_base +
1688 mac->cd_offset,
1689 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext);
1690 }
1691 break;
1692 case CRYPTO_DATA_UIO:
1693 ret = md5_digest_final_uio(
1694 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, mac,
1695 digest_len, digest);
1696 break;
1697 case CRYPTO_DATA_MBLK:
1698 ret = md5_digest_final_mblk(
1699 &PROV_MD5_HMAC_CTX(ctx)->hc_ocontext, mac,
1700 digest_len, digest);
1701 break;
1702 default:
1703 ret = CRYPTO_ARGUMENTS_BAD;
1704 }
1705
1706 if (ret == CRYPTO_SUCCESS) {
1707 mac->cd_length = digest_len;
1708 } else {
1709 mac->cd_length = 0;
1710 }
1711
1712 bzero(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t));
1713 kmem_free(ctx->cc_provider_private, sizeof (md5_hmac_ctx_t));
1714 ctx->cc_provider_private = NULL;
1715
1716 return (ret);
1717}
1718
1719#define MD5_MAC_UPDATE(data, ctx, ret) { \
1720 switch (data->cd_format) { \
1721 case CRYPTO_DATA_RAW: \
1722 MD5Update(&(ctx).hc_icontext, \
1723 data->cd_raw.iov_base + data->cd_offset, \
1724 data->cd_length); \
1725 break; \
1726 case CRYPTO_DATA_UIO: \
1727 ret = md5_digest_update_uio(&(ctx).hc_icontext, data); \
1728 break; \
1729 case CRYPTO_DATA_MBLK: \
1730 ret = md5_digest_update_mblk(&(ctx).hc_icontext, \
1731 data); \
1732 break; \
1733 default: \
1734 ret = CRYPTO_ARGUMENTS_BAD; \
1735 } \
1736}
1737
1738
1739/* ARGSUSED */
1740static int
1741md5_mac_atomic(crypto_provider_handle_t provider,
1742 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1743 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1744 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1745{
1746 int ret = CRYPTO_SUCCESS;
1747 uchar_t digest[MD5_DIGEST_LENGTH];
1748 md5_hmac_ctx_t md5_hmac_ctx;
1749 uint32_t digest_len = MD5_DIGEST_LENGTH;
1750 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1751
1752 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE &&
1753 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE)
1754 return (CRYPTO_MECHANISM_INVALID);
1755
1756 /* Add support for key by attributes (RFE 4706552) */
1757 if (key->ck_format != CRYPTO_KEY_RAW)
1758 return (CRYPTO_ARGUMENTS_BAD);
1759
1760 if (ctx_template != NULL) {
1761 /* reuse context template */
1762 bcopy(ctx_template, &md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
1763 } else {
1764 /* no context template, compute context */
1765 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) {
1766 /*
1767 * Hash the passed-in key to get a smaller key.
1768 * The inner context is used since it hasn't been
1769 * initialized yet.
1770 */
1771 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx.hc_icontext,
1772 key->ck_data, keylen_in_bytes, digest);
1773 md5_mac_init_ctx(&md5_hmac_ctx, digest,
1774 MD5_DIGEST_LENGTH);
1775 } else {
1776 md5_mac_init_ctx(&md5_hmac_ctx, key->ck_data,
1777 keylen_in_bytes);
1778 }
1779 }
1780
1781 /*
1782 * Get the mechanism parameters, if applicable.
1783 */
1784 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) {
1785 if (mechanism->cm_param == NULL ||
1786 mechanism->cm_param_len != sizeof (ulong_t)) {
1787 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1788 goto bail;
1789 }
1790 PROV_MD5_GET_DIGEST_LEN(mechanism, digest_len);
1791 if (digest_len > MD5_DIGEST_LENGTH) {
1792 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1793 goto bail;
1794 }
1795 }
1796
1797 /* do an MD5 update of the inner context using the specified data */
1798 MD5_MAC_UPDATE(data, md5_hmac_ctx, ret);
1799 if (ret != CRYPTO_SUCCESS)
1800 /* the update failed, free context and bail */
1801 goto bail;
1802
1803 /* do an MD5 final on the inner context */
1804 MD5Final(digest, &md5_hmac_ctx.hc_icontext);
1805
1806 /*
1807 * Do an MD5 update on the outer context, feeding the inner
1808 * digest as data.
1809 */
1810 MD5Update(&md5_hmac_ctx.hc_ocontext, digest, MD5_DIGEST_LENGTH);
1811
1812 /*
1813 * Do an MD5 final on the outer context, storing the computed
1814 * digest in the users buffer.
1815 */
1816 switch (mac->cd_format) {
1817 case CRYPTO_DATA_RAW:
1818 if (digest_len != MD5_DIGEST_LENGTH) {
1819 /*
1820 * The caller requested a short digest. Digest
1821 * into a scratch buffer and return to
1822 * the user only what was requested.
1823 */
1824 MD5Final(digest, &md5_hmac_ctx.hc_ocontext);
1825 bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
1826 mac->cd_offset, digest_len);
1827 } else {
1828 MD5Final((unsigned char *)mac->cd_raw.iov_base +
1829 mac->cd_offset, &md5_hmac_ctx.hc_ocontext);
1830 }
1831 break;
1832 case CRYPTO_DATA_UIO:
1833 ret = md5_digest_final_uio(&md5_hmac_ctx.hc_ocontext, mac,
1834 digest_len, digest);
1835 break;
1836 case CRYPTO_DATA_MBLK:
1837 ret = md5_digest_final_mblk(&md5_hmac_ctx.hc_ocontext, mac,
1838 digest_len, digest);
1839 break;
1840 default:
1841 ret = CRYPTO_ARGUMENTS_BAD;
1842 }
1843
1844 if (ret == CRYPTO_SUCCESS) {
1845 mac->cd_length = digest_len;
1846 } else {
1847 mac->cd_length = 0;
1848 }
1849 /* Extra paranoia: zeroizing the local context on the stack */
1850 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
1851
1852 return (ret);
1853bail:
1854 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
1855 mac->cd_length = 0;
1856 return (ret);
1857}
1858
1859/* ARGSUSED */
1860static int
1861md5_mac_verify_atomic(crypto_provider_handle_t provider,
1862 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1863 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1864 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1865{
1866 int ret = CRYPTO_SUCCESS;
1867 uchar_t digest[MD5_DIGEST_LENGTH];
1868 md5_hmac_ctx_t md5_hmac_ctx;
1869 uint32_t digest_len = MD5_DIGEST_LENGTH;
1870 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1871
1872 if (mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE &&
1873 mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE)
1874 return (CRYPTO_MECHANISM_INVALID);
1875
1876 /* Add support for key by attributes (RFE 4706552) */
1877 if (key->ck_format != CRYPTO_KEY_RAW)
1878 return (CRYPTO_ARGUMENTS_BAD);
1879
1880 if (ctx_template != NULL) {
1881 /* reuse context template */
1882 bcopy(ctx_template, &md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
1883 } else {
1884 /* no context template, compute context */
1885 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) {
1886 /*
1887 * Hash the passed-in key to get a smaller key.
1888 * The inner context is used since it hasn't been
1889 * initialized yet.
1890 */
1891 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx.hc_icontext,
1892 key->ck_data, keylen_in_bytes, digest);
1893 md5_mac_init_ctx(&md5_hmac_ctx, digest,
1894 MD5_DIGEST_LENGTH);
1895 } else {
1896 md5_mac_init_ctx(&md5_hmac_ctx, key->ck_data,
1897 keylen_in_bytes);
1898 }
1899 }
1900
1901 /*
1902 * Get the mechanism parameters, if applicable.
1903 */
1904 if (mechanism->cm_type == MD5_HMAC_GEN_MECH_INFO_TYPE) {
1905 if (mechanism->cm_param == NULL ||
1906 mechanism->cm_param_len != sizeof (ulong_t)) {
1907 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1908 goto bail;
1909 }
1910 PROV_MD5_GET_DIGEST_LEN(mechanism, digest_len);
1911 if (digest_len > MD5_DIGEST_LENGTH) {
1912 ret = CRYPTO_MECHANISM_PARAM_INVALID;
1913 goto bail;
1914 }
1915 }
1916
1917 if (mac->cd_length != digest_len) {
1918 ret = CRYPTO_INVALID_MAC;
1919 goto bail;
1920 }
1921
1922 /* do an MD5 update of the inner context using the specified data */
1923 MD5_MAC_UPDATE(data, md5_hmac_ctx, ret);
1924 if (ret != CRYPTO_SUCCESS)
1925 /* the update failed, free context and bail */
1926 goto bail;
1927
1928 /* do an MD5 final on the inner context */
1929 MD5Final(digest, &md5_hmac_ctx.hc_icontext);
1930
1931 /*
1932 * Do an MD5 update on the outer context, feeding the inner
1933 * digest as data.
1934 */
1935 MD5Update(&md5_hmac_ctx.hc_ocontext, digest, MD5_DIGEST_LENGTH);
1936
1937 /*
1938 * Do an MD5 final on the outer context, storing the computed
1939 * digest in the local digest buffer.
1940 */
1941 MD5Final(digest, &md5_hmac_ctx.hc_ocontext);
1942
1943 /*
1944 * Compare the computed digest against the expected digest passed
1945 * as argument.
1946 */
1947 switch (mac->cd_format) {
1948
1949 case CRYPTO_DATA_RAW:
1950 if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
1951 mac->cd_offset, digest_len) != 0)
1952 ret = CRYPTO_INVALID_MAC;
1953 break;
1954
1955 case CRYPTO_DATA_UIO: {
1956 off_t offset = mac->cd_offset;
1957 uint_t vec_idx;
1958 off_t scratch_offset = 0;
1959 size_t length = digest_len;
1960 size_t cur_len;
1961
1962 /* we support only kernel buffer */
1963 if (mac->cd_uio->uio_segflg != UIO_SYSSPACE)
1964 return (CRYPTO_ARGUMENTS_BAD);
1965
1966 /* jump to the first iovec containing the expected digest */
1967 for (vec_idx = 0;
1968 offset >= mac->cd_uio->uio_iov[vec_idx].iov_len &&
1969 vec_idx < mac->cd_uio->uio_iovcnt;
1970 offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len);
1971 if (vec_idx == mac->cd_uio->uio_iovcnt) {
1972 /*
1973 * The caller specified an offset that is
1974 * larger than the total size of the buffers
1975 * it provided.
1976 */
1977 ret = CRYPTO_DATA_LEN_RANGE;
1978 break;
1979 }
1980
1981 /* do the comparison of computed digest vs specified one */
1982 while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) {
1983 cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len -
1984 offset, length);
1985
1986 if (bcmp(digest + scratch_offset,
1987 mac->cd_uio->uio_iov[vec_idx].iov_base + offset,
1988 cur_len) != 0) {
1989 ret = CRYPTO_INVALID_MAC;
1990 break;
1991 }
1992
1993 length -= cur_len;
1994 vec_idx++;
1995 scratch_offset += cur_len;
1996 offset = 0;
1997 }
1998 break;
1999 }
2000
2001 case CRYPTO_DATA_MBLK: {
2002 off_t offset = mac->cd_offset;
2003 mblk_t *mp;
2004 off_t scratch_offset = 0;
2005 size_t length = digest_len;
2006 size_t cur_len;
2007
2008 /* jump to the first mblk_t containing the expected digest */
2009 for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp);
2010 offset -= MBLKL(mp), mp = mp->b_cont);
2011 if (mp == NULL) {
2012 /*
2013 * The caller specified an offset that is larger than
2014 * the total size of the buffers it provided.
2015 */
2016 ret = CRYPTO_DATA_LEN_RANGE;
2017 break;
2018 }
2019
2020 while (mp != NULL && length > 0) {
2021 cur_len = MIN(MBLKL(mp) - offset, length);
2022 if (bcmp(digest + scratch_offset,
2023 mp->b_rptr + offset, cur_len) != 0) {
2024 ret = CRYPTO_INVALID_MAC;
2025 break;
2026 }
2027
2028 length -= cur_len;
2029 mp = mp->b_cont;
2030 scratch_offset += cur_len;
2031 offset = 0;
2032 }
2033 break;
2034 }
2035
2036 default:
2037 ret = CRYPTO_ARGUMENTS_BAD;
2038 }
2039
2040 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
2041 return (ret);
2042bail:
2043 bzero(&md5_hmac_ctx, sizeof (md5_hmac_ctx_t));
2044 mac->cd_length = 0;
2045 return (ret);
2046}
2047
2048/*
2049 * KCF software provider context management entry points.
2050 */
2051
2052/* ARGSUSED */
2053static int
2054md5_create_ctx_template(crypto_provider_handle_t provider,
2055 crypto_mechanism_t *mechanism, crypto_key_t *key,
2056 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
2057 crypto_req_handle_t req)
2058{
2059 md5_hmac_ctx_t *md5_hmac_ctx_tmpl;
2060 uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
2061
2062 if ((mechanism->cm_type != MD5_HMAC_MECH_INFO_TYPE) &&
2063 (mechanism->cm_type != MD5_HMAC_GEN_MECH_INFO_TYPE))
2064 return (CRYPTO_MECHANISM_INVALID);
2065
2066 /* Add support for key by attributes (RFE 4706552) */
2067 if (key->ck_format != CRYPTO_KEY_RAW)
2068 return (CRYPTO_ARGUMENTS_BAD);
2069
2070 /*
2071 * Allocate and initialize MD5 context.
2072 */
2073 md5_hmac_ctx_tmpl = kmem_alloc(sizeof (md5_hmac_ctx_t),
2074 crypto_kmflag(req));
2075 if (md5_hmac_ctx_tmpl == NULL)
2076 return (CRYPTO_HOST_MEMORY);
2077
2078 if (keylen_in_bytes > MD5_HMAC_BLOCK_SIZE) {
2079 uchar_t digested_key[MD5_DIGEST_LENGTH];
2080
2081 /*
2082 * Hash the passed-in key to get a smaller key.
2083 * The inner context is used since it hasn't been
2084 * initialized yet.
2085 */
2086 PROV_MD5_DIGEST_KEY(&md5_hmac_ctx_tmpl->hc_icontext,
2087 key->ck_data, keylen_in_bytes, digested_key);
2088 md5_mac_init_ctx(md5_hmac_ctx_tmpl, digested_key,
2089 MD5_DIGEST_LENGTH);
2090 } else {
2091 md5_mac_init_ctx(md5_hmac_ctx_tmpl, key->ck_data,
2092 keylen_in_bytes);
2093 }
2094
2095 md5_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
2096 *ctx_template = (crypto_spi_ctx_template_t)md5_hmac_ctx_tmpl;
2097 *ctx_template_size = sizeof (md5_hmac_ctx_t);
2098
2099 return (CRYPTO_SUCCESS);
2100}
2101
2102static int
2103md5_free_context(crypto_ctx_t *ctx)
2104{
2105 uint_t ctx_len;
2106 md5_mech_type_t mech_type;
2107
2108 if (ctx->cc_provider_private == NULL)
2109 return (CRYPTO_SUCCESS);
2110
2111 /*
2112 * We have to free either MD5 or MD5-HMAC contexts, which
2113 * have different lengths.
2114 */
2115
2116 mech_type = PROV_MD5_CTX(ctx)->mc_mech_type;
2117 if (mech_type == MD5_MECH_INFO_TYPE)
2118 ctx_len = sizeof (md5_ctx_t);
2119 else {
2120 ASSERT(mech_type == MD5_HMAC_MECH_INFO_TYPE ||
2121 mech_type == MD5_HMAC_GEN_MECH_INFO_TYPE);
2122 ctx_len = sizeof (md5_hmac_ctx_t);
2123 }
2124
2125 bzero(ctx->cc_provider_private, ctx_len);
2126 kmem_free(ctx->cc_provider_private, ctx_len);
2127 ctx->cc_provider_private = NULL;
2128
2129 return (CRYPTO_SUCCESS);
2130}
2131
2132#endif /* _KERNEL && !_BOOT */