/* Initializes the write connection session * (write encrypted data) */ int _gnutls_write_connection_state_init(gnutls_session_t session) { const uint16_t epoch_next = session->security_parameters.epoch_next; int ret; /* Update internals from CipherSuite selected. * If we are resuming just copy the connection session */ if (session->internals.resumed == RESUME_FALSE) { ret = _gnutls_set_kx(session, _gnutls_cipher_suite_get_kx_algo (session->security_parameters. cipher_suite)); if (ret < 0) return ret; } else if (session->security_parameters.entity == GNUTLS_SERVER) _gnutls_set_resumed_parameters(session); ret = _gnutls_epoch_set_keys(session, epoch_next); if (ret < 0) return gnutls_assert_val(ret); _gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n", session, _gnutls_cipher_suite_get_name (session->security_parameters.cipher_suite)); _gnutls_handshake_log ("HSK[%p]: Initializing internal [write] cipher sessions\n", session); session->security_parameters.epoch_write = epoch_next; return 0; }
/** * gnutls_auth_client_get_type: * @session: is a #gnutls_session_t structure. * * Returns the type of credentials that were used for client authentication. * The returned information is to be used to distinguish the function used * to access authentication data. * * Returns: The type of credentials for the client authentication * schema, a #gnutls_credentials_type_t type. **/ gnutls_credentials_type_t gnutls_auth_client_get_type(gnutls_session_t session) { return _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo (session->security_parameters. cipher_suite), 0); }
/* This function reads the RSA parameters from the private key */ static int _gnutls_get_private_rsa_params (gnutls_session_t session, bigint_t ** params, int *params_size) { int bits; gnutls_certificate_credentials_t cred; gnutls_rsa_params_t rsa_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.selected_cert_list == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } bits = _gnutls_mpi_get_nbits (session->internals.selected_cert_list[0]. params[0]); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) == GNUTLS_KX_RSA_EXPORT && bits > 512) { rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); /* EXPORT case: */ if (rsa_params == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } /* In the export case, we do use temporary RSA params * of 512 bits size. The params in the certificate are * used to sign this temporary stuff. */ *params_size = RSA_PRIVATE_PARAMS; *params = rsa_params->params; return 0; } /* non export cipher suites. */ *params_size = session->internals.selected_key->params_size; *params = session->internals.selected_key->params; return 0; }
/** * gnutls_kx_get: * @session: is a #gnutls_session_t type. * * Get currently used key exchange algorithm. * * Returns: the key exchange algorithm used in the last handshake, a * #gnutls_kx_algorithm_t value. **/ gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session) { if (session->internals.handshake_in_progress) { /* This allows early call during handshake */ return _gnutls_cipher_suite_get_kx_algo(session->security_parameters.cipher_suite); } else { return session->security_parameters.kx_algorithm; } }
int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session, gnutls_buffer_st * data, gnutls_datum_t * pskkey) { int ret; gnutls_pk_params_st peer_pub; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_init(&peer_pub); ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, &session->key.dh_params, 1); if (ret < 0) return gnutls_assert_val(ret); _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X])); ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0); if (ret < 0) { gnutls_assert(); goto error; } peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_DHE_PSK) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, pskkey, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = data->length; error: gnutls_pk_params_clear(&session->key.dh_params); return ret; }
/** * gnutls_auth_get_type: * @session: is a #gnutls_session_t structure. * * Returns type of credentials for the current authentication schema. * The returned information is to be used to distinguish the function used * to access authentication data. * * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: * %GNUTLS_KX_RSA, %GNUTLS_KX_DHE_RSA), the same function are to be * used to access the authentication data. * * Returns: The type of credentials for the current authentication * schema, a #gnutls_credentials_type_t type. **/ gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session) { /* This is not the credentials we must set, but the authentication data * we get by the peer, so it should be reversed. */ int server = session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1; return _gnutls_map_kx_get_cred(_gnutls_cipher_suite_get_kx_algo (session->security_parameters. cipher_suite), server); }
/* This function reads the RSA parameters from the private key */ static int _gnutls_get_private_rsa_params (gnutls_session_t session, gnutls_pk_params_st** params) { int ret; gnutls_certificate_credentials_t cred; gnutls_rsa_params_t rsa_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.selected_cert_list == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = _gnutls_pubkey_is_over_rsa_512(session->internals.selected_cert_list[0].pubkey); if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_RSA_EXPORT || ret < 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); /* EXPORT case: */ if (rsa_params == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } /* In the export case, we do use temporary RSA params * of 512 bits size. The params in the certificate are * used to sign this temporary stuff. */ *params = &rsa_params->params; return 0; }
/* Initializes the read connection session * (read encrypted data) */ int _gnutls_read_connection_state_init (gnutls_session_t session) { const uint16_t epoch_next = session->security_parameters.epoch_next; int ret; /* Update internals from CipherSuite selected. * If we are resuming just copy the connection session */ if (session->internals.resumed == RESUME_FALSE) { ret = _gnutls_check_algos (session, &session-> security_parameters.current_cipher_suite, _gnutls_epoch_get_compression(session, epoch_next)); if (ret < 0) return ret; ret = _gnutls_set_kx (session, _gnutls_cipher_suite_get_kx_algo (&session-> security_parameters.current_cipher_suite)); if (ret < 0) return ret; } else if (session->security_parameters.entity == GNUTLS_CLIENT) _gnutls_set_resumed_parameters (session); ret = _gnutls_epoch_set_keys (session, epoch_next); if (ret < 0) return ret; _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session, _gnutls_cipher_suite_get_name (&session-> security_parameters.current_cipher_suite)); session->security_parameters.epoch_read = epoch_next; return 0; }
/* Read a v2 client hello. Some browsers still use that beast! * However they set their version to 3.0 or 3.1. */ int _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data, unsigned int datalen) { uint16_t session_id_len = 0; int pos = 0; int ret = 0, sret = 0; uint16_t sizeOfSuites; gnutls_protocol_t adv_version; uint8_t rnd[GNUTLS_RANDOM_SIZE]; int len = datalen; uint16_t challenge; uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE]; DECR_LEN(len, 2); _gnutls_handshake_log ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session, data[pos], data[pos + 1]); set_adv_version(session, data[pos], data[pos + 1]); adv_version = _gnutls_version_get(data[pos], data[pos + 1]); ret = _gnutls_negotiate_version(session, adv_version); if (ret < 0) { gnutls_assert(); return ret; } pos += 2; /* Read uint16_t cipher_spec_length */ DECR_LEN(len, 2); sizeOfSuites = _gnutls_read_uint16(&data[pos]); pos += 2; /* read session id length */ DECR_LEN(len, 2); session_id_len = _gnutls_read_uint16(&data[pos]); pos += 2; if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } /* read challenge length */ DECR_LEN(len, 2); challenge = _gnutls_read_uint16(&data[pos]); pos += 2; if (challenge < 16 || challenge > GNUTLS_RANDOM_SIZE) { gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } /* call the user hello callback */ ret = _gnutls_user_hello_func(session, adv_version); if (ret < 0) { if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) { sret = GNUTLS_E_INT_RET_0; } else { gnutls_assert(); return ret; } } /* find an appropriate cipher suite */ DECR_LEN(len, sizeOfSuites); ret = _gnutls_handshake_select_v2_suite(session, &data[pos], sizeOfSuites); pos += sizeOfSuites; if (ret < 0) { gnutls_assert(); return ret; } /* check if the credentials (username, public key etc.) are ok */ if (_gnutls_get_kx_cred (session, _gnutls_cipher_suite_get_kx_algo(session->security_parameters. cipher_suite)) == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* set the mod_auth_st to the appropriate struct * according to the KX algorithm. This is needed since all the * handshake functions are read from there; */ session->internals.auth_struct = _gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo (session->security_parameters. cipher_suite)); if (session->internals.auth_struct == NULL) { _gnutls_handshake_log ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n", session); gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } /* read random new values -skip session id for now */ DECR_LEN(len, session_id_len); /* skip session id for now */ memcpy(session_id, &data[pos], session_id_len); pos += session_id_len; DECR_LEN(len, challenge); memset(rnd, 0, GNUTLS_RANDOM_SIZE); memcpy(&rnd[GNUTLS_RANDOM_SIZE - challenge], &data[pos], challenge); ret = _gnutls_set_client_random(session, rnd); if (ret < 0) return gnutls_assert_val(ret); /* generate server random value */ ret = _gnutls_set_server_random(session, NULL); if (ret < 0) return gnutls_assert_val(ret); session->security_parameters.timestamp = gnutls_time(NULL); /* RESUME SESSION */ DECR_LEN(len, session_id_len); ret = _gnutls_server_restore_session(session, session_id, session_id_len); if (ret == 0) { /* resumed! */ /* get the new random values */ memcpy(session->internals.resumed_security_parameters. server_random, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy(session->internals.resumed_security_parameters. client_random, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); session->internals.resumed = RESUME_TRUE; return 0; } else { _gnutls_generate_session_id(session->security_parameters. session_id, &session->security_parameters. session_id_size); session->internals.resumed = RESUME_FALSE; } _gnutls_epoch_set_compression(session, EPOCH_NEXT, GNUTLS_COMP_NULL); session->security_parameters.compression_method = GNUTLS_COMP_NULL; return sret; }
int _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session, gnutls_buffer_st* data, gnutls_datum_t* pskkey) { bigint_t x = NULL, X = NULL; int ret; ret = gnutls_calc_dh_secret (&X, &x, session->key.client_g, session->key.client_p, 0); if (ret < 0) { gnutls_assert (); goto error; } _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x)); ret = _gnutls_buffer_append_mpi( data, 16, X, 0); if (ret < 0) { gnutls_assert(); goto error; } /* calculate the key after calculating the message */ ret = gnutls_calc_dh_key (&session->key.KEY, session->key.client_Y, x, session->key.client_p); if (ret < 0) { gnutls_assert(); goto error; } /* THESE SHOULD BE DISCARDED */ _gnutls_mpi_release (&session->key.client_Y); _gnutls_mpi_release (&session->key.client_p); _gnutls_mpi_release (&session->key.client_g); if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_DHE_PSK) { ret = _gnutls_mpi_dprint (session->key.KEY, &session->key.key); } else /* In DHE_PSK the key is set differently */ { gnutls_datum_t tmp_dh_key; ret = _gnutls_mpi_dprint (session->key.KEY, &tmp_dh_key); if (ret < 0) { gnutls_assert (); goto error; } ret = _gnutls_set_psk_session_key (session, pskkey, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } _gnutls_mpi_release (&session->key.KEY); if (ret < 0) { gnutls_assert (); goto error; } ret = data->length; error: _gnutls_mpi_release (&x); _gnutls_mpi_release (&X); return ret; }
int _gnutls_proc_dh_common_client_kx (gnutls_session_t session, opaque * data, size_t _data_size, mpi_t g, mpi_t p) { uint16_t n_Y; size_t _n_Y; int ret; ssize_t data_size = _data_size; DECR_LEN (data_size, 2); n_Y = _gnutls_read_uint16 (&data[0]); _n_Y = n_Y; DECR_LEN (data_size, n_Y); if (_gnutls_mpi_scan_nz (&session->key->client_Y, &data[2], &_n_Y)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_dh_set_peer_public (session, session->key->client_Y); session->key->KEY = gnutls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p); if (session->key->KEY == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_release (&session->key->client_Y); _gnutls_mpi_release (&session->key->dh_secret); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) != GNUTLS_KX_DHE_PSK) { ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); } else /* In DHE_PSK the key is set differently */ { gnutls_datum tmp_dh_key; ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_set_psk_session_key (session, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } _gnutls_mpi_release (&session->key->KEY); if (ret < 0) { return ret; } return 0; }
int _gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque ** data) { mpi_t x = NULL, X = NULL; size_t n_X; int ret; *data = NULL; X = gnutls_calc_dh_secret (&x, session->key->client_g, session->key->client_p); if (X == NULL || x == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x)); _gnutls_mpi_print (NULL, &n_X, X); (*data) = gnutls_malloc (n_X + 2); if (*data == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_mpi_print (&(*data)[2], &n_X, X); _gnutls_mpi_release (&X); _gnutls_write_uint16 (n_X, &(*data)[0]); /* calculate the key after calculating the message */ session->key->KEY = gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p); _gnutls_mpi_release (&x); if (session->key->KEY == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_dh_set_peer_public (session, session->key->client_Y); /* THESE SHOULD BE DISCARDED */ _gnutls_mpi_release (&session->key->client_Y); _gnutls_mpi_release (&session->key->client_p); _gnutls_mpi_release (&session->key->client_g); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) != GNUTLS_KX_DHE_PSK) { ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); } else /* In DHE_PSK the key is set differently */ { gnutls_datum tmp_dh_key; ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY); if (ret < 0) { gnutls_assert (); goto error; } ret = _gnutls_set_psk_session_key (session, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } _gnutls_mpi_release (&session->key->KEY); if (ret < 0) { gnutls_assert (); goto error; } return n_X + 2; error: _gnutls_mpi_release (&x); _gnutls_mpi_release (&X); gnutls_free (*data); *data = NULL; return ret; }
/* Initializes the write connection session * (write encrypted data) */ int _gnutls_write_connection_state_init (gnutls_session_t session) { int mac_size; int rc; _gnutls_uint64zero (session->connection_state.write_sequence_number); /* Update internals from CipherSuite selected. * If we are resuming just copy the connection session */ if (session->internals.resumed == RESUME_FALSE) { rc = _gnutls_set_write_cipher (session, _gnutls_cipher_suite_get_cipher_algo (&session->security_parameters. current_cipher_suite)); if (rc < 0) return rc; rc = _gnutls_set_write_mac (session, _gnutls_cipher_suite_get_mac_algo (&session->security_parameters. current_cipher_suite)); if (rc < 0) return rc; rc = _gnutls_set_kx (session, _gnutls_cipher_suite_get_kx_algo (&session->security_parameters. current_cipher_suite)); if (rc < 0) return rc; rc = _gnutls_set_write_compression (session, session->internals. compression_method); if (rc < 0) return rc; } else { /* RESUME_TRUE */ _gnutls_cpy_write_security_parameters (&session-> security_parameters, &session-> internals. resumed_security_parameters); } rc = _gnutls_set_write_keys (session); if (rc < 0) return rc; _gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n", session, _gnutls_cipher_suite_get_name (&session-> security_parameters. current_cipher_suite)); if (_gnutls_compression_is_ok (session->security_parameters.write_compression_algorithm) != 0) { gnutls_assert (); return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; } if (_gnutls_mac_is_ok (session->security_parameters.write_mac_algorithm) != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* Free all the previous keys/ sessions etc. */ if (session->connection_state.write_mac_secret.data != NULL) _gnutls_free_datum (&session->connection_state.write_mac_secret); if (session->connection_state.write_cipher_state != NULL) _gnutls_cipher_deinit (session->connection_state.write_cipher_state); if (session->connection_state.write_compression_state != NULL) _gnutls_comp_deinit (session->connection_state. write_compression_state, 0); mac_size = _gnutls_hash_get_algo_len (session->security_parameters. write_mac_algorithm); _gnutls_handshake_log ("HSK[%x]: Initializing internal [write] cipher sessions\n", session); switch (session->security_parameters.entity) { case GNUTLS_SERVER: /* initialize cipher session */ session->connection_state.write_cipher_state = _gnutls_cipher_init (session->security_parameters. write_bulk_cipher_algorithm, &session->cipher_specs. server_write_key, &session->cipher_specs.server_write_IV); if (session->connection_state.write_cipher_state == GNUTLS_CIPHER_FAILED && session->security_parameters. write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* copy mac secrets from cipherspecs, to connection * session. */ if (mac_size > 0) { if (_gnutls_sset_datum (&session->connection_state. write_mac_secret, session->cipher_specs. server_write_mac_secret.data, session->cipher_specs. server_write_mac_secret.size) < 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } } break; case GNUTLS_CLIENT: session->connection_state.write_cipher_state = _gnutls_cipher_init (session->security_parameters. write_bulk_cipher_algorithm, &session->cipher_specs. client_write_key, &session->cipher_specs.client_write_IV); if (session->connection_state.write_cipher_state == GNUTLS_CIPHER_FAILED && session->security_parameters. write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* copy mac secret to connection session */ if (mac_size > 0) { if (_gnutls_sset_datum (&session->connection_state. write_mac_secret, session->cipher_specs. client_write_mac_secret.data, session->cipher_specs. client_write_mac_secret.size) < 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } } break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } session->connection_state.write_compression_state = _gnutls_comp_init (session->security_parameters. write_compression_algorithm, 0); if (session->connection_state.write_compression_state == GNUTLS_COMP_FAILED) { gnutls_assert (); return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; } return 0; }
/* This function reads the RSA parameters from peer's certificate; */ static int _gnutls_get_public_rsa_params (gnutls_session_t session, bigint_t params[MAX_PUBLIC_PARAMS_SIZE], int *params_len) { int ret; cert_auth_info_t info; gnutls_cert peer_cert; int i; /* normal non export case */ info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_get_auth_info_gcert (&peer_cert, session->security_parameters.cert_type, info, CERT_ONLY_PUBKEY | CERT_NO_COPY); if (ret < 0) { gnutls_assert (); return ret; } /* EXPORT case: */ if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) == GNUTLS_KX_RSA_EXPORT && _gnutls_mpi_get_nbits (peer_cert.params[0]) > 512) { _gnutls_gcert_deinit (&peer_cert); if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (*params_len < 2) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } *params_len = 2; for (i = 0; i < *params_len; i++) { params[i] = _gnutls_mpi_copy (session->key->rsa[i]); } return 0; } /* end of export case */ if (*params_len < peer_cert.params_size) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } *params_len = peer_cert.params_size; for (i = 0; i < *params_len; i++) { params[i] = _gnutls_mpi_copy (peer_cert.params[i]); } _gnutls_gcert_deinit (&peer_cert); return 0; }
/* Read a v2 client hello. Some browsers still use that beast! * However they set their version to 3.0 or 3.1. */ int _gnutls_read_client_hello_v2 (gnutls_session_t session, opaque * data, int datalen) { uint16_t session_id_len = 0; int pos = 0; int ret = 0; uint16_t sizeOfSuites; gnutls_protocol_t version; opaque rnd[TLS_RANDOM_SIZE]; int len = datalen; int err; uint16_t challenge; opaque session_id[TLS_MAX_SESSION_ID_SIZE]; gnutls_protocol_t ver; /* we only want to get here once - only in client hello */ session->internals.v2_hello = 0; DECR_LEN (len, 2); _gnutls_handshake_log ("HSK[%x]: SSL 2.0 Hello: Client's version: %d.%d\n", session, data[pos], data[pos + 1]); set_adv_version (session, data[pos], data[pos + 1]); version = _gnutls_version_get (data[pos], data[pos + 1]); /* if we do not support that version */ if (_gnutls_version_is_supported (session, version) == 0) { ver = _gnutls_version_lowest (session); } else { ver = version; } _gnutls_set_current_version (session, ver); pos += 2; /* Read uint16_t cipher_spec_length */ DECR_LEN (len, 2); sizeOfSuites = _gnutls_read_uint16 (&data[pos]); pos += 2; /* read session id length */ DECR_LEN (len, 2); session_id_len = _gnutls_read_uint16 (&data[pos]); pos += 2; if (session_id_len > TLS_MAX_SESSION_ID_SIZE) { gnutls_assert (); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } /* read challenge length */ DECR_LEN (len, 2); challenge = _gnutls_read_uint16 (&data[pos]); pos += 2; if (challenge < 16 || challenge > TLS_RANDOM_SIZE) { gnutls_assert (); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } /* find an appropriate cipher suite */ DECR_LEN (len, sizeOfSuites); ret = _gnutls_handshake_select_v2_suite (session, &data[pos], sizeOfSuites); pos += sizeOfSuites; if (ret < 0) { gnutls_assert (); return ret; } /* check if the credentials (username, public key etc.) are ok */ if (_gnutls_get_kx_cred (session, _gnutls_cipher_suite_get_kx_algo (&session->security_parameters. current_cipher_suite), &err) == NULL && err != 0) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* set the mod_auth_st to the appropriate struct * according to the KX algorithm. This is needed since all the * handshake functions are read from there; */ session->internals.auth_struct = _gnutls_kx_auth_struct (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters. current_cipher_suite)); if (session->internals.auth_struct == NULL) { _gnutls_handshake_log ("HSK[%x]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n", session); gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* read random new values -skip session id for now */ DECR_LEN (len, session_id_len); /* skip session id for now */ memcpy (session_id, &data[pos], session_id_len); pos += session_id_len; DECR_LEN (len, challenge); memset (rnd, 0, TLS_RANDOM_SIZE); memcpy (&rnd[TLS_RANDOM_SIZE - challenge], &data[pos], challenge); _gnutls_set_client_random (session, rnd); /* generate server random value */ _gnutls_tls_create_random (rnd); _gnutls_set_server_random (session, rnd); session->security_parameters.timestamp = time (NULL); /* RESUME SESSION */ DECR_LEN (len, session_id_len); ret = _gnutls_server_restore_session (session, session_id, session_id_len); if (ret == 0) { /* resumed! */ /* get the new random values */ memcpy (session->internals.resumed_security_parameters. server_random, session->security_parameters.server_random, TLS_RANDOM_SIZE); memcpy (session->internals.resumed_security_parameters. client_random, session->security_parameters.client_random, TLS_RANDOM_SIZE); session->internals.resumed = RESUME_TRUE; return 0; } else { _gnutls_generate_session_id (session->security_parameters. session_id, &session->security_parameters. session_id_size); session->internals.resumed = RESUME_FALSE; } session->internals.compression_method = GNUTLS_COMP_NULL; return 0; }