Skip to content

Commit 0b598de

Browse files
committedFeb 14, 2025
Code review.
1 parent be94f3c commit 0b598de

File tree

1 file changed

+68
-32
lines changed

1 file changed

+68
-32
lines changed
 

‎src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp

+68-32
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,16 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
106106
const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
107107
uint8_t * tag, size_t tag_length)
108108
{
109-
ChipLogDetail(Crypto, "~~~ AES_CCM_encrypt, pl:%u", (unsigned)plaintext_length);
110109
VerifyOrReturnError(IsBufferNonEmpty(nonce, nonce_length), CHIP_ERROR_INVALID_ARGUMENT);
111110
VerifyOrReturnError(IsValidTag(tag, tag_length), CHIP_ERROR_INVALID_ARGUMENT);
112111
VerifyOrReturnError((ciphertext != nullptr && plaintext != nullptr) || plaintext_length == 0, CHIP_ERROR_INVALID_ARGUMENT);
113112
VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT);
114113

115114
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
116-
psa_status_t status = PSA_SUCCESS;
117115
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
118-
size_t out_length = 0;
119-
size_t tag_out_length = 0;
116+
psa_status_t status = PSA_SUCCESS;
117+
size_t out_length = 0;
118+
size_t tag_out_length = 0;
120119

121120
status = psa_aead_encrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
122121
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
@@ -127,14 +126,14 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
127126
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
128127
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
129128

130-
if (aad_length != 0)
129+
if (0 == aad_length)
131130
{
132-
status = psa_aead_update_ad(&operation, aad, aad_length);
133-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
131+
ChipLogDetail(Crypto, "AES_CCM_encrypt: Using aad == null path");
134132
}
135133
else
136134
{
137-
ChipLogDetail(Crypto, "AES_CCM_encrypt: Using aad == null path");
135+
status = psa_aead_update_ad(&operation, aad, aad_length);
136+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
138137
}
139138

140139
if (0 == plaintext_length)
@@ -147,13 +146,14 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
147146
// psa_aead_update() requires use of the macro PSA_AEAD_UPDATE_OUTPUT_SIZE to determine the output buffer size.
148147
// For AES-CCM, PSA_AEAD_UPDATE_OUTPUT_SIZE will round up the size to the next multiple of the block size (16).
149148
// If the ciphertext length is not a multiple of the block size, we will encrypt in two steps, first with the
150-
// block_aligned_length, and then with a rounded up partial_block_length, where a temporary buffer will be used for the output.
149+
// block_aligned_length, and then with a rounded up partial_block_length, where a temporary buffer will be used for the
150+
// output.
151151
constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES);
152152
size_t block_aligned_length = (plaintext_length / kBlockSize) * kBlockSize;
153153
size_t partial_block_length = plaintext_length % kBlockSize;
154-
size_t ciphertext_length = 0;
154+
size_t ciphertext_length = 0;
155155
uint8_t temp[kBlockSize];
156-
156+
157157
// Make sure the calculated block_aligned_length is compliant with PSA's output size requirements.
158158
VerifyOrReturnError(block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, block_aligned_length),
159159
CHIP_ERROR_INTERNAL);
@@ -164,20 +164,20 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
164164
VerifyOrReturnError(out_length == block_aligned_length, CHIP_ERROR_INTERNAL);
165165
ciphertext_length += out_length;
166166

167-
if(partial_block_length > 0)
167+
if (partial_block_length > 0)
168168
{
169169
// The update output should fit in the temp buffer
170170
size_t max_output = PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, partial_block_length);
171-
VerifyOrReturnError(max_output <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL);
172171

173172
// Add the non-aligned end of the plaintext
174-
status = psa_aead_update(&operation, &plaintext[block_aligned_length], partial_block_length, temp, max_output, &out_length);
173+
status =
174+
psa_aead_update(&operation, &plaintext[block_aligned_length], partial_block_length, temp, max_output, &out_length);
175175
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
176176
// Add the encrypted output, if any
177177
memcpy(&ciphertext[ciphertext_length], temp, out_length);
178178
ciphertext_length += out_length;
179179
}
180-
180+
181181
// The finish output should fit in the temp buffer
182182
size_t max_finish = PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm);
183183
VerifyOrReturnError(max_finish <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL);
@@ -205,9 +205,9 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
205205
VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT);
206206

