1*4e065a9fSAlexander Stetsenko /*
2*4e065a9fSAlexander Stetsenko  * CDDL HEADER START
3*4e065a9fSAlexander Stetsenko  *
4*4e065a9fSAlexander Stetsenko  * The contents of this file are subject to the terms of the
5*4e065a9fSAlexander Stetsenko  * Common Development and Distribution License (the "License").
6*4e065a9fSAlexander Stetsenko  * You may not use this file except in compliance with the License.
7*4e065a9fSAlexander Stetsenko  *
8*4e065a9fSAlexander Stetsenko  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4e065a9fSAlexander Stetsenko  * or http://www.opensolaris.org/os/licensing.
10*4e065a9fSAlexander Stetsenko  * See the License for the specific language governing permissions
11*4e065a9fSAlexander Stetsenko  * and limitations under the License.
12*4e065a9fSAlexander Stetsenko  *
13*4e065a9fSAlexander Stetsenko  * When distributing Covered Code, include this CDDL HEADER in each
14*4e065a9fSAlexander Stetsenko  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4e065a9fSAlexander Stetsenko  * If applicable, add the following below this CDDL HEADER, with the
16*4e065a9fSAlexander Stetsenko  * fields enclosed by brackets "[]" replaced with your own identifying
17*4e065a9fSAlexander Stetsenko  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4e065a9fSAlexander Stetsenko  *
19*4e065a9fSAlexander Stetsenko  * CDDL HEADER END
20*4e065a9fSAlexander Stetsenko  */
21*4e065a9fSAlexander Stetsenko /*
22*4e065a9fSAlexander Stetsenko  * Copyright 2020 RackTop Systems, Inc.
23*4e065a9fSAlexander Stetsenko  */
24*4e065a9fSAlexander Stetsenko 
25*4e065a9fSAlexander Stetsenko #include <smbsrv/smb2_kproto.h>
26*4e065a9fSAlexander Stetsenko #include <smbsrv/smb2.h>
27*4e065a9fSAlexander Stetsenko #include <sys/crypto/api.h>
28*4e065a9fSAlexander Stetsenko #include <smbsrv/smb_kproto.h>
29*4e065a9fSAlexander Stetsenko #include <smbsrv/smb_kcrypt.h>
30*4e065a9fSAlexander Stetsenko 
31*4e065a9fSAlexander Stetsenko /*
32*4e065a9fSAlexander Stetsenko  * SMB 3.1.1 Preauth Integrity
33*4e065a9fSAlexander Stetsenko  */
34*4e065a9fSAlexander Stetsenko int
smb3_sha512_getmech(smb_crypto_mech_t * mech)35*4e065a9fSAlexander Stetsenko smb3_sha512_getmech(smb_crypto_mech_t *mech)
36*4e065a9fSAlexander Stetsenko {
37*4e065a9fSAlexander Stetsenko 	crypto_mech_type_t t;
38*4e065a9fSAlexander Stetsenko 
39*4e065a9fSAlexander Stetsenko 	t = crypto_mech2id(SUN_CKM_SHA512);
40*4e065a9fSAlexander Stetsenko 	if (t == CRYPTO_MECH_INVALID) {
41*4e065a9fSAlexander Stetsenko 		cmn_err(CE_NOTE, "smb: no kcf mech: %s", SUN_CKM_SHA512);
42*4e065a9fSAlexander Stetsenko 		return (-1);
43*4e065a9fSAlexander Stetsenko 	}
44*4e065a9fSAlexander Stetsenko 	mech->cm_type = t;
45*4e065a9fSAlexander Stetsenko 	return (0);
46*4e065a9fSAlexander Stetsenko }
47*4e065a9fSAlexander Stetsenko 
48*4e065a9fSAlexander Stetsenko /*
49*4e065a9fSAlexander Stetsenko  * (called from smb2_negotiate_common)
50*4e065a9fSAlexander Stetsenko  */
51*4e065a9fSAlexander Stetsenko void
smb31_preauth_init_mech(smb_session_t * s)52*4e065a9fSAlexander Stetsenko smb31_preauth_init_mech(smb_session_t *s)
53*4e065a9fSAlexander Stetsenko {
54*4e065a9fSAlexander Stetsenko 	smb_crypto_mech_t *mech;
55*4e065a9fSAlexander Stetsenko 	int rc;
56*4e065a9fSAlexander Stetsenko 
57*4e065a9fSAlexander Stetsenko 	ASSERT3S(s->dialect, >=, SMB_VERS_3_11);
58*4e065a9fSAlexander Stetsenko 
59*4e065a9fSAlexander Stetsenko 	if (s->preauth_mech != NULL)
60*4e065a9fSAlexander Stetsenko 		return;
61*4e065a9fSAlexander Stetsenko 
62*4e065a9fSAlexander Stetsenko 	mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
63*4e065a9fSAlexander Stetsenko 	rc = smb3_sha512_getmech(mech);
64*4e065a9fSAlexander Stetsenko 	if (rc != 0) {
65*4e065a9fSAlexander Stetsenko 		kmem_free(mech, sizeof (*mech));
66*4e065a9fSAlexander Stetsenko 		return;
67*4e065a9fSAlexander Stetsenko 	}
68*4e065a9fSAlexander Stetsenko 	s->preauth_mech = mech;
69*4e065a9fSAlexander Stetsenko }
70*4e065a9fSAlexander Stetsenko 
71*4e065a9fSAlexander Stetsenko void
smb31_preauth_fini(smb_session_t * s)72*4e065a9fSAlexander Stetsenko smb31_preauth_fini(smb_session_t *s)
73*4e065a9fSAlexander Stetsenko {
74*4e065a9fSAlexander Stetsenko 	smb_crypto_mech_t *mech;
75*4e065a9fSAlexander Stetsenko 
76*4e065a9fSAlexander Stetsenko 	if ((mech = s->preauth_mech) != NULL) {
77*4e065a9fSAlexander Stetsenko 		kmem_free(mech, sizeof (*mech));
78*4e065a9fSAlexander Stetsenko 		s->preauth_mech = NULL;
79*4e065a9fSAlexander Stetsenko 	}
80*4e065a9fSAlexander Stetsenko }
81*4e065a9fSAlexander Stetsenko 
82*4e065a9fSAlexander Stetsenko /*
83*4e065a9fSAlexander Stetsenko  * Start the KCF session, load the key
84*4e065a9fSAlexander Stetsenko  */
85*4e065a9fSAlexander Stetsenko int
smb_sha512_init(smb_sign_ctx_t * ctxp,smb_crypto_mech_t * mech)86*4e065a9fSAlexander Stetsenko smb_sha512_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech)
87*4e065a9fSAlexander Stetsenko {
88*4e065a9fSAlexander Stetsenko 	int rv;
89*4e065a9fSAlexander Stetsenko 
90*4e065a9fSAlexander Stetsenko 	rv = crypto_digest_init(mech, ctxp, NULL);
91*4e065a9fSAlexander Stetsenko 
92*4e065a9fSAlexander Stetsenko 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
93*4e065a9fSAlexander Stetsenko }
94*4e065a9fSAlexander Stetsenko 
95*4e065a9fSAlexander Stetsenko /*
96*4e065a9fSAlexander Stetsenko  * Digest one segment
97*4e065a9fSAlexander Stetsenko  */
98*4e065a9fSAlexander Stetsenko int
smb_sha512_update(smb_sign_ctx_t ctx,void * buf,size_t len)99*4e065a9fSAlexander Stetsenko smb_sha512_update(smb_sign_ctx_t ctx, void *buf, size_t len)
100*4e065a9fSAlexander Stetsenko {
101*4e065a9fSAlexander Stetsenko 	crypto_data_t data;
102*4e065a9fSAlexander Stetsenko 	int rv;
103*4e065a9fSAlexander Stetsenko 
104*4e065a9fSAlexander Stetsenko 	bzero(&data, sizeof (data));
105*4e065a9fSAlexander Stetsenko 	data.cd_format = CRYPTO_DATA_RAW;
106*4e065a9fSAlexander Stetsenko 	data.cd_length = len;
107*4e065a9fSAlexander Stetsenko 	data.cd_raw.iov_base = buf;
108*4e065a9fSAlexander Stetsenko 	data.cd_raw.iov_len = len;
109*4e065a9fSAlexander Stetsenko 
110*4e065a9fSAlexander Stetsenko 	rv = crypto_digest_update(ctx, &data, 0);
111*4e065a9fSAlexander Stetsenko 
112*4e065a9fSAlexander Stetsenko 	if (rv != CRYPTO_SUCCESS) {
113*4e065a9fSAlexander Stetsenko 		crypto_cancel_ctx(ctx);
114*4e065a9fSAlexander Stetsenko 		return (-1);
115*4e065a9fSAlexander Stetsenko 	}
116*4e065a9fSAlexander Stetsenko 
117*4e065a9fSAlexander Stetsenko 	return (0);
118*4e065a9fSAlexander Stetsenko }
119*4e065a9fSAlexander Stetsenko 
120*4e065a9fSAlexander Stetsenko /*
121*4e065a9fSAlexander Stetsenko  * Get the final digest.
122*4e065a9fSAlexander Stetsenko  */
123*4e065a9fSAlexander Stetsenko int
smb_sha512_final(smb_sign_ctx_t ctx,uint8_t * digest)124*4e065a9fSAlexander Stetsenko smb_sha512_final(smb_sign_ctx_t ctx, uint8_t *digest)
125*4e065a9fSAlexander Stetsenko {
126*4e065a9fSAlexander Stetsenko 	crypto_data_t out;
127*4e065a9fSAlexander Stetsenko 	int rv;
128*4e065a9fSAlexander Stetsenko 
129*4e065a9fSAlexander Stetsenko 	bzero(&out, sizeof (out));
130*4e065a9fSAlexander Stetsenko 	out.cd_format = CRYPTO_DATA_RAW;
131*4e065a9fSAlexander Stetsenko 	out.cd_length = SHA512_DIGEST_LENGTH;
132*4e065a9fSAlexander Stetsenko 	out.cd_raw.iov_len = SHA512_DIGEST_LENGTH;
133*4e065a9fSAlexander Stetsenko 	out.cd_raw.iov_base = (void *)digest;
134*4e065a9fSAlexander Stetsenko 
135*4e065a9fSAlexander Stetsenko 	rv = crypto_digest_final(ctx, &out, 0);
136*4e065a9fSAlexander Stetsenko 
137*4e065a9fSAlexander Stetsenko 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
138*4e065a9fSAlexander Stetsenko }
139*4e065a9fSAlexander Stetsenko 
140*4e065a9fSAlexander Stetsenko int
smb31_preauth_sha512_calc(smb_request_t * sr,struct mbuf_chain * mbc,uint8_t * in_hashval,uint8_t * out_hashval)141*4e065a9fSAlexander Stetsenko smb31_preauth_sha512_calc(smb_request_t *sr, struct mbuf_chain *mbc,
142*4e065a9fSAlexander Stetsenko     uint8_t *in_hashval, uint8_t *out_hashval)
143*4e065a9fSAlexander Stetsenko {
144*4e065a9fSAlexander Stetsenko 	smb_session_t *s = sr->session;
145*4e065a9fSAlexander Stetsenko 	smb_sign_ctx_t ctx = 0;
146*4e065a9fSAlexander Stetsenko 	struct mbuf *mbuf = mbc->chain;
147*4e065a9fSAlexander Stetsenko 	int rc;
148*4e065a9fSAlexander Stetsenko 
149*4e065a9fSAlexander Stetsenko 	ASSERT3U(s->smb31_preauth_hashid, !=, 0);
150*4e065a9fSAlexander Stetsenko 
151*4e065a9fSAlexander Stetsenko 	if (s->preauth_mech == NULL)
152*4e065a9fSAlexander Stetsenko 		return (-1);
153*4e065a9fSAlexander Stetsenko 
154*4e065a9fSAlexander Stetsenko 	if ((rc = smb_sha512_init(&ctx, s->preauth_mech)) != 0)
155*4e065a9fSAlexander Stetsenko 		return (rc);
156*4e065a9fSAlexander Stetsenko 
157*4e065a9fSAlexander Stetsenko 	/* Digest current hashval */
158*4e065a9fSAlexander Stetsenko 	rc = smb_sha512_update(ctx, in_hashval, SHA512_DIGEST_LENGTH);
159*4e065a9fSAlexander Stetsenko 	if (rc != 0)
160*4e065a9fSAlexander Stetsenko 		return (rc);
161*4e065a9fSAlexander Stetsenko 
162*4e065a9fSAlexander Stetsenko 	while (mbuf != NULL) {
163*4e065a9fSAlexander Stetsenko 		rc = smb_sha512_update(ctx, mbuf->m_data, mbuf->m_len);
164*4e065a9fSAlexander Stetsenko 		if (rc != 0)
165*4e065a9fSAlexander Stetsenko 			return (rc);
166*4e065a9fSAlexander Stetsenko 		mbuf = mbuf->m_next;
167*4e065a9fSAlexander Stetsenko 	}
168*4e065a9fSAlexander Stetsenko 
169*4e065a9fSAlexander Stetsenko 	rc = smb_sha512_final(ctx, out_hashval);
170*4e065a9fSAlexander Stetsenko 	return (rc);
171*4e065a9fSAlexander Stetsenko }
172