Skip to content

Commit 66e2697

Browse files
committedFeb 14, 2025
Code review.
1 parent be94f3c commit 66e2697

File tree

1 file changed

+74
-33
lines changed

1 file changed

+74
-33
lines changed
 

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

+74-33
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;
155-
uint8_t temp[kBlockSize];
156-
154+
size_t ciphertext_length = 0;
155+
uint8_t temp[kBlockSize] = { 0 };
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,26 +164,28 @@ 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);
176+
VerifyOrReturnError(ciphertext_length + out_length <= plaintext_length, CHIP_ERROR_INTERNAL);
176177
// Add the encrypted output, if any
177178
memcpy(&ciphertext[ciphertext_length], temp, out_length);
178179
ciphertext_length += out_length;
179180
}
180-
181+
181182
// The finish output should fit in the temp buffer
182183
size_t max_finish = PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm);
183184
VerifyOrReturnError(max_finish <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL);
184185

185186
// The finish may return the last part of the ciphertext
186187
status = psa_aead_finish(&operation, temp, max_finish, &out_length, tag, tag_length, &tag_out_length);
188+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
187189
VerifyOrReturnError(ciphertext_length + out_length <= plaintext_length, CHIP_ERROR_INTERNAL);
188190
// Add the encrypted output, if any
189191
memcpy(&ciphertext[ciphertext_length], temp, out_length);
@@ -205,9 +207,9 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
205207
VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT);
206208

207209
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
208-
psa_status_t status = PSA_SUCCESS;
209210
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
210-
size_t outLength;
211+
psa_status_t status = PSA_SUCCESS;
212+
size_t out_length;
211213

212214
status = psa_aead_decrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
213215
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
@@ -218,32 +220,71 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
218220
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
219221
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
220222

221-
if (aad_length != 0)
223+
if (0 == aad_length)
222224
{
223-
status = psa_aead_update_ad(&operation, aad, aad_length);
224-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
225+
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
225226
}
226227
else
227228
{
228-
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
229+
status = psa_aead_update_ad(&operation, aad, aad_length);
230+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
229231
}
230232

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

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

249290
return CHIP_NO_ERROR;

0 commit comments

Comments
 (0)