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));
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
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (challenge_hash(peer_challenge, auth_challenge, username,
17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   username_len, challenge))
17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nt_password_hash(password, password_len, password_hash))
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	challenge_response(challenge, password_hash, response);
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN)
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN)
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN)
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT)
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_nt_response_pwhash(const u8 *auth_challenge,
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *peer_challenge,
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *username, size_t username_len,
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *password_hash,
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u8 *response)
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 challenge[8];
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (challenge_hash(peer_challenge, auth_challenge,
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   username, username_len,
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   challenge))
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	challenge_response(challenge, password_hash, response);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN)
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN)
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN)
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response)
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response_pwhash(
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *password_hash,
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *peer_challenge, const u8 *auth_challenge,
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *username, size_t username_len,
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *nt_response, u8 *response)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 magic1[39] = {
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 magic2[41] = {
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x6E
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 password_hash_hash[16], challenge[8];
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const unsigned char *addr1[3];
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t len1[3] = { 16, 24, sizeof(magic1) };
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const unsigned char *addr2[3];
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr1[0] = password_hash_hash;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr1[1] = nt_response;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr1[2] = magic1;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr2[0] = response;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr2[1] = challenge;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr2[2] = magic2;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hash_nt_password_hash(password_hash, password_hash_hash))
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sha1_vector(3, addr1, len1, response))
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (challenge_hash(peer_challenge, auth_challenge, username,
26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   username_len, challenge))
26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sha1_vector(3, addr2, len2, response);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8)
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NT-Response (IN)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_challenge: 16-octet PeerChallenge (IN)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username: 0-to-256-char UserName (IN)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @username_len: Length of username
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encoded as a 42-octet ASCII string (S=hexdump_of_response)
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint generate_authenticator_response(const u8 *password, size_t password_len,
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *peer_challenge,
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *auth_challenge,
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *username, size_t username_len,
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *nt_response, u8 *response)
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 password_hash[16];
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nt_password_hash(password, password_len, password_hash))
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return generate_authenticator_response_pwhash(
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		password_hash, peer_challenge, auth_challenge,
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		username, username_len, nt_response, response);
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @challenge: 8-octet Challenge (IN)
3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @response: 24-octet Response (OUT)
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint nt_challenge_response(const u8 *challenge, const u8 *password,
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t password_len, u8 *response)
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 password_hash[16];
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nt_password_hash(password, password_len, password_hash))
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	challenge_response(challenge, password_hash, response);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash_hash: 16-octet PasswordHashHash (IN)
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nt_response: 24-octet NTResponse (IN)
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (OUT)
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   u8 *master_key)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 magic1[27] = {
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const unsigned char *addr[3];
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t len[3] = { 16, 24, sizeof(magic1) };
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[SHA1_MAC_LEN];
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[0] = password_hash_hash;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[1] = nt_response;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[2] = magic1;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sha1_vector(3, addr, len, hash))
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(master_key, hash, 16);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @master_key: 16-octet MasterKey (IN)
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key: 8-to-16 octet SessionKey (OUT)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_key_len: SessionKeyLength (Length of session_key) (IN)
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_send: IsSend (IN, BOOLEAN)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @is_server: IsServer (IN, BOOLEAN)
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint get_asymetric_start_key(const u8 *master_key, u8 *session_key,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    size_t session_key_len, int is_send,
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    int is_server)
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 magic2[84] = {
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x6b, 0x65, 0x79, 0x2e
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 magic3[84] = {
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x6b, 0x65, 0x79, 0x2e
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 shs_pad1[40] = {
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		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 shs_pad2[40] = {
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		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 digest[SHA1_MAC_LEN];
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const unsigned char *addr[4];
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const size_t len[4] = { 16, 40, 84, 40 };
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[0] = master_key;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[1] = shs_pad1;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_send) {
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[2] = is_server ? magic3 : magic2;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[2] = is_server ? magic2 : magic3;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr[3] = shs_pad2;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sha1_vector(4, addr, len, digest))
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (session_key_len > SHA1_MAC_LEN)
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		session_key_len = SHA1_MAC_LEN;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(session_key, digest, session_key_len);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PWBLOCK_LEN 516
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @password: 0-to-256-unicode-char Password (IN; UTF-8)
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_len: Length of password
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octet PasswordHash (IN)
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pw_block: 516-byte PwBlock (OUT)
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint encrypt_pw_block_with_password_hash(
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *password, size_t password_len,
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *password_hash, u8 *pw_block)
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t ucs2_len, offset;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(pw_block, 0, PWBLOCK_LEN);
4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ucs2_len > 256)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	offset = (256 - ucs2_len) * 2;
4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (offset != 0) {
4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_get_random(pw_block, offset) < 0)
4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PasswordLength is 4 octets, but since the maximum password length is
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * 256, only first two (in little endian byte order) can be non-zero.
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = &pw_block[2 * 256];
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_LE16(pos, password_len * 2);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password
4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint new_password_encrypted_with_old_nt_password_hash(
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *new_password, size_t new_password_len,
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *old_password, size_t old_password_len,
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *encrypted_pw_block)
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 password_hash[16];
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nt_password_hash(old_password, old_password_len, password_hash))
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						password_hash,
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						encrypted_pw_block))
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @password_hash: 16-octer PasswordHash (IN)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @block: 16-octet Block (IN)
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cypher: 16-octer Cypher (OUT)
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid nt_password_hash_encrypted_with_block(const u8 *password_hash,
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *block, u8 *cypher)
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_encrypt(password_hash, block, cypher);
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	des_encrypt(password_hash + 8, block + 7, cypher + 8);
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_password_len: Length of new_password
5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @old_password_len: Length of old_password
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint old_nt_password_hash_encrypted_with_new_nt_password_hash(
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *new_password, size_t new_password_len,
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *old_password, size_t old_password_len,
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *encrypted_password_hash)
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 old_password_hash[16], new_password_hash[16];
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nt_password_hash(old_password, old_password_len,
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     old_password_hash) ||
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    nt_password_hash(new_password, new_password_len,
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     new_password_hash))
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nt_password_hash_encrypted_with_block(old_password_hash,
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      new_password_hash,
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      encrypted_password_hash);
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
527