Annotation of embedaddon/libpdel/ppp/ppp_msoft.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include "ppp/ppp_defs.h"
42: #include "ppp/ppp_msoft.h"
43:
44: #include <openssl/md4.h>
45: #include <openssl/des.h>
46: #include <openssl/sha.h>
47:
48: /* Magic constants */
49: #define MS_MAGIC_1 "This is the MPPE Master Key"
50: #define MS_MAGIC_2 "On the client side, this is the send key;" \
51: " on the server side, it is the receive key."
52: #define MS_MAGIC_3 "On the client side, this is the receive key;" \
53: " on the server side, it is the send key."
54: #define MS_AR_MAGIC_1 "Magic server to client signing constant"
55: #define MS_AR_MAGIC_2 "Pad to make it do more than one iteration"
56:
57: /* Internal functions */
58: static void ppp_msoft_challenge_response(const u_char *chal,
59: const char *pwHash, u_char *hash);
60: static void ppp_msoft_des_encrypt(const u_char *clear,
61: u_char *key0, u_char *cypher);
62: static void ppp_msoft_challenge_hash(const u_char *peerchal,
63: const u_char *authchal, const char *username,
64: u_char *hash);
65:
66: /*
67: * ppp_msoft_lm_password_hash()
68: *
69: * password ASCII password
70: * hash 16 byte output LanManager hash
71: */
72: void
73: ppp_msoft_lm_password_hash(const char *password, u_char *hash)
74: {
75: const char *const clear = "KGS!@#$%%";
76: u_char up[14];
77: int k;
78:
79: memset(&up, 0, sizeof(up));
80: for (k = 0; k < sizeof(up) && password[k]; k++)
81: up[k] = toupper(password[k]);
82:
83: ppp_msoft_des_encrypt(clear, &up[0], &hash[0]);
84: ppp_msoft_des_encrypt(clear, &up[7], &hash[8]);
85: }
86:
87: /*
88: * ppp_msoft_nt_password_hash()
89: *
90: * password ASCII (NOT Unicode) password
91: * hash 16 byte output NT hash
92: */
93: void
94: ppp_msoft_nt_password_hash(const char *password, u_char *hash)
95: {
96: u_int16_t unipw[128];
97: const char *s;
98: int unipwLen;
99: MD4_CTX ctx;
100:
101: /* Convert password to Unicode */
102: for (unipwLen = 0, s = password;
103: unipwLen < sizeof(unipw) / 2 && *s; s++)
104: unipw[unipwLen++] = htons(*s << 8);
105:
106: /* Compute MD4 of Unicode password */
107: MD4_Init(&ctx);
108: MD4_Update(&ctx, (u_char *)unipw, unipwLen * sizeof(*unipw));
109: MD4_Final(hash, &ctx);
110: }
111:
112: /*
113: * ppp_msoft_nt_challenge_response()
114: *
115: * chal 8 byte challenge
116: * password ASCII (NOT Unicode) password
117: * hash 24 byte response
118: */
119: void
120: ppp_msoft_nt_challenge_response(const u_char *chal,
121: const char *password, u_char *hash)
122: {
123: u_char pwHash[16];
124:
125: ppp_msoft_nt_password_hash(password, pwHash);
126: ppp_msoft_challenge_response(chal, pwHash, hash);
127: }
128:
129: /*
130: * ppp_msoft_challenge_response()
131: *
132: * chal 8 byte challenge
133: * pwHash 16 byte password hash
134: * hash 24 byte response
135: */
136: static void
137: ppp_msoft_challenge_response(const u_char *chal,
138: const char *pwHash, u_char *hash)
139: {
140: u_char buf[21];
141: int i;
142:
143: /* Initialize buffer */
144: memset(&buf, 0, sizeof(buf));
145: memcpy(buf, pwHash, 16);
146:
147: /* Use DES to hash the hash */
148: for (i = 0; i < 3; i++) {
149: u_char *const key = &buf[i * 7];
150: u_char *const output = &hash[i * 8];
151:
152: ppp_msoft_des_encrypt(chal, key, output);
153: }
154: }
155:
156: /*
157: * ppp_msoft_des_encrypt()
158: *
159: * clear 8 byte cleartext
160: * key 7 byte key
161: * cypher 8 byte cyphertext
162: */
163: static void
164: ppp_msoft_des_encrypt(const u_char *clear, u_char *key0, u_char *cypher)
165: {
166: des_key_schedule ks;
167: u_char key[8];
168:
169: /*
170: * Create DES key
171: *
172: * Note: we don't bother setting the parity bit because
173: * the des_set_key() algorithm does that for us. A different
174: * algorithm may care though.
175: */
176: key[0] = key0[0] & 0xfe;
177: key[1] = (key0[0] << 7) | (key0[1] >> 1);
178: key[2] = (key0[1] << 6) | (key0[2] >> 2);
179: key[3] = (key0[2] << 5) | (key0[3] >> 3);
180: key[4] = (key0[3] << 4) | (key0[4] >> 4);
181: key[5] = (key0[4] << 3) | (key0[5] >> 5);
182: key[6] = (key0[5] << 2) | (key0[6] >> 6);
183: key[7] = key0[6] << 1;
184: des_set_key((des_cblock *)key, ks);
185:
186: /* Encrypt using key */
187: des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cypher, ks, 1);
188: }
189:
190: /*
191: * ppp_msoft_get_start_key()
192: */
193: void
194: ppp_msoft_get_start_key(const u_char *chal, u_char *hash)
195: {
196: u_char sha1[SHA_DIGEST_LENGTH];
197: SHA_CTX ctx;
198:
199: SHA1_Init(&ctx);
200: SHA1_Update(&ctx, hash, 16);
201: SHA1_Update(&ctx, hash, 16);
202: SHA1_Update(&ctx, chal, 8);
203: SHA1_Final(sha1, &ctx);
204: memcpy(hash, sha1, 16);
205: }
206:
207: /*
208: * ppp_msoft_generate_nt_response()
209: *
210: * authchal 16 byte authenticator challenge
211: * peerchal 16 byte peer challenge
212: * username ASCII username
213: * password ASCII (NOT Unicode) password
214: * hash 24 byte response
215: */
216: void
217: ppp_msoft_generate_nt_response(const u_char *authchal, const u_char *peerchal,
218: const char *username, const char *password, u_char *hash)
219: {
220: u_char chal[8];
221: u_char pwHash[16];
222:
223: ppp_msoft_challenge_hash(peerchal, authchal, username, chal);
224: ppp_msoft_nt_password_hash(password, pwHash);
225: ppp_msoft_challenge_response(chal, pwHash, hash);
226: }
227:
228: /*
229: * ppp_msoft_challenge_hash()
230: *
231: * peerchal 16 byte peer challenge
232: * authchal 16 byte authenticator challenge
233: * username ASCII username
234: * hash 8 byte response
235: */
236: static void
237: ppp_msoft_challenge_hash(const u_char *peerchal, const u_char *authchal,
238: const char *username, u_char *hash)
239: {
240: u_char sha1[SHA_DIGEST_LENGTH];
241: SHA_CTX ctx;
242: const char *slash;
243:
244: /* Strip off NT domain (if any) */
245: if ((slash = strrchr(username, '\\')) != NULL)
246: username = slash + 1;
247: SHA1_Init(&ctx);
248: SHA1_Update(&ctx, peerchal, 16);
249: SHA1_Update(&ctx, authchal, 16);
250: SHA1_Update(&ctx, username, strlen(username));
251: SHA1_Final(sha1, &ctx);
252: memcpy(hash, sha1, 8);
253: }
254:
255: /*
256: * Compute master key for MPPE
257: */
258: void
259: ppp_msoft_get_master_key(const u_char *resp, u_char *hash)
260: {
261: u_char sha1[SHA_DIGEST_LENGTH];
262: SHA_CTX ctx;
263:
264: SHA1_Init(&ctx);
265: SHA1_Update(&ctx, hash, 16);
266: SHA1_Update(&ctx, resp, 24);
267: SHA1_Update(&ctx, MS_MAGIC_1, 27);
268: SHA1_Final(sha1, &ctx);
269: memcpy(hash, sha1, 16);
270: }
271:
272: /*
273: * Compute asymmetric start key for MPPE (MS-CHAPv2 authentication)
274: *
275: * which Zero for server xmit/client recv, 1 for server recv/client xmit
276: */
277: void
278: ppp_msoft_get_asymetric_start_key(int which, const u_char *master, u_char *key)
279: {
280: u_char sha1[SHA_DIGEST_LENGTH];
281: u_char sha_pad[2][40];
282: SHA_CTX ctx;
283:
284: /* Generate start key */
285: memset(&sha_pad[0], 0x00, sizeof(sha_pad[0]));
286: memset(&sha_pad[1], 0xf2, sizeof(sha_pad[1]));
287: SHA1_Init(&ctx);
288: SHA1_Update(&ctx, master, 16);
289: SHA1_Update(&ctx, sha_pad[0], 40);
290: SHA1_Update(&ctx, which ? MS_MAGIC_2 : MS_MAGIC_3, 84);
291: SHA1_Update(&ctx, sha_pad[1], 40);
292: SHA1_Final(sha1, &ctx);
293: memcpy(key, sha1, 16);
294: }
295:
296: /*
297: * Initialize MPPE key based on MS-CHAPv1 credentials.
298: *
299: * e128 Non-zero for 128 bit key, zero for 64 bit key.
300: * pass Originating side's password
301: * chal Answering side's challenge
302: * key 16 byte output buffer
303: */
304: void
305: ppp_msoft_init_key_v1(int e128,
306: const char *pass, const u_char *chal, u_char *key)
307: {
308: if (e128) { /* 128 bit key */
309: u_char hash[16];
310: MD4_CTX ctx;
311:
312: ppp_msoft_nt_password_hash(pass, hash);
313: MD4_Init(&ctx);
314: MD4_Update(&ctx, hash, 16);
315: MD4_Final(hash, &ctx);
316: ppp_msoft_get_start_key(chal, hash);
317: memcpy(key, hash, 16);
318: } else /* 40 or 56 bit key */
319: ppp_msoft_lm_password_hash(pass, key);
320: }
321:
322: /*
323: * Initialize MPPE key based on MS-CHAPv2 credentials.
324: *
325: * which Zero for server xmit/client recv, 1 for server recv/client xmit
326: * pass Originating side's password
327: * resp Answering side's challenge response hash
328: * key 16 byte output buffer
329: */
330: void
331: ppp_msoft_init_key_v2(int which,
332: const char *pass, const u_char *resp, u_char *key)
333: {
334: u_char hash[16];
335: MD4_CTX ctx;
336:
337: ppp_msoft_nt_password_hash(pass, hash);
338: MD4_Init(&ctx);
339: MD4_Update(&ctx, hash, 16);
340: MD4_Final(hash, &ctx);
341: ppp_msoft_get_master_key(resp, hash);
342: ppp_msoft_get_asymetric_start_key(which, hash, key);
343: }
344:
345: /*
346: * Generate response to MS-CHAPv2 piggy-backed challenge.
347: *
348: * "authresp" must point to a 20 byte buffer.
349: */
350: void
351: ppp_msoft_generate_authenticator_response(const char *password,
352: const u_char *ntresp, const u_char *peerchal,
353: const u_char *authchal, const char *username, u_char *authresp)
354: {
355: u_char hash[16];
356: u_char digest[SHA_DIGEST_LENGTH];
357: u_char chal[8];
358: MD4_CTX md4ctx;
359: SHA_CTX shactx;
360:
361: ppp_msoft_nt_password_hash(password, hash);
362:
363: MD4_Init(&md4ctx);
364: MD4_Update(&md4ctx, hash, 16);
365: MD4_Final(hash, &md4ctx);
366:
367: SHA1_Init(&shactx);
368: SHA1_Update(&shactx, hash, 16);
369: SHA1_Update(&shactx, ntresp, 24);
370: SHA1_Update(&shactx, MS_AR_MAGIC_1, 39);
371: SHA1_Final(digest, &shactx);
372:
373: ppp_msoft_challenge_hash(peerchal, authchal, username, chal);
374:
375: SHA1_Init(&shactx);
376: SHA1_Update(&shactx, digest, sizeof(digest));
377: SHA1_Update(&shactx, chal, 8);
378: SHA1_Update(&shactx, MS_AR_MAGIC_2, 41);
379: SHA1_Final(authresp, &shactx);
380: }
381:
382: /*
383: * Verify server's piggy-backed response.
384: *
385: * Returns 1 if OK, otherwise zero.
386: */
387: int
388: ppp_msoft_check_authenticator_response(const char *password,
389: const u_char *ntresp, const u_char *peerchal, const u_char *authchal,
390: const char *username, const char *rechash)
391: {
392: char authresp[43];
393:
394: ppp_msoft_generate_authenticator_response(password, ntresp,
395: peerchal, authchal, username, authresp);
396: return (strcmp(rechash, authresp) == 0);
397: }
398:
399:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>