1 /* $OpenBSD: chap_ms.c,v 1.9 2022/01/07 07:33:35 tb Exp $ */
2
3 /*
4 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 1997-2001 Brian Somers <brian@Awfulhak.org>
6 * Copyright (c) 1997 Gabor Kincses <gabor@acm.org>
7 * Copyright (c) 1995 Eric Rosenquist
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/types.h>
34
35 #include <ctype.h>
36 #include <string.h>
37 #include <stdio.h>
38
39 #include <openssl/evp.h>
40 #include <openssl/des.h>
41 #include <openssl/md4.h>
42 #include <openssl/md5.h>
43 #include <openssl/sha.h>
44
45 #include "chap_ms.h"
46
47 /*
48 * Documentation & specifications:
49 *
50 * MS-CHAP (CHAP80) RFC2433
51 * MS-CHAP-V2 (CHAP81) RFC2759
52 * MPPE key management RFC3079
53 *
54 * Security analysis:
55 * Schneier/Mudge/Wagner, "MS-CHAP-v2", Oct 99
56 * "It is unclear to us why this protocol is so complicated."
57 */
58
59 static u_int8_t sha1_pad1[40] = {
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
64 };
65
66 static u_int8_t sha1_pad2[40] = {
67 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
68 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
69 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
70 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
71 };
72
73 u_int8_t get7bits(u_int8_t *, int);
74 void mschap_des_addparity(u_int8_t *, u_int8_t *);
75 void mschap_des_encrypt(u_int8_t *, u_int8_t *, u_int8_t *);
76 void mschap_challenge_response(u_int8_t *, u_int8_t *, u_int8_t *);
77
78 u_int8_t
get7bits(u_int8_t * in,int start)79 get7bits(u_int8_t *in, int start)
80 {
81 u_int word;
82
83 word = (u_int)in[start / 8] << 8;
84 word |= (u_int)in[start / 8 + 1];
85 word >>= 15 - (start % 8 + 7);
86
87 return (word & 0xfe);
88 }
89
90 /* IN 56 bit DES key missing parity bits
91 OUT 64 bit DES key with parity bits added */
92 void
mschap_des_addparity(u_int8_t * key,u_int8_t * des_key)93 mschap_des_addparity(u_int8_t *key, u_int8_t *des_key)
94 {
95 des_key[0] = get7bits(key, 0);
96 des_key[1] = get7bits(key, 7);
97 des_key[2] = get7bits(key, 14);
98 des_key[3] = get7bits(key, 21);
99 des_key[4] = get7bits(key, 28);
100 des_key[5] = get7bits(key, 35);
101 des_key[6] = get7bits(key, 42);
102 des_key[7] = get7bits(key, 49);
103
104 DES_set_odd_parity((DES_cblock *)des_key);
105 }
106
107 void
mschap_des_encrypt(u_int8_t * clear,u_int8_t * key,u_int8_t * cipher)108 mschap_des_encrypt(u_int8_t *clear, u_int8_t *key, u_int8_t *cipher)
109 {
110 DES_cblock des_key;
111 DES_key_schedule key_schedule;
112
113 mschap_des_addparity(key, des_key);
114
115 DES_set_key(&des_key, &key_schedule);
116 DES_ecb_encrypt((DES_cblock *)clear, (DES_cblock *)cipher,
117 &key_schedule, 1);
118 }
119
120 void
mschap_challenge_response(u_int8_t * challenge,u_int8_t * pwhash,u_int8_t * response)121 mschap_challenge_response(u_int8_t *challenge, u_int8_t *pwhash,
122 u_int8_t *response)
123 {
124 u_int8_t padpwhash[21 + 1];
125
126 bzero(&padpwhash, sizeof(padpwhash));
127 memcpy(padpwhash, pwhash, MSCHAP_HASH_SZ);
128
129 mschap_des_encrypt(challenge, padpwhash + 0, response + 0);
130 mschap_des_encrypt(challenge, padpwhash + 7, response + 8);
131 mschap_des_encrypt(challenge, padpwhash + 14, response + 16);
132 }
133
134 void
mschap_ntpassword_hash(u_int8_t * in,int inlen,u_int8_t * hash)135 mschap_ntpassword_hash(u_int8_t *in, int inlen, u_int8_t *hash)
136 {
137 EVP_MD_CTX *ctx;
138 u_int mdlen;
139
140 ctx = EVP_MD_CTX_new();
141 EVP_DigestInit_ex(ctx, EVP_md4(), NULL);
142 EVP_DigestUpdate(ctx, in, inlen);
143 EVP_DigestFinal_ex(ctx, hash, &mdlen);
144 EVP_MD_CTX_free(ctx);
145 }
146
147 void
mschap_challenge_hash(u_int8_t * peer_challenge,u_int8_t * auth_challenge,u_int8_t * username,int usernamelen,u_int8_t * challenge)148 mschap_challenge_hash(u_int8_t *peer_challenge, u_int8_t *auth_challenge,
149 u_int8_t *username, int usernamelen, u_int8_t *challenge)
150 {
151 EVP_MD_CTX *ctx;
152 u_int8_t md[SHA_DIGEST_LENGTH];
153 u_int mdlen;
154 u_int8_t *name;
155
156 if ((name = strrchr(username, '\\')) == NULL)
157 name = username;
158 else
159 name++;
160
161 ctx = EVP_MD_CTX_new();
162 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
163 EVP_DigestUpdate(ctx, peer_challenge, MSCHAPV2_CHALLENGE_SZ);
164 EVP_DigestUpdate(ctx, auth_challenge, MSCHAPV2_CHALLENGE_SZ);
165 EVP_DigestUpdate(ctx, name, strlen(name));
166 EVP_DigestFinal_ex(ctx, md, &mdlen);
167 EVP_MD_CTX_free(ctx);
168
169 memcpy(challenge, md, MSCHAP_CHALLENGE_SZ);
170 }
171
172 void
mschap_nt_response(u_int8_t * auth_challenge,u_int8_t * peer_challenge,u_int8_t * username,int usernamelen,u_int8_t * password,int passwordlen,u_int8_t * response)173 mschap_nt_response(u_int8_t *auth_challenge, u_int8_t *peer_challenge,
174 u_int8_t *username, int usernamelen, u_int8_t *password, int passwordlen,
175 u_int8_t *response)
176 {
177 u_int8_t challenge[MSCHAP_CHALLENGE_SZ];
178 u_int8_t password_hash[MSCHAP_HASH_SZ];
179
180 mschap_challenge_hash(peer_challenge, auth_challenge,
181 username, usernamelen, challenge);
182
183 mschap_ntpassword_hash(password, passwordlen, password_hash);
184 mschap_challenge_response(challenge, password_hash, response);
185 }
186
187 void
mschap_auth_response(u_int8_t * password,int passwordlen,u_int8_t * ntresponse,u_int8_t * auth_challenge,u_int8_t * peer_challenge,u_int8_t * username,int usernamelen,u_int8_t * auth_response)188 mschap_auth_response(u_int8_t *password, int passwordlen,
189 u_int8_t *ntresponse, u_int8_t *auth_challenge, u_int8_t *peer_challenge,
190 u_int8_t *username, int usernamelen, u_int8_t *auth_response)
191 {
192 EVP_MD_CTX *ctx;
193 u_int8_t password_hash[MSCHAP_HASH_SZ];
194 u_int8_t password_hash2[MSCHAP_HASH_SZ];
195 u_int8_t challenge[MSCHAP_CHALLENGE_SZ];
196 u_int8_t md[SHA_DIGEST_LENGTH], *ptr;
197 u_int mdlen;
198 int i;
199 const u_int8_t hex[] = "0123456789ABCDEF";
200 static u_int8_t magic1[39] = {
201 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
202 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
203 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
204 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
205 };
206 static u_int8_t magic2[41] = {
207 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
208 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
209 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
210 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
211 0x6E
212 };
213
214 mschap_ntpassword_hash(password, passwordlen, password_hash);
215 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
216
217 ctx = EVP_MD_CTX_new();
218 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
219 EVP_DigestUpdate(ctx, password_hash2, sizeof(password_hash2));
220 EVP_DigestUpdate(ctx, ntresponse, 24);
221 EVP_DigestUpdate(ctx, magic1, 39);
222 EVP_DigestFinal_ex(ctx, md, &mdlen);
223
224 mschap_challenge_hash(peer_challenge, auth_challenge,
225 username, usernamelen, challenge);
226
227 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
228 EVP_DigestUpdate(ctx, md, sizeof(md));
229 EVP_DigestUpdate(ctx, challenge, sizeof(challenge));
230 EVP_DigestUpdate(ctx, magic2, 41);
231 EVP_DigestFinal_ex(ctx, md, &mdlen);
232 EVP_MD_CTX_free(ctx);
233
234 /*
235 * Encode the value of 'Digest' as "S=" followed by
236 * 40 ASCII hexadecimal digits and return it in
237 * AuthenticatorResponse.
238 * For example,
239 * "S=0123456789ABCDEF0123456789ABCDEF01234567"
240 */
241 ptr = auth_response;
242 *ptr++ = 'S';
243 *ptr++ = '=';
244 for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
245 *ptr++ = hex[md[i] >> 4];
246 *ptr++ = hex[md[i] & 0x0f];
247 }
248 }
249
250 void
mschap_masterkey(u_int8_t * password_hash2,u_int8_t * ntresponse,u_int8_t * masterkey)251 mschap_masterkey(u_int8_t *password_hash2, u_int8_t *ntresponse,
252 u_int8_t *masterkey)
253 {
254 u_int8_t md[SHA_DIGEST_LENGTH];
255 u_int mdlen;
256 EVP_MD_CTX *ctx;
257 static u_int8_t magic1[27] = {
258 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
259 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
260 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
261 };
262
263 ctx = EVP_MD_CTX_new();
264 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
265 EVP_DigestUpdate(ctx, password_hash2, MSCHAP_HASH_SZ);
266 EVP_DigestUpdate(ctx, ntresponse, 24);
267 EVP_DigestUpdate(ctx, magic1, 27);
268 EVP_DigestFinal_ex(ctx, md, &mdlen);
269 EVP_MD_CTX_free(ctx);
270
271 memcpy(masterkey, md, 16);
272 }
273
274 void
mschap_asymetric_startkey(u_int8_t * masterkey,u_int8_t * sessionkey,int sessionkeylen,int issend,int isserver)275 mschap_asymetric_startkey(u_int8_t *masterkey, u_int8_t *sessionkey,
276 int sessionkeylen, int issend, int isserver)
277 {
278 EVP_MD_CTX *ctx;
279 u_int8_t md[SHA_DIGEST_LENGTH];
280 u_int mdlen;
281 u_int8_t *s;
282 static u_int8_t magic2[84] = {
283 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
284 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
285 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
286 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
287 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
288 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
289 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
290 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
291 0x6b, 0x65, 0x79, 0x2e
292 };
293 static u_int8_t magic3[84] = {
294 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
295 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
296 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
297 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
298 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
299 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
300 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
301 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
302 0x6b, 0x65, 0x79, 0x2e
303 };
304
305 if (issend)
306 s = isserver ? magic3 : magic2;
307 else
308 s = isserver ? magic2 : magic3;
309
310 ctx = EVP_MD_CTX_new();
311 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
312 EVP_DigestUpdate(ctx, masterkey, 16);
313 EVP_DigestUpdate(ctx, sha1_pad1, 40);
314 EVP_DigestUpdate(ctx, s, 84);
315 EVP_DigestUpdate(ctx, sha1_pad2, 40);
316 EVP_DigestFinal_ex(ctx, md, &mdlen);
317 EVP_MD_CTX_free(ctx);
318
319 memcpy(sessionkey, md, sessionkeylen);
320 }
321
322 void
mschap_msk(u_int8_t * password,int passwordlen,u_int8_t * ntresponse,u_int8_t * msk)323 mschap_msk(u_int8_t *password, int passwordlen,
324 u_int8_t *ntresponse, u_int8_t *msk)
325 {
326 u_int8_t password_hash[MSCHAP_HASH_SZ];
327 u_int8_t password_hash2[MSCHAP_HASH_SZ];
328 u_int8_t masterkey[MSCHAP_MASTERKEY_SZ];
329 u_int8_t sendkey[MSCHAP_MASTERKEY_SZ];
330 u_int8_t recvkey[MSCHAP_MASTERKEY_SZ];
331
332 mschap_ntpassword_hash(password, passwordlen, password_hash);
333 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
334
335 mschap_masterkey(password_hash2, ntresponse, masterkey);
336 mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1);
337 mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1);
338
339 /* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */
340 bzero(msk, MSCHAP_MSK_SZ);
341 memcpy(msk, &recvkey, sizeof(recvkey));
342 memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey));
343 }
344
345 void
mschap_radiuskey(u_int8_t * plain,const u_int8_t * encrypted,const u_int8_t * authenticator,const u_int8_t * secret)346 mschap_radiuskey(u_int8_t *plain, const u_int8_t *encrypted,
347 const u_int8_t *authenticator, const u_int8_t *secret)
348 {
349 EVP_MD_CTX *ctx;
350 u_int8_t b[MD5_DIGEST_LENGTH], p[32];
351 u_int i, mdlen;
352
353 ctx = EVP_MD_CTX_new();
354 EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
355 EVP_DigestUpdate(ctx, secret, strlen(secret));
356 EVP_DigestUpdate(ctx, authenticator, 16);
357 EVP_DigestUpdate(ctx, encrypted, 2);
358 EVP_DigestFinal_ex(ctx, b, &mdlen);
359
360 for (i = 0; i < mdlen; i++) {
361 p[i] = b[i] ^ encrypted[i+2];
362 }
363
364 EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
365 EVP_DigestUpdate(ctx, secret, strlen(secret));
366 EVP_DigestUpdate(ctx, encrypted + 2, mdlen);
367 EVP_DigestFinal_ex(ctx, b, &mdlen);
368 EVP_MD_CTX_free(ctx);
369
370 for (i = 0; i < mdlen; i++) {
371 p[i+16] = b[i] ^ encrypted[i+18];
372 }
373
374 memcpy(plain, p+1, 16);
375 }
376