1 /* $NetBSD: chap-md5.c,v 1.4 2014/10/25 21:11:37 christos Exp $ */ 2 3 /* 4 * chap-md5.c - New CHAP/MD5 implementation. 5 * 6 * Copyright (c) 2003 Paul Mackerras. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. The name(s) of the authors of this software must not be used to 16 * endorse or promote products derived from this software without 17 * prior written permission. 18 * 19 * 3. Redistributions of any form whatsoever must retain the following 20 * acknowledgment: 21 * "This product includes software developed by Paul Mackerras 22 * <paulus@samba.org>". 23 * 24 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 25 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 26 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 27 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 29 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 30 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 31 */ 32 33 #include <sys/cdefs.h> 34 #if 0 35 #define RCSID "Id: chap-md5.c,v 1.4 2004/11/09 22:39:25 paulus Exp " 36 static const char rcsid[] = RCSID; 37 #else 38 __RCSID("$NetBSD: chap-md5.c,v 1.4 2014/10/25 21:11:37 christos Exp $"); 39 #endif 40 41 #include <stdlib.h> 42 #include <string.h> 43 #include <md5.h> 44 #include "pppd.h" 45 #include "chap-new.h" 46 #include "chap-md5.h" 47 #include "magic.h" 48 49 #define MD5_HASH_SIZE 16 50 #define MD5_MIN_CHALLENGE 16 51 #define MD5_MAX_CHALLENGE 24 52 53 static void 54 chap_md5_generate_challenge(unsigned char *cp) 55 { 56 int clen; 57 58 clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE)) 59 + MD5_MIN_CHALLENGE; 60 *cp++ = clen; 61 random_bytes(cp, clen); 62 } 63 64 static int 65 chap_md5_verify_response(int id, char *name, 66 unsigned char *secret, int secret_len, 67 unsigned char *challenge, unsigned char *response, 68 char *message, int message_space) 69 { 70 MD5_CTX ctx; 71 unsigned char idbyte = id; 72 unsigned char hash[MD5_HASH_SIZE]; 73 int challenge_len, response_len; 74 75 challenge_len = *challenge++; 76 response_len = *response++; 77 if (response_len == MD5_HASH_SIZE) { 78 /* Generate hash of ID, secret, challenge */ 79 MD5Init(&ctx); 80 MD5Update(&ctx, &idbyte, 1); 81 MD5Update(&ctx, secret, secret_len); 82 MD5Update(&ctx, challenge, challenge_len); 83 MD5Final(hash, &ctx); 84 85 /* Test if our hash matches the peer's response */ 86 if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { 87 slprintf(message, message_space, "Access granted"); 88 return 1; 89 } 90 } 91 slprintf(message, message_space, "Access denied"); 92 return 0; 93 } 94 95 static void 96 chap_md5_make_response(unsigned char *response, int id, char *our_name, 97 unsigned char *challenge, char *secret, int secret_len, 98 unsigned char *private) 99 { 100 MD5_CTX ctx; 101 unsigned char idbyte = id; 102 int challenge_len = *challenge++; 103 104 MD5Init(&ctx); 105 MD5Update(&ctx, &idbyte, 1); 106 MD5Update(&ctx, secret, secret_len); 107 MD5Update(&ctx, challenge, challenge_len); 108 MD5Final(&response[1], &ctx); 109 response[0] = MD5_HASH_SIZE; 110 } 111 112 static struct chap_digest_type md5_digest = { 113 CHAP_MD5, /* code */ 114 chap_md5_generate_challenge, 115 chap_md5_verify_response, 116 chap_md5_make_response, 117 NULL, /* check_success */ 118 NULL, /* handle_failure */ 119 }; 120 121 void 122 chap_md5_init(void) 123 { 124 chap_register_digest(&md5_digest); 125 } 126