External resumption tokens don't work across processes
Categories
(NSS :: Libraries, defect, P2)
Tracking
(Not tracked)
People
(Reporter: mt, Unassigned)
References
Details
Bug 1399439 introduced the ability to externalize session storage. The idea was to provide a token that could be saved by an application rather than NSS. This would provide both privacy and performance benefits.
External storage of tokens would enable more granular control over session resumption, which has some privacy advantages as session resumption provides linkability.
This feature was also intended to enable more resumption because the tokens could be persisted to stores that are retained over longer periods. On mobile devices, this was supposed to provide significant benefits, because applications are frequently stopped and restarted to manage their battery impact.
While the privacy benefits still exist, the performance benefits are currently broken. Resumption tokens are not portable across processes. If resumption tokens were to be taken from one process and then later passed to another process, they would be accepted by NSS, but they would result in connection attempts failing.
The problem lies in the way that the master secret (or resumption secret) held in tokens is encoded when it is exported and imported. NSS holds the master secret as a symmetric key in a PKCS#11 token. Some tokens refuse to expose the raw value of keys, so when NSS wants to store a master secrets for resumption (in a ticket or its session database), it wraps the value as it exports it. The key that it uses to wrap the master secret is the problem.
NSS generates a wrapping key for each slot that holds a master secret. It does this the first time that it needs to wrap a key in that slot. This key is stored with the slot, but it is ephemeral: when the process is terminated, the key is gone.
The worst part is that when a wrapping key is regenerated in the new process, NSS could happily use the new value to unwrap resumption tokens. The wrapping key is different, so it garbles the master secret. The wrapping mechanism that NSS uses (by default triple-DES in ECB mode), doesn't have any integrity check, so NSS fails to notice that the master secret is garbled.
This isn't a guaranteed result. This only happens if the object ID of the newly created wrapping key matches the ID of the old one. If there is a mismatch, a debug build will crash with a fatal assertion and a release build should just not attempt resumption. In my testing, a collision on the object ID is moderately common, I'd estimate that it would happen around 1/4 invocations; it does seem highly situation-dependent.
It's also possible that an object ID mismatch could produce a key that is usable for the intended purpose.
If the object ID collides or a usable key is found, we only learn this when we get failures (SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE in TLS 1.3). On the plus side, for Firefox at least, this is one of the errors on the list of errors that will trigger another connection attempt.
Reporter | ||
Updated•6 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Description
•