OS Crypt Async
This directory contains the new version of OSCrypt
that supports asynchronous initialization and pluggable providers. It is intended to gradually replace os_crypt::OSCrypt
(AKA “OSCrypt Sync”) with a new version with improved capabilities.
Main interfaces
browser/
should only be included by code that lives in the browser process. An instance of OSCryptAsync
should be constructed and held in browser and is responsible for minting Encryptor
instances. //chrome holds a browser-wide instance that's accessible from g_browser_process
using os_crypt_async()
method.
GetInstance
can be called as many times as necessary to obtain instances of Encryptor
that should be used for encryption operations. Note that GetInstance
returns a base::CallbackListSubscription
whose destruction will cause the callback to never run. This should be stored with the same lifetime as the callback to ensure correct function. See documentation for base::CallbackList
for more on this.
When calling GetInstance
an Encryptor hint can be supplied. This can change the Encryption behavior of the resulting Encryptor instance, see encryptor.h
for details and see below. Note that all Encryptor
returned from the same instance of OSCryptAsync
will always be able to decrypt each other's data.
common/
can be included by any code in any process and allows Encryptor
instances to perform encrypt/decrypt operations. These EncryptString
and DecryptString
operations are sync and can be called on any thread, the same as with legacy os_crypt::OSCrypt
.
Encryptor
instances can be passed over mojo if necessary, as mojo traits exist to serialize and deserialize. If an Encryptor
instance is passed to a process then that process will be able to decrypt any data encrypted with OSCryptAsync
.
It is preferred to use the base::span
EncryptData
and DecryptData
APIs, however the EncryptString
and DecryptString
APIs are provided for ease of compatibility with existing callers of os_crypt::OSCrypt
. The string and span APIs are compatible with one another.
Integration Guide
OSCryptAsync
is currently integrated into the Cookie encryption within the network service, and this code can be used as a full end-to-end example of how to integrate OSCryptAsync
into your existing code that is using os_crypt::OSCrypt
.
There are a few considerations that are important for integrators:
GetInstance()
must be called on the same sequence that it was created on, which, if you are using the instance managed by //chrome is the UI thread. Therefore, plan for your GetInstance
calls to be made on this sequence. Callbacks will also arrive on this sequence. Once you have an Encryptor
it can be safely passed and used on another sequence, though.os_crypt::OSCrypt
and OSCryptAsync
are likely being used to seal valuable data so all precautions should be made to avoid any potential data loss.os_crypt::OSCrypt
should be converted to perform an asynchronous initialization of an Encryptor instance by calling GetInstance
and handling the callback. The Encryptor
instance that is returned can then be used as if the code were calling directly to os_crypt::OSCrypt
but since the Encryptor
is move-only it will have to be held by an object on the calling sequence to make the calls themselves. If multiple sequences need to make encryption calls, that‘s supported, but you’ll need to get an Encryptor
for each sequence and explicitly pass it to those sequences. In this phase, it is highly recommended to:GetInstance
with the kEncryptSyncCompat
option. This will ask the Encryptor
to always encrypt any data in a format that is backwards compatible with os_crypt::OSCrypt
. This means that if any issues are found when converting the code from sync to async, there is no risk of any permanent data loss, and any CLs can be safely rolled back, or features turned off.kEncryptSyncCompat
and a feature flag, the code can be iterated on without risk to any permanent data loss for users.OSCryptAsync
might not yet have obtained a valid Encryptor
instance.kEncryptSyncCompat
option passed to GetInstance
from all calls, and data will now start being encrypted with the keys managed by the installed OSCryptAsync
key providers in a potentially non-backwards compatible way. In this phase, for example, data might start being encrypted with App-Bound encryption on supported platforms. At this point you will want to double check no data loss caused by encrypting data with the new keys, although core OSCryptAsync
metrics themselves are used as guardrails against this scenario.os_crypt::OSCrypt
, and data encrypted with OSCryptAsync
depending on when it was originally encrypted) should be read in from persistent storage, decrypted, re-encrypted, and then and written back to persistent storage. This ensures that all data is now encrypted with OSCryptAsync
and secured by new keys.