From: Nikos Mavrogiannopoulos Date: Wed, 9 Feb 2011 21:24:53 +0000 (+0100) Subject: The extensions code is now using the gnutls_buffer_st. X-Git-Tag: gnutls_2_99_0~285 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=410239fc93c6834492bb45b1468eb4c2b254b76f;p=thirdparty%2Fgnutls.git The extensions code is now using the gnutls_buffer_st. --- diff --git a/lib/auth_cert.c b/lib/auth_cert.c index dea7aaefef..60bb989264 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -1674,9 +1674,7 @@ _gnutls_proc_cert_client_cert_vrfy (gnutls_session_t session, return 0; } - #define CERTTYPE_SIZE 3 -#define SIGN_ALGO_SIZE (2 + MAX_SIGNATURE_ALGORITHMS * 2) int _gnutls_gen_cert_server_cert_req (gnutls_session_t session, gnutls_buffer_st * data) { @@ -1708,7 +1706,7 @@ _gnutls_gen_cert_server_cert_req (gnutls_session_t session, gnutls_buffer_st * d if (_gnutls_version_has_selectable_sighash (ver)) /* Need two bytes to announce the number of supported hash functions (see below). */ - size += SIGN_ALGO_SIZE; + size += MAX_SIGN_ALGO_SIZE; tmp_data[0] = CERTTYPE_SIZE - 1; tmp_data[1] = RSA_SIGN; @@ -1720,10 +1718,10 @@ _gnutls_gen_cert_server_cert_req (gnutls_session_t session, gnutls_buffer_st * d if (_gnutls_version_has_selectable_sighash (ver)) { - uint8_t p[SIGN_ALGO_SIZE]; + uint8_t p[MAX_SIGN_ALGO_SIZE]; ret = - _gnutls_sign_algorithm_write_params (session, p, SIGN_ALGO_SIZE); + _gnutls_sign_algorithm_write_params (session, p, MAX_SIGN_ALGO_SIZE); if (ret < 0) { gnutls_assert (); @@ -1731,7 +1729,7 @@ _gnutls_gen_cert_server_cert_req (gnutls_session_t session, gnutls_buffer_st * d } /* recalculate size */ - size -= SIGN_ALGO_SIZE + ret; + size -= MAX_SIGN_ALGO_SIZE + ret; ret = _gnutls_buffer_append_data( data, p, ret); if (ret < 0) @@ -2040,7 +2038,7 @@ _gnutls_server_select_cert (gnutls_session_t session, gnutls_pk_algorithm_t requested_algo) { unsigned i; - int idx; + int idx, ret; gnutls_certificate_credentials_t cred; cred = (gnutls_certificate_credentials_t) @@ -2055,17 +2053,30 @@ _gnutls_server_select_cert (gnutls_session_t session, * use it and leave. */ if (cred->server_get_cert_callback != NULL) - return call_get_cert_callback (session, NULL, 0, NULL, 0); + { + ret = call_get_cert_callback (session, NULL, 0, NULL, 0); + if (ret < 0) + return gnutls_assert_val(ret); + return ret; + } /* Otherwise... */ idx = -1; /* default is use no certificate */ + _gnutls_handshake_log("HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n", session, + gnutls_pk_get_name(requested_algo), requested_algo, + gnutls_certificate_type_get_name(session->security_parameters.cert_type), session->security_parameters.cert_type); + for (i = 0; i < cred->ncerts; i++) { /* find one compatible certificate */ + _gnutls_handshake_log("HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d) - sig: %s (%d)\n", session, i, + gnutls_pk_get_name(cred->cert_list[i][0].subject_pk_algorithm), cred->cert_list[i][0].subject_pk_algorithm, + gnutls_certificate_type_get_name(cred->cert_list[i][0].cert_type), cred->cert_list[i][0].cert_type, + gnutls_sign_get_name(cred->cert_list[i][0].sign_algo), cred->cert_list[i][0].sign_algo); if (requested_algo == GNUTLS_PK_ANY || requested_algo == cred->cert_list[i][0].subject_pk_algorithm) { @@ -2077,9 +2088,6 @@ _gnutls_server_select_cert (gnutls_session_t session, && (cred->cert_list[i][0].cert_type == GNUTLS_CRT_OPENPGP || /* FIXME: make this a check for certificate type capabilities */ - !_gnutls_version_has_selectable_sighash - (gnutls_protocol_get_version (session)) - || _gnutls_session_sign_algo_requested (session, cred->cert_list[i][0].sign_algo) == 0)) { @@ -2101,8 +2109,11 @@ _gnutls_server_select_cert (gnutls_session_t session, cred->pkey[idx], 0); } else - /* Certificate does not support REQUESTED_ALGO. */ - return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + { + gnutls_assert(); + /* Certificate does not support REQUESTED_ALGO. */ + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } return 0; } diff --git a/lib/ext_cert_type.c b/lib/ext_cert_type.c index ca5f7a0e0c..5a03878ffb 100644 --- a/lib/ext_cert_type.c +++ b/lib/ext_cert_type.c @@ -43,7 +43,7 @@ static int _gnutls_cert_type_recv_params (gnutls_session_t session, const opaque * data, size_t data_size); static int _gnutls_cert_type_send_params (gnutls_session_t session, - opaque * data, size_t); + gnutls_buffer_st * extdata); extension_entry_st ext_mod_cert_type = { .name = "CERT TYPE", @@ -153,8 +153,6 @@ _gnutls_cert_type_recv_params (gnutls_session_t session, _gnutls_session_cert_type_set (session, new_type); } - - } return 0; @@ -163,11 +161,12 @@ _gnutls_cert_type_recv_params (gnutls_session_t session, /* returns data_size or a negative number on failure */ static int -_gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, - size_t data_size) +_gnutls_cert_type_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { unsigned len, i; - + int ret; + uint8_t p; + /* this function sends the client extension data (dnsname) */ if (session->security_parameters.entity == GNUTLS_CLIENT) { @@ -187,21 +186,21 @@ _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, return 0; } - if (data_size < len + 1) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - /* this is a vector! */ - data[0] = (uint8_t) len; + p = (uint8_t) len; + ret = _gnutls_buffer_append_data(extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); for (i = 0; i < len; i++) { - data[i + 1] = + p = _gnutls_cert_type2num (session->internals.priorities. cert_type.priority[i]); + ret = _gnutls_buffer_append_data(extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); } return len + 1; } @@ -212,14 +211,13 @@ _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data, if (session->security_parameters.cert_type != DEFAULT_CERT_TYPE) { len = 1; - if (data_size < len) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - data[0] = + p = _gnutls_cert_type2num (session->security_parameters.cert_type); + ret = _gnutls_buffer_append_data(extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); + return len; } diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c index 35931d8e1a..195d37aea3 100644 --- a/lib/ext_max_record.c +++ b/lib/ext_max_record.c @@ -35,7 +35,7 @@ static int _gnutls_max_record_recv_params (gnutls_session_t session, const opaque * data, size_t data_size); static int _gnutls_max_record_send_params (gnutls_session_t session, - opaque * data, size_t); + gnutls_buffer_st* extdata); static int _gnutls_max_record_unpack (gnutls_buffer_st * ps, extension_priv_data_t * _priv); @@ -141,10 +141,9 @@ _gnutls_max_record_recv_params (gnutls_session_t session, /* returns data_size or a negative number on failure */ static int -_gnutls_max_record_send_params (gnutls_session_t session, opaque * data, - size_t data_size) +_gnutls_max_record_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { - uint16_t len; + uint8_t p; int ret; /* this function sends the client extension data (dnsname) */ @@ -162,15 +161,12 @@ _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, if (epriv.num != DEFAULT_MAX_RECORD_SIZE) { - len = 1; - if (data_size < len) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } + p = (uint8_t) _gnutls_mre_record2num (epriv.num); + ret = _gnutls_buffer_append_data( extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); - data[0] = (uint8_t) _gnutls_mre_record2num (epriv.num); - return len; + return 1; } } @@ -180,21 +176,17 @@ _gnutls_max_record_send_params (gnutls_session_t session, opaque * data, if (session->security_parameters.max_record_recv_size != DEFAULT_MAX_RECORD_SIZE) { - len = 1; - if (data_size < len) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - data[0] = + p = (uint8_t) _gnutls_mre_record2num (session->security_parameters.max_record_recv_size); - return len; - } + ret = _gnutls_buffer_append_data( extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); + return 1; + } } return 0; diff --git a/lib/ext_safe_renegotiation.c b/lib/ext_safe_renegotiation.c index c34d450ef2..a44c1dea08 100644 --- a/lib/ext_safe_renegotiation.c +++ b/lib/ext_safe_renegotiation.c @@ -29,8 +29,7 @@ static int _gnutls_sr_recv_params (gnutls_session_t state, const opaque * data, size_t data_size); -static int _gnutls_sr_send_params (gnutls_session_t state, - opaque * data, size_t); +static int _gnutls_sr_send_params (gnutls_session_t state, gnutls_buffer_st*); static void _gnutls_sr_deinit_data (extension_priv_data_t priv); extension_entry_st ext_mod_sr = { @@ -362,18 +361,17 @@ _gnutls_sr_recv_params (gnutls_session_t session, } static int -_gnutls_sr_send_params (gnutls_session_t session, - opaque * data, size_t _data_size) +_gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { /* The format of this extension is a one-byte length of verify data followed * by the verify data itself. Note that the length byte does not include * itself; IOW, empty verify data is represented as a length of 0. That means * the minimum extension is one byte: 0x00. */ - ssize_t data_size = _data_size; sr_ext_st *priv; - int ret, set = 0; + int ret, set = 0, len; extension_priv_data_t epriv; + size_t init_length = extdata->length; if (session->internals.priorities.sr == SR_DISABLED) { @@ -406,36 +404,35 @@ _gnutls_sr_send_params (gnutls_session_t session, else priv = epriv.ptr; - data[0] = 0; - /* Always offer the extension if we're a client */ if (priv->connection_using_safe_renegotiation || session->security_parameters.entity == GNUTLS_CLIENT) { - DECR_LEN (data_size, 1); - data[0] = priv->client_verify_data_len; - - DECR_LEN (data_size, priv->client_verify_data_len); + len = priv->client_verify_data_len; + if (session->security_parameters.entity == GNUTLS_SERVER) + len += priv->server_verify_data_len; + + ret = _gnutls_buffer_append_prefix(extdata, 8, len); + if (ret < 0) + return gnutls_assert_val(ret); - if (priv->client_verify_data_len > 0) - memcpy (&data[1], priv->client_verify_data, - priv->client_verify_data_len); + ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data, + priv->client_verify_data_len); + if (ret < 0) + return gnutls_assert_val(ret); if (session->security_parameters.entity == GNUTLS_SERVER) { - data[0] += priv->server_verify_data_len; - - DECR_LEN (data_size, priv->server_verify_data_len); - - if (priv->server_verify_data_len > 0) - memcpy (&data[1 + priv->client_verify_data_len], - priv->server_verify_data, priv->server_verify_data_len); + ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data, + priv->server_verify_data_len); + if (ret < 0) + return gnutls_assert_val(ret); } } else return 0; - return 1 + data[0]; /* don't forget the length byte */ + return extdata->length - init_length; } static void diff --git a/lib/ext_server_name.c b/lib/ext_server_name.c index 1dccb709bf..c223fd8736 100644 --- a/lib/ext_server_name.c +++ b/lib/ext_server_name.c @@ -33,7 +33,7 @@ static int _gnutls_server_name_recv_params (gnutls_session_t session, const opaque * data, size_t data_size); static int _gnutls_server_name_send_params (gnutls_session_t session, - opaque * data, size_t); + gnutls_buffer_st* extdata); static int _gnutls_server_name_unpack (gnutls_buffer_st * ps, extension_priv_data_t * _priv); @@ -174,12 +174,10 @@ _gnutls_server_name_recv_params (gnutls_session_t session, */ static int _gnutls_server_name_send_params (gnutls_session_t session, - opaque * data, size_t _data_size) + gnutls_buffer_st* extdata) { uint16_t len; - opaque *p; unsigned i; - ssize_t data_size = _data_size; int total_size = 0, ret; server_name_ext_st *priv; extension_priv_data_t epriv; @@ -214,13 +212,12 @@ _gnutls_server_name_send_params (gnutls_session_t session, total_size += 1 + 2 + len; } - p = data; - /* UINT16: write total size of all names */ - DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER); - _gnutls_write_uint16 (total_size - 2, p); - p += 2; + ret = _gnutls_buffer_append_prefix(extdata, 16, total_size - 2); + if (ret < 0) + return gnutls_assert_val(ret); + for (i = 0; i < priv->server_names_size; i++) { @@ -235,17 +232,14 @@ _gnutls_server_name_send_params (gnutls_session_t session, * UINT16: size of the first name * LEN: the actual server name. */ - DECR_LENGTH_RET (data_size, len + 3, - GNUTLS_E_SHORT_MEMORY_BUFFER); + ret = _gnutls_buffer_append_prefix(extdata, 8, 0); + if (ret < 0) + return gnutls_assert_val(ret); - *p = 0; /* NAME_DNS type */ - p++; + ret = _gnutls_buffer_append_data_prefix(extdata, 16, priv->server_names[i].name, len); + if (ret < 0) + return gnutls_assert_val(ret); - _gnutls_write_uint16 (len, p); - p += 2; - - memcpy (p, priv->server_names[i].name, len); - p += len; break; default: gnutls_assert (); diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c index 3c778689bd..25a01a05f9 100644 --- a/lib/ext_session_ticket.c +++ b/lib/ext_session_ticket.c @@ -48,7 +48,7 @@ static int session_ticket_recv_params (gnutls_session_t session, const opaque * data, size_t data_size); static int session_ticket_send_params (gnutls_session_t session, - opaque * data, size_t data_size); + gnutls_buffer_st* extdata); static int session_ticket_unpack (gnutls_buffer_st * ps, extension_priv_data_t * _priv); static int session_ticket_pack (extension_priv_data_t _priv, @@ -361,9 +361,8 @@ session_ticket_recv_params (gnutls_session_t session, */ static int session_ticket_send_params (gnutls_session_t session, - opaque * data, size_t _data_size) + gnutls_buffer_st * extdata) { - ssize_t data_size = _data_size; session_ticket_ext_st *priv = NULL; extension_priv_data_t epriv; int ret; @@ -403,9 +402,9 @@ session_ticket_send_params (gnutls_session_t session, if (priv->session_ticket_len > 0) { - DECR_LENGTH_RET (data_size, priv->session_ticket_len, - GNUTLS_E_SHORT_MEMORY_BUFFER); - memcpy (data, priv->session_ticket, priv->session_ticket_len); + ret = _gnutls_buffer_append_data( extdata, priv->session_ticket, priv->session_ticket_len); + if (ret < 0) + return gnutls_assert_val(ret); return priv->session_ticket_len; } diff --git a/lib/ext_signature.c b/lib/ext_signature.c index af6328b758..29f63eaf9e 100644 --- a/lib/ext_signature.c +++ b/lib/ext_signature.c @@ -39,7 +39,7 @@ static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, const opaque * data, size_t data_size); static int _gnutls_signature_algorithm_send_params (gnutls_session_t session, - opaque * data, size_t); + gnutls_buffer_st * extdata); static void signature_algorithms_deinit_data (extension_priv_data_t priv); static int signature_algorithms_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps); @@ -87,7 +87,7 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, p += 2; - for (i = j = 0; i < session->internals.priorities.sign_algo.algorithms; i += 2, j++) + for (i = j = 0; j < session->internals.priorities.sign_algo.algorithms; i += 2, j++) { aid = _gnutls_sign_to_tls_aid (session->internals.priorities. @@ -96,7 +96,7 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, if (aid == NULL) continue; - _gnutls_debug_log ("EXT[SIGA]: sent signature algo (%d.%d) %s\n", aid->hash_algorithm, + _gnutls_debug_log ("EXT[%p]: sent signature algo (%d.%d) %s\n", session, aid->hash_algorithm, aid->sign_algorithm, gnutls_sign_get_name(session->internals.priorities.sign_algo.priority[j])); *p = aid->hash_algorithm; p++; @@ -106,7 +106,6 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, } _gnutls_write_uint16 (len, len_p); - return len + 2; } @@ -138,7 +137,7 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session, sig = _gnutls_tls_aid_to_sign (&aid); - _gnutls_debug_log ("EXT[SIGA]: rcvd signature algo (%d.%d) %s\n", aid.hash_algorithm, + _gnutls_debug_log ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, aid.hash_algorithm, aid.sign_algorithm, gnutls_sign_get_name(sig)); if (sig != GNUTLS_SIGN_UNKNOWN) @@ -211,9 +210,10 @@ _gnutls_signature_algorithm_recv_params (gnutls_session_t session, */ static int _gnutls_signature_algorithm_send_params (gnutls_session_t session, - opaque * data, size_t data_size) + gnutls_buffer_st* extdata) { int ret; + size_t init_length = extdata->length; gnutls_protocol_t ver = gnutls_protocol_get_version (session); /* this function sends the client extension data */ @@ -222,14 +222,18 @@ _gnutls_signature_algorithm_send_params (gnutls_session_t session, { if (session->internals.priorities.sign_algo.algorithms > 0) { + uint8_t p[MAX_SIGN_ALGO_SIZE]; + ret = - _gnutls_sign_algorithm_write_params (session, data, data_size); + _gnutls_sign_algorithm_write_params (session, p, sizeof(p)); if (ret < 0) - { - gnutls_assert (); - return ret; - } - return ret; + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_data(extdata, p, ret); + if (ret < 0) + return gnutls_assert_val(ret); + + return extdata->length - init_length; } } @@ -322,6 +326,10 @@ _gnutls_session_sign_algo_requested (gnutls_session_t session, for (i = 0; i < priv->sign_algorithms_size; i++) { + _gnutls_handshake_log("HSK[%p]: allowed sign algorithm: %s (%d)-- want %s (%d)\n", session, + gnutls_sign_get_name(priv->sign_algorithms[i]), priv->sign_algorithms[i], + gnutls_sign_get_name(sig), sig); + if (priv->sign_algorithms[i] == sig) { return 0; /* ok */ diff --git a/lib/ext_srp.c b/lib/ext_srp.c index e77be77bc0..e97d997699 100644 --- a/lib/ext_srp.c +++ b/lib/ext_srp.c @@ -42,8 +42,7 @@ static int _gnutls_srp_pack (extension_priv_data_t epriv, static void _gnutls_srp_deinit_data (extension_priv_data_t epriv); static int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data, size_t data_size); -static int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, - size_t); +static int _gnutls_srp_send_params (gnutls_session_t state, gnutls_buffer_st * extdata); extension_entry_st ext_mod_srp = { .name = "SRP", @@ -106,12 +105,14 @@ _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, * data is allocated locally */ static int -_gnutls_srp_send_params (gnutls_session_t session, opaque * data, - size_t data_size) +_gnutls_srp_send_params (gnutls_session_t session, + gnutls_buffer_st * extdata) { unsigned len; + int ret; extension_priv_data_t epriv; srp_ext_st *priv; + char *username = NULL, *password = NULL; if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 && _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 && @@ -135,21 +136,16 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, { /* send username */ len = MIN (strlen (cred->username), 255); - if (data_size < len + 1) - { - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } + ret = _gnutls_buffer_append_data_prefix(extdata, 8, cred->username, len); + if (ret < 0) + return gnutls_assert_val(ret); - data[0] = (uint8_t) len; - memcpy (&data[1], cred->username, len); return len + 1; } else if (cred->get_function != NULL) { /* Try the callback */ - char *username = NULL, *password = NULL; if (cred->get_function (session, &username, &password) < 0 || username == NULL || password == NULL) @@ -160,19 +156,12 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, len = MIN (strlen (username), 255); - if (data_size < len + 1) - { - gnutls_free (username); - gnutls_free (password); - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - priv = gnutls_malloc (sizeof (*priv)); if (priv == NULL) { gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; } priv->username = username; @@ -181,12 +170,23 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv); - data[0] = (uint8_t) len; - memcpy (&data[1], username, len); + ret = _gnutls_buffer_append_data_prefix(extdata, 8, username, len); + if (ret < 0) + { + ret = gnutls_assert_val(ret); + goto cleanup; + } + return len + 1; } } return 0; + +cleanup: + gnutls_free (username); + gnutls_free (password); + + return ret; } static void diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 6449a39f15..451065184f 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -236,32 +236,16 @@ _gnutls_extension_list_add (gnutls_session_t session, uint16_t type) } int -_gnutls_gen_extensions (gnutls_session_t session, opaque * data, - size_t data_size, gnutls_ext_parse_type_t parse_type) +_gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata, + gnutls_ext_parse_type_t parse_type) { int size; - uint16_t pos = 0; - opaque *sdata; - size_t sdata_size; - size_t i; + int pos, size_pos, ret; + size_t i, init_size = extdata->length; - if (data_size < 2) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } + pos = extdata->length; /* we will store length later on */ + _gnutls_buffer_append_prefix( extdata, 16, 0); - /* allocate enough data for each extension. - */ - sdata_size = data_size; - sdata = gnutls_malloc (sdata_size); - if (sdata == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - pos += 2; for (i = 0; i < extfunc_size; i++) { extension_entry_st *p = &extfunc[i]; @@ -272,30 +256,27 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type) continue; - size = p->send_func (session, sdata, sdata_size); + ret = _gnutls_buffer_append_prefix( extdata, 16, p->type); + if (ret < 0) + return gnutls_assert_val(ret); + + size_pos = extdata->length; + ret = _gnutls_buffer_append_prefix (extdata, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + size = p->send_func (session, extdata); + /* returning GNUTLS_E_INT_RET_0 means to send an empty + * extension of this type. + */ if (size > 0 || size == GNUTLS_E_INT_RET_0) { if (size == GNUTLS_E_INT_RET_0) size = 0; - - if (data_size < pos + (size_t) size + 4) - { - gnutls_assert (); - gnutls_free (sdata); - return GNUTLS_E_INTERNAL_ERROR; - } - - /* write extension type */ - _gnutls_write_uint16 (p->type, &data[pos]); - pos += 2; - - /* write size */ - _gnutls_write_uint16 (size, &data[pos]); - pos += 2; - - memcpy (&data[pos], sdata, size); - pos += size; - + + /* write the real size */ + _gnutls_write_uint16(size, &extdata->data[size_pos]); + /* add this extension to the extension list */ _gnutls_extension_list_add (session, p->type); @@ -306,24 +287,19 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, else if (size < 0) { gnutls_assert (); - gnutls_free (sdata); return size; } + else if (size == 0) + extdata->length -= 4; /* reset type and size */ } - size = pos; - pos -= 2; /* remove the size of the size header! */ - - _gnutls_write_uint16 (pos, data); + /* remove any initial data, and the size of the header */ + size = extdata->length - init_size - 2; + + if ( size > 0) + _gnutls_write_uint16(size, &extdata->data[pos]); - if (size == 2) - { /* empty */ - size = 0; - } - - gnutls_free (sdata); return size; - } int diff --git a/lib/gnutls_extensions.h b/lib/gnutls_extensions.h index a381b823ec..9906f5bbc6 100644 --- a/lib/gnutls_extensions.h +++ b/lib/gnutls_extensions.h @@ -26,11 +26,18 @@ #ifndef GNUTLS_EXTENSIONS_H #define GNUTLS_EXTENSIONS_H +#include + +typedef int (*gnutls_ext_recv_func) (gnutls_session_t session, + const unsigned char *data, size_t len); +typedef int (*gnutls_ext_send_func) (gnutls_session_t session, + gnutls_buffer_st *extdata); + int _gnutls_parse_extensions (gnutls_session_t session, gnutls_ext_parse_type_t parse_type, const opaque * data, int data_size); -int _gnutls_gen_extensions (gnutls_session_t session, opaque * data, - size_t data_size, gnutls_ext_parse_type_t); +int _gnutls_gen_extensions (gnutls_session_t session, gnutls_buffer_st * extdata, + gnutls_ext_parse_type_t); int _gnutls_ext_init (void); void _gnutls_ext_deinit (void); diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index de899c2db0..84fb9e120c 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1874,14 +1874,14 @@ _gnutls_read_server_hello (gnutls_session_t session, */ static int _gnutls_copy_ciphersuites (gnutls_session_t session, - opaque * ret_data, size_t ret_data_size, + gnutls_buffer_st * cdata, int add_scsv) { int ret, i; cipher_suite_st *cipher_suites; uint16_t cipher_num; - int datalen, pos; uint16_t loop_max; + size_t init_length = cdata->length; ret = _gnutls_supported_ciphersuites_sorted (session, &cipher_suites); if (ret < 0) @@ -1919,44 +1919,52 @@ _gnutls_copy_ciphersuites (gnutls_session_t session, cipher_num *= sizeof (uint16_t); /* in order to get bytes */ - datalen = pos = 0; - - datalen += sizeof (uint16_t) + cipher_num; - - if ((size_t) datalen > ret_data_size) + ret = _gnutls_buffer_append_prefix(cdata, 16, cipher_num); + if (ret < 0) { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + gnutls_assert(); + goto cleanup; } - _gnutls_write_uint16 (cipher_num, ret_data); - pos += 2; loop_max = add_scsv ? cipher_num - 2 : cipher_num; - for (i = 0; i < (loop_max / 2); i++) { - memcpy (&ret_data[pos], cipher_suites[i].suite, 2); - pos += 2; + ret = _gnutls_buffer_append_data( cdata, cipher_suites[i].suite, 2); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } } if (add_scsv) { + uint8_t p[2]; /* Safe renegotiation signalling CS value is { 0x00, 0xff } */ - ret_data[pos++] = 0x00; - ret_data[pos++] = 0xff; + p[0] = 0x00; + p[1] = 0xff; + ret = _gnutls_buffer_append_data( cdata, p, 2); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + ret = _gnutls_ext_sr_send_cs (session); if (ret < 0) { gnutls_assert (); - gnutls_free (cipher_suites); - return ret; + goto cleanup; } } + ret = cdata->length - init_length; + +cleanup: gnutls_free (cipher_suites); - return datalen; + return ret; } @@ -1965,11 +1973,11 @@ _gnutls_copy_ciphersuites (gnutls_session_t session, */ static int _gnutls_copy_comp_methods (gnutls_session_t session, - opaque * ret_data, size_t ret_data_size) + gnutls_buffer_st * cdata) { int ret, i; uint8_t *compression_methods, comp_num; - int datalen, pos; + size_t init_length = cdata->length; ret = _gnutls_supported_compression_methods (session, &compression_methods); if (ret < 0) @@ -1980,25 +1988,30 @@ _gnutls_copy_comp_methods (gnutls_session_t session, comp_num = ret; - datalen = pos = 0; - datalen += comp_num + 1; - - if ((size_t) datalen > ret_data_size) + /* put the number of compression methods */ + ret = _gnutls_buffer_append_prefix(cdata, 8, comp_num); + if (ret < 0) { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + gnutls_assert(); + goto cleanup; } - ret_data[pos++] = comp_num; /* put the number of compression methods */ - for (i = 0; i < comp_num; i++) { - ret_data[pos++] = compression_methods[i]; + ret = _gnutls_buffer_append_data(cdata, &compression_methods[i], 1); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } } + ret = cdata->length - init_length; + +cleanup: gnutls_free (compression_methods); - return datalen; + return ret; } /* This should be sufficient by now. It should hold all the extensions @@ -2013,16 +2026,17 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) { mbuffer_st *bufel = NULL; opaque *data = NULL; - int extdatalen; int pos = 0, type; int datalen = 0, ret = 0; opaque rnd[GNUTLS_RANDOM_SIZE]; gnutls_protocol_t hver; - opaque *extdata = NULL; + gnutls_buffer_st extdata; int rehandshake = 0; uint8_t session_id_len = session->internals.resumed_security_parameters.session_id_size; + _gnutls_buffer_init(&extdata); + /* note that rehandshake is different than resuming */ if (session->security_parameters.session_id_size) @@ -2043,14 +2057,6 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) return GNUTLS_E_MEMORY_ERROR; } data = _mbuffer_get_udata_ptr (bufel); - extdatalen = MAX_EXT_DATA_LENGTH; - - extdata = gnutls_malloc (extdatalen); - if (extdata == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } /* if we are resuming a session then we set the * version number to the previously established. @@ -2072,7 +2078,6 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) { gnutls_assert (); gnutls_free (bufel); - gnutls_free (extdata); return GNUTLS_E_INTERNAL_ERROR; } @@ -2132,55 +2137,26 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) gnutls_protocol_get_version (session) == GNUTLS_SSL3) { ret = - _gnutls_copy_ciphersuites (session, extdata, extdatalen, TRUE); + _gnutls_copy_ciphersuites (session, &extdata, TRUE); _gnutls_extension_list_add (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION); } else - ret = _gnutls_copy_ciphersuites (session, extdata, extdatalen, FALSE); + ret = _gnutls_copy_ciphersuites (session, &extdata, FALSE); - if (ret > 0) - { - ret = _mbuffer_append_data (bufel, extdata, ret); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (extdata); - return ret; - } - } - else + if (ret < 0) { - if (extdatalen == 0) - extdatalen = GNUTLS_E_INTERNAL_ERROR; - gnutls_free (bufel); - gnutls_free (extdata); - gnutls_assert (); - return ret; + gnutls_assert(); + goto cleanup; } - /* Copy the compression methods. */ - ret = _gnutls_copy_comp_methods (session, extdata, extdatalen); - if (ret > 0) - { - ret = _mbuffer_append_data (bufel, extdata, ret); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (extdata); - return ret; - } - } - else + ret = _gnutls_copy_comp_methods (session, &extdata); + if (ret < 0) { - if (extdatalen == 0) - extdatalen = GNUTLS_E_INTERNAL_ERROR; - gnutls_free (bufel); - gnutls_free (extdata); - gnutls_assert (); - return ret; + gnutls_assert(); + goto cleanup; } /* Generate and copy TLS extensions. @@ -2195,32 +2171,29 @@ _gnutls_send_client_hello (gnutls_session_t session, int again) type = GNUTLS_EXT_NONE; } - ret = _gnutls_gen_extensions (session, extdata, extdatalen, type); - - if (ret > 0) + ret = _gnutls_gen_extensions (session, &extdata, type); + if (ret < 0) { - ret = _mbuffer_append_data (bufel, extdata, ret); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (extdata); - return ret; - } + gnutls_assert(); + goto cleanup; } - else if (ret < 0) + + ret = _mbuffer_append_data (bufel, extdata.data, extdata.length); + if (ret < 0) { gnutls_assert (); - gnutls_free (bufel); - gnutls_free (extdata); - return ret; + goto cleanup; } } - gnutls_free (extdata); + _gnutls_buffer_clear(&extdata); - ret = + return _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_CLIENT_HELLO); +cleanup: + gnutls_free (bufel); + _gnutls_buffer_clear(&extdata); return ret; } @@ -2229,8 +2202,7 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) { mbuffer_st *bufel = NULL; opaque *data = NULL; - opaque *extdata = NULL; - int extdatalen; + gnutls_buffer_st extdata; int pos = 0; int datalen, ret = 0; uint8_t comp; @@ -2239,30 +2211,21 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) datalen = 0; + _gnutls_buffer_init(&extdata); + if (again == 0) { - - extdata = gnutls_malloc (MAX_EXT_DATA_LENGTH); - if (extdata == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - datalen = 2 + session_id_len + 1 + GNUTLS_RANDOM_SIZE + 3; ret = - _gnutls_gen_extensions (session, extdata, MAX_EXT_DATA_LENGTH, - GNUTLS_EXT_ANY); - + _gnutls_gen_extensions (session, &extdata, GNUTLS_EXT_ANY); if (ret < 0) { gnutls_assert (); goto fail; } - extdatalen = ret; bufel = - _gnutls_handshake_alloc (datalen + extdatalen, datalen + extdatalen); + _gnutls_handshake_alloc (datalen + extdata.length, datalen + extdata.length); if (bufel == NULL) { gnutls_assert (); @@ -2303,11 +2266,10 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) data[pos++] = comp; - if (extdatalen > 0) + if (extdata.length > 0) { - datalen += extdatalen; - - memcpy (&data[pos], extdata, extdatalen); + datalen += extdata.length; + memcpy (&data[pos], extdata.data, extdata.length); } } @@ -2315,7 +2277,7 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_SERVER_HELLO); fail: - gnutls_free (extdata); + _gnutls_buffer_clear(&extdata); return ret; } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index b01dc5c383..ed354890f9 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -98,10 +98,35 @@ typedef struct #define GNUTLS_MASTER_SIZE 48 #define GNUTLS_RANDOM_SIZE 32 +/* TLS Extensions */ /* we can receive up to MAX_EXT_TYPES extensions. */ #define MAX_EXT_TYPES 32 + /** + * gnutls_ext_parse_type_t: + * @GNUTLS_EXT_NONE: Never parsed + * @GNUTLS_EXT_ANY: Any extension type. + * @GNUTLS_EXT_APPLICATION: Application extension. + * @GNUTLS_EXT_TLS: TLS-internal extension. + * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled). + * + * Enumeration of different TLS extension types. This flag + * indicates for an extension whether it is useful to application + * level or TLS level only. This is (only) used to parse the + * application level extensions before the "client_hello" callback + * is called. + */ + typedef enum + { + GNUTLS_EXT_ANY = 0, + GNUTLS_EXT_APPLICATION = 1, + GNUTLS_EXT_TLS = 2, + GNUTLS_EXT_MANDATORY = 3, + GNUTLS_EXT_NONE = 4 + } gnutls_ext_parse_type_t; + + /* The initial size of the receive * buffer size. This will grow if larger * packets are received. @@ -322,6 +347,7 @@ typedef struct */ #define MAX_SIGNATURE_ALGORITHMS 16 +#define MAX_SIGN_ALGO_SIZE (2 + MAX_SIGNATURE_ALGORITHMS * 2) #define MAX_VERIFY_DATA_SIZE 36 /* in SSL 3.0, 12 in TLS 1.0 */ diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index 90e9daf3e4..ee4fb03779 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -421,7 +421,7 @@ _gnutls_dsa_sign (gnutls_datum_t * signature, k = hash->size; if (k < 20) - { /* SHA1 or better only */ + { /* SHA1 or better only */ gnutls_assert (); return GNUTLS_E_PK_SIGN_FAILED; } diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 17ebf405ba..f32661c087 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -147,6 +147,9 @@ _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert, gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } + + _gnutls_handshake_log("HSK[%p]: hash from highest priority sigalgorithm: %s (%d)\n", + session, gnutls_mac_get_name(hash_algo), hash_algo); ret = _gnutls_hash_init (&td_sha, hash_algo); if (ret < 0) @@ -219,6 +222,8 @@ _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert, _gnutls_hash_deinit (&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } + +fprintf(stderr, "asking to sign: %d bytes\n", dconcat.size); ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature); if (ret < 0) { diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 7f463f759b..2f90f01dc0 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -59,6 +59,8 @@ void _gnutls_session_cert_type_set (gnutls_session_t session, gnutls_certificate_type_t ct) { + _gnutls_handshake_log("HSK[%p]: Selected certificate type %s (%d)\n", session, + gnutls_certificate_type_get_name(ct), ct); session->security_parameters.cert_type = ct; } diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 385d238b40..33fd483d9e 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -797,37 +797,6 @@ extern "C" size_t seed_size, const char *seed, size_t outsize, char *out); -/* TLS Extensions */ - - typedef int (*gnutls_ext_recv_func) (gnutls_session_t session, - const unsigned char *data, size_t len); - typedef int (*gnutls_ext_send_func) (gnutls_session_t session, - unsigned char *data, size_t len); - - /** - * gnutls_ext_parse_type_t: - * @GNUTLS_EXT_NONE: Never parsed - * @GNUTLS_EXT_ANY: Any extension type. - * @GNUTLS_EXT_APPLICATION: Application extension. - * @GNUTLS_EXT_TLS: TLS-internal extension. - * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled). - * - * Enumeration of different TLS extension types. This flag - * indicates for an extension whether it is useful to application - * level or TLS level only. This is (only) used to parse the - * application level extensions before the "client_hello" callback - * is called. - */ - typedef enum - { - GNUTLS_EXT_ANY = 0, - GNUTLS_EXT_APPLICATION = 1, - GNUTLS_EXT_TLS = 2, - GNUTLS_EXT_MANDATORY = 3, - GNUTLS_EXT_NONE = 4 - } gnutls_ext_parse_type_t; - - /** * gnutls_server_name_type_t: * @GNUTLS_NAME_DNS: Domain Name System name type. diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 001b9b2d46..6d37078b9c 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -288,6 +288,7 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo, if (vdata->size != _gnutls_hash_get_algo_len (hash)) { gnutls_assert (); + _gnutls_debug_log("Asked to sign %d bytes with hash %s\n", vdata->size, gnutls_mac_get_name(hash)); ret = GNUTLS_E_PK_SIGN_FAILED; goto dsa_fail; }