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>