Reordering new API's that have a libctx, propq

Richard Levitte levitte at
Sun Sep 6 06:02:50 UTC 2020

There are many red herrings in here, and I would argue that trying to
be too uniform in the way you think about all functions may be
harmful, because not all functions are classified the same.

We cannot deny that many of our interfaces have an OOP flair.  We may
be programming in C, but we very obviously have that kind of pattern,
a "poor man's OOP" in C.  So speaking about our interfaces in OOP
terms is not far fetched, as long as we keep in mind that we can only
take the argument so far.

I would argue that EVP_XXX_get_whatever() / EVP_XXX_get_whatever() are
classic accessors, and I assume that we have all been brought up with
the description of "this" as the hidden first argument to any class
method in C++, so it's not very far fetched to emulate that in C by
making the instance you want details from or change details of as the
(explicit) first argument.

I would further argue that EVP_XXX_fetch() is a constructor (of an
instance of EVP_XXX), and that with the assumption that there is no
"this" in a constructor, the discussion about the arguments and their
order must be different.

What I hear, even though not in such terms, is an argument of the
what the library context is and how that should affect the interface.
In relation to EVP_XXX_fetch(), it seems to be more of a factory (or
strictly speaking, the pool of resources, with hidden factory
functions), and depending on the factory model you lean on, it might
or might not be sensible to have it as first argument.  My you, I'm
trying quite hard to see it from a fresh user experience (as far as I
can imagine it...  after all, 20ish years with my fingers deep in
OpenSSL entrails makes you not so fresh).

I think, BTW, that this really comes down to how we view the library
context.  So far, I've seen all these interpretations (not all said
explicitly, but clearly visible in code or how we argue about it):

- framework
- scope (I'm unsure if that differs much from framework)
- factory / factory pool
- bag of resources

Personally, I have zero problems viewing it as all of these combined,
but that requires us to be clear on how it's used in different places.


On Sat, 05 Sep 2020 23:18:21 +0200,
Tim Hudson wrote:
> On Sun, Sep 6, 2020 at 6:55 AM Richard Levitte <levitte at> wrote:
>     I'd rank the algorithm name as the most important, it really can't do
>     anything of value without it.
> It also cannot do anything without knowing which libctx to use. Look at the implementation.
> Without the libctx there is no "from-where" to specify. 
> This is again hitting the concept of where do things come from and what is a default.
> Once "global" disappears as such, logically everything comes from a libctx.
> Your argument is basically "what" is more important than "from" or "where".
> And the specific context here is where you see "from" or "where" can be defaulted to a value so it
> can be deduced so it isn't (as) important in the API.
> That would basically indicate you would (applying the same pattern/rule in a different context)
> change:
> int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out);
> To the following (putting what you want as the most important rather than from):
> int EVP_PKEY_get_int_param(char *key_name, EVP_PKEY *pkey, int *out);
> Or pushing it right to the end after the output parameter:
> int EVP_PKEY_get_int_param(char *key_name, int *out,EVP_PKEY *pkey);
> The context of where things come from is actually the most critical item in any of the APIs we
> have.
> Even though what you want to get from where you want to get it is in the point of the API call you
> need to specify where from first as that context sets the frame of the call.
> Think of it around this way - we could have an implementation where we remember the last key that
> we have used and allow you to simply indicate you use the last key or if we didn't want the last
> key used to be able to specify it via a non-NULL pointer. This isn't that unusual an API but not
> something I'm suggesting we add - just trying to get the point across that you are still thinking
> of global and libctx as something super special with an exception in its handling rather than
> applying a general rule which is pretty much what we use everywhere else.
> And in which case where you generally don't provide a reference as there is some default meaning
> for it in general and can provide a reference for that sort of API would this make sense to you:
> int EVP_PKEY_get_int_param(char *key_name, int *out,EVP_PKEY *pkey);
> If pkey is NULL then you use the last key that you referenced, if it is not then you use the
> specified pkey. For the application the specific key_name is the most important thing (using your
> argument that basically states the "what" is what counts). 
> I would suggest that you really would still want to place the EVP_PKEY first - even if you had a
> defaulting mechanism of referring to the last key used. Conceptually you always have to have
> knowledge of from-where when you are performing a function. And that *context* is what is the most
> important.
> Tim.
Richard Levitte         levitte at
OpenSSL Project

More information about the openssl-project mailing list