Skip to content

Commit ae03713

Browse files
[SL-UP] Adds support for PKCS7 padding in OTA flow (#511)
Co-authored-by: Restyled.io <[email protected]>
1 parent 6e4fd28 commit ae03713

File tree

6 files changed

+66
-10
lines changed

6 files changed

+66
-10
lines changed

scripts/tools/silabs/ota/crypto_utils.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,11 @@ def decrypt(self, ciphertext):
380380

381381
def encryptFlashData(nonce, key, data, imageLen):
382382
encyptedBlock = ''
383-
if (imageLen % 16) != 0:
384-
for x in range(16 - (imageLen % 16)):
385-
data = data + bytes([255])
386-
imageLen = len(data)
383+
block_size = 16
384+
# pad using PKCS#7 padding
385+
pad_len = block_size - (imageLen % block_size)
386+
data = data + bytes([pad_len] * pad_len)
387+
imageLen = len(data)
387388

388389
r = rijndael(key, block_size=16)
389390

src/platform/silabs/multi-ota/OTAFirmwareProcessor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ CHIP_ERROR OTAFirmwareProcessor::ProcessInternal(ByteSpan & block)
7272
}
7373

7474
OTATlvProcessor::vOtaProcessInternalEncryption(byteBlock);
75+
if (IsLastBlock() == true)
76+
{
77+
// Remove padding from the last block since if the file was padded, last block will contain padding bytes.
78+
VerifyOrReturnError(OTATlvProcessor::RemovePadding(byteBlock) == CHIP_NO_ERROR, CHIP_ERROR_WRONG_ENCRYPTION_TYPE,
79+
ChipLogError(SoftwareUpdate, "Failed to remove padding"));
80+
}
7581
block = byteBlock;
7682
#endif
7783

src/platform/silabs/multi-ota/OTAMultiImageProcessorImpl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,14 +427,13 @@ void OTAMultiImageProcessorImpl::HandleApply(intptr_t context)
427427
imageProcessor->mAccumulator.Clear();
428428

429429
ChipLogProgress(SoftwareUpdate, "HandleApply: Finished and Soft Reset initiated");
430-
430+
#if (defined(_SILICON_LABS_32B_SERIES_3) || defined(SLI_SI91X_MCU_INTERFACE)) && CHIP_PROGRESS_LOGGING
431+
osDelay(500); // sl-temp: delay for uart print before reboot
432+
#endif
431433
// This reboots the device
432434
#ifdef SLI_SI91X_MCU_INTERFACE // 917 SoC reboot
433435
chip::DeviceLayer::Silabs::GetPlatform().SoftwareReset();
434436
#else // EFR reboot
435-
#if defined(_SILICON_LABS_32B_SERIES_3) && CHIP_PROGRESS_LOGGING
436-
osDelay(100); // sl-temp: delay for uart print before reboot
437-
#endif
438437
CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();)
439438
#endif
440439
}

src/platform/silabs/multi-ota/OTATlvProcessor.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ CHIP_ERROR OTATlvProcessor::Process(ByteSpan & block)
5959
CHIP_ERROR status = CHIP_NO_ERROR;
6060
uint32_t bytes = chip::min(mLength - mProcessedLength, static_cast<uint32_t>(block.size()));
6161
ByteSpan relevantData = block.SubSpan(0, bytes);
62-
62+
if (mProcessedLength + bytes >= mLength)
63+
{
64+
mLastBlock = true;
65+
}
6366
status = ProcessInternal(relevantData);
6467
if (!IsError(status))
6568
{
@@ -86,6 +89,7 @@ void OTATlvProcessor::ClearInternal()
8689
mLength = 0;
8790
mProcessedLength = 0;
8891
mWasSelected = false;
92+
mLastBlock = false;
8993
#if OTA_ENCRYPTION_ENABLE
9094
mIVOffset = 0;
9195
#endif
@@ -148,5 +152,34 @@ CHIP_ERROR OTATlvProcessor::vOtaProcessInternalEncryption(MutableByteSpan & bloc
148152

149153
return CHIP_NO_ERROR;
150154
}
155+
156+
CHIP_ERROR OTATlvProcessor::RemovePadding(MutableByteSpan & block)
157+
{
158+
if (block.size() == 0)
159+
{
160+
ChipLogError(DeviceLayer, "Block size is zero, cannot unpad");
161+
return CHIP_ERROR_INVALID_ARGUMENT;
162+
}
163+
164+
uint8_t padLength = block.data()[block.size() - 1];
165+
if (padLength == 0 || padLength > block.size())
166+
{
167+
ChipLogError(DeviceLayer, "Invalid PKCS7 padding");
168+
return CHIP_ERROR_INVALID_ARGUMENT;
169+
}
170+
171+
// Verify padding bytes
172+
for (size_t i = 0; i < padLength; ++i)
173+
{
174+
if (block.data()[block.size() - 1 - i] != padLength)
175+
{
176+
ChipLogError(DeviceLayer, "PKCS7 padding verification failed");
177+
return CHIP_ERROR_INVALID_ARGUMENT;
178+
}
179+
}
180+
181+
block.reduce_size(block.size() - padLength);
182+
return CHIP_NO_ERROR;
183+
}
151184
#endif // OTA_ENCRYPTION_ENABLE
152185
} // namespace chip

src/platform/silabs/multi-ota/OTATlvProcessor.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,19 @@ class OTATlvProcessor
152152
void SetWasSelected(bool selected) { mWasSelected = selected; }
153153
bool WasSelected() { return mWasSelected; }
154154
bool IsValidTag(OTAProcessorTag tag);
155+
bool IsLastBlock() const { return mLastBlock; }
155156

156157
#ifdef OTA_ENCRYPTION_ENABLE
157158
CHIP_ERROR vOtaProcessInternalEncryption(MutableByteSpan & block);
159+
/**
160+
* @brief Remove padding from the given block.
161+
* This is necessary to remove any padding that might have been added during encryption.
162+
*
163+
* @param block The block of data to remove padding from.
164+
* @return CHIP_NO_ERROR on success, or an error code if padding removal fails.
165+
* @note The method assumes the block is padded using PKCS7 padding.
166+
*/
167+
CHIP_ERROR RemovePadding(MutableByteSpan & block);
158168
#endif
159169

160170
protected:
@@ -199,8 +209,9 @@ class OTATlvProcessor
199209
uint32_t mProcessedLength = 0;
200210
bool mWasSelected = false;
201211
ProcessDescriptor mCallbackProcessDescriptor = nullptr;
212+
bool mDescriptorProcessed = false;
213+
bool mLastBlock = false;
202214
OTADataAccumulator mAccumulator;
203-
bool mDescriptorProcessed = false;
204215
};
205216

206217
} // namespace chip

src/platform/silabs/multi-ota/SiWx917/OTAWiFiFirmwareProcessor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ CHIP_ERROR OTAWiFiFirmwareProcessor::ProcessInternal(ByteSpan & block)
6363
}
6464

6565
OTATlvProcessor::vOtaProcessInternalEncryption(byteBlock);
66+
if (IsLastBlock() == true)
67+
{
68+
// Remove padding from the last block since if the file was padded, last block will contain padding bytes.
69+
VerifyOrReturnError(OTATlvProcessor::RemovePadding(byteBlock) == CHIP_NO_ERROR, CHIP_ERROR_WRONG_ENCRYPTION_TYPE,
70+
ChipLogError(SoftwareUpdate, "Failed to remove padding"));
71+
}
6672
block = byteBlock;
6773
#endif // OTA_ENCRYPTION_ENABLE
6874

0 commit comments

Comments
 (0)