/*
* Copyright (C) 1998-1999 Brian Bruns
* Copyright (C) 2004 Frediano Ziglio
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "global.h"
#include "md4.h"
#include "des.h"
/*
* The following code is based on some psuedo-C code from ronald@innovation.ch
*/
static void ntlm_encrypt_answer (unsigned char *hash,
const unsigned char *challenge,
unsigned char *answer);
static void ntlm_convert_key (unsigned char *key_56, DES_KEY * ks);
static void ntlm_des_set_odd_parity (char *key);
NTLM_STATIC void
SMBencrypt (const char *passwd, const uint8 * challenge, uint8 * answer)
{
#define MAX_PW_SZ 14
int len;
int i;
static const char magic[8] =
{ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
DES_KEY ks;
unsigned char hash[24];
unsigned char passwd_up[MAX_PW_SZ];
/* convert password to upper and pad to 14 chars */
memset (passwd_up, 0, MAX_PW_SZ);
len = strlen (passwd);
if (len > MAX_PW_SZ)
len = MAX_PW_SZ;
for (i = 0; i < len; i++)
passwd_up[i] = toupper ((unsigned char) passwd[i]);
/* hash the first 7 characters */
ntlm_convert_key (passwd_up, &ks);
ntlm_des_ecb_encrypt (&magic, sizeof (magic), &ks, (hash + 0));
/* hash the second 7 characters */
ntlm_convert_key (passwd_up + 7, &ks);
ntlm_des_ecb_encrypt (&magic, sizeof (magic), &ks, (hash + 8));
memset (hash + 16, 0, 5);
ntlm_encrypt_answer (hash, challenge, answer);
/* with security is best be pedantic */
memset (&ks, 0, sizeof (ks));
memset (hash, 0, sizeof (hash));
memset (passwd_up, 0, sizeof (passwd_up));
}
NTLM_STATIC void
SMBNTencrypt (const char *passwd, const uint8 * challenge, uint8 * answer)
{
size_t len, i;
DES_KEY ks;
unsigned char hash[24];
unsigned char nt_pw[256];
MD4_CTX context;
/* NT resp */
len = strlen (passwd);
if (len > 128)
len = 128;
for (i = 0; i < len; ++i)
{
nt_pw[2 * i] = passwd[i];
nt_pw[2 * i + 1] = 0;
}
MD4Init (&context);
MD4Update (&context, nt_pw, len * 2);
MD4Final (&context, hash);
memset (hash + 16, 0, 5);
ntlm_encrypt_answer (hash, challenge, answer);
/* with security is best be pedantic */
memset (&ks, 0, sizeof (ks));
memset (hash, 0, sizeof (hash));
memset (nt_pw, 0, sizeof (nt_pw));
memset (&context, 0, sizeof (context));
}
/*
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
* 8 byte plaintext is encrypted with each key and the resulting 24
* bytes are stored in the results array.
*/
static void
ntlm_encrypt_answer (unsigned char *hash, const unsigned char *challenge,
unsigned char *answer)
{
DES_KEY ks;
ntlm_convert_key (hash, &ks);
ntlm_des_ecb_encrypt (challenge, 8, &ks, answer);
ntlm_convert_key (&hash[7], &ks);
ntlm_des_ecb_encrypt (challenge, 8, &ks, &answer[8]);
ntlm_convert_key (&hash[14], &ks);
ntlm_des_ecb_encrypt (challenge, 8, &ks, &answer[16]);
memset (&ks, 0, sizeof (ks));
}
static void
ntlm_des_set_odd_parity (char *key)
{
int i;
unsigned char parity;
for (i = 0; i < 8; i++)
{
parity = key[i];
parity ^= parity >> 4;
parity ^= parity >> 2;
parity ^= parity >> 1;
key[i] = (key[i] & 0xfe) | (parity & 1);
}
}
/*
* turns a 56 bit key into the 64 bit, odd parity key and sets the key.
* The key schedule ks is also set.
*/
static void
ntlm_convert_key (unsigned char *key_56, DES_KEY * ks)
{
unsigned char key[8];
key[0] = key_56[0];
key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
key[7] = (key_56[6] << 1) & 0xFF;
ntlm_des_set_odd_parity (key);
ntlm_des_set_key (ks, key, sizeof (key));
memset (&key, 0, sizeof (key));
}
/** \@} */
syntax highlighted by Code2HTML, v. 0.9.1