/* * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) */ static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; lwip_sha1_context sha1Context; u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); lwip_sha1_init(&sha1Context); lwip_sha1_starts(&sha1Context); lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); lwip_sha1_update(&sha1Context, rchallenge, 8); lwip_sha1_finish(&sha1Context, Digest); lwip_sha1_free(&sha1Context); /* Same key in both directions. */ mppe_set_key(pcb, &pcb->mppe_comp, Digest); mppe_set_key(pcb, &pcb->mppe_decomp, Digest); pcb->mppe_keys_set = 1; }
static void NTPasswordHashHash(const uint8_t * password, uint32_t password_len, uint8_t ret_hash[NT_PASSWORD_HASH_SIZE]) { uint8_t hash[NT_PASSWORD_HASH_SIZE]; NTPasswordHash(password, password_len, hash); NTPasswordHash(hash, NT_PASSWORD_HASH_SIZE, ret_hash); return; }
static void GenerateAuthenticatorResponse(char *secret, int secret_len, u_char NTResponse[24], u_char PeerChallenge[16], u_char *rchallenge, char *username, u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { /* * "Magic" constants used in response generation, from RFC 2759. */ u_char Magic1[39] = /* "Magic server to client signing constant" */ { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E }; int i; SHA1_CTX sha1Context; u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; u_char Digest[SHA1_SIGNATURE_SIZE]; u_char Challenge[8]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); SHA1_Init(&sha1Context); SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash)); SHA1_Update(&sha1Context, NTResponse, 24); SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); SHA1_Final(Digest, &sha1Context); ChallengeHash(PeerChallenge, rchallenge, username, Challenge); SHA1_Init(&sha1Context); SHA1_Update(&sha1Context, Digest, sizeof(Digest)); SHA1_Update(&sha1Context, Challenge, sizeof(Challenge)); SHA1_Update(&sha1Context, Magic2, sizeof(Magic2)); SHA1_Final(Digest, &sha1Context); /* Convert to ASCII hex string. */ for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++) sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); }
/* * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) */ static void Set_Start_Key(u_char *rchallenge, char *secret, int secret_len) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); mppe_set_keys(rchallenge, PasswordHashHash); }
static void GenerateAuthenticatorResponsePlain( const char *secret, int secret_len, u_char NTResponse[24], const u_char PeerChallenge[16], const u_char *rchallenge, const char *username, u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, rchallenge, username, authResponse); }
static void NTChallengeResponse(const uint8_t challenge[MSCHAP_NT_CHALLENGE_SIZE], const uint8_t * password, uint32_t password_len, uint8_t response[MSCHAP_NT_RESPONSE_SIZE]) { uint8_t hash[NT_PASSWORD_HASH_SIZE]; NTPasswordHash(password, password_len, hash); ChallengeResponse(challenge, hash, response); return; }
static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, u_char NTResponse[24]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; /* Hash the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); ChallengeResponse(rchallenge, PasswordHash, NTResponse); }
/* * RFC 2759, Section 8.12 * OldNtPasswordHashEncryptedWithNewNtPasswordHash() */ void NTPasswordHashEncryptOldWithNew(const uint8_t * new_password, uint32_t new_password_len, const uint8_t * old_password, uint32_t old_password_len, uint8_t encrypted_hash[NT_PASSWORD_HASH_SIZE]) { uint8_t new_password_unicode[NT_MAXPWLEN * 2]; uint8_t new_pw_hash[NT_PASSWORD_HASH_SIZE]; uint8_t old_password_unicode[NT_MAXPWLEN * 2]; uint8_t old_pw_hash[NT_PASSWORD_HASH_SIZE]; new_password_len = password_to_unicode(new_password, new_password_len, new_password_unicode); NTPasswordHash(new_password_unicode, new_password_len, new_pw_hash); old_password_len = password_to_unicode(old_password, old_password_len, old_password_unicode); NTPasswordHash(old_password_unicode, old_password_len, old_pw_hash); NTPasswordHashEncryptedWithBlock(old_pw_hash, new_pw_hash, encrypted_hash); return; }
static void ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username, char *secret, int secret_len, u_char NTResponse[24]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char Challenge[8]; ChallengeHash(PeerChallenge, rchallenge, username, Challenge); /* Hash the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); ChallengeResponse(Challenge, PasswordHash, NTResponse); }
/* * RFC 2759, Section 8.9 * NewPasswordEncryptedWithOldNtPasswordHash */ void NTPasswordBlockEncryptNewPasswordWithOldHash(const uint8_t * new_password, uint32_t new_password_len, const uint8_t * old_password, uint32_t old_password_len, NTPasswordBlockRef pwblock) { uint8_t hash[NT_PASSWORD_HASH_SIZE]; uint8_t new_password_unicode[NT_MAXPWLEN * 2]; uint8_t old_password_unicode[NT_MAXPWLEN * 2]; new_password_len = password_to_unicode(new_password, new_password_len, new_password_unicode); old_password_len = password_to_unicode(old_password, old_password_len, old_password_unicode); NTPasswordHash(old_password_unicode, old_password_len, hash); EncryptPwBlockWithPasswordHash(new_password_unicode, new_password_len, hash, pwblock); return; }
/* * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) */ static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; lwip_sha1_context sha1Context; u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ const u_char *s; /* "This is the MPPE Master Key" */ static const u_char Magic1[27] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; /* "On the client side, this is the send key; " "on the server side, it is the receive key." */ static const u_char Magic2[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x2e }; /* "On the client side, this is the receive key; " "on the server side, it is the send key." */ static const u_char Magic3[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x2e }; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); lwip_sha1_init(&sha1Context); lwip_sha1_starts(&sha1Context); lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); lwip_sha1_update(&sha1Context, NTResponse, 24); lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); lwip_sha1_finish(&sha1Context, MasterKey); lwip_sha1_free(&sha1Context); /* * generate send key */ if (IsServer) s = Magic3; else s = Magic2; lwip_sha1_init(&sha1Context); lwip_sha1_starts(&sha1Context); lwip_sha1_update(&sha1Context, MasterKey, 16); lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); lwip_sha1_update(&sha1Context, s, 84); lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); lwip_sha1_finish(&sha1Context, Digest); lwip_sha1_free(&sha1Context); mppe_set_key(pcb, &pcb->mppe_comp, Digest); /* * generate recv key */ if (IsServer) s = Magic2; else s = Magic3; lwip_sha1_init(&sha1Context); lwip_sha1_starts(&sha1Context); lwip_sha1_update(&sha1Context, MasterKey, 16); lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); lwip_sha1_update(&sha1Context, s, 84); lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); lwip_sha1_finish(&sha1Context, Digest); lwip_sha1_free(&sha1Context); mppe_set_key(pcb, &pcb->mppe_decomp, Digest); pcb->mppe_keys_set = 1; }
/* * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) */ static void SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer) { SHA1_CTX sha1Context; u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ u_char SHApad1[40] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; u_char SHApad2[40] = { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; /* "This is the MPPE Master Key" */ u_char Magic1[27] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; /* "On the client side, this is the send key; " "on the server side, it is the receive key." */ u_char Magic2[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x2e }; /* "On the client side, this is the receive key; " "on the server side, it is the send key." */ u_char Magic3[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x2e }; u_char *s; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); SHA1_Init(&sha1Context); SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash)); SHA1_Update(&sha1Context, NTResponse, 24); SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); SHA1_Final(MasterKey, &sha1Context); /* * generate send key */ if (IsServer) s = Magic3; else s = Magic2; SHA1_Init(&sha1Context); SHA1_Update(&sha1Context, MasterKey, 16); SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); SHA1_Update(&sha1Context, s, 84); SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); SHA1_Final(Digest, &sha1Context); BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key)); /* * generate recv key */ if (IsServer) s = Magic2; else s = Magic3; SHA1_Init(&sha1Context); SHA1_Update(&sha1Context, MasterKey, 16); SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); SHA1_Update(&sha1Context, s, 84); SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); SHA1_Final(Digest, &sha1Context); BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key)); }