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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
29 #include <sys/types.h>
31 #include <security/cryptoki.h>
32 #include <security/pkcs11.h>
33 #include <cryptoutil.h>
34 #include <smbsrv/libsmb.h>
36 static void smb_initlmkey(unsigned char *keyin
, unsigned char *keyout
);
41 * Randomize the contents of the specified buffer.
44 randomize(char *data
, unsigned len
)
48 if (pkcs11_get_random(data
, len
) == 0)
52 * Implement a "fall back", because current callers
53 * don't expect an error from this. In practice,
54 * we never use this fall back.
57 *p
++ = (random() >> 24);
64 * Compute an MD4 digest.
67 smb_auth_md4(unsigned char *result
, unsigned char *input
, int length
)
71 MD4Init(&md4_context
);
72 MD4Update(&md4_context
, input
, length
);
73 MD4Final(result
, &md4_context
);
74 return (SMBAUTH_SUCCESS
);
78 smb_auth_hmac_md5(unsigned char *data
,
82 unsigned char *digest
)
85 CK_MECHANISM mechanism
;
86 CK_OBJECT_HANDLE hKey
;
87 CK_SESSION_HANDLE hSession
;
88 CK_ULONG diglen
= MD_DIGEST_LEN
;
90 mechanism
.mechanism
= CKM_MD5_HMAC
;
91 mechanism
.pParameter
= 0;
92 mechanism
.ulParameterLen
= 0;
93 rv
= SUNW_C_GetMechSession(mechanism
.mechanism
, &hSession
);
95 return (SMBAUTH_FAILURE
);
98 rv
= SUNW_C_KeyToObject(hSession
, mechanism
.mechanism
,
101 (void) C_CloseSession(hSession
);
102 return (SMBAUTH_FAILURE
);
105 /* Initialize the digest operation in the session */
106 rv
= C_SignInit(hSession
, &mechanism
, hKey
);
108 (void) C_DestroyObject(hSession
, hKey
);
109 (void) C_CloseSession(hSession
);
110 return (SMBAUTH_FAILURE
);
112 rv
= C_SignUpdate(hSession
, (CK_BYTE_PTR
)data
, data_len
);
114 (void) C_DestroyObject(hSession
, hKey
);
115 (void) C_CloseSession(hSession
);
116 return (SMBAUTH_FAILURE
);
118 rv
= C_SignFinal(hSession
, (CK_BYTE_PTR
)digest
, &diglen
);
120 (void) C_DestroyObject(hSession
, hKey
);
121 (void) C_CloseSession(hSession
);
122 return (SMBAUTH_FAILURE
);
124 (void) C_DestroyObject(hSession
, hKey
);
125 (void) C_CloseSession(hSession
);
126 if (diglen
!= MD_DIGEST_LEN
) {
127 return (SMBAUTH_FAILURE
);
129 return (SMBAUTH_SUCCESS
);
133 smb_auth_DES(unsigned char *Result
, int ResultLen
,
134 unsigned char *Key
, int KeyLen
,
135 unsigned char *Data
, int DataLen
)
138 CK_MECHANISM mechanism
;
139 CK_OBJECT_HANDLE hKey
;
140 CK_SESSION_HANDLE hSession
;
141 CK_ULONG ciphertext_len
;
148 * Calculate proper number of iterations.
149 * Known call cases include:
150 * ResultLen=16, KeyLen=14, DataLen=8
151 * ResultLen=24, KeyLen=21, DataLen=8
152 * ResultLen=16, KeyLen=14, DataLen=16
156 if ((KeyLen
% 7) || (DataLen
% 8))
158 if (K
== 0 || D
== 0)
160 if (ResultLen
< (K
* 8))
164 * Use SUNW convenience function to initialize the cryptoki
165 * library, and open a session with a slot that supports
166 * the mechanism we plan on using.
168 mechanism
.mechanism
= CKM_DES_ECB
;
169 mechanism
.pParameter
= NULL
;
170 mechanism
.ulParameterLen
= 0;
171 rv
= SUNW_C_GetMechSession(mechanism
.mechanism
, &hSession
);
173 return (SMBAUTH_FAILURE
);
176 for (d
= k
= 0; k
< K
; k
++, d
++) {
177 /* Cycle the input again, as necessary. */
180 smb_initlmkey(&Key
[k
* 7], des_key
);
181 rv
= SUNW_C_KeyToObject(hSession
, mechanism
.mechanism
,
187 /* Initialize the encryption operation in the session */
188 rv
= C_EncryptInit(hSession
, &mechanism
, hKey
);
195 /* Read in the data and encrypt this portion */
196 rv
= C_EncryptUpdate(hSession
,
197 (CK_BYTE_PTR
)Data
+ (d
* 8), 8,
198 (CK_BYTE_PTR
)Result
+ (k
* 8),
205 (void) C_DestroyObject(hSession
, hKey
);
210 (void) C_DestroyObject(hSession
, hKey
);
212 (void) C_CloseSession(hSession
);
215 return (SMBAUTH_FAILURE
);
217 return (SMBAUTH_SUCCESS
);
221 * See "Netlogon Credential Computation" section of MS-NRPC document.
224 smb_initlmkey(unsigned char *keyin
, unsigned char *keyout
)
228 keyout
[0] = keyin
[0] >> 0x01;
229 keyout
[1] = ((keyin
[0] & 0x01) << 6) | (keyin
[1] >> 2);
230 keyout
[2] = ((keyin
[1] & 0x03) << 5) | (keyin
[2] >> 3);
231 keyout
[3] = ((keyin
[2] & 0x07) << 4) | (keyin
[3] >> 4);
232 keyout
[4] = ((keyin
[3] & 0x0f) << 3) | (keyin
[4] >> 5);
233 keyout
[5] = ((keyin
[4] & 0x1f) << 2) | (keyin
[5] >> 6);
234 keyout
[6] = ((keyin
[5] & 0x3f) << 1) | (keyin
[6] >> 7);
235 keyout
[7] = keyin
[6] & 0x7f;
237 for (i
= 0; i
< 8; i
++)
238 keyout
[i
] = (keyout
[i
] << 1) & 0xfe;
245 smb_auth_RC4(uchar_t
*Result
, int ResultLen
,
246 uchar_t
*Key
, int KeyLen
,
247 uchar_t
*Data
, int DataLen
)
250 CK_MECHANISM mechanism
;
251 CK_OBJECT_HANDLE hKey
;
252 CK_SESSION_HANDLE hSession
;
253 CK_ULONG ciphertext_len
;
254 int error
= SMBAUTH_FAILURE
;
257 * Use SUNW convenience function to initialize the cryptoki
258 * library, and open a session with a slot that supports
259 * the mechanism we plan on using.
261 mechanism
.mechanism
= CKM_RC4
;
262 mechanism
.pParameter
= NULL
;
263 mechanism
.ulParameterLen
= 0;
264 rv
= SUNW_C_GetMechSession(mechanism
.mechanism
, &hSession
);
266 return (SMBAUTH_FAILURE
);
269 rv
= SUNW_C_KeyToObject(hSession
, mechanism
.mechanism
,
274 /* Initialize the encryption operation in the session */
275 rv
= C_EncryptInit(hSession
, &mechanism
, hKey
);
279 ciphertext_len
= ResultLen
;
280 rv
= C_EncryptUpdate(hSession
,
281 (CK_BYTE_PTR
)Data
, DataLen
,
282 (CK_BYTE_PTR
)Result
, &ciphertext_len
);
287 (void) C_DestroyObject(hSession
, hKey
);
289 (void) C_CloseSession(hSession
);