Harden SPDM 1.4 PSK_FINISH opaque handling with core unit test coverage#3606
Harden SPDM 1.4 PSK_FINISH opaque handling with core unit test coverage#3606
PSK_FINISH opaque handling with core unit test coverage#3606Conversation
93d5603 to
ce5ae7d
Compare
PSK_FINISH opaque handling with core unit test coverage
| status = LIBSPDM_STATUS_INVALID_PARAMETER; | ||
| libspdm_release_sender_buffer (spdm_context); | ||
| goto error; | ||
| } |
There was a problem hiding this comment.
In current libspdm, we always use ASSERT for SPDM_MAX_OPAQUE_DATA_SIZE check.
You may search others, such as key_exchange, finish.
Why we have to add check here, in this psk_finish?
There was a problem hiding this comment.
Agree. For outbound requester input-size validation, key_exchange / psk_exchange / finish use LIBSPDM_ASSERT and do not return runtime INVALID_PARAMETER.
I will align psk_finish with existing style by removing the runtime check and keeping ASSERT-only
| if (requester_opaque_data_size != 0) { | ||
| status = LIBSPDM_STATUS_INVALID_PARAMETER; | ||
| libspdm_release_sender_buffer (spdm_context); | ||
| goto error; | ||
| } |
There was a problem hiding this comment.
Same question.
I think we need use a consistent way to decide when to check and when not to check.
Please refer to opaque data handling in other command.
There was a problem hiding this comment.
Agree. The requester_opaque_data == NULL && requester_opaque_data_size != 0 runtime error is also not used in peer commands.
I will remove this runtime check for consistency with existing requester command patterns.
| if (((spdm_context->connection_info.algorithm.other_params_support & | ||
| SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) | ||
| && (opaque_data_size != 0)) { | ||
| status = LIBSPDM_STATUS_INVALID_MSG_FIELD; | ||
| goto receive_done; | ||
| } |
There was a problem hiding this comment.
This is already checked in key_exchange. Why we need to check again?
There was a problem hiding this comment.
Agree this is redundant with current negotiated state handling and inconsistent with finish/key_exchange response parsing style.
I will remove this extra check to keep behavior/policy consistent.
|
|
||
| if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) { | ||
| if (opaque_data_size >= *responder_opaque_data_size) { | ||
| if (opaque_data_size > *responder_opaque_data_size) { |
There was a problem hiding this comment.
Good catch!
I notice finish has same issue.
There was a problem hiding this comment.
Thanks. Do you think we better create separate follow-up issue or propose "finish" fix within this PR ?
There was a problem hiding this comment.
I am OK to create another PR.
I just want to ensure 1) all issues are fixed, 2) the solution is consistent, especially the similar ones.
That is why I cross-check other commands.
There was a problem hiding this comment.
Thank you :) can we confirm also another cases?
- FINISH - what you found
libspdm/library/spdm_requester_lib/libspdm_req_finish.c
Lines 611 to 614 in 538d089
- KEY_EXCHANGE
libspdm/library/spdm_requester_lib/libspdm_req_key_exchange.c
Lines 728 to 731 in 538d089
- PSK_EXCHANGE
libspdm/library/spdm_requester_lib/libspdm_req_psk_exchange.c
Lines 459 to 462 in 538d089
| opaque_data_entry_size = 0; | ||
| } | ||
| spdm_response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size; | ||
| spdm_response_size = sizeof(spdm_psk_finish_response_t) + opaque_data_entry_size; |
| } | ||
|
|
||
| if ((opaque_data_size > SPDM_MAX_OPAQUE_DATA_SIZE) || | ||
| (opaque_data_size > max_opaque_data_size)) { |
There was a problem hiding this comment.
I am not sure how it is possible that (opaque_data_size > max_opaque_data_size).
I feel (opaque_data_size > SPDM_MAX_OPAQUE_DATA_SIZE) should be enough.
There was a problem hiding this comment.
I recommend keeping both checks:
SPDM_MAX_OPAQUE_DATA_SIZE: protocol/library upper bound
max_opaque_data_size: output-buffer capacity bound
They protect different constraints, so both are valid.
It can happen when the protocol limit and the actual buffer capacity are different.
SPDM_MAX_OPAQUE_DATA_SIZE is a global maximum allowed by libspdm/protocol.
max_opaque_data_size is how many bytes are currently free in this specific response buffer after headers.
So opaque_data_size may still be valid globally, but too large for the current output buffer.
Example: global max is 1024, but current buffer has only 80 bytes left; function generates 120 bytes. Then:
120 <= 1024 (passes global check)
120 > 80 (fails buffer-capacity check)
There was a problem hiding this comment.
I am looking at libspdm_psk_finish_rsp_opaque_data() API. opaque_data_size is an IN OUT.
opaque_data_size is already max_opaque_data_size on input.
The output opaque_data_size must be equal or smaller than the input size.
That is why I think it is impossible. Otherwise, the buffer overflow already happened.
There was a problem hiding this comment.
OK, I understand we want to assume IN OUT is working here, if it didn't then it is already too late to detect. I will remove this.
38d26ed to
08382fc
Compare
…erage - Harden requester/responder SPDM 1.4 PSK_FINISH opaque validation paths. - Align requester SPDM 1.4 opaque format negotiation setup in UT. - Keep core opaque boundary/error coverage: req cases 18/19 and rsp cases 17/18. - Remove optional requester cases 20/21 and related harness scaffolding. Signed-off-by: Cezary Zwolak <cezary.zwolak@intel.com>
08382fc to
be32879
Compare
Fix #3592.