207207
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
208-
psa_status_t status = PSA_SUCCESS;
209208
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
210-
size_t outLength;
209+
psa_status_t status = PSA_SUCCESS;
210+
size_t out_length;
211211

212212
status = psa_aead_decrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
213213
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
@@ -218,32 +218,68 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
218218
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
219219
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
220220

221-
if (aad_length != 0)
221+
if (0 == aad_length)
222222
{
223-
status = psa_aead_update_ad(&operation, aad, aad_length);
224-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
223+
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
225224
}
226225
else
227226
{
228-
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
227+
status = psa_aead_update_ad(&operation, aad, aad_length);
228+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
229229
}
230230

231-
if (ciphertext_length != 0)
231+
if (0 == ciphertext_length)
232232
{
233-
status = psa_aead_update(&operation, ciphertext, ciphertext_length, plaintext,
234-
PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, ciphertext_length), &outLength);
235-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
236-
237-
plaintext += outLength;
238-
239-
status = psa_aead_verify(&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &outLength, tag,
240-
tag_length);
233+
status = psa_aead_verify(&operation, nullptr, 0, &out_length, tag, tag_length);
241234
}
242235
else
243236
{
244-
status = psa_aead_verify(&operation, nullptr, 0, &outLength, tag, tag_length);
245-
}
237+
// psa_aead_update() requires use of the macro PSA_AEAD_UPDATE_OUTPUT_SIZE to determine the output buffer size.
238+
// For AES-CCM, PSA_AEAD_UPDATE_OUTPUT_SIZE will round up the size to the next multiple of the block size (16).
239+
// If the plaintext length is not a multiple of the block size, we will encrypt in two steps, first with the
240+
// block_aligned_length, and then with a rounded up partial_block_length, where a temporary buffer will be used for the
241+
// output.
242+
constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES);
243+
size_t block_aligned_length = (ciphertext_length / kBlockSize) * kBlockSize;
244+
size_t partial_block_length = ciphertext_length % kBlockSize;
245+
size_t plaintext_length = 0;
246+
uint8_t temp[kBlockSize];
247+
248+
// Make sure the calculated block_aligned_length is compliant with PSA's output size requirements.
249+
VerifyOrReturnError(block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, block_aligned_length),
250+
CHIP_ERROR_INTERNAL);
251+
252+
// Add the aligned part of the ciphertext
253+
status = psa_aead_update(&operation, ciphertext, block_aligned_length, plaintext, block_aligned_length, &out_length);
254+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
255+
VerifyOrReturnError(out_length == block_aligned_length, CHIP_ERROR_INTERNAL);
256+
plaintext_length += out_length;
257+
258+
if (partial_block_length > 0)
259+
{
260+
// The update output should fit in the temp buffer
261+
size_t max_output = PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, partial_block_length);
246262

263+
// Add the non-aligned end of the ciphertext
264+
status =
265+
psa_aead_update(&operation, &ciphertext[block_aligned_length], partial_block_length, temp, max_output, &out_length);
266+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
267+
// Add the decrypted output, if any
268+
memcpy(&plaintext[plaintext_length], temp, out_length);
269+
plaintext_length += out_length;
270+
}
271+
272+
// The finish output should fit in the temp buffer
273+
size_t max_verify = PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm);
274+
VerifyOrReturnError(max_verify <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL);
275+
276+
// Complete verification
277+
status = psa_aead_verify(&operation, temp, max_verify, &out_length, tag, tag_length);
278+
// Add the decrypted output, if any
279+
memcpy(&plaintext[plaintext_length], temp, out_length);
280+
plaintext_length += out_length;
281+
VerifyOrReturnError(ciphertext_length == plaintext_length, CHIP_ERROR_INTERNAL);
282+
}
247283
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
248284

249285
return CHIP_NO_ERROR;

0 commit comments

Comments
 (0)