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  * Returns: 0 on success, -1 on failure
    144  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 #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  */
    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  */
    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  */
    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  */
    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