1/* 2 * chap-md5.c - New CHAP/MD5 implementation. 3 * 4 * Copyright (c) 2003 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. The name(s) of the authors of this software must not be used to 14 * endorse or promote products derived from this software without 15 * prior written permission. 16 * 17 * 3. Redistributions of any form whatsoever must retain the following 18 * acknowledgment: 19 * "This product includes software developed by Paul Mackerras 20 * <paulus@samba.org>". 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#define RCSID "$Id: chap-md5.c,v 1.4 2004/11/09 22:39:25 paulus Exp $" 32 33#include <stdlib.h> 34#include <string.h> 35#include "pppd.h" 36#include "chap-new.h" 37#include "chap-md5.h" 38#include "magic.h" 39#include "md5.h" 40 41#define MD5_HASH_SIZE 16 42#define MD5_MIN_CHALLENGE 16 43#define MD5_MAX_CHALLENGE 24 44 45static void 46chap_md5_generate_challenge(unsigned char *cp) 47{ 48 int clen; 49 50 clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE)) 51 + MD5_MIN_CHALLENGE; 52 *cp++ = clen; 53 random_bytes(cp, clen); 54} 55 56static int 57chap_md5_verify_response(int id, char *name, 58 unsigned char *secret, int secret_len, 59 unsigned char *challenge, unsigned char *response, 60 char *message, int message_space) 61{ 62 MD5_CTX ctx; 63 unsigned char idbyte = id; 64 unsigned char hash[MD5_HASH_SIZE]; 65 int challenge_len, response_len; 66 67 challenge_len = *challenge++; 68 response_len = *response++; 69 if (response_len == MD5_HASH_SIZE) { 70 /* Generate hash of ID, secret, challenge */ 71 MD5_Init(&ctx); 72 MD5_Update(&ctx, &idbyte, 1); 73 MD5_Update(&ctx, secret, secret_len); 74 MD5_Update(&ctx, challenge, challenge_len); 75 MD5_Final(hash, &ctx); 76 77 /* Test if our hash matches the peer's response */ 78 if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { 79 slprintf(message, message_space, "Access granted"); 80 return 1; 81 } 82 } 83 slprintf(message, message_space, "Access denied"); 84 return 0; 85} 86 87static void 88chap_md5_make_response(unsigned char *response, int id, char *our_name, 89 unsigned char *challenge, char *secret, int secret_len, 90 unsigned char *private) 91{ 92 MD5_CTX ctx; 93 unsigned char idbyte = id; 94 int challenge_len = *challenge++; 95 96 MD5_Init(&ctx); 97 MD5_Update(&ctx, &idbyte, 1); 98 MD5_Update(&ctx, (u_char *)secret, secret_len); 99 MD5_Update(&ctx, challenge, challenge_len); 100 MD5_Final(&response[1], &ctx); 101 response[0] = MD5_HASH_SIZE; 102} 103 104static struct chap_digest_type md5_digest = { 105 CHAP_MD5, /* code */ 106 chap_md5_generate_challenge, 107 chap_md5_verify_response, 108 chap_md5_make_response, 109 NULL, /* check_success */ 110 NULL, /* handle_failure */ 111}; 112 113void 114chap_md5_init(void) 115{ 116 chap_register_digest(&md5_digest); 117} 118