2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_auth.h"
25 #include "gnutls_auth_int.h"
26 #include "gnutls_algorithms.h"
27 #include "auth_cert.h"
28 #include <gnutls_datum.h>
30 #include "auth_anon.h"
31 /* The functions here are used in order for authentication algorithms
32 * to be able to retrieve the needed credentials eg public and private
36 /* This clears the whole linked list */
37 int gnutls_clear_creds( GNUTLS_STATE state
) {
38 AUTH_CRED
* ccred
, *ncred
;
40 if (state
->gnutls_key
->cred
!=NULL
) { /* begining of the list */
41 ccred
= state
->gnutls_key
->cred
;
44 if (ccred
!=NULL
) gnutls_free(ccred
);
47 state
->gnutls_key
->cred
= NULL
;
54 * This creates a linked list of the form:
55 * { algorithm, credentials, pointer to next }
58 * gnutls_cred_set - Sets the needed credentials for the specified authentication algorithm.
59 * @state: is a &GNUTLS_STATE structure.
60 * @type: is the type of the credentials
61 * @cred: is a pointer to a structure.
63 * Sets the needed credentials for the specified type.
64 * Eg username, password - or public and private keys etc.
65 * The (void* cred) parameter is a structure that depends on the
66 * specified type and on the current state (client or server).
67 * [ In order to minimize memory usage, and share credentials between
68 * several threads gnutls keeps a pointer to cred, and not the whole cred
69 * structure. Thus you will have to keep the structure allocated until
70 * you call gnutls_deinit(). ]
72 * For GNUTLS_CRD_ANON cred should be ANON_CLIENT_CREDENTIALS in case of a client.
73 * In case of a server it should be ANON_SERVER_CREDENTIALS.
75 * For GNUTLS_CRD_SRP cred should be SRP_CLIENT_CREDENTIALS
76 * in case of a client, and SRP_SERVER_CREDENTIALS, in case
79 * For GNUTLS_CRD_CERTIFICATE cred should be CERTIFICATE_CLIENT_CREDENTIALS
80 * in case of a client, and CERTIFICATE_SERVER_CREDENTIALS, in case
83 int gnutls_cred_set( GNUTLS_STATE state
, GNUTLS_CredType type
, void* cred
) {
84 AUTH_CRED
* ccred
=NULL
, *pcred
=NULL
;
87 if (state
->gnutls_key
->cred
==NULL
) { /* begining of the list */
89 state
->gnutls_key
->cred
= gnutls_malloc(sizeof(AUTH_CRED
));
90 if (state
->gnutls_key
->cred
== NULL
) return GNUTLS_E_MEMORY_ERROR
;
92 /* copy credentials localy */
93 state
->gnutls_key
->cred
->credentials
= cred
;
95 state
->gnutls_key
->cred
->next
= NULL
;
96 state
->gnutls_key
->cred
->algorithm
= type
;
98 ccred
= state
->gnutls_key
->cred
;
100 if (ccred
->algorithm
==type
) {
107 /* After this, pcred is not null.
110 if (exists
==0) { /* new entry */
111 pcred
->next
= gnutls_malloc(sizeof(AUTH_CRED
));
112 if (pcred
->next
== NULL
) return GNUTLS_E_MEMORY_ERROR
;
116 /* copy credentials localy */
117 ccred
->credentials
= cred
;
120 ccred
->algorithm
= type
;
121 } else { /* modify existing entry */
122 gnutls_free(ccred
->credentials
);
123 ccred
->credentials
= cred
;
131 * gnutls_auth_get_type - Returns the type of credentials for the current authentication schema.
132 * @state: is a &GNUTLS_STATE structure.
134 * Returns type of credentials for the current authentication schema.
135 * The returned information is to be used to distinguish the function used
136 * to access authentication data.
138 * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA),
139 * the same function are to be used to access the authentication data.
141 GNUTLS_CredType
gnutls_auth_get_type( GNUTLS_STATE state
) {
143 return _gnutls_map_kx_get_cred(
144 _gnutls_cipher_suite_get_kx_algo
145 (state
->security_parameters
.current_cipher_suite
));
149 * This returns an pointer to the linked list. Don't
152 const void *_gnutls_get_kx_cred( GNUTLS_KEY key
, KXAlgorithm algo
, int *err
) {
153 return _gnutls_get_cred( key
, _gnutls_map_kx_get_cred(algo
), err
);
155 const void *_gnutls_get_cred( GNUTLS_KEY key
, CredType type
, int *err
) {
160 if (ccred
->algorithm
==type
) {
166 if (err
!=NULL
) *err
=-1;
170 if (err
!=NULL
) *err
=0;
171 return ccred
->credentials
;
175 * _gnutls_get_auth_info - Returns a pointer to authentication information.
176 * @state: is a &GNUTLS_STATE structure.
178 * This function must be called after a succesful gnutls_handshake().
179 * Returns a pointer to authentication information. That information
180 * is data obtained by the handshake protocol, the key exchange algorithm,
181 * and the TLS extensions messages.
183 * In case of GNUTLS_CRD_ANON returns a pointer to &ANON_(SERVER/CLIENT)_AUTH_INFO;
184 * In case of GNUTLS_CRD_CERTIFICATE returns a pointer to structure &CERTIFICATE_(SERVER/CLIENT)_AUTH_INFO;
185 * In case of GNUTLS_CRD_SRP returns a pointer to structure &SRP_(SERVER/CLIENT)_AUTH_INFO;
187 void* _gnutls_get_auth_info( GNUTLS_STATE state
) {
188 return state
->gnutls_key
->auth_info
;
192 * _gnutls_free_auth_info - Frees the auth info structure
193 * @state: is a &GNUTLS_STATE structure.
195 * this function frees the auth info structure and sets it to
196 * null. It must be called since some structures contain malloced
199 void _gnutls_free_auth_info( GNUTLS_STATE state
) {
200 if (state
==NULL
|| state
->gnutls_key
==NULL
) {
205 switch ( state
->gnutls_key
->auth_info_type
) {
207 case GNUTLS_CRD_ANON
:
210 case GNUTLS_CRD_CERTIFICATE
: {
212 CERTIFICATE_AUTH_INFO info
=
213 _gnutls_get_auth_info(state
);
215 if (info
==NULL
) break;
216 for (i
=0;i
<info
->ncerts
;i
++) {
217 gnutls_free_datum( &info
->raw_certificate_list
[i
]);
220 gnutls_free( info
->raw_certificate_list
);
221 info
->raw_certificate_list
= NULL
;
232 gnutls_free( state
->gnutls_key
->auth_info
);
233 state
->gnutls_key
->auth_info
= NULL
;
234 state
->gnutls_key
->auth_info_size
= 0;
235 state
->gnutls_key
->auth_info_type
= 0;
239 /* This function will set the auth info structure in the gnutls_key
241 * If allow change is !=0 then this will allow changing the auth
242 * info structure to a different type.
244 int _gnutls_auth_info_set( GNUTLS_STATE state
, CredType type
, int size
, int allow_change
) {
245 if ( state
->gnutls_key
->auth_info
== NULL
) {
246 state
->gnutls_key
->auth_info
= gnutls_calloc( 1, size
);
247 if (state
->gnutls_key
->auth_info
== NULL
) {
249 return GNUTLS_E_MEMORY_ERROR
;
251 state
->gnutls_key
->auth_info_type
= type
;
252 state
->gnutls_key
->auth_info_size
= size
;
254 if (allow_change
==0) {
255 /* If the credentials for the current authentication scheme,
256 * are not the one we want to set, then it's an error.
257 * This may happen if a rehandshake is performed an the
258 * ciphersuite which is negotiated has different authentication
261 if ( gnutls_auth_get_type( state
) != state
->gnutls_key
->auth_info_type
) {
263 return GNUTLS_E_INVALID_REQUEST
;
266 /* The new behaviour: Here we reallocate the auth info structure
267 * in order to be able to negotiate different authentication
268 * types. Ie. perform an auth_anon and then authenticate again using a
269 * certificate (in order to prevent revealing the certificate's contents,
270 * to passive eavesdropers.
272 if ( gnutls_auth_get_type( state
) != state
->gnutls_key
->auth_info_type
) {
273 state
->gnutls_key
->auth_info
= gnutls_realloc_fast(
274 state
->gnutls_key
->auth_info
, size
);
275 if (state
->gnutls_key
->auth_info
== NULL
) {
277 return GNUTLS_E_MEMORY_ERROR
;
279 memset( state
->gnutls_key
->auth_info
, 0, size
);
280 state
->gnutls_key
->auth_info_type
= type
;
281 state
->gnutls_key
->auth_info_size
= size
;
288 /* this function will copy an GNUTLS_MPI key to
291 int _gnutls_generate_key(GNUTLS_KEY key
) {
292 _gnutls_mpi_print( NULL
, &key
->key
.size
, key
->KEY
);
293 key
->key
.data
= gnutls_secure_malloc( key
->key
.size
);
294 if ( key
->key
.data
==NULL
) {
295 return GNUTLS_E_MEMORY_ERROR
;
297 _gnutls_mpi_print( key
->key
.data
, &key
->key
.size
, key
->KEY
);