xref: /netbsd-src/external/bsd/ppp/dist/pppd/chap-md5.c (revision b8ecfcfef0e343ad71faea7a54fb5fcb42ad4e27)
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