Skip to content

Commit 09cd327

Browse files
[nrf toup] [Crypto] Use single-part API for PSA AEAD functions.
Use single-part instead of multi-part API for PSA AEAD functions for AES_CCM encrypt and decrypt methods. This reduces amount of crypto interactions and keep the same functionality. Signed-off-by: Arkadiusz Balys <arkadiusz.balys@nordicsemi.no>
1 parent cb45489 commit 09cd327

1 file changed

Lines changed: 32 additions & 67 deletions

File tree

src/crypto/CHIPCryptoPALPSA.cpp

Lines changed: 32 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <lib/support/BufferWriter.h>
2929
#include <lib/support/BytesToHex.h>
3030
#include <lib/support/CHIPArgParser.hpp>
31+
#include <lib/support/CHIPMem.h>
3132
#include <lib/support/CodeUtils.h>
3233
#include <lib/support/SafeInt.h>
3334
#include <lib/support/SafePointerCast.h>
@@ -71,45 +72,28 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
7172

7273
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
7374
psa_status_t status = PSA_SUCCESS;
74-
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
75-
size_t out_length;
76-
size_t tag_out_length;
75+
size_t ciphertext_length = 0;
7776

78-
status = psa_aead_encrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
79-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
77+
// The PSA single-part API appends the tag to the ciphertext output buffer.
78+
// So we need to allocate a temporary buffer to hold ciphertext + tag, then split them.
79+
size_t total_output_size = plaintext_length + tag_length;
80+
uint8_t * temp_output = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(total_output_size));
81+
VerifyOrReturnError(temp_output != nullptr, CHIP_ERROR_NO_MEMORY);
8082

81-
status = psa_aead_set_lengths(&operation, aad_length, plaintext_length);
82-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
83+
status = psa_aead_encrypt(key.As<psa_key_id_t>(), algorithm, nonce, nonce_length, aad, aad_length, plaintext, plaintext_length,
84+
temp_output, total_output_size, &ciphertext_length);
8385

84-
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
85-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
86-
87-
if (aad_length != 0)
88-
{
89-
status = psa_aead_update_ad(&operation, aad, aad_length);
90-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
91-
}
92-
else
86+
if (status == PSA_SUCCESS && ciphertext_length == total_output_size)
9387
{
94-
ChipLogDetail(Crypto, "AES_CCM_encrypt: Using aad == null path");
95-
}
96-
97-
if (plaintext_length != 0)
98-
{
99-
status = psa_aead_update(&operation, plaintext, plaintext_length, ciphertext,
100-
PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, plaintext_length), &out_length);
101-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
102-
103-
ciphertext += out_length;
104-
105-
status = psa_aead_finish(&operation, ciphertext, PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &out_length, tag,
106-
tag_length, &tag_out_length);
107-
}
108-
else
109-
{
110-
status = psa_aead_finish(&operation, nullptr, 0, &out_length, tag, tag_length, &tag_out_length);
88+
// Copy ciphertext and tag to their respective output buffers
89+
if (plaintext_length > 0)
90+
{
91+
memcpy(ciphertext, temp_output, plaintext_length);
92+
}
93+
memcpy(tag, temp_output + plaintext_length, tag_length);
11194
}
112-
VerifyOrReturnError(status == PSA_SUCCESS && tag_length == tag_out_length, CHIP_ERROR_INTERNAL);
95+
chip::Platform::MemoryFree(temp_output);
96+
VerifyOrReturnError(status == PSA_SUCCESS && ciphertext_length == total_output_size, CHIP_ERROR_INTERNAL);
11397

11498
return CHIP_NO_ERROR;
11599
}
@@ -125,45 +109,26 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
125109

126110
const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length);
127111
psa_status_t status = PSA_SUCCESS;
128-
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
129-
size_t outLength;
130-
131-
status = psa_aead_decrypt_setup(&operation, key.As<psa_key_id_t>(), algorithm);
132-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
133-
134-
status = psa_aead_set_lengths(&operation, aad_length, ciphertext_length);
135-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
112+
size_t plaintext_length = 0;
136113

137-
status = psa_aead_set_nonce(&operation, nonce, nonce_length);
138-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
114+
// The PSA single-part API expects the tag to be appended to the ciphertext input buffer.
115+
// So we need to allocate a temporary buffer to hold ciphertext + tag.
116+
size_t total_input_size = ciphertext_length + tag_length;
117+
uint8_t * temp_input = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(total_input_size));
118+
VerifyOrReturnError(temp_input != nullptr, CHIP_ERROR_NO_MEMORY);
139119

140-
if (aad_length != 0)
141-
{
142-
status = psa_aead_update_ad(&operation, aad, aad_length);
143-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
144-
}
145-
else
120+
if (ciphertext_length > 0)
146121
{
147-
ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path");
122+
memcpy(temp_input, ciphertext, ciphertext_length);
148123
}
124+
memcpy(temp_input + ciphertext_length, tag, tag_length);
149125

150-
if (ciphertext_length != 0)
151-
{
152-
status = psa_aead_update(&operation, ciphertext, ciphertext_length, plaintext,
153-
PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, ciphertext_length), &outLength);
154-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
155-
156-
plaintext += outLength;
126+
status = psa_aead_decrypt(key.As<psa_key_id_t>(), algorithm, nonce, nonce_length, aad, aad_length, temp_input, total_input_size,
127+
plaintext, ciphertext_length, &plaintext_length);
157128

158-
status = psa_aead_verify(&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &outLength, tag,
159-
tag_length);
160-
}
161-
else
162-
{
163-
status = psa_aead_verify(&operation, nullptr, 0, &outLength, tag, tag_length);
164-
}
165-
166-
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
129+
chip::Platform::MemoryFree(temp_input);
130+
VerifyOrReturnError(status == PSA_SUCCESS && plaintext_length == ciphertext_length,
131+
(status == PSA_ERROR_INVALID_SIGNATURE) ? CHIP_ERROR_INVALID_SIGNATURE : CHIP_ERROR_INTERNAL);
167132

168133
return CHIP_NO_ERROR;
169134
}

0 commit comments

Comments
 (0)