1/*
2 * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "sha1.h"
13#include "ms_funcs.h"
14#include "crypto.h"
15
16/**
17 * utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding
18 * @utf8_string: UTF-8 string (IN)
19 * @utf8_string_len: Length of utf8_string (IN)
20 * @ucs2_buffer: UCS-2 buffer (OUT)
21 * @ucs2_buffer_size: Length of UCS-2 buffer (IN)
22 * @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string
23 * Returns: 0 on success, -1 on failure
24 */
25static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
26                        u8 *ucs2_buffer, size_t ucs2_buffer_size,
27                        size_t *ucs2_string_size)
28{
29	size_t i, j;
30
31	for (i = 0, j = 0; i < utf8_string_len; i++) {
32		u8 c = utf8_string[i];
33		if (j >= ucs2_buffer_size) {
34			/* input too long */
35			return -1;
36		}
37		if (c <= 0x7F) {
38			WPA_PUT_LE16(ucs2_buffer + j, c);
39			j += 2;
40		} else if (i == utf8_string_len - 1 ||
41			   j >= ucs2_buffer_size - 1) {
42			/* incomplete surrogate */
43			return -1;
44		} else {
45			u8 c2 = utf8_string[++i];
46			if ((c & 0xE0) == 0xC0) {
47				/* two-byte encoding */
48				WPA_PUT_LE16(ucs2_buffer + j,
49					     ((c & 0x1F) << 6) | (c2 & 0x3F));
50				j += 2;
51			} else if (i == utf8_string_len ||
52				   j >= ucs2_buffer_size - 1) {
53				/* incomplete surrogate */
54				return -1;
55			} else {
56				/* three-byte encoding */
57				u8 c3 = utf8_string[++i];
58				WPA_PUT_LE16(ucs2_buffer + j,
59					     ((c & 0xF) << 12) |
60					     ((c2 & 0x3F) << 6) | (c3 & 0x3F));
61				j += 2;
62			}
63		}
64	}
65
66	if (ucs2_string_size)
67		*ucs2_string_size = j / 2;
68	return 0;
69}
70
71
72/**
73 * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
74 * @peer_challenge: 16-octet PeerChallenge (IN)
75 * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
76 * @username: 0-to-256-char UserName (IN)
77 * @username_len: Length of username
78 * @challenge: 8-octet Challenge (OUT)
79 * Returns: 0 on success, -1 on failure
80 */
81int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
82		   const u8 *username, size_t username_len, u8 *challenge)
83{
84	u8 hash[SHA1_MAC_LEN];
85	const unsigned char *addr[3];
86	size_t len[3];
87
88	addr[0] = peer_challenge;
89	len[0] = 16;
90	addr[1] = auth_challenge;
91	len[1] = 16;
92	addr[2] = username;
93	len[2] = username_len;
94
95	if (sha1_vector(3, addr, len, hash))
96		return -1;
97	os_memcpy(challenge, hash, 8);
98	return 0;
99}
100
101
102/**
103 * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
104 * @password: 0-to-256-unicode-char Password (IN; UTF-8)
105 * @password_len: Length of password
106 * @password_hash: 16-octet PasswordHash (OUT)
107 * Returns: 0 on success, -1 on failure
108 */
109int nt_password_hash(const u8 *password, size_t password_len,
110		      u8 *password_hash)
111{
112	u8 buf[512], *pos;
113	size_t len, max_len;
114
115	max_len = sizeof(buf);
116	if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0)
117		return -1;
118
119	len *= 2;
120	pos = buf;
121	return md4_vector(1, (const u8 **) &pos, &len, password_hash);
122}
123
124
125/**
126 * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
127 * @password_hash: 16-octet PasswordHash (IN)
128 * @password_hash_hash: 16-octet PasswordHashHash (OUT)
129 * Returns: 0 on success, -1 on failure
130 */
131int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
132{
133	size_t len = 16;
134	return md4_vector(1, &password_hash, &len, password_hash_hash);
135}
136
137
138/**
139 * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
140 * @challenge: 8-octet Challenge (IN)
141 * @password_hash: 16-octet PasswordHash (IN)
142 * @response: 24-octet Response (OUT)
143 */
144void challenge_response(const u8 *challenge, const u8 *password_hash,
145			u8 *response)
146{
147	u8 zpwd[7];
148	des_encrypt(challenge, password_hash, response);
149	des_encrypt(challenge, password_hash + 7, response + 8);
150	zpwd[0] = password_hash[14];
151	zpwd[1] = password_hash[15];
152	os_memset(zpwd + 2, 0, 5);
153	des_encrypt(challenge, zpwd, response + 16);
154}
155
156
157/**
158 * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
159 * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
160 * @peer_challenge: 16-octet PeerChallenge (IN)
161 * @username: 0-to-256-char UserName (IN)
162 * @username_len: Length of username
163 * @password: 0-to-256-unicode-char Password (IN; UTF-8)
164 * @password_len: Length of password
165 * @response: 24-octet Response (OUT)
166 * Returns: 0 on success, -1 on failure
167 */
168int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
169			 const u8 *username, size_t username_len,
170			 const u8 *password, size_t password_len,
171			 u8 *response)
172{
173	u8 challenge[8];
174	u8 password_hash[16];
175
176	if (challenge_hash(peer_challenge, auth_challenge, username,
177			   username_len, challenge))
178		return -1;
179	if (nt_password_hash(password, password_len, password_hash))
180		return -1;
181	challenge_response(challenge, password_hash, response);
182	return 0;
183}
184
185
186/**
187 * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
188 * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
189 * @peer_challenge: 16-octet PeerChallenge (IN)
190 * @username: 0-to-256-char UserName (IN)
191 * @username_len: Length of username
192 * @password_hash: 16-octet PasswordHash (IN)
193 * @response: 24-octet Response (OUT)
194 * Returns: 0 on success, -1 on failure
195 */
196int generate_nt_response_pwhash(const u8 *auth_challenge,
197				const u8 *peer_challenge,
198				const u8 *username, size_t username_len,
199				const u8 *password_hash,
200				u8 *response)
201{
202	u8 challenge[8];
203
204	if (challenge_hash(peer_challenge, auth_challenge,
205			   username, username_len,
206			   challenge))
207		return -1;
208	challenge_response(challenge, password_hash, response);
209	return 0;
210}
211
212
213/**
214 * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
215 * @password_hash: 16-octet PasswordHash (IN)
216 * @nt_response: 24-octet NT-Response (IN)
217 * @peer_challenge: 16-octet PeerChallenge (IN)
218 * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
219 * @username: 0-to-256-char UserName (IN)
220 * @username_len: Length of username
221 * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
222 * encoded as a 42-octet ASCII string (S=hexdump_of_response)
223 * Returns: 0 on success, -1 on failure
224 */
225int generate_authenticator_response_pwhash(
226	const u8 *password_hash,
227	const u8 *peer_challenge, const u8 *auth_challenge,
228	const u8 *username, size_t username_len,
229	const u8 *nt_response, u8 *response)
230{
231	static const u8 magic1[39] = {
232		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
233		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
234		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
235		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
236	};
237	static const u8 magic2[41] = {
238		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
239		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
240		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
241		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
242		0x6E
243	};
244
245	u8 password_hash_hash[16], challenge[8];
246	const unsigned char *addr1[3];
247	const size_t len1[3] = { 16, 24, sizeof(magic1) };
248	const unsigned char *addr2[3];
249	const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
250
251	addr1[0] = password_hash_hash;
252	addr1[1] = nt_response;
253	addr1[2] = magic1;
254
255	addr2[0] = response;
256	addr2[1] = challenge;
257	addr2[2] = magic2;
258
259	if (hash_nt_password_hash(password_hash, password_hash_hash))
260		return -1;
261	if (sha1_vector(3, addr1, len1, response))
262		return -1;
263
264	if (challenge_hash(peer_challenge, auth_challenge, username,
265			   username_len, challenge))
266		return -1;
267	return sha1_vector(3, addr2, len2, response);
268}
269
270
271/**
272 * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
273 * @password: 0-to-256-unicode-char Password (IN; UTF-8)
274 * @password_len: Length of password
275 * @nt_response: 24-octet NT-Response (IN)
276 * @peer_challenge: 16-octet PeerChallenge (IN)
277 * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
278 * @username: 0-to-256-char UserName (IN)
279 * @username_len: Length of username
280 * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
281 * encoded as a 42-octet ASCII string (S=hexdump_of_response)
282 * Returns: 0 on success, -1 on failure
283 */
284int generate_authenticator_response(const u8 *password, size_t password_len,
285				    const u8 *peer_challenge,
286				    const u8 *auth_challenge,
287				    const u8 *username, size_t username_len,
288				    const u8 *nt_response, u8 *response)
289{
290	u8 password_hash[16];
291	if (nt_password_hash(password, password_len, password_hash))
292		return -1;
293	return generate_authenticator_response_pwhash(
294		password_hash, peer_challenge, auth_challenge,
295		username, username_len, nt_response, response);
296}
297
298
299/**
300 * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
301 * @challenge: 8-octet Challenge (IN)
302 * @password: 0-to-256-unicode-char Password (IN; UTF-8)
303 * @password_len: Length of password
304 * @response: 24-octet Response (OUT)
305 * Returns: 0 on success, -1 on failure
306 */
307int nt_challenge_response(const u8 *challenge, const u8 *password,
308			  size_t password_len, u8 *response)
309{
310	u8 password_hash[16];
311	if (nt_password_hash(password, password_len, password_hash))
312		return -1;
313	challenge_response(challenge, password_hash, response);
314	return 0;
315}
316
317
318/**
319 * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
320 * @password_hash_hash: 16-octet PasswordHashHash (IN)
321 * @nt_response: 24-octet NTResponse (IN)
322 * @master_key: 16-octet MasterKey (OUT)
323 * Returns: 0 on success, -1 on failure
324 */
325int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
326		   u8 *master_key)
327{
328	static const u8 magic1[27] = {
329		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
330		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
331		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
332	};
333	const unsigned char *addr[3];
334	const size_t len[3] = { 16, 24, sizeof(magic1) };
335	u8 hash[SHA1_MAC_LEN];
336
337	addr[0] = password_hash_hash;
338	addr[1] = nt_response;
339	addr[2] = magic1;
340
341	if (sha1_vector(3, addr, len, hash))
342		return -1;
343	os_memcpy(master_key, hash, 16);
344	return 0;
345}
346
347
348/**
349 * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
350 * @master_key: 16-octet MasterKey (IN)
351 * @session_key: 8-to-16 octet SessionKey (OUT)
352 * @session_key_len: SessionKeyLength (Length of session_key) (IN)
353 * @is_send: IsSend (IN, BOOLEAN)
354 * @is_server: IsServer (IN, BOOLEAN)
355 * Returns: 0 on success, -1 on failure
356 */
357int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
358			    size_t session_key_len, int is_send,
359			    int is_server)
360{
361	static const u8 magic2[84] = {
362		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
363		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
364		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
365		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
366		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
367		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
368		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
369		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
370		0x6b, 0x65, 0x79, 0x2e
371	};
372	static const u8 magic3[84] = {
373		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
374		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
375		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
376		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
377		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
378		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
379		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
380		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
381		0x6b, 0x65, 0x79, 0x2e
382	};
383	static const u8 shs_pad1[40] = {
384		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
388	};
389
390	static const u8 shs_pad2[40] = {
391		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
392		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
393		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
394		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
395	};
396	u8 digest[SHA1_MAC_LEN];
397	const unsigned char *addr[4];
398	const size_t len[4] = { 16, 40, 84, 40 };
399
400	addr[0] = master_key;
401	addr[1] = shs_pad1;
402	if (is_send) {
403		addr[2] = is_server ? magic3 : magic2;
404	} else {
405		addr[2] = is_server ? magic2 : magic3;
406	}
407	addr[3] = shs_pad2;
408
409	if (sha1_vector(4, addr, len, digest))
410		return -1;
411
412	if (session_key_len > SHA1_MAC_LEN)
413		session_key_len = SHA1_MAC_LEN;
414	os_memcpy(session_key, digest, session_key_len);
415	return 0;
416}
417
418
419#define PWBLOCK_LEN 516
420
421/**
422 * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
423 * @password: 0-to-256-unicode-char Password (IN; UTF-8)
424 * @password_len: Length of password
425 * @password_hash: 16-octet PasswordHash (IN)
426 * @pw_block: 516-byte PwBlock (OUT)
427 * Returns: 0 on success, -1 on failure
428 */
429int encrypt_pw_block_with_password_hash(
430	const u8 *password, size_t password_len,
431	const u8 *password_hash, u8 *pw_block)
432{
433	size_t ucs2_len, offset;
434	u8 *pos;
435
436	os_memset(pw_block, 0, PWBLOCK_LEN);
437
438	if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
439		return -1;
440
441	if (ucs2_len > 256)
442		return -1;
443
444	offset = (256 - ucs2_len) * 2;
445	if (offset != 0) {
446		os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
447		if (os_get_random(pw_block, offset) < 0)
448			return -1;
449	}
450	/*
451	 * PasswordLength is 4 octets, but since the maximum password length is
452	 * 256, only first two (in little endian byte order) can be non-zero.
453	 */
454	pos = &pw_block[2 * 256];
455	WPA_PUT_LE16(pos, password_len * 2);
456	rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
457	return 0;
458}
459
460
461/**
462 * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
463 * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
464 * @new_password_len: Length of new_password
465 * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
466 * @old_password_len: Length of old_password
467 * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
468 * Returns: 0 on success, -1 on failure
469 */
470int new_password_encrypted_with_old_nt_password_hash(
471	const u8 *new_password, size_t new_password_len,
472	const u8 *old_password, size_t old_password_len,
473	u8 *encrypted_pw_block)
474{
475	u8 password_hash[16];
476
477	if (nt_password_hash(old_password, old_password_len, password_hash))
478		return -1;
479	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
480						password_hash,
481						encrypted_pw_block))
482		return -1;
483	return 0;
484}
485
486
487/**
488 * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
489 * @password_hash: 16-octer PasswordHash (IN)
490 * @block: 16-octet Block (IN)
491 * @cypher: 16-octer Cypher (OUT)
492 */
493void nt_password_hash_encrypted_with_block(const u8 *password_hash,
494					   const u8 *block, u8 *cypher)
495{
496	des_encrypt(password_hash, block, cypher);
497	des_encrypt(password_hash + 8, block + 7, cypher + 8);
498}
499
500
501/**
502 * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
503 * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
504 * @new_password_len: Length of new_password
505 * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
506 * @old_password_len: Length of old_password
507 * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
508 * Returns: 0 on success, -1 on failure
509 */
510int old_nt_password_hash_encrypted_with_new_nt_password_hash(
511	const u8 *new_password, size_t new_password_len,
512	const u8 *old_password, size_t old_password_len,
513	u8 *encrypted_password_hash)
514{
515	u8 old_password_hash[16], new_password_hash[16];
516
517	if (nt_password_hash(old_password, old_password_len,
518			     old_password_hash) ||
519	    nt_password_hash(new_password, new_password_len,
520			     new_password_hash))
521		return -1;
522	nt_password_hash_encrypted_with_block(old_password_hash,
523					      new_password_hash,
524					      encrypted_password_hash);
525	return 0;
526}
527