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

ADR 0019: Key Manager Policy Improvements #10

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions 0019-key-manager-policy-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# ADR 0019: Key Manager Policy Improvements

## Component

Oasis Core

## Changelog

- {date}: {changelog}

## Status

Proposed

## Context

The initial key manager design uses a dynamic policy for access control,
that is signed by a hard-coded set of signers. While the current design
is functional, there are several "ease of use" type improvements that can
be made to how policies and their signatures are handled.

## Decision

### KM Enclave Status changes

To facilitate extra verification at the consensus layer, the per-key manager
instance runtime status field is to be extended as follows:

```golang
type Status struct {
// ... existing fields omitted ...

// BaseSigners is the list of allowed policy signers, as hard-coded in
// the enclave binary.
BaseSigners []signature.PublicKey `json:"base_signers,omitempty"`

// BaseSignerThreshold is the number of valid signatures that are required
// for a policy, as hard-coded in the enclave binary.
BaseSignerThreshold uint32 `json:"base_signer_threshold,omitempty"`
}
```

The ordering of the elements in the `BaseSigners` list is not explicitly
specified beyond the fact that it MUST be globally consistent across all
deployments of a given enclave binary.

It is also emphasized that, the list is of the hard-coded policy signers,
as of the time the enclave binary was built.

### KM Policy Updates

The existing key manager `UpdatePolicy` method is to be deprecated, and
replaced with the following methods.

```golang

type PolicyProposal struct {
// The unsigned policy.
Policy PolicySGX `json:"policy"`

// Manually collected signatures.
Signatures []signature.Signatures `json:"signatures,omitempty"`

// XXX: Specify some sort of voting period... or hardcode it? idk.
}

type PolicyVote struct {
// The policy serial number that this vote is for.
Serial uint32 `json:"serial"`
// The runtime ID that this vote is for.
ID common.Namespace `json:"id"`

// The signature over the PolicyProposal.Policy.
Signature signature.Signature `json:"signature"`
}

// TODO: Document the backend extensions.

var (
MethodPolicyPropose = transaction.NewMethodName(ModuleName, "PolicyPropose", PolicyProposal{})
MethodPolicyVote = transaction.NewMethodName(ModuleName, "PolicyVote", PolicyVote{})
)
```

Like with `UpdatePolicy`, the new update process is initiated by the owner
of the KM runtime in question, but now with a `PolicyProposal`.

If other entities support the update, they will sign the policy and submit
the signature as a `PolicyVote` transaction.

On the consensus side, votes:
- Must be for an open (not expired) `PolicyProposal`
- Must be signed by a public key that is part of `Status.BaseSigners`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the key must not be revoked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do revocation, yeah. Like I said, I'm not convinced it's worth the complexity.


Once the number of signatures (be them from `PolicyProposal.Signatures` or
`PolicyVote`s) is greater than `Status.BaseSignerThreshold`, the policy
is considered ratified, and will take effect on the key managers nodes.

As a special case to support legacy KM runtime deployments, `UpdatePolicy`
transactions submitted for existing runtimes, that both have an empty
`Status.BaseSigners` list AND a `0` `Status.BaseSignerThreshold`, are
treated as ratified iff `UpdatePolicy.Signatures` contains more than one
valid signature.

### KM Key Revocation

A new key manager method `PolicyRevokeKey` is to be added.

```golang
var (
MethodPolicyRevokeKey = transaction.NewMethodName(ModuleName, "PolicyRevokeKey", struct{})
)

type Backend interface {
// Existing methods omitted....

GetRevocations(context.Context, int64) ([]signature.PublicKey, error)
}
```

Submitting a `PolicyRevokeKey` transaction, will invalidate the signing key
for the purpose of ratifying key manager policies. Note that revocations
are expected to take effect the next time various nodes re-attest (the light
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the enclave should fetch the latest revocation list each time before accepting any policy update (similar to how policy publication is checked) instead of on re-attestation?

Obviously the consensus layer will also enforce the revocation policy before accepting PolicyVotes so verifying publication is implicitly verifying the revocation list.

I guess the question is what happens with existing policies signed by the revoked key? Could they become invalid retroactively? I think this would be bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of allowing for revoking existing policies, but in retrospect that probably isn't the best of ideas. I am not entirely convinced that revocation is actually useful either. I would say "Surely people store their keys properly, and we use a large/disjoint enough committee size", but this industry is full of morons like those involved in the Ronin Bridge stupidity, so that's probably not realistic.

client MUST pull down the revocation list).

## Consequences

### Positive

It will be significantly easier to update key manager policies as the tabulation
of signatures will be done on-chain.

Revocation may be a more expedient emergency halt mechanism than the alternatives.

### Negative

This adds non-trivial amount of complexity for, what realitically is a process
that a handful of people will ever need to do.

### Neutral

## References

> Are there any relevant PR comments, issues that led up to this, or articles
> referenced for why we made the given design choice? If so, link them here.

- {reference link}