Home | History | Annotate | Download | only in crypto
      1 /*
      2  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
      3  * Copyright (c) 2004-2012, 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 - 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  */
     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  */
    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 	    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 	    sha1_vector(3, addr1, len1, response) ||
    260 	    challenge_hash(peer_challenge, auth_challenge, username,
    261 			   username_len, challenge))
    262 		return -1;
    263 	return sha1_vector(3, addr2, len2, response);
    264 }
    265 
    266 
    267 /**
    268  * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
    269  * @password: 0-to-256-unicode-char Password (IN; UTF-8)
    270  * @password_len: Length of password
    271  * @nt_response: 24-octet NT-Response (IN)
    272  * @peer_challenge: 16-octet PeerChallenge (IN)
    273  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
    274  * @username: 0-to-256-char UserName (IN)
    275  * @username_len: Length of username
    276  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
    277  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
    278  * Returns: 0 on success, -1 on failure
    279  */
    280 int generate_authenticator_response(const u8 *password, size_t password_len,
    281 				    const u8 *peer_challenge,
    282 				    const u8 *auth_challenge,
    283 				    const u8 *username, size_t username_len,
    284 				    const u8 *nt_response, u8 *response)
    285 {
    286 	u8 password_hash[16];
    287 	if (nt_password_hash(password, password_len, password_hash))
    288 		return -1;
    289 	return generate_authenticator_response_pwhash(
    290 		password_hash, peer_challenge, auth_challenge,
    291 		username, username_len, nt_response, response);
    292 }
    293 
    294 
    295 /**
    296  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
    297  * @challenge: 8-octet Challenge (IN)
    298  * @password: 0-to-256-unicode-char Password (IN; UTF-8)
    299  * @password_len: Length of password
    300  * @response: 24-octet Response (OUT)
    301  * Returns: 0 on success, -1 on failure
    302  */
    303 int nt_challenge_response(const u8 *challenge, const u8 *password,
    304 			  size_t password_len, u8 *response)
    305 {
    306 	u8 password_hash[16];
    307 	if (nt_password_hash(password, password_len, password_hash))
    308 		return -1;
    309 	challenge_response(challenge, password_hash, response);
    310 	return 0;
    311 }
    312 
    313 
    314 /**
    315  * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
    316  * @password_hash_hash: 16-octet PasswordHashHash (IN)
    317  * @nt_response: 24-octet NTResponse (IN)
    318  * @master_key: 16-octet MasterKey (OUT)
    319  * Returns: 0 on success, -1 on failure
    320  */
    321 int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
    322 		   u8 *master_key)
    323 {
    324 	static const u8 magic1[27] = {
    325 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
    326 		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
    327 		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
    328 	};
    329 	const unsigned char *addr[3];
    330 	const size_t len[3] = { 16, 24, sizeof(magic1) };
    331 	u8 hash[SHA1_MAC_LEN];
    332 
    333 	addr[0] = password_hash_hash;
    334 	addr[1] = nt_response;
    335 	addr[2] = magic1;
    336 
    337 	if (sha1_vector(3, addr, len, hash))
    338 		return -1;
    339 	os_memcpy(master_key, hash, 16);
    340 	return 0;
    341 }
    342 
    343 
    344 /**
    345  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
    346  * @master_key: 16-octet MasterKey (IN)
    347  * @session_key: 8-to-16 octet SessionKey (OUT)
    348  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
    349  * @is_send: IsSend (IN, BOOLEAN)
    350  * @is_server: IsServer (IN, BOOLEAN)
    351  * Returns: 0 on success, -1 on failure
    352  */
    353 int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
    354 			    size_t session_key_len, int is_send,
    355 			    int is_server)
    356 {
    357 	static const u8 magic2[84] = {
    358 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
    359 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
    360 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    361 		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
    362 		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
    363 		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
    364 		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    365 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
    366 		0x6b, 0x65, 0x79, 0x2e
    367 	};
    368 	static const u8 magic3[84] = {
    369 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
    370 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
    371 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    372 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
    373 		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
    374 		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
    375 		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
    376 		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
    377 		0x6b, 0x65, 0x79, 0x2e
    378 	};
    379 	static const u8 shs_pad1[40] = {
    380 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    381 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    382 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    383 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    384 	};
    385 
    386 	static const u8 shs_pad2[40] = {
    387 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    388 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    389 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    390 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
    391 	};
    392 	u8 digest[SHA1_MAC_LEN];
    393 	const unsigned char *addr[4];
    394 	const size_t len[4] = { 16, 40, 84, 40 };
    395 
    396 	addr[0] = master_key;
    397 	addr[1] = shs_pad1;
    398 	if (is_send) {
    399 		addr[2] = is_server ? magic3 : magic2;
    400 	} else {
    401 		addr[2] = is_server ? magic2 : magic3;
    402 	}
    403 	addr[3] = shs_pad2;
    404 
    405 	if (sha1_vector(4, addr, len, digest))
    406 		return -1;
    407 
    408 	if (session_key_len > SHA1_MAC_LEN)
    409 		session_key_len = SHA1_MAC_LEN;
    410 	os_memcpy(session_key, digest, session_key_len);
    411 	return 0;
    412 }
    413 
    414 
    415 #ifndef CONFIG_NO_RC4
    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 	    || ucs2_len > 256)
    438 		return -1;
    439 
    440 	offset = (256 - ucs2_len) * 2;
    441 	if (offset != 0) {
    442 		os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
    443 		if (os_get_random(pw_block, offset) < 0)
    444 			return -1;
    445 	}
    446 	/*
    447 	 * PasswordLength is 4 octets, but since the maximum password length is
    448 	 * 256, only first two (in little endian byte order) can be non-zero.
    449 	 */
    450 	pos = &pw_block[2 * 256];
    451 	WPA_PUT_LE16(pos, password_len * 2);
    452 	rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
    453 	return 0;
    454 }
    455 
    456 
    457 /**
    458  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
    459  * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
    460  * @new_password_len: Length of new_password
    461  * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
    462  * @old_password_len: Length of old_password
    463  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
    464  * Returns: 0 on success, -1 on failure
    465  */
    466 int new_password_encrypted_with_old_nt_password_hash(
    467 	const u8 *new_password, size_t new_password_len,
    468 	const u8 *old_password, size_t old_password_len,
    469 	u8 *encrypted_pw_block)
    470 {
    471 	u8 password_hash[16];
    472 
    473 	if (nt_password_hash(old_password, old_password_len, password_hash))
    474 		return -1;
    475 	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
    476 						password_hash,
    477 						encrypted_pw_block))
    478 		return -1;
    479 	return 0;
    480 }
    481 
    482 #endif /* CONFIG_NO_RC4 */
    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