18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sha1.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ms_funcs.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding 181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @utf8_string: UTF-8 string (IN) 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @utf8_string_len: Length of utf8_string (IN) 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @ucs2_buffer: UCS-2 buffer (OUT) 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @ucs2_buffer_size: Length of UCS-2 buffer (IN) 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Returns: 0 on success, -1 on failure 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len, 261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *ucs2_buffer, size_t ucs2_buffer_size, 271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t *ucs2_string_size) 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t i, j; 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0, j = 0; i < utf8_string_len; i++) { 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 c = utf8_string[i]; 331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (j >= ucs2_buffer_size) { 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* input too long */ 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (c <= 0x7F) { 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(ucs2_buffer + j, c); 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt j += 2; 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (i == utf8_string_len - 1 || 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt j >= ucs2_buffer_size - 1) { 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* incomplete surrogate */ 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 c2 = utf8_string[++i]; 461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((c & 0xE0) == 0xC0) { 471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* two-byte encoding */ 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(ucs2_buffer + j, 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ((c & 0x1F) << 6) | (c2 & 0x3F)); 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt j += 2; 511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (i == utf8_string_len || 521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt j >= ucs2_buffer_size - 1) { 531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* incomplete surrogate */ 541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* three-byte encoding */ 571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 c3 = utf8_string[++i]; 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(ucs2_buffer + j, 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ((c & 0xF) << 12) | 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ((c2 & 0x3F) << 6) | (c3 & 0x3F)); 61bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt j += 2; 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ucs2_string_size) 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *ucs2_string_size = j / 2; 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (OUT) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[3]; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = peer_challenge; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 16; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = auth_challenge; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 16; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = username; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = username_len; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr, len, hash)) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(challenge, hash, 8); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (OUT) 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint nt_password_hash(const u8 *password, size_t password_len, 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *password_hash) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[512], *pos; 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t len, max_len; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt max_len = sizeof(buf); 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0) 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len *= 2; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return md4_vector(1, (const u8 **) &pos, &len, password_hash); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash_hash: 16-octet PasswordHashHash (OUT) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 16; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return md4_vector(1, &password_hash, &len, password_hash_hash); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (IN) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid challenge_response(const u8 *challenge, const u8 *password_hash, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 zpwd[7]; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, password_hash, response); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, password_hash + 7, response + 8); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt zpwd[0] = password_hash[14]; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt zpwd[1] = password_hash[15]; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(zpwd + 2, 0, 5); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, zpwd, response + 16); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, size_t password_len, 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 challenge[8]; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (challenge_hash(peer_challenge, auth_challenge, username, 17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username_len, challenge)) 17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_nt_response_pwhash(const u8 *auth_challenge, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 challenge[8]; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge_hash(peer_challenge, auth_challenge, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge)) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response_pwhash( 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, const u8 *auth_challenge, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nt_response, u8 *response) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic1[39] = { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic2[41] = { 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6E 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash_hash[16], challenge[8]; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr1[3]; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len1[3] = { 16, 24, sizeof(magic1) }; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr2[3]; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[0] = password_hash_hash; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[1] = nt_response; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[2] = magic1; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[0] = response; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[1] = challenge; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[2] = magic2; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hash_nt_password_hash(password_hash, password_hash_hash)) 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr1, len1, response)) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (challenge_hash(peer_challenge, auth_challenge, username, 26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt username_len, challenge)) 26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sha1_vector(3, addr2, len2, response); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response(const u8 *password, size_t password_len, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth_challenge, 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nt_response, u8 *response) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return generate_authenticator_response_pwhash( 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_hash, peer_challenge, auth_challenge, 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, response); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (IN) 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint nt_challenge_response(const u8 *challenge, const u8 *password, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t password_len, u8 *response) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash_hash: 16-octet PasswordHashHash (IN) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NTResponse (IN) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (OUT) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_master_key(const u8 *password_hash_hash, const u8 *nt_response, 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *master_key) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic1[27] = { 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[3]; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[3] = { 16, 24, sizeof(magic1) }; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = password_hash_hash; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = nt_response; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = magic1; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr, len, hash)) 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(master_key, hash, 16); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (IN) 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key: 8-to-16 octet SessionKey (OUT) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key_len: SessionKeyLength (Length of session_key) (IN) 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_send: IsSend (IN, BOOLEAN) 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_server: IsServer (IN, BOOLEAN) 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_asymetric_start_key(const u8 *master_key, u8 *session_key, 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t session_key_len, int is_send, 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int is_server) 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic2[84] = { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x2e 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic3[84] = { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x2e 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 shs_pad1[40] = { 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 shs_pad2[40] = { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 digest[SHA1_MAC_LEN]; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[4]; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[4] = { 16, 40, 84, 40 }; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = master_key; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = shs_pad1; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_send) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = is_server ? magic3 : magic2; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = is_server ? magic2 : magic3; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = shs_pad2; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(4, addr, len, digest)) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_key_len > SHA1_MAC_LEN) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_key_len = SHA1_MAC_LEN; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(session_key, digest, session_key_len); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PWBLOCK_LEN 516 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pw_block: 516-byte PwBlock (OUT) 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint encrypt_pw_block_with_password_hash( 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, size_t password_len, 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, u8 *pw_block) 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t ucs2_len, offset; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(pw_block, 0, PWBLOCK_LEN); 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0) 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ucs2_len > 256) 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = (256 - ucs2_len) * 2; 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (offset != 0) { 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memmove(pw_block + offset, pw_block, ucs2_len * 2); 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_get_random(pw_block, offset) < 0) 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PasswordLength is 4 octets, but since the maximum password length is 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 256, only first two (in little endian byte order) can be non-zero. 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = &pw_block[2 * 256]; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, password_len * 2); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8) 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password 4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint new_password_encrypted_with_old_nt_password_hash( 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *new_password, size_t new_password_len, 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *old_password, size_t old_password_len, 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *encrypted_pw_block) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(old_password, old_password_len, password_hash)) 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt_pw_block_with_password_hash(new_password, new_password_len, 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_hash, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypted_pw_block)) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octer PasswordHash (IN) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @block: 16-octet Block (IN) 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cypher: 16-octer Cypher (OUT) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid nt_password_hash_encrypted_with_block(const u8 *password_hash, 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *block, u8 *cypher) 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(password_hash, block, cypher); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(password_hash + 8, block + 7, cypher + 8); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8) 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint old_nt_password_hash_encrypted_with_new_nt_password_hash( 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *new_password, size_t new_password_len, 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *old_password, size_t old_password_len, 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *encrypted_password_hash) 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 old_password_hash[16], new_password_hash[16]; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(old_password, old_password_len, 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_password_hash) || 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash(new_password, new_password_len, 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash)) 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash_encrypted_with_block(old_password_hash, 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypted_password_hash); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528