Added generic CHAP layer, independent of iSCSI
[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 <errno.h>
22 #include <assert.h>
23 #include <malloc.h>
24 #include <gpxe/crypto.h>
25 #include <gpxe/chap.h>
26
27 /** @file
28  *
29  * CHAP protocol
30  *
31  */
32
33 /**
34  * Initialise CHAP challenge/response
35  *
36  * @v chap              CHAP challenge/response
37  * @v digest            Digest algorithm to use
38  * @ret rc              Return status code
39  *
40  * Initialises a CHAP challenge/response structure.  This routine
41  * allocates memory, and so may fail.  The allocated memory must
42  * eventually be freed by a call to chap_finish().
43  */
44 int chap_init ( struct chap_challenge *chap,
45                 struct digest_algorithm *digest ) {
46         assert ( chap->digest == NULL );
47         assert ( chap->digest_context == NULL );
48         assert ( chap->response == NULL );
49
50         chap->digest = digest;
51         chap->digest_context = malloc ( digest->context_len );
52         if ( ! chap->digest_context )
53                 goto err;
54         chap->response = malloc ( digest->digest_len );
55         if ( ! chap->response )
56                 goto err;
57         chap->response_len = digest->digest_len;
58         chap->digest->init ( chap->digest_context );
59         return 0;
60
61  err:
62         chap_finish ( chap );
63         return -ENOMEM;
64 }
65
66 /**
67  * Add data to the CHAP challenge
68  *
69  * @v chap              CHAP challenge/response
70  * @v data              Data to add
71  * @v len               Length of data to add
72  */
73 void chap_update ( struct chap_challenge *chap, const void *data,
74                    size_t len ) {
75         assert ( chap->digest != NULL );
76         assert ( chap->digest_context != NULL );
77
78         chap->digest->update ( chap->digest_context, data, len );
79 }
80
81 /**
82  * Respond to the CHAP challenge
83  *
84  * @v chap              CHAP challenge/response
85  *
86  * Calculates the final CHAP response value, and places it in @c
87  * chap->response, with a length of @c chap->response_len.
88  */
89 void chap_respond ( struct chap_challenge *chap ) {
90         assert ( chap->digest != NULL );
91         assert ( chap->digest_context != NULL );
92         assert ( chap->response != NULL );
93
94         chap->digest->finish ( chap->digest_context, chap->response );
95 }
96
97 /**
98  * Free resources used by a CHAP challenge/response
99  *
100  * @v chap              CHAP challenge/response
101  */
102 void chap_finish ( struct chap_challenge *chap ) {
103         free ( chap->digest_context );
104         chap->digest_context = NULL;
105         free ( chap->response );
106         chap->response = NULL;
107         chap->digest = NULL;
108 }