Changeset View
Changeset View
Standalone View
Standalone View
crypto/heimdal/lib/ntlm/ntlm.c
Show First 20 Lines • Show All 1,005 Lines • ▼ Show 20 Lines | out: | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* | * | ||||
*/ | */ | ||||
static void | static int | ||||
splitandenc(unsigned char *hash, | splitandenc(unsigned char *hash, | ||||
unsigned char *challenge, | unsigned char *challenge, | ||||
unsigned char *answer) | unsigned char *answer) | ||||
{ | { | ||||
EVP_CIPHER_CTX ctx; | EVP_CIPHER_CTX *ctx; | ||||
unsigned char key[8]; | unsigned char key[8]; | ||||
key[0] = hash[0]; | key[0] = hash[0]; | ||||
key[1] = (hash[0] << 7) | (hash[1] >> 1); | key[1] = (hash[0] << 7) | (hash[1] >> 1); | ||||
key[2] = (hash[1] << 6) | (hash[2] >> 2); | key[2] = (hash[1] << 6) | (hash[2] >> 2); | ||||
key[3] = (hash[2] << 5) | (hash[3] >> 3); | key[3] = (hash[2] << 5) | (hash[3] >> 3); | ||||
key[4] = (hash[3] << 4) | (hash[4] >> 4); | key[4] = (hash[3] << 4) | (hash[4] >> 4); | ||||
key[5] = (hash[4] << 3) | (hash[5] >> 5); | key[5] = (hash[4] << 3) | (hash[5] >> 5); | ||||
key[6] = (hash[5] << 2) | (hash[6] >> 6); | key[6] = (hash[5] << 2) | (hash[6] >> 6); | ||||
key[7] = (hash[6] << 1); | key[7] = (hash[6] << 1); | ||||
EVP_CIPHER_CTX_init(&ctx); | ctx = EVP_CIPHER_CTX_new(); | ||||
if (ctx == NULL) | |||||
return ENOMEM; | |||||
EVP_CipherInit_ex(&ctx, EVP_des_cbc(), NULL, key, NULL, 1); | EVP_CipherInit_ex(ctx, EVP_des_cbc(), NULL, key, NULL, 1); | ||||
EVP_Cipher(&ctx, answer, challenge, 8); | EVP_Cipher(ctx, answer, challenge, 8); | ||||
EVP_CIPHER_CTX_cleanup(&ctx); | EVP_CIPHER_CTX_free(ctx); | ||||
memset(key, 0, sizeof(key)); | memset(key, 0, sizeof(key)); | ||||
return 0; | |||||
} | } | ||||
/** | /** | ||||
* Calculate the NTLM key, the password is assumed to be in UTF8. | * Calculate the NTLM key, the password is assumed to be in UTF8. | ||||
* | * | ||||
* @param password password to calcute the key for. | * @param password password to calcute the key for. | ||||
* @param key calcuted key, should be freed with heim_ntlm_free_buf(). | * @param key calcuted key, should be freed with heim_ntlm_free_buf(). | ||||
* | * | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
heim_ntlm_calculate_ntlm1(void *key, size_t len, | heim_ntlm_calculate_ntlm1(void *key, size_t len, | ||||
unsigned char challenge[8], | unsigned char challenge[8], | ||||
struct ntlm_buf *answer) | struct ntlm_buf *answer) | ||||
{ | { | ||||
unsigned char res[21]; | unsigned char res[21]; | ||||
int ret; | |||||
if (len != MD4_DIGEST_LENGTH) | if (len != MD4_DIGEST_LENGTH) | ||||
return HNTLM_ERR_INVALID_LENGTH; | return HNTLM_ERR_INVALID_LENGTH; | ||||
memcpy(res, key, len); | memcpy(res, key, len); | ||||
memset(&res[MD4_DIGEST_LENGTH], 0, sizeof(res) - MD4_DIGEST_LENGTH); | memset(&res[MD4_DIGEST_LENGTH], 0, sizeof(res) - MD4_DIGEST_LENGTH); | ||||
answer->data = malloc(24); | answer->data = malloc(24); | ||||
if (answer->data == NULL) | if (answer->data == NULL) | ||||
return ENOMEM; | return ENOMEM; | ||||
answer->length = 24; | answer->length = 24; | ||||
splitandenc(&res[0], challenge, ((unsigned char *)answer->data) + 0); | ret = splitandenc(&res[0], challenge, ((unsigned char *)answer->data) + 0); | ||||
splitandenc(&res[7], challenge, ((unsigned char *)answer->data) + 8); | if (ret) | ||||
splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16); | goto out; | ||||
ret = splitandenc(&res[7], challenge, ((unsigned char *)answer->data) + 8); | |||||
if (ret) | |||||
goto out; | |||||
ret = splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16); | |||||
if (ret) | |||||
goto out; | |||||
return 0; | return 0; | ||||
out: | |||||
free(answer->data); | |||||
answer->data = NULL; | |||||
bjk: Probably cleanest to also zero answer->length here. | |||||
Done Inline ActionsI went ahead and used heim_ntlm_free_buf() since it is already used elsewhere in this file. jhb: I went ahead and used heim_ntlm_free_buf() since it is already used elsewhere in this file. | |||||
return ret; | |||||
} | } | ||||
int | int | ||||
heim_ntlm_v1_base_session(void *key, size_t len, | heim_ntlm_v1_base_session(void *key, size_t len, | ||||
struct ntlm_buf *session) | struct ntlm_buf *session) | ||||
{ | { | ||||
EVP_MD_CTX *m; | EVP_MD_CTX *m; | ||||
Show All 18 Lines | |||||
} | } | ||||
int | int | ||||
heim_ntlm_v2_base_session(void *key, size_t len, | heim_ntlm_v2_base_session(void *key, size_t len, | ||||
struct ntlm_buf *ntlmResponse, | struct ntlm_buf *ntlmResponse, | ||||
struct ntlm_buf *session) | struct ntlm_buf *session) | ||||
{ | { | ||||
unsigned int hmaclen; | unsigned int hmaclen; | ||||
HMAC_CTX c; | HMAC_CTX *c; | ||||
if (ntlmResponse->length <= 16) | if (ntlmResponse->length <= 16) | ||||
return HNTLM_ERR_INVALID_LENGTH; | return HNTLM_ERR_INVALID_LENGTH; | ||||
session->data = malloc(16); | session->data = malloc(16); | ||||
if (session->data == NULL) | if (session->data == NULL) | ||||
return ENOMEM; | return ENOMEM; | ||||
session->length = 16; | session->length = 16; | ||||
/* Note: key is the NTLMv2 key */ | /* Note: key is the NTLMv2 key */ | ||||
HMAC_CTX_init(&c); | c = HMAC_CTX_new(); | ||||
HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); | if (c == NULL) { | ||||
HMAC_Update(&c, ntlmResponse->data, 16); | free(session->data); | ||||
HMAC_Final(&c, session->data, &hmaclen); | session->data = NULL; | ||||
Done Inline ActionsProbably cleanest to zero session->length. bjk: Probably cleanest to zero session->length.
I guess there's heim_ntlm_free_buf()? | |||||
HMAC_CTX_cleanup(&c); | return ENOMEM; | ||||
} | |||||
HMAC_Init_ex(c, key, len, EVP_md5(), NULL); | |||||
HMAC_Update(c, ntlmResponse->data, 16); | |||||
HMAC_Final(c, session->data, &hmaclen); | |||||
HMAC_CTX_free(c); | |||||
return 0; | return 0; | ||||
} | } | ||||
int | int | ||||
heim_ntlm_keyex_wrap(struct ntlm_buf *base_session, | heim_ntlm_keyex_wrap(struct ntlm_buf *base_session, | ||||
struct ntlm_buf *session, | struct ntlm_buf *session, | ||||
struct ntlm_buf *encryptedSession) | struct ntlm_buf *encryptedSession) | ||||
{ | { | ||||
EVP_CIPHER_CTX c; | EVP_CIPHER_CTX *c; | ||||
int ret; | int ret; | ||||
session->length = MD4_DIGEST_LENGTH; | session->length = MD4_DIGEST_LENGTH; | ||||
session->data = malloc(session->length); | session->data = malloc(session->length); | ||||
if (session->data == NULL) { | if (session->data == NULL) { | ||||
session->length = 0; | session->length = 0; | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
encryptedSession->length = MD4_DIGEST_LENGTH; | encryptedSession->length = MD4_DIGEST_LENGTH; | ||||
encryptedSession->data = malloc(encryptedSession->length); | encryptedSession->data = malloc(encryptedSession->length); | ||||
if (encryptedSession->data == NULL) { | if (encryptedSession->data == NULL) { | ||||
heim_ntlm_free_buf(session); | heim_ntlm_free_buf(session); | ||||
encryptedSession->length = 0; | encryptedSession->length = 0; | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
EVP_CIPHER_CTX_init(&c); | c = EVP_CIPHER_CTX_new(); | ||||
if (c == NULL) { | |||||
heim_ntlm_free_buf(encryptedSession); | |||||
heim_ntlm_free_buf(session); | |||||
return ENOMEM; | |||||
} | |||||
ret = EVP_CipherInit_ex(&c, EVP_rc4(), NULL, base_session->data, NULL, 1); | ret = EVP_CipherInit_ex(c, EVP_rc4(), NULL, base_session->data, NULL, 1); | ||||
if (ret != 1) { | if (ret != 1) { | ||||
EVP_CIPHER_CTX_cleanup(&c); | EVP_CIPHER_CTX_free(c); | ||||
heim_ntlm_free_buf(encryptedSession); | heim_ntlm_free_buf(encryptedSession); | ||||
heim_ntlm_free_buf(session); | heim_ntlm_free_buf(session); | ||||
return HNTLM_ERR_CRYPTO; | return HNTLM_ERR_CRYPTO; | ||||
} | } | ||||
if (RAND_bytes(session->data, session->length) != 1) { | if (RAND_bytes(session->data, session->length) != 1) { | ||||
EVP_CIPHER_CTX_cleanup(&c); | EVP_CIPHER_CTX_free(c); | ||||
heim_ntlm_free_buf(encryptedSession); | heim_ntlm_free_buf(encryptedSession); | ||||
heim_ntlm_free_buf(session); | heim_ntlm_free_buf(session); | ||||
return HNTLM_ERR_RAND; | return HNTLM_ERR_RAND; | ||||
} | } | ||||
EVP_Cipher(&c, encryptedSession->data, session->data, encryptedSession->length); | EVP_Cipher(c, encryptedSession->data, session->data, encryptedSession->length); | ||||
EVP_CIPHER_CTX_cleanup(&c); | EVP_CIPHER_CTX_free(c); | ||||
return 0; | return 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
* @ingroup ntlm_core | * @ingroup ntlm_core | ||||
*/ | */ | ||||
int | int | ||||
heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey, | heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey, | ||||
struct ntlm_buf *encryptedSession, | struct ntlm_buf *encryptedSession, | ||||
struct ntlm_buf *session) | struct ntlm_buf *session) | ||||
{ | { | ||||
EVP_CIPHER_CTX c; | EVP_CIPHER_CTX *c; | ||||
memset(session, 0, sizeof(*session)); | memset(session, 0, sizeof(*session)); | ||||
if (baseKey->length != MD4_DIGEST_LENGTH) | if (baseKey->length != MD4_DIGEST_LENGTH) | ||||
return HNTLM_ERR_INVALID_LENGTH; | return HNTLM_ERR_INVALID_LENGTH; | ||||
session->length = MD4_DIGEST_LENGTH; | session->length = MD4_DIGEST_LENGTH; | ||||
session->data = malloc(session->length); | session->data = malloc(session->length); | ||||
if (session->data == NULL) { | if (session->data == NULL) { | ||||
session->length = 0; | session->length = 0; | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
EVP_CIPHER_CTX_init(&c); | c = EVP_CIPHER_CTX_new(); | ||||
if (c == NULL) { | |||||
heim_ntlm_free_buf(session); | |||||
return ENOMEM; | |||||
} | |||||
if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) { | if (EVP_CipherInit_ex(c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) { | ||||
EVP_CIPHER_CTX_cleanup(&c); | EVP_CIPHER_CTX_free(c); | ||||
heim_ntlm_free_buf(session); | heim_ntlm_free_buf(session); | ||||
return HNTLM_ERR_CRYPTO; | return HNTLM_ERR_CRYPTO; | ||||
} | } | ||||
EVP_Cipher(&c, session->data, encryptedSession->data, session->length); | EVP_Cipher(c, session->data, encryptedSession->data, session->length); | ||||
EVP_CIPHER_CTX_cleanup(&c); | EVP_CIPHER_CTX_free(c); | ||||
return 0; | return 0; | ||||
} | } | ||||
/** | /** | ||||
* Generates an NTLMv2 session key. | * Generates an NTLMv2 session key. | ||||
* | * | ||||
Show All 11 Lines | |||||
int | int | ||||
heim_ntlm_ntlmv2_key(const void *key, size_t len, | heim_ntlm_ntlmv2_key(const void *key, size_t len, | ||||
const char *username, | const char *username, | ||||
const char *target, | const char *target, | ||||
unsigned char ntlmv2[16]) | unsigned char ntlmv2[16]) | ||||
{ | { | ||||
int ret; | int ret; | ||||
unsigned int hmaclen; | unsigned int hmaclen; | ||||
HMAC_CTX c; | HMAC_CTX *c; | ||||
HMAC_CTX_init(&c); | c = HMAC_CTX_new(); | ||||
HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); | if (c == NULL) | ||||
return ENOMEM; | |||||
HMAC_Init_ex(c, key, len, EVP_md5(), NULL); | |||||
{ | { | ||||
struct ntlm_buf buf; | struct ntlm_buf buf; | ||||
/* uppercase username and turn it into ucs2-le */ | /* uppercase username and turn it into ucs2-le */ | ||||
ret = ascii2ucs2le(username, 1, &buf); | ret = ascii2ucs2le(username, 1, &buf); | ||||
if (ret) | if (ret) | ||||
goto out; | goto out; | ||||
HMAC_Update(&c, buf.data, buf.length); | HMAC_Update(c, buf.data, buf.length); | ||||
free(buf.data); | free(buf.data); | ||||
/* uppercase target and turn into ucs2-le */ | /* uppercase target and turn into ucs2-le */ | ||||
ret = ascii2ucs2le(target, 1, &buf); | ret = ascii2ucs2le(target, 1, &buf); | ||||
if (ret) | if (ret) | ||||
goto out; | goto out; | ||||
HMAC_Update(&c, buf.data, buf.length); | HMAC_Update(c, buf.data, buf.length); | ||||
free(buf.data); | free(buf.data); | ||||
} | } | ||||
HMAC_Final(&c, ntlmv2, &hmaclen); | HMAC_Final(c, ntlmv2, &hmaclen); | ||||
out: | out: | ||||
HMAC_CTX_cleanup(&c); | HMAC_CTX_free(c); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* | * | ||||
*/ | */ | ||||
Show All 37 Lines | |||||
heim_ntlm_calculate_lm2(const void *key, size_t len, | heim_ntlm_calculate_lm2(const void *key, size_t len, | ||||
const char *username, | const char *username, | ||||
const char *target, | const char *target, | ||||
const unsigned char serverchallenge[8], | const unsigned char serverchallenge[8], | ||||
unsigned char ntlmv2[16], | unsigned char ntlmv2[16], | ||||
struct ntlm_buf *answer) | struct ntlm_buf *answer) | ||||
{ | { | ||||
unsigned char clientchallenge[8]; | unsigned char clientchallenge[8]; | ||||
int ret; | |||||
if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) | if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) | ||||
return HNTLM_ERR_RAND; | return HNTLM_ERR_RAND; | ||||
/* calculate ntlmv2 key */ | /* calculate ntlmv2 key */ | ||||
heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2); | heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2); | ||||
answer->data = malloc(24); | answer->data = malloc(24); | ||||
if (answer->data == NULL) | if (answer->data == NULL) | ||||
return ENOMEM; | return ENOMEM; | ||||
answer->length = 24; | answer->length = 24; | ||||
heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, | ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, | ||||
serverchallenge, answer->data); | serverchallenge, answer->data); | ||||
if (ret) | |||||
return ret; | |||||
memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8); | memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8); | ||||
return 0; | return 0; | ||||
} | } | ||||
/** | /** | ||||
Show All 24 Lines | heim_ntlm_calculate_ntlm2(const void *key, size_t len, | ||||
struct ntlm_buf *answer) | struct ntlm_buf *answer) | ||||
{ | { | ||||
krb5_error_code ret; | krb5_error_code ret; | ||||
krb5_data data; | krb5_data data; | ||||
unsigned char ntlmv2answer[16]; | unsigned char ntlmv2answer[16]; | ||||
krb5_storage *sp; | krb5_storage *sp; | ||||
unsigned char clientchallenge[8]; | unsigned char clientchallenge[8]; | ||||
uint64_t t; | uint64_t t; | ||||
int code; | |||||
t = unix2nttime(time(NULL)); | t = unix2nttime(time(NULL)); | ||||
if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) | if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) | ||||
return HNTLM_ERR_RAND; | return HNTLM_ERR_RAND; | ||||
/* calculate ntlmv2 key */ | /* calculate ntlmv2 key */ | ||||
Show All 18 Lines | return ENOMEM; | ||||
CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length), | CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length), | ||||
infotarget->length); | infotarget->length); | ||||
CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */ | CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */ | ||||
CHECK(krb5_storage_to_data(sp, &data), 0); | CHECK(krb5_storage_to_data(sp, &data), 0); | ||||
krb5_storage_free(sp); | krb5_storage_free(sp); | ||||
sp = NULL; | sp = NULL; | ||||
heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer); | code = heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer); | ||||
if (code) | |||||
return code; | |||||
Done Inline ActionsThis leaks data.data; need to krb5_data_free(&data) bjk: This leaks data.data; need to krb5_data_free(&data) | |||||
sp = krb5_storage_emem(); | sp = krb5_storage_emem(); | ||||
if (sp == NULL) { | if (sp == NULL) { | ||||
krb5_data_free(&data); | krb5_data_free(&data); | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
CHECK(krb5_storage_write(sp, ntlmv2answer, 16), 16); | CHECK(krb5_storage_write(sp, ntlmv2answer, 16), 16); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | heim_ntlm_verify_ntlm2(const void *key, size_t len, | ||||
krb5_error_code ret; | krb5_error_code ret; | ||||
unsigned char clientanswer[16]; | unsigned char clientanswer[16]; | ||||
unsigned char clientnonce[8]; | unsigned char clientnonce[8]; | ||||
unsigned char serveranswer[16]; | unsigned char serveranswer[16]; | ||||
krb5_storage *sp; | krb5_storage *sp; | ||||
time_t authtime; | time_t authtime; | ||||
uint32_t temp; | uint32_t temp; | ||||
uint64_t t; | uint64_t t; | ||||
int code; | |||||
infotarget->length = 0; | infotarget->length = 0; | ||||
infotarget->data = NULL; | infotarget->data = NULL; | ||||
if (answer->length < 16) | if (answer->length < 16) | ||||
return HNTLM_ERR_INVALID_LENGTH; | return HNTLM_ERR_INVALID_LENGTH; | ||||
if (now == 0) | if (now == 0) | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | goto out; | ||||
krb5_storage_free(sp); | krb5_storage_free(sp); | ||||
sp = NULL; | sp = NULL; | ||||
if (answer->length < 16) { | if (answer->length < 16) { | ||||
ret = HNTLM_ERR_INVALID_LENGTH; | ret = HNTLM_ERR_INVALID_LENGTH; | ||||
goto out; | goto out; | ||||
} | } | ||||
heim_ntlm_derive_ntlm2_sess(ntlmv2, | code = heim_ntlm_derive_ntlm2_sess(ntlmv2, | ||||
((unsigned char *)answer->data) + 16, answer->length - 16, | ((unsigned char *)answer->data) + 16, answer->length - 16, | ||||
serverchallenge, | serverchallenge, | ||||
serveranswer); | serveranswer); | ||||
if (code) | |||||
return code; | |||||
Done Inline Actionsheim_ntlm_free_buf(infotarget) bjk: heim_ntlm_free_buf(infotarget) | |||||
Done Inline ActionsI chose to reuse the 'out' label similar to the error case a few lines above. jhb: I chose to reuse the 'out' label similar to the error case a few lines above. | |||||
if (memcmp(serveranswer, clientanswer, 16) != 0) { | if (memcmp(serveranswer, clientanswer, 16) != 0) { | ||||
heim_ntlm_free_buf(infotarget); | heim_ntlm_free_buf(infotarget); | ||||
return HNTLM_ERR_AUTH; | return HNTLM_ERR_AUTH; | ||||
} | } | ||||
return 0; | return 0; | ||||
out: | out: | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | return ENOMEM; | ||||
/* first setup the lm resp */ | /* first setup the lm resp */ | ||||
memset(lm->data, 0, 24); | memset(lm->data, 0, 24); | ||||
memcpy(lm->data, clnt_nonce, 8); | memcpy(lm->data, clnt_nonce, 8); | ||||
memset(res, 0, sizeof(res)); | memset(res, 0, sizeof(res)); | ||||
memcpy(res, ntlm_hash, 16); | memcpy(res, ntlm_hash, 16); | ||||
resp = ntlm->data; | resp = ntlm->data; | ||||
splitandenc(&res[0], ntlm2_sess_hash, resp + 0); | code = splitandenc(&res[0], ntlm2_sess_hash, resp + 0); | ||||
splitandenc(&res[7], ntlm2_sess_hash, resp + 8); | if (code) | ||||
splitandenc(&res[14], ntlm2_sess_hash, resp + 16); | goto out; | ||||
code = splitandenc(&res[7], ntlm2_sess_hash, resp + 8); | |||||
if (code) | |||||
goto out; | |||||
code = splitandenc(&res[14], ntlm2_sess_hash, resp + 16); | |||||
if (code) | |||||
goto out; | |||||
return 0; | return 0; | ||||
out: | |||||
free(ntlm->data); | |||||
ntlm->data = NULL; | |||||
free(lm->data); | |||||
lm->data = NULL; | |||||
Done Inline Actionsheim_ntlm_free_buf() will zero the length as well (for both ntlm and lm) bjk: heim_ntlm_free_buf() will zero the length as well (for both ntlm and lm) | |||||
return code; | |||||
} | } | ||||
/* | /* | ||||
* Calculate the NTLM2 Session "Verifier" | * Calculate the NTLM2 Session "Verifier" | ||||
* | * | ||||
* @param clnt_nonce client nonce | * @param clnt_nonce client nonce | ||||
* @param svr_chal server challage | * @param svr_chal server challage | ||||
Show All 38 Lines | |||||
* @param derivedkey salted session key | * @param derivedkey salted session key | ||||
* | * | ||||
* @return In case of success 0 is return, an errors, a errno in what | * @return In case of success 0 is return, an errors, a errno in what | ||||
* went wrong. | * went wrong. | ||||
* | * | ||||
* @ingroup ntlm_core | * @ingroup ntlm_core | ||||
*/ | */ | ||||
void | int | ||||
heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], | heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], | ||||
const unsigned char *clnt_nonce, size_t clnt_nonce_length, | const unsigned char *clnt_nonce, size_t clnt_nonce_length, | ||||
const unsigned char svr_chal[8], | const unsigned char svr_chal[8], | ||||
unsigned char derivedkey[16]) | unsigned char derivedkey[16]) | ||||
{ | { | ||||
unsigned int hmaclen; | unsigned int hmaclen; | ||||
HMAC_CTX c; | HMAC_CTX *c; | ||||
/* HMAC(Ksession, serverchallenge || clientchallenge) */ | /* HMAC(Ksession, serverchallenge || clientchallenge) */ | ||||
HMAC_CTX_init(&c); | c = HMAC_CTX_new(); | ||||
HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL); | if (c == NULL) | ||||
HMAC_Update(&c, svr_chal, 8); | return ENOMEM; | ||||
HMAC_Update(&c, clnt_nonce, clnt_nonce_length); | HMAC_Init_ex(c, sessionkey, 16, EVP_md5(), NULL); | ||||
HMAC_Final(&c, derivedkey, &hmaclen); | HMAC_Update(c, svr_chal, 8); | ||||
HMAC_CTX_cleanup(&c); | HMAC_Update(c, clnt_nonce, clnt_nonce_length); | ||||
HMAC_Final(c, derivedkey, &hmaclen); | |||||
HMAC_CTX_free(c); | |||||
return 0; | |||||
} | } | ||||
Probably cleanest to also zero answer->length here.