1 /* $OpenBSD: chap_ms.c,v 1.10 2021/02/04 19:59:15 tobhe 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 extern __dead void fatalx(const char *, ...)
48 __attribute__((__format__ (printf, 1, 2)));
49
50 /*
51 * Documentation & specifications:
52 *
53 * MS-CHAP (CHAP80) RFC2433
54 * MS-CHAP-V2 (CHAP81) RFC2759
55 * MPPE key management RFC3079
56 *
57 * Security analysis:
58 * Schneier/Mudge/Wagner, "MS-CHAP-v2", Oct 99
59 * "It is unclear to us why this protocol is so complicated."
60 */
61
62 static uint8_t sha1_pad1[40] = {
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
67 };
68
69 static uint8_t sha1_pad2[40] = {
70 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
71 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
72 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
73 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
74 };
75
76 uint8_t get7bits(uint8_t *, int);
77 void mschap_des_addparity(uint8_t *, uint8_t *);
78 void mschap_des_encrypt(uint8_t *, uint8_t *, uint8_t *);
79 void mschap_challenge_response(uint8_t *, uint8_t *, uint8_t *);
80
81 uint8_t
get7bits(uint8_t * in,int start)82 get7bits(uint8_t *in, int start)
83 {
84 unsigned int word;
85
86 word = (unsigned int)in[start / 8] << 8;
87 word |= (unsigned int)in[start / 8 + 1];
88 word >>= 15 - (start % 8 + 7);
89
90 return (word & 0xfe);
91 }
92
93 /* IN 56 bit DES key missing parity bits
94 OUT 64 bit DES key with parity bits added */
95 void
mschap_des_addparity(uint8_t * key,uint8_t * des_key)96 mschap_des_addparity(uint8_t *key, uint8_t *des_key)
97 {
98 des_key[0] = get7bits(key, 0);
99 des_key[1] = get7bits(key, 7);
100 des_key[2] = get7bits(key, 14);
101 des_key[3] = get7bits(key, 21);
102 des_key[4] = get7bits(key, 28);
103 des_key[5] = get7bits(key, 35);
104 des_key[6] = get7bits(key, 42);
105 des_key[7] = get7bits(key, 49);
106
107 DES_set_odd_parity((DES_cblock *)des_key);
108 }
109
110 void
mschap_des_encrypt(uint8_t * clear,uint8_t * key,uint8_t * cipher)111 mschap_des_encrypt(uint8_t *clear, uint8_t *key, uint8_t *cipher)
112 {
113 DES_cblock des_key;
114 DES_key_schedule key_schedule;
115
116 mschap_des_addparity(key, des_key);
117
118 DES_set_key(&des_key, &key_schedule);
119 DES_ecb_encrypt((DES_cblock *)clear, (DES_cblock *)cipher,
120 &key_schedule, 1);
121 }
122
123 void
mschap_challenge_response(uint8_t * challenge,uint8_t * pwhash,uint8_t * response)124 mschap_challenge_response(uint8_t *challenge, uint8_t *pwhash,
125 uint8_t *response)
126 {
127 uint8_t padpwhash[21 + 1];
128
129 bzero(&padpwhash, sizeof(padpwhash));
130 memcpy(padpwhash, pwhash, MSCHAP_HASH_SZ);
131
132 mschap_des_encrypt(challenge, padpwhash + 0, response + 0);
133 mschap_des_encrypt(challenge, padpwhash + 7, response + 8);
134 mschap_des_encrypt(challenge, padpwhash + 14, response + 16);
135 }
136
137 void
mschap_ntpassword_hash(uint8_t * in,int inlen,uint8_t * hash)138 mschap_ntpassword_hash(uint8_t *in, int inlen, uint8_t *hash)
139 {
140 EVP_MD_CTX *ctx;
141 unsigned int mdlen;
142
143 ctx = EVP_MD_CTX_new();
144 if (ctx == NULL)
145 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
146 EVP_DigestInit(ctx, EVP_md4());
147 EVP_DigestUpdate(ctx, in, inlen);
148 EVP_DigestFinal(ctx, hash, &mdlen);
149 EVP_MD_CTX_free(ctx);
150 }
151
152 void
mschap_challenge_hash(uint8_t * peer_challenge,uint8_t * auth_challenge,uint8_t * username,int usernamelen,uint8_t * challenge)153 mschap_challenge_hash(uint8_t *peer_challenge, uint8_t *auth_challenge,
154 uint8_t *username, int usernamelen, uint8_t *challenge)
155 {
156 EVP_MD_CTX *ctx;
157 uint8_t md[SHA_DIGEST_LENGTH];
158 unsigned int mdlen;
159 uint8_t *name;
160
161 if ((name = strrchr(username, '\\')) == NULL)
162 name = username;
163 else
164 name++;
165
166 ctx = EVP_MD_CTX_new();
167 if (ctx == NULL)
168 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
169 EVP_DigestInit(ctx, EVP_sha1());
170 EVP_DigestUpdate(ctx, peer_challenge, MSCHAPV2_CHALLENGE_SZ);
171 EVP_DigestUpdate(ctx, auth_challenge, MSCHAPV2_CHALLENGE_SZ);
172 EVP_DigestUpdate(ctx, name, strlen(name));
173 EVP_DigestFinal(ctx, md, &mdlen);
174 EVP_MD_CTX_free(ctx);
175
176 memcpy(challenge, md, MSCHAP_CHALLENGE_SZ);
177 }
178
179 void
mschap_nt_response(uint8_t * auth_challenge,uint8_t * peer_challenge,uint8_t * username,int usernamelen,uint8_t * password,int passwordlen,uint8_t * response)180 mschap_nt_response(uint8_t *auth_challenge, uint8_t *peer_challenge,
181 uint8_t *username, int usernamelen, uint8_t *password, int passwordlen,
182 uint8_t *response)
183 {
184 uint8_t challenge[MSCHAP_CHALLENGE_SZ];
185 uint8_t password_hash[MSCHAP_HASH_SZ];
186
187 mschap_challenge_hash(peer_challenge, auth_challenge,
188 username, usernamelen, challenge);
189
190 mschap_ntpassword_hash(password, passwordlen, password_hash);
191 mschap_challenge_response(challenge, password_hash, response);
192 }
193
194 void
mschap_auth_response(uint8_t * password,int passwordlen,uint8_t * ntresponse,uint8_t * auth_challenge,uint8_t * peer_challenge,uint8_t * username,int usernamelen,uint8_t * auth_response)195 mschap_auth_response(uint8_t *password, int passwordlen,
196 uint8_t *ntresponse, uint8_t *auth_challenge, uint8_t *peer_challenge,
197 uint8_t *username, int usernamelen, uint8_t *auth_response)
198 {
199 EVP_MD_CTX *ctx;
200 uint8_t password_hash[MSCHAP_HASH_SZ];
201 uint8_t password_hash2[MSCHAP_HASH_SZ];
202 uint8_t challenge[MSCHAP_CHALLENGE_SZ];
203 uint8_t md[SHA_DIGEST_LENGTH], *ptr;
204 unsigned int mdlen;
205 int i;
206 const uint8_t hex[] = "0123456789ABCDEF";
207 static uint8_t magic1[39] = {
208 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
209 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
210 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
211 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
212 };
213 static uint8_t magic2[41] = {
214 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
215 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
216 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
217 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
218 0x6E
219 };
220
221 ctx = EVP_MD_CTX_new();
222 if (ctx == NULL)
223 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
224 mschap_ntpassword_hash(password, passwordlen, password_hash);
225 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
226
227 EVP_DigestInit(ctx, EVP_sha1());
228 EVP_DigestUpdate(ctx, password_hash2, sizeof(password_hash2));
229 EVP_DigestUpdate(ctx, ntresponse, 24);
230 EVP_DigestUpdate(ctx, magic1, 39);
231 EVP_DigestFinal(ctx, md, &mdlen);
232
233 mschap_challenge_hash(peer_challenge, auth_challenge,
234 username, usernamelen, challenge);
235
236 EVP_DigestInit(ctx, EVP_sha1());
237 EVP_DigestUpdate(ctx, md, sizeof(md));
238 EVP_DigestUpdate(ctx, challenge, sizeof(challenge));
239 EVP_DigestUpdate(ctx, magic2, 41);
240 EVP_DigestFinal(ctx, md, &mdlen);
241 EVP_MD_CTX_free(ctx);
242
243 /*
244 * Encode the value of 'Digest' as "S=" followed by
245 * 40 ASCII hexadecimal digits and return it in
246 * AuthenticatorResponse.
247 * For example,
248 * "S=0123456789ABCDEF0123456789ABCDEF01234567"
249 */
250 ptr = auth_response;
251 *ptr++ = 'S';
252 *ptr++ = '=';
253 for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
254 *ptr++ = hex[md[i] >> 4];
255 *ptr++ = hex[md[i] & 0x0f];
256 }
257 }
258
259 void
mschap_masterkey(uint8_t * password_hash2,uint8_t * ntresponse,uint8_t * masterkey)260 mschap_masterkey(uint8_t *password_hash2, uint8_t *ntresponse,
261 uint8_t *masterkey)
262 {
263 uint8_t md[SHA_DIGEST_LENGTH];
264 unsigned int mdlen;
265 EVP_MD_CTX *ctx;
266 static uint8_t magic1[27] = {
267 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
268 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
269 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
270 };
271
272 ctx = EVP_MD_CTX_new();
273 if (ctx == NULL)
274 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
275 EVP_DigestInit(ctx, EVP_sha1());
276 EVP_DigestUpdate(ctx, password_hash2, MSCHAP_HASH_SZ);
277 EVP_DigestUpdate(ctx, ntresponse, 24);
278 EVP_DigestUpdate(ctx, magic1, 27);
279 EVP_DigestFinal(ctx, md, &mdlen);
280 EVP_MD_CTX_free(ctx);
281
282 memcpy(masterkey, md, 16);
283 }
284
285 void
mschap_asymetric_startkey(uint8_t * masterkey,uint8_t * sessionkey,int sessionkeylen,int issend,int isserver)286 mschap_asymetric_startkey(uint8_t *masterkey, uint8_t *sessionkey,
287 int sessionkeylen, int issend, int isserver)
288 {
289 EVP_MD_CTX *ctx;
290 uint8_t md[SHA_DIGEST_LENGTH];
291 unsigned int mdlen;
292 uint8_t *s;
293 static uint8_t magic2[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, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
298 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
299 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
300 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
301 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
302 0x6b, 0x65, 0x79, 0x2e
303 };
304 static uint8_t magic3[84] = {
305 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
306 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
307 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
308 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
309 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
310 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
311 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
312 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
313 0x6b, 0x65, 0x79, 0x2e
314 };
315
316 if (issend)
317 s = isserver ? magic3 : magic2;
318 else
319 s = isserver ? magic2 : magic3;
320
321 ctx = EVP_MD_CTX_new();
322 if (ctx == NULL)
323 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
324 EVP_DigestInit(ctx, EVP_sha1());
325 EVP_DigestUpdate(ctx, masterkey, 16);
326 EVP_DigestUpdate(ctx, sha1_pad1, 40);
327 EVP_DigestUpdate(ctx, s, 84);
328 EVP_DigestUpdate(ctx, sha1_pad2, 40);
329 EVP_DigestFinal(ctx, md, &mdlen);
330 EVP_MD_CTX_free(ctx);
331
332 memcpy(sessionkey, md, sessionkeylen);
333 }
334
335 void
mschap_msk(uint8_t * password,int passwordlen,uint8_t * ntresponse,uint8_t * msk)336 mschap_msk(uint8_t *password, int passwordlen,
337 uint8_t *ntresponse, uint8_t *msk)
338 {
339 uint8_t password_hash[MSCHAP_HASH_SZ];
340 uint8_t password_hash2[MSCHAP_HASH_SZ];
341 uint8_t masterkey[MSCHAP_MASTERKEY_SZ];
342 uint8_t sendkey[MSCHAP_MASTERKEY_SZ];
343 uint8_t recvkey[MSCHAP_MASTERKEY_SZ];
344
345 mschap_ntpassword_hash(password, passwordlen, password_hash);
346 mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2);
347
348 mschap_masterkey(password_hash2, ntresponse, masterkey);
349 mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1);
350 mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1);
351
352 /* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */
353 bzero(msk, MSCHAP_MSK_SZ);
354 memcpy(msk, &recvkey, sizeof(recvkey));
355 memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey));
356 }
357
358 void
mschap_radiuskey(uint8_t * plain,const uint8_t * crypted,const uint8_t * authenticator,const uint8_t * secret)359 mschap_radiuskey(uint8_t *plain, const uint8_t *crypted,
360 const uint8_t *authenticator, const uint8_t *secret)
361 {
362 EVP_MD_CTX *ctx;
363 uint8_t b[MD5_DIGEST_LENGTH], p[32];
364 unsigned int i, mdlen;
365
366 ctx = EVP_MD_CTX_new();
367 if (ctx == NULL)
368 fatalx("%s: EVP_MD_CTX_NEW()", __func__);
369 EVP_DigestInit(ctx, EVP_md5());
370 EVP_DigestUpdate(ctx, secret, strlen(secret));
371 EVP_DigestUpdate(ctx, authenticator, 16);
372 EVP_DigestUpdate(ctx, crypted, 2);
373 EVP_DigestFinal(ctx, b, &mdlen);
374
375 for (i = 0; i < mdlen; i++) {
376 p[i] = b[i] ^ crypted[i+2];
377 }
378
379 EVP_DigestInit(ctx, EVP_md5());
380 EVP_DigestUpdate(ctx, secret, strlen(secret));
381 EVP_DigestUpdate(ctx, crypted + 2, mdlen);
382 EVP_DigestFinal(ctx, b, &mdlen);
383 EVP_MD_CTX_free(ctx);
384
385 for (i = 0; i < mdlen; i++) {
386 p[i+16] = b[i] ^ crypted[i+18];
387 }
388
389 memcpy(plain, p+1, 16);
390 }
391