+ /*
+ * "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 Digest[SHA1_SIGNATURE_SIZE];
+ u_char Challenge[8];
+
+ SHA1_Init(&sha1Context);
+ SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+ 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]);
+}
+
+
+static void
+GenerateAuthenticatorResponsePlain
+ (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])
+{
+ 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);
+}
+
+
+#ifdef MPPE
+
+/*
+ * 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_chapv1(rchallenge, PasswordHashHash);
+}
+
+/*
+ * 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)
+{
+ 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_chapv2(PasswordHashHash, NTResponse, IsServer);
+}
+
+#endif /* MPPE */
+
+
+void
+ChapMS(u_char *rchallenge, char *secret, int secret_len,
+ unsigned char *response)
+{
+ BZERO(response, MS_CHAP_RESPONSE_LEN);
+
+ ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);
+