Skip to content

Commit

Permalink
[ICD] Add Nonce validation to Check-In protocol and parsing unit tests (
Browse files Browse the repository at this point in the history
#31080)

* Add Nonce validation and parsing unit tests

* Add missing comments

* Remove unused test signature

* fix comment

* remove include

* fix comment
  • Loading branch information
mkardous-silabs authored Dec 19, 2023
1 parent 7f2b391 commit 9643ea4
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 116 deletions.
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
9 changes: 6 additions & 3 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). 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
* 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

0 comments on commit 9643ea4

Please sign in to comment.