1254721Semaste/*
2254721Semaste * chap-md5.c - New CHAP/MD5 implementation.
3254721Semaste *
4254721Semaste * Copyright (c) 2003 Paul Mackerras. All rights reserved.
5254721Semaste *
6254721Semaste * Redistribution and use in source and binary forms, with or without
7254721Semaste * modification, are permitted provided that the following conditions
8254721Semaste * are met:
9254721Semaste *
10254721Semaste * 1. Redistributions of source code must retain the above copyright
11254721Semaste *    notice, this list of conditions and the following disclaimer.
12254721Semaste *
13254721Semaste * 2. The name(s) of the authors of this software must not be used to
14254721Semaste *    endorse or promote products derived from this software without
15254721Semaste *    prior written permission.
16254721Semaste *
17254721Semaste * 3. Redistributions of any form whatsoever must retain the following
18254721Semaste *    acknowledgment:
19254721Semaste *    "This product includes software developed by Paul Mackerras
20254721Semaste *     <paulus@samba.org>".
21254721Semaste *
22254721Semaste * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23254721Semaste * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24254721Semaste * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25254721Semaste * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26254721Semaste * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27254721Semaste * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28254721Semaste * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29254721Semaste */
30254721Semaste
31254721Semaste#include "netif/ppp/ppp_opts.h"
32254721Semaste#if PPP_SUPPORT && CHAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
33254721Semaste
34254721Semaste#if 0 /* UNUSED */
35254721Semaste#include <stdlib.h>
36254721Semaste#include <string.h>
37254721Semaste#endif /* UNUSED */
38254721Semaste
39254721Semaste#include "netif/ppp/ppp_impl.h"
40254721Semaste
41254721Semaste#include "netif/ppp/chap-new.h"
42254721Semaste#include "netif/ppp/chap-md5.h"
43254721Semaste#include "netif/ppp/magic.h"
44254721Semaste#include "netif/ppp/pppcrypt.h"
45254721Semaste
46254721Semaste#define MD5_HASH_SIZE		16
47254721Semaste#define MD5_MIN_CHALLENGE	17
48254721Semaste#define MD5_MAX_CHALLENGE	24
49254721Semaste#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE     3   /* 2^3-1 = 7, 17+7 = 24 */
50254721Semaste
51254721Semaste#if PPP_SERVER
52254721Semastestatic void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) {
53254721Semaste	int clen;
54254721Semaste	LWIP_UNUSED_ARG(pcb);
55254721Semaste
56254721Semaste	clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE);
57254721Semaste	*cp++ = clen;
58254721Semaste	magic_random_bytes(cp, clen);
59254721Semaste}
60254721Semaste
61254721Semastestatic int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name,
62254721Semaste			 const unsigned char *secret, int secret_len,
63254721Semaste			 const unsigned char *challenge, const unsigned char *response,
64254721Semaste			 char *message, int message_space) {
65254721Semaste	lwip_md5_context ctx;
66254721Semaste	unsigned char idbyte = id;
67254721Semaste	unsigned char hash[MD5_HASH_SIZE];
68254721Semaste	int challenge_len, response_len;
69254721Semaste	LWIP_UNUSED_ARG(name);
70254721Semaste	LWIP_UNUSED_ARG(pcb);
71254721Semaste
72254721Semaste	challenge_len = *challenge++;
73254721Semaste	response_len = *response++;
74254721Semaste	if (response_len == MD5_HASH_SIZE) {
75254721Semaste		/* Generate hash of ID, secret, challenge */
76254721Semaste		lwip_md5_init(&ctx);
77254721Semaste		lwip_md5_starts(&ctx);
78254721Semaste		lwip_md5_update(&ctx, &idbyte, 1);
79254721Semaste		lwip_md5_update(&ctx, secret, secret_len);
80254721Semaste		lwip_md5_update(&ctx, challenge, challenge_len);
81254721Semaste		lwip_md5_finish(&ctx, hash);
82254721Semaste		lwip_md5_free(&ctx);
83254721Semaste
84254721Semaste		/* Test if our hash matches the peer's response */
85254721Semaste		if (memcmp(hash, response, MD5_HASH_SIZE) == 0) {
86254721Semaste			ppp_slprintf(message, message_space, "Access granted");
87254721Semaste			return 1;
88254721Semaste		}
89254721Semaste	}
90254721Semaste	ppp_slprintf(message, message_space, "Access denied");
91254721Semaste	return 0;
92254721Semaste}
93254721Semaste#endif /* PPP_SERVER */
94254721Semaste
95254721Semastestatic void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name,
96254721Semaste		       const unsigned char *challenge, const char *secret, int secret_len,
97254721Semaste		       unsigned char *private_) {
98254721Semaste	lwip_md5_context ctx;
99254721Semaste	unsigned char idbyte = id;
100254721Semaste	int challenge_len = *challenge++;
101254721Semaste	LWIP_UNUSED_ARG(our_name);
102254721Semaste	LWIP_UNUSED_ARG(private_);
103254721Semaste	LWIP_UNUSED_ARG(pcb);
104254721Semaste
105254721Semaste	lwip_md5_init(&ctx);
106254721Semaste	lwip_md5_starts(&ctx);
107254721Semaste	lwip_md5_update(&ctx, &idbyte, 1);
108254721Semaste	lwip_md5_update(&ctx, (const u_char *)secret, secret_len);
109254721Semaste	lwip_md5_update(&ctx, challenge, challenge_len);
110254721Semaste	lwip_md5_finish(&ctx, &response[1]);
111254721Semaste	lwip_md5_free(&ctx);
112254721Semaste	response[0] = MD5_HASH_SIZE;
113254721Semaste}
114254721Semaste
115254721Semasteconst struct chap_digest_type md5_digest = {
116254721Semaste	CHAP_MD5,		/* code */
117254721Semaste#if PPP_SERVER
118254721Semaste	chap_md5_generate_challenge,
119254721Semaste	chap_md5_verify_response,
120254721Semaste#endif /* PPP_SERVER */
121254721Semaste	chap_md5_make_response,
122254721Semaste	NULL,			/* check_success */
123254721Semaste	NULL,			/* handle_failure */
124254721Semaste};
125254721Semaste
126254721Semaste#endif /* PPP_SUPPORT && CHAP_SUPPORT */
127254721Semaste