1 /* mppe.c - MPPE key implementation 2 * 3 * Copyright (c) 2020 Eivind Naess. All rights reserved. 4 * Copyright (c) 2008-2024 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 unsigned 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 unsigned 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 326