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

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: {
1.1.1.3 ! misho      58:   const u_char*         clear = (const u_char *)"KGS!@#$%%";
1.1       misho      59:   u_char       up[14];         /* upper case password */
1.1.1.3 ! misho      60:   unsigned     k;
1.1       misho      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];
1.1.1.3 ! misho      81:   unsigned     unipwLen;
1.1       misho      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);
1.1.1.3 ! misho     110:   MD4_Update(&md4ctx, nthash, 16);
1.1       misho     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.3 ! misho     184: #ifdef __clang__
        !           185: #pragma clang diagnostic push
        !           186: #pragma clang diagnostic ignored "-Wcast-qual"
        !           187: #endif
        !           188:   DES_ecb_encrypt((const_DES_cblock *) clear, (DES_cblock *) cypher, &ks, 1);
        !           189: #ifdef __clang__
        !           190: #pragma clang diagnostic pop
        !           191: #endif
1.1       misho     192: }
                    193: 
                    194: /*
                    195:  * MsoftGetStartKey()
                    196:  */
                    197: 
                    198: void
                    199: MsoftGetStartKey(u_char *chal, u_char *h)
                    200: {
                    201:   SHA_CTX      c;
                    202:   u_char       hash[20];
                    203: 
                    204:   SHA1_Init(&c);
                    205:   SHA1_Update(&c, h, 16);
                    206:   SHA1_Update(&c, h, 16);
                    207:   SHA1_Update(&c, chal, 8);
                    208:   SHA1_Final(hash, &c);
                    209:   memcpy(h, hash, 16);
                    210: }
                    211: 
                    212: /*
                    213:  * GenerateNTResponse()
                    214:  *
                    215:  * authchal    16 byte authenticator challenge
                    216:  * peerchal    16 byte peer challenge
                    217:  * username    ASCII username
                    218:  * nthash      NT-Hash
                    219:  * hash                24 byte response
                    220:  */
                    221: 
                    222: void
                    223: GenerateNTResponse(const u_char *authchal, const u_char *peerchal,
                    224:   const char *username, const char *nthash, u_char *hash)
                    225: {
                    226:   u_char       chal[8];
                    227: 
                    228:   ChallengeHash(peerchal, authchal, username, chal);
                    229:   ChallengeResponse(chal, nthash, hash);
                    230: }
                    231: 
                    232: /*
                    233:  * ChallengeHash()
                    234:  *
                    235:  * peerchal    16 byte peer challenge
                    236:  * authchal    16 byte authenticator challenge
                    237:  * username    ASCII username
                    238:  * hash                8 byte response
                    239:  */
                    240: 
                    241: static void
                    242: ChallengeHash(const u_char *peerchal, const u_char *authchal,
                    243:   const char *username, u_char *hash)
                    244: {
                    245:   SHA_CTX      c;
                    246:   u_char       digest[20];
                    247: 
                    248:   SHA1_Init(&c);
                    249:   SHA1_Update(&c, peerchal, 16);
                    250:   SHA1_Update(&c, authchal, 16);
                    251:   SHA1_Update(&c, username, strlen(username));
                    252:   SHA1_Final(digest, &c);
                    253:   memcpy(hash, digest, 8);
                    254: }
                    255: 
                    256: /*
                    257:  * Generate response to MS-CHAPv2 piggy-backed challenge.
                    258:  *
                    259:  * "authresp" must point to a 20 byte buffer.
                    260:  */
                    261: void
                    262: GenerateAuthenticatorResponse(const u_char *nthash,
                    263:   const u_char *ntresp, const u_char *peerchal,
                    264:   const u_char *authchal, const char *username, u_char *authresp)
                    265: {
                    266:   u_char hash[16];
                    267:   u_char digest[SHA_DIGEST_LENGTH];
                    268:   u_char chal[8];
                    269:   MD4_CTX md4ctx;
                    270:   SHA_CTX shactx;
                    271: 
                    272:   MD4_Init(&md4ctx);
                    273:   MD4_Update(&md4ctx, nthash, 16);
                    274:   MD4_Final(hash, &md4ctx);
                    275: 
                    276:   SHA1_Init(&shactx);
                    277:   SHA1_Update(&shactx, hash, 16);
                    278:   SHA1_Update(&shactx, ntresp, 24);
                    279:   SHA1_Update(&shactx, MS_AR_MAGIC_1, 39);
                    280:   SHA1_Final(digest, &shactx);
                    281: 
                    282:   ChallengeHash(peerchal, authchal, username, chal);
                    283: 
                    284:   SHA1_Init(&shactx);
                    285:   SHA1_Update(&shactx, digest, sizeof(digest));
                    286:   SHA1_Update(&shactx, chal, 8);
                    287:   SHA1_Update(&shactx, MS_AR_MAGIC_2, 41);
                    288:   SHA1_Final(authresp, &shactx);
                    289: }
                    290: 
                    291: /*
                    292:  * MsoftGetMasterKey()
                    293:  */
                    294: 
                    295: void
                    296: MsoftGetMasterKey(u_char *resp, u_char *h)
                    297: {
                    298:   SHA_CTX      c;
                    299:   u_char       hash[20];
                    300: 
                    301:   SHA1_Init(&c);
                    302:   SHA1_Update(&c, h, 16);
                    303:   SHA1_Update(&c, resp, 24);
                    304:   SHA1_Update(&c, MS_MAGIC_1, 27);
                    305:   SHA1_Final(hash, &c);
                    306:   memcpy(h, hash, 16);
                    307: }
                    308: 
                    309: /*
                    310:  * MsoftGetAsymetricStartKey()
                    311:  */
                    312: 
                    313: void
                    314: MsoftGetAsymetricStartKey(u_char *h, int server_recv)
                    315: {
                    316:   SHA_CTX              c;
                    317:   u_char               pad[40];
                    318:   u_char               hash[20];
                    319: 
                    320:   SHA1_Init(&c);
                    321:   SHA1_Update(&c, h, 16);
                    322:   memset(pad, 0x00, sizeof(pad));
                    323:   SHA1_Update(&c, pad, sizeof(pad));
                    324:   SHA1_Update(&c, server_recv ? MS_MAGIC_2 : MS_MAGIC_3, 84);
                    325:   memset(pad, 0xf2, sizeof(pad));
                    326:   SHA1_Update(&c, pad, sizeof(pad));
                    327:   SHA1_Final(hash, &c);
                    328:   memcpy(h, hash, 16);
                    329: }
                    330: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>