xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_crypt.c (revision 7052:efa04b030974)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw 
225331Samw /*
23*7052Samw  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245331Samw  * Use is subject to license terms.
255331Samw  */
265331Samw 
275331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
285331Samw 
295331Samw #include <sys/md4.h>
305331Samw #include <sys/types.h>
315331Samw #include <string.h>
325331Samw #include <security/cryptoki.h>
335331Samw #include <security/pkcs11.h>
345331Samw #include <cryptoutil.h>
355331Samw #include <smbsrv/libsmb.h>
365331Samw 
37*7052Samw static void smb_initlmkey(unsigned char *keyin, unsigned char *keyout);
385331Samw 
395331Samw /*
405331Samw  * smb_auth_md4
415331Samw  *
425331Samw  * Compute an MD4 digest.
435331Samw  */
445331Samw int
smb_auth_md4(unsigned char * result,unsigned char * input,int length)455331Samw smb_auth_md4(unsigned char *result, unsigned char *input, int length)
465331Samw {
475331Samw 	MD4_CTX md4_context;
485331Samw 
495331Samw 	MD4Init(&md4_context);
505331Samw 	MD4Update(&md4_context, input, length);
515331Samw 	MD4Final(result, &md4_context);
525331Samw 	return (SMBAUTH_SUCCESS);
535331Samw }
545331Samw 
555331Samw int
smb_auth_hmac_md5(unsigned char * data,int data_len,unsigned char * key,int key_len,unsigned char * digest)565331Samw smb_auth_hmac_md5(unsigned char *data,
575331Samw 	int data_len,
585331Samw 	unsigned char *key,
595331Samw 	int key_len,
605331Samw 	unsigned char *digest)
615331Samw {
625331Samw 	CK_RV rv;
635331Samw 	CK_MECHANISM mechanism;
645331Samw 	CK_OBJECT_HANDLE hKey;
655331Samw 	CK_SESSION_HANDLE hSession;
66*7052Samw 	CK_ULONG diglen = MD_DIGEST_LEN;
675331Samw 
685331Samw 	mechanism.mechanism = CKM_MD5_HMAC;
695331Samw 	mechanism.pParameter = 0;
705331Samw 	mechanism.ulParameterLen = 0;
715331Samw 	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
725331Samw 	if (rv != CKR_OK) {
735331Samw 		return (SMBAUTH_FAILURE);
745331Samw 	}
755331Samw 
765331Samw 	rv = SUNW_C_KeyToObject(hSession, mechanism.mechanism,
775331Samw 	    key, key_len, &hKey);
785331Samw 	if (rv != CKR_OK) {
795331Samw 		(void) C_CloseSession(hSession);
805331Samw 		return (SMBAUTH_FAILURE);
815331Samw 	}
825331Samw 
835331Samw 	/* Initialize the digest operation in the session */
845331Samw 	rv = C_SignInit(hSession, &mechanism, hKey);
855331Samw 	if (rv != CKR_OK) {
865331Samw 		(void) C_DestroyObject(hSession, hKey);
875331Samw 		(void) C_CloseSession(hSession);
885331Samw 		return (SMBAUTH_FAILURE);
895331Samw 	}
905331Samw 	rv = C_SignUpdate(hSession, (CK_BYTE_PTR)data, data_len);
915331Samw 	if (rv != CKR_OK) {
925331Samw 		(void) C_DestroyObject(hSession, hKey);
935331Samw 		(void) C_CloseSession(hSession);
945331Samw 		return (SMBAUTH_FAILURE);
955331Samw 	}
965331Samw 	rv = C_SignFinal(hSession, (CK_BYTE_PTR)digest, &diglen);
975331Samw 	if (rv != CKR_OK) {
985331Samw 		(void) C_DestroyObject(hSession, hKey);
995331Samw 		(void) C_CloseSession(hSession);
1005331Samw 		return (SMBAUTH_FAILURE);
1015331Samw 	}
1025331Samw 	(void) C_DestroyObject(hSession, hKey);
1035331Samw 	(void) C_CloseSession(hSession);
1045331Samw 	if (diglen != MD_DIGEST_LEN) {
1055331Samw 		return (SMBAUTH_FAILURE);
1065331Samw 	}
1075331Samw 	return (SMBAUTH_SUCCESS);
1085331Samw }
1095331Samw 
1105331Samw int
smb_auth_DES(unsigned char * Result,int ResultLen,unsigned char * Key,int KeyLen,unsigned char * Data,int DataLen)1115331Samw smb_auth_DES(unsigned char *Result, int ResultLen,
1125331Samw     unsigned char *Key, int KeyLen,
1135331Samw     unsigned char *Data, int DataLen)
1145331Samw {
1155331Samw 	CK_RV rv;
1165331Samw 	CK_MECHANISM mechanism;
1175331Samw 	CK_OBJECT_HANDLE hKey;
1185331Samw 	CK_SESSION_HANDLE hSession;
1195331Samw 	CK_ULONG ciphertext_len;
1205331Samw 	uchar_t des_key[8];
1215331Samw 	int error = 0;
1225331Samw 	int K, D;
1235331Samw 	int k, d;
1245331Samw 
1255331Samw 	/* Calculate proper number of iterations */
1265331Samw 	K = KeyLen / 7;
1275331Samw 	D = DataLen / 8;
1285331Samw 
1295331Samw 	if (ResultLen < (K * 8 * D)) {
1305331Samw 		return (SMBAUTH_FAILURE);
1315331Samw 	}
1325331Samw 
1335331Samw 	/*
1345331Samw 	 * Use SUNW convenience function to initialize the cryptoki
1355331Samw 	 * library, and open a session with a slot that supports
1365331Samw 	 * the mechanism we plan on using.
1375331Samw 	 */
1385331Samw 	mechanism.mechanism = CKM_DES_ECB;
1395331Samw 	mechanism.pParameter = NULL;
1405331Samw 	mechanism.ulParameterLen = 0;
1415331Samw 	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
1425331Samw 	if (rv != CKR_OK) {
1435331Samw 		return (SMBAUTH_FAILURE);
1445331Samw 	}
1455331Samw 
1465331Samw 	for (k = 0; k < K; k++) {
147*7052Samw 		smb_initlmkey(&Key[k * 7], des_key);
1485331Samw 		rv = SUNW_C_KeyToObject(hSession, mechanism.mechanism,
1495331Samw 		    des_key, 8, &hKey);
1505331Samw 		if (rv != CKR_OK) {
1515331Samw 			error = 1;
1525331Samw 			goto exit_session;
1535331Samw 		}
1545331Samw 		/* Initialize the encryption operation in the session */
1555331Samw 		rv = C_EncryptInit(hSession, &mechanism, hKey);
1565331Samw 		if (rv != CKR_OK) {
1575331Samw 			error = 1;
1585331Samw 			goto exit_encrypt;
1595331Samw 		}
1605331Samw 		ciphertext_len = DataLen;
1615331Samw 		for (d = 0; d < D; d++) {
1625331Samw 			/* Read in the data and encrypt this portion */
1635331Samw 			rv = C_EncryptUpdate(hSession,
1645331Samw 			    (CK_BYTE_PTR)Data + (d * 8), 8,
1655331Samw 			    &Result[(k * (8 * D)) + (d * 8)],
1665331Samw 			    &ciphertext_len);
1675331Samw 			if (rv != CKR_OK) {
1685331Samw 				error = 1;
1695331Samw 				goto exit_encrypt;
1705331Samw 			}
1715331Samw 		}
1725331Samw 		(void) C_DestroyObject(hSession, hKey);
1735331Samw 	}
1745331Samw 	goto exit_session;
1755331Samw 
1765331Samw exit_encrypt:
1775331Samw 	(void) C_DestroyObject(hSession, hKey);
1785331Samw exit_session:
1795331Samw 	(void) C_CloseSession(hSession);
1805331Samw 
1815331Samw 	if (error)
1825331Samw 		return (SMBAUTH_FAILURE);
1835331Samw 
1845331Samw 	return (SMBAUTH_SUCCESS);
1855331Samw }
1865331Samw 
1875331Samw /*
188*7052Samw  * See "Netlogon Credential Computation" section of MS-NRPC document.
1895331Samw  */
1905331Samw static void
smb_initlmkey(unsigned char * keyin,unsigned char * keyout)191*7052Samw smb_initlmkey(unsigned char *keyin, unsigned char *keyout)
1925331Samw {
193*7052Samw 	int i;
194*7052Samw 
195*7052Samw 	keyout[0] = keyin[0] >> 0x01;
196*7052Samw 	keyout[1] = ((keyin[0] & 0x01) << 6) | (keyin[1] >> 2);
197*7052Samw 	keyout[2] = ((keyin[1] & 0x03) << 5) | (keyin[2] >> 3);
198*7052Samw 	keyout[3] = ((keyin[2] & 0x07) << 4) | (keyin[3] >> 4);
199*7052Samw 	keyout[4] = ((keyin[3] & 0x0f) << 3) | (keyin[4] >> 5);
200*7052Samw 	keyout[5] = ((keyin[4] & 0x1f) << 2) | (keyin[5] >> 6);
201*7052Samw 	keyout[6] = ((keyin[5] & 0x3f) << 1) | (keyin[6] >> 7);
202*7052Samw 	keyout[7] = keyin[6] & 0x7f;
203*7052Samw 
204*7052Samw 	for (i = 0; i < 8; i++)
205*7052Samw 		keyout[i] = (keyout[i] << 1) & 0xfe;
2065331Samw }
207