HSM Policy JSON File#
The HSM policy is established by a simple JSON file, which configures various security settings, and the rules for which transactions should be signed automatically by the Coldcard. This JSON file is uploaded to the Coldcard, which parses it, and creates a text version of the policy, for you to approve on-screen.
The file has two parts: global settings and a variable number of "rules". The global (top-level) values are as follows:
notes
: free-form text, shown at top of confirmation message, up to 80 chars longperiod
: (integer) velocity period, in minutes, shared across all the rulesmust_log
: (bool) fail anything we can't log to SD cardnever_log
: (bool) disable all log generation (even if SD card inserted)-
warnings_ok
: (bool) normally will fail a PSBT that has any warnings, this allows it -
msg_paths
: enable message signing, but only using provided derivation paths (a list) useany
to allow any path share_xpubs
: same for xpubs sharing, butm
is always shared regardless-
share_addrs
: same for addrs, but keywordp2sh
in list also allows p2sh address calcs -
set_sl
: (text string) load the storage locker with a value: max 416 chars -
allow_sl
: (integer) number of times the storage locker can be read per boot-up -
boot_to_hsm
: if defined, six-digit numeric code used to escape boot-to-HSM feature -
priv_over_ux
: (bool) reduce chattiness of status responses in HSM mode, making UX harder -
rules
: list of objects, see below. Each rule is checked in order given in this list.
Each rule consists of these values:
whitelist
: a list of specific addresses which are allowed as destinationsper_period
: total BTC that can move thru this rule in the periodmax_amount
: max BTC per transaction, that this rule can apply to (independent of period)users
: a list of usernames that are able to approve (N)min_users
: number of users (M) needed to approve (from list of users for rule, not system), if missing, assume all users required (M=N)local_conf
: bool flag, local user must (also) approve (via 6-digits entered on keypad)wallet
: either name of a multisig wallet, or"1"
indicating rule only applies to non-multisig
When an element of the rule is missing or has value null
, then
the restriction does not apply. For example, if whitelist
is
missing, then the Coldcard will not consider the destination address
when considering the rule.
If no rules are defined, then no PSBT will be signed. This can be
useful for text message signing applications. On the other hand,
an empty rule, meaning just {}
, allows any transaction to be
signed, so be careful!
Spending Period (Velocity)#
To implement spending limits based on time, the Coldcard requires you to define
a period. This period, expressed in minutes, applies to all rules. Any rule with
a defined per_period
value, will be affected.
The period starts when it is first used. There is no absolute concept of
time on the Coldcard (it doesn't have a real time clock). There is only one
period, so it will begin as soon as any rule using a per_period
limit
is applied successfully.
At the end of the period, the totals are reset to zero.
Spending Rules#
Multiple spending rules can be defined. The system scans the rules starting from the first one, and will test each rule. The first rule that is satisfied is applied and following rules are not considered.
We recommend putting the most narrow rules first. Catch-all rules, which might move more money should be later in the list.
Max Transaction Amount#
max_amount
per transaction is less useful because a number of transactions
could be put together to "work around" this rule. However, if there is natural
rate-limiting in your system, for example, by using a
local operator to enter a code each time,
then this is still helpful. Use local_conf=True
to enable
the local code when the rule is applied.
Per-Period Limit#
per_period
is the total amount, in Satoshis, that can be spent
using this rule in the period.
Authorizing Users#
You can list username in the users
field. If defined the min_users
controls
how many of those are required. By default (if min_users
isn't defined), all users
listed must confirm the operation. You can achieve 2-of-5 and similar setups
using min_users
. All users listed must already be defined on the Coldcard
before the policy is activated.
The local_conf
boolean enables the local PIN code,
and requires it for transactions
that take advantage of the rule. It can be combined with the user list, or used
by itself.
Limit to Named Wallet#
The wallet
field can be omitted, or set to the name of a multisig wallet. If set
to the string "1"
, it indicates this rule only applies to the non-multisig wallet.
Whitelist Address#
You may specify a list of addresses in the whitelist
field. The Coldcard will
only apply the rule if all destination addresses of the PSBT transaction are
included in the whitelist. This is a powerful feature when your target wallets
that you control in the whitelist, such as emergency cold wallets.
Global Policy Values#
Logging to MicroSD Card#
Two setting affect logging: must_log
and never_log
. By default,
the Coldcard will log if a card is inserted. It does not fail if
the card is missing. If that is an issue for you, then set must_log
and transactions will be refused if the card isn't installed and
working. never_log
is useful when you don't want to keep records
at the Coldcard's location.
Warnings Okay?#
This boolean allows the Coldcard to sign PSBT files that have warnings. Typically this is overly-large fees or weird path derivations. Since we don't expect warnings, any transactions with a warning is normally refused.
Message Signing#
To enable text message signing, list one or more BIP32 derivation paths in msg_paths
.
You can use the special value "any"
to allow all signing. You may also use a star
in the last position of a path, like these examples:
m/84'/0'/0/*
m/84'/0'/0'/*'
m/9984/*
The star allows any number in the final position (only). It does not allow deeper paths.
Sharing Xpubs#
The Coldcard can calculate XPUB values for derived paths, if
share_xpubs
is defined. You can limit this feature by giving a
list of permitted paths, or the keyword "any"
to allow any subpath.
The master xpub (m
) is always available over USB protocol and cannot be disabled.
Sharing Addresses#
Similarly, the Coldcard can calculate wallet addresses, if share_addrs
contains a list of whitelisted derivation paths. Star patterns, and the keyword "any"
can be used,
as well as the keyword "p2sh"
which allows addresses in multisig
wallets to be shared.
In the case of multisig wallets, we do not check the script provided, beyond the normal checks for inclusion into a known multisig wallet.
Storage Locker#
The storage locker is small number of bytes held in the secure
element of the Coldcard (Mk3 only). The HSM policy file can be used
to write a text value to this area, using set_sl
. (That part of
the policy file is forgotten after it's committed into the secure
element.) The storage locker is protected by the master PIN, and
has the same level of protection as the master seed.
The storage locker is readable over the USB connection in HSM mode.
However, the number of times it can be read is limited by the
allow_sl
value. You may set this to one, so that when your
companion software is started, it has one opportunity to read the
locker. If it is restarted, or other (unauthorized) software on your
USB-connected machine reads the locker, it will fail. Further access
will require reboot of the Coldcard, and knowledge of the master PIN.
CKBunker manages the Storage Locker for it's own purposes: it stores a 32-byte secret to unlock a NaCL secret box holding all CKBunker settings.
Boot-to-HSM#
This feature forces the Coldcard to start in HSM mode immediately
after boot up (and entry of the master PIN). It is enabled
if boot_to_hsm
is defined.
If you specify a 6-digit numeric code for boot_to_hsm
, and if
that code is provided in the first 60 seconds after startup, the Coldcard
will leave HSM mode.
But if you set the boot_to_hsm
value to a non-numeric value which
cannot be entered by the keypad, the Coldcard will never be able
to leave HSM mode.
Bricking Hazard
No changes to firmware, HSM policy, Coldcard settings will be possible—ever again.
Not even the master PIN holder can change HSM policy nor escape HSM
mode! Firmware upgrades are not possible.
Privacy over UX#
During development of the HSM feature, we found there were numerous status and informational values being shared over USB that, to some degree, assist attackers. However, those values are needed to provide a usable interface and a nice user experience (UX).
If you set priv_over_ux
to true, the following values will not be
shared over USB in the HSM status response:
- text summary of the spending policy
- count of approvals / refusals
- the number of time the storage locker has been read
- the period length
- when the period will end
- how much each rule has spent in current period
- system uptime
- list of usernames
- number of users which have provided auth credentials for current PSBT
The CKBunker can operate in either mode, but you will find it harder to use, as it's not possible to know where you stand in terms of velocity spending and user authorization.
Example JSON Policy File#
Here is a sample policy file, ready to be uploaded into a Coldcard.
It has three rules:
- local user can authorize up to 1BTC per txn (by themselves)
- either Alice or Bob can authorize up to 1BTC per 4 hour period
- allow any txn that sends to address
bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
{
"never_log": true,
"must_log": false,
"priv_over_ux": false,
"boot_to_hsm": null,
"period": 240,
"set_sl": "my secret here",
"allow_sl": 13,
"rules": [
{
"whitelist": [],
"per_period": null,
"max_amount": 100000000,
"users": [],
"local_conf": true,
"wallet": null
},
{
"whitelist": [],
"per_period": 100000000,
"max_amount": null,
"users": [
"alice",
"bob"
],
"min_users": 1,
"local_conf": false,
"wallet": null
},
{
"whitelist": [
"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"
],
"per_period": null,
"max_amount": null,
"users": [],
"local_conf": false,
"wallet": null
}
],
"msg_paths": [
"any"
],
"share_xpubs": [
"m/84'/0'/0'/*"
],
"share_addrs": [
"m/84'/0'/0'/*"
],
"notes": "Semper Fi"
}
The Coldcard will show this text to summarize the policy:
=-=
Semper Fi
=-=
Transactions:
- Rule #1: Up to 1 XTN per txn will be approved if local user confirms
- Rule #2: Up to 1 XTN per period may be authorized by any one user: alice OR bob
- Rule #3: Any amount will be approved provided it goes to: bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
Velocity Period:
240 minutes
= 4 hrs
Message signing:
- Allowed if path matches: (any path)
Other policy:
- No logging.
- Storage Locker will be updated, and can be read 13 times.
- XPUB values will be shared, if path matches: m OR m/84'/0'/0'/*.
- Address values values will be shared, if path matches: m/84'/0'/0'/*.