NSS does not properly import or export pkcs12 files with large passwords and pkcs5v2 encoding.
Categories
(NSS :: Libraries, defect, P3)
Tracking
(Not tracked)
People
(Reporter: rrelyea, Assigned: rrelyea)
Details
Attachments
(1 file)
Traditionally NSS use PKCS5v1/PKCS12 kdfs when exporting PKCS#12 files as those are the standards used in the original DES, Triple-DES encodings. Modern tools have been moving to using PKCS5v2 and AES for the encoding. As part of the move to PKCS5v2 is a move to change the raw password from BMP encoding (subset of UCS2) to UTF8 encoding.
It turns out the spec is quite explicit about all aspects of the BMP encoding (byte order, including a 2 byte NULL termination, etc.) but does not clearly specify whether or not the UTF8 password should the NULL for PKCS5v2.
It turns out that in PKCS5v2, password is used as a key for the HMAC. If the password is less than the block size of the HMAC (typically 32 bytes for SHA265), then it doesn't matter because the password is expanded to the full length of the HMAC block with zero padding. The null termination simply becomes part of the padding and the KDF produces the same result whether or not NULL termination is used. If the total password is greater then the blocksize, however, the password is hashed once, and that hash because the key for the HMAC. Having an extra NULL byte in this case affects the value that is hashed. That means libraries which add a NULL won't interoperate with libraries that don't for password lengths greater than 31. It turns out openssl and gnutls do not add the NULL and NSS does.
In addition, on decrypt, NSS first encodes the password in UCS2 with a NULL, because the integrity Hash is still encoded using PKCS12 KDF. NSS takes the UCS2 password and recodes it to UTF8, but the function that did this has a bug there it's trying to guarrentee adding the NULL at the end, but it mistakenly trying to add a double NULL a the end. This means on decode we are passing a UTF8 string which has 2 NULLs and we'll fail to decrypt any pkcs12 file generate by any library (including NSS) with passwords of length greater than 30 bytes.
Evidently this has been known for a while, but not why: https://stafwag.github.io/blog/blog/2016/01/17/thunderbird-importing-s-slash-mime-certificate-failed/
This issue was first reported to us here:
https://bugzilla.redhat.com/show_bug.cgi?id=2041832
Assignee | ||
Comment 1•3 years ago
|
||
After some discussion (which you can see in the redhat bug). We determined that:
- The spec was ambiguous as to whether the NULL should be included UTF8. Even though it's clear is should be included in the BMP/UCS 2 case. The silence is a minor point for not including it, though it can go either way.
- Both openssl and gnutls tools do not include the NULL.
- In the case that matters, NSS is already self-broken (that is a pkcs12 file created by NSS in the failing case, will not be able to be imported by NSS itself either).
Given this we decided that it was probably safest for NSS to fix both the decrypt and encrypt case to not include the NULL. NOTE: while some of this is controlled by NSS supplied callbacks (conversion functions to and from UCS2/UTF8), some of it is determined by what the application passes in, so additional work may be necessary in the Firefox use case (Firefox, IIRC will pass in NULL terminated UCS2 directly, which means we just need to be consistent on how the UTF8 is handled).
Anyway we should discuss if this logic still works for Mozilla.
Comment 2•3 years ago
•
|
||
Bob - Do I understand right that the proposed change would fix a currently always-broken path in NSS, but also will break some (hopefully rare) existing PKCS#12 files which currently successfully in load in NSS?
Dana, Kai - Do you have any thoughts about the impact on Firefox or Thunderbird?
Updated•3 years ago
|
Assignee | ||
Comment 3•3 years ago
|
||
Dennis - No, there are not case the would successfully load today that would break. There may be some cases where a file exported by NSS may be successfully imported, but a new file exported by NSS won't be. I haven't tested the case of trying to import pkcs5v2 into windows.
-
Before the change, someone including a single 'NULL' in UTF8 won't be able to import into NSS. After the change, they still won't import. (this means NSS files exported before the change that can't import today, still won't import after the change).
Export | Import-> NSS before change NSS after change Uses NULL Doesn't Use NULL
V
NSS before change Fail Fail Success Fail
NSS after change Fail Success Fail Success
Uses NULL Fail Fail Success Fail
Doesn't USE NULL Fail Success Fail Success
We don't know of any applications that use NULL in UTF8 pkcs5v2. I haven't tested Windows. I think Windows can't or doesn't export with PKCS 5v2, so we really only need to test the import case.
Openssl and gnutls each don't use NULL, so NSS after the change NSS will have the same profile as those two libraries.
The problem only occurs for long passwords (>30 characters for SHA256, > 18 characters for SHA-1) with PKCS5v2 (AES or Camellia) exported files. Using 3DES or PKCS5v2 with short passwords would work in all cases in the table.
bob
Assignee | ||
Comment 4•3 years ago
|
||
Import
Export | NSS before change | NSS after change | Uses NULL | Doesn't Use NULL
------------------------------------------------------------------------------------------
NSS before change | Fail | Fail | Success | Fail
NSS after change | Fail | Success | Fail | Success
Uses NULL | Fail | Fail | Success | Fail
Doesn't USE NULL | Fail | Success | Fail | Success
Better formatted table from Comment 3
Comment 5•3 years ago
|
||
It seems like we might be able to do a "try it one way and fall back to the other if it doesn't work" approach in PSM, which is something we've done in the past with empty passwords, if I recall correctly (i.e. "does an empty password mean 0 bytes or does it mean two NULL bytes?")
Assignee | ||
Comment 6•3 years ago
|
||
It's a little trickier, because pkcs5v2 encodes the password differently from pkcs12/pkcs5v1, which means the application has to supply one encoding, and NSS has to convert to the other. So PSM would have to override that conversion and figure out which way it was supposed to be trying. Fortunately the NULL case isn't an issue because in pkcs5v2, no passord, password of '0', or even a password of '00', generates the same HMAC key and thus the same pbe.
Assignee | ||
Comment 7•3 years ago
|
||
Also I think the issue is windows importing our p12 file rather than us importing the windows. I don't think they've been encoded yet.
Assignee | ||
Comment 8•3 years ago
|
||
Don't use NULL when encoding UTF8 with pkcs5v2. Fix a bug here when converting from UCS2 to UTF8 we would add a double NULL when adding a NULL.
Updated•3 years ago
|
Comment 9•2 years ago
|
||
Description
•