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 <auth_cert.h>
25 #include <gnutls_cert.h>
26 #include <x509_asn1.h>
28 #include <gnutls_datum.h>
29 #include <gnutls_mpi.h>
30 #include <gnutls_global.h>
31 #include <x509_verify.h>
32 #include <gnutls_privkey.h>
33 #include <x509_extensions.h>
34 #include <gnutls_algorithms.h>
35 #include <gnutls_dh.h>
36 #include <gnutls_str.h>
37 #include <gnutls_state.h>
38 #include <gnutls_auth_int.h>
39 #include <gnutls_x509.h>
40 #include <gnutls_extra.h>
42 /* KX mappings to PK algorithms */
44 KXAlgorithm kx_algorithm
;
45 PKAlgorithm pk_algorithm
;
48 /* This table maps the Key exchange algorithms to
49 * the certificate algorithms. Eg. if we have
50 * RSA algorithm in the certificate then we can
51 * use GNUTLS_KX_RSA or GNUTLS_KX_DHE_RSA.
53 static const gnutls_pk_map pk_mappings
[] = {
54 {GNUTLS_KX_RSA
, GNUTLS_PK_RSA
},
55 {GNUTLS_KX_DHE_RSA
, GNUTLS_PK_RSA
},
56 {GNUTLS_KX_DHE_DSS
, GNUTLS_PK_DSA
},
60 #define GNUTLS_PK_MAP_LOOP(b) \
61 const gnutls_pk_map *p; \
62 for(p = pk_mappings; p->kx_algorithm != 0; p++) { b ; }
64 #define GNUTLS_PK_MAP_ALG_LOOP(a) \
65 GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == kx_algorithm) { a; break; })
68 /* returns the PKAlgorithm which is compatible with
69 * the given KXAlgorithm.
71 PKAlgorithm
_gnutls_map_pk_get_pk(KXAlgorithm kx_algorithm
)
75 GNUTLS_PK_MAP_ALG_LOOP(ret
= p
->pk_algorithm
);
79 void _gnutls_free_cert(gnutls_cert cert
)
83 for (i
= 0; i
< cert
.params_size
; i
++) {
84 _gnutls_mpi_release(&cert
.params
[i
]);
87 gnutls_free_datum(&cert
.signature
);
88 gnutls_free_datum(&cert
.raw
);
94 * gnutls_certificate_free_sc - Used to free an allocated CERTIFICATE CREDENTIALS structure
95 * @sc: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
97 * This structure is complex enough to manipulate directly thus
98 * this helper function is provided in order to free (deallocate)
101 void gnutls_certificate_free_sc(GNUTLS_CERTIFICATE_CREDENTIALS sc
)
105 for (i
= 0; i
< sc
->ncerts
; i
++) {
106 for (j
= 0; j
< sc
->cert_list_length
[i
]; j
++) {
107 _gnutls_free_cert(sc
->cert_list
[i
][j
]);
109 gnutls_free( sc
->cert_list
[i
]);
112 gnutls_free(sc
->cert_list_length
);
113 gnutls_free(sc
->cert_list
);
115 for (j
= 0; j
< sc
->x509_ncas
; j
++) {
116 _gnutls_free_cert( sc
->x509_ca_list
[j
]);
119 gnutls_free( sc
->x509_ca_list
);
120 gnutls_free_datum( &sc
->keyring
);
122 for (i
= 0; i
< sc
->ncerts
; i
++) {
123 _gnutls_free_private_key(sc
->pkey
[i
]);
126 gnutls_free( sc
->pkey
);
127 gnutls_free( sc
->x509_rdn_sequence
.data
);
134 * gnutls_certificate_allocate_sc - Used to allocate an x509 SERVER CREDENTIALS structure
135 * @res: is a pointer to an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
137 * This structure is complex enough to manipulate directly thus
138 * this helper function is provided in order to allocate
141 int gnutls_certificate_allocate_sc(GNUTLS_CERTIFICATE_CREDENTIALS
* res
)
143 *res
= gnutls_calloc(1, sizeof(CERTIFICATE_CREDENTIALS_INT
));
146 return GNUTLS_E_MEMORY_ERROR
;
148 (*res
)->dh_params
= &_gnutls_dh_default_params
;
154 /* returns the KX algorithms that are supported by a
155 * certificate. (Eg a certificate with RSA params, supports
156 * GNUTLS_KX_RSA algorithm).
157 * This function also uses the KeyUsage field of the certificate
158 * extensions in order to disable unneded algorithms.
160 int _gnutls_cert_supported_kx(const gnutls_cert
* cert
, KXAlgorithm
** alg
,
166 KXAlgorithm kxlist
[MAX_ALGOS
];
169 for (kx
= 0; kx
< MAX_ALGOS
; kx
++) {
170 pk
= _gnutls_map_pk_get_pk(kx
);
171 if (pk
== cert
->subject_pk_algorithm
) {
172 if (cert
->cert_type
==GNUTLS_CRT_X509
) {
173 /* then check key usage */
174 if (_gnutls_check_x509_key_usage(cert
, kx
) == 0) {
178 } else if ( cert
->cert_type
==GNUTLS_CRT_OPENPGP
) {
179 /* FIXME: something like key usage
190 return GNUTLS_E_INVALID_PARAMETERS
;
193 *alg
= gnutls_calloc(1, sizeof(KXAlgorithm
) * i
);
195 return GNUTLS_E_MEMORY_ERROR
;
199 memcpy(*alg
, kxlist
, i
* sizeof(KXAlgorithm
));
206 * gnutls_certificate_server_set_request - Used to set whether to request a client certificate
207 * @state: is an &GNUTLS_STATE structure.
208 * @req: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE
210 * This function specifies if we (in case of a server) are going
211 * to send a certificate request message to the client. If 'req'
212 * is GNUTLS_CERT_REQUIRE then the server will return an error if
213 * the peer does not provide a certificate. If you do not
214 * call this function then the client will not be asked to
215 * send a certificate.
217 void gnutls_certificate_server_set_request(GNUTLS_STATE state
,
218 CertificateRequest req
)
220 state
->gnutls_internals
.send_cert_req
= req
;
224 * gnutls_certificate_client_set_select_func - Used to set a callback while selecting the proper (client) certificate
225 * @state: is a &GNUTLS_STATE structure.
226 * @func: is the callback function
228 * The callback's function form is:
229 * int (*callback)(GNUTLS_STATE, gnutls_datum *client_cert, int ncerts, gnutls_datum* req_ca_cert, int nreqs);
231 * 'client_cert' contains 'ncerts' gnutls_datum structures which hold
232 * the raw certificates (DER for X.509 or binary for OpenPGP), of the
235 * 'req_ca_cert', is only used in X.509 certificates.
236 * Contains a list with the CA names that the server considers trusted.
237 * Normaly we should send a certificate that is signed
238 * by one of these CAs. These names are DER encoded. To get a more
239 * meaningful value use the function gnutls_x509_extract_dn().
241 * This function specifies what we, in case of a client, are going
242 * to do when we have to send a certificate. If this callback
243 * function is not provided then gnutls will automaticaly try to
244 * find an appropriate certificate to send.
246 * If the callback function is provided then gnutls will call it
247 * once with NULL parameters. If the callback function returns
248 * a positive or zero number then gnutls will attempt to automaticaly
249 * choose the appropriate certificate. If gnutls fails to find an appropriate
250 * certificate, then it will call the callback function again with the
251 * appropriate parameters.
253 * In case the callback returned a negative number then gnutls will
254 * not attempt to choose the appropriate certificate and will call again
255 * the callback function with the appropriate parameters, and rely
256 * only to the return value of the callback function.
258 * The callback function should return the index of the certificate
259 * choosen by the user. -1 indicates that the user
260 * does not want to use client authentication.
262 * This function returns 0 on success.
264 void gnutls_certificate_client_set_select_func(GNUTLS_STATE state
,
265 certificate_client_select_func
268 state
->gnutls_internals
.client_cert_callback
= func
;
272 * gnutls_certificate_server_set_select_func - Used to set a callback while selecting the proper (server) certificate
273 * @state: is a &GNUTLS_STATE structure.
274 * @func: is the callback function
276 * The callback's function form is:
277 * int (*callback)(GNUTLS_STATE, gnutls_datum *server_cert, int ncerts);
279 * 'server_cert' contains 'ncerts' gnutls_datum structures which hold
280 * the raw certificate (DER encoded in X.509) of the server.
282 * This function specifies what we, in case of a server, are going
283 * to do when we have to send a certificate. If this callback
284 * function is not provided then gnutls will automaticaly try to
285 * find an appropriate certificate to send. (actually send the first in the list)
287 * In case the callback returned a negative number then gnutls will
288 * not attempt to choose the appropriate certificate and the caller function
291 * The callback function will only be called once per handshake.
292 * The callback function should return the index of the certificate
293 * choosen by the server. -1 indicates an error.
296 void gnutls_certificate_server_set_select_func(GNUTLS_STATE state
,
297 certificate_server_select_func
300 state
->gnutls_internals
.server_cert_callback
= func
;
303 /* These are set by the gnutls_extra library's initialization function.
306 OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_extract_key_creation_time
= NULL
;
307 OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_extract_key_expiration_time
= NULL
;
308 OPENPGP_VERIFY_KEY_FUNC _E_gnutls_openpgp_verify_key
= NULL
;
311 * _gnutls_openpgp_cert_verify_peers - This function returns the peer's certificate status
312 * @state: is a gnutls state
314 * This function will try to verify the peer's certificate and return it's status (TRUSTED, INVALID etc.).
315 * Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
318 int _gnutls_openpgp_cert_verify_peers(GNUTLS_STATE state
)
320 CERTIFICATE_AUTH_INFO info
;
321 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
322 CertificateStatus verify
;
323 int peer_certificate_list_size
;
325 CHECK_AUTH(GNUTLS_CRD_CERTIFICATE
, GNUTLS_E_INVALID_REQUEST
);
327 info
= _gnutls_get_auth_info(state
);
329 return GNUTLS_E_INVALID_REQUEST
;
331 cred
= _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
334 return GNUTLS_E_INSUFICIENT_CRED
;
337 if (info
->raw_certificate_list
== NULL
|| info
->ncerts
== 0) {
339 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
342 /* generate a list of gnutls_certs based on the auth info
345 peer_certificate_list_size
= info
->ncerts
;
347 if (peer_certificate_list_size
!= 1) {
349 return GNUTLS_E_UNKNOWN_ERROR
;
352 /* Verify certificate
354 if (_E_gnutls_openpgp_verify_key
==NULL
) {
356 return GNUTLS_E_INVALID_REQUEST
;
358 verify
= _E_gnutls_openpgp_verify_key( cred
->pgp_trustdb
, &cred
->keyring
, &info
->raw_certificate_list
[0],
359 peer_certificate_list_size
);
363 return GNUTLS_CERT_INVALID
;
371 * gnutls_certificate_verify_peers - This function returns the peer's certificate verification status
372 * @state: is a gnutls state
374 * This function will try to verify the peer's certificate and return it's status (TRUSTED, INVALID etc.).
375 * The return value (status) should be one of the CertificateStatus enumerated elements.
376 * However you must also check the peer's name in order to check if the verified certificate belongs to the
379 * The return value (status) should be one or more of the CertificateStatus
380 * enumerated elements bitwise or'd. The return value is the same as
381 * gnutls_x509_verify_certificate().
384 int gnutls_certificate_verify_peers(GNUTLS_STATE state
)
386 CERTIFICATE_AUTH_INFO info
;
388 CHECK_AUTH(GNUTLS_CRD_CERTIFICATE
, GNUTLS_E_INVALID_REQUEST
);
390 info
= _gnutls_get_auth_info(state
);
393 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
396 if (info
->raw_certificate_list
== NULL
|| info
->ncerts
== 0)
397 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
399 switch( gnutls_cert_type_get( state
)) {
400 case GNUTLS_CRT_X509
:
401 return _gnutls_x509_cert_verify_peers( state
);
402 case GNUTLS_CRT_OPENPGP
:
403 return _gnutls_openpgp_cert_verify_peers( state
);
405 return GNUTLS_E_INVALID_REQUEST
;
410 * gnutls_certificate_expiration_time_peers - This function returns the peer's certificate expiration time
411 * @state: is a gnutls state
413 * This function will return the peer's certificate expiration time.
415 * Returns (time_t) -1 on error.
418 time_t gnutls_certificate_expiration_time_peers(GNUTLS_STATE state
)
420 CERTIFICATE_AUTH_INFO info
;
422 CHECK_AUTH(GNUTLS_CRD_CERTIFICATE
, GNUTLS_E_INVALID_REQUEST
);
424 info
= _gnutls_get_auth_info(state
);
430 if (info
->raw_certificate_list
== NULL
|| info
->ncerts
== 0) {
435 switch( gnutls_cert_type_get( state
)) {
436 case GNUTLS_CRT_X509
:
437 return gnutls_x509_extract_certificate_expiration_time(
438 &info
->raw_certificate_list
[0]);
439 case GNUTLS_CRT_OPENPGP
:
440 if (_E_gnutls_openpgp_extract_key_expiration_time
==NULL
)
442 return _E_gnutls_openpgp_extract_key_expiration_time(
443 &info
->raw_certificate_list
[0]);
450 * gnutls_certificate_activation_time_peers - This function returns the peer's certificate activation time
451 * @state: is a gnutls state
453 * This function will return the peer's certificate activation time.
454 * This is the creation time for openpgp keys.
456 * Returns (time_t) -1 on error.
459 time_t gnutls_certificate_activation_time_peers(GNUTLS_STATE state
)
461 CERTIFICATE_AUTH_INFO info
;
463 CHECK_AUTH(GNUTLS_CRD_CERTIFICATE
, GNUTLS_E_INVALID_REQUEST
);
465 info
= _gnutls_get_auth_info(state
);
471 if (info
->raw_certificate_list
== NULL
|| info
->ncerts
== 0) {
476 switch( gnutls_cert_type_get( state
)) {
477 case GNUTLS_CRT_X509
:
478 return gnutls_x509_extract_certificate_activation_time(
479 &info
->raw_certificate_list
[0]);
480 case GNUTLS_CRT_OPENPGP
:
481 if (_E_gnutls_openpgp_extract_key_creation_time
==NULL
)
483 return _E_gnutls_openpgp_extract_key_creation_time(
484 &info
->raw_certificate_list
[0]);