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