1 /* * mppe.c - MPPE key implementation
3 * Copyright (c) 2020 Eivind Naess. All rights reserved.
4 * Copyright (c) 2008 Paul Mackerras. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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
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.
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.
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;
52 mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen)
55 if (length > MPPE_MAX_KEY_SIZE)
56 length = MPPE_MAX_KEY_SIZE;
59 BCOPY(send_key, mppe_send_key, length);
60 BZERO(send_key, keylen);
64 BCOPY(recv_key, mppe_recv_key, length);
65 BZERO(recv_key, keylen);
68 mppe_keys_set = length;
74 return !!mppe_keys_set;
78 mppe_get_recv_key(u_char *recv_key, int length)
80 if (mppe_keys_isset()) {
81 if (length > mppe_keys_set)
82 length = mppe_keys_set;
83 BCOPY(mppe_recv_key, recv_key, length);
90 mppe_get_send_key(u_char *send_key, int length)
92 if (mppe_keys_isset()) {
93 if (length > mppe_keys_set)
94 length = mppe_keys_set;
95 BCOPY(mppe_send_key, send_key, length);
102 mppe_clear_keys(void)
105 BZERO(mppe_send_key, sizeof(mppe_send_key));
106 BZERO(mppe_recv_key, sizeof(mppe_recv_key));
110 * Set mppe_xxxx_key from the NTPasswordHashHash.
111 * RFC 2548 (RADIUS support) requires us to export this function (ugh).
114 mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
116 SHA1_CTX sha1Context;
117 u_char Digest[SHA1_SIGNATURE_SIZE];
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);
125 /* Same key in both directions. */
126 mppe_set_keys(Digest, Digest, sizeof(Digest));
130 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
132 * This helper function used in the Winbind module, which gets the
133 * NTHashHash from the server.
136 mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
137 u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer)
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];
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 };
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 };
155 /* "This is the MPPE Master Key" */
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." */
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." */
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 };
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);
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);
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);
220 mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE);
226 * Set MPPE options from plugins.
229 mppe_set_enc_types(int policy, int types)
231 /* Early exit for unknown policies. */
232 if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
233 policy != MPPE_ENC_POL_ENC_REQUIRED)
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)
241 * Disable undesirable encryption types. Note that we don't ENABLE
242 * any encryption types, to avoid overriding manual configuration.
245 case MPPE_ENC_TYPES_RC4_40:
246 ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
248 case MPPE_ENC_TYPES_RC4_128:
249 ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */