summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-12-09 10:50:57 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-12-09 10:50:57 +0000
commita83a82623599e77b9df86a497fee69896b4dabfe (patch)
treeb3ba164011af142a120dc02855443bce14af6c4e
parent745b110197d9a1af0354a5607bdbe49eda4012a7 (diff)
downloadgnutls-a83a82623599e77b9df86a497fee69896b4dabfe.tar.gz
Optimizations in server certificate callback.
-rw-r--r--NEWS1
-rw-r--r--lib/auth_x509.c39
-rw-r--r--lib/auth_x509.h4
-rw-r--r--lib/gnutls_cert.c1
-rw-r--r--lib/gnutls_errors_int.h21
-rw-r--r--lib/gnutls_handshake.c28
-rw-r--r--lib/gnutls_int.h4
7 files changed, 63 insertions, 35 deletions
diff --git a/NEWS b/NEWS
index 32a825e339..374221912c 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Version ?.?.?
- Fixes in MPI handling (fixes possible with signed integers)
- Removed name indication extension
- Added gnutls_transport_get_ptr() and gnutls_db_get_ptr()
+- Optimizations in server certificate callback.
Version 0.2.90 (7/12/2001)
- gnutls_handshake(), gnutls_read() etc. functions no longer require
diff --git a/lib/auth_x509.c b/lib/auth_x509.c
index b2de54efc9..05a225c9a6 100644
--- a/lib/auth_x509.c
+++ b/lib/auth_x509.c
@@ -104,7 +104,8 @@ static int _gnutls_get_private_rsa_params(GNUTLS_KEY key,
return 0;
}
-/* Returns the issuer's Distinguished name in odn, of the certificate specified in cert.
+/* Returns the issuer's Distinguished name in odn, of the certificate
+ * specified in cert.
*/
int _gnutls_find_dn(gnutls_datum * odn, gnutls_cert * cert)
{
@@ -874,13 +875,9 @@ int _gnutls_find_apr_cert(GNUTLS_STATE state, gnutls_cert ** apr_cert_list,
gnutls_assert(); /* this is not allowed */
return GNUTLS_E_INSUFICIENT_CRED;
} else {
-
- ind =
- _gnutls_server_find_cert_list_index(state,
- cred->
- cert_list,
- cred->
- ncerts);
+ /* find_cert_list_index() has been called before.
+ */
+ ind = state->gnutls_internals.selected_cert_index;
if (ind < 0) {
*apr_cert_list = NULL;
@@ -1285,30 +1282,38 @@ int gnutls_x509pki_get_peer_certificate_status(GNUTLS_STATE state)
* The 'appropriate' is defined by the user.
* (frontend to _gnutls_server_find_cert_index())
*/
-const gnutls_cert *_gnutls_server_find_cert(GNUTLS_STATE state,
- gnutls_cert ** cert_list,
- int cert_list_length)
+const gnutls_cert *_gnutls_server_find_x509_cert(GNUTLS_STATE state)
{
int i;
+ const X509PKI_CREDENTIALS x509_cred;
+
+ x509_cred =
+ _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
+
+ if (x509_cred==NULL)
+ return NULL;
+
+ i = _gnutls_server_find_x509_cert_list_index(state, x509_cred->cert_list,
+ x509_cred->ncerts);
- i = _gnutls_server_find_cert_list_index(state, cert_list,
- cert_list_length);
if (i < 0)
return NULL;
- return &cert_list[i][0];
+ return &x509_cred->cert_list[i][0];
}
/* finds the most appropriate certificate in the cert list.
* The 'appropriate' is defined by the user.
*/
-int _gnutls_server_find_cert_list_index(GNUTLS_STATE state,
+int _gnutls_server_find_x509_cert_list_index(GNUTLS_STATE state,
gnutls_cert ** cert_list,
int cert_list_length)
{
int i, index = -1;
const X509PKI_CREDENTIALS cred;
+ state->gnutls_internals.selected_cert_index = 0;
+
cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
if (cred == NULL) {
gnutls_assert();
@@ -1339,5 +1344,9 @@ int _gnutls_server_find_cert_list_index(GNUTLS_STATE state,
gnutls_free(my_certs);
}
+ /* store the index for future use, in the handshake.
+ * (This will allow not calling this callback again.)
+ */
+ state->gnutls_internals.selected_cert_index = index;
return index;
}
diff --git a/lib/auth_x509.h b/lib/auth_x509.h
index 422f5ff35b..cd67750627 100644
--- a/lib/auth_x509.h
+++ b/lib/auth_x509.h
@@ -63,8 +63,8 @@ int _gnutls_proc_x509_client_cert_vrfy(GNUTLS_STATE, opaque *, int);
int _gnutls_proc_x509_server_certificate(GNUTLS_STATE, opaque *, int);
int _gnutls_find_apr_cert( GNUTLS_STATE state, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_private_key** apr_pkey);
int _gnutls_find_dn( gnutls_datum* odn, gnutls_cert* cert);
-const gnutls_cert* _gnutls_server_find_cert( struct GNUTLS_STATE_INT*, gnutls_cert** cert_list, int cert_list_length);
-int _gnutls_server_find_cert_list_index( struct GNUTLS_STATE_INT*, gnutls_cert ** cert_list, int cert_list_length);
+const gnutls_cert* _gnutls_server_find_x509_cert( struct GNUTLS_STATE_INT*);
+int _gnutls_server_find_x509_cert_list_index( struct GNUTLS_STATE_INT*, gnutls_cert ** cert_list, int cert_list_length);
#define _gnutls_proc_x509_client_certificate _gnutls_proc_x509_server_certificate
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 2f721813ac..d11f1a15ba 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -1110,6 +1110,7 @@ void gnutls_x509pki_set_client_cert_callback(GNUTLS_STATE state,
* not attempt to choose the appropriate certificate and the caller function
* will fail.
*
+ * The callback function will only be called once per handshake.
* The callback function should return the index of the certificate
* choosen by the server (or -1 in case of an error)
*
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index ee9ea32697..4f3c73bf2b 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -1,8 +1,9 @@
-/* error codes
+/* Gnutls error codes. The mapping to a TLS alert is also shown in
+ * comments.
*/
#define GNUTLS_E_SUCCESS 0
-#define GNUTLS_E_MAC_FAILED -1 /* GNUTLS_BAD_RECORD_MAC */
+#define GNUTLS_E_MAC_FAILED -1 /* GNUTLS_A_BAD_RECORD_MAC */
#define GNUTLS_E_UNKNOWN_CIPHER -2
#define GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM -3
#define GNUTLS_E_UNKNOWN_MAC_ALGORITHM -4
@@ -16,17 +17,17 @@
#define GNUTLS_E_FATAL_ALERT_RECEIVED -12
#define GNUTLS_E_RECEIVED_BAD_MESSAGE -13
#define GNUTLS_E_RECEIVED_MORE_DATA -14
-#define GNUTLS_E_UNEXPECTED_PACKET -15 /* GNUTLS_UNEXPECTED_MESSAGE */
+#define GNUTLS_E_UNEXPECTED_PACKET -15 /* GNUTLS_A_UNEXPECTED_MESSAGE */
#define GNUTLS_E_WARNING_ALERT_RECEIVED -16
#define GNUTLS_E_ERROR_IN_FINISHED_PACKET -18
#define GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET -19
#define GNUTLS_E_UNKNOWN_KX_ALGORITHM -20
-#define GNUTLS_E_UNKNOWN_CIPHER_SUITE -21 /* GNUTLS_HANDSHAKE_FAILURE */
+#define GNUTLS_E_UNKNOWN_CIPHER_SUITE -21 /* GNUTLS_A_HANDSHAKE_FAILURE */
#define GNUTLS_E_UNWANTED_ALGORITHM -22
#define GNUTLS_E_MPI_SCAN_FAILED -23
-#define GNUTLS_E_DECRYPTION_FAILED -24 /* GNUTLS_DECRYPTION_FAILED */
+#define GNUTLS_E_DECRYPTION_FAILED -24 /* GNUTLS_A_DECRYPTION_FAILED */
#define GNUTLS_E_MEMORY_ERROR -25
-#define GNUTLS_E_DECOMPRESSION_FAILED -26 /* GNUTLS_DECOMPRESSION_FAILURE */
+#define GNUTLS_E_DECOMPRESSION_FAILED -26 /* GNUTLS_A_DECOMPRESSION_FAILURE */
#define GNUTLS_E_COMPRESSION_FAILED -27
#define GNUTLS_E_AGAIN -28
#define GNUTLS_E_EXPIRED -29
@@ -36,25 +37,25 @@
#define GNUTLS_E_HASH_FAILED -33
#define GNUTLS_E_PARSING_ERROR -34
#define GNUTLS_E_MPI_PRINT_FAILED -35
-#define GNUTLS_E_REHANDSHAKE -37 /* GNUTLS_NO_RENEGOTIATION */
+#define GNUTLS_E_REHANDSHAKE -37 /* GNUTLS_A_NO_RENEGOTIATION */
#define GNUTLS_E_GOT_APPLICATION_DATA -38
#define GNUTLS_E_RECORD_LIMIT_REACHED -39
#define GNUTLS_E_ENCRYPTION_FAILED -40
#define GNUTLS_E_ASN1_ERROR -41
-#define GNUTLS_E_ASN1_PARSING_ERROR -42 /* GNUTLS_BAD_CERTIFICATE */
+#define GNUTLS_E_ASN1_PARSING_ERROR -42 /* GNUTLS_A_BAD_CERTIFICATE */
#define GNUTLS_E_X509_CERTIFICATE_ERROR -43
#define GNUTLS_E_PK_ENCRYPTION_FAILED -44
#define GNUTLS_E_PK_DECRYPTION_FAILED -45
#define GNUTLS_E_PK_SIGNATURE_FAILED -46
#define GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION -47
#define GNUTLS_E_X509_KEY_USAGE_VIOLATION -48
-#define GNUTLS_E_NO_CERTIFICATE_FOUND -49 /* GNUTLS_BAD_CERTIFICATE */
+#define GNUTLS_E_NO_CERTIFICATE_FOUND -49 /* GNUTLS_A_BAD_CERTIFICATE */
#define GNUTLS_E_INVALID_PARAMETERS -50
#define GNUTLS_E_INVALID_REQUEST -51
#define GNUTLS_E_INTERRUPTED -52
#define GNUTLS_E_PUSH_ERROR -53
#define GNUTLS_E_PULL_ERROR -54
-#define GNUTLS_E_ILLEGAL_PARAMETER -55 /* GNUTLS_ILLEGAL_PARAMETER */
+#define GNUTLS_E_ILLEGAL_PARAMETER -55 /* GNUTLS_A_ILLEGAL_PARAMETER */
#define GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE -56
#define GNUTLS_E_PKCS1_WRONG_PAD -57
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 931633222e..ce195e3367 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -1894,8 +1894,7 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state,
cert = NULL;
cert =
- _gnutls_server_find_cert(state, x509_cred->cert_list,
- x509_cred->ncerts);
+ _gnutls_server_find_x509_cert(state);
if (cert == NULL) {
/* No certificate was found
@@ -1918,29 +1917,42 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state,
gnutls_malloc(numCipherSuites * sizeof(GNUTLS_CipherSuite));
if (newSuite==NULL) {
gnutls_assert();
+ gnutls_free(alg);
return GNUTLS_E_MEMORY_ERROR;
}
for (i = 0; i < numCipherSuites; i++) {
+ /* finds the key exchange algorithm in
+ * the ciphersuite
+ */
kx = _gnutls_cipher_suite_get_kx_algo((*cipherSuites)[i]);
keep = 0;
+
+ /* If there was no credentials to use with the specified
+ * key exchange method, then just remove it.
+ */
if (_gnutls_map_kx_get_cred(kx) == GNUTLS_X509PKI) {
keep = 1; /* do not keep */
if (x509_cred != NULL)
+ /* here we check if the KX algorithm
+ * is compatible with the X.509 certificate.
+ */
for (j = 0; j < alg_size; j++) {
if (alg[j] == kx) {
keep = 0;
break;
}
}
- } else
- /* if it is defined but had no credentials
- */
- if (_gnutls_get_kx_cred(state->gnutls_key, kx, NULL) ==
- NULL)
- keep = 1;
+ } else {
+ /* if it is defined but had no credentials
+ */
+
+ if (_gnutls_get_kx_cred(state->gnutls_key, kx, NULL) == NULL)
+ keep = 1;
+ }
+
if (keep == 0) {
memcpy(newSuite[newSuiteSize].CipherSuite,
(*cipherSuites)[i].CipherSuite, 2);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index dd271e9f13..d7e200d043 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -481,6 +481,10 @@ typedef struct {
* user.
*/
uint16 proposed_record_size;
+
+ /* holds the index of the selected certificate.
+ */
+ int selected_cert_index;
} GNUTLS_INTERNALS;
struct GNUTLS_STATE_INT {