Added debug statements.
[people/xl0/gpxe.git] / src / crypto / chap.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <assert.h>
24 #include <malloc.h>
25 #include <gpxe/crypto.h>
26 #include <gpxe/chap.h>
27
28 /** @file
29  *
30  * CHAP protocol
31  *
32  */
33
34 /**
35  * Initialise CHAP challenge/response
36  *
37  * @v chap              CHAP challenge/response
38  * @v digest            Digest algorithm to use
39  * @ret rc              Return status code
40  *
41  * Initialises a CHAP challenge/response structure.  This routine
42  * allocates memory, and so may fail.  The allocated memory must
43  * eventually be freed by a call to chap_finish().
44  */
45 int chap_init ( struct chap_challenge *chap,
46                 struct digest_algorithm *digest ) {
47         size_t state_len;
48         void *state;
49
50         assert ( chap->digest == NULL );
51         assert ( chap->digest_context == NULL );
52         assert ( chap->response == NULL );
53
54         DBG ( "CHAP %p initialising with %s digest\n", chap, digest->name );
55
56         state_len = ( digest->context_len + digest->digest_len );
57         state = malloc ( state_len );
58         if ( ! state ) {
59                 DBG ( "CHAP %p could not allocate %d bytes for state\n",
60                       chap, state_len );
61                 return -ENOMEM;
62         }
63         
64         chap->digest = digest;
65         chap->digest_context = state;
66         chap->response = ( state + digest->context_len );
67         chap->response_len = digest->digest_len;
68         chap->digest->init ( chap->digest_context );
69         return 0;
70 }
71
72 /**
73  * Add data to the CHAP challenge
74  *
75  * @v chap              CHAP challenge/response
76  * @v data              Data to add
77  * @v len               Length of data to add
78  */
79 void chap_update ( struct chap_challenge *chap, const void *data,
80                    size_t len ) {
81         assert ( chap->digest != NULL );
82         assert ( chap->digest_context != NULL );
83
84         if ( ! chap->digest )
85                 return;
86
87         chap->digest->update ( chap->digest_context, data, len );
88 }
89
90 /**
91  * Respond to the CHAP challenge
92  *
93  * @v chap              CHAP challenge/response
94  *
95  * Calculates the final CHAP response value, and places it in @c
96  * chap->response, with a length of @c chap->response_len.
97  */
98 void chap_respond ( struct chap_challenge *chap ) {
99         assert ( chap->digest != NULL );
100         assert ( chap->digest_context != NULL );
101         assert ( chap->response != NULL );
102
103         DBG ( "CHAP %p responding to challenge\n", chap );
104
105         if ( ! chap->digest )
106                 return;
107
108         chap->digest->finish ( chap->digest_context, chap->response );
109 }
110
111 /**
112  * Free resources used by a CHAP challenge/response
113  *
114  * @v chap              CHAP challenge/response
115  */
116 void chap_finish ( struct chap_challenge *chap ) {
117         void *state = chap->digest_context;
118
119         DBG ( "CHAP %p finished\n", chap );
120
121         free ( state );
122         memset ( chap, 0, sizeof ( *chap ) );
123 }