mirror of
https://github.com/cshepherd/gscifs.git
synced 2025-01-14 11:29:45 +00:00
98 lines
2.6 KiB
C
98 lines
2.6 KiB
C
/****************************************************************************
|
|
* TinySMB
|
|
* Nintendo Wii/GameCube SMB implementation
|
|
*
|
|
* NTLM authentication
|
|
****************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <ogc/machine/processor.h>
|
|
#include <stdint.h>
|
|
|
|
typedef struct
|
|
{
|
|
uint32_t encrypt_subkeys[32];
|
|
uint32_t decrypt_subkeys[32];
|
|
} gl_des_ctx;
|
|
|
|
extern void *md4_buffer(const char *buffer, size_t len, void *resblock);
|
|
extern void gl_des_setkey(gl_des_ctx *ctx, const char * key);
|
|
extern void gl_des_ecb_encrypt(gl_des_ctx *ctx, const char * from, char * to);
|
|
|
|
/* C89 compliant way to cast 'char' to 'unsigned char'. */
|
|
static inline unsigned char to_uchar(char ch)
|
|
{
|
|
return ch;
|
|
}
|
|
|
|
/*
|
|
* turns a 56 bit key into the 64 bit, and sets the key schedule ks.
|
|
*/
|
|
static void ntlm_convert_key(char *key_56, gl_des_ctx * ks)
|
|
{
|
|
char key[8];
|
|
|
|
key[0] = to_uchar(key_56[0]);
|
|
key[1] = ((to_uchar(key_56[0]) << 7) & 0xFF) | (to_uchar(key_56[1]) >> 1);
|
|
key[2] = ((to_uchar(key_56[1]) << 6) & 0xFF) | (to_uchar(key_56[2]) >> 2);
|
|
key[3] = ((to_uchar(key_56[2]) << 5) & 0xFF) | (to_uchar(key_56[3]) >> 3);
|
|
key[4] = ((to_uchar(key_56[3]) << 4) & 0xFF) | (to_uchar(key_56[4]) >> 4);
|
|
key[5] = ((to_uchar(key_56[4]) << 3) & 0xFF) | (to_uchar(key_56[5]) >> 5);
|
|
key[6] = ((to_uchar(key_56[5]) << 2) & 0xFF) | (to_uchar(key_56[6]) >> 6);
|
|
key[7] = (to_uchar(key_56[6]) << 1) & 0xFF;
|
|
|
|
gl_des_setkey(ks, key);
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
}
|
|
|
|
/*
|
|
* 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(char *hash, const char *challenge, char *answer)
|
|
{
|
|
gl_des_ctx ks;
|
|
|
|
ntlm_convert_key(hash, &ks);
|
|
gl_des_ecb_encrypt(&ks, challenge, answer);
|
|
|
|
ntlm_convert_key(&hash[7], &ks);
|
|
gl_des_ecb_encrypt(&ks, challenge, &answer[8]);
|
|
|
|
ntlm_convert_key(&hash[14], &ks);
|
|
gl_des_ecb_encrypt(&ks, challenge, &answer[16]);
|
|
|
|
memset(&ks, 0, sizeof(ks));
|
|
}
|
|
|
|
void ntlm_smb_nt_encrypt(const char *passwd, const u8 * challenge, u8 * answer)
|
|
{
|
|
size_t len, i;
|
|
unsigned char hash[24];
|
|
unsigned char nt_pw[256];
|
|
|
|
/* 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;
|
|
}
|
|
|
|
md4_buffer((const char *) nt_pw, len * 2, hash);
|
|
|
|
memset(hash + 16, 0, 5);
|
|
ntlm_encrypt_answer((char *) hash, (const char *) challenge,
|
|
(char *) answer);
|
|
|
|
/* with security is best be pedantic */
|
|
memset(hash, 0, sizeof(hash));
|
|
memset(nt_pw, 0, sizeof(nt_pw));
|
|
}
|