• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
3  * Copyright (c) 2004-2009, 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  */
utf8_to_ucs2(const u8 * utf8_string,size_t utf8_string_len,u8 * ucs2_buffer,size_t ucs2_buffer_size,size_t * ucs2_string_size)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  */
challenge_hash(const u8 * peer_challenge,const u8 * auth_challenge,const u8 * username,size_t username_len,u8 * challenge)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  */
nt_password_hash(const u8 * password,size_t password_len,u8 * password_hash)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  */
hash_nt_password_hash(const u8 * password_hash,u8 * password_hash_hash)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  */
challenge_response(const u8 * challenge,const u8 * password_hash,u8 * response)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  */
generate_nt_response(const u8 * auth_challenge,const u8 * peer_challenge,const u8 * username,size_t username_len,const u8 * password,size_t password_len,u8 * response)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 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
177 		       challenge);
178 	if (nt_password_hash(password, password_len, password_hash))
179 		return -1;
180 	challenge_response(challenge, password_hash, response);
181 	return 0;
182 }
183 
184 
185 /**
186  * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
187  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
188  * @peer_challenge: 16-octet PeerChallenge (IN)
189  * @username: 0-to-256-char UserName (IN)
190  * @username_len: Length of username
191  * @password_hash: 16-octet PasswordHash (IN)
192  * @response: 24-octet Response (OUT)
193  * Returns: 0 on success, -1 on failure
194  */
generate_nt_response_pwhash(const u8 * auth_challenge,const u8 * peer_challenge,const u8 * username,size_t username_len,const u8 * password_hash,u8 * response)195 int generate_nt_response_pwhash(const u8 *auth_challenge,
196 				const u8 *peer_challenge,
197 				const u8 *username, size_t username_len,
198 				const u8 *password_hash,
199 				u8 *response)
200 {
201 	u8 challenge[8];
202 
203 	if (challenge_hash(peer_challenge, auth_challenge,
204 			   username, username_len,
205 			   challenge))
206 		return -1;
207 	challenge_response(challenge, password_hash, response);
208 	return 0;
209 }
210 
211 
212 /**
213  * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
214  * @password_hash: 16-octet PasswordHash (IN)
215  * @nt_response: 24-octet NT-Response (IN)
216  * @peer_challenge: 16-octet PeerChallenge (IN)
217  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
218  * @username: 0-to-256-char UserName (IN)
219  * @username_len: Length of username
220  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
221  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
222  * Returns: 0 on success, -1 on failure
223  */
generate_authenticator_response_pwhash(const u8 * password_hash,const u8 * peer_challenge,const u8 * auth_challenge,const u8 * username,size_t username_len,const u8 * nt_response,u8 * response)224 int generate_authenticator_response_pwhash(
225 	const u8 *password_hash,
226 	const u8 *peer_challenge, const u8 *auth_challenge,
227 	const u8 *username, size_t username_len,
228 	const u8 *nt_response, u8 *response)
229 {
230 	static const u8 magic1[39] = {
231 		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
232 		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
233 		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
234 		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
235 	};
236 	static const u8 magic2[41] = {
237 		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
238 		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
239 		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
240 		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
241 		0x6E
242 	};
243 
244 	u8 password_hash_hash[16], challenge[8];
245 	const unsigned char *addr1[3];
246 	const size_t len1[3] = { 16, 24, sizeof(magic1) };
247 	const unsigned char *addr2[3];
248 	const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
249 
250 	addr1[0] = password_hash_hash;
251 	addr1[1] = nt_response;
252 	addr1[2] = magic1;
253 
254 	addr2[0] = response;
255 	addr2[1] = challenge;
256 	addr2[2] = magic2;
257 
258 	if (hash_nt_password_hash(password_hash, password_hash_hash))
259 		return -1;
260 	if (sha1_vector(3, addr1, len1, response))
261 		return -1;
262 
263 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
264 		       challenge);
265 	return sha1_vector(3, addr2, len2, response);
266 }
267 
268 
269 /**
270  * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
271  * @password: 0-to-256-unicode-char Password (IN; UTF-8)
272  * @password_len: Length of password
273  * @nt_response: 24-octet NT-Response (IN)
274  * @peer_challenge: 16-octet PeerChallenge (IN)
275  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
276  * @username: 0-to-256-char UserName (IN)
277  * @username_len: Length of username
278  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
279  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
280  * Returns: 0 on success, -1 on failure
281  */
generate_authenticator_response(const u8 * password,size_t password_len,const u8 * peer_challenge,const u8 * auth_challenge,const u8 * username,size_t username_len,const u8 * nt_response,u8 * response)282 int generate_authenticator_response(const u8 *password, size_t password_len,
283 				    const u8 *peer_challenge,
284 				    const u8 *auth_challenge,
285 				    const u8 *username, size_t username_len,
286 				    const u8 *nt_response, u8 *response)
287 {
288 	u8 password_hash[16];
289 	if (nt_password_hash(password, password_len, password_hash))
290 		return -1;
291 	return generate_authenticator_response_pwhash(
292 		password_hash, peer_challenge, auth_challenge,
293 		username, username_len, nt_response, response);
294 }
295 
296 
297 /**
298  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
299  * @challenge: 8-octet Challenge (IN)
300  * @password: 0-to-256-unicode-char Password (IN; UTF-8)
301  * @password_len: Length of password
302  * @response: 24-octet Response (OUT)
303  * Returns: 0 on success, -1 on failure
304  */
nt_challenge_response(const u8 * challenge,const u8 * password,size_t password_len,u8 * response)305 int nt_challenge_response(const u8 *challenge, const u8 *password,
306 			  size_t password_len, u8 *response)
307 {
308 	u8 password_hash[16];
309 	if (nt_password_hash(password, password_len, password_hash))
310 		return -1;
311 	challenge_response(challenge, password_hash, response);
312 	return 0;
313 }
314 
315 
316 /**
317  * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
318  * @password_hash_hash: 16-octet PasswordHashHash (IN)
319  * @nt_response: 24-octet NTResponse (IN)
320  * @master_key: 16-octet MasterKey (OUT)
321  * Returns: 0 on success, -1 on failure
322  */
get_master_key(const u8 * password_hash_hash,const u8 * nt_response,u8 * master_key)323 int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
324 		   u8 *master_key)
325 {
326 	static const u8 magic1[27] = {
327 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
328 		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
329 		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
330 	};
331 	const unsigned char *addr[3];
332 	const size_t len[3] = { 16, 24, sizeof(magic1) };
333 	u8 hash[SHA1_MAC_LEN];
334 
335 	addr[0] = password_hash_hash;
336 	addr[1] = nt_response;
337 	addr[2] = magic1;
338 
339 	if (sha1_vector(3, addr, len, hash))
340 		return -1;
341 	os_memcpy(master_key, hash, 16);
342 	return 0;
343 }
344 
345 
346 /**
347  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
348  * @master_key: 16-octet MasterKey (IN)
349  * @session_key: 8-to-16 octet SessionKey (OUT)
350  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
351  * @is_send: IsSend (IN, BOOLEAN)
352  * @is_server: IsServer (IN, BOOLEAN)
353  * Returns: 0 on success, -1 on failure
354  */
get_asymetric_start_key(const u8 * master_key,u8 * session_key,size_t session_key_len,int is_send,int is_server)355 int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
356 			    size_t session_key_len, int is_send,
357 			    int is_server)
358 {
359 	static const u8 magic2[84] = {
360 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
361 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
362 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
363 		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
364 		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
365 		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
366 		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
367 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
368 		0x6b, 0x65, 0x79, 0x2e
369 	};
370 	static const u8 magic3[84] = {
371 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
372 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
373 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
374 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
375 		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
376 		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
377 		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
378 		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
379 		0x6b, 0x65, 0x79, 0x2e
380 	};
381 	static const u8 shs_pad1[40] = {
382 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
386 	};
387 
388 	static const u8 shs_pad2[40] = {
389 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
390 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
391 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
392 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
393 	};
394 	u8 digest[SHA1_MAC_LEN];
395 	const unsigned char *addr[4];
396 	const size_t len[4] = { 16, 40, 84, 40 };
397 
398 	addr[0] = master_key;
399 	addr[1] = shs_pad1;
400 	if (is_send) {
401 		addr[2] = is_server ? magic3 : magic2;
402 	} else {
403 		addr[2] = is_server ? magic2 : magic3;
404 	}
405 	addr[3] = shs_pad2;
406 
407 	if (sha1_vector(4, addr, len, digest))
408 		return -1;
409 
410 	if (session_key_len > SHA1_MAC_LEN)
411 		session_key_len = SHA1_MAC_LEN;
412 	os_memcpy(session_key, digest, session_key_len);
413 	return 0;
414 }
415 
416 
417 #define PWBLOCK_LEN 516
418 
419 /**
420  * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
421  * @password: 0-to-256-unicode-char Password (IN; UTF-8)
422  * @password_len: Length of password
423  * @password_hash: 16-octet PasswordHash (IN)
424  * @pw_block: 516-byte PwBlock (OUT)
425  * Returns: 0 on success, -1 on failure
426  */
encrypt_pw_block_with_password_hash(const u8 * password,size_t password_len,const u8 * password_hash,u8 * pw_block)427 int encrypt_pw_block_with_password_hash(
428 	const u8 *password, size_t password_len,
429 	const u8 *password_hash, u8 *pw_block)
430 {
431 	size_t ucs2_len, offset;
432 	u8 *pos;
433 
434 	os_memset(pw_block, 0, PWBLOCK_LEN);
435 
436 	if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
437 		return -1;
438 
439 	if (ucs2_len > 256)
440 		return -1;
441 
442 	offset = (256 - ucs2_len) * 2;
443 	if (offset != 0) {
444 		os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
445 		if (os_get_random(pw_block, offset) < 0)
446 			return -1;
447 	}
448 	/*
449 	 * PasswordLength is 4 octets, but since the maximum password length is
450 	 * 256, only first two (in little endian byte order) can be non-zero.
451 	 */
452 	pos = &pw_block[2 * 256];
453 	WPA_PUT_LE16(pos, password_len * 2);
454 	rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
455 	return 0;
456 }
457 
458 
459 /**
460  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
461  * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
462  * @new_password_len: Length of new_password
463  * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
464  * @old_password_len: Length of old_password
465  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
466  * Returns: 0 on success, -1 on failure
467  */
new_password_encrypted_with_old_nt_password_hash(const u8 * new_password,size_t new_password_len,const u8 * old_password,size_t old_password_len,u8 * encrypted_pw_block)468 int new_password_encrypted_with_old_nt_password_hash(
469 	const u8 *new_password, size_t new_password_len,
470 	const u8 *old_password, size_t old_password_len,
471 	u8 *encrypted_pw_block)
472 {
473 	u8 password_hash[16];
474 
475 	if (nt_password_hash(old_password, old_password_len, password_hash))
476 		return -1;
477 	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
478 						password_hash,
479 						encrypted_pw_block))
480 		return -1;
481 	return 0;
482 }
483 
484 
485 /**
486  * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
487  * @password_hash: 16-octer PasswordHash (IN)
488  * @block: 16-octet Block (IN)
489  * @cypher: 16-octer Cypher (OUT)
490  */
nt_password_hash_encrypted_with_block(const u8 * password_hash,const u8 * block,u8 * cypher)491 void nt_password_hash_encrypted_with_block(const u8 *password_hash,
492 					   const u8 *block, u8 *cypher)
493 {
494 	des_encrypt(password_hash, block, cypher);
495 	des_encrypt(password_hash + 8, block + 7, cypher + 8);
496 }
497 
498 
499 /**
500  * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
501  * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
502  * @new_password_len: Length of new_password
503  * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
504  * @old_password_len: Length of old_password
505  * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
506  * Returns: 0 on success, -1 on failure
507  */
old_nt_password_hash_encrypted_with_new_nt_password_hash(const u8 * new_password,size_t new_password_len,const u8 * old_password,size_t old_password_len,u8 * encrypted_password_hash)508 int old_nt_password_hash_encrypted_with_new_nt_password_hash(
509 	const u8 *new_password, size_t new_password_len,
510 	const u8 *old_password, size_t old_password_len,
511 	u8 *encrypted_password_hash)
512 {
513 	u8 old_password_hash[16], new_password_hash[16];
514 
515 	if (nt_password_hash(old_password, old_password_len,
516 			     old_password_hash) ||
517 	    nt_password_hash(new_password, new_password_len,
518 			     new_password_hash))
519 		return -1;
520 	nt_password_hash_encrypted_with_block(old_password_hash,
521 					      new_password_hash,
522 					      encrypted_password_hash);
523 	return 0;
524 }
525