]> git.ozlabs.org Git - ppp.git/blob - pppd/mppe.c
Makefile.am: Add explicit openssl directory to pppd include path
[ppp.git] / pppd / mppe.c
1 /* mppe.c - MPPE key implementation
2  *
3  * Copyright (c) 2020 Eivind Naess. All rights reserved.
4  * Copyright (c) 2008 Paul Mackerras. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name(s) of the authors of this software must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission.
21  *
22  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36
37
38 #include "pppd-private.h"
39 #include "fsm.h"
40 #include "ccp.h"
41 #include "chap_ms.h"
42 #include "mppe.h"
43 #include "crypto.h"
44
45 u_char mppe_send_key[MPPE_MAX_KEY_SIZE];
46 u_char mppe_recv_key[MPPE_MAX_KEY_SIZE];
47 int mppe_keys_set = 0;
48
49 void
50 mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen)
51 {
52         int length = keylen;
53         if (length > MPPE_MAX_KEY_SIZE)
54                 length = MPPE_MAX_KEY_SIZE;
55         
56         if (send_key) {
57             BCOPY(send_key, mppe_send_key, length);
58             BZERO(send_key, keylen);
59         }
60
61         if (recv_key) {
62             BCOPY(recv_key, mppe_recv_key, length);
63             BZERO(recv_key, keylen);
64         }
65
66         mppe_keys_set = length;
67 }
68
69 bool
70 mppe_keys_isset()
71 {
72         return !!mppe_keys_set;
73 }
74
75 int
76 mppe_get_recv_key(u_char *recv_key, int length)
77 {
78         if (mppe_keys_isset()) {
79                 if (length > mppe_keys_set)
80                         length = mppe_keys_set;
81                 BCOPY(mppe_recv_key, recv_key, length);
82                 return length;
83         }
84         return 0;
85 }
86
87 int
88 mppe_get_send_key(u_char *send_key, int length)
89 {
90         if (mppe_keys_isset()) {
91                 if (length > mppe_keys_set)
92                         length = mppe_keys_set;
93                 BCOPY(mppe_send_key, send_key, length);
94                 return length;
95         }
96         return 0;
97 }
98
99 void
100 mppe_clear_keys(void)
101 {
102         mppe_keys_set = 0;
103         BZERO(mppe_send_key, sizeof(mppe_send_key));
104         BZERO(mppe_recv_key, sizeof(mppe_recv_key));
105 }
106
107 /*
108  * Set mppe_xxxx_key from the NTPasswordHashHash.
109  * RFC 2548 (RADIUS support) requires us to export this function (ugh).
110  */
111 void
112 mppe_set_chapv1(unsigned char *rchallenge, unsigned char *PasswordHashHash)
113 {
114     PPP_MD_CTX *ctx;
115     u_char Digest[SHA_DIGEST_LENGTH];
116     int DigestLen;
117
118     ctx = PPP_MD_CTX_new();
119     if (ctx != NULL) {
120
121         if (PPP_DigestInit(ctx, PPP_sha1())) {
122
123             if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) {
124
125                 if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) {
126
127                     if (PPP_DigestUpdate(ctx, rchallenge, 8)) {
128                         
129                         DigestLen = SHA_DIGEST_LENGTH;
130                         PPP_DigestFinal(ctx, Digest, &DigestLen);
131                     }
132                 }
133             }
134         }
135         
136         PPP_MD_CTX_free(ctx);
137     }
138
139
140     /* Same key in both directions. */
141     mppe_set_keys(Digest, Digest, sizeof(Digest));
142 }
143
144 /*
145  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
146  *
147  * This helper function used in the Winbind module, which gets the
148  * NTHashHash from the server.
149  */
150 void
151 mppe_set_chapv2(unsigned char *PasswordHashHash, unsigned char *NTResponse,
152         int IsServer)
153 {
154     PPP_MD_CTX *ctx;
155     
156     u_char      MasterKey[SHA_DIGEST_LENGTH];
157     u_char      SendKey[SHA_DIGEST_LENGTH];
158     u_char      RecvKey[SHA_DIGEST_LENGTH];
159     int KeyLen;
160
161     u_char SHApad1[40] =
162         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
166     u_char SHApad2[40] =
167         { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
168           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
169           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
170           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
171
172     /* "This is the MPPE Master Key" */
173     u_char Magic1[27] =
174         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
175           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
176           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
177     /* "On the client side, this is the send key; "
178        "on the server side, it is the receive key." */
179     u_char Magic2[84] =
180         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
181           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
182           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
183           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
184           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
185           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
186           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
187           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
188           0x6b, 0x65, 0x79, 0x2e };
189     /* "On the client side, this is the receive key; "
190        "on the server side, it is the send key." */
191     u_char Magic3[84] =
192         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
193           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
194           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
195           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
196           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
197           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
198           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
199           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
200           0x6b, 0x65, 0x79, 0x2e };
201     u_char *s;
202
203     ctx = PPP_MD_CTX_new();
204     if (ctx != NULL) {
205
206         if (PPP_DigestInit(ctx, PPP_sha1())) {
207
208             if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) {
209
210                 if (PPP_DigestUpdate(ctx, NTResponse, 24)) {
211
212                     if (PPP_DigestUpdate(ctx, Magic1, sizeof(Magic1))) {
213                         
214                         KeyLen = SHA_DIGEST_LENGTH;
215                         PPP_DigestFinal(ctx, MasterKey, &KeyLen);
216                     }
217                 }
218             }
219         }
220         
221         PPP_MD_CTX_free(ctx);
222     }
223
224     /*
225      * generate send key
226      */
227     if (IsServer)
228         s = Magic3;
229     else
230         s = Magic2;
231
232     ctx = PPP_MD_CTX_new();
233     if (ctx != NULL) {
234
235         if (PPP_DigestInit(ctx, PPP_sha1())) {
236
237             if (PPP_DigestUpdate(ctx, MasterKey, 16)) {
238
239                 if (PPP_DigestUpdate(ctx, SHApad1, sizeof(SHApad1))) {
240
241                     if (PPP_DigestUpdate(ctx, s, 84)) {
242
243                         if (PPP_DigestUpdate(ctx, SHApad2, sizeof(SHApad2))) {
244                         
245                             KeyLen = SHA_DIGEST_LENGTH;
246                             PPP_DigestFinal(ctx, SendKey, &KeyLen);
247                         }
248                     }
249                 }
250             }
251         }
252         
253         PPP_MD_CTX_free(ctx);
254     }
255
256
257     /*
258      * generate recv key
259      */
260     if (IsServer)
261         s = Magic2;
262     else
263         s = Magic3;
264
265     ctx = PPP_MD_CTX_new();
266     if (ctx != NULL) {
267
268         if (PPP_DigestInit(ctx, PPP_sha1())) {
269
270             if (PPP_DigestUpdate(ctx, MasterKey, 16)) {
271
272                 if (PPP_DigestUpdate(ctx, SHApad1, sizeof(SHApad1))) {
273
274                     if (PPP_DigestUpdate(ctx, s, 84)) {
275
276                         if (PPP_DigestUpdate(ctx, SHApad2, sizeof(SHApad2))) {
277                         
278                             KeyLen = SHA_DIGEST_LENGTH;
279                             PPP_DigestFinal(ctx, RecvKey, &KeyLen);
280                         }
281                     }
282                 }
283             }
284         }
285         
286         PPP_MD_CTX_free(ctx);
287     }
288
289     mppe_set_keys(SendKey, RecvKey, SHA_DIGEST_LENGTH);
290 }
291
292 #ifndef UNIT_TEST
293
294 /*
295  * Set MPPE options from plugins.
296  */
297 void
298 mppe_set_enc_types(int policy, int types)
299 {
300     /* Early exit for unknown policies. */
301     if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
302         policy != MPPE_ENC_POL_ENC_REQUIRED)
303         return;
304
305     /* Don't modify MPPE if it's optional and wasn't already configured. */
306     if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
307         return;
308
309     /*
310      * Disable undesirable encryption types.  Note that we don't ENABLE
311      * any encryption types, to avoid overriding manual configuration.
312      */
313     switch(types) {
314         case MPPE_ENC_TYPES_RC4_40:
315             ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
316             break;
317         case MPPE_ENC_TYPES_RC4_128:
318             ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
319             break;
320         default:
321             break;
322     }
323 }
324
325 #endif