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