Following from #13190, it was suggested that we can also work on platform hooks for multi-part AES-CCM*, so that callers that cannot present a contiguous frame can offload to platform implementations / crypto accelerators. In the existing implementation for example, MLE presents its payload as a chain of Message buffers, which means it cannot use a platform one-shot hook and falls back to the software engine.
There are three issues I wanted to get consensus and review on:
1. Fixing the operation at Start
AesCcm::Engine currently takes operation input per payload chunk and always produces the tag through
Finalize. There are some constraints with this approach given PSA and mbedTLS requirements on multi-part AEAD operations.
For this piece, I have a draft PR ready: #13485
2. Payload output can trail payload input
AesCcm::Engine::AddPayload assumes that a payload fed in yields its output immediately, so callers pass one buffer as both input and output. It seems like block-cipher AEAD cannot promise that, since:
There are two approaches we can use here:
- 2a. Require full output on every call and let the platform do buffering. This doesn't seem possible over plain PSA multi-part AEAD, since the implementation would have to produce output that the backend hasn't given it yet.
- 2b. Mirror PSA, and let the hook consume all input and reports how much output it produced. The trailing piece can arrive with a later
UpdatePayload call, or with Finish / Verify.
The second approach 2b. keeps the platform layer simple, and lets us hide the reassembly complexity inside the AesCcm engine.
We could implement a new:
otError otPlatCryptoAesCcmUpdatePayload(otCryptoContext *aContext,
const uint8_t *aInput, uint32_t aInputLength,
uint8_t *aOutput, uint32_t aOutputSize,
uint32_t *aOutputLength);
AddPayload can return a "written" count, and the software engine can advance both input and output together. This shouldn't change anything with our existing contract, but a change is some stack usage for multi-part operations, since it needs to feed the payload in configurable slices, copy each slice of output and hold one more block for the trailing bytes that arrive with Finish or Verify.
3. Should default one-shot be built on the multi-part hooks?
The comment raised near the end of #13190 said: we could clean up the architecture by providing an OT_TOOL_WEAK default implementation for otPlatCryptoAesCcmProcessOneShot built on top of the multi-part API. Platforms would then have the flexibility to either provide their own optimized one-shot implementation or simply fall back to the default/weak implemenation.
My question is for the default weak implementation only. otPlatCryptoAesCcmProcessOneShot directly calls the platform's single shot AEAD entry point. We still want to default to that in case the new PLATFORM_MULTI_PART config is not enabled right?
Following from #13190, it was suggested that we can also work on platform hooks for multi-part AES-CCM*, so that callers that cannot present a contiguous frame can offload to platform implementations / crypto accelerators. In the existing implementation for example, MLE presents its payload as a chain of Message buffers, which means it cannot use a platform one-shot hook and falls back to the software engine.
There are three issues I wanted to get consensus and review on:
1. Fixing the operation at
StartAesCcm::Enginecurrently takes operation input per payload chunk and always produces the tag throughFinalize. There are some constraints with this approach given PSA and mbedTLS requirements on multi-part AEAD operations.For this piece, I have a draft PR ready: #13485
2. Payload output can trail payload input
AesCcm::Engine::AddPayloadassumes that a payload fed in yields its output immediately, so callers pass one buffer as both input and output. It seems like block-cipher AEAD cannot promise that, since:psa_aead_updatemay return fewer output bytes than it consumed.PSA_AEAD_UPDATE_OUTPUT_SIZErequires an output buffer sized by an implementation-defined macro rather than by the input length.psa_aead_finish/psa_aead_verifyboth carry any trailing partial blocks.There are two approaches we can use here:
UpdatePayloadcall, or withFinish/Verify.The second approach 2b. keeps the platform layer simple, and lets us hide the reassembly complexity inside the
AesCcmengine.We could implement a new:
AddPayloadcan return a "written" count, and the software engine can advance both input and output together. This shouldn't change anything with our existing contract, but a change is some stack usage for multi-part operations, since it needs to feed the payload in configurable slices, copy each slice of output and hold one more block for the trailing bytes that arrive withFinishorVerify.3. Should default one-shot be built on the multi-part hooks?
The comment raised near the end of #13190 said:
we could clean up the architecture by providing an OT_TOOL_WEAK default implementation for otPlatCryptoAesCcmProcessOneShot built on top of the multi-part API. Platforms would then have the flexibility to either provide their own optimized one-shot implementation or simply fall back to the default/weak implemenation.My question is for the default weak implementation only.
otPlatCryptoAesCcmProcessOneShotdirectly calls the platform's single shot AEAD entry point. We still want to default to that in case the newPLATFORM_MULTI_PARTconfig is not enabled right?