• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 FILE_LICENCE ( GPL2_OR_LATER );
20 
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <gpxe/crypto.h>
27 #include <gpxe/chap.h>
28 
29 /** @file
30  *
31  * CHAP protocol
32  *
33  */
34 
35 /**
36  * Initialise CHAP challenge/response
37  *
38  * @v chap		CHAP challenge/response
39  * @v digest		Digest algorithm to use
40  * @ret rc		Return status code
41  *
42  * Initialises a CHAP challenge/response structure.  This routine
43  * allocates memory, and so may fail.  The allocated memory must
44  * eventually be freed by a call to chap_finish().
45  */
chap_init(struct chap_response * chap,struct digest_algorithm * digest)46 int chap_init ( struct chap_response *chap,
47 		struct digest_algorithm *digest ) {
48 	size_t state_len;
49 	void *state;
50 
51 	assert ( chap->digest == NULL );
52 	assert ( chap->digest_context == NULL );
53 	assert ( chap->response == NULL );
54 
55 	DBG ( "CHAP %p initialising with %s digest\n", chap, digest->name );
56 
57 	state_len = ( digest->ctxsize + digest->digestsize );
58 	state = malloc ( state_len );
59 	if ( ! state ) {
60 		DBG ( "CHAP %p could not allocate %zd bytes for state\n",
61 		      chap, state_len );
62 		return -ENOMEM;
63 	}
64 
65 	chap->digest = digest;
66 	chap->digest_context = state;
67 	chap->response = ( state + digest->ctxsize );
68 	chap->response_len = digest->digestsize;
69 	digest_init ( chap->digest, chap->digest_context );
70 	return 0;
71 }
72 
73 /**
74  * Add data to the CHAP challenge
75  *
76  * @v chap		CHAP response
77  * @v data		Data to add
78  * @v len		Length of data to add
79  */
chap_update(struct chap_response * chap,const void * data,size_t len)80 void chap_update ( struct chap_response *chap, const void *data,
81 		   size_t len ) {
82 	assert ( chap->digest != NULL );
83 	assert ( chap->digest_context != NULL );
84 
85 	if ( ! chap->digest )
86 		return;
87 
88 	digest_update ( chap->digest, chap->digest_context, data, len );
89 }
90 
91 /**
92  * Respond to the CHAP challenge
93  *
94  * @v chap		CHAP response
95  *
96  * Calculates the final CHAP response value, and places it in @c
97  * chap->response, with a length of @c chap->response_len.
98  */
chap_respond(struct chap_response * chap)99 void chap_respond ( struct chap_response *chap ) {
100 	assert ( chap->digest != NULL );
101 	assert ( chap->digest_context != NULL );
102 	assert ( chap->response != NULL );
103 
104 	DBG ( "CHAP %p responding to challenge\n", chap );
105 
106 	if ( ! chap->digest )
107 		return;
108 
109 	digest_final ( chap->digest, chap->digest_context, chap->response );
110 }
111 
112 /**
113  * Free resources used by a CHAP response
114  *
115  * @v chap		CHAP response
116  */
chap_finish(struct chap_response * chap)117 void chap_finish ( struct chap_response *chap ) {
118 	void *state = chap->digest_context;
119 
120 	DBG ( "CHAP %p finished\n", chap );
121 
122 	free ( state );
123 	memset ( chap, 0, sizeof ( *chap ) );
124 }
125