Disable loading of unprotected credentials from PKCS#12 files.#31
Disable loading of unprotected credentials from PKCS#12 files.#31martin-barta-sie wants to merge 1 commit intosiemens:masterfrom
Conversation
- containers with **empty password** are **rejected** if a nonempty password is provided as parameter (i.e. the empty password can no longer be used to circumvent UTA-protection) - containers that don't have private keys encrypted with the same algorithm that is used by "storage" functions (e.g. `CREDENTIALS_save_dv`) are **rejected**
There was a problem hiding this comment.
Update: Meanwhile I learned from Benjamin what that background of these checks is. So okay to have them, but not by default.
Sorry to say, but I see little sense in the two restrictions added in this PR.
What does it help if an application refuses to load certain types of PKCS#12 files?
The files are in storage anyway, so an attacker can just use them and load their contents using some other software (such as vanilla OpenSSL), learn their contents, and potentially do havoc with them.
Moreover, the new checks are are not acceptable as mandatory checks because they (needlessly) restrict the general usability of PKCS#12 loading, so if you really want to keep them, make them somehow optional.
| { | ||
| LOG(FL_WARN, "Unencrypted PKCS#12 file%s%s", for_str, desc_str); | ||
| pass = ""; | ||
| LOG(FL_WARN, "Rejecting unencrypted PKCS#12 file%s%s", for_str, desc_str); |
There was a problem hiding this comment.
FL_WARN -> FL_ERR, if this case is really considered an error, but see below.
| LOG(FL_WARN, "Unencrypted PKCS#12 file%s%s", for_str, desc_str); | ||
| pass = ""; | ||
| LOG(FL_WARN, "Rejecting unencrypted PKCS#12 file%s%s", for_str, desc_str); | ||
| return 0; |
There was a problem hiding this comment.
This PR does not really do what is given it is description.
It rejects PKCS#12 not having a password even if the password provided by the caller is empty or no password was given by the caller. This is too much of a restriction.
In the cases just described, you can give a warning if wanted, but do not stop with an error. Otherwise, this library can no more be used to handle PKCS#12 files that (possibly for a good reason) are not password-protected.
|
|
||
| pass = tpass; | ||
|
|
||
| if(0 is_eq algo_allowed(p12, pass, len, NID_aes_256_cbc)) |
There was a problem hiding this comment.
I wonder about the strange - and not very readable - way of checking a Boolean (return) value here and at many other places. Better use if(not algo_allowed(...))
There was a problem hiding this comment.
Here you hard-coded NID_aes_256_cbc, but our PR description says
"the same algorithm that is used by "storage" functions (e.g. CREDENTIALS_save_dv)".
Instead, you should define a symbolic name for this algorithm and use it in the code where appropriate in order to prevent (future) inconsistencies.
There was a problem hiding this comment.
The algo check must not be made mandatory because otherwise general usability of PKCS#12 loading is hampered.
| desired algorithm. */ | ||
| /* Iterates over all keybags in the file but only looks inside Shrouded keybags. Returns 1 if the desired algorithm | ||
| and no other was found, 0 otherwise. */ | ||
| static int algo_allowed(const PKCS12* p12, const char* pass, int passlen, int desired_algo_nid) |
There was a problem hiding this comment.
better: static bool algo_allowed(...) to point out that the result is Boolean
and use false and true rather than 0 and 1 for Boolean values below.
| { | ||
| continue; | ||
| } | ||
| if(!bags) |
| found_desired_algo = 1; | ||
| continue; | ||
| } | ||
| sk_PKCS7_pop_free(auth_safes, PKCS7_free); |
|
|
||
| static int password_callback(char* buf, int bufsiz, int verify, void* cb_tmp) | ||
| { | ||
| if(0 == buf || bufsiz <= 0 || 0 == cb_tmp) |
There was a problem hiding this comment.
Better move the checks on buf and bufsiz below into if(password not_eq 0) {
because they are needed only in this case.
| } | ||
|
|
||
|
|
||
| static int bag_get_pkey_algo(const PKCS12_SAFEBAG *bag, const char *pass, int passlen) |
There was a problem hiding this comment.
pass and passlen are unused, so remove them from the function parameter list.
| } | ||
|
|
||
|
|
||
| static int bags_get_pkey_algo(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen, int desired_algo_nid) |
There was a problem hiding this comment.
pass and passlen are effectively unused, so remove them from the function parameter list.
| return encnid; | ||
| } | ||
|
|
||
| return NID_undef; |
There was a problem hiding this comment.
Is it really justified to return ID_undef for all other cases, i.e. pbenid != NID_pbes2?
If you, add a comment why.
|
I suggest making the implementation and use of the two new checks on PKCS#12 files dependent on a compile-time flag that is not set by default but set for S2L2 Linux, e.g. |
password is provided as parameter (i.e. the empty password can no longer
be used to circumvent UTA-protection)
that is used by "storage" functions (e.g.
CREDENTIALS_save_dv) arerejected