Annotation of embedaddon/mpd/src/msoft.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * msoft.c
! 4: *
! 5: * Rewritten by Archie Cobbs <archie@freebsd.org>
! 6: * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.whistle''
! 8: */
! 9:
! 10: #include "ppp.h"
! 11: #include "msoft.h"
! 12: #include <openssl/sha.h>
! 13: #include <openssl/md4.h>
! 14: #include <openssl/des.h>
! 15:
! 16: /*
! 17: * This stuff is described in:
! 18: *
! 19: * MS-CHAPv1
! 20: * http://www.es.net/pub/rfcs/rfc2433.txt
! 21: *
! 22: * MS-CHAPv2
! 23: * http://www.es.net/pub/rfcs/rfc2759.txt
! 24: *
! 25: * Deriving MPPE keys from MS-CHAPv1 and MS-CHAPv2
! 26: * http://www.es.net/pub/rfcs/rfc3079.txt
! 27: */
! 28:
! 29: /* Magic constants */
! 30: #define MS_MAGIC_1 "This is the MPPE Master Key"
! 31: #define MS_MAGIC_2 "On the client side, this is the send key;" \
! 32: " on the server side, it is the receive key."
! 33: #define MS_MAGIC_3 "On the client side, this is the receive key;" \
! 34: " on the server side, it is the send key."
! 35: #define MS_AR_MAGIC_1 "Magic server to client signing constant"
! 36: #define MS_AR_MAGIC_2 "Pad to make it do more than one iteration"
! 37:
! 38: /*
! 39: * INTERNAL FUNCTIONS
! 40: */
! 41:
! 42: static void ChallengeResponse(const u_char *chal,
! 43: const char *pwHash, u_char *hash);
! 44: static void DesEncrypt(const u_char *clear, u_char *key0, u_char *cypher);
! 45: static void ChallengeHash(const u_char *peerchal, const u_char *authchal,
! 46: const char *username, u_char *hash);
! 47:
! 48: /*
! 49: * LMPasswordHash()
! 50: *
! 51: * password ASCII password
! 52: * hash 16 byte output LanManager hash
! 53: */
! 54:
! 55: void
! 56: LMPasswordHash(const char *password, u_char *hash)
! 57: {
! 58: const u_char *const clear = (u_char *) "KGS!@#$%%";
! 59: u_char up[14]; /* upper case password */
! 60: int k;
! 61:
! 62: memset(&up, 0, sizeof(up));
! 63: for (k = 0; k < sizeof(up) && password[k]; k++)
! 64: up[k] = toupper(password[k]);
! 65:
! 66: DesEncrypt(clear, &up[0], &hash[0]);
! 67: DesEncrypt(clear, &up[7], &hash[8]);
! 68: }
! 69:
! 70: /*
! 71: * NTPasswordHash()
! 72: *
! 73: * password ASCII (NOT Unicode) password
! 74: * hash 16 byte output NT hash
! 75: */
! 76:
! 77: void
! 78: NTPasswordHash(const char *password, u_char *hash)
! 79: {
! 80: u_int16_t unipw[128];
! 81: int unipwLen;
! 82: MD4_CTX md4ctx;
! 83: const char *s;
! 84:
! 85: /* Convert password to Unicode */
! 86:
! 87: for (unipwLen = 0, s = password; unipwLen < sizeof(unipw) / 2 && *s; s++)
! 88: unipw[unipwLen++] = htons(*s << 8);
! 89:
! 90: /* Compute MD4 of Unicode password */
! 91:
! 92: MD4_Init(&md4ctx);
! 93: MD4_Update(&md4ctx, (u_char *) unipw, unipwLen * sizeof(*unipw));
! 94: MD4_Final(hash, &md4ctx);
! 95: }
! 96:
! 97: /*
! 98: * NTPasswordHashHash()
! 99: *
! 100: * nthash 16 bytes NT-Hash
! 101: * hash 16 bytes MD4 of NT-hash
! 102: */
! 103:
! 104: void
! 105: NTPasswordHashHash(const u_char *nthash, u_char *hash)
! 106: {
! 107: MD4_CTX md4ctx;
! 108:
! 109: MD4_Init(&md4ctx);
! 110: MD4_Update(&md4ctx, (u_char *) nthash, 16);
! 111: MD4_Final(hash, &md4ctx);
! 112: }
! 113:
! 114: /*
! 115: * NTChallengeResponse()
! 116: *
! 117: * chal 8 byte challenge
! 118: * nthash NT-Hash
! 119: * hash 24 byte response
! 120: */
! 121:
! 122: void
! 123: NTChallengeResponse(const u_char *chal, const char *nthash, u_char *hash)
! 124: {
! 125: ChallengeResponse(chal, nthash, hash);
! 126: }
! 127:
! 128: /*
! 129: * ChallengeResponse()
! 130: *
! 131: * chal 8 byte challenge
! 132: * pwHash 16 byte password hash
! 133: * hash 24 byte response
! 134: */
! 135:
! 136: static void
! 137: ChallengeResponse(const u_char *chal, const char *pwHash, u_char *hash)
! 138: {
! 139: u_char buf[21];
! 140: int k;
! 141:
! 142: memset(&buf, 0, sizeof(buf));
! 143: memcpy(buf, pwHash, 16);
! 144:
! 145: /* Use DES to hash the hash */
! 146:
! 147: for (k = 0; k < 3; k++)
! 148: {
! 149: u_char *const key = &buf[k * 7];
! 150: u_char *const output = &hash[k * 8];
! 151:
! 152: DesEncrypt(chal, key, output);
! 153: }
! 154: }
! 155:
! 156: /*
! 157: * DesEncrypt()
! 158: *
! 159: * clear 8 byte cleartext
! 160: * key 7 byte key
! 161: * cypher 8 byte cyphertext
! 162: */
! 163:
! 164: static void
! 165: DesEncrypt(const u_char *clear, u_char *key0, u_char *cypher)
! 166: {
! 167: des_key_schedule ks;
! 168: u_char key[8];
! 169:
! 170: /* Create DES key */
! 171:
! 172: key[0] = key0[0] & 0xfe;
! 173: key[1] = (key0[0] << 7) | (key0[1] >> 1);
! 174: key[2] = (key0[1] << 6) | (key0[2] >> 2);
! 175: key[3] = (key0[2] << 5) | (key0[3] >> 3);
! 176: key[4] = (key0[3] << 4) | (key0[4] >> 4);
! 177: key[5] = (key0[4] << 3) | (key0[5] >> 5);
! 178: key[6] = (key0[5] << 2) | (key0[6] >> 6);
! 179: key[7] = key0[6] << 1;
! 180: des_set_key((des_cblock *) key, ks);
! 181:
! 182: /* Encrypt using key */
! 183:
! 184: des_ecb_encrypt((des_cblock *) clear, (des_cblock *) cypher, ks, 1);
! 185: }
! 186:
! 187: /*
! 188: * MsoftGetStartKey()
! 189: */
! 190:
! 191: void
! 192: MsoftGetStartKey(u_char *chal, u_char *h)
! 193: {
! 194: SHA_CTX c;
! 195: u_char hash[20];
! 196:
! 197: SHA1_Init(&c);
! 198: SHA1_Update(&c, h, 16);
! 199: SHA1_Update(&c, h, 16);
! 200: SHA1_Update(&c, chal, 8);
! 201: SHA1_Final(hash, &c);
! 202: memcpy(h, hash, 16);
! 203: }
! 204:
! 205: /*
! 206: * GenerateNTResponse()
! 207: *
! 208: * authchal 16 byte authenticator challenge
! 209: * peerchal 16 byte peer challenge
! 210: * username ASCII username
! 211: * nthash NT-Hash
! 212: * hash 24 byte response
! 213: */
! 214:
! 215: void
! 216: GenerateNTResponse(const u_char *authchal, const u_char *peerchal,
! 217: const char *username, const char *nthash, u_char *hash)
! 218: {
! 219: u_char chal[8];
! 220:
! 221: ChallengeHash(peerchal, authchal, username, chal);
! 222: ChallengeResponse(chal, nthash, hash);
! 223: }
! 224:
! 225: /*
! 226: * ChallengeHash()
! 227: *
! 228: * peerchal 16 byte peer challenge
! 229: * authchal 16 byte authenticator challenge
! 230: * username ASCII username
! 231: * hash 8 byte response
! 232: */
! 233:
! 234: static void
! 235: ChallengeHash(const u_char *peerchal, const u_char *authchal,
! 236: const char *username, u_char *hash)
! 237: {
! 238: SHA_CTX c;
! 239: u_char digest[20];
! 240:
! 241: SHA1_Init(&c);
! 242: SHA1_Update(&c, peerchal, 16);
! 243: SHA1_Update(&c, authchal, 16);
! 244: SHA1_Update(&c, username, strlen(username));
! 245: SHA1_Final(digest, &c);
! 246: memcpy(hash, digest, 8);
! 247: }
! 248:
! 249: /*
! 250: * Generate response to MS-CHAPv2 piggy-backed challenge.
! 251: *
! 252: * "authresp" must point to a 20 byte buffer.
! 253: */
! 254: void
! 255: GenerateAuthenticatorResponse(const u_char *nthash,
! 256: const u_char *ntresp, const u_char *peerchal,
! 257: const u_char *authchal, const char *username, u_char *authresp)
! 258: {
! 259: u_char hash[16];
! 260: u_char digest[SHA_DIGEST_LENGTH];
! 261: u_char chal[8];
! 262: MD4_CTX md4ctx;
! 263: SHA_CTX shactx;
! 264:
! 265: MD4_Init(&md4ctx);
! 266: MD4_Update(&md4ctx, nthash, 16);
! 267: MD4_Final(hash, &md4ctx);
! 268:
! 269: SHA1_Init(&shactx);
! 270: SHA1_Update(&shactx, hash, 16);
! 271: SHA1_Update(&shactx, ntresp, 24);
! 272: SHA1_Update(&shactx, MS_AR_MAGIC_1, 39);
! 273: SHA1_Final(digest, &shactx);
! 274:
! 275: ChallengeHash(peerchal, authchal, username, chal);
! 276:
! 277: SHA1_Init(&shactx);
! 278: SHA1_Update(&shactx, digest, sizeof(digest));
! 279: SHA1_Update(&shactx, chal, 8);
! 280: SHA1_Update(&shactx, MS_AR_MAGIC_2, 41);
! 281: SHA1_Final(authresp, &shactx);
! 282: }
! 283:
! 284: /*
! 285: * MsoftGetMasterKey()
! 286: */
! 287:
! 288: void
! 289: MsoftGetMasterKey(u_char *resp, u_char *h)
! 290: {
! 291: SHA_CTX c;
! 292: u_char hash[20];
! 293:
! 294: SHA1_Init(&c);
! 295: SHA1_Update(&c, h, 16);
! 296: SHA1_Update(&c, resp, 24);
! 297: SHA1_Update(&c, MS_MAGIC_1, 27);
! 298: SHA1_Final(hash, &c);
! 299: memcpy(h, hash, 16);
! 300: }
! 301:
! 302: /*
! 303: * MsoftGetAsymetricStartKey()
! 304: */
! 305:
! 306: void
! 307: MsoftGetAsymetricStartKey(u_char *h, int server_recv)
! 308: {
! 309: SHA_CTX c;
! 310: u_char pad[40];
! 311: u_char hash[20];
! 312:
! 313: SHA1_Init(&c);
! 314: SHA1_Update(&c, h, 16);
! 315: memset(pad, 0x00, sizeof(pad));
! 316: SHA1_Update(&c, pad, sizeof(pad));
! 317: SHA1_Update(&c, server_recv ? MS_MAGIC_2 : MS_MAGIC_3, 84);
! 318: memset(pad, 0xf2, sizeof(pad));
! 319: SHA1_Update(&c, pad, sizeof(pad));
! 320: SHA1_Final(hash, &c);
! 321: memcpy(h, hash, 16);
! 322: }
! 323:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>