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>