Drew DeVault: 2 all: add some light hardening docs/security.txt: document security model 6 files changed, 152 insertions(+), 1 deletions(-)
This is exactly what I had in mind. Great writeup! I was thinking that the easiest attack would be to replace the daemon binary. Maybe it would be helpful to add something like "any process could request a secret value or even replace the daemon itself". But then again there are probably far too many possible attacks to enumerate them all.
Was "store retain" intentional here? English is not my first language, but I felt like there should be only one verb.
Thanks for writing this!
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~sircmpwn/himitsu-devel/patches/50772/mbox | git am -3Learn more about email & git
- Wipes more data from memory when the key store is unlocked. - Prevents core dumps and debugging on Linux Signed-off-by: Drew DeVault <sir@cmpwn.com> --- cmd/himitsud/harden+linux.ha | 6 ++++++ cmd/himitsud/harden.ha | 3 +++ cmd/himitsud/main.ha | 2 ++ secstore/secstore.ha | 3 ++- secstore/types.ha | 3 +++ 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 cmd/himitsud/harden+linux.ha create mode 100644 cmd/himitsud/harden.ha diff --git a/cmd/himitsud/harden+linux.ha b/cmd/himitsud/harden+linux.ha new file mode 100644 index 0000000..b384158 --- /dev/null +++ b/cmd/himitsud/harden+linux.ha @@ -0,0 +1,6 @@ +use rt; + +fn harden() void = { + // Prevent core dumps from being made and debuggers from attaching + rt::prctl(rt::PR_SET_DUMPABLE, 0, 0, 0, 0)!; +}; diff --git a/cmd/himitsud/harden.ha b/cmd/himitsud/harden.ha new file mode 100644 index 0000000..6ae5f8c --- /dev/null +++ b/cmd/himitsud/harden.ha @@ -0,0 +1,3 @@ +fn harden() void = { + return; +}; diff --git a/cmd/himitsud/main.ha b/cmd/himitsud/main.ha index 607a724..653ca52 100644 --- a/cmd/himitsud/main.ha +++ b/cmd/himitsud/main.ha @@ -40,6 +40,8 @@ export fn main() void = { }; defer secstore::close(&store); + harden(); + let pipe = unix::pipe()!; sigwrite = pipe.1; signal::handle(signal::sig::INT, &handle); diff --git a/secstore/secstore.ha b/secstore/secstore.ha index 1612611..67b6b57 100644 --- a/secstore/secstore.ha +++ b/secstore/secstore.ha @@ -317,12 +317,13 @@ export fn lock(store: *secstore) void = { yield; }; store.state = state::SOFT_LOCKED; + free_keys(store); + free(store.entries); }; // Closes the secstore, freeing any associated resources. export fn close(store: *secstore) void = { lock(store); - free_keys(store); io::close(store.index)!; free(store.dir); }; diff --git a/secstore/types.ha b/secstore/types.ha index eae73ed..81eb46b 100644 --- a/secstore/types.ha +++ b/secstore/types.ha @@ -1,7 +1,9 @@ +use bytes; use crypto::keystore; use errors; use fs; use io; +use strings; use uuid; export type state = enum { @@ -40,6 +42,7 @@ fn entry_finish(ent: *entry) void = { free(pair.key); match (pair.value) { case let val: str => + bytes::zero(strings::toutf8(val)); free(val); case uuid::uuid => yield; -- 2.44.0
Thanks! To https://git.sr.ht/~sircmpwn/himitsu c657d70..6becc84 master -> master
Signed-off-by: Drew DeVault <sir@cmpwn.com> --- docs/security.txt | 136 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 docs/security.txt diff --git a/docs/security.txt b/docs/security.txt new file mode 100644 index 0000000..8f41546 --- /dev/null +++ b/docs/security.txt @@ -0,0 +1,136 @@ +# Himitsu security model + +This document discusses Himitsu's approach to and design regarding security and +privacy, what guarantees it attempts to make, and what it does not attempt to +protect against. + +Note that Himitsu's implementation has not been independently audited, and in +practice the security may be undermined by bugs and/or unforeseen issues with +the design and implementation. + +## Glossary + +* **key store**: the set of keys stored in Himitsu +* **key**: a single "key", which may have many key/value "pairs". + `foo=bar bar!=baz` is a key. +* **secret pair**: a key/value pair of a key which has the secret flag set, such + as `bar!=baz`. "baz" is the **secret value** of this pair. +* **secstore**: "Secure store", the encrypted-at-rest storage for the key store +* **master key**: an cryptographic key used to encrypt and authenticate your key + store +* **master passphrase**: the passphrase from which Himitsu derives your master + key
With the new key version the master key is randomly generated when initializing the store. The key derived from the master passphrase is used to decrypt the master key, which is stored in the `key` file.
+ +## Offline security + +*"Offline security" in this document refers to the security measures taken to +protect your key store when the Himitsu daemon is not running. Threats covered +here include attackers running programs on the same system as yourself or +another user, a copy of your key store being in the posession of an attacker, +and so on.* + +Himitsu's secret store is used to store your private data offline. The secstore +contains the following information: + +* Your master key, obfuscated
The master key is stored in encrypted form, not obfuscated.
+* An index, encrypted with your master key +* Secret keys, encrypted with your master key + +Your master key is used as the input to a key derivation algorithm (argon2id at +the time of writing) which both derives the symmetric encryption key and +obfuscates the master password stored on disk. The key derivation algorithm is
Your master passphrase is used as the input to a key derivation algorithm (argon2id at the time of writing) which both derives the key to decrypt the master key and a reference value to verify the passphrase, before use. I don't know a better word for reference value here.
+designed to be resistant to an offline attack, and at the time of writing there +are no known practical attacks against argon2id. + +However, the master key is ultimately only as secure as your passphrase. If you +use very short or common passphrases, an attacker may be able to guess it in a +practical amount of time. Moreover, no amount of software security will prevent +someone from reading the master passphrase off of a sticky note on your desk. An +ideal passphrase is long, so it's secure, and memorable, so you don't have to +write it down: 5 or 6 randomly-selected dictionary words are a safe bet. + +The master key is used to separately encrypt each key in the secstore "index". +The index is encrypted and authenticated. An attacker can determine the number +of keys in your key store, and can estimate the length of each key in bytes, but +cannot read the pairs, secret or not. An attacker cannot tamper with your +key-store, either: they may change the order of the pairs but they cannot read, +modify, or forge your keys. + +The index stores the "key" portion of a secret pair (i.e. **key**!=value) and +stores a UUID uniquely associated with the secret value. The secret value is +stored in a separate file named for this UUID. The secret value itself is +encrypted and authenticated in a tamper-resistant manner. An attacker can +determine the total number of secret values among all keys in your key store, +and estimate each of their lengths in bytes, but cannot read, modify, or forge +secret values. + +Authenticated encryption is performed at the time of with an algorithm based on +RFC 8439, but using XChaCha20 instead of ChaCha20. + +### Additional offline security measures + +Your secstore is stored with the Unix permissions configured such that it is +only readable and writable by your user account. + +### Securely handling your secstore + +Himitsu is designed such that your secstore can fall into an adversary's hands +and remain secure. Assuming you have chosen a strong enough password, you are +able to safely store it with a cloud provider, copy it between machines, put it +on a flash drive and lose it, and so on. + + +## Online security + +The Himitsu daemon has several security features to implement a defense-in-depth +design. The Himitsu daemon has two online security models: locked and unlocked. + +When you start Himitsu, it runs in locked mode. In this mode, Himitsu waits for +the user to initiate an key store operation and stores no sensitive information +in memory whatsoever. When you attempt any operation for the first time, Himitsu +will prompt you for your master passphrase and enter unlocked mode to complete +your request. + +Once unlocked, the daemon will decrypt and authenticate the index, then store +retain the master key and a copy of the index in memory. It will *not* decrypt +secret values or store them in memory while unlocked. + +Clients access the key store via a Unix socket. The Unix socket is located in +the user's runtime directory and its file permissions are only read/writable by +the user's Unix user. When the daemon is unlocked, any client may read the key +store pairs *without* their secret values, without user approval. When a client +requests to read a secret value, the user is prompted to consent to disclosure +of the secret value. + +If the user agrees, the daemon will look up the appropriate secret value by UUID +in the secstore, decrypt and authenticate it, and provide it to the client +application in plain text over the Unix socket connection. + +No attempt is made to authenticate the client request. It will have come from a +process running on the user's Unix account, but if the user runs untrusted code, +or their system is otherwise compromised, any process could request a secret +value and cause the consent dialog to appear. It is up to the user to approve +secret requests with appropriate scrutiny and discretion. Furthermore, nothing +prevents the client from retaining the secret value once disclosed, or otherwise +handling the secret value incautiously. + +### Hardening features + +The following extra steps are taken to harden the daemon: + +* All sensitive data is securely erased from memory after use, such as the + master passphrase, secret values, and so on. + +**Linux-specific** + +* In the unlocked state, the master key is retained in kernel memory via keyctl. + It is only present in daemon memory during cryptographic operations, and is + securely erased when the operations are completed. This prevents bugs which + could be exploited to read the daemon's memory from accessing the master key + when it is not in use. +* Note that no attempt is made to lock memory (Himitsu requires more memory than + it is practical to lock on Linux). It is recommended to use encrypted swap to + reduce the risk of your key store contents being stored in plain text on swap. + The risk of disclosure is relatively low, as Himitsu does not use enough + memory to generally be a priority for Linux to swap to reclaim space, and a + limited amount of sensitive information is stored on idle pages. -- 2.44.0
Tobias Bengfort <tobias.bengfort@posteo.de>This is exactly what I had in mind. Great writeup! I was thinking that the easiest attack would be to replace the daemon binary. Maybe it would be helpful to add something like "any process could request a secret value or even replace the daemon itself". But then again there are probably far too many possible attacks to enumerate them all.
Tobias Bengfort <tobias.bengfort@posteo.de>Was "store retain" intentional here? English is not my first language, but I felt like there should be only one verb.
Thanks for writing this!