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  */
25 static 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 			}
62 		}
63 	}
64 
65 	if (ucs2_string_size)
66 		*ucs2_string_size = j / 2;
67 	return 0;
68 }
69 
70 
71 /**
72  * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
73  * @peer_challenge: 16-octet PeerChallenge (IN)
74  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
75  * @username: 0-to-256-char UserName (IN)
76  * @username_len: Length of username
77  * @challenge: 8-octet Challenge (OUT)
78  * Returns: 0 on success, -1 on failure
79  */
80 static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
81 			  const u8 *username, size_t username_len,
82 			  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  */
109 int 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  */
131 int 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  */
144 void 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  */
168 int 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  */
196 int 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  */
225 int 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  */
284 int 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  */
307 int 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  */
325 int 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  */
357 int 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  */
429 int 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  */
470 int 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  */
493 void 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  */
510 int 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