Annotation of embedaddon/mpd/src/msoft.c, revision 1.1.1.2

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: {
1.1.1.2 ! misho     167:   DES_key_schedule     ks;
1.1       misho     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;
1.1.1.2 ! misho     180:   DES_set_key((DES_cblock *) key, &ks);
1.1       misho     181: 
                    182: /* Encrypt using key */
                    183: 
1.1.1.2 ! misho     184:   DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, 1);
1.1       misho     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>