Skip to content

Commit

Permalink
Add client node TEE freshness verification
Browse files Browse the repository at this point in the history
  • Loading branch information
peternose committed Sep 5, 2022
1 parent bed69f6 commit 6e537f9
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 4 deletions.
1 change: 1 addition & 0 deletions .changelog/4922.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add client node TEE freshness verification
20 changes: 20 additions & 0 deletions go/runtime/host/protocol/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"reflect"

"github.com/tendermint/tendermint/crypto/merkle"

beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/cbor"
Expand All @@ -14,6 +16,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/sgx/quote"
"github.com/oasisprotocol/oasis-core/go/common/version"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
consensusTx "github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
"github.com/oasisprotocol/oasis-core/go/roothash/api/commitment"
Expand Down Expand Up @@ -109,6 +112,8 @@ type Body struct {
HostFetchTxBatchResponse *HostFetchTxBatchResponse `json:",omitempty"`
HostFetchGenesisHeightRequest *HostFetchGenesisHeightRequest `json:",omitempty"`
HostFetchGenesisHeightResponse *HostFetchGenesisHeightResponse `json:",omitempty"`
HostProveFreshnessRequest *HostProveFreshnessRequest `json:",omitempty"`
HostProveFreshnessResponse *HostProveFreshnessResponse `json:",omitempty"`
}

// Type returns the message type by determining the name of the first non-nil member.
Expand Down Expand Up @@ -503,3 +508,18 @@ type HostFetchTxBatchResponse struct {
// Batch is a batch of transactions.
Batch [][]byte `json:"batch,omitempty"`
}

// HostProveFreshnessRequest is a request to host to prove state freshness.
type HostProveFreshnessRequest struct {
Blob [32]byte `json:"blob"`
}

// HostProveFreshnessResponse is a response from host proving state freshness.
type HostProveFreshnessResponse struct {
// Signed prove freshness transaction.
SignedTx *consensusTx.SignedTransaction `json:"signed_tx"`
// Height at which the transaction was published.
Height uint64 `json:"height"`
// Merkle proof of inclusion.
Proof *merkle.Proof `json:"proof"`
}
74 changes: 74 additions & 0 deletions go/runtime/registry/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ package registry

import (
"context"
"crypto/sha256"
"fmt"
"reflect"

"github.com/tendermint/tendermint/crypto/merkle"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
"github.com/oasisprotocol/oasis-core/go/runtime/host/protocol"
runtimeKeymanager "github.com/oasisprotocol/oasis-core/go/runtime/keymanager/api"
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
Expand Down Expand Up @@ -113,3 +120,70 @@ func handlerHostFetchTxBatchRequest(ctx context.Context, h *runtimeHostHandler,
Batch: raw,
}, nil
}

func handlerHostProveFreshnessRequest(ctx context.Context, h *runtimeHostHandler, rq *protocol.HostProveFreshnessRequest) (*protocol.HostProveFreshnessResponse, error) {
// Subscribe before submit as we don't want to miss the block with the transaction.
blockCh, blockSub, err := h.consensus.WatchBlocks(ctx)
if err != nil {
return nil, err
}
defer blockSub.Close()

// Prepare, sign and submit prove freshness transaction.
identity, err := h.env.GetIdentity(ctx)
if err != nil {
return nil, err
}
tx := registry.NewProveFreshnessTx(0, nil, rq.Blob)
sigTx, err := consensus.SignAndSubmitTx(ctx, h.consensus, identity.NodeSigner, tx)
if err != nil {
return nil, err
}
cborTx := cbor.Marshal(sigTx)

// Once transaction is included in a block, construct Merkle proof of inclusion and send it
// as a response back to the runtime.
loop:
for {
select {
case block, ok := <-blockCh:
if !ok {
break loop
}

// Check inclusion.
txs, err := h.consensus.GetTransactions(ctx, block.Height)
if err != nil {
return nil, err
}
idx := -1
for i, tx := range txs {
if reflect.DeepEqual(tx, cborTx) {
idx = i
break
}
}
if idx < 0 {
continue
}

// Merkle tree is computed over hashes and not over transactions.
hashes := make([][]byte, 0, len(txs))
for _, tx := range txs {
hash := sha256.Sum256(tx)
hashes = append(hashes, hash[:])
}
_, proofs := merkle.ProofsFromByteSlices(hashes)

return &protocol.HostProveFreshnessResponse{
SignedTx: sigTx,
Height: uint64(block.Height),
Proof: proofs[idx],
}, nil
case <-ctx.Done():
break loop
}
}

return nil, fmt.Errorf("failed to prove freshness: ProveFreshness transaction not published in a block")
}
6 changes: 6 additions & 0 deletions go/runtime/registry/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/eapache/channels"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/identity"
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/version"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
Expand Down Expand Up @@ -150,6 +151,9 @@ type RuntimeHostHandlerEnvironment interface {

// GetTxPool returns the transaction pool for this runtime.
GetTxPool(ctx context.Context) (txpool.TransactionPool, error)

// GetIdentity returns the identity of a node running this runtime.
GetIdentity(ctx context.Context) (*identity.Identity, error)
}

// RuntimeHostHandler is a runtime host handler suitable for compute runtimes. It provides the
Expand Down Expand Up @@ -182,6 +186,8 @@ func (h *runtimeHostHandler) Handle(ctx context.Context, rq *protocol.Body) (*pr
rsp.HostFetchGenesisHeightResponse, err = handlerHostFetchGenesisHeightRequest(ctx, h, rq.HostFetchGenesisHeightRequest)
case rq.HostFetchTxBatchRequest != nil:
rsp.HostFetchTxBatchResponse, err = handlerHostFetchTxBatchRequest(ctx, h, rq.HostFetchTxBatchRequest)
case rq.HostProveFreshnessRequest != nil:
rsp.HostProveFreshnessResponse, err = handlerHostProveFreshnessRequest(ctx, h, rq.HostProveFreshnessRequest)
default:
err = errMethodNotSupported
}
Expand Down
6 changes: 6 additions & 0 deletions go/worker/common/committee/runtime_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package committee
import (
"context"

"github.com/oasisprotocol/oasis-core/go/common/identity"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
"github.com/oasisprotocol/oasis-core/go/runtime/host"
"github.com/oasisprotocol/oasis-core/go/runtime/host/protocol"
Expand Down Expand Up @@ -44,6 +45,11 @@ func (env *nodeEnvironment) GetTxPool(ctx context.Context) (txpool.TransactionPo
return env.n.TxPool, nil
}

// GetIdentity implements RuntimeHostHandlerEnvironment.
func (env *nodeEnvironment) GetIdentity(ctx context.Context) (*identity.Identity, error) {
return env.n.Identity, nil
}

// NewRuntimeHostHandler implements RuntimeHostHandlerFactory.
func (n *Node) NewRuntimeHostHandler() protocol.Handler {
return runtimeRegistry.NewRuntimeHostHandler(&nodeEnvironment{n}, n.Runtime, n.Consensus)
Expand Down
13 changes: 13 additions & 0 deletions runtime/src/common/crypto/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,19 @@ pub struct SignatureBundle {
pub signature: Signature,
}

impl SignatureBundle {
/// Verify returns true iff the signature is valid over the given context
/// and message.
pub fn verify(&self, context: &[u8], message: &[u8]) -> bool {
let pk = match self.public_key {
Some(pk) => pk,
None => return false,
};

self.signature.verify(&pk, context, message).is_ok()
}
}

/// A abstract signer.
pub trait Signer: Send + Sync {
/// Generates a signature over the context and message.
Expand Down
Loading

0 comments on commit 6e537f9

Please sign in to comment.