Comments (16)
Here are some useful resources:
@martindisch and me are attempting to do an implementation of AES-CCM in Rust using TinyCrypt as a reference implementation. Among other notable implementations there is aes-ccm from wpa_supplicant. @marcovr is also interested in OSCORE with libcose.
from libcose.
As discussed on IRC, I'd like to start restricting the crypto to algorithms to ciphers that allow some sort of incremental API. This to reduce the memory requirements for COSE (not needing a message twice in different structures). In practice, this restricts libcose to 'on-line' stream ciphers.
With AES-CCM, the message size and the length of the authenticated data needs to be known up front. For this reason, most crypto libraries don't implement it with an incremental API. If there is a library implementing CCM with an API where the authenticated data can be supplied with an incremental API, I can add support for it.
from libcose.
If there is a library implementing CCM with an API where the authenticated data can be supplied with an incremental API, I can add support for it.
Of course the library should be somewhat suitable for embedded applications (no malloc and such :) )
from libcose.
So far I've looked at
- libsodium: no streaming AEAD (and no AES-CCM, for that matter)
- wolfCrypt: no steraming AEAD (but given their interest in embedded applications, maybe they can be persuaded to add it)
- openssl: streaming AEAD (see example, esp. "zero or more calls" part) but not particularly embedded friendly
and thus did not find a suitable candidate.
That's by no means comprehensive, but if the trend continues it may mean that a libcose backend just can't implement the OSCORE mandatory-to-implement AES-CCM. Not too much of an issue IMO as that'll affect other crypto backends just as well -- and when one turns up to be usable, it can still be added to libcose.
from libcose.
Apologies, I mixed things up: AES-CCM is not available in OpenSSL in a streaming manner, only AES-GCM is. At least the payload length (possibly also the AAD length; wikipedia claims that, I don't quite see why from the tinycrypt implementation -- edit: readingccm_cbc_mac
with flag=1 which is set for AAD, now I do) needs to be known in advance for AES-CCM before the first AAD data is fed.
That, to me, begs the question of what the precise incremental API would be: Should it be
- the strong incremental form, where the length of the AAD and payload does not need to be known in advance (ruling out AES-CCM altogether), or
- the weak incremental form, where the caller needs to provide AAD and plaintext lengths, but can then feed the AAD and plaintext / ciphertext in chunk by chunk?
For OSCORE, I require only the weak version (because the AAD's length is effectively encoded inside itself somewhere in the first few bytes, and by the time I know the AAD's full length I also know the payload length, and only then can actually start feeding in AAD data). Are there cases in COSE where the implementation would profit from the strong form?
from libcose.
In case that helps with the incremental API part, here's the backend interface I'm currently describing: oscore_crypto_aead_encrypt_start and friends (the decrypt part is still in the nonincremental form). It's tailored towards what OSCORE needs (ie. knows payload and AAD lengths in advance, does AEAD in place and wants the tag after the ciphertext).
from libcose.
For OSCORE, I require only the weak version (because the AAD's length is effectively encoded inside itself somewhere in the first few bytes, and by the time I know the AAD's full length I also know the payload length, and only then can actually start feeding in AAD data).
This should be the same for COSE.
Are there cases in COSE where the implementation would profit from the strong form?
From the top of my head: no, don't think so.
The practical issue here is that for a crypto backend library, supporting this weak incremental form allows for easy misuse of the library by having a mismatch between the claimed AAD length (supplied with the first initialization call) and the actual supplied number of bytes for the AAD. I think COSE (and with that OSCORE) is more an exception where it is almost a hard requirement to use this weak incremental form.
To be honest, I don't mind wrapping the basic CBC-MAC and AES-CTR calls if that would allow libcose to support AES-CCM using the weak incremental form.
from libcose.
To be honest, I don't mind wrapping the basic CBC-MAC and AES-CTR calls if that would allow libcose to support AES-CCM using the weak incremental form.
Be careful as AES-CCM uses its own version of CBC-MAC and AES-CTR.
from libcose.
Be careful as AES-CCM uses its own version of CBC-MAC and AES-CTR.
I'm aware that I should carefully read the spec before attempting to implement this. I'd also like to have some tests against a known working AES-CCM implementation in the CI to validate the wrapping.
from libcose.
Here are some useful resources:
Thanks!
from libcose.
@martindisch and me are attempting to do an implementation of AES-CCM in Rust
I think that would make quite an interesting additional backend to libcose, and could be a practical example of the Rust backends libraries useful in RIOT which I'm looking for in RIOT-OS/RIOT#9799.
from libcose.
To propose a concrete way forward here, would this work for you?
- Add an API that reflects the weak incremental form, with roughly
init(*struct, algorithm, AEAD length)
,feed_aad(*struct, AAD bytes)
,{encrypt,decrypt}(*struct, source area, destination area, tag area)
- Backends are changed to the incremental API
- The old API can still be served by a three-line compatibility implementation if it was public
- Change internal users to the new API
- Some backends will initially not support incremental API well (ie. require contiguous memory input); they would need to resort to dynamic memory management (yikes I know, but it's only for the low-quality backends…) to build a scratch buffer into which the fed AAD parts are placed. If that's done in a clever fashion, it can be possible to avoid memory allocation if all the AAD happens to be fed in at a single feed call – but being clever here may not be worth it, as we're aiming for high-quality streamable backends anyway, and the dynamic memory part is more of a migration helper.
Having this library as a showcase may help making the case for AAD streaming at backend libraries (@danielinux, would wolfCrypt be able to accomodate this?).
from libcose.
* Add an API that reflects the weak incremental form, with roughly `init(*struct, algorithm, AEAD length)`, `feed_aad(*struct, AAD bytes)`, `{encrypt,decrypt}(*struct, source area, destination area, tag area)`
For the signing/verification I have something along these lines 80% ready somewhere. The main issue I had is that the context struct required for the crypto algorithm is not constant in size among the different algorithm. This resulted in a fairly complex structure where the crypto_sign
function 1. initializes the crypto alg, 2. calls a cose sign specific function, 3. the cose sign function calls a passed update()
call a number of times, 4. the crypto_sign
function finalizes the crypto alg and generates the signature.
Backends are changed to the incremental API
👍
The old API can still be served by a three-line compatibility implementation if it was public
Also 👍
Change internal users to the new API
Still good here. I do have to make an explicit choice here whether I want to consider the crypto API as public. On a related note, it might make sense to move the crypto multiplexing code to a separate project/library and reuse that for both libcose and your OSCORE work.
- Some backends will initially not support incremental API well (ie. require contiguous memory input); they would need to resort to dynamic memory management (yikes I know, but it's only for the low-quality backends…) to build a scratch buffer into which the fed AAD parts are placed. If that's done in a clever fashion, it can be possible to avoid memory allocation if all the AAD happens to be fed in at a single feed call – but being clever here may not be worth it, as we're aiming for high-quality streamable backends anyway, and the dynamic memory part is more of a migration helper.
Yeah, this is also what I concluded a while ago. I think some compile time setting to enable malloc()
/free()
usage is not necessarily a bad thing. This way more generic (non-embedded) crypto libs could also be supported.
from libcose.
from libcose.
Small detail on the API details: We may need to give the plain- and ciphertext locations at the initialization already – at least judging from the wolfSSL source of ChaCha20Poly1305 where those are processed before the AAD is processed. It's asking a bit more of the application (having the pointers ready and keeping them exclusive to the operation for the time feeding the AAD), but if it helps having more algorithms usable that way…
(I don't know ChaCha20Poly1305 well enough to know whether that's inherent to the algorithm or just an implementation choice of WolfCrypt, but either way, given that AEAD algorithm authors seem to rarely think of those concerns, the more defensive API seems appropriate).
from libcose.
With the #103 merged this can be closed. We may want to revisit the discussions had here when refactoring the interfaces to allow streaming AAD, and I might still update my tinydtls branch to add an alternative AES-CCM implementation (primarily depending on how to easiest get HKDF again), but the core of the issue is closed.
from libcose.
Related Issues (14)
- Apache 2.0/MIT/BSD/CC Licensing
- gh-pages out of date
- Finalize migration to tinycbor
- Check key ops
- Easier ECDSA handling HOT 1
- cose_sign_get_payload() HOT 1
- Missing C++ guards
- checklist v0.4 release
- Add external AAD test to sign and encrypt
- `cose_sign_verify_first` is untested
- Add direct KDFs HOT 4
- Behavior changes through tinyDTLS HOT 1
- mbedtls writes ECDSA signatures in ASN1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from libcose.