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