wolfSSL releases a new product; wolfCOSE a zero alloc C embbedded COSE stack
71 points
7 hours ago
| 2 comments
| github.com
| HN
magicalhippo
5 hours ago
[-]
For those of us not in the loop, COSE[1] is CBOR Object Signing and Encryption, with CBOR being a binary JSON alternative. It is patterned off JOSE, the JSON standards which includes favorites like JWK.

[1]: https://www.rfc-editor.org/info/rfc9052/

reply
mgaunard
4 hours ago
[-]
so some sort of JWT alternative?
reply
SV_BubbleTime
1 hour ago
[-]
For the most part yes. JWT is a part of JOSE. For most things CBOR, think binary JSON.

I love me some CBOR, but Carl isn’t very adventurous in deviating from JSON (rightfully!) so I don’t expect a lot new in COSE if you have worked with JOSE.

Other than the tagged data types, the main inconpatibiiiry in CBOR to JSON is that CBOR map keys can be integers and in JSON must be strings.

reply
Neywiny
4 hours ago
[-]
2 things of notice in the readme as recently I've been in the efficient binary communication hunt:

1. .text size without clarifying the architecture, flags, and compiler is meaningless unless it's all rodata (and it's not)

2. Saying it takes 0 .bss and .data just means it allocates everything elsewhere and that can be helpful to know. Of course in compilation that'll also be dependent on how and for what it's built. To say it's zero alloc is incorrect or at best misleading. Here's a line of code that allocates a ton of stuff on the stack: https://github.com/wolfSSL/wolfCOSE/blob/b90b34abcba90aa7b8a... (previously pointed to another line but it was diluting my thesis). Anyone in embedded who's had to increase stack size to use a fancy function knows what I'm talking about. I'm looking at you, sscanf. Some of this code will allocate hundreds if not low thousands of bytes onto the stack. Which is maybe fine but don't say it's zero alloc just because it's all on the stack.

reply
nine_k
4 hours ago
[-]
I used to think that zero alloc = zero malloc, and all stack allocations are of statically known fixed size (you know the max call depth), so you can preallocate your stack area with some confidence, and will never run out of RAM.

The line you point at creates a single local pointer variable which is used in a tight loop; I don't see why won't it stay entirely in a register.

I'm not a real embedded developer though; last time I worked as one I worked on 8-bit devices. Maybe things changed since then.

reply
Neywiny
3 hours ago
[-]
I think your experience on 8 bit is just fine. Imagine, if you will, that your 8 bit micro has 2 kB of RAM, such as the famous atmega328p of the Arduino UNO. Sure the compiler might put it into a register, but it might not. It most certainly won't put where later in the code they define 3 66 byte arrays on the stack, but that's maybe ok. The question is: how do you preallocate the stack safely? How do you know exactly what your usage is without overflowing the stack and wreaking havoc? Maybe you profile the code with debug on and it's X bytes, then in release mode it's Y because register packing. This effects all code, but it's something we need to be cognizant of when we're trying to maximize the 2 kB. It's easy to throw kilobytes of stack around on desktop. Megabytes even. I've done gigabytes before for quick and dirty stuff. But on deeply embedded 8 bits, you don't want to be doing that.

My bigger point was that no malloc should be called "stack allocated" or some other more technically correct term. That tells me "hey if you run this code and something goes haywire, check your stack isn't corrupted" because 9 times out of ten for me that's the problem.

reply
AlotOfReading
2 hours ago
[-]
I don't know if you work in embedded, but I do and I've always understood zero alloc as "no dynamic allocation".

Most companies buying anything from WolfSSL will already be using a script or toolchain flags to validate stack usage. And if they don't, even embedded toolchains generally support canaries these days.

reply
amiga386
3 hours ago
[-]
That line allocates nothing. The function is their version of explicit_bzero(). The line casts an existing pointer passed in (e.g. pointing to something on the stack, or allocated by you) to a volatile pointer, which prevents the compiler from optimising away the writes.

Their README states "zero dynamic allocation: all operations use caller-provided buffers" and "Full COSE lifecycle in ~<1KB RAM (excluding wolfCrypt internals)", so I assume their stack usage is low too, because you (the caller) will own and have to allocate all buffers yourself

reply
Neywiny
2 hours ago
[-]
p is allocated on the stack
reply
amiga386
2 hours ago
[-]
So what? So is every automatic variable, including size_t i on the next line, unless it fits in a register. So are the platform-specific preserved registers across function calls, so are the function parameters if the platform declares they need to be on the stack, so is the return value in some cases. So is the preserved return address / link register for the function call.

Nobody is going to write code with exclusively global variables and GOTO instead of function calls, in order to use zero stack. And if they did, the other claim (no .data or .bss) would be untrue.

I'm not sure how you misinterpreted "Zero dynamic allocation" to mean "not even stack variables", because nobody would read it that way, and I don't think anyone sane would use software that promised it used no stack.

reply
wmwragg
4 hours ago
[-]
My understanding of zero alloc is that there are no heap allocations i.e. use of a form of malloc. At least that has always been my experience, use of the stack is perfectly fine
reply
Neywiny
3 hours ago
[-]
But it puts sizeable arrays on the stack. That's not really better since instead of an out of memory exception it'll just corrupt the stack of on the majority of embedded implementations that don't have hardware stack protection in use or available.
reply
dezgeg
3 hours ago
[-]
Some stricter interpretations also require that maximum stack usage can be statically analyzed (ie. no recursion, no function pointers, no VLAs/alloca).
reply