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 program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "sha1.h"
     19 #include "ms_funcs.h"
     20 #include "crypto.h"
     21 
     22 
     23 /**
     24  * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
     25  * @peer_challenge: 16-octet PeerChallenge (IN)
     26  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
     27  * @username: 0-to-256-char UserName (IN)
     28  * @username_len: Length of username
     29  * @challenge: 8-octet Challenge (OUT)
     30  * Returns: 0 on success, -1 on failure
     31  */
     32 static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
     33 			  const u8 *username, size_t username_len,
     34 			  u8 *challenge)
     35 {
     36 	u8 hash[SHA1_MAC_LEN];
     37 	const unsigned char *addr[3];
     38 	size_t len[3];
     39 
     40 	addr[0] = peer_challenge;
     41 	len[0] = 16;
     42 	addr[1] = auth_challenge;
     43 	len[1] = 16;
     44 	addr[2] = username;
     45 	len[2] = username_len;
     46 
     47 	if (sha1_vector(3, addr, len, hash))
     48 		return -1;
     49 	os_memcpy(challenge, hash, 8);
     50 	return 0;
     51 }
     52 
     53 
     54 /**
     55  * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
     56  * @password: 0-to-256-unicode-char Password (IN; ASCII)
     57  * @password_len: Length of password
     58  * @password_hash: 16-octet PasswordHash (OUT)
     59  * Returns: 0 on success, -1 on failure
     60  */
     61 int nt_password_hash(const u8 *password, size_t password_len,
     62 		      u8 *password_hash)
     63 {
     64 	u8 buf[512], *pos;
     65 	size_t i, len;
     66 
     67 	if (password_len > 256)
     68 		password_len = 256;
     69 
     70 	/* Convert password into unicode */
     71 	for (i = 0; i < password_len; i++) {
     72 		buf[2 * i] = password[i];
     73 		buf[2 * i + 1] = 0;
     74 	}
     75 
     76 	len = password_len * 2;
     77 	pos = buf;
     78 	return md4_vector(1, (const u8 **) &pos, &len, password_hash);
     79 }
     80 
     81 
     82 /**
     83  * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
     84  * @password_hash: 16-octet PasswordHash (IN)
     85  * @password_hash_hash: 16-octet PasswordHashHash (OUT)
     86  * Returns: 0 on success, -1 on failure
     87  */
     88 int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
     89 {
     90 	size_t len = 16;
     91 	return md4_vector(1, &password_hash, &len, password_hash_hash);
     92 }
     93 
     94 
     95 /**
     96  * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
     97  * @challenge: 8-octet Challenge (IN)
     98  * @password_hash: 16-octet PasswordHash (IN)
     99  * @response: 24-octet Response (OUT)
    100  */
    101 void challenge_response(const u8 *challenge, const u8 *password_hash,
    102 			u8 *response)
    103 {
    104 	u8 zpwd[7];
    105 	des_encrypt(challenge, password_hash, response);
    106 	des_encrypt(challenge, password_hash + 7, response + 8);
    107 	zpwd[0] = password_hash[14];
    108 	zpwd[1] = password_hash[15];
    109 	os_memset(zpwd + 2, 0, 5);
    110 	des_encrypt(challenge, zpwd, response + 16);
    111 }
    112 
    113 
    114 /**
    115  * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
    116  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
    117  * @peer_challenge: 16-octet PeerChallenge (IN)
    118  * @username: 0-to-256-char UserName (IN)
    119  * @username_len: Length of username
    120  * @password: 0-to-256-unicode-char Password (IN; ASCII)
    121  * @password_len: Length of password
    122  * @response: 24-octet Response (OUT)
    123  * Returns: 0 on success, -1 on failure
    124  */
    125 int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
    126 			 const u8 *username, size_t username_len,
    127 			 const u8 *password, size_t password_len,
    128 			 u8 *response)
    129 {
    130 	u8 challenge[8];
    131 	u8 password_hash[16];
    132 
    133 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
    134 		       challenge);
    135 	if (nt_password_hash(password, password_len, password_hash))
    136 		return -1;
    137 	challenge_response(challenge, password_hash, response);
    138 	return 0;
    139 }
    140 
    141 
    142 /**
    143  * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
    144  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
    145  * @peer_challenge: 16-octet PeerChallenge (IN)
    146  * @username: 0-to-256-char UserName (IN)
    147  * @username_len: Length of username
    148  * @password_hash: 16-octet PasswordHash (IN)
    149  * @response: 24-octet Response (OUT)
    150  * Returns: 0 on success, -1 on failure
    151  */
    152 int generate_nt_response_pwhash(const u8 *auth_challenge,
    153 				const u8 *peer_challenge,
    154 				const u8 *username, size_t username_len,
    155 				const u8 *password_hash,
    156 				u8 *response)
    157 {
    158 	u8 challenge[8];
    159 
    160 	if (challenge_hash(peer_challenge, auth_challenge,
    161 			   username, username_len,
    162 			   challenge))
    163 		return -1;
    164 	challenge_response(challenge, password_hash, response);
    165 	return 0;
    166 }
    167 
    168 
    169 /**
    170  * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
    171  * @password_hash: 16-octet PasswordHash (IN)
    172  * @nt_response: 24-octet NT-Response (IN)
    173  * @peer_challenge: 16-octet PeerChallenge (IN)
    174  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
    175  * @username: 0-to-256-char UserName (IN)
    176  * @username_len: Length of username
    177  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
    178  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
    179  * Returns: 0 on success, -1 on failure
    180  */
    181 int generate_authenticator_response_pwhash(
    182 	const u8 *password_hash,
    183 	const u8 *peer_challenge, const u8 *auth_challenge,
    184 	const u8 *username, size_t username_len,
    185 	const u8 *nt_response, u8 *response)
    186 {
    187 	static const u8 magic1[39] = {
    188 		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
    189 		0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
    190 		0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
    191 		0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
    192 	};
    193 	static const u8 magic2[41] = {
    194 		0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
    195 		0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
    196 		0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
    197 		0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
    198 		0x6E
    199 	};
    200 
    201 	u8 password_hash_hash[16], challenge[8];
    202 	const unsigned char *addr1[3];
    203 	const size_t len1[3] = { 16, 24, sizeof(magic1) };
    204 	const unsigned char *addr2[3];
    205 	const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
    206 
    207 	addr1[0] = password_hash_hash;
    208 	addr1[1] = nt_response;
    209 	addr1[2] = magic1;
    210 
    211 	addr2[0] = response;
    212 	addr2[1] = challenge;
    213 	addr2[2] = magic2;
    214 
    215 	if (hash_nt_password_hash(password_hash, password_hash_hash))
    216 		return -1;
    217 	if (sha1_vector(3, addr1, len1, response))
    218 		return -1;
    219 
    220 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
    221 		       challenge);
    222 	return sha1_vector(3, addr2, len2, response);
    223 }
    224 
    225 
    226 /**
    227  * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
    228  * @password: 0-to-256-unicode-char Password (IN; ASCII)
    229  * @password_len: Length of password
    230  * @nt_response: 24-octet NT-Response (IN)
    231  * @peer_challenge: 16-octet PeerChallenge (IN)
    232  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
    233  * @username: 0-to-256-char UserName (IN)
    234  * @username_len: Length of username
    235  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
    236  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
    237  * Returns: 0 on success, -1 on failure
    238  */
    239 int generate_authenticator_response(const u8 *password, size_t password_len,
    240 				    const u8 *peer_challenge,
    241 				    const u8 *auth_challenge,
    242 				    const u8 *username, size_t username_len,
    243 				    const u8 *nt_response, u8 *response)
    244 {
    245 	u8 password_hash[16];
    246 	if (nt_password_hash(password, password_len, password_hash))
    247 		return -1;
    248 	return generate_authenticator_response_pwhash(
    249 		password_hash, peer_challenge, auth_challenge,
    250 		username, username_len, nt_response, response);
    251 }
    252 
    253 
    254 /**
    255  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
    256  * @challenge: 8-octet Challenge (IN)
    257  * @password: 0-to-256-unicode-char Password (IN; ASCII)
    258  * @password_len: Length of password
    259  * @response: 24-octet Response (OUT)
    260  * Returns: 0 on success, -1 on failure
    261  */
    262 int nt_challenge_response(const u8 *challenge, const u8 *password,
    263 			  size_t password_len, u8 *response)
    264 {
    265 	u8 password_hash[16];
    266 	if (nt_password_hash(password, password_len, password_hash))
    267 		return -1;
    268 	challenge_response(challenge, password_hash, response);
    269 	return 0;
    270 }
    271 
    272 
    273 /**
    274  * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
    275  * @password_hash_hash: 16-octet PasswordHashHash (IN)
    276  * @nt_response: 24-octet NTResponse (IN)
    277  * @master_key: 16-octet MasterKey (OUT)
    278  * Returns: 0 on success, -1 on failure
    279  */
    280 int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
    281 		   u8 *master_key)
    282 {
    283 	static const u8 magic1[27] = {
    284 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
    285 		0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
    286 		0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
    287 	};
    288 	const unsigned char *addr[3];
    289 	const size_t len[3] = { 16, 24, sizeof(magic1) };
    290 	u8 hash[SHA1_MAC_LEN];
    291 
    292 	addr[0] = password_hash_hash;
    293 	addr[1] = nt_response;
    294 	addr[2] = magic1;
    295 
    296 	if (sha1_vector(3, addr, len, hash))
    297 		return -1;
    298 	os_memcpy(master_key, hash, 16);
    299 	return 0;
    300 }
    301 
    302 
    303 /**
    304  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
    305  * @master_key: 16-octet MasterKey (IN)
    306  * @session_key: 8-to-16 octet SessionKey (OUT)
    307  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
    308  * @is_send: IsSend (IN, BOOLEAN)
    309  * @is_server: IsServer (IN, BOOLEAN)
    310  * Returns: 0 on success, -1 on failure
    311  */
    312 int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
    313 			    size_t session_key_len, int is_send,
    314 			    int is_server)
    315 {
    316 	static const u8 magic2[84] = {
    317 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
    318 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
    319 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    320 		0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
    321 		0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
    322 		0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
    323 		0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    324 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
    325 		0x6b, 0x65, 0x79, 0x2e
    326 	};
    327 	static const u8 magic3[84] = {
    328 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
    329 		0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
    330 		0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
    331 		0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
    332 		0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
    333 		0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
    334 		0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
    335 		0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
    336 		0x6b, 0x65, 0x79, 0x2e
    337 	};
    338 	static const u8 shs_pad1[40] = {
    339 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    340 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    341 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    342 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    343 	};
    344 
    345 	static const u8 shs_pad2[40] = {
    346 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    347 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    348 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    349 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
    350 	};
    351 	u8 digest[SHA1_MAC_LEN];
    352 	const unsigned char *addr[4];
    353 	const size_t len[4] = { 16, 40, 84, 40 };
    354 
    355 	addr[0] = master_key;
    356 	addr[1] = shs_pad1;
    357 	if (is_send) {
    358 		addr[2] = is_server ? magic3 : magic2;
    359 	} else {
    360 		addr[2] = is_server ? magic2 : magic3;
    361 	}
    362 	addr[3] = shs_pad2;
    363 
    364 	if (sha1_vector(4, addr, len, digest))
    365 		return -1;
    366 
    367 	if (session_key_len > SHA1_MAC_LEN)
    368 		session_key_len = SHA1_MAC_LEN;
    369 	os_memcpy(session_key, digest, session_key_len);
    370 	return 0;
    371 }
    372 
    373 
    374 #define PWBLOCK_LEN 516
    375 
    376 /**
    377  * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
    378  * @password: 0-to-256-unicode-char Password (IN; ASCII)
    379  * @password_len: Length of password
    380  * @password_hash: 16-octet PasswordHash (IN)
    381  * @pw_block: 516-byte PwBlock (OUT)
    382  * Returns: 0 on success, -1 on failure
    383  */
    384 int encrypt_pw_block_with_password_hash(
    385 	const u8 *password, size_t password_len,
    386 	const u8 *password_hash, u8 *pw_block)
    387 {
    388 	size_t i, offset;
    389 	u8 *pos;
    390 
    391 	if (password_len > 256)
    392 		return -1;
    393 
    394 	os_memset(pw_block, 0, PWBLOCK_LEN);
    395 	offset = (256 - password_len) * 2;
    396 	if (os_get_random(pw_block, offset) < 0)
    397 		return -1;
    398 	for (i = 0; i < password_len; i++)
    399 		pw_block[offset + i * 2] = password[i];
    400 	/*
    401 	 * PasswordLength is 4 octets, but since the maximum password length is
    402 	 * 256, only first two (in little endian byte order) can be non-zero.
    403 	 */
    404 	pos = &pw_block[2 * 256];
    405 	WPA_PUT_LE16(pos, password_len * 2);
    406 	rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
    407 	return 0;
    408 }
    409 
    410 
    411 /**
    412  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
    413  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
    414  * @new_password_len: Length of new_password
    415  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
    416  * @old_password_len: Length of old_password
    417  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
    418  * Returns: 0 on success, -1 on failure
    419  */
    420 int new_password_encrypted_with_old_nt_password_hash(
    421 	const u8 *new_password, size_t new_password_len,
    422 	const u8 *old_password, size_t old_password_len,
    423 	u8 *encrypted_pw_block)
    424 {
    425 	u8 password_hash[16];
    426 
    427 	if (nt_password_hash(old_password, old_password_len, password_hash))
    428 		return -1;
    429 	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
    430 						password_hash,
    431 						encrypted_pw_block))
    432 		return -1;
    433 	return 0;
    434 }
    435 
    436 
    437 /**
    438  * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
    439  * @password_hash: 16-octer PasswordHash (IN)
    440  * @block: 16-octet Block (IN)
    441  * @cypher: 16-octer Cypher (OUT)
    442  */
    443 void nt_password_hash_encrypted_with_block(const u8 *password_hash,
    444 					   const u8 *block, u8 *cypher)
    445 {
    446 	des_encrypt(password_hash, block, cypher);
    447 	des_encrypt(password_hash + 8, block + 7, cypher + 8);
    448 }
    449 
    450 
    451 /**
    452  * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
    453  * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
    454  * @new_password_len: Length of new_password
    455  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
    456  * @old_password_len: Length of old_password
    457  * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
    458  * Returns: 0 on success, -1 on failure
    459  */
    460 int old_nt_password_hash_encrypted_with_new_nt_password_hash(
    461 	const u8 *new_password, size_t new_password_len,
    462 	const u8 *old_password, size_t old_password_len,
    463 	u8 *encrypted_password_hash)
    464 {
    465 	u8 old_password_hash[16], new_password_hash[16];
    466 
    467 	if (nt_password_hash(old_password, old_password_len,
    468 			     old_password_hash) ||
    469 	    nt_password_hash(new_password, new_password_len,
    470 			     new_password_hash))
    471 		return -1;
    472 	nt_password_hash_encrypted_with_block(old_password_hash,
    473 					      new_password_hash,
    474 					      encrypted_password_hash);
    475 	return 0;
    476 }
    477