Skip to content

Commit 54e6cac

Browse files
Code review.
1 parent be94f3c commit 54e6cac

File tree

1 file changed

+58
-26
lines changed

1 file changed

+58
-26
lines changed

src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp

+58-26
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,14 @@ 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;
116+
psa_status_t status = PSA_SUCCESS;
118117
size_t out_length = 0;
119118
size_t tag_out_length = 0;
120119

@@ -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)
@@ -153,7 +152,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
153152
size_t partial_block_length = plaintext_length % kBlockSize;
154153
size_t ciphertext_length = 0;
155154
uint8_t temp[kBlockSize];
156-
155+
157156
// Make sure the calculated block_aligned_length is compliant with PSA's output size requirements.
158157
VerifyOrReturnError(block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, block_aligned_length),
159158
CHIP_ERROR_INTERNAL);
@@ -168,7 +167,6 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
168167
{
169168
// The update output should fit in the temp buffer
170169
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);
172170

173171
// Add the non-aligned end of the plaintext
174172
status = psa_aead_update(&operation, &plaintext[block_aligned_length], partial_block_length, temp, max_output, &out_length);
@@ -177,7 +175,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
177175
memcpy(&ciphertext[ciphertext_length], temp, out_length);
178176
ciphertext_length += out_length;
179177
}
180-
178+
181179
// The finish output should fit in the temp buffer
182180
size_t max_finish = PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm);
183181
VerifyOrReturnError(max_finish <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL);
@@ -205,9 +203,9 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
205203
VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT);
206204

207205
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
208-
psa_status_t status = PSA_SUCCESS;
209206
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
210-
size_t outLength;
207+
psa_status_t status = PSA_SUCCESS;
208+
size_t out_length;
211209

212210
status = psa_aead_decrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
213211
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
@@ -218,32 +216,66 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
218216
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
219217
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
220218

221-
if (aad_length != 0)
219+
if (0 == aad_length)
222220
{
223-
status = psa_aead_update_ad(&operation, aad, aad_length);
224-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
221+
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
225222
}
226223
else
227224
{
228-
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
225+
status = psa_aead_update_ad(&operation, aad, aad_length);
226+
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
229227
}
230228

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

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

249281
return CHIP_NO_ERROR;

0 commit comments

Comments
 (0)