File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / msoft.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

    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>