File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / msoft.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

    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*	 clear = (const u_char *)"KGS!@#$%%";
   59:   u_char	up[14];		/* upper case password */
   60:   unsigned	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:   unsigned	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, 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: #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
  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>