I'd say the problem is in the documentation (or lack thereof.) I've had to use OpenSSL before and the question of "should this thing be freed after I use it?" was
very common and only resolved fully by inspecting the source carefully. The heavy use of macros adds to the frustration; often, 3 or more layers of them hide the actual code that gets executed, making it hard to tell where things go.
On the other hand, I've also worked on some codebases that were very well-documented with respect to this: every function that either returned a pointer or accepted pointers made it clear if/when they should be freed (and if so, with what function.) One example of that looks like:
void /* OWN */ *some_func(void *a, void /* OWN */ *b, void */* OWN */*c);
And the "/* OWN */" are intended to be read like "const" and "static", so this says the function returns a pointer to an object whose ownership is transferred to the caller, its first parameter does not change owners, the second one does, and the third is a pointer to an array of pointers whose ownership is passed to the function. The accompanying comment then says what function should be used to free the returned pointer, and what function will be used (by other code) to eventually free b and c.