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.
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;
47 mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen)
50 if (length > MPPE_MAX_KEY_SIZE)
51 length = MPPE_MAX_KEY_SIZE;
54 BCOPY(send_key, mppe_send_key, length);
55 BZERO(send_key, keylen);
59 BCOPY(recv_key, mppe_recv_key, length);
60 BZERO(recv_key, keylen);
63 mppe_keys_set = length;
69 return !!mppe_keys_set;
73 mppe_get_recv_key(u_char *recv_key, int length)
75 if (mppe_keys_isset()) {
76 if (length > mppe_keys_set)
77 length = mppe_keys_set;
78 BCOPY(mppe_recv_key, recv_key, length);
85 mppe_get_send_key(u_char *send_key, int length)
87 if (mppe_keys_isset()) {
88 if (length > mppe_keys_set)
89 length = mppe_keys_set;
90 BCOPY(mppe_send_key, send_key, length);
100 BZERO(mppe_send_key, sizeof(mppe_send_key));
101 BZERO(mppe_recv_key, sizeof(mppe_recv_key));
105 * Set mppe_xxxx_key from the NTPasswordHashHash.
106 * RFC 2548 (RADIUS support) requires us to export this function (ugh).
109 mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
111 SHA1_CTX sha1Context;
112 u_char Digest[SHA1_SIGNATURE_SIZE];
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);
120 /* Same key in both directions. */
121 mppe_set_keys(Digest, Digest, sizeof(Digest));
125 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
127 * This helper function used in the Winbind module, which gets the
128 * NTHashHash from the server.
131 mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
132 u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer)
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];
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 };
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 };
150 /* "This is the MPPE Master Key" */
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." */
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." */
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 };
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);
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);
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);
215 mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE);
219 * Set MPPE options from plugins.
222 mppe_set_enc_types(int policy, int types)
224 /* Early exit for unknown policies. */
225 if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
226 policy != MPPE_ENC_POL_ENC_REQUIRED)
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)
234 * Disable undesirable encryption types. Note that we don't ENABLE
235 * any encryption types, to avoid overriding manual configuration.
238 case MPPE_ENC_TYPES_RC4_40:
239 ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
241 case MPPE_ENC_TYPES_RC4_128:
242 ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */