18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, 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)); 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ucs2_string_size) 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *ucs2_string_size = j / 2; 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (OUT) 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[3]; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = peer_challenge; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 16; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = auth_challenge; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 16; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = username; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = username_len; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr, len, hash)) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(challenge, hash, 8); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (OUT) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint nt_password_hash(const u8 *password, size_t password_len, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *password_hash) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[512], *pos; 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t len, max_len; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt max_len = sizeof(buf); 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0) 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len *= 2; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return md4_vector(1, (const u8 **) &pos, &len, password_hash); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash_hash: 16-octet PasswordHashHash (OUT) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 16; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return md4_vector(1, &password_hash, &len, password_hash_hash); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (IN) 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid challenge_response(const u8 *challenge, const u8 *password_hash, 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 zpwd[7]; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, password_hash, response); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, password_hash + 7, response + 8); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt zpwd[0] = password_hash[14]; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt zpwd[1] = password_hash[15]; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(zpwd + 2, 0, 5); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(challenge, zpwd, response + 16); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, size_t password_len, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 challenge[8]; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_hash(peer_challenge, auth_challenge, username, username_len, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_nt_response_pwhash(const u8 *auth_challenge, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 challenge[8]; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge_hash(peer_challenge, auth_challenge, 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge)) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response_pwhash( 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, const u8 *auth_challenge, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nt_response, u8 *response) 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic1[39] = { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic2[41] = { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6E 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash_hash[16], challenge[8]; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr1[3]; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len1[3] = { 16, 24, sizeof(magic1) }; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr2[3]; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[0] = password_hash_hash; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[1] = nt_response; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr1[2] = magic1; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[0] = response; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[1] = challenge; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr2[2] = magic2; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hash_nt_password_hash(password_hash, password_hash_hash)) 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr1, len1, response)) 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_hash(peer_challenge, auth_challenge, username, username_len, 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sha1_vector(3, addr2, len2, response); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response(const u8 *password, size_t password_len, 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer_challenge, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth_challenge, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, size_t username_len, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nt_response, u8 *response) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return generate_authenticator_response_pwhash( 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_hash, peer_challenge, auth_challenge, 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, response); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (IN) 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT) 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint nt_challenge_response(const u8 *challenge, const u8 *password, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t password_len, u8 *response) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(password, password_len, password_hash)) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password_hash, response); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash_hash: 16-octet PasswordHashHash (IN) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NTResponse (IN) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (OUT) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_master_key(const u8 *password_hash_hash, const u8 *nt_response, 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *master_key) 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic1[27] = { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[3]; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[3] = { 16, 24, sizeof(magic1) }; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = password_hash_hash; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = nt_response; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = magic1; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(3, addr, len, hash)) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(master_key, hash, 16); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (IN) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key: 8-to-16 octet SessionKey (OUT) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key_len: SessionKeyLength (Length of session_key) (IN) 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_send: IsSend (IN, BOOLEAN) 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_server: IsServer (IN, BOOLEAN) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_asymetric_start_key(const u8 *master_key, u8 *session_key, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t session_key_len, int is_send, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int is_server) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic2[84] = { 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x2e 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 magic3[84] = { 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x6b, 0x65, 0x79, 0x2e 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 shs_pad1[40] = { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const u8 shs_pad2[40] = { 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 digest[SHA1_MAC_LEN]; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *addr[4]; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[4] = { 16, 40, 84, 40 }; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = master_key; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = shs_pad1; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_send) { 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = is_server ? magic3 : magic2; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = is_server ? magic2 : magic3; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = shs_pad2; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_vector(4, addr, len, digest)) 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_key_len > SHA1_MAC_LEN) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_key_len = SHA1_MAC_LEN; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(session_key, digest, session_key_len); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PWBLOCK_LEN 516 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8) 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN) 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pw_block: 516-byte PwBlock (OUT) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint encrypt_pw_block_with_password_hash( 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, size_t password_len, 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password_hash, u8 *pw_block) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t ucs2_len, offset; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(pw_block, 0, PWBLOCK_LEN); 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ucs2_len > 256) 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = (256 - ucs2_len) * 2; 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (offset != 0) { 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memmove(pw_block + offset, pw_block, ucs2_len * 2); 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_get_random(pw_block, offset) < 0) 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PasswordLength is 4 octets, but since the maximum password length is 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 256, only first two (in little endian byte order) can be non-zero. 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = &pw_block[2 * 256]; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, password_len * 2); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint new_password_encrypted_with_old_nt_password_hash( 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *new_password, size_t new_password_len, 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *old_password, size_t old_password_len, 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *encrypted_pw_block) 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16]; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(old_password, old_password_len, password_hash)) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt_pw_block_with_password_hash(new_password, new_password_len, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_hash, 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypted_pw_block)) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octer PasswordHash (IN) 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @block: 16-octet Block (IN) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cypher: 16-octer Cypher (OUT) 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid nt_password_hash_encrypted_with_block(const u8 *password_hash, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *block, u8 *cypher) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(password_hash, block, cypher); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des_encrypt(password_hash + 8, block + 7, cypher + 8); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint old_nt_password_hash_encrypted_with_new_nt_password_hash( 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *new_password, size_t new_password_len, 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *old_password, size_t old_password_len, 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *encrypted_password_hash) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 old_password_hash[16], new_password_hash[16]; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nt_password_hash(old_password, old_password_len, 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_password_hash) || 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash(new_password, new_password_len, 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash)) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash_encrypted_with_block(old_password_hash, 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypted_password_hash); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 525