Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ICD] Add Nonce validation to Check-In protocol and parsing unit tests #31080

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/protocols/secure_channel/CheckinMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,25 @@ CHIP_ERROR CheckinMessage::ParseCheckinMessagePayload(const Crypto::Aes128KeyHan
}

// Read decrypted counter and application data
counter = Encoding::LittleEndian::Get32(appData.data());
static_assert(sizeof(CounterType) == sizeof(uint32_t), "Expect counter to be 32 bits for correct decoding");
CounterType tempCounter = Encoding::LittleEndian::Get32(appData.data());

// TODO : Validate received nonce by calculating it with the hmacKeyHandle and received Counter value
// Validate that the received nonce is correct
{
uint8_t calculatedNonceBuffer[CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES] = { 0 };
Encoding::LittleEndian::BufferWriter writer(calculatedNonceBuffer, sizeof(calculatedNonceBuffer));

ReturnErrorOnFailure(GenerateCheckInMessageNonce(hmacKeyHandle, tempCounter, writer));

// Validate received nonce is the same as the calculated
ByteSpan nonce = payload.SubSpan(0, CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES);
VerifyOrReturnError(memcmp(nonce.data(), calculatedNonceBuffer, sizeof(calculatedNonceBuffer)) == 0, CHIP_ERROR_INTERNAL);
}

// We have successfully decrypted and validated Check-In message
// Set output values

counter = tempCounter;
// Shift to remove the counter from the appData
memmove(appData.data(), sizeof(CounterType) + appData.data(), appDataSize);
appData.reduce_size(appDataSize);
Expand Down
7 changes: 5 additions & 2 deletions src/protocols/secure_channel/CheckinMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,16 @@ class DLL_EXPORT CheckinMessage
* @param[in] hmac128KeyHandle Key handle with which to verify the received nonce in the check-in payload (using HMAC).
* @param[in] payload The received payload to decrypt and parse
* @param[out] counter The counter value retrieved from the payload
* If an error occurs, no value will be set.
* @param[in,out] appData The optional application data decrypted. The input size of appData must be at least the
* size of GetAppDataSize(payload) + sizeof(CounterType), because appData is used as a work buffer for the decryption process.
* The output size on success will be GetAppDataSize(payload).
* size of GetAppDataSize(payload) + sizeof(CounterType), because appData is used as a work
* buffer for the decryption process. The output size on success will be GetAppDataSize(payload).
mkardous-silabs marked this conversation as resolved.
Show resolved Hide resolved
* If an error occurs, appData might countain data, but the data CANNOT be used since we were not able to validate it.
*
* @return CHIP_ERROR_INVALID_MESSAGE_LENGTH if the payload is shorter than the minimum payload size
* CHIP_ERROR_BUFFER_TOO_SMALL if appData buffer is too small
* CHIP_ERROR_INVALID_ARGUMENT if the provided arguments cannot be used to parse the Check-In message
mkardous-silabs marked this conversation as resolved.
Show resolved Hide resolved
* CHIP_ERROR_INTERNAL if we were not able to decrypt or validate the Check-In message
*/
static CHIP_ERROR ParseCheckinMessagePayload(const Crypto::Aes128KeyHandle & aes128KeyHandle,
const Crypto::Hmac128KeyHandle & hmacKeyHandle, ByteSpan & payload,
Expand Down
42 changes: 42 additions & 0 deletions src/protocols/secure_channel/tests/CheckIn_Message_test_vectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,45 @@ const CheckIn_Message_test_vector vector5 = { .key = kKey5,
.payload_len = sizeof(kPayload5) };

const CheckIn_Message_test_vector checkIn_message_test_vectors[]{ vector1, vector2, vector3, vector4, vector5 };

/**
* Invalid Counter / Nonce Match vector
*/

const uint8_t kInvalidNonceKey[] = {
0xca, 0x67, 0xd4, 0x1f, 0xf7, 0x11, 0x29, 0x10, 0xfd, 0xd1, 0x8a, 0x1b, 0xf9, 0x9e, 0xa9, 0x74
};

const uint8_t kInvalidNonceApplicationData[] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6c,
0x6f, 0x6e, 0x67, 0x75, 0x65, 0x72, 0x20, 0x6c, 0x6f, 0x6e, 0x67,
0x75, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67 };

const uint8_t kInvalidNonceNonce[] = { 0x06, 0x34, 0x67, 0x6e, 0xa6, 0xe0, 0x70, 0x7b, 0x7a, 0xd7, 0x81, 0x4f, 0xf8 };

const uint8_t kInvalidNonceCiphertext[] = { 0x29, 0x5b, 0x18, 0xd1, 0x9a, 0x23, 0xb2, 0xe4, 0xfa, 0xdf, 0x82, 0x92,
0x53, 0x51, 0x7f, 0xf3, 0xc9, 0x1d, 0x9d, 0x50, 0xd6, 0x62, 0x42, 0x03,
0x35, 0x01, 0xaa, 0x23, 0xad, 0x19, 0xcb, 0x6f, 0x5b, 0xee, 0x56, 0xb3 };

const uint8_t kInvalidNonceMic[] = {
0xd5, 0x8a, 0x92, 0x2b, 0x66, 0x44, 0x89, 0x3e, 0x66, 0x31, 0x8b, 0xb5, 0x53, 0x79, 0x24, 0x8b
};

const uint8_t kInvalidNoncePayload[] = { 0x06, 0x34, 0x67, 0x6e, 0xa6, 0xe0, 0x70, 0x7b, 0x7a, 0xd7, 0x81, 0x4f, 0xf8,
0x29, 0x5b, 0x18, 0xd1, 0x9a, 0x23, 0xb2, 0xe4, 0xfa, 0xdf, 0x82, 0x92, 0x53,
0x51, 0x7f, 0xf3, 0xc9, 0x1d, 0x9d, 0x50, 0xd6, 0x62, 0x42, 0x03, 0x35, 0x01,
0xaa, 0x23, 0xad, 0x19, 0xcb, 0x6f, 0x5b, 0xee, 0x56, 0xb3, 0xd5, 0x8a, 0x92,
0x2b, 0x66, 0x44, 0x89, 0x3e, 0x66, 0x31, 0x8b, 0xb5, 0x53, 0x79, 0x24, 0x8b };

const CheckIn_Message_test_vector invalidNonceVector = { .key = kInvalidNonceKey,
.key_len = sizeof(kInvalidNonceKey),
.application_data = kInvalidNonceApplicationData,
.application_data_len = sizeof(kInvalidNonceApplicationData),
.counter = 12,
.nonce = kInvalidNonceNonce,
.nonce_len = sizeof(kInvalidNonceNonce),
.ciphertext = kInvalidNonceCiphertext,
.ciphertext_len = sizeof(kInvalidNonceCiphertext),
.mic = kInvalidNonceMic,
.mic_len = sizeof(kInvalidNonceMic),
.payload = kInvalidNoncePayload,
.payload_len = sizeof(kInvalidNoncePayload) };
Loading
Loading