# RFC 9946 §5: Requirements, Security Operations, and Optional Checksum

The 73 Requirements of RFC 9946 §5, each quoted from the RFC with its state and the tests that prove it. [Conformance](index.md) explains the states.

| State | Requirements |
|---|--:|
| Tested | 57 |
| Deviation | 3 |
| Operational | 8 |
| Not applicable | 5 |

## RFC9946-5-L1 {#RFC9946-5-L1}

**Tested**

> Due to the additional complexities, and loss of the direct mapping of packets to datagrams between Layer 3 and Layer 4, it is recommended that Layer 3 fragmentation be avoided.

Note: Default datagram sizes fit a traditional MTU.

Proving tests:

- [`crates/udpstp-core/src/sending_rate_table.rs::packet_sizes_follow_the_modifiers_and_the_mtu`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/src/sending_rate_table.rs)

## RFC9946-5-1 {#RFC9946-5-1}

**Deviation**

> Unless IP fragmentation is expected, and is one of the attributes being measured, the IPv4 Don't Fragment (DF) bit SHOULD be set for all tests.

Note: The dont_fragment setting, on by default.

Recorded in [windows-dont-fragment-unset](../conformance/deviations.md#windows-dont-fragment-unset).

Proving tests:

- [`crates/udpstp/tests/netns.rs::downstream_and_upstream_tests_measure_the_bottleneck`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/netns.rs)
- [`crates/udpstp-runtime/src/ip_options.rs::test_traffic_carries_df_and_max_hops`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-runtime/src/ip_options.rs)

## RFC9946-5-L2 {#RFC9946-5-L2}

**Tested**

> Note: When this specification is used for network debugging, it may be useful for fragmentation to be under the control of the test administrator.

Note: The dont_fragment setting.

Proving tests:

- [`crates/udpstp/tests/cli.rs::the_admission_limits_are_server_settings`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/cli.rs)

## RFC9946-5-2 {#RFC9946-5-2}

**Not applicable**

> This section specifies generic requirements, which a measurement load rate adjustment algorithm conforming to this specification MUST fulfill.

Note: An introduction to the section's Requirements, each recorded with its own ID; nothing to do beyond them.

## RFC9946-5.1-1 {#RFC9946-5.1-1}

**Not applicable**

> Load rate adjustment algorithms for capacity measurement MUST comply with the requirements specified by this section.

Note: An introduction to the section's Requirements, each recorded with its own ID; nothing to do beyond them.

## RFC9946-5.1-2 {#RFC9946-5.1-2}

**Not applicable**

> New standard load rate adjustment algorithms for capacity measurement MUST be reviewed by IETF designated experts prior to assignment of a code point in the "Test Activation PDU Rate Adjustment Algo" registry.

Note: An IANA registration process, not endpoint behaviour.

## RFC9946-5.1-3 {#RFC9946-5.1-3}

**Operational**

> The measurement load rate adjustment algorithm described in this section MUST NOT be used as a general CCA.

Note: A usage statement: udpstp runs the algorithm only within a Test.

## RFC9946-5.1-4 {#RFC9946-5.1-4}

**Operational**

> This specification MUST only be used in the application of diagnostic and operations measurements.

Note: A usage statement.

## RFC9946-5.1-5 {#RFC9946-5.1-5}

**Tested**

> Both Load PDU messages and Status Feedback PDU messages MUST contain sequence numbers.

Note: lpduSeqNo and spduSeqNo fields.

Proving tests:

- [`crates/udpstp-core/tests/status_pdus.rs::status_pdus_follow_the_first_load_pdu_every_trial_interval`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/status_pdus.rs)

## RFC9946-5.1-6 {#RFC9946-5.1-6}

**Tested**

> The nominal duration of a measurement interval at the Destination, parameter testIntTime ("I" in [RFC9097]), MUST default to a value of no more than 10 seconds.

Note: testIntTime default.

Proving tests:

- [`crates/udpstp-core/tests/parameter_ranges.rs::the_client_asks_for_the_defaults`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/parameter_ranges.rs)

## RFC9946-5.1-7 {#RFC9946-5.1-7}

**Tested**

> A high-speed mode to achieve high sending rates quickly MUST reduce the measurement load below a level for which the first feedback interval inferred "congestion" from the measurements.

Note: Fast Mode's drop when Congestion is confirmed.

Conformance Records: [fast-mode-stops-at-the-gigabit-row](../conformance/interpretations.md#fast-mode-stops-at-the-gigabit-row), [confirming-drop-below-the-gigabit-row-only](../conformance/interpretations.md#confirming-drop-below-the-gigabit-row-only).

Proving tests:

- [`crates/udpstp-core/tests/algorithm_b.rs::congestion_is_confirmed_by_back_to_back_errored_intervals`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/algorithm_b.rs)
- [`crates/udpstp-core/tests/algorithm_b.rs::the_confirming_drop_stops_at_row_0_and_follows_the_row_it_starts_from`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/algorithm_b.rs)

## RFC9946-5.1-L1 {#RFC9946-5.1-L1}

**Tested**

> Consecutive feedback intervals that have a supra-threshold count of sequence number anomalies and/or contain an upper delay variation threshold exception in all of the consecutive intervals indicate "congestion" within a test.

Note: Congestion Confirmed after slowAdjThresh Errored Intervals back to back (ADR 0005).

Conformance Records: [latched-congestion-confirmed](../conformance/interpretations.md#latched-congestion-confirmed).

Proving tests:

- [`crates/udpstp-core/tests/algorithm_b.rs::congestion_is_confirmed_by_back_to_back_errored_intervals`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/algorithm_b.rs)
- [`crates/udpstp-core/tests/algorithm_b.rs::intermittent_errored_intervals_do_not_confirm_congestion`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/algorithm_b.rs)

## RFC9946-5.1-8 {#RFC9946-5.1-8}

**Deviation**

> The threshold of consecutive feedback intervals SHALL be configurable with a default of 3 intervals and a maximum duration to infer congestion of 500 ms (milliseconds).

Note: slowAdjThresh and trialInt.

Recorded in [operator-keys-exempt-from-500-ms-congestion-inference](../conformance/deviations.md#operator-keys-exempt-from-500-ms-congestion-inference).

Conformance Records: [congestion-inference-within-500-ms](../conformance/interpretations.md#congestion-inference-within-500-ms).

Proving tests:

- [`crates/udpstp-core/tests/algorithm_b.rs::the_accepted_parameters_drive_the_algorithm`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/algorithm_b.rs)
- [`crates/udpstp-core/tests/test_interval_limits.rs::slow_adj_thresh_times_trial_int_is_at_most_500_ms`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/test_interval_limits.rs)

## RFC9946-5.1-9 {#RFC9946-5.1-9}

**Tested**

> Congestion MUST be indicated if the Status Feedback PDUs indicate that either sequence number anomalies were detected OR the delay range was above the upper delay variation threshold.

Note: seqErrThresh and upperThresh.

Conformance Records: [clean-needs-delay-var-below-low-thresh](../conformance/interpretations.md#clean-needs-delay-var-below-low-thresh), [seq-err-thresh-always-applied](../conformance/interpretations.md#seq-err-thresh-always-applied), [no-delay-sample-is-never-clean](../conformance/interpretations.md#no-delay-sample-is-never-clean).

Proving tests:

- [`crates/udpstp-core/tests/interval_classification.rs::the_average_rounds_and_clean_is_strictly_below_the_low_threshold`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/interval_classification.rs)
- [`crates/udpstp-core/tests/interval_classification.rs::the_maximum_is_the_default_and_the_average_a_setting`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/interval_classification.rs)
- [`crates/udpstp-core/tests/interval_classification.rs::no_delay_samples_is_never_clean`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/interval_classification.rs)
- [`crates/udpstp-core/tests/interval_classification.rs::seq_err_thresh_is_always_applied`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/interval_classification.rs)
- [`crates/udpstp-core/tests/interval_classification.rs::an_upstream_server_classifies_the_status_pdus_it_sends`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/interval_classification.rs)

## RFC9946-5.1-10 {#RFC9946-5.1-10}

**Tested**

> The RECOMMENDED threshold values are 10 for sequence number gaps, 30 ms for lower delay variation thresholds, and 90 ms for upper delay variation thresholds.

Note: seqErrThresh, lowThresh and upperThresh defaults.

Proving tests:

- [`crates/udpstp-core/tests/parameter_ranges.rs::the_client_asks_for_the_defaults`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/parameter_ranges.rs)

## RFC9946-5.1-11 {#RFC9946-5.1-11}

**Tested**

> The load rate adjustment algorithm MUST include a Load PDU timeout and a Status PDU timeout, which both stop the test when received PDU streams cease unexpectedly.

Note: ADR 0002 reconciles them with the Section 6.1 Watchdog.

Conformance Records: [receive-timeouts-stop-sending-at-1s](../conformance/interpretations.md#receive-timeouts-stop-sending-at-1s), [receive-timeouts-run-from-data-phase-start](../conformance/interpretations.md#receive-timeouts-run-from-data-phase-start).

Proving tests:

- [`crates/udpstp/tests/loopback.rs::the_client_reports_a_server_that_goes_away`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/timeouts.rs::a_downstream_path_that_breaks_stops_within_1_s_and_ends_at_3_s`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)
- [`crates/udpstp-core/tests/timeouts.rs::an_upstream_client_stops_when_status_pdus_stop`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)
- [`crates/udpstp-core/tests/timeouts.rs::load_pdus_failing_the_checksum_do_not_reset_the_watchdog`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-12 {#RFC9946-5.1-12}

**Tested**

> The Load PDU timeout SHALL be reset to the configured value each time a Load PDU is received.

Proving tests:

- [`crates/udpstp-core/tests/timeouts.rs::rx_stopped_clears_when_traffic_comes_back_in_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-13 {#RFC9946-5.1-13}

**Tested**

> If the Load PDU timeout expires, the receiver SHALL be closed and no further Status PDU feedback sent.

Conformance Records: [receive-timeout-is-final](../conformance/interpretations.md#receive-timeout-is-final).

Proving tests:

- [`crates/udpstp-core/tests/timeouts.rs::a_downstream_path_that_breaks_stops_within_1_s_and_ends_at_3_s`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)
- [`crates/udpstp-core/tests/timeouts.rs::an_upstream_client_stops_when_status_pdus_stop`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-14 {#RFC9946-5.1-14}

**Tested**

> The default Load PDU timeout MUST be no more than 1 second.

Proving tests:

- [`crates/udpstp/tests/loopback.rs::the_client_reports_a_server_that_goes_away`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/timeouts.rs::a_downstream_path_that_breaks_stops_within_1_s_and_ends_at_3_s`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-15 {#RFC9946-5.1-15}

**Tested**

> The Status PDU timeout SHALL be reset to the configured value each time a feedback message is received.

Proving tests:

- [`crates/udpstp-core/tests/stale_status_pdus.rs::a_stale_status_pdu_still_counts_as_heard`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/stale_status_pdus.rs)

## RFC9946-5.1-16 {#RFC9946-5.1-16}

**Tested**

> If the Status PDU timeout expires, the sender SHALL be closed and no further load packets sent.

Conformance Records: [receive-timeout-is-final](../conformance/interpretations.md#receive-timeout-is-final).

Proving tests:

- [`crates/udpstp-core/tests/timeouts.rs::a_downstream_path_that_breaks_stops_within_1_s_and_ends_at_3_s`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)
- [`crates/udpstp-core/tests/timeouts.rs::an_upstream_client_stops_when_status_pdus_stop`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-17 {#RFC9946-5.1-17}

**Tested**

> The default Status PDU timeout MUST be no more than 1 second.

Proving tests:

- [`crates/udpstp-core/tests/timeouts.rs::a_downstream_path_that_breaks_stops_within_1_s_and_ends_at_3_s`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)
- [`crates/udpstp-core/tests/timeouts.rs::an_upstream_client_stops_when_status_pdus_stop`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/timeouts.rs)

## RFC9946-5.1-18 {#RFC9946-5.1-18}

**Tested**

> A network operator who is certain of the IP-Layer Capacity to be validated MAY start with a fixed-rate test at the IP-Layer Capacity and avoid activating the measurement load rate adjustment algorithm (see Section 8.1 of [RFC9097]).

Note: A Fixed-Rate Test under an Operator Key.

Proving tests:

- [`crates/udpstp/tests/interop.rs::unauthenticated_and_fixed_rate_tests_interoperate`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/interop.rs)
- [`crates/udpstp/tests/loopback.rs::fixed_rate_tests_complete_over_loopback`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)

## RFC9946-5.1-19 {#RFC9946-5.1-19}

**Operational**

> However, the stimulus for a diagnostic test (such as a subscriber request) strongly implies that there is no certainty, and the load adjustment algorithm is RECOMMENDED.

Note: An operator's choice of test.

## RFC9946-5.1-20 {#RFC9946-5.1-20}

**Operational**

> This specification MUST only be used in circumstances consistent with Section 10 (Security Considerations) of [RFC9097].

Note: A usage statement.

## RFC9946-5.3-1 {#RFC9946-5.3-1}

**Deviation**

> A REQUIRED mode with authentication during the Control phase (Test Setup and Test Activation exchanges).

Note: Authentication Mode 1; authMode field.

Recorded in [unauthenticated-mode](../conformance/deviations.md#unauthenticated-mode).

Proving tests:

- [`crates/udpstp/tests/interop.rs::our_client_completes_a_mode_1_downstream_test_against_obudpst`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/interop.rs)
- [`crates/udpstp/tests/loopback.rs::a_mode1_test_runs_with_a_toml_key_table_and_an_obudpst_key_file`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::mode1_tests_are_activated_in_both_directions`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::mode1_setup_between_our_cores_is_accepted`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3-2 {#RFC9946-5.3-2}

**Tested**

> An OPTIONAL mode with the additional authentication of the Status Feedback messages during the Data phase.

Note: Authentication Mode 2; authMode field.

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_mode2_test_completes_both_ways`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)

## RFC9946-5.3.1-1 {#RFC9946-5.3.1-1}

**Tested**

> In this mode, the client and the server SHALL be configured to use one of a number of shared secret keys, designated via the numeric keyId field (see Section 5.4).

Note: keyId field; the Key Table.

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_mode1_test_runs_with_a_toml_key_table_and_an_obudpst_key_file`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)

## RFC9946-5.3.1-2 {#RFC9946-5.3.1-2}

**Tested**

> This key SHALL be used as input to the KDF, as specified in Section 5.4.1, to obtain the actual keys used by the client and server for authentication.

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_drops_a_request_signed_with_the_shared_key_itself`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3.1-3 {#RFC9946-5.3.1-3}

**Tested**

> During the Control phase, the sender SHALL read the current system (wall-clock) time and populate the authUnixTime field and next calculate the 32-octet HMAC-SHA-256 hash of the entire PDU according to Section 6 of [RFC6234] (with the authDigest and checkSum preset to all zeroes).

Note: authUnixTime and authDigest fields.

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_answers_a_signed_activation_with_a_response_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::client_signs_its_activation_request_with_the_client_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_accepts_a_request_signed_with_the_client_key_and_answers_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_signs_its_setup_request_with_the_client_key_from_its_own_auth_unix_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-wire/tests/hmac_rfc4231.rs::hmac_sha256_matches_every_rfc_4231_test_case`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/hmac_rfc4231.rs)
- [`crates/udpstp-wire/tests/obudpst_control_kat.rs::our_wire_layer_reproduces_every_obudpst_pdu_from_its_fields`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/obudpst_control_kat.rs)

## RFC9946-5.3.1-L1 {#RFC9946-5.3.1-L1}

**Tested**

> The authDigest field is filled by the result, then the packet is sent to the receiver.

Note: authDigest field.

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::client_signs_its_activation_request_with_the_client_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_signs_its_setup_request_with_the_client_key_from_its_own_auth_unix_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3.1-4 {#RFC9946-5.3.1-4}

**Tested**

> The value in the authUnixTime field is a 32-bit timestamp, and a 10-second tolerance window (+/- 5 seconds) SHALL be used by the receiver to distinguish a subsequent replay of a PDU.

Note: authUnixTime field; the replay cache.

Conformance Records: [auth-time-window-inclusive-modulo-2-32](../conformance/interpretations.md#auth-time-window-inclusive-modulo-2-32), [replay-cache-for-setup-requests](../conformance/interpretations.md#replay-cache-for-setup-requests), [replay-cache-activation-keyed-on-sender](../conformance/interpretations.md#replay-cache-activation-keyed-on-sender), [replay-cache-lifetime-and-capacity](../conformance/interpretations.md#replay-cache-lifetime-and-capacity).

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_silently_drops_activations_that_fail_verification`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::server_accepts_an_activation_time_5_s_off`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::client_ignores_responses_that_fail_verification`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::clocks_five_seconds_apart_are_within_the_window`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_more_than_five_seconds_off`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::setup_is_accepted_across_the_2106_wraparound`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_ignores_a_response_more_than_five_seconds_off`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3.1-L2 {#RFC9946-5.3.1-L2}

**Not applicable**

> See Table 2 of [TR-471] for a recommended timestamp resolution.

Note: A pointer to TR-471's recommended timestamp resolution, not a behaviour; authUnixTime is whole seconds as the PDU defines it.

## RFC9946-5.3.1-5 {#RFC9946-5.3.1-5}

**Tested**

> Upon reception, the receiver SHALL validate the message PDU for correct length, validity of authDigest, immediacy of authUnixTime, and expected formatting (PDU-specific fields are also checked, such as protocol version).

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_silently_drops_activations_that_fail_verification`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::server_verifies_the_digest_over_the_bytes_received`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::client_ignores_responses_that_fail_verification`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)

## RFC9946-5.3.1-L3 {#RFC9946-5.3.1-L3}

**Tested**

> Validation of the authDigest requires that it be extracted from the PDU and the field, along with the checkSum field, zeroed prior to the Hashed Message Authentication Code (HMAC) calculation used for comparison (see Section 7.2 of [RFC9145]).

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_verifies_the_digest_over_the_bytes_received`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_accepts_a_request_whose_checksum_was_filled_after_the_digest`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-wire/tests/null_pdu.rs::a_signed_null_pdu_verifies_as_received`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/null_pdu.rs)
- [`crates/udpstp-wire/tests/obudpst_control_kat.rs::our_wire_layer_verifies_every_obudpst_digest`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/obudpst_control_kat.rs)

## RFC9946-5.3.1-6 {#RFC9946-5.3.1-6}

**Tested**

> If the validation fails, the receiver SHOULD NOT continue with the Control phase and SHOULD implement silent rejection (no further packets sent on the address/port pairs).

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_silently_drops_activations_that_fail_verification`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/key_table.rs::a_key_outside_its_accept_lifetime_is_an_authentication_failure`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/key_table.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_signed_from_a_different_shared_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_whose_key_id_it_does_not_have`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_more_than_five_seconds_off`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::by_default_authentication_failures_are_silent`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::a_failed_activation_request_stays_silent_in_troubleshooting_mode`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)

## RFC9946-5.3.1-L4 {#RFC9946-5.3.1-L4}

**Tested**

> The exception is when the testing hosts have been configured for troubleshooting Control phase failures and rejection messages will aid in the process.

Note: Permits reporting a failed validation when configured for troubleshooting.

Proving tests:

- [`crates/udpstp-core/tests/troubleshooting_mode.rs::an_unknown_key_id_is_answered_with_authfail`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::a_time_outside_the_window_is_answered_with_a_signed_authtime`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::an_unauthenticated_request_is_answered_with_authreq`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::an_authenticated_request_to_a_server_without_keys_is_answered_with_authnc`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)
- [`crates/udpstp-core/tests/troubleshooting_mode.rs::an_unsupported_mode_is_answered_with_authinv`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/troubleshooting_mode.rs)

## RFC9946-5.3.1-7 {#RFC9946-5.3.1-7}

**Tested**

> If the validation succeeds, the receiver SHALL continue with the Control phase and compose a successful response or a response indicating the error conditions identified (if any).

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::mode1_setup_between_our_cores_is_accepted`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3.1-8 {#RFC9946-5.3.1-8}

**Tested**

> This process SHALL be executed for the request and response in the Test Setup exchange, including the Null Request (Section 6) and the Test Activation exchange (Section 7).

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_answers_a_signed_activation_with_a_response_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/null_request.rs::a_mode_1_null_request_is_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/null_request.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::mode1_setup_between_our_cores_is_accepted`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.3.2-1 {#RFC9946-5.3.2-1}

**Tested**

> When using the optional authentication during the Data phase, authentication SHALL also be applied to the Status Feedback PDU (see Section 8.2).

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_mode2_test_completes_both_ways`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::a_client_s_early_stop_is_authenticated`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.3.2-2 {#RFC9946-5.3.2-2}

**Tested**

> The Status PDU sender SHALL 1) read the current system (wall-clock) time and populate the authUnixTime field, 2) calculate the authDigest field of the entire Status PDU (with the authDigest and checkSum preset to all zeroes), and 3) send the packet to the receiver.

Note: Status PDU authUnixTime and authDigest fields.

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_mode2_test_completes_both_ways`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)
- [`crates/udpstp-wire/tests/status_pdu.rs::a_signed_status_pdu_verifies_as_received`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)
- [`crates/udpstp-wire/tests/status_pdu.rs::verification_covers_every_byte_but_the_digest_and_checksum`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)

## RFC9946-5.3.2-L1 {#RFC9946-5.3.2-L1}

**Tested**

> The values of authUnixTime field and authDigest field are determined as defined by Section 5.3.1.

Proving tests:

- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.3.2-3 {#RFC9946-5.3.2-3}

**Tested**

> Upon reception, the receiver SHALL validate the message PDU for correct length, validity of authDigest, immediacy of authUnixTime, and expected formatting (PDU-specific fields are also checked, such as protocol version).

Proving tests:

- [`crates/udpstp-core/src/data_phase.rs::a_status_pdu_must_pass_every_mode_2_check`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/src/data_phase.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.3.2-L2 {#RFC9946-5.3.2-L2}

**Tested**

> Validation of the authDigest will require that it be extracted from the PDU and the field, along with the checkSum field, zeroed prior to the HMAC calculation used for comparison.

Proving tests:

- [`crates/udpstp-wire/tests/status_pdu.rs::a_signed_status_pdu_verifies_as_received`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)

## RFC9946-5.3.2-4 {#RFC9946-5.3.2-4}

**Tested**

> If the authentication validation fails, the receiver SHALL ignore the message.

Proving tests:

- [`crates/udpstp-core/tests/mode2_status.rs::failing_status_pdus_are_ignored_until_the_watchdog_ends_the_test`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.3.2-5 {#RFC9946-5.3.2-5}

**Tested**

> If the watchdog timer expires (due to successive failed validations), the test session will prematurely terminate (and no further load traffic SHALL be transmitted).

Proving tests:

- [`crates/udpstp-core/tests/mode2_status.rs::failing_status_pdus_are_ignored_until_the_watchdog_ends_the_test`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.3.2-6 {#RFC9946-5.3.2-6}

**Tested**

> If this optional mode has not been selected, then the keyId, authUnixTime, and authDigest fields of the Status PDU (see Section 8.2) SHALL be set to all zeroes.

Note: Status PDU keyId, authUnixTime and authDigest fields.

Conformance Records: [status-pdu-auth-fields-ignored-outside-mode-2](../conformance/interpretations.md#status-pdu-auth-fields-ignored-outside-mode-2).

Proving tests:

- [`crates/udpstp-core/tests/mode2_status.rs::in_mode_1_the_status_pdu_s_authentication_fields_are_zero`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)
- [`crates/udpstp-core/tests/status_pdus.rs::status_pdus_carry_the_auth_mode_and_zero_auth_fields`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/status_pdus.rs)
- [`crates/udpstp-core/tests/upstream.rs::the_server_sends_status_pdus_with_its_row`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/upstream.rs)

## RFC9946-5.4-1 {#RFC9946-5.4-1}

**Tested**

> The key table SHALL be used with the REQUIRED authentication mode and the OPTIONAL authentication mode (using the same key).

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_mode2_test_completes_both_ways`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)

## RFC9946-5.4-2 {#RFC9946-5.4-2}

**Tested**

> For authentication, this key SHALL only be used as input to the KDF, as specified in Section 5.4.1, to derive the actual keys used for authentication processing.

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_drops_a_request_signed_with_the_shared_key_itself`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.4-3 {#RFC9946-5.4-3}

**Tested**

> The key table SHALL have (at least) the following fields per Section 2 of [RFC7210]: * AdminKeyName * LocalKeyName * KDF * AlgID * Key * SendLifetimeStart * SendLifeTimeEnd * AcceptLifeTimeStart * AcceptLifeTimeEnd

Note: The TOML Key Table.

Conformance Records: [key-table-lifetimes](../conformance/interpretations.md#key-table-lifetimes), [key-table-alg-id](../conformance/interpretations.md#key-table-alg-id), [key-table-operator-extension](../conformance/interpretations.md#key-table-operator-extension).

Proving tests:

- [`crates/udpstp/tests/key_files.rs::the_server_loads_a_toml_key_table`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/key_files.rs)
- [`crates/udpstp-core/tests/key_table.rs::a_key_outside_its_accept_lifetime_is_an_authentication_failure`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/key_table.rs)
- [`crates/udpstp-core/tests/key_table.rs::a_key_is_accepted_on_the_edges_of_its_accept_lifetime`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/key_table.rs)
- [`crates/udpstp-core/tests/key_table.rs::a_shared_key_id_uses_the_row_valid_at_the_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/key_table.rs)
- [`crates/udpstp-core/tests/key_table.rs::the_client_sends_with_the_newest_valid_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/key_table.rs)

## RFC9946-5.4-4 {#RFC9946-5.4-4}

**Tested**

> The LocalKeyName SHALL be determined from the corresponding keyId field in the PDUs that follow.

Note: keyId field.

Conformance Records: [key-table-alg-id](../conformance/interpretations.md#key-table-alg-id).

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_whose_key_id_it_does_not_have`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.4.1-1 {#RFC9946-5.4.1-1}

**Tested**

> The KDF algorithm SHALL be a Key Derivation Function in Counter Mode, as specified in Section 4.1 of [NIST800-108].

Proving tests:

- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)

## RFC9946-5.4.1-2 {#RFC9946-5.4.1-2}

**Tested**

> The Pseudorandom Function (PRF) used in the KDF SHALL be HMAC-SHA-256, as defined in Section 6 of [RFC6234].

Proving tests:

- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)

## RFC9946-5.4.1-3 {#RFC9946-5.4.1-3}

**Tested**

> The KDF SHALL use the following parameters: * Kin (key-derivation key): The shared key as identified by the keyId field in the PDU. * Label: The fixed string "UDPSTP" (without quotes), encoded as a UTF-8 string, used to bind the derived keys to this specific protocol. * Context: The UTF-8 string representation of the authUnixTime field received in the very first Setup Request PDU sent from the client to the server. This ensures that the derived keys are unique to the session and tied to the temporal context of the initial setup exchange. The authUnixTime field serves as a nonce and is protected from modification by the HMAC-SHA-256 hash present in the authDigest field. * r: The length of the binary encoding of the counter SHALL be 32 (bits).

Note: The fixed input is laid out as Appendix A builds it.

Conformance Records: [kdf-appendix-a-layout](../conformance/interpretations.md#kdf-appendix-a-layout).

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_accepts_a_request_signed_with_the_client_key_and_answers_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_drops_a_request_whose_keys_come_from_another_auth_unix_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_signs_its_setup_request_with_the_client_key_from_its_own_auth_unix_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)

## RFC9946-5.4.1-4 {#RFC9946-5.4.1-4}

**Tested**

> The length of the binary encoding of the counter SHALL be 32 (bits).

Note: The r parameter.

Proving tests:

- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)

## RFC9946-5.4.1-5 {#RFC9946-5.4.1-5}

**Tested**

> The total derived key material SHALL be 512 bits (64 octets) in length.

Proving tests:

- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)

## RFC9946-5.4.1-6 {#RFC9946-5.4.1-6}

**Tested**

> The key material SHALL be structured as follows, from most significant bit (MSB) to least significant bit (LSB): * Client Authentication Key: 256 bits (32 octets); used for authenticating messages sent by the client. * Server Authentication Key: 256 bits (32 octets); used for authenticating messages sent by the server.

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_answers_a_signed_activation_with_a_response_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::client_signs_its_activation_request_with_the_client_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/mode2_status.rs::each_status_pdu_is_signed_with_its_sender_s_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/mode2_status.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_accepts_a_request_signed_with_the_client_key_and_answers_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_drops_a_request_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_signs_its_setup_request_with_the_client_key_from_its_own_auth_unix_time`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::client_ignores_a_response_signed_with_the_client_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)
- [`crates/udpstp-wire/tests/kdf_kat.rs::derived_keys_match_every_openssl_vector`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/kdf_kat.rs)
- [`crates/udpstp-wire/tests/obudpst_control_kat.rs::our_wire_layer_verifies_every_obudpst_digest`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/obudpst_control_kat.rs)

## RFC9946-5.4.1-7 {#RFC9946-5.4.1-7}

**Tested**

> If authentication of the initial Setup Request PDU received by the server fails, due to an invalid authDigest field, any and all derived keying material and keys SHALL be considered invalid.

Conformance Records: [derived-keys-depend-only-on-the-row-and-time](../conformance/interpretations.md#derived-keys-depend-only-on-the-row-and-time).

Proving tests:

- [`crates/udpstp-core/tests/setup_mode1.rs::server_silently_drops_a_setup_signed_from_a_different_shared_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.4.1-8 {#RFC9946-5.4.1-8}

**Tested**

> The key material derived from the initial Setup Request PDU, either at the client prior to transmission or at the server upon reception, SHALL be used for all subsequent PDUs sent between them for that test connection.

Conformance Records: [activation-auth-matches-setup](../conformance/interpretations.md#activation-auth-matches-setup).

Proving tests:

- [`crates/udpstp-core/tests/activation_mode1.rs::server_answers_a_signed_activation_with_a_response_signed_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/activation_mode1.rs::client_signs_its_activation_request_with_the_client_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/activation_mode1.rs)
- [`crates/udpstp-core/tests/setup_mode1.rs::server_accepts_a_request_signed_with_the_client_key_and_answers_with_the_server_key`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/setup_mode1.rs)

## RFC9946-5.5-L1 {#RFC9946-5.5-L1}

**Operational**

> Successful interaction with a local firewall assumes the firewall is configured to allow a host to open a bidirectional connection using unique source and destination addresses as well as port numbers (i.e., a 4-tuple) by sending a packet using that 4-tuple for a given transport protocol.

Note: Client-side firewall configuration.

## RFC9946-5.5-1 {#RFC9946-5.5-1}

**Operational**

> The firewall at the server MUST be configured with an open pinhole for the server IP address and standard UDP port number of the server.

Note: Server firewall configuration.

## RFC9946-5.5-2 {#RFC9946-5.5-2}

**Tested**

> Assuming that the firewall administration at the server does not allow an open UDP ephemeral port range, then the server MUST send a Null Request to the client from the ephemeral port number communicated to the client in the Test Setup Response.

Note: Null Request, sent from the Ephemeral Port.

Proving tests:

- [`crates/udpstp/tests/netns.rs::a_stateful_firewall_needs_only_the_standard_port_open`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/netns.rs)
- [`crates/udpstp-core/tests/null_request.rs::the_server_sends_a_null_request_after_the_setup_response`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/null_request.rs)

## RFC9946-5.5-L2 {#RFC9946-5.5-L2}

**Tested**

> If the server firewall administration allows an open UDP ephemeral port range, then the Null Request is not strictly necessary.

Note: Permits leaving out the Null Request.

Proving tests:

- [`crates/udpstp-core/tests/null_request.rs::a_forged_or_missing_null_request_changes_nothing`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/null_request.rs)

## RFC9946-5.6-1 {#RFC9946-5.6-1}

**Operational**

> The protocol MUST utilize the standard UDP checksum for all IPv4 and IPv6 datagrams it sends.

Note: The operating system's UDP stack computes the UDP checksum; udpstp never turns it off (no SO_NO_CHECK), and IPv6 requires it.

## RFC9946-5.6-L1 {#RFC9946-5.6-L1}

**Tested**

> All of the PDUs exchanged between the client and server support an optional header checksum that covers the various fields in the UDPSTP PDU (excluding the payload content of the Load PDU and, to be clear, also the IP and UDP headers).

Note: checkSum field.

Proving tests:

- [`crates/udpstp-wire/tests/load_pdu.rs::load_header_checksum_covers_the_header_only`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)

## RFC9946-5.6-L2 {#RFC9946-5.6-L2}

**Tested**

> The calculation is the same as the 16-bit one's complement Internet checksum used in the IPv4 packet Header Checksum specification (see Section 3.1 of [RFC0791]).

Note: checkSum field.

Proving tests:

- [`crates/udpstp-wire/tests/load_pdu.rs::internet_checksum_matches_the_rfc_1071_example`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)
- [`crates/udpstp-wire/tests/load_pdu.rs::internet_checksum_pads_an_odd_length`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)
- [`crates/udpstp-wire/tests/load_pdu.rs::internet_checksum_folds_every_carry`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)

## RFC9946-5.6-2 {#RFC9946-5.6-2}

**Operational**

> However, all UDPSTP datagrams transmitted via IPv4 or IPv6 SHALL include a standard UDP checksum to protect other potential recipients to whom a corrupted packet may be delivered.

Note: The operating system's UDP stack computes the UDP checksum; udpstp never turns it off (no SO_NO_CHECK), and IPv6 requires it.

## RFC9946-5.6-L3 {#RFC9946-5.6-L3}

**Not applicable**

> In the case of a nonstandard network API, one option to reduce processing overhead may be to restrict testing to only utilize a payload content of all zeros so that the UDP checksum calculation need not include it for Load PDUs.

Note: udpstp sends through the standard socket API.

## RFC9946-5.6-3 {#RFC9946-5.6-3}

**Tested**

> If a PDU sender is populating the checkSum field, it SHALL do so as the last step after the PDU is built in all other respects (with the checkSum field set to zero prior to the calculation).

Note: checkSum field.

Conformance Records: [zero-checksum-sent-as-ffff](../conformance/interpretations.md#zero-checksum-sent-as-ffff).

Proving tests:

- [`crates/udpstp-core/tests/control_checksum.rs::every_control_pdu_carries_a_checksum_that_verifies`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/downstream_load.rs::the_server_fills_the_header_checksum_when_configured`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/downstream_load.rs)
- [`crates/udpstp-core/tests/status_pdus.rs::status_pdus_carry_a_checksum_when_configured`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/status_pdus.rs)
- [`crates/udpstp-wire/tests/control_checksum.rs::a_zero_checksum_is_sent_as_ffff`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/control_checksum.rs)
- [`crates/udpstp-wire/tests/load_pdu.rs::load_header_checksum_covers_the_header_only`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)
- [`crates/udpstp-wire/tests/load_pdu.rs::a_zero_checksum_is_sent_as_all_ones`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)
- [`crates/udpstp-wire/tests/obudpst_control_kat.rs::our_wire_layer_reproduces_every_obudpst_pdu_from_its_fields`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/obudpst_control_kat.rs)
- [`crates/udpstp-wire/tests/status_pdu.rs::status_checksum_covers_the_whole_pdu`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)
- [`crates/udpstp-wire/tests/status_pdu.rs::a_zero_status_checksum_is_sent_as_all_ones`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)

## RFC9946-5.6-4 {#RFC9946-5.6-4}

**Tested**

> The PDU receiver SHALL subsequently verify the PDU checksum whenever checksum processing has been configured and the field is populated.

Note: checkSum field.

Proving tests:

- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_setup_request_is_dropped_before_authentication`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_setup_response_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_activation_request_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_activation_response_or_null_request_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::only_a_configured_receiver_verifies_and_only_a_populated_field`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/downstream_load.rs::the_client_verifies_a_populated_checksum_when_configured`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/downstream_load.rs)
- [`crates/udpstp-core/tests/status_pdus.rs::the_load_sender_verifies_a_populated_status_checksum`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/status_pdus.rs)
- [`crates/udpstp-wire/tests/load_pdu.rs::load_header_checksum_covers_the_header_only`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/load_pdu.rs)
- [`crates/udpstp-wire/tests/obudpst_control_kat.rs::the_checksum_build_s_pdus_carry_checksums_that_verify`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/obudpst_control_kat.rs)
- [`crates/udpstp-wire/tests/status_pdu.rs::status_checksum_covers_the_whole_pdu`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-wire/tests/status_pdu.rs)

## RFC9946-5.6-5 {#RFC9946-5.6-5}

**Tested**

> If PDU checksum validation fails, the PDU SHALL be discarded.

Proving tests:

- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_setup_request_is_dropped_before_authentication`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_setup_response_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_activation_request_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/control_checksum.rs::a_corrupted_activation_response_or_null_request_is_dropped`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/control_checksum.rs)
- [`crates/udpstp-core/tests/downstream_load.rs::the_client_verifies_a_populated_checksum_when_configured`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/downstream_load.rs)
- [`crates/udpstp-core/tests/status_pdus.rs::the_load_sender_verifies_a_populated_status_checksum`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/status_pdus.rs)

## RFC9946-5.6-6 {#RFC9946-5.6-6}

**Tested**

> Because of the redundancy when used in conjunction with authentication, it is OPTIONAL for a PDU sender to utilize the UDPSTP checkSum field.

Note: checkSum field.

Proving tests:

- [`crates/udpstp/tests/loopback.rs::a_test_activates_with_checksums_on_both_ends`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp/tests/loopback.rs)

## RFC9946-5.6-7 {#RFC9946-5.6-7}

**Tested**

> However, because authentication is not applicable to the Load PDU, the checkSum field SHALL be utilized by the sender whenever UDP data integrity may be uncertain (as outlined above).

Note: Load PDU checkSum field.

Proving tests:

- [`crates/udpstp-core/tests/downstream_load.rs::the_server_fills_the_header_checksum_when_configured`](https://github.com/pederbe/udpstp/blob/c88fe32e0973594682a069c58de24fd703714277/crates/udpstp-core/tests/downstream_load.rs)

