1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2eda14cbcSMatt Macy /*
3eda14cbcSMatt Macy * CDDL HEADER START
4eda14cbcSMatt Macy *
5eda14cbcSMatt Macy * The contents of this file are subject to the terms of the
6eda14cbcSMatt Macy * Common Development and Distribution License (the "License").
7eda14cbcSMatt Macy * You may not use this file except in compliance with the License.
8eda14cbcSMatt Macy *
9eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0.
11eda14cbcSMatt Macy * See the License for the specific language governing permissions
12eda14cbcSMatt Macy * and limitations under the License.
13eda14cbcSMatt Macy *
14eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each
15eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the
17eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying
18eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner]
19eda14cbcSMatt Macy *
20eda14cbcSMatt Macy * CDDL HEADER END
21eda14cbcSMatt Macy */
22eda14cbcSMatt Macy
23eda14cbcSMatt Macy /*
24eda14cbcSMatt Macy * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25eda14cbcSMatt Macy * Use is subject to license terms.
26eda14cbcSMatt Macy */
27eda14cbcSMatt Macy
28eda14cbcSMatt Macy #include <sys/zfs_context.h>
29eda14cbcSMatt Macy #include <sys/crypto/common.h>
30eda14cbcSMatt Macy #include <sys/crypto/spi.h>
31eda14cbcSMatt Macy #include <sys/crypto/icp.h>
32eda14cbcSMatt Macy #include <sys/sha2.h>
33eda14cbcSMatt Macy #include <sha2/sha2_impl.h>
34eda14cbcSMatt Macy
35eda14cbcSMatt Macy /*
36eda14cbcSMatt Macy * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed
37eda14cbcSMatt Macy * by KCF to one of the entry points.
38eda14cbcSMatt Macy */
39eda14cbcSMatt Macy
40eda14cbcSMatt Macy #define PROV_SHA2_CTX(ctx) ((sha2_ctx_t *)(ctx)->cc_provider_private)
41eda14cbcSMatt Macy #define PROV_SHA2_HMAC_CTX(ctx) ((sha2_hmac_ctx_t *)(ctx)->cc_provider_private)
42eda14cbcSMatt Macy
43eda14cbcSMatt Macy /* to extract the digest length passed as mechanism parameter */
44eda14cbcSMatt Macy #define PROV_SHA2_GET_DIGEST_LEN(m, len) { \
45eda14cbcSMatt Macy if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \
46eda14cbcSMatt Macy (len) = (uint32_t)*((ulong_t *)(m)->cm_param); \
47eda14cbcSMatt Macy else { \
48eda14cbcSMatt Macy ulong_t tmp_ulong; \
49da5137abSMartin Matuska memcpy(&tmp_ulong, (m)->cm_param, sizeof (ulong_t)); \
50eda14cbcSMatt Macy (len) = (uint32_t)tmp_ulong; \
51eda14cbcSMatt Macy } \
52eda14cbcSMatt Macy }
53eda14cbcSMatt Macy
54eda14cbcSMatt Macy #define PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) { \
55eda14cbcSMatt Macy SHA2Init(mech, ctx); \
56eda14cbcSMatt Macy SHA2Update(ctx, key, len); \
57eda14cbcSMatt Macy SHA2Final(digest, ctx); \
58eda14cbcSMatt Macy }
59eda14cbcSMatt Macy
60eda14cbcSMatt Macy /*
61eda14cbcSMatt Macy * Mechanism info structure passed to KCF during registration.
62eda14cbcSMatt Macy */
63e92ffd9bSMartin Matuska static const crypto_mech_info_t sha2_mech_info_tab[] = {
64eda14cbcSMatt Macy /* SHA512-HMAC */
65eda14cbcSMatt Macy {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE,
66c03c5b1cSMartin Matuska CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
67eda14cbcSMatt Macy };
68eda14cbcSMatt Macy
69eda14cbcSMatt Macy static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
70c03c5b1cSMartin Matuska crypto_spi_ctx_template_t);
71c03c5b1cSMartin Matuska static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *);
72c03c5b1cSMartin Matuska static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *);
73c03c5b1cSMartin Matuska static int sha2_mac_atomic(crypto_mechanism_t *, crypto_key_t *,
74c03c5b1cSMartin Matuska crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
75c03c5b1cSMartin Matuska static int sha2_mac_verify_atomic(crypto_mechanism_t *, crypto_key_t *,
76c03c5b1cSMartin Matuska crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
77eda14cbcSMatt Macy
78e92ffd9bSMartin Matuska static const crypto_mac_ops_t sha2_mac_ops = {
79eda14cbcSMatt Macy .mac_init = sha2_mac_init,
80eda14cbcSMatt Macy .mac = NULL,
81eda14cbcSMatt Macy .mac_update = sha2_mac_update,
82eda14cbcSMatt Macy .mac_final = sha2_mac_final,
83eda14cbcSMatt Macy .mac_atomic = sha2_mac_atomic,
84eda14cbcSMatt Macy .mac_verify_atomic = sha2_mac_verify_atomic
85eda14cbcSMatt Macy };
86eda14cbcSMatt Macy
87c03c5b1cSMartin Matuska static int sha2_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
88c03c5b1cSMartin Matuska crypto_spi_ctx_template_t *, size_t *);
89eda14cbcSMatt Macy static int sha2_free_context(crypto_ctx_t *);
90eda14cbcSMatt Macy
91e92ffd9bSMartin Matuska static const crypto_ctx_ops_t sha2_ctx_ops = {
92eda14cbcSMatt Macy .create_ctx_template = sha2_create_ctx_template,
93eda14cbcSMatt Macy .free_context = sha2_free_context
94eda14cbcSMatt Macy };
95eda14cbcSMatt Macy
96c03c5b1cSMartin Matuska static const crypto_ops_t sha2_crypto_ops = {
97eda14cbcSMatt Macy NULL,
98eda14cbcSMatt Macy &sha2_mac_ops,
99c03c5b1cSMartin Matuska &sha2_ctx_ops,
100c03c5b1cSMartin Matuska };
101eda14cbcSMatt Macy
102c03c5b1cSMartin Matuska static const crypto_provider_info_t sha2_prov_info = {
103eda14cbcSMatt Macy "SHA2 Software Provider",
104eda14cbcSMatt Macy &sha2_crypto_ops,
105eda14cbcSMatt Macy sizeof (sha2_mech_info_tab) / sizeof (crypto_mech_info_t),
106eda14cbcSMatt Macy sha2_mech_info_tab
107c03c5b1cSMartin Matuska };
108eda14cbcSMatt Macy
109eda14cbcSMatt Macy static crypto_kcf_provider_handle_t sha2_prov_handle = 0;
110eda14cbcSMatt Macy
111eda14cbcSMatt Macy int
sha2_mod_init(void)112eda14cbcSMatt Macy sha2_mod_init(void)
113eda14cbcSMatt Macy {
114eda14cbcSMatt Macy int ret;
115eda14cbcSMatt Macy
116eda14cbcSMatt Macy /*
117eda14cbcSMatt Macy * Register with KCF. If the registration fails, log an
118eda14cbcSMatt Macy * error but do not uninstall the module, since the functionality
119eda14cbcSMatt Macy * provided by misc/sha2 should still be available.
120eda14cbcSMatt Macy */
121eda14cbcSMatt Macy if ((ret = crypto_register_provider(&sha2_prov_info,
122eda14cbcSMatt Macy &sha2_prov_handle)) != CRYPTO_SUCCESS)
123eda14cbcSMatt Macy cmn_err(CE_WARN, "sha2 _init: "
124eda14cbcSMatt Macy "crypto_register_provider() failed (0x%x)", ret);
125eda14cbcSMatt Macy
126eda14cbcSMatt Macy return (0);
127eda14cbcSMatt Macy }
128eda14cbcSMatt Macy
129eda14cbcSMatt Macy int
sha2_mod_fini(void)130eda14cbcSMatt Macy sha2_mod_fini(void)
131eda14cbcSMatt Macy {
132e92ffd9bSMartin Matuska int ret = 0;
133eda14cbcSMatt Macy
134eda14cbcSMatt Macy if (sha2_prov_handle != 0) {
135eda14cbcSMatt Macy if ((ret = crypto_unregister_provider(sha2_prov_handle)) !=
136eda14cbcSMatt Macy CRYPTO_SUCCESS) {
137eda14cbcSMatt Macy cmn_err(CE_WARN,
138eda14cbcSMatt Macy "sha2 _fini: crypto_unregister_provider() "
139eda14cbcSMatt Macy "failed (0x%x)", ret);
140eda14cbcSMatt Macy return (EBUSY);
141eda14cbcSMatt Macy }
142eda14cbcSMatt Macy sha2_prov_handle = 0;
143eda14cbcSMatt Macy }
144eda14cbcSMatt Macy
145e92ffd9bSMartin Matuska return (ret);
146eda14cbcSMatt Macy }
147eda14cbcSMatt Macy
148eda14cbcSMatt Macy /*
149eda14cbcSMatt Macy * Helper SHA2 digest update function for uio data.
150eda14cbcSMatt Macy */
151eda14cbcSMatt Macy static int
sha2_digest_update_uio(SHA2_CTX * sha2_ctx,crypto_data_t * data)152eda14cbcSMatt Macy sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data)
153eda14cbcSMatt Macy {
154eda14cbcSMatt Macy off_t offset = data->cd_offset;
155eda14cbcSMatt Macy size_t length = data->cd_length;
156eda14cbcSMatt Macy uint_t vec_idx = 0;
157eda14cbcSMatt Macy size_t cur_len;
158eda14cbcSMatt Macy
159eda14cbcSMatt Macy /* we support only kernel buffer */
160184c1b94SMartin Matuska if (zfs_uio_segflg(data->cd_uio) != UIO_SYSSPACE)
161eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD);
162eda14cbcSMatt Macy
163eda14cbcSMatt Macy /*
164eda14cbcSMatt Macy * Jump to the first iovec containing data to be
165eda14cbcSMatt Macy * digested.
166eda14cbcSMatt Macy */
167184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(data->cd_uio, offset, &vec_idx);
168184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(data->cd_uio)) {
169eda14cbcSMatt Macy /*
170eda14cbcSMatt Macy * The caller specified an offset that is larger than the
171eda14cbcSMatt Macy * total size of the buffers it provided.
172eda14cbcSMatt Macy */
173eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE);
174eda14cbcSMatt Macy }
175eda14cbcSMatt Macy
176eda14cbcSMatt Macy /*
177eda14cbcSMatt Macy * Now do the digesting on the iovecs.
178eda14cbcSMatt Macy */
179184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(data->cd_uio) && length > 0) {
180184c1b94SMartin Matuska cur_len = MIN(zfs_uio_iovlen(data->cd_uio, vec_idx) -
181eda14cbcSMatt Macy offset, length);
182eda14cbcSMatt Macy
183184c1b94SMartin Matuska SHA2Update(sha2_ctx, (uint8_t *)zfs_uio_iovbase(data->cd_uio,
184eda14cbcSMatt Macy vec_idx) + offset, cur_len);
185eda14cbcSMatt Macy length -= cur_len;
186eda14cbcSMatt Macy vec_idx++;
187eda14cbcSMatt Macy offset = 0;
188eda14cbcSMatt Macy }
189eda14cbcSMatt Macy
190184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(data->cd_uio) && length > 0) {
191eda14cbcSMatt Macy /*
192eda14cbcSMatt Macy * The end of the specified iovec's was reached but
193eda14cbcSMatt Macy * the length requested could not be processed, i.e.
194eda14cbcSMatt Macy * The caller requested to digest more data than it provided.
195eda14cbcSMatt Macy */
196eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE);
197eda14cbcSMatt Macy }
198eda14cbcSMatt Macy
199eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
200eda14cbcSMatt Macy }
201eda14cbcSMatt Macy
202eda14cbcSMatt Macy /*
203eda14cbcSMatt Macy * Helper SHA2 digest final function for uio data.
204eda14cbcSMatt Macy * digest_len is the length of the desired digest. If digest_len
205eda14cbcSMatt Macy * is smaller than the default SHA2 digest length, the caller
206eda14cbcSMatt Macy * must pass a scratch buffer, digest_scratch, which must
207eda14cbcSMatt Macy * be at least the algorithm's digest length bytes.
208eda14cbcSMatt Macy */
209eda14cbcSMatt Macy static int
sha2_digest_final_uio(SHA2_CTX * sha2_ctx,crypto_data_t * digest,ulong_t digest_len,uchar_t * digest_scratch)210eda14cbcSMatt Macy sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest,
211eda14cbcSMatt Macy ulong_t digest_len, uchar_t *digest_scratch)
212eda14cbcSMatt Macy {
213eda14cbcSMatt Macy off_t offset = digest->cd_offset;
214eda14cbcSMatt Macy uint_t vec_idx = 0;
215eda14cbcSMatt Macy
216eda14cbcSMatt Macy /* we support only kernel buffer */
217184c1b94SMartin Matuska if (zfs_uio_segflg(digest->cd_uio) != UIO_SYSSPACE)
218eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD);
219eda14cbcSMatt Macy
220eda14cbcSMatt Macy /*
221eda14cbcSMatt Macy * Jump to the first iovec containing ptr to the digest to
222eda14cbcSMatt Macy * be returned.
223eda14cbcSMatt Macy */
224184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(digest->cd_uio, offset, &vec_idx);
225184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(digest->cd_uio)) {
226eda14cbcSMatt Macy /*
227eda14cbcSMatt Macy * The caller specified an offset that is
228eda14cbcSMatt Macy * larger than the total size of the buffers
229eda14cbcSMatt Macy * it provided.
230eda14cbcSMatt Macy */
231eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE);
232eda14cbcSMatt Macy }
233eda14cbcSMatt Macy
234eda14cbcSMatt Macy if (offset + digest_len <=
235184c1b94SMartin Matuska zfs_uio_iovlen(digest->cd_uio, vec_idx)) {
236eda14cbcSMatt Macy /*
237eda14cbcSMatt Macy * The computed SHA2 digest will fit in the current
238eda14cbcSMatt Macy * iovec.
239eda14cbcSMatt Macy */
24075e1fea6SMartin Matuska ASSERT3U(sha2_ctx->algotype, ==, SHA512_HMAC_MECH_INFO_TYPE);
24175e1fea6SMartin Matuska if (digest_len != SHA512_DIGEST_LENGTH) {
242eda14cbcSMatt Macy /*
243eda14cbcSMatt Macy * The caller requested a short digest. Digest
244eda14cbcSMatt Macy * into a scratch buffer and return to
245eda14cbcSMatt Macy * the user only what was requested.
246eda14cbcSMatt Macy */
247eda14cbcSMatt Macy SHA2Final(digest_scratch, sha2_ctx);
248eda14cbcSMatt Macy
249da5137abSMartin Matuska memcpy((uchar_t *)
250184c1b94SMartin Matuska zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset,
251da5137abSMartin Matuska digest_scratch, digest_len);
252eda14cbcSMatt Macy } else {
253184c1b94SMartin Matuska SHA2Final((uchar_t *)zfs_uio_iovbase(digest->
254eda14cbcSMatt Macy cd_uio, vec_idx) + offset,
255eda14cbcSMatt Macy sha2_ctx);
256eda14cbcSMatt Macy
257eda14cbcSMatt Macy }
258eda14cbcSMatt Macy } else {
259eda14cbcSMatt Macy /*
260eda14cbcSMatt Macy * The computed digest will be crossing one or more iovec's.
261eda14cbcSMatt Macy * This is bad performance-wise but we need to support it.
262eda14cbcSMatt Macy * Allocate a small scratch buffer on the stack and
263eda14cbcSMatt Macy * copy it piece meal to the specified digest iovec's.
264eda14cbcSMatt Macy */
265eda14cbcSMatt Macy uchar_t digest_tmp[SHA512_DIGEST_LENGTH];
266eda14cbcSMatt Macy off_t scratch_offset = 0;
267eda14cbcSMatt Macy size_t length = digest_len;
268eda14cbcSMatt Macy size_t cur_len;
269eda14cbcSMatt Macy
270eda14cbcSMatt Macy SHA2Final(digest_tmp, sha2_ctx);
271eda14cbcSMatt Macy
272184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(digest->cd_uio) && length > 0) {
273eda14cbcSMatt Macy cur_len =
274184c1b94SMartin Matuska MIN(zfs_uio_iovlen(digest->cd_uio, vec_idx) -
275eda14cbcSMatt Macy offset, length);
276da5137abSMartin Matuska memcpy(
277184c1b94SMartin Matuska zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset,
278da5137abSMartin Matuska digest_tmp + scratch_offset,
279eda14cbcSMatt Macy cur_len);
280eda14cbcSMatt Macy
281eda14cbcSMatt Macy length -= cur_len;
282eda14cbcSMatt Macy vec_idx++;
283eda14cbcSMatt Macy scratch_offset += cur_len;
284eda14cbcSMatt Macy offset = 0;
285eda14cbcSMatt Macy }
286eda14cbcSMatt Macy
287184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(digest->cd_uio) && length > 0) {
288eda14cbcSMatt Macy /*
289eda14cbcSMatt Macy * The end of the specified iovec's was reached but
290eda14cbcSMatt Macy * the length requested could not be processed, i.e.
291eda14cbcSMatt Macy * The caller requested to digest more data than it
292eda14cbcSMatt Macy * provided.
293eda14cbcSMatt Macy */
294eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE);
295eda14cbcSMatt Macy }
296eda14cbcSMatt Macy }
297eda14cbcSMatt Macy
298eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
299eda14cbcSMatt Macy }
300eda14cbcSMatt Macy
301eda14cbcSMatt Macy /*
302eda14cbcSMatt Macy * KCF software provider mac entry points.
303eda14cbcSMatt Macy *
304eda14cbcSMatt Macy * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text))
305eda14cbcSMatt Macy *
306eda14cbcSMatt Macy * Init:
307eda14cbcSMatt Macy * The initialization routine initializes what we denote
308eda14cbcSMatt Macy * as the inner and outer contexts by doing
309eda14cbcSMatt Macy * - for inner context: SHA2(key XOR ipad)
310eda14cbcSMatt Macy * - for outer context: SHA2(key XOR opad)
311eda14cbcSMatt Macy *
312eda14cbcSMatt Macy * Update:
313eda14cbcSMatt Macy * Each subsequent SHA2 HMAC update will result in an
314eda14cbcSMatt Macy * update of the inner context with the specified data.
315eda14cbcSMatt Macy *
316eda14cbcSMatt Macy * Final:
317eda14cbcSMatt Macy * The SHA2 HMAC final will do a SHA2 final operation on the
318eda14cbcSMatt Macy * inner context, and the resulting digest will be used
319eda14cbcSMatt Macy * as the data for an update on the outer context. Last
320eda14cbcSMatt Macy * but not least, a SHA2 final on the outer context will
321eda14cbcSMatt Macy * be performed to obtain the SHA2 HMAC digest to return
322eda14cbcSMatt Macy * to the user.
323eda14cbcSMatt Macy */
324eda14cbcSMatt Macy
325eda14cbcSMatt Macy /*
326eda14cbcSMatt Macy * Initialize a SHA2-HMAC context.
327eda14cbcSMatt Macy */
328eda14cbcSMatt Macy static void
sha2_mac_init_ctx(sha2_hmac_ctx_t * ctx,void * keyval,uint_t length_in_bytes)329eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
330eda14cbcSMatt Macy {
331da5137abSMartin Matuska uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)] = {0};
332da5137abSMartin Matuska uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)] = {0};
333eda14cbcSMatt Macy int i, block_size, blocks_per_int64;
334eda14cbcSMatt Macy
335eda14cbcSMatt Macy /* Determine the block size */
33675e1fea6SMartin Matuska ASSERT3U(ctx->hc_mech_type, ==, SHA512_HMAC_MECH_INFO_TYPE);
337eda14cbcSMatt Macy block_size = SHA512_HMAC_BLOCK_SIZE;
338eda14cbcSMatt Macy blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t);
339eda14cbcSMatt Macy
340da5137abSMartin Matuska (void) memset(ipad, 0, block_size);
341da5137abSMartin Matuska (void) memset(opad, 0, block_size);
342c03c5b1cSMartin Matuska
343c03c5b1cSMartin Matuska if (keyval != NULL) {
344da5137abSMartin Matuska (void) memcpy(ipad, keyval, length_in_bytes);
345da5137abSMartin Matuska (void) memcpy(opad, keyval, length_in_bytes);
346c03c5b1cSMartin Matuska } else {
347c03c5b1cSMartin Matuska ASSERT0(length_in_bytes);
348c03c5b1cSMartin Matuska }
349eda14cbcSMatt Macy
350eda14cbcSMatt Macy /* XOR key with ipad (0x36) and opad (0x5c) */
351eda14cbcSMatt Macy for (i = 0; i < blocks_per_int64; i ++) {
352eda14cbcSMatt Macy ipad[i] ^= 0x3636363636363636;
353eda14cbcSMatt Macy opad[i] ^= 0x5c5c5c5c5c5c5c5c;
354eda14cbcSMatt Macy }
355eda14cbcSMatt Macy
356eda14cbcSMatt Macy /* perform SHA2 on ipad */
357eda14cbcSMatt Macy SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext);
358eda14cbcSMatt Macy SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size);
359eda14cbcSMatt Macy
360eda14cbcSMatt Macy /* perform SHA2 on opad */
361eda14cbcSMatt Macy SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext);
362eda14cbcSMatt Macy SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size);
363eda14cbcSMatt Macy }
364eda14cbcSMatt Macy
365eda14cbcSMatt Macy /*
366eda14cbcSMatt Macy */
367eda14cbcSMatt Macy static int
sha2_mac_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template)368eda14cbcSMatt Macy sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
369c03c5b1cSMartin Matuska crypto_key_t *key, crypto_spi_ctx_template_t ctx_template)
370eda14cbcSMatt Macy {
371eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS;
372eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
373eda14cbcSMatt Macy uint_t sha_digest_len, sha_hmac_block_size;
374eda14cbcSMatt Macy
375eda14cbcSMatt Macy /*
376eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the
377eda14cbcSMatt Macy * mechanism
378eda14cbcSMatt Macy */
379eda14cbcSMatt Macy switch (mechanism->cm_type) {
380eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE:
381eda14cbcSMatt Macy sha_digest_len = SHA512_DIGEST_LENGTH;
382eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
383eda14cbcSMatt Macy break;
384eda14cbcSMatt Macy default:
385eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID);
386eda14cbcSMatt Macy }
387eda14cbcSMatt Macy
388c03c5b1cSMartin Matuska ctx->cc_provider_private =
389c03c5b1cSMartin Matuska kmem_alloc(sizeof (sha2_hmac_ctx_t), KM_SLEEP);
390eda14cbcSMatt Macy if (ctx->cc_provider_private == NULL)
391eda14cbcSMatt Macy return (CRYPTO_HOST_MEMORY);
392eda14cbcSMatt Macy
393eda14cbcSMatt Macy PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
394eda14cbcSMatt Macy if (ctx_template != NULL) {
395eda14cbcSMatt Macy /* reuse context template */
396da5137abSMartin Matuska memcpy(PROV_SHA2_HMAC_CTX(ctx), ctx_template,
397eda14cbcSMatt Macy sizeof (sha2_hmac_ctx_t));
398eda14cbcSMatt Macy } else {
399eda14cbcSMatt Macy /* no context template, compute context */
400eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) {
401eda14cbcSMatt Macy uchar_t digested_key[SHA512_DIGEST_LENGTH];
402eda14cbcSMatt Macy sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
403eda14cbcSMatt Macy
404eda14cbcSMatt Macy /*
405eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key.
406eda14cbcSMatt Macy * The inner context is used since it hasn't been
407eda14cbcSMatt Macy * initialized yet.
408eda14cbcSMatt Macy */
409eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
410eda14cbcSMatt Macy &hmac_ctx->hc_icontext,
411eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digested_key);
412eda14cbcSMatt Macy sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
413eda14cbcSMatt Macy digested_key, sha_digest_len);
414eda14cbcSMatt Macy } else {
415eda14cbcSMatt Macy sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
416eda14cbcSMatt Macy key->ck_data, keylen_in_bytes);
417eda14cbcSMatt Macy }
418eda14cbcSMatt Macy }
419eda14cbcSMatt Macy
420eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS) {
421da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, sizeof (sha2_hmac_ctx_t));
422eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
423eda14cbcSMatt Macy ctx->cc_provider_private = NULL;
424eda14cbcSMatt Macy }
425eda14cbcSMatt Macy
426eda14cbcSMatt Macy return (ret);
427eda14cbcSMatt Macy }
428eda14cbcSMatt Macy
429eda14cbcSMatt Macy static int
sha2_mac_update(crypto_ctx_t * ctx,crypto_data_t * data)430c03c5b1cSMartin Matuska sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data)
431eda14cbcSMatt Macy {
432eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS;
433eda14cbcSMatt Macy
434eda14cbcSMatt Macy ASSERT(ctx->cc_provider_private != NULL);
435eda14cbcSMatt Macy
436eda14cbcSMatt Macy /*
437eda14cbcSMatt Macy * Do a SHA2 update of the inner context using the specified
438eda14cbcSMatt Macy * data.
439eda14cbcSMatt Macy */
440eda14cbcSMatt Macy switch (data->cd_format) {
441eda14cbcSMatt Macy case CRYPTO_DATA_RAW:
442eda14cbcSMatt Macy SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext,
443eda14cbcSMatt Macy (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
444eda14cbcSMatt Macy data->cd_length);
445eda14cbcSMatt Macy break;
446eda14cbcSMatt Macy case CRYPTO_DATA_UIO:
447eda14cbcSMatt Macy ret = sha2_digest_update_uio(
448eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data);
449eda14cbcSMatt Macy break;
450eda14cbcSMatt Macy default:
451eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD;
452eda14cbcSMatt Macy }
453eda14cbcSMatt Macy
454eda14cbcSMatt Macy return (ret);
455eda14cbcSMatt Macy }
456eda14cbcSMatt Macy
457eda14cbcSMatt Macy static int
sha2_mac_final(crypto_ctx_t * ctx,crypto_data_t * mac)458c03c5b1cSMartin Matuska sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac)
459eda14cbcSMatt Macy {
460eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS;
461eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH];
462eda14cbcSMatt Macy uint32_t digest_len, sha_digest_len;
463eda14cbcSMatt Macy
464eda14cbcSMatt Macy ASSERT(ctx->cc_provider_private != NULL);
465eda14cbcSMatt Macy
466eda14cbcSMatt Macy /* Set the digest lengths to values appropriate to the mechanism */
467eda14cbcSMatt Macy switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) {
468eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE:
469eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
470eda14cbcSMatt Macy break;
471eda14cbcSMatt Macy default:
472eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD);
473eda14cbcSMatt Macy }
474eda14cbcSMatt Macy
475eda14cbcSMatt Macy /*
476eda14cbcSMatt Macy * We need to just return the length needed to store the output.
477eda14cbcSMatt Macy * We should not destroy the context for the following cases.
478eda14cbcSMatt Macy */
479eda14cbcSMatt Macy if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
480eda14cbcSMatt Macy mac->cd_length = digest_len;
481eda14cbcSMatt Macy return (CRYPTO_BUFFER_TOO_SMALL);
482eda14cbcSMatt Macy }
483eda14cbcSMatt Macy
484eda14cbcSMatt Macy /*
485eda14cbcSMatt Macy * Do a SHA2 final on the inner context.
486eda14cbcSMatt Macy */
487eda14cbcSMatt Macy SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext);
488eda14cbcSMatt Macy
489eda14cbcSMatt Macy /*
490eda14cbcSMatt Macy * Do a SHA2 update on the outer context, feeding the inner
491eda14cbcSMatt Macy * digest as data.
492eda14cbcSMatt Macy */
493eda14cbcSMatt Macy SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest,
494eda14cbcSMatt Macy sha_digest_len);
495eda14cbcSMatt Macy
496eda14cbcSMatt Macy /*
497eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computing
498eda14cbcSMatt Macy * digest in the users buffer.
499eda14cbcSMatt Macy */
500eda14cbcSMatt Macy switch (mac->cd_format) {
501eda14cbcSMatt Macy case CRYPTO_DATA_RAW:
502eda14cbcSMatt Macy if (digest_len != sha_digest_len) {
503eda14cbcSMatt Macy /*
504eda14cbcSMatt Macy * The caller requested a short digest. Digest
505eda14cbcSMatt Macy * into a scratch buffer and return to
506eda14cbcSMatt Macy * the user only what was requested.
507eda14cbcSMatt Macy */
508eda14cbcSMatt Macy SHA2Final(digest,
509eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
510da5137abSMartin Matuska memcpy((unsigned char *)mac->cd_raw.iov_base +
511da5137abSMartin Matuska mac->cd_offset, digest, digest_len);
512eda14cbcSMatt Macy } else {
513eda14cbcSMatt Macy SHA2Final((unsigned char *)mac->cd_raw.iov_base +
514eda14cbcSMatt Macy mac->cd_offset,
515eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
516eda14cbcSMatt Macy }
517eda14cbcSMatt Macy break;
518eda14cbcSMatt Macy case CRYPTO_DATA_UIO:
519eda14cbcSMatt Macy ret = sha2_digest_final_uio(
520eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac,
521eda14cbcSMatt Macy digest_len, digest);
522eda14cbcSMatt Macy break;
523eda14cbcSMatt Macy default:
524eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD;
525eda14cbcSMatt Macy }
526eda14cbcSMatt Macy
527eda14cbcSMatt Macy if (ret == CRYPTO_SUCCESS)
528eda14cbcSMatt Macy mac->cd_length = digest_len;
529eda14cbcSMatt Macy else
530eda14cbcSMatt Macy mac->cd_length = 0;
531eda14cbcSMatt Macy
532da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, sizeof (sha2_hmac_ctx_t));
533eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
534eda14cbcSMatt Macy ctx->cc_provider_private = NULL;
535eda14cbcSMatt Macy
536eda14cbcSMatt Macy return (ret);
537eda14cbcSMatt Macy }
538eda14cbcSMatt Macy
539eda14cbcSMatt Macy #define SHA2_MAC_UPDATE(data, ctx, ret) { \
540eda14cbcSMatt Macy switch (data->cd_format) { \
541eda14cbcSMatt Macy case CRYPTO_DATA_RAW: \
542eda14cbcSMatt Macy SHA2Update(&(ctx).hc_icontext, \
543eda14cbcSMatt Macy (uint8_t *)data->cd_raw.iov_base + \
544eda14cbcSMatt Macy data->cd_offset, data->cd_length); \
545eda14cbcSMatt Macy break; \
546eda14cbcSMatt Macy case CRYPTO_DATA_UIO: \
547eda14cbcSMatt Macy ret = sha2_digest_update_uio(&(ctx).hc_icontext, data); \
548eda14cbcSMatt Macy break; \
549eda14cbcSMatt Macy default: \
550eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; \
551eda14cbcSMatt Macy } \
552eda14cbcSMatt Macy }
553eda14cbcSMatt Macy
554eda14cbcSMatt Macy static int
sha2_mac_atomic(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t ctx_template)555c03c5b1cSMartin Matuska sha2_mac_atomic(crypto_mechanism_t *mechanism,
556eda14cbcSMatt Macy crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
557c03c5b1cSMartin Matuska crypto_spi_ctx_template_t ctx_template)
558eda14cbcSMatt Macy {
559eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS;
560eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH];
561eda14cbcSMatt Macy sha2_hmac_ctx_t sha2_hmac_ctx;
562eda14cbcSMatt Macy uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
563eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
564eda14cbcSMatt Macy
565eda14cbcSMatt Macy /*
566eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the
567eda14cbcSMatt Macy * mechanism
568eda14cbcSMatt Macy */
569eda14cbcSMatt Macy switch (mechanism->cm_type) {
570eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE:
571eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
572eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
573eda14cbcSMatt Macy break;
574eda14cbcSMatt Macy default:
575eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID);
576eda14cbcSMatt Macy }
577eda14cbcSMatt Macy
578eda14cbcSMatt Macy if (ctx_template != NULL) {
579eda14cbcSMatt Macy /* reuse context template */
580da5137abSMartin Matuska memcpy(&sha2_hmac_ctx, ctx_template, sizeof (sha2_hmac_ctx_t));
581eda14cbcSMatt Macy } else {
582eda14cbcSMatt Macy sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
583eda14cbcSMatt Macy /* no context template, initialize context */
584eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) {
585eda14cbcSMatt Macy /*
586eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key.
587eda14cbcSMatt Macy * The inner context is used since it hasn't been
588eda14cbcSMatt Macy * initialized yet.
589eda14cbcSMatt Macy */
590eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
591eda14cbcSMatt Macy &sha2_hmac_ctx.hc_icontext,
592eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digest);
593eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
594eda14cbcSMatt Macy sha_digest_len);
595eda14cbcSMatt Macy } else {
596eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
597eda14cbcSMatt Macy keylen_in_bytes);
598eda14cbcSMatt Macy }
599eda14cbcSMatt Macy }
600eda14cbcSMatt Macy
601eda14cbcSMatt Macy /* do a SHA2 update of the inner context using the specified data */
602eda14cbcSMatt Macy SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
603eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS)
604eda14cbcSMatt Macy /* the update failed, free context and bail */
605eda14cbcSMatt Macy goto bail;
606eda14cbcSMatt Macy
607eda14cbcSMatt Macy /*
608eda14cbcSMatt Macy * Do a SHA2 final on the inner context.
609eda14cbcSMatt Macy */
610eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
611eda14cbcSMatt Macy
612eda14cbcSMatt Macy /*
613eda14cbcSMatt Macy * Do an SHA2 update on the outer context, feeding the inner
614eda14cbcSMatt Macy * digest as data.
615eda14cbcSMatt Macy */
61675e1fea6SMartin Matuska ASSERT3U(mechanism->cm_type, ==, SHA512_HMAC_MECH_INFO_TYPE);
617eda14cbcSMatt Macy SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
618eda14cbcSMatt Macy
619eda14cbcSMatt Macy /*
620eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computed
621eda14cbcSMatt Macy * digest in the users buffer.
622eda14cbcSMatt Macy */
623eda14cbcSMatt Macy switch (mac->cd_format) {
624eda14cbcSMatt Macy case CRYPTO_DATA_RAW:
625eda14cbcSMatt Macy if (digest_len != sha_digest_len) {
626eda14cbcSMatt Macy /*
627eda14cbcSMatt Macy * The caller requested a short digest. Digest
628eda14cbcSMatt Macy * into a scratch buffer and return to
629eda14cbcSMatt Macy * the user only what was requested.
630eda14cbcSMatt Macy */
631eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
632da5137abSMartin Matuska memcpy((unsigned char *)mac->cd_raw.iov_base +
633da5137abSMartin Matuska mac->cd_offset, digest, digest_len);
634eda14cbcSMatt Macy } else {
635eda14cbcSMatt Macy SHA2Final((unsigned char *)mac->cd_raw.iov_base +
636eda14cbcSMatt Macy mac->cd_offset, &sha2_hmac_ctx.hc_ocontext);
637eda14cbcSMatt Macy }
638eda14cbcSMatt Macy break;
639eda14cbcSMatt Macy case CRYPTO_DATA_UIO:
640eda14cbcSMatt Macy ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac,
641eda14cbcSMatt Macy digest_len, digest);
642eda14cbcSMatt Macy break;
643eda14cbcSMatt Macy default:
644eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD;
645eda14cbcSMatt Macy }
646eda14cbcSMatt Macy
647eda14cbcSMatt Macy if (ret == CRYPTO_SUCCESS) {
648eda14cbcSMatt Macy mac->cd_length = digest_len;
649eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
650eda14cbcSMatt Macy }
651eda14cbcSMatt Macy bail:
652da5137abSMartin Matuska memset(&sha2_hmac_ctx, 0, sizeof (sha2_hmac_ctx_t));
653eda14cbcSMatt Macy mac->cd_length = 0;
654eda14cbcSMatt Macy return (ret);
655eda14cbcSMatt Macy }
656eda14cbcSMatt Macy
657eda14cbcSMatt Macy static int
sha2_mac_verify_atomic(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t ctx_template)658c03c5b1cSMartin Matuska sha2_mac_verify_atomic(crypto_mechanism_t *mechanism,
659eda14cbcSMatt Macy crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
660c03c5b1cSMartin Matuska crypto_spi_ctx_template_t ctx_template)
661eda14cbcSMatt Macy {
662eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS;
663eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH];
664eda14cbcSMatt Macy sha2_hmac_ctx_t sha2_hmac_ctx;
665eda14cbcSMatt Macy uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
666eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
667eda14cbcSMatt Macy
668eda14cbcSMatt Macy /*
669eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the
670eda14cbcSMatt Macy * mechanism
671eda14cbcSMatt Macy */
672eda14cbcSMatt Macy switch (mechanism->cm_type) {
673eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE:
674eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
675eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
676eda14cbcSMatt Macy break;
677eda14cbcSMatt Macy default:
678eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID);
679eda14cbcSMatt Macy }
680eda14cbcSMatt Macy
681eda14cbcSMatt Macy if (ctx_template != NULL) {
682eda14cbcSMatt Macy /* reuse context template */
683da5137abSMartin Matuska memcpy(&sha2_hmac_ctx, ctx_template, sizeof (sha2_hmac_ctx_t));
684eda14cbcSMatt Macy } else {
685eda14cbcSMatt Macy sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
686eda14cbcSMatt Macy /* no context template, initialize context */
687eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) {
688eda14cbcSMatt Macy /*
689eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key.
690eda14cbcSMatt Macy * The inner context is used since it hasn't been
691eda14cbcSMatt Macy * initialized yet.
692eda14cbcSMatt Macy */
693eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
694eda14cbcSMatt Macy &sha2_hmac_ctx.hc_icontext,
695eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digest);
696eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
697eda14cbcSMatt Macy sha_digest_len);
698eda14cbcSMatt Macy } else {
699eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
700eda14cbcSMatt Macy keylen_in_bytes);
701eda14cbcSMatt Macy }
702eda14cbcSMatt Macy }
703eda14cbcSMatt Macy
704eda14cbcSMatt Macy if (mac->cd_length != digest_len) {
705eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC;
706eda14cbcSMatt Macy goto bail;
707eda14cbcSMatt Macy }
708eda14cbcSMatt Macy
709eda14cbcSMatt Macy /* do a SHA2 update of the inner context using the specified data */
710eda14cbcSMatt Macy SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
711eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS)
712eda14cbcSMatt Macy /* the update failed, free context and bail */
713eda14cbcSMatt Macy goto bail;
714eda14cbcSMatt Macy
715eda14cbcSMatt Macy /* do a SHA2 final on the inner context */
716eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
717eda14cbcSMatt Macy
718eda14cbcSMatt Macy /*
719eda14cbcSMatt Macy * Do an SHA2 update on the outer context, feeding the inner
720eda14cbcSMatt Macy * digest as data.
721eda14cbcSMatt Macy */
72275e1fea6SMartin Matuska ASSERT3U(mechanism->cm_type, ==, SHA512_HMAC_MECH_INFO_TYPE);
723eda14cbcSMatt Macy SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
724eda14cbcSMatt Macy
725eda14cbcSMatt Macy /*
726eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computed
727eda14cbcSMatt Macy * digest in the users buffer.
728eda14cbcSMatt Macy */
729eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
730eda14cbcSMatt Macy
731eda14cbcSMatt Macy /*
732eda14cbcSMatt Macy * Compare the computed digest against the expected digest passed
733eda14cbcSMatt Macy * as argument.
734eda14cbcSMatt Macy */
735eda14cbcSMatt Macy
736eda14cbcSMatt Macy switch (mac->cd_format) {
737eda14cbcSMatt Macy
738eda14cbcSMatt Macy case CRYPTO_DATA_RAW:
739da5137abSMartin Matuska if (memcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
740eda14cbcSMatt Macy mac->cd_offset, digest_len) != 0)
741eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC;
742eda14cbcSMatt Macy break;
743eda14cbcSMatt Macy
744eda14cbcSMatt Macy case CRYPTO_DATA_UIO: {
745eda14cbcSMatt Macy off_t offset = mac->cd_offset;
746eda14cbcSMatt Macy uint_t vec_idx = 0;
747eda14cbcSMatt Macy off_t scratch_offset = 0;
748eda14cbcSMatt Macy size_t length = digest_len;
749eda14cbcSMatt Macy size_t cur_len;
750eda14cbcSMatt Macy
751eda14cbcSMatt Macy /* we support only kernel buffer */
752184c1b94SMartin Matuska if (zfs_uio_segflg(mac->cd_uio) != UIO_SYSSPACE)
753eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD);
754eda14cbcSMatt Macy
755eda14cbcSMatt Macy /* jump to the first iovec containing the expected digest */
756184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(mac->cd_uio, offset, &vec_idx);
757184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(mac->cd_uio)) {
758eda14cbcSMatt Macy /*
759eda14cbcSMatt Macy * The caller specified an offset that is
760eda14cbcSMatt Macy * larger than the total size of the buffers
761eda14cbcSMatt Macy * it provided.
762eda14cbcSMatt Macy */
763eda14cbcSMatt Macy ret = CRYPTO_DATA_LEN_RANGE;
764eda14cbcSMatt Macy break;
765eda14cbcSMatt Macy }
766eda14cbcSMatt Macy
767eda14cbcSMatt Macy /* do the comparison of computed digest vs specified one */
768184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(mac->cd_uio) && length > 0) {
769184c1b94SMartin Matuska cur_len = MIN(zfs_uio_iovlen(mac->cd_uio, vec_idx) -
770eda14cbcSMatt Macy offset, length);
771eda14cbcSMatt Macy
772da5137abSMartin Matuska if (memcmp(digest + scratch_offset,
773184c1b94SMartin Matuska zfs_uio_iovbase(mac->cd_uio, vec_idx) + offset,
774eda14cbcSMatt Macy cur_len) != 0) {
775eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC;
776eda14cbcSMatt Macy break;
777eda14cbcSMatt Macy }
778eda14cbcSMatt Macy
779eda14cbcSMatt Macy length -= cur_len;
780eda14cbcSMatt Macy vec_idx++;
781eda14cbcSMatt Macy scratch_offset += cur_len;
782eda14cbcSMatt Macy offset = 0;
783eda14cbcSMatt Macy }
784eda14cbcSMatt Macy break;
785eda14cbcSMatt Macy }
786eda14cbcSMatt Macy
787eda14cbcSMatt Macy default:
788eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD;
789eda14cbcSMatt Macy }
790eda14cbcSMatt Macy
791eda14cbcSMatt Macy return (ret);
792eda14cbcSMatt Macy bail:
793da5137abSMartin Matuska memset(&sha2_hmac_ctx, 0, sizeof (sha2_hmac_ctx_t));
794eda14cbcSMatt Macy mac->cd_length = 0;
795eda14cbcSMatt Macy return (ret);
796eda14cbcSMatt Macy }
797eda14cbcSMatt Macy
798eda14cbcSMatt Macy /*
799eda14cbcSMatt Macy * KCF software provider context management entry points.
800eda14cbcSMatt Macy */
801eda14cbcSMatt Macy
802eda14cbcSMatt Macy static int
sha2_create_ctx_template(crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t * ctx_template,size_t * ctx_template_size)803c03c5b1cSMartin Matuska sha2_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
804c03c5b1cSMartin Matuska crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size)
805eda14cbcSMatt Macy {
806eda14cbcSMatt Macy sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl;
807eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
808eda14cbcSMatt Macy uint32_t sha_digest_len, sha_hmac_block_size;
809eda14cbcSMatt Macy
810eda14cbcSMatt Macy /*
811eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the
812eda14cbcSMatt Macy * mechanism
813eda14cbcSMatt Macy */
814eda14cbcSMatt Macy switch (mechanism->cm_type) {
815eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE:
816eda14cbcSMatt Macy sha_digest_len = SHA512_DIGEST_LENGTH;
817eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
818eda14cbcSMatt Macy break;
819eda14cbcSMatt Macy default:
820eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID);
821eda14cbcSMatt Macy }
822eda14cbcSMatt Macy
823eda14cbcSMatt Macy /*
824eda14cbcSMatt Macy * Allocate and initialize SHA2 context.
825eda14cbcSMatt Macy */
826c03c5b1cSMartin Matuska sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t), KM_SLEEP);
827eda14cbcSMatt Macy if (sha2_hmac_ctx_tmpl == NULL)
828eda14cbcSMatt Macy return (CRYPTO_HOST_MEMORY);
829eda14cbcSMatt Macy
830eda14cbcSMatt Macy sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
831eda14cbcSMatt Macy
832eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) {
833eda14cbcSMatt Macy uchar_t digested_key[SHA512_DIGEST_LENGTH];
834eda14cbcSMatt Macy
835eda14cbcSMatt Macy /*
836eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key.
837eda14cbcSMatt Macy * The inner context is used since it hasn't been
838eda14cbcSMatt Macy * initialized yet.
839eda14cbcSMatt Macy */
840eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
841eda14cbcSMatt Macy &sha2_hmac_ctx_tmpl->hc_icontext,
842eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digested_key);
843eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key,
844eda14cbcSMatt Macy sha_digest_len);
845eda14cbcSMatt Macy } else {
846eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data,
847eda14cbcSMatt Macy keylen_in_bytes);
848eda14cbcSMatt Macy }
849eda14cbcSMatt Macy
850eda14cbcSMatt Macy *ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl;
851eda14cbcSMatt Macy *ctx_template_size = sizeof (sha2_hmac_ctx_t);
852eda14cbcSMatt Macy
853eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
854eda14cbcSMatt Macy }
855eda14cbcSMatt Macy
856eda14cbcSMatt Macy static int
sha2_free_context(crypto_ctx_t * ctx)857eda14cbcSMatt Macy sha2_free_context(crypto_ctx_t *ctx)
858eda14cbcSMatt Macy {
859eda14cbcSMatt Macy uint_t ctx_len;
860eda14cbcSMatt Macy
861eda14cbcSMatt Macy if (ctx->cc_provider_private == NULL)
862eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
863eda14cbcSMatt Macy
86475e1fea6SMartin Matuska ASSERT3U(PROV_SHA2_CTX(ctx)->sc_mech_type, ==,
86575e1fea6SMartin Matuska SHA512_HMAC_MECH_INFO_TYPE);
866eda14cbcSMatt Macy ctx_len = sizeof (sha2_hmac_ctx_t);
867eda14cbcSMatt Macy
868da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, ctx_len);
869eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, ctx_len);
870eda14cbcSMatt Macy ctx->cc_provider_private = NULL;
871eda14cbcSMatt Macy
872eda14cbcSMatt Macy return (CRYPTO_SUCCESS);
873eda14cbcSMatt Macy }
874