Skip to content

Commit

Permalink
go/common/crypto/signature/signers/remote: Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
Yawning committed Feb 26, 2020
1 parent 33f872b commit f83c880
Show file tree
Hide file tree
Showing 37 changed files with 1,036 additions and 80 deletions.
2 changes: 2 additions & 0 deletions .buildkite/code.pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ steps:
- buildkite-agent artifact upload oasis-test-runner
- cd /workdir/go/oasis-net-runner
- buildkite-agent artifact upload oasis-net-runner
- cd /workdir/go/oasis-remote-signer
- buildkite-agent artifact upload oasis-remote-signer
plugins:
<<: *docker_plugin

Expand Down
3 changes: 2 additions & 1 deletion .buildkite/scripts/download_e2e_test_artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ set -euxo pipefail

source .buildkite/scripts/common.sh

# Oasis node, test runner and runtime loader.
# Oasis node, test runner, remote signer and runtime loader.
download_artifact oasis-node go/oasis-node 755
download_artifact integrationrunner.test go/oasis-node/integrationrunner 755
download_artifact oasis-test-runner go/oasis-test-runner 755
download_artifact oasis-remote-signer go/oasis-remote-signer 755
download_artifact oasis-core-runtime-loader target/default/debug 755

# Key manager runtime.
Expand Down
1 change: 1 addition & 0 deletions .buildkite/scripts/test_e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ${WORKDIR}/go/oasis-test-runner/oasis-test-runner \
--e2e.runtime.binary_dir ${WORKDIR}/target/${runtime_target}/debug \
--e2e.runtime.loader ${WORKDIR}/target/default/debug/oasis-core-runtime-loader \
--e2e.tee_hardware ${OASIS_TEE_HARDWARE:-""} \
--remote_signer.binary ${WORKDIR}/go/oasis-remote-signer/oasis-remote-signer \
--log.level info \
${BUILDKITE_PARALLEL_JOB_COUNT:+--parallel.job_count ${BUILDKITE_PARALLEL_JOB_COUNT}} \
${BUILDKITE_PARALLEL_JOB:+--parallel.job_index ${BUILDKITE_PARALLEL_JOB}} \
Expand Down
5 changes: 5 additions & 0 deletions .changelog/2686.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
go/common/crypto/signature/signers/remote: Add experimental remote signer

This commit adds an experimental remote signer, reference remote signer
implementation, and theoretically allows the node to be ran with a
non-file based signer backend.
1 change: 1 addition & 0 deletions go/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ oasis-node/oasis-node
oasis-node/integrationrunner/integrationrunner.test
oasis-test-runner/oasis-test-runner
oasis-net-runner/oasis-net-runner
oasis-remote-signer/oasis-remote-signer
storage/mkvs/urkel/interop/urkel-test-helpers
2 changes: 1 addition & 1 deletion go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ all: build

# Build.
# List of Go binaries to build.
go-binaries := oasis-node oasis-test-runner oasis-net-runner extra/stats
go-binaries := oasis-node oasis-test-runner oasis-net-runner oasis-remote-signer extra/stats
# List of test helpers to build.
test-helpers := urkel
# List of test vectors to generate.
Expand Down
39 changes: 37 additions & 2 deletions go/common/crypto/signature/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@ var (
errUnregisteredContext = errors.New("signature: unregistered context")
errNoChainContext = errors.New("signature: chain domain separation context not set")

registeredContexts sync.Map
registeredContexts sync.Map
allowUnregisteredContexts bool

chainContextLock sync.RWMutex
chainContext Context

// SignerRoles is the list of all supported signer roles.
SignerRoles = []SignerRole{
SignerEntity,
SignerNode,
SignerP2P,
SignerConsensus,
}
)

type contextOptions struct {
Expand Down Expand Up @@ -111,6 +120,19 @@ func UnsafeResetChainContext() {
chainContext = Context("")
}

// UnsafeAllowUnregisteredContexts bypasses the context registration check.
//
// This function is only for the benefit of implementing a remote signer.
func UnsafeAllowUnregisteredContexts() {
allowUnregisteredContexts = true
}

// IsUnsafeUnregisteredContextsAllowed returns true iff context registration
// checks are bypassed.
func IsUnsafeUnregisteredContextsAllowed() bool {
return allowUnregisteredContexts
}

// SetChainContext configures the chain domain separation context that is
// used with any contexts constructed using the WithChainSeparation option.
func SetChainContext(rawContext string) {
Expand All @@ -137,10 +159,12 @@ const (
SignerNode
SignerP2P
SignerConsensus

// If you add to this, also add the new roles to SignerRoles.
)

// SignerFactoryCtor is an SignerFactory constructor.
type SignerFactoryCtor func(interface{}, ...SignerRole) SignerFactory
type SignerFactoryCtor func(interface{}, ...SignerRole) (SignerFactory, error)

// SignerFactory is the opaque factory interface for Signers.
type SignerFactory interface {
Expand Down Expand Up @@ -187,6 +211,17 @@ type UnsafeSigner interface {

// PrepareSignerContext prepares a context for use during signing by a Signer.
func PrepareSignerContext(context Context) ([]byte, error) {
// The remote signer implementation uses the raw context, and
// registration is dealt with client side. Just check that the
// length is sensible, even though the client should be sending
// something sane.
if allowUnregisteredContexts {
if cLen := len(context); cLen == 0 || cLen > ed25519.ContextMaxSize {
return nil, errMalformedContext
}
return []byte(context), nil
}

// Ensure that the context is registered for use.
rawOpts, isRegistered := registeredContexts.Load(context)
if !isRegistered {
Expand Down
10 changes: 10 additions & 0 deletions go/common/crypto/signature/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,14 @@ func TestContext(t *testing.T) {
msg3, err := PrepareSignerMessage(chainCtx, []byte("message"))
require.NoError(err, "PrepareSignerMessage should work")
require.NotEqual(msg2, msg3, "messages for different contexts should be different")

// The remote signer requires bypassing the context registration checks.
UnsafeAllowUnregisteredContexts()
defer func() {
allowUnregisteredContexts = false
}()
require.True(IsUnsafeUnregisteredContextsAllowed(), "context registration must be bypassed")

_, err = PrepareSignerMessage(unregCtx, []byte("message"))
require.NoError(err, "PrepareSignerMessage should work with unregisered context (bypassed)")
}
6 changes: 3 additions & 3 deletions go/common/crypto/signature/signers/file/file_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ var (

// NewFactory creates a new factory with the specified roles, with the
// specified dataDir.
func NewFactory(config interface{}, roles ...signature.SignerRole) signature.SignerFactory {
func NewFactory(config interface{}, roles ...signature.SignerRole) (signature.SignerFactory, error) {
dataDir, ok := config.(string)
if !ok {
panic("invalid file signer configuration provided")
return nil, errors.New("signature/signer/file: invalid file signer configuration provided")
}

return &Factory{
roles: append([]signature.SignerRole{}, roles...),
dataDir: dataDir,
}
}, nil
}

// Factory is a PEM file backed SignerFactory.
Expand Down
3 changes: 2 additions & 1 deletion go/common/crypto/signature/signers/file/file_signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ func TestFileSigner(t *testing.T) {
defer os.RemoveAll(tmpDir)

rolePEMFiles[signature.SignerUnknown] = "unit_test.pem"
factory := NewFactory(tmpDir, signature.SignerUnknown)
factory, err := NewFactory(tmpDir, signature.SignerUnknown)
require.NoError(err, "NewFactory()")

// Missing, no generate.
_, err = factory.Load(signature.SignerUnknown)
Expand Down
6 changes: 3 additions & 3 deletions go/common/crypto/signature/signers/ledger/ledger_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ type FactoryConfig struct {
}

// NewFactory creates a new factory with the specified roles.
func NewFactory(config interface{}, roles ...signature.SignerRole) signature.SignerFactory {
func NewFactory(config interface{}, roles ...signature.SignerRole) (signature.SignerFactory, error) {
ledgerConfig, ok := config.(*FactoryConfig)
if !ok {
panic("invalid Ledger signer configuration provided")
return nil, fmt.Errorf("invalid Ledger signer configuration provided")
}
return &Factory{
roles: append([]signature.SignerRole{}, roles...),
address: ledgerConfig.Address,
index: ledgerConfig.Index,
}
}, nil
}

// EnsureRole ensures that the SignatureFactory is configured for the given
Expand Down
Loading

0 comments on commit f83c880

Please sign in to comment.