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