Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using zeroize-on-drop in mc-transaction-core #2717

Open
6 tasks
cbeck88 opened this issue Oct 17, 2022 · 0 comments
Open
6 tasks

Using zeroize-on-drop in mc-transaction-core #2717

cbeck88 opened this issue Oct 17, 2022 · 0 comments
Assignees
Labels
security Public issues which impact security impact transaction-core Area: Rules defining a valid transaction and its structure

Comments

@cbeck88
Copy link
Contributor

cbeck88 commented Oct 17, 2022

Historically, most objects in transaction-core did not implement Zeroize.
This is because curve25519-dalek::RistrettoPoint did not implement Zeroize and so it was impossible.

Now, it does implement Zeroize, but not drop(Zeroize). This means, we know how to zeroize it, but it is not automatically zeroized on drop. Many (maybe not all?) sensitive types in TransactionCore also derive Zeroize now.

Generally, we want "secrets" to be zeroized on drop. This represents an implementation hardening step that can protect against information leaks, by reducing the window for an adversary who has hacked into your device from obtaining secrets that are resident in memory.

However, in a typical transaction almost everything is a secret in our model. Not only are your private keys a secret, but also who you are sending money to is a secret.

  • tx_private_key should be zeroized on drop
  • tx_out_shared_secret should be zeroized on drop
  • Your friend's public address should be zeroized on drop
  • Which inputs you selected to spend, and which ring input is the real input, should be zeroized on drop.
  • Pseudo-output blinding factors should be zeroized on drop, because they can be used to unblind amounts in a transaction.
  • Possibly the whole Tx should be zeroized, but this might be overkill.

Zeroizing on drop has additional consequences.

  • Drop types cannot be Copy. Some types like CompressedRistrettoPublic are Copy.
  • This can interfere with some optimizations (although it is probably minor).
  • I am not sure how it interacts with Prost.

This issue tracks discussion and implementation around:

  • What types if any should be Zeroized on Drop?

An alternative approach is:

  • Types are not usually marked zeroize-on-drop, instead, variables are Zeroizing wrappers around types that implement Zeroize. This has other tradeoffs compared to using Zeroize on drop.

One basic step we can take is, try making Tx object Zeroize on drop and test if this has performance implications for the consensus network. IIRC a large part of the consensus enclave has to do with deserializing these objects, calling validate by passing a reference, and then possibly re-encrypting it and passing it to peer enclaves, and there is not much reason to make copies of parts of the Tx for other purposes, so this change may clean up a large number of secrets on its own. Then we can follow up by seeing what copies of secrets if any are made during Tx validation and ensure that we clean up those also.


  • Zeroize Tx on drop Make the Tx object zeroize itself on drop #2925
  • Zeroize tx_private_key on drop
  • Zeroize tx_out_shared_secret on drop
  • Zeroize transaction builder arguments, such as public address (and amounts?) of an output
  • Zeroize inputs, true ring input, on drop
  • Zeroize pseudo-output blinding factors on drop
@cbeck88 cbeck88 added security Public issues which impact security impact transaction-core Area: Rules defining a valid transaction and its structure labels Oct 17, 2022
@cbeck88 cbeck88 self-assigned this Dec 1, 2022
cbeck88 added a commit that referenced this issue Dec 5, 2022
This is an experimental change to improve hygeine of memory in
the consensus enclave (but also in the clients)

This makes a bunch of objects derive `Zeroize` in transaction-core,
and makes the `Tx` object zeroize itself on drop.

For examples of why this is a good change, consider that, in the
`mc-connection` ThickClient crate, after we serialize a Tx to protobuf
and encrypt it for the enclave, we zeroize the plaintext. However,
before this change, we do not zeroize the `Tx` object (since it
would not have been possible), so another copy of the data that
we zeroized continues to exist in memory. After this change, the
`Tx` will zeroize itself automatically as well.

The main reason not to do this would be if it hurts the performance
of the consensus nodes, but I consider this unlikely, because,
the untrusted side never actually sees `Tx` objects so SCP should
not be meaningfully impacted by this, only the transaction validation
handles the decrypted `Tx`. And the elliptic curve operations done
to validate a Tx should be many orders of magnitude more expensive
than a zeroizing operation. So I expect no measurable performance
difference as a result of this change.

See github issue #2717
cbeck88 added a commit that referenced this issue Dec 7, 2022
This is an experimental change to improve hygeine of memory in
the consensus enclave (but also in the clients)

This makes a bunch of objects derive `Zeroize` in transaction-core,
and makes the `Tx` object zeroize itself on drop.

For examples of why this is a good change, consider that, in the
`mc-connection` ThickClient crate, after we serialize a Tx to protobuf
and encrypt it for the enclave, we zeroize the plaintext. However,
before this change, we do not zeroize the `Tx` object (since it
would not have been possible), so another copy of the data that
we zeroized continues to exist in memory. After this change, the
`Tx` will zeroize itself automatically as well.

The main reason not to do this would be if it hurts the performance
of the consensus nodes, but I consider this unlikely, because,
the untrusted side never actually sees `Tx` objects so SCP should
not be meaningfully impacted by this, only the transaction validation
handles the decrypted `Tx`. And the elliptic curve operations done
to validate a Tx should be many orders of magnitude more expensive
than a zeroizing operation. So I expect no measurable performance
difference as a result of this change.

See github issue #2717
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
security Public issues which impact security impact transaction-core Area: Rules defining a valid transaction and its structure
Projects
None yet
Development

No branches or pull requests

1 participant