?? mschap.c
字號:
#include <string.h>
#include "net.h"
#include "local.h"
#include "support.h"
#include "ppp.h"
#define TESTING 0 /* Set to 1 for testing this code standalone */
/* MS-CHAP makes use of the MD4 digest as described in rfc1320 */
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD4 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD4 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* MD4 context. */
typedef struct {
unsigned long int state[4]; /* state (ABCD) */
unsigned long int count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD4_CTX;
/* Constants for MD4Transform routine. */
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* FF4, GG4 and HH4 are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF4(a, b, c, d, x, s) { \
(a) += F((b), (c), (d)) + (x); \
(a) = ROTATE_LEFT((a), (s)); }
#define GG4(a, b, c, d, x, s) { \
(a) += G((b), (c), (d)) + (x) + (unsigned long int)0x5a827999; \
(a) = ROTATE_LEFT((a), (s)); }
#define HH4(a, b, c, d, x, s) { \
(a) += H((b), (c), (d)) + (x) + (unsigned long int)0x6ed9eba1; \
(a) = ROTATE_LEFT((a), (s)); }
/* Encodes input (unsigned long int) into output (unsigned char). Assumes len is
a multiple of 4. */
static void MD4encode(unsigned char *output, unsigned long int *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decode input (unsigned char) into output (unsigned long int). Assumes len is
a multiple of 4. */
static void MD4decode(unsigned long int *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((unsigned long int)input[j]) | (((unsigned long int)input[j+1]) << 8) |
(((unsigned long int)input[j+2]) << 16) | (((unsigned long int)input[j+3]) << 24);
}
/* MD4 basic transformation. Transforms state based on block. */
static void MD4Transform(unsigned long int state[4], unsigned char block[64])
{
unsigned long int a, b, c, d, x[16];
a = state[0];
b = state[1];
c = state[2];
d = state[3];
MD4decode(x, block, 64);
/* Round 1 */
FF4(a, b, c, d, x[ 0], S11);
FF4(d, a, b, c, x[ 1], S12);
FF4(c, d, a, b, x[ 2], S13);
FF4(b, c, d, a, x[ 3], S14);
FF4(a, b, c, d, x[ 4], S11);
FF4(d, a, b, c, x[ 5], S12);
FF4(c, d, a, b, x[ 6], S13);
FF4(b, c, d, a, x[ 7], S14);
FF4(a, b, c, d, x[ 8], S11);
FF4(d, a, b, c, x[ 9], S12);
FF4(c, d, a, b, x[10], S13);
FF4(b, c, d, a, x[11], S14);
FF4(a, b, c, d, x[12], S11);
FF4(d, a, b, c, x[13], S12);
FF4(c, d, a, b, x[14], S13);
FF4(b, c, d, a, x[15], S14);
/* Round 2 */
GG4(a, b, c, d, x[ 0], S21);
GG4(d, a, b, c, x[ 4], S22);
GG4(c, d, a, b, x[ 8], S23);
GG4(b, c, d, a, x[12], S24);
GG4(a, b, c, d, x[ 1], S21);
GG4(d, a, b, c, x[ 5], S22);
GG4(c, d, a, b, x[ 9], S23);
GG4(b, c, d, a, x[13], S24);
GG4(a, b, c, d, x[ 2], S21);
GG4(d, a, b, c, x[ 6], S22);
GG4(c, d, a, b, x[10], S23);
GG4(b, c, d, a, x[14], S24);
GG4(a, b, c, d, x[ 3], S21);
GG4(d, a, b, c, x[ 7], S22);
GG4(c, d, a, b, x[11], S23);
GG4(b, c, d, a, x[15], S24);
/* Round 3 */
HH4(a, b, c, d, x[ 0], S31);
HH4(d, a, b, c, x[ 8], S32);
HH4(c, d, a, b, x[ 4], S33);
HH4(b, c, d, a, x[12], S34);
HH4(a, b, c, d, x[ 2], S31);
HH4(d, a, b, c, x[10], S32);
HH4(c, d, a, b, x[ 6], S33);
HH4(b, c, d, a, x[14], S34);
HH4(a, b, c, d, x[ 1], S31);
HH4(d, a, b, c, x[ 9], S32);
HH4(c, d, a, b, x[ 5], S33);
HH4(b, c, d, a, x[13], S34);
HH4(a, b, c, d, x[ 3], S31);
HH4(d, a, b, c, x[11], S32);
HH4(c, d, a, b, x[ 7], S33);
HH4(b, c, d, a, x[15], S34);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset((unsigned char *)x, 0, sizeof (x));
}
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
static void MD4Init(MD4_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD4 block update operation. Continues an MD4 message-digest
operation, processing another message block, and updating the
context. */
static void MD4Update(MD4_CTX *context, unsigned char *input, unsigned int inputLen)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((unsigned long)inputLen << 3))
< ((unsigned long int)inputLen << 3))
context->count[1]++;
context->count[1] += ((unsigned long)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
Nmemcpy((unsigned char *)&context->buffer[index], (unsigned char *)input, partLen);
MD4Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD4Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
Nmemcpy((unsigned char *)&context->buffer[index], (unsigned char *)&input[i],inputLen-i);
}
/* MD4 finalization. Ends an MD4 message-digest operation, writing the
the message digest and zeroizing the context. */
static void MD4Final (unsigned char digest[16], MD4_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
MD4encode(bits, context->count, 8);
/* Pad out to 56 mod 64. */
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD4Update(context, PADDING, padLen);
/* Append length (before padding) */
MD4Update(context, bits, 8);
/* Store state in digest */
MD4encode(digest, context->state, 16);
/* Zeroize sensitive information. */
memset((unsigned char *)context, 0, sizeof (*context));
}
void MD4digest(unsigned char *in, unsigned int inLen, unsigned char *out)
{
MD4_CTX context;
MD4Init(&context);
MD4Update(&context, in, inLen);
MD4Final(out, &context);
}
/* End of MD4 */
/* MS-CHAP specific support routines */
void CombineClearKey2(unsigned char x[8], unsigned char key[8],
unsigned char Ret[8]);
static void CombineClearKey(unsigned char Clear[8], unsigned char Key[7],
unsigned char Ret[8])
{
unsigned char cp[8], sh;
int i; /* This is an integer named 'i' used for temporary storage */
for (cp[0]=0, i=0, sh=0xfe; i<7; sh<<=1, i++) {
cp[i] |= ((Key[i] & sh)>>i);
cp[i+1] = ((Key[i] & ~sh)<<(7-i));
}
/* Clear into Ret with Key (parity bits ('0's) included) */
CombineClearKey2(Clear, cp, Ret);
}
static void ChallengeResponse(unsigned char Challenge[8],
unsigned char PasswordHash[16], unsigned char Response[24])
{
unsigned char ZPasswordHash[21];
/* Initialize ZPasswordHash */
memset(ZPasswordHash, 0, sizeof(ZPasswordHash));
Nmemcpy(ZPasswordHash, PasswordHash, 16);
/* Generate Response */
CombineClearKey(Challenge, ZPasswordHash, Response);
CombineClearKey(Challenge, ZPasswordHash+7, Response+8);
CombineClearKey(Challenge, ZPasswordHash+14, Response+16);
}
/* STDTEXT is defined by Microsoft */
#define MS_STDTEXT "KGS!@#$%"
/* Input: challange, 0-14-oem-char case-insensitive password
** Output: response */
void LmChallengeResponse(unsigned char Challenge[8], unsigned char Password[14],
unsigned char Response[24])
{
unsigned char PasswordHash[16], UcasePassword[15];
int i;
memset(UcasePassword, 0, 15);
for (i=0; Password[i] && i < 14; i++)
UcasePassword[i] = (Password[i] > 0x60 && Password[i] < 0x7b) ?
Password[i] - 0x20 : Password[i];
CombineClearKey(MS_STDTEXT, UcasePassword, PasswordHash);
CombineClearKey(MS_STDTEXT, UcasePassword+7, PasswordHash+8);
ChallengeResponse(Challenge, PasswordHash, Response);
}
/* NT uses MD4digest to hash password
** Input: challenge, (char*) unicode password, length.
** Output: response */
void NtChallengeResponse(unsigned char Challenge[8], unsigned char Password[29],
int len, unsigned char Response[24])
{
unsigned char PasswordHash[16];
MD4digest(Password, (unsigned int)len, PasswordHash);
ChallengeResponse(Challenge, PasswordHash, Response);
}
#if TESTING != 0
/* This can be used to test ms-chap functions.
** Compile and link mschap.c and mschap2.c */
#include <stdio.h>
static unsigned char htc(unsigned char c)
{
if (c > 0x2f && c < 0x3a)
return c - 0x30;
if (c > 0x60 && c < 0x7b)
return c - 0x61 + 0xa;
if (c > 0x40 && c < 0x5b)
return c - 0x41 + 0xa;
else
return 0;
}
/*
RFC2433 standard test values...
Full Copyright Statement
Copyright (C) The Internet Society (1998). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
8-octet Challenge:
10 2D B5 DF 08 5D 30 41
0-to-256-unicode-char NtPassword ("MyPw"):
4D 00 79 00 50 00 77 00
24-octet NtChallengeResponse:
4E 9D 3C 8F 9C FD 38 5D 5B F4 D3 24 67 91 95 6C
A4 C3 51 AB 40 9A 3D 61
*/
void main(int argc, char **argv)
{
int i, plen;
unsigned char *cp, challenge[9], password[15], response[25],
gasword[29], ch[17];
if (argv[1][0] == '-') {
printf("This program tests two things:\n");
printf(" (1) NT/LM ch/rs: mschap <16-hex challenge> <14-ascii password>\n");
printf(" (2) MD4: mschap <14-ascii password>\n");
return;
}
memset(ch,0,17);
memset(challenge,0,9);
memset(password,0,15);
memset(response,0,25);
if (argc == 3) {
if (strlen(argv[1]) < 17) strcpy(ch, argv[1]);
else strcpy(ch, argv[1]);
if (strlen(argv[2]) < 15) strcpy(password, argv[2]);
else strcpy(password, argv[2]);
} else if (argc == 2) {
if (strlen(argv[1]) < 15) strcpy(password, argv[1]);
else strcpy(password, argv[1]);
printf("Password \"%s\"\n",password);
MD4digest(password, strlen(password), response);
printf("MD4 Digested password\n");
for (i=0; i<16; i++)
printf(" %02x",response[i]);
printf("\n");
return;
}
else
password[0] = 'a';
plen = (strlen(password)>14) ? 14 : strlen(password);
for (i=0; i<8; i++) {
if (ch[2*i] != 0 || ch[2*i+1] != 0)
challenge[i] = ((htc(ch[2*i])<<4) + htc(ch[2*i+1])) & 0xff;
}
memset(gasword, 0, 30);
for (i = 0; i<plen; i++)
gasword[i*2] = password[i]; /* Little byte ordering on purpose */
NtChallengeResponse(challenge, gasword, plen * 2, response);
printf("NT Challenge");
for (i=0; i<8; i++)
printf(" %02x", challenge[i]);
printf("\nNT Password");
for (i=0; i<plen; i++) {
if (i == 7)
printf("\n ");
printf(" %02x", gasword[2*i]);
printf(" %02x", gasword[2*i+1]);
}
printf("\nNT Response");
for (i=0; i<24; i++) {
if (i == 12)
printf("\n ");
printf(" %02x", response[i]);
}
memset(response,0,24);
LmChallengeResponse(challenge, password, response);
printf("\nLM Challenge");
for (i=0; i<8; i++)
printf(" %02x", challenge[i]);
printf("\nLM Password");
for (i=0; i<plen; i++)
printf(" %02x", password[i]);
printf("\nLM Response");
for (i=0; i<24; i++) {
if (i == 12)
printf("\n ");
printf(" %02x", response[i]);
}
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -