4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * Copyright 2001,2002 Google, Inc.
19 * Copyright 2005,2006 TRI-D Systems, Inc.
25 /* avoid inclusion of these FR headers which conflict w/ OpenSSL */
29 #include <rad_assert.h>
35 #include <openssl/des.h>
36 #include <openssl/md4.h>
37 #include <openssl/md5.h>
38 #include <openssl/sha.h>
43 * Add MPPE attributes to a request, if required.
46 otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
49 VALUE_PAIR **avp = &request->reply->vps;
50 VALUE_PAIR *cvp, *rvp, *vp;
52 cvp = pairfind(request->packet->vps, pwattr[pwe - 1]);
53 rvp = pairfind(request->packet->vps, pwattr[pwe]);
61 /* First, set some related attributes. */
62 vp = pairmake("MS-MPPE-Encryption-Policy",
63 otp_mppe_policy[opt->mschap_mppe_policy], T_OP_EQ);
64 rad_assert(vp != NULL);
66 vp = pairmake("MS-MPPE-Encryption-Types",
67 otp_mppe_types[opt->mschap_mppe_types], T_OP_EQ);
68 rad_assert(vp != NULL);
71 /* If no MPPE, we're done. */
72 if (!opt->mschap_mppe_policy)
76 * Generate the MS-CHAP-MPPE-Keys attribute. This is not specified
77 * anywhere -- RFC 2548, par. 2.4.1 is the authority but it has
78 * typos and omissions that make this unimplementable. The
79 * code here is based on experimental results provided by
80 * Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp>.
81 * We only support 128-bit keys derived from the NT hash; 40-bit
82 * and 56-bit keys are derived from the LM hash, which besides
83 * being deprecated, has severe security problems.
86 size_t i, passcode_len;
87 unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];
88 unsigned char password_md[MD4_DIGEST_LENGTH];
89 unsigned char mppe_keys[32];
90 /* 0x ASCII(mppe_keys) '\0' */
91 char mppe_keys_string[2 + (2 * sizeof(mppe_keys)) + 1];
93 /* Zero the LM-Key sub-field (and padding). */
94 (void) memset(mppe_keys, 0, sizeof(mppe_keys));
97 * The NT-Key sub-field is MD4(MD4(unicode(password))).
98 * Start by hashing the unicode passcode.
99 * This is broken because unicode chars are machine-ordered,
100 * but the spec (RFC 2433) doesn't say how to prepare
101 * the password for md4 (other than by example values).
103 passcode_len = strlen(passcode);
104 for (i = 0; i < passcode_len; ++i) {
105 /* Set the high order 8 bits to 0 (little-endian) */
106 password_unicode[i * 2] = *passcode++;
107 password_unicode[i * 2 + 1] = 0;
110 (void) MD4(password_unicode, 2 * passcode_len, password_md);
112 (void) MD4(password_md, MD4_DIGEST_LENGTH, &mppe_keys[8]);
114 #if 0 /* encoding now handled in lib/radius.c:rad_pwencode() */
116 unsigned char md5_md[MD5_DIGEST_LENGTH];
117 unsigned char encode_buf[AUTH_VECTOR_LEN + MAX_STRING_LEN];
120 /* Now we must encode the key as User-Password is encoded. */
121 secretlen = strlen(request->secret);
122 (void) memcpy(encode_buf, request->secret, secretlen);
123 (void) memcpy(encode_buf + secretlen, request->packet->vector,
125 (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN, md5_md);
126 for (i = 0; i < 16; ++i)
127 mppe_keys[i] ^= md5_md[i];
128 (void) memcpy(encode_buf + secretlen, mppe_keys, MD5_DIGEST_LENGTH);
129 (void) MD5(encode_buf, secretlen + MD5_DIGEST_LENGTH, md5_md);
130 for (i = 0; i < 16; ++i)
131 mppe_keys[i + 16] ^= md5_md[i];
135 /* Whew. Now stringify it for pairmake(). */
136 mppe_keys_string[0] = '0';
137 mppe_keys_string[1] = 'x';
138 for (i = 0; i < 32; ++i)
139 (void) sprintf(&mppe_keys_string[i*2+2], "%02X", mppe_keys[i]);
140 vp = pairmake("MS-CHAP-MPPE-Keys", mppe_keys_string, T_OP_EQ);
141 rad_assert(vp != NULL);
144 break; /* PWE_MSCHAP */
149 unsigned char password_md_md[MD4_DIGEST_LENGTH];
152 * MS-CHAPv2 requires mutual authentication; we must prove
153 * that we know the secret. This is a bit circuitous: set
154 * MD1 = SHA(MD4(MD4(unicode(password)))|NT_RESPONSE|MAGIC1),
155 * MD2 = MSB8(SHA(PEER_CHALLENGE|MS_CHAP_CHALLENGE|USERNAME)),
156 * and finally use SHA(MD1|MD2|MAGIC2) as the authenticator.
157 * The authenticator is returned as the string "S=<auth>",
158 * <auth> is the authenticator expressed as [uppercase] ASCII.
163 unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];
164 unsigned char password_md[MD4_DIGEST_LENGTH];
167 unsigned char md1[SHA_DIGEST_LENGTH];
168 unsigned char md2[SHA_DIGEST_LENGTH];
169 unsigned char auth_md[SHA_DIGEST_LENGTH];
170 /* S= ( ASCII(auth_md) ) \0 */
171 char auth_md_string[2 + (2 * sizeof(auth_md)) + 1];
173 * ugh. The ASCII authenticator (auth_md_string) is sent
174 * along with a single (useless) binary byte (the ID).
175 * So we must "stringify" it again (for pairmake()) since the
176 * binary byte requires the attribute to be of type "octets".
178 /* 0x (ID) ( ASCII("S="ASCII(auth_md))) */
179 char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];
181 char *username = request->username->strvalue;
182 int username_len = request->username->length;
184 /* "Magic server to client signing constant" */
185 unsigned char magic1[39] =
186 { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
187 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
188 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
189 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
190 /* "Pad to make it do more than one iteration" */
191 unsigned char magic2[41] =
192 { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
193 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
194 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
195 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
199 * Start by hashing the unicode passcode.
200 * This is broken because unicode chars are machine-ordered,
201 * but the spec (RFC 2759) doesn't say how to prepare
202 * the password for md4 (other than by example values).
204 passcode_len = strlen(passcode);
205 for (i = 0; i < passcode_len; ++i) {
206 /* Set the high order 8 bits to 0 (little-endian) */
207 password_unicode[i * 2] = *passcode++;
208 password_unicode[i * 2 + 1] = 0;
211 (void) MD4(password_unicode, 2 * passcode_len, password_md);
213 (void) MD4(password_md, MD4_DIGEST_LENGTH, password_md_md);
217 SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
218 SHA1_Update(&ctx, rvp->strvalue + 26, 24);
219 SHA1_Update(&ctx, magic1, sizeof(magic1));
220 SHA1_Final(md1, &ctx);
224 SHA1_Update(&ctx, rvp->strvalue + 2, 16);
225 SHA1_Update(&ctx, cvp->strvalue, 16);
226 SHA1_Update(&ctx, username, username_len);
227 SHA1_Final(md2, &ctx);
229 /* The Authenticator */
231 SHA1_Update(&ctx, md1, SHA_DIGEST_LENGTH);
232 SHA1_Update(&ctx, md2, 8);
233 SHA1_Update(&ctx, magic2, sizeof(magic2));
234 SHA1_Final(auth_md, &ctx);
236 /* String conversion. */
237 auth_md_string[0] = 'S';
238 auth_md_string[1] = '=';
239 for (i = 0; i < sizeof(auth_md); ++i)
240 (void) sprintf(&auth_md_string[i * 2 + 2], "%02X", auth_md[i]);
242 /* And then octet conversion. Ugh! */
243 auth_octet_string[0] = '0';
244 auth_octet_string[1] = 'x';
245 (void) sprintf(&auth_octet_string[2], "%02X", rvp->strvalue[0]);
246 for (i = 0; i < sizeof(auth_md_string) - 1; ++i)
247 (void) sprintf(&auth_octet_string[i * 2 +4], "%02X", auth_md_string[i]);
249 vp = pairmake("MS-CHAP2-Success", auth_octet_string, T_OP_EQ);
250 rad_assert(vp != NULL);
252 } /* Generate mutual auth info. */
255 * Now, set some MPPE related attributes.
257 vp = pairmake("MS-MPPE-Encryption-Policy",
258 otp_mppe_policy[opt->mschapv2_mppe_policy], T_OP_EQ);
259 rad_assert(vp != NULL);
261 vp = pairmake("MS-MPPE-Encryption-Types",
262 otp_mppe_types[opt->mschapv2_mppe_types], T_OP_EQ);
263 rad_assert(vp != NULL);
266 /* If no MPPE, we're done. */
267 if (!opt->mschapv2_mppe_policy)
271 * Generate the MPPE initial session key, per RFC 3079.
272 * (Although, RFC 2548 leaves us guessing at how to generate this.)
273 * For MS-CHAPv2 we support all key lengths (40-, 56- and 128-bit),
274 * although MPPE via RADIUS supports only 40- and 128-bit keys.
275 * This is a bit more complicated than MS-CHAP. Start by generating
276 * a "master session key"
277 * MSB16(SHA(NTPasswordHashHash|NT_RESPONSE|MAGIC1)), where
278 * NTPasswordHashHash is MD4(MD4(unicode(password))), NT_RESPONSE
279 * is from the MS-CHAP2-Response attribute, and MAGIC1 is a
280 * constant from RFC 3079. Then, we derive asymmetric send/receive
281 * keys from the master session key. The "master send key" is
282 * MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC3|SHSPAD2)),
283 * and the "master receive key" is
284 * MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC2|SHSPAD2)), where
285 * MASTERKEY is the "master session key" generated above, and the
286 * other values are constants from RFC 3079. MSBx is the x-most
287 * significant bytes, where x is 5, 7, or 16 as appropriate for
288 * the desired key length. We always generate 16 byte (128-bit)
289 * keys, the NAS is required to truncate as needed.
292 /* These constants and key vars are named from RFC 3079. */
293 /* "This is the MPPE Master Key" */
294 unsigned char Magic1[27] =
295 { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
296 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
297 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
298 /* "On the client side, this is the send key; "
299 "on the server side, it is the receive key." */
300 unsigned char Magic2[84] =
301 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
302 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
303 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
304 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
305 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
306 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
307 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
308 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
309 0x6b, 0x65, 0x79, 0x2e };
310 /* "On the client side, this is the receive key; "
311 "on the server side, it is the send key." */
312 unsigned char Magic3[84] =
313 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
314 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
315 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
316 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
317 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
318 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
319 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
320 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
321 0x6b, 0x65, 0x79, 0x2e };
322 unsigned char SHSpad1[40] =
323 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
327 unsigned char SHSpad2[40] =
328 { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
329 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
330 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
331 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
332 unsigned char MasterKey[16];
333 unsigned char MasterSendKey[16];
334 unsigned char MasterReceiveKey[16];
337 unsigned char sha_md[SHA_DIGEST_LENGTH];
338 #if 0 /* salting/encoding now handled in lib/radius.c:tunnel_pwencode() */
339 unsigned char md5_md[MD5_DIGEST_LENGTH];
341 /* From RFC 2548: S R A */
342 unsigned char encode_buf[MAX_STRING_LEN + AUTH_VECTOR_LEN + 2];
345 /* A useless value required by RFC 2548. */
346 unsigned char salt[2];
347 unsigned char mppe_key[32]; /* 1 + 16 + padding */
348 /* 0x ( ASCII(salt) ) */
349 unsigned char mppe_key_string[2 + (2 * sizeof(salt)) +
350 /* ( ASCII(mppe_key) ) \0 */
351 (2 * sizeof(mppe_key)) + 1];
353 /* 0x ( ASCII(mppe_key) ) \0 */
354 unsigned char mppe_key_string[2 + (2 * sizeof(MasterKey)) + 1];
357 /* Generate the master session key. */
359 SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
360 SHA1_Update(&ctx, rvp->strvalue + 26, 24);
361 SHA1_Update(&ctx, Magic1, sizeof(Magic1));
362 SHA1_Final(sha_md, &ctx);
363 (void) memcpy(MasterKey, sha_md, 16);
365 /* Generate the master send key. */
367 SHA1_Update(&ctx, MasterKey, 16);
368 SHA1_Update(&ctx, SHSpad1, 40);
369 SHA1_Update(&ctx, Magic3, sizeof(Magic3));
370 SHA1_Update(&ctx, SHSpad2, 40);
371 SHA1_Final(sha_md, &ctx);
372 (void) memcpy(MasterSendKey, sha_md, 16);
374 /* Generate the master receive key. */
376 SHA1_Update(&ctx, MasterKey, 16);
377 SHA1_Update(&ctx, SHSpad1, 40);
378 SHA1_Update(&ctx, Magic2, sizeof(Magic3));
379 SHA1_Update(&ctx, SHSpad2, 40);
380 SHA1_Final(sha_md, &ctx);
381 (void) memcpy(MasterReceiveKey, sha_md, 16);
384 * Now, generate the MS-MPPE-Send-Key attribute.
387 /* Setup the salt value. */
391 /* Encode the key. */
392 (void) memset(mppe_key, 0, sizeof(mppe_key));
393 mppe_key[0] = 16; /* length */
394 (void) memcpy(&mppe_key[1], MasterSendKey, 16);
395 secretlen = strlen(request->secret);
396 (void) memcpy(encode_buf, request->secret, secretlen);
397 (void) memcpy(encode_buf + secretlen, request->packet->vector,
399 (void) memcpy(encode_buf + secretlen + 16, salt, 2);
400 (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
401 for (i = 0; i < 16; ++i)
402 mppe_key[i] ^= md5_md[i];
403 (void) memcpy(encode_buf + secretlen, mppe_key, 16);
404 (void) MD5(encode_buf, secretlen + 16, md5_md);
405 for (i = 0; i < 16; ++i)
406 mppe_key[i + 16] ^= md5_md[i];
408 /* Whew. Now stringify it for pairmake(). */
409 mppe_key_string[0] = '0';
410 mppe_key_string[1] = 'x';
411 (void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
412 (void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
413 for (i = 0; i < sizeof(mppe_key); ++i)
414 (void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
416 mppe_key_string[0] = '0';
417 mppe_key_string[1] = 'x';
418 for (i = 0; i < sizeof(MasterSendKey); ++i)
419 (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterSendKey[i]);
421 vp = pairmake("MS-MPPE-Send-Key", mppe_key_string, T_OP_EQ);
422 rad_assert(vp != NULL);
426 * Generate the MS-MPPE-Recv-Key attribute.
429 /* Setup the salt value. */
433 /* Encode the key. */
434 (void) memset(mppe_key, 0, sizeof(mppe_key));
435 mppe_key[0] = 16; /* length */
436 (void) memcpy(&mppe_key[1], MasterReceiveKey, 16);
437 secretlen = strlen(request->secret);
438 (void) memcpy(encode_buf, request->secret, secretlen);
439 (void) memcpy(encode_buf + secretlen, request->packet->vector,
441 (void) memcpy(encode_buf + secretlen + 16, salt, 2);
442 (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
443 for (i = 0; i < 16; ++i)
444 mppe_key[i] ^= md5_md[i];
445 (void) memcpy(encode_buf + secretlen, mppe_key, 16);
446 (void) MD5(encode_buf, secretlen + 16, md5_md);
447 for (i = 0; i < 16; ++i)
448 mppe_key[i + 16] ^= md5_md[i];
450 /* Whew. Now stringify it for pairmake(). */
451 mppe_key_string[0] = '0';
452 mppe_key_string[1] = 'x';
453 (void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
454 (void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
455 for (i = 0; i < sizeof(mppe_key); ++i)
456 (void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
458 mppe_key_string[0] = '0';
459 mppe_key_string[1] = 'x';
460 for (i = 0; i < sizeof(MasterReceiveKey); ++i)
461 (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterReceiveKey[i]);
463 vp = pairmake("MS-MPPE-Recv-Key", mppe_key_string, T_OP_EQ);
464 rad_assert(vp != NULL);
469 break; /* PWE_MSCHAP2 */