]> git.ozlabs.org Git - ppp.git/blob - pppd/mppe.c
4f3d1313cf20abd2bff5e6396cf7c5bb7740a08a
[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
32 #include <string.h>
33
34 #include "pppd.h"
35 #include "fsm.h"
36 #include "md4.h"
37 #include "sha1.h"
38 #include "ccp.h"
39 #include "chap_ms.h"
40 #include "mppe.h"
41
42 u_char mppe_send_key[MPPE_MAX_KEY_SIZE];
43 u_char mppe_recv_key[MPPE_MAX_KEY_SIZE];
44 int mppe_keys_set = 0;
45
46 void
47 mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen)
48 {
49         int length = keylen;
50         if (length > MPPE_MAX_KEY_SIZE)
51                 length = MPPE_MAX_KEY_SIZE;
52         
53         if (send_key) {
54             BCOPY(send_key, mppe_send_key, length);
55             BZERO(send_key, keylen);
56         }
57
58         if (recv_key) {
59             BCOPY(recv_key, mppe_recv_key, length);
60             BZERO(recv_key, keylen);
61         }
62
63         mppe_keys_set = length;
64 }
65
66 bool
67 mppe_keys_isset()
68 {
69         return !!mppe_keys_set;
70 }
71
72 int
73 mppe_get_recv_key(u_char *recv_key, int length)
74 {
75         if (mppe_keys_isset()) {
76                 if (length > mppe_keys_set)
77                         length = mppe_keys_set;
78                 BCOPY(mppe_recv_key, recv_key, length);
79                 return length;
80         }
81         return 0;
82 }
83
84 int
85 mppe_get_send_key(u_char *send_key, int length)
86 {
87         if (mppe_keys_isset()) {
88                 if (length > mppe_keys_set)
89                         length = mppe_keys_set;
90                 BCOPY(mppe_send_key, send_key, length);
91                 return length;
92         }
93         return 0;
94 }
95
96 void
97 mppe_clear_keys(void)
98 {
99         mppe_keys_set = 0;
100         BZERO(mppe_send_key, sizeof(mppe_send_key));
101         BZERO(mppe_recv_key, sizeof(mppe_recv_key));
102 }
103
104 /*
105  * Set mppe_xxxx_key from the NTPasswordHashHash.
106  * RFC 2548 (RADIUS support) requires us to export this function (ugh).
107  */
108 void
109 mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
110 {
111     SHA1_CTX    sha1Context;
112     u_char      Digest[SHA1_SIGNATURE_SIZE];
113
114     SHA1_Init(&sha1Context);
115     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
116     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
117     SHA1_Update(&sha1Context, rchallenge, 8);
118     SHA1_Final(Digest, &sha1Context);
119
120     /* Same key in both directions. */
121     mppe_set_keys(Digest, Digest, sizeof(Digest));
122 }
123
124 /*
125  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
126  *
127  * This helper function used in the Winbind module, which gets the
128  * NTHashHash from the server.
129  */
130 void
131 mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
132                u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer)
133 {
134     SHA1_CTX    sha1Context;
135     u_char      MasterKey[SHA1_SIGNATURE_SIZE];
136     u_char      SendKey[SHA1_SIGNATURE_SIZE];
137     u_char      RecvKey[SHA1_SIGNATURE_SIZE];
138
139     u_char SHApad1[40] =
140         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
144     u_char SHApad2[40] =
145         { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
146           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
147           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
148           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
149
150     /* "This is the MPPE Master Key" */
151     u_char Magic1[27] =
152         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
153           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
154           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
155     /* "On the client side, this is the send key; "
156        "on the server side, it is the receive key." */
157     u_char Magic2[84] =
158         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
159           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
160           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
161           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
162           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
163           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
164           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
165           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
166           0x6b, 0x65, 0x79, 0x2e };
167     /* "On the client side, this is the receive key; "
168        "on the server side, it is the send key." */
169     u_char Magic3[84] =
170         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
171           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
172           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
173           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
174           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
175           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
176           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
177           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
178           0x6b, 0x65, 0x79, 0x2e };
179     u_char *s;
180
181     SHA1_Init(&sha1Context);
182     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
183     SHA1_Update(&sha1Context, NTResponse, 24);
184     SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
185     SHA1_Final(MasterKey, &sha1Context);
186
187     /*
188      * generate send key
189      */
190     if (IsServer)
191         s = Magic3;
192     else
193         s = Magic2;
194     SHA1_Init(&sha1Context);
195     SHA1_Update(&sha1Context, MasterKey, 16);
196     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
197     SHA1_Update(&sha1Context, s, 84);
198     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
199     SHA1_Final(SendKey, &sha1Context);
200
201     /*
202      * generate recv key
203      */
204     if (IsServer)
205         s = Magic2;
206     else
207         s = Magic3;
208     SHA1_Init(&sha1Context);
209     SHA1_Update(&sha1Context, MasterKey, 16);
210     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
211     SHA1_Update(&sha1Context, s, 84);
212     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
213     SHA1_Final(RecvKey, &sha1Context);
214
215     mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE);
216 }
217
218 /*
219  * Set MPPE options from plugins.
220  */
221 void
222 mppe_set_enc_types(int policy, int types)
223 {
224     /* Early exit for unknown policies. */
225     if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
226         policy != MPPE_ENC_POL_ENC_REQUIRED)
227         return;
228
229     /* Don't modify MPPE if it's optional and wasn't already configured. */
230     if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
231         return;
232
233     /*
234      * Disable undesirable encryption types.  Note that we don't ENABLE
235      * any encryption types, to avoid overriding manual configuration.
236      */
237     switch(types) {
238         case MPPE_ENC_TYPES_RC4_40:
239             ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
240             break;
241         case MPPE_ENC_TYPES_RC4_128:
242             ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
243             break;
244         default:
245             break;
246     }
247 }
248