gnutls_sdatum plaintext;
gnutls_datum ciphertext;
int ret, dsize;
- MPI params[2];
+ MPI params[RSA_PARAMS];
if ( gnutls_protocol_get_version(state) == GNUTLS_SSL3) {
/* SSL 3.0 */
params[0] = state->gnutls_key->A;
params[1] = state->gnutls_key->u;
ret =
- _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, params, 2); /* btype==2 */
+ _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, params, 2); /* btype==2 */
if (ret < 0) {
/* in case decryption fails then don't inform
gnutls_assert();
- _gnutls_log( "RSA_auth: Possible PKCS-1 format attack\n");
+ _gnutls_log( "RSA_AUTH: Possible PKCS-1 format attack\n");
RANDOMIZE_KEY(state->gnutls_key->key, gnutls_secure_malloc);
} else {
* The 'appropriate' is defined by the user.
* (frontend to _gnutls_server_find_cert_index())
*/
-const gnutls_cert *_gnutls_server_find_x509_cert(GNUTLS_STATE state)
+const gnutls_cert *_gnutls_server_find_x509_cert(GNUTLS_STATE state, PKAlgorithm requested_algo)
{
int i;
const GNUTLS_X509PKI_CREDENTIALS x509_cred;
return NULL;
i = _gnutls_server_find_x509_cert_list_index(state, x509_cred->cert_list,
- x509_cred->ncerts);
+ x509_cred->ncerts, requested_algo);
if (i < 0)
return NULL;
/* finds the most appropriate certificate in the cert list.
* The 'appropriate' is defined by the user.
+ *
+ * requested_algo holds the parameters required by the peer (RSA, DSA
+ * or -1 for any).
*/
int _gnutls_server_find_x509_cert_list_index(GNUTLS_STATE state,
gnutls_cert ** cert_list,
- int cert_list_length)
+ int cert_list_length,
+ PKAlgorithm requested_algo)
{
- int i, index = -1;
+ int i, index = -1, j;
const GNUTLS_X509PKI_CREDENTIALS cred;
-
- state->gnutls_internals.selected_cert_index = 0;
+ int my_certs_length;
cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
if (cred == NULL) {
return GNUTLS_E_INSUFICIENT_CRED;
}
- if (cred->ncerts > 0)
+ if (cred->ncerts > 0) {
+ state->gnutls_internals.selected_cert_index = 0;
index = 0; /* default is use the first certificate */
+ /* find one compatible certificate */
+ if (requested_algo>0) {
+ for (i = 0; i < cred->ncerts; i++) {
+ if (requested_algo==cred->cert_list[i][0].subject_pk_algorithm) {
+ state->gnutls_internals.selected_cert_index = i;
+ index = i;
+ }
+ }
+ }
+ }
+
if (state->gnutls_internals.client_cert_callback != NULL && cred->ncerts > 0) { /* use the callback to get certificate */
gnutls_datum *my_certs = NULL;
gnutls_malloc(cred->ncerts * sizeof(gnutls_datum));
if (my_certs == NULL)
goto clear;
+ my_certs_length = cred->ncerts;
/* put our certificate's issuer and dn into cdn, idn
*/
- for (i = 0; i < cred->ncerts; i++) {
- my_certs[i] = cred->cert_list[i][0].raw;
+ j=0;
+ for (i = 0; i < cred->ncerts; i++,j++) {
+ /* Does not add incompatible certificates */
+ if (requested_algo>0) {
+ if (requested_algo!=cred->cert_list[i][0].subject_pk_algorithm) {
+ my_certs_length--;
+ j--;
+ continue;
+ }
+ }
+ my_certs[j] = cred->cert_list[i][0].raw;
}
index =
state->gnutls_internals.server_cert_callback(state, my_certs,
- cred->ncerts);
+ my_certs_length);
clear:
gnutls_free(my_certs);
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_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);
+const gnutls_cert* _gnutls_server_find_x509_cert( struct GNUTLS_STATE_INT*, PKAlgorithm);
+int _gnutls_server_find_x509_cert_list_index( struct GNUTLS_STATE_INT*, gnutls_cert ** cert_list, int cert_list_length, PKAlgorithm);
#define _gnutls_proc_x509_client_certificate _gnutls_proc_x509_server_certificate
#define TRUE 1
#define FALSE 0
-static int _gnutls_server_select_suite(GNUTLS_STATE state, opaque *data, int datalen);
int _gnutls_server_select_comp_method(GNUTLS_STATE state,
opaque * data, int datalen);
return ret;
}
+/* returns PK_RSA if the given cipher suite list only supports,
+ * RSA algorithms, PK_DSA if DSS, and -1 if both or none.
+ */
+int _gnutls_find_pk_algos_in_ciphersuites( opaque* data, int datalen) {
+int j;
+PKAlgorithm algo=-1, prev_algo = 0;
+KXAlgorithm kx;
+
+ for (j = 0; j < datalen; j += 2) {
+ kx = _gnutls_cipher_suite_get_kx_algo(*((GNUTLS_CipherSuite *) & data[j]));
+
+ if ( _gnutls_map_kx_get_cred( kx) == GNUTLS_X509PKI) {
+ algo = _gnutls_map_pk_get_pk( kx);
+
+ if (algo!=prev_algo && prev_algo!=0) return -1;
+ prev_algo = algo;
+ }
+ }
+
+ return algo;
+}
/* This selects the best supported ciphersuite from the ones supported. Then
* it adds the suite into the state and performs some checks.
*/
-static int _gnutls_server_select_suite(GNUTLS_STATE state, opaque *data, int datalen)
+int _gnutls_server_select_suite(GNUTLS_STATE state, opaque *data, int datalen)
{
int x, i, j;
GNUTLS_CipherSuite *ciphers;
int retval, err;
+ PKAlgorithm pk_algo; /* will hold the pk algorithms
+ * supported by the peer.
+ */
+
+ pk_algo = _gnutls_find_pk_algos_in_ciphersuites( data, datalen);
x = _gnutls_supported_ciphersuites(state, &ciphers);
* the certificate requested, or to the
* authentication requested (eg SRP).
*/
- x = _gnutls_remove_unwanted_ciphersuites(state, &ciphers, x);
+ x = _gnutls_remove_unwanted_ciphersuites(state, &ciphers, x, pk_algo);
#ifdef HANDSHAKE_DEBUG
_gnutls_handshake_log("HSK: Requested cipher suites: \n");
}
/* This function copies the appropriate ciphersuites, to a localy allocated buffer
- * Needed in hello messages. Returns the new data length.
+ * Needed in client hello messages. Returns the new data length.
*/
static int _gnutls_copy_ciphersuites(GNUTLS_STATE state,
opaque ** ret_data)
*/
ret =
_gnutls_remove_unwanted_ciphersuites(state, &cipher_suites,
- ret);
+ ret, -1);
if (ret < 0) {
gnutls_assert();
return ret;
*/
int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state,
GNUTLS_CipherSuite **
- cipherSuites, int numCipherSuites)
+ cipherSuites, int numCipherSuites,
+ PKAlgorithm requested_pk_algo)
{
int ret = 0;
cert = NULL;
if (state->security_parameters.entity == GNUTLS_SERVER)
- cert = _gnutls_server_find_x509_cert(state);
+ cert = _gnutls_server_find_x509_cert(state, requested_pk_algo);
if (cert == NULL) {
/* No certificate was found
return GNUTLS_E_MEMORY_ERROR;
}
+ /* now removes ciphersuites based on the KX algorithm
+ */
for (i = 0; i < numCipherSuites; i++) {
/* finds the key exchange algorithm in
* the ciphersuite
void _gnutls_set_server_random( GNUTLS_STATE state, uint8* random);
void _gnutls_set_client_random( GNUTLS_STATE state, uint8* random);
int _gnutls_create_random( opaque* dst);
-int _gnutls_remove_unwanted_ciphersuites( GNUTLS_STATE state, GNUTLS_CipherSuite ** cipherSuites, int numCipherSuites);
+int _gnutls_remove_unwanted_ciphersuites( GNUTLS_STATE state, GNUTLS_CipherSuite ** cipherSuites, int numCipherSuites, PKAlgorithm);
void gnutls_handshake_set_max_packet_length( GNUTLS_STATE state, int max);
+int _gnutls_find_pk_algos_in_ciphersuites( opaque* data, int datalen);
+int _gnutls_server_select_suite(GNUTLS_STATE state, opaque *data, int datalen);
#define STATE state->gnutls_internals.handshake_state
/* This returns true if we have got there
#include "gnutls_random.h"
#include "gnutls_auth_int.h"
-int _gnutls_SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, opaque * data, int datalen);
-
/* This selects the best supported ciphersuite from the ones provided */
-static int SelectSuite_v2(GNUTLS_STATE state, opaque ret[2], char *data,
- int datalen)
+static int _gnutls_handshake_select_v2_suite(GNUTLS_STATE state, char *data, int datalen)
{
- int x, i, j;
- GNUTLS_CipherSuite *ciphers;
-
- x = _gnutls_supported_ciphersuites(state, &ciphers);
- x = _gnutls_remove_unwanted_ciphersuites( state, &ciphers, x);
-
-#ifdef HANDSHAKE_DEBUG
- _gnutls_handshake_log( "HSK: Requested cipher suites [v2 hello]: \n");
- for (j = 0; j < datalen; j += 3) {
- if (data[j] == 0) { /* only print if in v2 compat mode */
- _gnutls_handshake_log( "\t%s\n",
- _gnutls_cipher_suite_get_name(*
- ((GNUTLS_CipherSuite *) & data[j+1])));
- }
+ int i, j, ret;
+ char* _data;
+ int _datalen;
+
+ _data = gnutls_malloc( datalen);
+ if (_data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
}
- _gnutls_handshake_log( "HSK: Supported cipher suites: \n");
- for (j = 0; j < x; j++)
- _gnutls_handshake_log( "\t%s\n",
- _gnutls_cipher_suite_get_name(ciphers[j]));
-#endif
- memset(ret, '\0', 2);
+ _gnutls_handshake_log( "HSK: Parsing a version 2.0 client hello.\n");
+
+ i = _datalen = 0;
for (j = 0; j < datalen; j += 3) {
- for (i = 0; i < x; i++) {
- if (data[j] == 0)
- if ( memcmp(ciphers[i].CipherSuite, &data[j+1],
- 2) == 0) {
-
- _gnutls_handshake_log(
- "HSK: Selected cipher suite: ");
- _gnutls_handshake_log( "%s\n",
- _gnutls_cipher_suite_get_name
- (*
- ((GNUTLS_CipherSuite *) &
- data[j+1])));
-
- memcpy(ret,
- ciphers[i].CipherSuite,
- 2);
- gnutls_free(ciphers);
-
- return 0;
- }
+ if (data[j] == 0) {
+ memcpy( &_data[i], &data[j+1], 2);
+ i+=2;
+ _datalen+=2;
}
}
+ ret = _gnutls_server_select_suite( state, _data, _datalen);
+ gnutls_free(_data);
- gnutls_free(ciphers);
- gnutls_assert();
- return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
+ return ret;
}
DECR_LEN(len, 2);
- _gnutls_handshake_log( "HSK: V2 Hello: Client's version: %d.%d\n", data[pos],
+ _gnutls_handshake_log( "HSK: SSL 2.0 Hello: Client's version: %d.%d\n", data[pos],
data[pos + 1]);
set_adv_version( state, data[pos], data[pos+1]);
/* find an appropriate cipher suite */
DECR_LEN(len, sizeOfSuites);
- ret = SelectSuite_v2(state, state->security_parameters.
- current_cipher_suite.CipherSuite,
- &data[pos], sizeOfSuites);
+ ret = _gnutls_handshake_select_v2_suite(state, &data[pos], sizeOfSuites);
pos += sizeOfSuites;
if (ret < 0) {
if (state->gnutls_internals.auth_struct == NULL) {
_gnutls_handshake_log(
- "HSK: V2 Hello: Cannot find the appropriate handler for the KX algorithm\n");
+ "HSK: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n");
gnutls_assert();
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;