ntlm-encrypt.c revision 7d85c4e4e727a48ba7f6d6e6522de8338240ad74
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/*
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * NTLM and NTLMv2 hash generation.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen *
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen *
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * This library is free software; you can redistribute it and/or modify
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * it under the terms of the GNU Lesser General Public License as published
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * by the Free Software Foundation; either version 2 of the License, or
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * (at your option) any later version.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "lib.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "buffer.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "compat.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "safe-memset.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "md4.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "hmac-md5.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "ntlm.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "ntlm-des.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
0729d22d8f7be5b40f34748279183820a81aa851Timo Sirainen#include <ctype.h>
0729d22d8f7be5b40f34748279183820a81aa851Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic unsigned char *
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainent_unicode_str(const char *src, int ucase, size_t *size)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen buffer_t *wstr;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen wstr = buffer_create_dynamic(unsafe_data_stack_pool, 32, (size_t)-1);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen for ( ; *src; src++) {
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen buffer_append_c(wstr, ucase ? i_toupper(*src) : *src);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen buffer_append_c(wstr, '\0');
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen *size = buffer_get_used_size(wstr);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen return buffer_free_without_data(wstr);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainenconst unsigned char *
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainenlm_hash(const char *passwd, unsigned char hash[LM_HASH_SIZE])
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen{
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen static const unsigned char lm_magic[8] = "KGS!@#$%";
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen unsigned char buffer[14];
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen unsigned int i;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen strncpy(buffer, passwd, sizeof(buffer));
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen for (i = 0; i < sizeof(buffer); i++)
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen buffer[i] = i_toupper(buffer[i]);
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen deshash(hash, buffer, lm_magic);
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen deshash(hash + 8, buffer + 7, lm_magic);
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen safe_memset(buffer, 0, sizeof(buffer));
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen return hash;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen}
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenconst unsigned char *
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenntlm_v1_hash(const char *passwd, unsigned char hash[NTLMSSP_HASH_SIZE])
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen size_t len;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen void *wpwd = t_unicode_str(passwd, 0, &len);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen md4_get_digest(wpwd, len, hash);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen safe_memset(wpwd, 0, len);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen return hash;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic void
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenhmac_md5_ucs2le_string_ucase(struct hmac_md5_context *ctx, const char *str)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen size_t len;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char *wstr = t_unicode_str(str, 1, &len);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_update(ctx, wstr, len);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic void
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenntlm_v2_hash(const char *user, const char *target,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *hash_v1,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char hash[NTLMSSP_V2_HASH_SIZE])
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen struct hmac_md5_context ctx;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_ucs2le_string_ucase(&ctx, user);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (target)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_ucs2le_string_ucase(&ctx, target);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_final(&ctx, hash);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenvoid
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenntlmssp_v1_response(const unsigned char *hash,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *challenge,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char response[NTLMSSP_RESPONSE_SIZE])
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char des_hash[NTLMSSP_DES_KEY_LENGTH * 3];
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen memcpy(des_hash, hash, NTLMSSP_HASH_SIZE);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen memset(des_hash + NTLMSSP_HASH_SIZE, 0,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen sizeof(des_hash) - NTLMSSP_HASH_SIZE);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen deshash(response, des_hash, challenge);
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen deshash(response + 8, des_hash + 7, challenge);
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen deshash(response + 16, des_hash + 14, challenge);
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen safe_memset(des_hash, 0, sizeof(des_hash));
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenvoid
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenntlmssp_v2_response(const char *user, const char *target,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *hash_v1,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *challenge,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *blob, size_t blob_size,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char response[NTLMSSP_V2_RESPONSE_SIZE])
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen struct hmac_md5_context ctx;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char hash[NTLMSSP_V2_HASH_SIZE];
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen ntlm_v2_hash(user, target, hash_v1, hash);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_update(&ctx, blob, blob_size);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hmac_md5_final(&ctx, response);
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen
7d85c4e4e727a48ba7f6d6e6522de8338240ad74Timo Sirainen safe_memset(hash, 0, sizeof(hash));
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}