libgoldilocks uses a pattern of "manifest array" typedefs for structures. Basically, a typedef is added for a struct that has a one element member. Something like this:
typedef struct foo_s {
} foo_s, foo_p[1];
There are two different positive reasons for using this pattern. First, when using a struct inside of another struct, if the member is one of these manifest arrays the struct will have its storage fully embedded inside of the enclosing struct, while still making it very clean to send the struct (and not a copy of it) as argument to functions. The other benefit is that when using the struct inside of a function, storage will automatically be allocated and deallocated, without explicit mallocs and frees.
These reasons are good for the purpose of the libgoldilocks primitives, primarily the goldilocks_448_point_p and goldilocks_448_scalar_p types. However, for libotr-ng, we have ended up with a LOT of places using this pattern as well, which doesn't work so well for a few reasons:
It bloats structures, making them less likely to fit in cache-lines
In many cases you need to copy data inside it, instead of assigning a pointer
You can't return the _p types
Having arguments with a specific length array is actually not supported in C, and causes splint warnings
It stops us from using custom allocation and cleaning functions (for example, if we want to allocate secret scalars in a high-security allocation arena, we can't do this, since they will always be allocated on the stack).
It's generally very confusing and hides what is happening
So, in order to fix this, this is the plan for how we will handle structs inside libotr-ng:
[ ] Remove most of the _p typedefs
[ ] Evaluate the right way of referring to each structure we use
[ ] Keep use of _p structs from libotr-ng, but potentially allocate them manually where we use them
libgoldilocks uses a pattern of "manifest array" typedefs for structures. Basically, a typedef is added for a struct that has a one element member. Something like this:
There are two different positive reasons for using this pattern. First, when using a struct inside of another struct, if the member is one of these manifest arrays the struct will have its storage fully embedded inside of the enclosing struct, while still making it very clean to send the struct (and not a copy of it) as argument to functions. The other benefit is that when using the struct inside of a function, storage will automatically be allocated and deallocated, without explicit
malloc
s andfree
s.These reasons are good for the purpose of the libgoldilocks primitives, primarily the goldilocks_448_point_p and goldilocks_448_scalar_p types. However, for libotr-ng, we have ended up with a LOT of places using this pattern as well, which doesn't work so well for a few reasons:
So, in order to fix this, this is the plan for how we will handle structs inside libotr-ng: