xref: /titanic_44/usr/src/lib/smbsrv/libsmb/common/smb_mac.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1*da6c28aaSamw /*
2*da6c28aaSamw  * CDDL HEADER START
3*da6c28aaSamw  *
4*da6c28aaSamw  * The contents of this file are subject to the terms of the
5*da6c28aaSamw  * Common Development and Distribution License (the "License").
6*da6c28aaSamw  * You may not use this file except in compliance with the License.
7*da6c28aaSamw  *
8*da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10*da6c28aaSamw  * See the License for the specific language governing permissions
11*da6c28aaSamw  * and limitations under the License.
12*da6c28aaSamw  *
13*da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14*da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16*da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17*da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da6c28aaSamw  *
19*da6c28aaSamw  * CDDL HEADER END
20*da6c28aaSamw  */
21*da6c28aaSamw /*
22*da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*da6c28aaSamw  * Use is subject to license terms.
24*da6c28aaSamw  */
25*da6c28aaSamw 
26*da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*da6c28aaSamw 
28*da6c28aaSamw /*
29*da6c28aaSamw  * SMB MAC Signing support.
30*da6c28aaSamw  */
31*da6c28aaSamw 
32*da6c28aaSamw #include <strings.h>
33*da6c28aaSamw #include <security/cryptoki.h>
34*da6c28aaSamw #include <security/pkcs11.h>
35*da6c28aaSamw 
36*da6c28aaSamw #include <smbsrv/libsmb.h>
37*da6c28aaSamw 
38*da6c28aaSamw #include <smbsrv/smb.h>
39*da6c28aaSamw 
40*da6c28aaSamw /*
41*da6c28aaSamw  * smb_mac_init
42*da6c28aaSamw  *
43*da6c28aaSamw  * Calculates the MAC key using the specified user session
44*da6c28aaSamw  * key (NTLM or NTLMv2).
45*da6c28aaSamw  *
46*da6c28aaSamw  * Returns SMBAUTH_SUCCESS if key generation was successful,
47*da6c28aaSamw  * SMBAUTH_FAILURE if not.
48*da6c28aaSamw  */
49*da6c28aaSamw int
smb_mac_init(smb_sign_ctx_t * sign_ctx,smb_auth_info_t * auth)50*da6c28aaSamw smb_mac_init(smb_sign_ctx_t *sign_ctx, smb_auth_info_t *auth)
51*da6c28aaSamw {
52*da6c28aaSamw 	unsigned char S16[SMBAUTH_SESSION_KEY_SZ];
53*da6c28aaSamw 
54*da6c28aaSamw 	if (smb_auth_gen_session_key(auth, S16) != SMBAUTH_SUCCESS)
55*da6c28aaSamw 		return (SMBAUTH_FAILURE);
56*da6c28aaSamw 	bcopy(S16, sign_ctx->ssc_mackey, SMBAUTH_SESSION_KEY_SZ);
57*da6c28aaSamw 	bcopy(auth->cs, &(sign_ctx->ssc_mackey[SMBAUTH_SESSION_KEY_SZ]),
58*da6c28aaSamw 	    auth->cs_len);
59*da6c28aaSamw 	sign_ctx->ssc_keylen = SMBAUTH_SESSION_KEY_SZ + auth->cs_len;
60*da6c28aaSamw 	return (SMBAUTH_SUCCESS);
61*da6c28aaSamw }
62*da6c28aaSamw 
63*da6c28aaSamw /*
64*da6c28aaSamw  * smb_mac_calc
65*da6c28aaSamw  *
66*da6c28aaSamw  * Calculates MAC signature for the given buffer and returns
67*da6c28aaSamw  * it in the mac_sign parameter.
68*da6c28aaSamw  *
69*da6c28aaSamw  * The MAC signature is calculated as follows:
70*da6c28aaSamw  *
71*da6c28aaSamw  * data = concat(MAC_Key, MAC_Key_Len, SMB_Msg, SMB_Msg_Len);
72*da6c28aaSamw  * hash = MD5(data);
73*da6c28aaSamw  * MAC  = head(hash, 8);
74*da6c28aaSamw  *
75*da6c28aaSamw  * The tricky part is that a sequence number should be used
76*da6c28aaSamw  * in calculation instead of the signature field in the
77*da6c28aaSamw  * SMB header.
78*da6c28aaSamw  *
79*da6c28aaSamw  * Returns SMBAUTH_SUCCESS if cryptology framework use was successful,
80*da6c28aaSamw  * SMBAUTH_FAILURE if not.
81*da6c28aaSamw  */
82*da6c28aaSamw int
smb_mac_calc(smb_sign_ctx_t * sign_ctx,const unsigned char * buf,size_t buf_len,unsigned char * mac_sign)83*da6c28aaSamw smb_mac_calc(smb_sign_ctx_t *sign_ctx, const unsigned char *buf,
84*da6c28aaSamw     size_t buf_len, unsigned char *mac_sign)
85*da6c28aaSamw {
86*da6c28aaSamw 	CK_RV rv;
87*da6c28aaSamw 	CK_MECHANISM mechanism;
88*da6c28aaSamw 	CK_SESSION_HANDLE hSession;
89*da6c28aaSamw 	unsigned long diglen = MD_DIGEST_LEN;
90*da6c28aaSamw 	int rc = SMBAUTH_FAILURE;
91*da6c28aaSamw 
92*da6c28aaSamw 	int offset_end_of_sig = (SMB_SIG_OFFS + SMB_SIG_SIZE);
93*da6c28aaSamw 	unsigned char seq_buf[SMB_SIG_SIZE];
94*da6c28aaSamw 	unsigned char mac[16];
95*da6c28aaSamw 
96*da6c28aaSamw 	/*
97*da6c28aaSamw 	 * put seq_num into the first 4 bytes and
98*da6c28aaSamw 	 * zero out the next 4 bytes
99*da6c28aaSamw 	 */
100*da6c28aaSamw 	bcopy(&sign_ctx->ssc_seqnum, seq_buf, 4);
101*da6c28aaSamw 	bzero(seq_buf + 4, 4);
102*da6c28aaSamw 
103*da6c28aaSamw 	mechanism.mechanism = CKM_MD5;
104*da6c28aaSamw 	mechanism.pParameter = 0;
105*da6c28aaSamw 	mechanism.ulParameterLen = 0;
106*da6c28aaSamw 
107*da6c28aaSamw 	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
108*da6c28aaSamw 	if (rv != CKR_OK)
109*da6c28aaSamw 		return (SMBAUTH_FAILURE);
110*da6c28aaSamw 
111*da6c28aaSamw 	/* Initialize the digest operation in the session */
112*da6c28aaSamw 	rv = C_DigestInit(hSession, &mechanism);
113*da6c28aaSamw 	if (rv != CKR_OK)
114*da6c28aaSamw 		goto smbmacdone;
115*da6c28aaSamw 
116*da6c28aaSamw 	/* init with the MAC key */
117*da6c28aaSamw 	rv = C_DigestUpdate(hSession, sign_ctx->ssc_mackey,
118*da6c28aaSamw 	    sign_ctx->ssc_keylen);
119*da6c28aaSamw 	if (rv != CKR_OK)
120*da6c28aaSamw 		goto smbmacdone;
121*da6c28aaSamw 
122*da6c28aaSamw 	/* copy in SMB packet info till signature field */
123*da6c28aaSamw 	rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)buf, SMB_SIG_OFFS);
124*da6c28aaSamw 	if (rv != CKR_OK)
125*da6c28aaSamw 		goto smbmacdone;
126*da6c28aaSamw 
127*da6c28aaSamw 	/* copy in the seq_buf instead of the signature */
128*da6c28aaSamw 	rv = C_DigestUpdate(hSession, seq_buf, sizeof (seq_buf));
129*da6c28aaSamw 	if (rv != CKR_OK)
130*da6c28aaSamw 		goto smbmacdone;
131*da6c28aaSamw 
132*da6c28aaSamw 	/* copy in the rest of the packet, skipping the signature */
133*da6c28aaSamw 	rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)buf + offset_end_of_sig,
134*da6c28aaSamw 	    buf_len - offset_end_of_sig);
135*da6c28aaSamw 	if (rv != CKR_OK)
136*da6c28aaSamw 		goto smbmacdone;
137*da6c28aaSamw 
138*da6c28aaSamw 	rv = C_DigestFinal(hSession, mac, &diglen);
139*da6c28aaSamw 	if (rv != CKR_OK)
140*da6c28aaSamw 		goto smbmacdone;
141*da6c28aaSamw 
142*da6c28aaSamw 	bcopy(mac, mac_sign, SMB_SIG_SIZE);
143*da6c28aaSamw 	rc = SMBAUTH_SUCCESS;
144*da6c28aaSamw 
145*da6c28aaSamw smbmacdone:
146*da6c28aaSamw 	(void) C_CloseSession(hSession);
147*da6c28aaSamw 	return (rc);
148*da6c28aaSamw }
149*da6c28aaSamw 
150*da6c28aaSamw /*
151*da6c28aaSamw  * smb_mac_chk
152*da6c28aaSamw  *
153*da6c28aaSamw  * Calculates MAC signature for the given buffer
154*da6c28aaSamw  * and compares it to the signature in the given context.
155*da6c28aaSamw  * Return 1 if the signature are match, otherwise, return (0);
156*da6c28aaSamw  */
157*da6c28aaSamw int
smb_mac_chk(smb_sign_ctx_t * sign_ctx,const unsigned char * buf,size_t buf_len)158*da6c28aaSamw smb_mac_chk(smb_sign_ctx_t *sign_ctx,
159*da6c28aaSamw 			const unsigned char *buf, size_t buf_len)
160*da6c28aaSamw {
161*da6c28aaSamw 	unsigned char mac_sign[SMB_SIG_SIZE];
162*da6c28aaSamw 
163*da6c28aaSamw 	/* calculate mac signature */
164*da6c28aaSamw 	if (smb_mac_calc(sign_ctx, buf, buf_len, mac_sign) != SMBAUTH_SUCCESS)
165*da6c28aaSamw 		return (0);
166*da6c28aaSamw 
167*da6c28aaSamw 	/* compare the signatures */
168*da6c28aaSamw 	if (memcmp(sign_ctx->ssc_sign, mac_sign, SMB_SIG_SIZE) == 0)
169*da6c28aaSamw 		return (1);
170*da6c28aaSamw 
171*da6c28aaSamw 	return (0);
172*da6c28aaSamw }
173*da6c28aaSamw 
174*da6c28aaSamw /*
175*da6c28aaSamw  * smb_mac_sign
176*da6c28aaSamw  *
177*da6c28aaSamw  * Calculates MAC signature for the given buffer,
178*da6c28aaSamw  * and write it to the buffer's signature field.
179*da6c28aaSamw  *
180*da6c28aaSamw  * Returns SMBAUTH_SUCCESS if cryptology framework use was successful,
181*da6c28aaSamw  * SMBAUTH_FAILURE if not.
182*da6c28aaSamw  */
183*da6c28aaSamw int
smb_mac_sign(smb_sign_ctx_t * sign_ctx,unsigned char * buf,size_t buf_len)184*da6c28aaSamw smb_mac_sign(smb_sign_ctx_t *sign_ctx, unsigned char *buf, size_t buf_len)
185*da6c28aaSamw {
186*da6c28aaSamw 	unsigned char mac_sign[SMB_SIG_SIZE];
187*da6c28aaSamw 
188*da6c28aaSamw 	/* calculate mac signature */
189*da6c28aaSamw 	if (smb_mac_calc(sign_ctx, buf, buf_len, mac_sign) != SMBAUTH_SUCCESS)
190*da6c28aaSamw 		return (SMBAUTH_FAILURE);
191*da6c28aaSamw 
192*da6c28aaSamw 	/* put mac signature in the header's signature field */
193*da6c28aaSamw 	(void) memcpy(buf + SMB_SIG_OFFS, mac_sign, SMB_SIG_SIZE);
194*da6c28aaSamw 	return (SMBAUTH_SUCCESS);
195*da6c28aaSamw }
196*da6c28aaSamw 
197*da6c28aaSamw void
smb_mac_inc_seqnum(smb_sign_ctx_t * sign_ctx)198*da6c28aaSamw smb_mac_inc_seqnum(smb_sign_ctx_t *sign_ctx)
199*da6c28aaSamw {
200*da6c28aaSamw 	sign_ctx->ssc_seqnum++;
201*da6c28aaSamw }
202*da6c28aaSamw 
203*da6c28aaSamw void
smb_mac_dec_seqnum(smb_sign_ctx_t * sign_ctx)204*da6c28aaSamw smb_mac_dec_seqnum(smb_sign_ctx_t *sign_ctx)
205*da6c28aaSamw {
206*da6c28aaSamw 	sign_ctx->ssc_seqnum--;
207*da6c28aaSamw }
208