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   */
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 - 1 ||
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   */
challenge_hash(const u8 * peer_challenge,const u8 * auth_challenge,const u8 * username,size_t username_len,u8 * challenge)81  int 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   */
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   * Returns: 0 on success, -1 on failure
144   */
challenge_response(const u8 * challenge,const u8 * password_hash,u8 * response)145  int challenge_response(const u8 *challenge, const u8 *password_hash,
146  		       u8 *response)
147  {
148  	u8 zpwd[7];
149  
150  	if (des_encrypt(challenge, password_hash, response) < 0 ||
151  	    des_encrypt(challenge, password_hash + 7, response + 8) < 0)
152  		return -1;
153  	zpwd[0] = password_hash[14];
154  	zpwd[1] = password_hash[15];
155  	os_memset(zpwd + 2, 0, 5);
156  	return des_encrypt(challenge, zpwd, response + 16);
157  }
158  
159  
160  /**
161   * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
162   * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
163   * @peer_challenge: 16-octet PeerChallenge (IN)
164   * @username: 0-to-256-char UserName (IN)
165   * @username_len: Length of username
166   * @password: 0-to-256-unicode-char Password (IN; UTF-8)
167   * @password_len: Length of password
168   * @response: 24-octet Response (OUT)
169   * Returns: 0 on success, -1 on failure
170   */
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)171  int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
172  			 const u8 *username, size_t username_len,
173  			 const u8 *password, size_t password_len,
174  			 u8 *response)
175  {
176  	u8 challenge[8];
177  	u8 password_hash[16];
178  
179  	if (challenge_hash(peer_challenge, auth_challenge, username,
180  			   username_len, challenge) ||
181  	    nt_password_hash(password, password_len, password_hash) ||
182  	    challenge_response(challenge, password_hash, response))
183  		return -1;
184  	return 0;
185  }
186  
187  
188  /**
189   * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
190   * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
191   * @peer_challenge: 16-octet PeerChallenge (IN)
192   * @username: 0-to-256-char UserName (IN)
193   * @username_len: Length of username
194   * @password_hash: 16-octet PasswordHash (IN)
195   * @response: 24-octet Response (OUT)
196   * Returns: 0 on success, -1 on failure
197   */
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)198  int generate_nt_response_pwhash(const u8 *auth_challenge,
199  				const u8 *peer_challenge,
200  				const u8 *username, size_t username_len,
201  				const u8 *password_hash,
202  				u8 *response)
203  {
204  	u8 challenge[8];
205  
206  	if (challenge_hash(peer_challenge, auth_challenge,
207  			   username, username_len,
208  			   challenge) ||
209  	    challenge_response(challenge, password_hash, response))
210  		return -1;
211  	return 0;
212  }
213  
214  
215  /**
216   * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
217   * @password_hash: 16-octet PasswordHash (IN)
218   * @nt_response: 24-octet NT-Response (IN)
219   * @peer_challenge: 16-octet PeerChallenge (IN)
220   * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
221   * @username: 0-to-256-char UserName (IN)
222   * @username_len: Length of username
223   * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
224   * encoded as a 42-octet ASCII string (S=hexdump_of_response)
225   * Returns: 0 on success, -1 on failure
226   */
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)227  int generate_authenticator_response_pwhash(
228  	const u8 *password_hash,
229  	const u8 *peer_challenge, const u8 *auth_challenge,
230  	const u8 *username, size_t username_len,
231  	const u8 *nt_response, u8 *response)
232  {
233  	static const u8 magic1[39] = {
234  		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
235  		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
236  		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
237  		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
238  	};
239  	static const u8 magic2[41] = {
240  		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
241  		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
242  		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
243  		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
244  		0x6E
245  	};
246  
247  	u8 password_hash_hash[16], challenge[8];
248  	const unsigned char *addr1[3];
249  	const size_t len1[3] = { 16, 24, sizeof(magic1) };
250  	const unsigned char *addr2[3];
251  	const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
252  
253  	addr1[0] = password_hash_hash;
254  	addr1[1] = nt_response;
255  	addr1[2] = magic1;
256  
257  	addr2[0] = response;
258  	addr2[1] = challenge;
259  	addr2[2] = magic2;
260  
261  	if (hash_nt_password_hash(password_hash, password_hash_hash) ||
262  	    sha1_vector(3, addr1, len1, response) ||
263  	    challenge_hash(peer_challenge, auth_challenge, username,
264  			   username_len, challenge))
265  		return -1;
266  	return sha1_vector(3, addr2, len2, response);
267  }
268  
269  
270  /**
271   * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
272   * @password: 0-to-256-unicode-char Password (IN; UTF-8)
273   * @password_len: Length of password
274   * @nt_response: 24-octet NT-Response (IN)
275   * @peer_challenge: 16-octet PeerChallenge (IN)
276   * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
277   * @username: 0-to-256-char UserName (IN)
278   * @username_len: Length of username
279   * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
280   * encoded as a 42-octet ASCII string (S=hexdump_of_response)
281   * Returns: 0 on success, -1 on failure
282   */
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)283  int generate_authenticator_response(const u8 *password, size_t password_len,
284  				    const u8 *peer_challenge,
285  				    const u8 *auth_challenge,
286  				    const u8 *username, size_t username_len,
287  				    const u8 *nt_response, u8 *response)
288  {
289  	u8 password_hash[16];
290  	if (nt_password_hash(password, password_len, password_hash))
291  		return -1;
292  	return generate_authenticator_response_pwhash(
293  		password_hash, peer_challenge, auth_challenge,
294  		username, username_len, nt_response, response);
295  }
296  
297  
298  /**
299   * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
300   * @challenge: 8-octet Challenge (IN)
301   * @password: 0-to-256-unicode-char Password (IN; UTF-8)
302   * @password_len: Length of password
303   * @response: 24-octet Response (OUT)
304   * Returns: 0 on success, -1 on failure
305   */
nt_challenge_response(const u8 * challenge,const u8 * password,size_t password_len,u8 * response)306  int nt_challenge_response(const u8 *challenge, const u8 *password,
307  			  size_t password_len, u8 *response)
308  {
309  	u8 password_hash[16];
310  
311  	if (nt_password_hash(password, password_len, password_hash) ||
312  	    challenge_response(challenge, password_hash, response))
313  		return -1;
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   */
get_master_key(const u8 * password_hash_hash,const u8 * nt_response,u8 * master_key)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   */
get_asymetric_start_key(const u8 * master_key,u8 * session_key,size_t session_key_len,int is_send,int is_server)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  #ifndef CONFIG_NO_RC4
420  
421  #define PWBLOCK_LEN 516
422  
423  /**
424   * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
425   * @password: 0-to-256-unicode-char Password (IN; UTF-8)
426   * @password_len: Length of password
427   * @password_hash: 16-octet PasswordHash (IN)
428   * @pw_block: 516-byte PwBlock (OUT)
429   * Returns: 0 on success, -1 on failure
430   */
encrypt_pw_block_with_password_hash(const u8 * password,size_t password_len,const u8 * password_hash,u8 * pw_block)431  int encrypt_pw_block_with_password_hash(
432  	const u8 *password, size_t password_len,
433  	const u8 *password_hash, u8 *pw_block)
434  {
435  	size_t ucs2_len, offset;
436  	u8 *pos;
437  
438  	os_memset(pw_block, 0, PWBLOCK_LEN);
439  
440  	if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0
441  	    || 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   */
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)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  #endif /* CONFIG_NO_RC4 */
487  
488  
489  /**
490   * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
491   * @password_hash: 16-octer PasswordHash (IN)
492   * @block: 16-octet Block (IN)
493   * @cypher: 16-octer Cypher (OUT)
494   * Returns: 0 on success, -1 on failure
495   */
nt_password_hash_encrypted_with_block(const u8 * password_hash,const u8 * block,u8 * cypher)496  int nt_password_hash_encrypted_with_block(const u8 *password_hash,
497  					  const u8 *block, u8 *cypher)
498  {
499  	if (des_encrypt(password_hash, block, cypher) < 0 ||
500  	    des_encrypt(password_hash + 8, block + 7, cypher + 8) < 0)
501  		return -1;
502  	return 0;
503  }
504  
505  
506  /**
507   * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
508   * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
509   * @new_password_len: Length of new_password
510   * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
511   * @old_password_len: Length of old_password
512   * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
513   * Returns: 0 on success, -1 on failure
514   */
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)515  int old_nt_password_hash_encrypted_with_new_nt_password_hash(
516  	const u8 *new_password, size_t new_password_len,
517  	const u8 *old_password, size_t old_password_len,
518  	u8 *encrypted_password_hash)
519  {
520  	u8 old_password_hash[16], new_password_hash[16];
521  
522  	if (nt_password_hash(old_password, old_password_len,
523  			     old_password_hash) ||
524  	    nt_password_hash(new_password, new_password_len,
525  			     new_password_hash) ||
526  	    nt_password_hash_encrypted_with_block(old_password_hash,
527  						  new_password_hash,
528  						  encrypted_password_hash))
529  		return -1;
530  	return 0;
531  }
532