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