xref: /dragonfly/contrib/wpa_supplicant/src/crypto/ms_funcs.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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