static int supp_client_send_func(gnutls_session_t session, gnutls_buffer_t buf) { TLS_SUPPLEMENTALDATA_client_sent = 1; gnutls_buffer_append_data(buf, supp_data, sizeof(supp_data)); return GNUTLS_E_SUCCESS; }
static int _gnutls_dumbfw_send_params(gnutls_session_t session, gnutls_buffer_st * extdata) { int total_size = 0, ret; uint8_t pad[257]; unsigned pad_size; if (session->security_parameters.entity == GNUTLS_SERVER || session->internals.priorities.dumbfw == 0 || IS_DTLS(session) != 0 || (extdata->length < 256 || extdata->length >= 512)) { return 0; } else { /* 256 <= extdata->length < 512 */ pad_size = 512 - extdata->length; memset(pad, 0, pad_size); ret = gnutls_buffer_append_data(extdata, pad, pad_size); if (ret < 0) return gnutls_assert_val(ret); total_size += pad_size; } return total_size; }
static int compute_psk_binder(gnutls_session_t session, const mac_entry_st *prf, unsigned binders_length, int exts_length, int ext_offset, const gnutls_datum_t *psk, const gnutls_datum_t *client_hello, bool resuming, void *out) { int ret; unsigned client_hello_pos, extensions_len_pos; gnutls_buffer_st handshake_buf; uint8_t binder_key[MAX_HASH_SIZE]; _gnutls_buffer_init(&handshake_buf); if (session->security_parameters.entity == GNUTLS_CLIENT) { if (session->internals.hsk_flags & HSK_HRR_RECEIVED) { ret = gnutls_buffer_append_data(&handshake_buf, (const void *) session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length); if (ret < 0) { gnutls_assert(); goto error; } } client_hello_pos = handshake_buf.length; ret = gnutls_buffer_append_data(&handshake_buf, client_hello->data, client_hello->size); if (ret < 0) { gnutls_assert(); goto error; } /* This is a ClientHello message */ handshake_buf.data[client_hello_pos] = GNUTLS_HANDSHAKE_CLIENT_HELLO; /* At this point we have not yet added the binders to the ClientHello, * but we have to overwrite the size field, pretending as if binders * of the correct length were present. */ _gnutls_write_uint24(handshake_buf.length - client_hello_pos + binders_length - 2, &handshake_buf.data[client_hello_pos + 1]); _gnutls_write_uint16(handshake_buf.length - client_hello_pos + binders_length - ext_offset, &handshake_buf.data[client_hello_pos + ext_offset]); extensions_len_pos = handshake_buf.length - client_hello_pos - exts_length - 2; _gnutls_write_uint16(exts_length + binders_length + 2, &handshake_buf.data[client_hello_pos + extensions_len_pos]); } else { if (session->internals.hsk_flags & HSK_HRR_SENT) { if (unlikely(session->internals.handshake_hash_buffer.length <= client_hello->size)) { ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); goto error; } ret = gnutls_buffer_append_data(&handshake_buf, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length - client_hello->size); if (ret < 0) { gnutls_assert(); goto error; } } if (unlikely(client_hello->size <= binders_length)) { ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); goto error; } ret = gnutls_buffer_append_data(&handshake_buf, (const void *) client_hello->data, client_hello->size - binders_length); if (ret < 0) { gnutls_assert(); goto error; } } ret = compute_binder_key(prf, psk->data, psk->size, resuming, binder_key); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls13_compute_finished(prf, binder_key, &handshake_buf, out); if (ret < 0) { gnutls_assert(); goto error; } ret = 0; error: _gnutls_buffer_clear(&handshake_buf); return ret; }
static int _gnutls_server_cert_type_send_params(gnutls_session_t session, gnutls_buffer_st* data) { int ret; uint8_t cert_type; // Holds an IANA cert type ID uint8_t i = 0, num_cert_types = 0; priority_st* cert_priorities; gnutls_datum_t tmp_cert_types; // For type conversion uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported cert types. Inv: 0 <= cert type Id < 256 /* Only activate this extension if we have cert credentials set * and alternative cert types are allowed */ if (!are_alternative_cert_types_allowed(session) || (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)) return 0; if (!IS_SERVER(session)) { // Client mode // For brevity cert_priorities = &session->internals.priorities->server_ctype; /* Retrieve server certificate type priorities if any. If no * priorities are set then the default server certificate type * initialization values apply. This default is currently set to * X.509 in which case we don't enable this extension. */ if (cert_priorities->num_priorities > 0) { // Priorities are explicitly set /* If the certificate priority is explicitly set to only * X.509 (default) then, according to spec we don't send * this extension. We check this here to avoid further work in * this routine. We also check it below after pruning supported * types. */ if (cert_priorities->num_priorities == 1 && cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) { _gnutls_handshake_log ("EXT[%p]: Server certificate type was set to default cert type (%s). " "We therefore do not send this extension.\n", session, gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); // Explicitly set but default ctype, so don't send anything return 0; } /* We are only allowed to send certificate types that we support. * Therefore we check this here and prune our original list. * This check might seem redundant now because we don't check for * credentials (they are not needed for a client) and only check the * priorities over which we already iterate. In the future, * additional checks might be necessary and they can be easily * added in the ..type_supported() routine without modifying the * structure of the code here. */ for (i = 0; i < cert_priorities->num_priorities; i++) { if (_gnutls_session_cert_type_supported (session, cert_priorities->priorities[i], false, GNUTLS_CTYPE_SERVER) == 0) { /* Check whether we are allowed to store another cert type * in our buffer. In other words, prevent a possible buffer * overflow. This situation can occur when a user sets * duplicate cert types in the priority strings. */ if (num_cert_types >= GNUTLS_CRT_MAX) return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); // Convert to IANA representation ret = cert_type2IANA(cert_priorities->priorities[i]); if (ret < 0) return gnutls_assert_val(ret); cert_type = ret; // For readability // Add this cert type to our list with supported types cert_types[num_cert_types] = cert_type; num_cert_types++; _gnutls_handshake_log ("EXT[%p]: Server certificate type %s (%d) was queued.\n", session, gnutls_certificate_type_get_name(cert_priorities->priorities[i]), cert_type); } } /* Check whether there are any supported certificate types left * after the previous pruning step. If not, we do not send this * extension. Also, if the only supported type is the default type * we do not send this extension (according to RFC7250). */ if (num_cert_types == 0) { // For now, this should not occur since we only check priorities while pruning. _gnutls_handshake_log ("EXT[%p]: Server certificate types were set but none of them is supported. " "We do not send this extension.\n", session); return 0; } else if (num_cert_types == 1 && IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) { _gnutls_handshake_log ("EXT[%p]: The only supported server certificate type is (%s) which is the default. " "We therefore do not send this extension.\n", session, gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); return 0; } /* We have data to send and store a copy internally. We convert * our list with supported cert types to a datum_t in order to * be able to make the ..._set_datum call. */ tmp_cert_types.data = cert_types; tmp_cert_types.size = num_cert_types; _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_SERVER_CERT_TYPE, &tmp_cert_types); /* Serialize the certificate types into a sequence of octets * uint8: length of sequence of cert types (1 octet) * uint8: cert types (0 <= #octets <= 255) */ ret = _gnutls_buffer_append_data_prefix(data, 8, cert_types, num_cert_types); // Check for errors and cleanup in case of error if (ret < 0) { return gnutls_assert_val(ret); } else { // Number of bytes we are sending return num_cert_types + 1; } } } else { // Server mode // Retrieve negotiated server certificate type and send it ret = cert_type2IANA(get_certificate_type( session, GNUTLS_CTYPE_SERVER)); if (ret < 0) return gnutls_assert_val(ret); cert_type = ret; // For readability ret = gnutls_buffer_append_data(data, &cert_type, 1); if (ret < 0) return gnutls_assert_val(ret); return 1; // sent one byte } // In all other cases don't enable this extension return 0; }