Skip to content

Commit

Permalink
conway: new key derivation schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
janmazak committed Nov 29, 2023
1 parent 08cbfa7 commit 537cadc
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
65 changes: 62 additions & 3 deletions src/bip44.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include "hash.h"
#include "keyDerivation.h"

#define CARDANO_CHAIN_EXTERNAL 0
#define CARDANO_CHAIN_INTERNAL 1
#define CARDANO_CHAIN_STAKING_KEY 2
static const uint32_t CARDANO_CHAIN_EXTERNAL = 0;
static const uint32_t CARDANO_CHAIN_INTERNAL = 1;
static const uint32_t CARDANO_CHAIN_STAKING_KEY = 2;
static const uint32_t CARDANO_CHAIN_DREP_KEY = 3;
static const uint32_t CARDANO_CHAIN_COMMITTEE_COLD_KEY = 4;
static const uint32_t CARDANO_CHAIN_COMMITTEE_HOT_KEY = 5;

static const uint32_t MAX_REASONABLE_ACCOUNT = 100;
static const uint32_t MAX_REASONABLE_ADDRESS = 1000000;
Expand Down Expand Up @@ -252,6 +255,42 @@ bool bip44_isMultidelegationStakingKeyPath(const bip44_path_t* pathSpec)
&& (bip44_getAddressValue(pathSpec) > 0);
}

bool bip44_isDRepKeyPath(const bip44_path_t* pathSpec)
{
#define CHECK(cond) if (!(cond)) return false
CHECK(pathSpec->length == BIP44_I_ADDRESS + 1);
CHECK(bip44_hasShelleyPrefix(pathSpec));
CHECK(isHardened(bip44_getAccount(pathSpec)));
CHECK(bip44_getChainTypeValue(pathSpec) == CARDANO_CHAIN_DREP_KEY);
CHECK(bip44_getAddressValue(pathSpec) == 0); // TODO allow other values and check for hardened only?
return true;
#undef CHECK
}

bool bip44_isCommitteeColdKeyPath(const bip44_path_t* pathSpec)
{
#define CHECK(cond) if (!(cond)) return false
CHECK(pathSpec->length == BIP44_I_ADDRESS + 1);
CHECK(bip44_hasShelleyPrefix(pathSpec));
CHECK(isHardened(bip44_getAccount(pathSpec)));
CHECK(bip44_getChainTypeValue(pathSpec) == CARDANO_CHAIN_COMMITTEE_COLD_KEY);
CHECK(bip44_getAddressValue(pathSpec) == 0); // TODO allow other values and check for hardened only?
return true;
#undef CHECK
}

bool bip44_isCommitteeHotKeyPath(const bip44_path_t* pathSpec)
{
#define CHECK(cond) if (!(cond)) return false
CHECK(pathSpec->length == BIP44_I_ADDRESS + 1);
CHECK(bip44_hasShelleyPrefix(pathSpec));
CHECK(isHardened(bip44_getAccount(pathSpec)));
CHECK(bip44_getChainTypeValue(pathSpec) == CARDANO_CHAIN_COMMITTEE_HOT_KEY);
CHECK(bip44_getAddressValue(pathSpec) == 0); // TODO allow other values and check for hardened only?
return true;
#undef CHECK
}

