Since I will use the Linux's built-in crypto API for different purposes, I've been reading the sources carefully.
While attempting to understand what's going on, I have been struck by the instance handling part of the code.
The code is C, nevertheless this part is clearly object-oriented. Thus, when a user needs to perform some encryption, it will ask for the allocation of a transform instance which will involve the use of a particular algorithm in a particular encryption mode. The pair (algorithm, mode) will be handled this way in the crypto API :
The "pure" algorithm is stored in a struct crypto_alg structure.
The mode is defined through a struct crypto_template which says how to initialize a specific struct crypto_instance
Here are the definitions of the structures crypto_instance and crypto_spawn
struct crypto_instance {
struct crypto_alg alg;
/*
* The alg struct will be filled according to the template 'alloc' method
*/
struct crypto_template *tmpl;
struct hlist_node list;
void *__ctx[] CRYPTO_MINALIGN_ATTR;
};
struct crypto_spawn {
struct list_head list; // Embedded list_head to list the spawns
struct crypto_alg *alg; // Ptr to the underlying algorithm
struct crypto_instance *inst;
const struct crypto_type *frontend;
u32 mask;
}
Then, to me it looks like there is a kind of hierarchy : the crypto_spawn is here to manage the combination of an encryption mode defined by a crypto_instance and a pure encryption algorithm defined by a crypto_alg. In terms of model object, we can see that crypto_instance inherits crypto_alg and it is totally reasonable to consider "cascading" templates over a given algorithm.
The thing I don't understand is why the crypto_spawn and the crypto_instance structures are not merged together. This question has even more struck me when I met the instance allocation code :
struct crypto_instance *crypto_alloc_instance(const char *name,
struct crypto_alg *alg)
{
struct crypto_instance *inst;
struct crypto_spawn *spawn;
int err;
inst = crypto_alloc_instance2(name, alg, 0);
if (IS_ERR(inst))
goto out;
spawn = crypto_instance_ctx(inst);
/*
* This line expands to :
* spawn = inst->__ctx;
*/
err = crypto_init_spawn(spawn, alg, inst,
CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
if (err)
goto err_free_inst;
return inst;
err_free_inst:
kfree(inst);
inst = ERR_PTR(err);
out:
return inst;
}
The crypto_alloc_instance2 just allocates the physical memory to hold the structure and fills the inst->alg structure's name fields :
void *crypto_alloc_instance2(const char *name, struct crypto_alg *alg,
unsigned int head)
{
struct crypto_instance *inst;
char *p;
int err;
p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn),
GFP_KERNEL);
if (!p)
return ERR_PTR(-ENOMEM);
inst = (void *)(p + head);
/* Names editing + error checking ... */
return p;
}
As you can see, a spawn is "physically" bound to an instance, so why are they defined separately. I find it very troubling when then trying to understand how the whole thing is mixed and handled.
At the moment, the only reason that came to my mind is that it allows the API to opacify the underlying algorithm from the crypto_instance object. But since the last bytes of the structure will easily give the spawn through the spawn = inst->__ctx instruction, it is not very very opaque.
As a recall after this bunch of code and comments, the question is :
What reasons lead the developers to make this "separation" between the instance and the spawn structure ?
Thanks in advance for any enlightenment !
Note : I added the tag cryptography because I thought that developers interested in this tag have probably already taken a look into the Linux Kernel crypto part.
Related
I'm working on a high-reliance implementation of an algorithm for an embedded system.
in main.c:
//.. in main()
int queue_buffer[QUEUE_LEN + 1] = { 0 };
Queue queue;
queue_init(&queue, QUEUE_LEN, queue_buffer);
do_things_on_queue(&queue);
//.. in main()
in queue.c:
void queue_init(Queue *q, int len, int *data) {
q->head = 0;
q->tail = 0;
q->len = len;
q->data = data; // an array of length `len + 1`
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int *data;
} Queue;
I would like to 1. have main.c to not know about Queue; and 2. not use malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
//.. in some function
Is it possible to modify queue_init in queue.cto achieve this in C99? If so, what's the best approach?
Tentative Solutions
I am aware of the technique discussed in this post yet they seems unfeasible without using malloc. I know for sure that I will simultaneously have 4 queues at most. This makes me think that I could declare a memory pool for the queues as a static global array of queues of size 4. Is it ok to use global variables in this case?
#KamilKuk suggested to just have queue_init to return the structure itself since QUEUE_LEN is known at compile time. This requires the following:
in queue.c:
Queue queue_init(void) {
Queue q;
q.head = 0;
q.tail = 0;
q.len = QUEUE_LEN;
for (int i=0; i < QUEUE_LEN; i++)
q.data[i] = 0;
return q;
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int data[QUEUE_LEN];
} Queue;
Queue queue_init(void);
This appears to greatly simplify the structure initialization.
However this does not solve the privacy problem, since main.c should know about Queue to initialize this struct.
Thank you.
I would like to 1. have main.c to not know about Queue; and 2. not use
malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue queue = queue_init(something_eventually);
do_things_with_queue(&queue);
//.. in some function
No, your objectives do not imply a solution as described. You cannot declare or use an object of type Queue anywhere that the definition of that type is not visible. That follows directly from the language's rules, but if you want a more meaningful justification then consider that even if main does not access any of the members of Queue, it still needs the definition simply to know how much space to reserve for one.
It's not obvious to me that it serves a useful purpose to make type Queue opaque in main.c (or anywhere), but if that's what you want then in that scope you can forward declare it, never define it, and work only with pointers to it:
typedef struct queue Queue;
// ...
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
For that to work without dynamic memory allocation, the pointed-to Queue objects must have static storage duration, but that does not mean that they need to be globals -- either in the sense of being accessible via a name with external linkage, or in the sense of being declared at file scope.
Additionally, you have the option of allocating the data arrays automatically, as in your example code, so as to not tie up that memory in queues when they are not in use. If you prefer, you can wrap that up in a macro or two for a bit of additional ease of use (left as an exercise).
For example,
queue.h
typedef struct queue Queue;
Queue *queue_init(int queue_size, int queue_data[]);
void queue_release(Queue *queue);
queue.c
#include "queue.h"
struct queue {
int head;
int tail;
int len;
int *data;
};
Queue *queue_init(int queue_len, int queue_data[]) {
// queue_pool has static storage duration and no linkage
static Queue queue_pool[4] = {{0}};
// Find an available Queue, judging by the data pointers
for (Queue *queue = queue_pool;
queue < queue_pool + sizeof(queue_pool) / sizeof(*queue_pool);
queue++) {
if (queue->data == NULL) {
// This one will do. Initialize it and return a pointer to it.
queue->head = 0;
queue->tail = 0;
queue->len = queue_len;
queue->data = queue_data;
return queue;
}
}
// no available Queue
return NULL;
}
void queue_release(Queue *queue) {
if (queue) {
queue->data = NULL;
}
}
main.c
// ... in some function
int queue_data[SOME_QUEUE_LENGTH];
Queue *queue = queue_init(SOME_QUEUE_LENGTH, queue_data);
do_things_with_queue(queue);
queue_release(queue);
// ...
Of course, if you prefer, you can put the queue data directly into the queue structure, as in your tentative solution, and maybe provide a flag there to indicate whether the queue is presently in use. That would relieve users of any need to provide storage, at the cost of tying up the storage for all the elements of all the queues for the whole duration of the program.
The best way to do this is to pass a buffer and its size to the init function, exactly as you already have.
It is a very bad idea to worry about calling a function versus having the data fixed at compile time. Both the execution time and code size for a tiny initialization like this is negligible. Making your code interface awkward just to save a few instructions at startup is not just a waste of effort, it makes the code hard to maintain and risks introducing bugs.
There are a number of embedded systems or libraries that provide a macro which declares both the storage array and the control structure in one go and gives them a name which is known only to the library, and then you have to use a macro to generate the name every time you access the item. For an example of this you might look at osMailQDef in CMSIS-OS. I don't really recommend this method though. It is too easy to get wrong, whereas doing it the usual way is easy to read and any reviewer will be able to spot a mistake straight away.
I would typically do:
// queue.h
#define QUEUE_INIT(data, len) { .len = len, .data = data }
#define QUEUE_INIT_ON_STACK(len) QUEUE_INIT((char[len]){0}, len)
// main.c
static Queue queue = QUEUE_INIT_ON_STACK(QUEUE_LEN + 1);
As for PIMPL idiom, it's easy to implement with descriptors just like file descriptors in LINUX, especially when the count is static.
// queue.h
typedef Queue int;
void do_things_with_queue(Queue);
// queue.c
struct RealQueue { stuff; };
static struct RealQeueue arr[4] = { stuff };
static struct RealQeueue *get_RealQueue(Queue i) {
assert(0 <= i && i < sizeof(arr)/sizeof(*arr));
return &arr[i];
}
void do_things_with_queue(Queue i) {
struct RealQueue *queue = get_RealQueue(i);
}
// main.c
static Queue queue = 1;
// etc.
Or you can break all hell and synchronize alignment between source and header file:
// queue.h
struct Queue {
// This has to be adjusted __for each compiler and environment__
alignas(60) char data[123];
};
#define QUEUE_INIT() { 0xAA, 0xBB, etc.. constant precomputed data }
// queue.c
struct RealQeueue { stuff; };
static_assert(alingof(struct RealQueue) == alignof(struct Queue), "");
static_assert(sizeof(struct RealQueue) == sizeof(struct Queue), "");
void do_things_with_queue(Queue *i) {
struct RealQueue *queue = (struct RealQueue*)i->data;
}
I am working with the library libusb which is working nicely, but now I am trying to use its structures in a structure of my own. I think the problem is just the way I copy the structures, so there is probably no need to understand how libusb works.
I have my structure containing libusb structures:
struct device {
libusb_device *device_handled;
libusb_device_handle *handle;
int port[7];
};
typedef struct device device;
and my function:
int myfunction(device *device_element)
{
libusb_device *tempdevice;
libusb_device_handle *temphandle;
device_element = malloc(sizeof(device));
//my code here where I use tempdevice and temphandle
(&device_element)->device_handled = tempdevice;
(&device_element)->handle = temphandle;
}
The error issued come from the two last lines and I don't really understand why.
‘device_element’ is a pointer; did you mean to use ‘->’?
(&device_element)->handle = temphandle;
^~
->
you don't need to add & before device_element because malloc returns a pointer to the allocated structure. So just use:
(device_element)->device_handled = tempdevice;
(device_element)->handle = temphandle;
You don't need the & operator there.
Just use
device_element->device_handled = tempdevice;
device_element->handle = temphandle;
I'm not even sure how to properly formulate question about this.
I'm writing a library where I have multiple implementations (multiple libraries out of one). I want to hide as much as possible, if not all, implementation details from client app, in order to write an app disregarding implementation details.
It's all fine when implementation is contained within one function. However, often I need to instantiate a struct from library, do something to it with a function from library, resume writing app as normal, and then return to a function from library with data from previous function from library.
Struct details are important ONLY to library functions. I don't need to see or touch those from client application apart from passing them around because of this.
So, is there a way to hide struct details from client app and still be able to use it or if there's another way of doing this by some form of encapsulation or maybe even some kind of data (globals?) visible only to library?
Here's my lame illustration example with code:
/*
library_private.h
*/
#if (A)
{
struct mystruct_t {
A *something;
}
}
#else
struct mystruct_t {
B *something;
}
#endif
/*
library_public.h
*/
struct mystruct_t;
/*
library.c
*/
struct mystruct_t* create() {
struct mystruct_t *handle = malloc(sizeof(struct mystruct_t));
return handle;
}
/*
client.h
*/
struct mystruct_t;
/* but, I need a definition, so I have to repeat either from library_private.h */
/*
client.c
*/
int main(int argc, char const *argv[]) {
struct mystruct_t *handle = create();
/*...*/
something(handle);
return 0;
}
Cast to a void * when returning and back to structure mystruct_t just after passing into a function. This is not great as you will loose some of the compiler type checking.
client.c (or client.h) should include library_public.h. There is no need to have the structure definition. Only its declaration struct mystruct_t; is enough to use pointers to the structure. Of course, you cannot access its members, but that is exactly what you want in this case.
I am trying to implement a low-level thread lock without the use of dynamic memory allocation; this code will basically be used on a completely bare-bones kernel.
However, I am running into the problem of receiving a seg fault when I am trying to dereference a member inside this global static struct. My code is as such
My wrapper struct
/** LOCKING STRUCT & FUNCTIONS **/
struct lock {
int free;
struct thread_list* wait_list;
struct thread* current_holder;
};
The nested struct(intended as a linked list sort of deal)
struct thread_list {
struct thread *head;
};
And the member inside this list
struct thread {
void *top; // top of the stack for this thread
void *sp; // current stack pointer for this thread (context)
void (*start_func)(void *);
void *arg;
int state;
int exit_value;
struct thread *join_thread;
struct thread *next_thread;
int id;
};
The method I'm trying to implement is as such
void lock_init (struct lock *lk) {
lk->free = 1; //Set lock as free
struct thread_list waiting = lk->wait_list; //Get waitlist, works fine
waiting->head = NULL; //Set waitlist's head to null, SEGFAULTS HERE
}
I am not super proficient at C, but I can't seem to figure out the correct methodology/syntax to make my code work like this.
struct thread_list waiting = lk->wait_list; //Get waitlist, works fine
waiting->head = NULL; //Set waitlist's head to null, SEGFAULTS HERE
waiting is not a struct pointer but a struct variable . To access member using it you need to use . operator -
waiting.head = NULL;
Or to use -> operator declare it as a struct pointer .
I'm playing with integrating the gssapi into node.js. Im not sure how to represent this:
The gss_init_sec_context function contains many struct based parameters, some of which are nested pretty deeply. For example this struct:
typedef struct gss_ctx_id_struct
{
gss_OID mech;
#ifdef USE_KERBEROS5
struct _gss_krb5_ctx_struct *krb5;
#endif
} gss_ctx_id_desc;
So based on this I'm guessing I need to implement some kind of Structure (with ref-struct) to represent the krb5 pointer (since kerberos5 is being used). So I looked at this _gss_krb_ctx_struct and saw this...
typedef struct _gss_krb5_ctx_struct {
Shishi *sh;
Shishi_ap *ap;
Shishi_tkt *tkt;
Shishi_key *key;
gss_name_t peerptr;
int acceptor;
uint32_t acceptseqnr;
uint32_t initseqnr;
OM_uint32 flags;
int reqdone;
int repdone;
} _gss_krb5_ctx_desc, *_gss_krb5_ctx_t;
Where Shishi is a pointer to a library, and shishi_ap appears to be a pointer to a function. I'm not sure how to implement these things in node-ffi. Can someone give me some guidance here?