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>