Home | History | Annotate | Download | only in crypto
      1 /*
      2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
      3  * Copyright (c) 2004-2009, Jouni Malinen <j (at) 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 	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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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