Skip to content

Commit

Permalink
Add support for signed output from runtime (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
bendecoste authored Mar 27, 2023
1 parent d46aae6 commit b155b6f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 22 deletions.
17 changes: 15 additions & 2 deletions cape.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
package cli

import "github.com/capeprivacy/attest/attest"

type Checksums struct {
Input []byte `json:"input"`
Function []byte `json:"function"`
Output []byte `json:"output"`
}

type RunResult struct {
Type string `json:"type"`
Message []byte `json:"message"`
Type string `json:"type"`
Message []byte `json:"message"`
Checksums Checksums `json:"checksums"`
SignedChecksums []byte `json:"signed_checksums"`

DecodedAttestationDocument *attest.AttestationDoc `json:"decoded_attestation_document"`
RawAttestationDocument []byte `json:"raw_attestation_document"`
}
14 changes: 12 additions & 2 deletions cmd/cape/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (

"github.com/spf13/cobra"

"github.com/capeprivacy/attest/attest"

"github.com/capeprivacy/cli"

"github.com/capeprivacy/cli/entities"
Expand Down Expand Up @@ -228,8 +230,16 @@ func runPlain(result cli.RunResult) error {

func runJSON(result cli.RunResult) error {
return json.NewEncoder(os.Stdout).Encode(struct {
Output string `json:"output"`
Output string `json:"output"`
Checksums cli.Checksums `json:"checksums"`
SignedResults []byte `json:"signed_results"`
AttestationDoc *attest.AttestationDoc `json:"attestation_doc"`
RawAttestationDoc []byte `json:"raw_attestation_doc"`
}{
Output: string(result.Message),
Output: string(result.Message),
Checksums: result.Checksums,
SignedResults: result.SignedChecksums,
AttestationDoc: result.DecodedAttestationDocument,
RawAttestationDoc: result.RawAttestationDocument,
})
}
7 changes: 4 additions & 3 deletions sdk/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import (
)

type AttestationUserData struct {
FuncChecksum []byte `json:"func_checksum"`
KeyChecksum []byte `json:"key_checksum"`
CapeKey []byte `json:"key"`
FuncChecksum []byte `json:"func_checksum"`
KeyChecksum []byte `json:"key_checksum"`
CapeKey []byte `json:"key"`
SignatureVerificationKey []byte `json:"signature_verification_public_key"`
}

type KeyRequest struct {
Expand Down
59 changes: 44 additions & 15 deletions sdk/run.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package sdk

import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/json"
"fmt"
"reflect"
Expand All @@ -12,7 +16,7 @@ import (
"github.com/capeprivacy/cli"

"github.com/capeprivacy/attest/attest"
"github.com/capeprivacy/cli/crypto"
capeCrypto "github.com/capeprivacy/cli/crypto"
"github.com/capeprivacy/cli/entities"
"github.com/capeprivacy/cli/pcrs"
)
Expand All @@ -30,6 +34,11 @@ type RunRequest struct {
Insecure bool
}

type attestationDoc struct {
decoded *attest.AttestationDoc
raw []byte
}

// Run loads the given function into a secure enclave and invokes it on the given data, then returns the result.
func Run(req RunRequest) (*cli.RunResult, error) {
conn, doc, err := connect(req.URL, req.FunctionID, req.FunctionAuth, req.FuncChecksum, req.KeyChecksum, req.PcrSlice, req.Insecure)
Expand All @@ -43,7 +52,7 @@ func Run(req RunRequest) (*cli.RunResult, error) {
return invoke(doc, conn, req.Data)
}

func connect(url string, functionID string, functionAuth entities.FunctionAuth, funcChecksum []byte, keyChecksum []byte, pcrSlice []string, insecure bool) (*websocket.Conn, *attest.AttestationDoc, error) {
func connect(url string, functionID string, functionAuth entities.FunctionAuth, funcChecksum []byte, keyChecksum []byte, pcrSlice []string, insecure bool) (*websocket.Conn, *attestationDoc, error) {
endpoint := fmt.Sprintf("%s/v1/run/%s", url, functionID)

authProtocolType := "cape.runtime"
Expand All @@ -54,7 +63,7 @@ func connect(url string, functionID string, functionAuth entities.FunctionAuth,
return nil, nil, err
}

nonce, err := crypto.GetNonce()
nonce, err := capeCrypto.GetNonce()
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -114,20 +123,14 @@ func connect(url string, functionID string, functionAuth entities.FunctionAuth,
return nil, nil, fmt.Errorf("returned key policy checksum did not match provided, got: %x, want %x", userData.KeyChecksum, keyChecksum)
}

return conn, doc, nil
return conn, &attestationDoc{
decoded: doc,
raw: attestDoc,
}, nil
}

func invoke(doc *attest.AttestationDoc, conn *websocket.Conn, data []byte) (*cli.RunResult, error) {
if doc == nil {
log.Error("missing attestation document, you may need to run cape.Connect()")
return nil, errors.New("missing attestation document")
}
if conn == nil {
log.Error("missing websocket connection, you may need to run cape.Connect()")
return nil, errors.New("no active connection")
}

encryptedData, err := crypto.LocalEncrypt(*doc, data)
func invoke(attestDoc *attestationDoc, conn *websocket.Conn, data []byte) (*cli.RunResult, error) {
encryptedData, err := capeCrypto.LocalEncrypt(*attestDoc.decoded, data)
if err != nil {
log.Println("error encrypting")
return nil, err
Expand All @@ -146,6 +149,32 @@ func invoke(doc *attest.AttestationDoc, conn *websocket.Conn, data []byte) (*cli
return nil, err
}
log.Debugf("< Received Function Results.")
resData.DecodedAttestationDocument = attestDoc.decoded
resData.RawAttestationDocument = attestDoc.raw

log.Debugf("* Verifying Function Results.")

// TODO -- connect is already doing this
var ud AttestationUserData
if err := json.Unmarshal(attestDoc.decoded.UserData, &ud); err != nil {
return nil, err
}

publicKey, err := x509.ParsePKCS1PublicKey(ud.SignatureVerificationKey)
if err != nil {
return nil, err
}

c := sha256.New()
if err := json.NewEncoder(c).Encode(resData.Checksums); err != nil {
return nil, err
}

if err := rsa.VerifyPSS(publicKey, crypto.SHA256, c.Sum(nil), resData.SignedChecksums, nil); err != nil {
return nil, err
}

log.Debugf("* Function Results Verified")

return resData, nil
}
Expand Down

0 comments on commit b155b6f

Please sign in to comment.