Security Overview

Security Model

From a security point of view, the core idea of the Builder Vault TSM is that all cryptographic keys are split across a set of separate parties called MPC nodes. Each MPC node will only have a share of the key, which in itself reveals no information about the key, yet together multiple MPC nodes are able to perform cryptographic operations without learning anything but their own key share.

To use a key held in the TSM, the key shares are not collected in a single place. Instead, the TSM applies an advanced cryptographic technique known as Secure Multiparty Computation (MPC) to compute signatures or encryptions, without the secret key being reconstructed at any point. As a result, there is no single point of trust in the system. Applying MPC to shares of cryptographic keys is also known as threshold cryptography.

Concretely, when a key is created in - or imported into - the TSM, the key is a secret shared among a set of n of the MPC nodes, using a security threshold of t. The security threshold specifies the number of key shares that can be leaked without being able to learn anything about the original key. In other words, if a key is stored in the TSM using a security threshold of t, then the secret sharing and the MPC technology ensure confidentiality of the key, as long as at most t of the MPC nodes are corrupted.

Typically, a key is generated on two MPC nodes (n=2) with a security threshold of one (t=1). In this case, we say that the key is a (2,1) sharing, This means that the key is protected even if one of the two MPC nodes gets compromized.

As another example, a key could be imported into three MPC nodes in the TSM (n=3) using a security threshold of one (t=1). This means that the key remains secure even if any one of the three MPC nodes gets compromized. It is also possible to use t=2, meaning that the key remains secure even if two of the three MPC nodes gets corrupted.

Generally, using a higher security threshold increases the key confidentiality. The MPC will, on the other hand, often require t+1 MPC nodes to participate in the generation of a signature or encryption. So there is a trade-off between confidentiality and availability of the key secret shared in the TSM.

MPC Node Configuration and Database

In addition to it's database, each MPC node has a configuration file which contains information about how to communicate with the other MPC nodes (its own private key and the URLs and public keys used to establish secure connections to the other MPC nodes), information about how to connect to its database, how to encrypt its sensitive database contents, which MPC protocols to use, etc.

When starting an MPC node the EncryptorMasterPassword (or the EncryptorKeyFile) from the configuration file is used to derive a key encryption key (KEK) using PBKDF2. This KEK is used to decrypt the master encryption key (MK) stored in the database (automatically generated on first startup). When encrypting and decrypting sensitive database content such as key shares, a content encryption key (CEK) is derived from the MK and some additional (non secret) data (i.e. KeyID) using HKDF. The actual data is encrypted under this CEK. All encryptions are done using AES-GCM with 256 bit keys.

This encryption method can also be used to encrypt the configuration file itself, with exception of the database section as that is needed to instantiate the encryptor. To avoid having the encryption password stored in the clear, the database encryption key can also be read from a file (e.g. on a USB stick that is only present during startup) or read from the command line.

Randomness and Entropy

The source of randomness is Go's rand package, thus the concrete details will depend on the underlying system/environment, e.g.,

  • Linux, FreeBSD: getrandom(2) if available, /dev/urandom otherwise
  • OpenBSD: getentropy(2)
  • Unix-like systems: /dev/urandom
  • Windows: CryptGenRandom API

A version of the TSM based on a platform consisting of Go and BoringCrypto running on Intel hardware is currently in the process of being FIPS-140-3 certified. BoringCrypto is FIPS-140-2 certified and on an Intel platform, the DRBG utilizes RDRAND, which is also FIPS-140-2 certified.

When generating keys in the TSM this will draw upon the described entropy sources at each MPC node. During key generation a node only learns its own share, and the full key is never assembled or available.

Secure Channels between the MPC Nodes

  • If the TSM is configured for direct TLS connections, the MPC nodes will establish secure pairwise connections via 2-way TLS v1.3. The MPC nodes use their private key from the configuration file to set up their TLS server, and the public keys for the other nodes to do public key pinning, i.e. we do not rely on a certificate authority.
  • If the TSM is configured to use a message broker, each MPC node will establish a secure TLS connection with the message broker. The secure termination is terminated at the message broker, but the MPC nodes will apply an additional layer of encryption on top the TLS, meaning that the message broker will not be a trusted party.

SDK Authentication

Each MPC node is controlled by an SDK. The SDK connects to its MPC node using HTTP or HTTPS.

If HTTPS is used, the SDK will validate the MPC node’s certificate using the certificate store from the operating system (public key pinning is also possible). HTTP is not recommended in production unless the communication channel is secured in some other way, or for example in a setup where HTTPS is terminated in a load balancer in front of the node.

The SDK authentication method can be configured in the MPC node’s configuration file:

  • If API key authentication is used, the SDK then sends the API key over the channel and gets a JWT token back. The JWT token lifetime can be configured in the MPC node configuration files.
  • Alternatively, SDKs can be authenticated using TLS. In this case the connection between the SDK and the MPC node will be a 2-way TLS where not only the MPC node, but also the SDK holds a private key.
  • A third alternative is to configure the MPC node to use OIDC, where the SDK is authenticated via a 3rd party OIDC provider, such as Google or Auth0.

SDK authenticating with API keys requires the API keys to be written in the the MPC node configuration files, along with the application ID to which the API key maps.

In the case of 2-way TLS and OIDC authentication, applications are created when their client certificate passes authentication. The application ID is either a hash of the distinguished name (DN) or the OIDC identifier.

👍

You can now specify an application ID for TLS to limit access, and certificates can be revoked using OCSP.

Execution of MPC Protocols

When the TSM runs distributed MPC protocols the MPC nodes exchange a number of messages in order to generate keys or produce signatures or encryptions using the generated keys. The keys are stored as secret sharings between the MPC nodes.

To run a distributed MPC protocol (such as generating an RSA or ECDSA signature on a message), each of the MPC nodes in the TSM must be told to start the given operation via an SDK call to e.g. SignPKCS1v15. For this to work, the SDK operators (which may belong to different organizations) need to agree on a unique session ID. Each SDK operator must then call SignPKCS1v15 on his own SDK using this session ID. Note that this means that an RSA signature can only be generated on a given message if an (authorized) SDK operator at each MPC node agrees to call the SignPKCS1v15 method on its SDK for that message.

The operations allowed can be controlled via the MPC node config file. E.g., to enable RSA signatures, the MPC configuration file has to contain a section that enables the RSA MPC protocol.

When a session is about to start, all nodes compare their metadata about the session (including a hash of the message to sign, if it is a signing operation), and abort the session if there is a disagreement about which operation is about to be performed.

Dynamic Node Configuration (MPC Node Multi-Tenancy)

The TSM allows the public keys used for establishing secure connection between the MPC nodes to be provided dynamically, when the MPC session starts. This can be used to implement MPC Node “multi-tenancy”, where some MPC nodes remain static, while there can be many instances of other MPC nodes. A typical setup will involve one or two static nodes running as servers, and one multi-tenant node run on a mobile device. The static MPC nodes may decide to accept executing an MPC protocol with a specific mobile device by providing the public key for that device as part of the MPC session configuration when a key or signature is to be generated.

If MPC nodes communicate with direct TLS connections, only one of the nodes can be dynamically configured. If using a message broker, any subset of MPC nodes can be dynamically configured, even all of them.