2 * chap-md5.c - New CHAP/MD5 implementation.
4 * Copyright (c) 2003 Paul Mackerras. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
17 * 3. Redistributions of any form whatsoever must retain the following
19 * "This product includes software developed by Paul Mackerras
20 * <paulus@samba.org>".
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.
31 #define RCSID "$Id: chap-md5.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
41 #define MD5_HASH_SIZE 16
42 #define MD5_MIN_CHALLENGE 16
43 #define MD5_MAX_CHALLENGE 24
46 chap_md5_generate_challenge(unsigned char *cp
)
50 clen
= (int)(drand48() * (MD5_MAX_CHALLENGE
- MD5_MIN_CHALLENGE
))
53 random_bytes(cp
, clen
);
57 chap_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
)
63 unsigned char idbyte
= id
;
64 unsigned char hash
[MD5_HASH_SIZE
];
65 int challenge_len
, response_len
;
67 challenge_len
= *challenge
++;
68 response_len
= *response
++;
69 if (response_len
== MD5_HASH_SIZE
) {
70 /* Generate hash of ID, secret, challenge */
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
);
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");
83 slprintf(message
, message_space
, "Access denied");
88 chap_md5_make_response(unsigned char *response
, int id
, char *our_name
,
89 unsigned char *challenge
, char *secret
, int secret_len
,
90 unsigned char *private)
93 unsigned char idbyte
= id
;
94 int challenge_len
= *challenge
++;
97 MD5_Update(&ctx
, &idbyte
, 1);
98 MD5_Update(&ctx
, secret
, secret_len
);
99 MD5_Update(&ctx
, challenge
, challenge_len
);
100 MD5_Final(&response
[1], &ctx
);
101 response
[0] = MD5_HASH_SIZE
;
104 static struct chap_digest_type md5_digest
= {
106 chap_md5_generate_challenge
,
107 chap_md5_verify_response
,
108 chap_md5_make_response
,
109 NULL
, /* check_success */
110 NULL
, /* handle_failure */
116 chap_register_digest(&md5_digest
);