bool bip44_isMintKeyPath(const bip44_path_t* pathSpec)
{
#define CHECK(cond) if (!(cond)) return false
Expand Down Expand Up @@ -367,6 +406,21 @@ static bip44_path_type_t bip44_classifyOrdinaryWalletPath(const bip44_path_t* pa
PATH_ORDINARY_STAKING_KEY :
PATH_INVALID;

case CARDANO_CHAIN_DREP_KEY:
return bip44_isDRepKeyPath(pathSpec) ?
PATH_DREP_KEY :
PATH_INVALID;

case CARDANO_CHAIN_COMMITTEE_COLD_KEY:
return bip44_isCommitteeColdKeyPath(pathSpec) ?
PATH_COMMITTEE_COLD_KEY :
PATH_INVALID;

case CARDANO_CHAIN_COMMITTEE_HOT_KEY:
return bip44_isCommitteeHotKeyPath(pathSpec) ?
PATH_COMMITTEE_HOT_KEY :
PATH_INVALID;

default:
return PATH_INVALID;
}
Expand Down Expand Up @@ -492,6 +546,11 @@ bool bip44_isPathReasonable(const bip44_path_t* pathSpec)
case PATH_MULTISIG_STAKING_KEY:
return bip44_hasReasonableAccount(pathSpec) && bip44_hasReasonableAddress(pathSpec);

case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:
return bip44_hasReasonableAccount(pathSpec);

case PATH_MINT_KEY:
return bip44_hasReasonableMintPolicy(pathSpec);

Expand Down
16 changes: 16 additions & 0 deletions src/bip44.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,17 @@ bool bip44_isOrdinaryStakingKeyPath(const bip44_path_t* pathSpec);
bool bip44_isMultisigStakingKeyPath(const bip44_path_t* pathSpec);
bool bip44_isMultidelegationStakingKeyPath(const bip44_path_t* pathSpec);

bool bip44_isDRepKeyPath(const bip44_path_t* pathSpec);
bool bip44_isCommitteeColdKeyPath(const bip44_path_t* pathSpec);
bool bip44_isCommitteeHotKeyPath(const bip44_path_t* pathSpec);

bool bip44_isMintKeyPath(const bip44_path_t* pathSpec);

bool bip44_isPoolColdKeyPath(const bip44_path_t* pathSpec);

bool bip44_isCVoteKeyPath(const bip44_path_t* pathSpec);


size_t bip44_printToStr(const bip44_path_t*, char* out, size_t outSize);


Expand All @@ -101,6 +106,17 @@ typedef enum {
PATH_ORDINARY_STAKING_KEY,
PATH_MULTISIG_STAKING_KEY,

// DRep key
// m / 1852' / 1815' / account' / 3 / address_index
PATH_DREP_KEY,

// constitutional committee hot key TODO not approved yet https://github.com/Ryun1/CIPs/blob/conway-keys/CIP-conway-keys/README.md
// m / 1852' / 1815' / account' / 4 / address_index
PATH_COMMITTEE_COLD_KEY,
// constitutional committee cold key TODO not approved yet
// m / 1852' / 1815' / account' / 5 / address_index
PATH_COMMITTEE_HOT_KEY,

// native token minting/burning
PATH_MINT_KEY,

Expand Down
38 changes: 35 additions & 3 deletions src/securityPolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ security_policy_t policyForDerivePrivateKey(const bip44_path_t* path)
case PATH_MULTISIG_SPENDING_KEY:
case PATH_MULTISIG_STAKING_KEY:

case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:

case PATH_MINT_KEY:

case PATH_POOL_COLD_KEY:
Expand Down Expand Up @@ -162,6 +166,9 @@ security_policy_t policyForGetExtendedPublicKey(const bip44_path_t* pathSpec)
case PATH_ORDINARY_STAKING_KEY:
case PATH_MULTISIG_SPENDING_KEY:
case PATH_MULTISIG_STAKING_KEY:
case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:
case PATH_CVOTE_KEY:
WARN_UNLESS(bip44_isPathReasonable(pathSpec));
// ask for permission (it is unusual if client asks this instead of the account key)
Expand All @@ -187,6 +194,9 @@ security_policy_t policyForGetExtendedPublicKeyBulkExport(const bip44_path_t* pa
case PATH_MULTISIG_ACCOUNT:
case PATH_MULTISIG_SPENDING_KEY:
case PATH_MULTISIG_STAKING_KEY:
case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:
case PATH_MINT_KEY:
case PATH_CVOTE_ACCOUNT:
case PATH_CVOTE_KEY:
Expand All @@ -197,7 +207,7 @@ security_policy_t policyForGetExtendedPublicKeyBulkExport(const bip44_path_t* pa

case PATH_POOL_COLD_KEY:
WARN_UNLESS(bip44_isPathReasonable(pathSpec));
// but ask for permission when pool cold key is requested
// but ask for permission
PROMPT();
break;

Expand Down Expand Up @@ -1391,15 +1401,30 @@ static inline security_policy_t _ordinaryWitnessPolicy(const bip44_path_t* path,
switch (bip44_classifyPath(path)) {
case PATH_ORDINARY_SPENDING_KEY:
case PATH_ORDINARY_STAKING_KEY:
// ordinary key paths can be hidden if they are not unusual
// (the user saw all outputs not belonging to him, withdrawals and certificates,
// those belong to him in an ORDINARY txs thanks to
// keys being displayed by paths instead of hashes)
DENY_IF(violatesSingleAccountOrStoreIt(path));
WARN_UNLESS(bip44_isPathReasonable(path));
SHOW_IF(app_mode_expert());
ALLOW();
break;

case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:
// these have to be shown because the tx might contain
// an action proposal that cannot be fully shown on the device
// TODO what about violation of single account policy?
DENY_IF(violatesSingleAccountOrStoreIt(path));
WARN_UNLESS(bip44_isPathReasonable(path));
SHOW();
break;

case PATH_POOL_COLD_KEY:
// ordinary key paths and pool cold key paths can be hidden if they are not unusual
// (the user saw all outputs, withdrawals and pool certificates and they all belong to him)
// could be hidden perhaps, but it's safer to let the user to know
// the SW wallet wants to sign with the stake pool key
WARN_UNLESS(bip44_isPathReasonable(path));
SHOW();
break;
Expand Down Expand Up @@ -1439,6 +1464,7 @@ static inline security_policy_t _multisigWitnessPolicy(const bip44_path_t* path,

default:
// ordinary and pool cold keys forbidden
// DRep and committee keys forbidden
DENY();
break;
}
Expand Down Expand Up @@ -1709,6 +1735,12 @@ static bool is_required_signer_allowed(bip44_path_t* path)
case PATH_MULTISIG_STAKING_KEY:
return true;

case PATH_DREP_KEY:
case PATH_COMMITTEE_COLD_KEY:
case PATH_COMMITTEE_HOT_KEY:
// no known use case, but also no reason to deny
return true;

case PATH_MINT_KEY:
return true;

Expand Down

0 comments on commit 537cadc

Please sign in to comment.