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