Skip to content

Commit dba6c37

Browse files
g2flyermbrandenburger
authored andcommitted
Peer Assistance Utility
* handles so far attestations to evidence conversion, stubs but no implementation yet for client request and response processing * peer assistance utility integrated in peer for initEnclave * some refactoring of managment api to make above easier and more consistent * credentials are now also base64 encoded on initEnclave return flow (as in spec) * client_sdk is now also included into global make * a few missing gitignores Signed-off-by: michael steiner <[email protected]>
1 parent 89f489a commit dba6c37

File tree

15 files changed

+165
-65
lines changed

15 files changed

+165
-65
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
TOP = .
77
include $(TOP)/build.mk
88

9-
SUB_DIRS = protos common internal ercc ecc_enclave ecc tlcc_enclave tlcc fabric examples utils integration # demo # docs
9+
SUB_DIRS = protos common internal ercc ecc_enclave ecc tlcc_enclave tlcc fabric client_sdk examples utils integration # demo # docs
1010

1111
FPC_SDK_DEP_DIRS = protos utils/fabric common ecc_enclave ecc
1212
FPC_PEER_DEP_DIRS = protos common ercc tlcc_enclave tlcc fabric ecc_enclave ecc

client_sdk/Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright IBM Corp. All Rights Reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
TOP = ..
6+
include $(TOP)/build.mk
7+
8+
SUB_DIRS = go
9+
10+
all build test clean clobber:
11+
$(foreach DIR, $(SUB_DIRS), $(MAKE) -C $(DIR) $@ || exit ;)

client_sdk/go/Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright IBM Corp. All Rights Reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
TOP = ../..
6+
include $(TOP)/build.mk
7+
8+
SUB_DIRS = fpc test
9+
10+
all build test clean clobber:
11+
$(foreach DIR, $(SUB_DIRS), $(MAKE) -C $(DIR) $@ || exit ;)

client_sdk/go/fpc/Makefile

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2019 Intel Corporation
2+
# Copyright IBM Corp. All Rights Reserved.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
TOP = ../../..
7+
include $(TOP)/build.mk
8+
9+
build:
10+
$(GO) build
11+
12+
test:
13+
$(GO) test $(GOTAGS) -v ./...
14+
15+
clean:
16+
$(GO) clean

client_sdk/go/fpc/management.go

+21-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"fmt"
1313
"log"
1414

15-
"github.com/golang/protobuf/proto"
1615
"github.com/hyperledger-labs/fabric-private-chaincode/client_sdk/go/fpc/attestation"
1716
"github.com/hyperledger-labs/fabric-private-chaincode/internal/protos"
1817
pbatt "github.com/hyperledger-labs/fabric-private-chaincode/internal/protos/attestation"
@@ -76,28 +75,39 @@ func (c *managementState) InitEnclave(peerEndpoint string, attestationParams ...
7675
}
7776

7877
log.Printf("calling __initEnclave\n")
79-
credentialsBytes, err := txn.Evaluate(utils.ProtoAsBase64(initMsg))
78+
credentialsBytes, err := txn.Evaluate(utils.MarshallProto(initMsg))
8079
if err != nil {
8180
return fmt.Errorf("evaluation error: %s", err)
8281
}
8382

84-
credentials := &protos.Credentials{}
85-
err = proto.Unmarshal(credentialsBytes, credentials)
83+
var convertedCredentials string
84+
convertedCredentials, err = ConvertCredentials(string(credentialsBytes))
8685
if err != nil {
87-
return fmt.Errorf("cannot unmarshal credentials: %s", err)
86+
return fmt.Errorf("evaluation error: %s", err)
8887
}
8988

90-
// perform attestation evidence transformation
91-
credentials, err = attestation.ToEvidence(credentials)
89+
log.Printf("calling registerEnclave\n")
90+
_, err = c.ercc.SubmitTransaction("registerEnclave", convertedCredentials)
9291
if err != nil {
9392
return err
9493
}
9594

96-
log.Printf("calling registerEnclave\n")
97-
_, err = c.ercc.SubmitTransaction("registerEnclave", utils.ProtoAsBase64(credentials))
95+
return nil
96+
}
97+
98+
// perform attestation evidence transformation
99+
func ConvertCredentials(credentialsOnlyAttestation string) (credentialsWithEvidence string, err error) {
100+
log.Printf("Received Credential: '%s'", credentialsOnlyAttestation)
101+
credentials, err := utils.UnmarshalCredentials(credentialsOnlyAttestation)
98102
if err != nil {
99-
return err
103+
return "", fmt.Errorf("cannot decode credentials: %s", err)
100104
}
101105

102-
return nil
106+
credentials, err = attestation.ToEvidence(credentials)
107+
if err != nil {
108+
return "", err
109+
}
110+
credentialsOnlyAttestation = utils.MarshallProto(credentials)
111+
log.Printf("Converted to Credential: '%s'", credentialsOnlyAttestation)
112+
return credentialsOnlyAttestation, nil
103113
}

client_sdk/go/test/.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
test
3+
wallet
4+
keystore

ecc_mock/chaincode/ecc.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
77
package chaincode
88

99
import (
10+
"encoding/base64"
1011
"fmt"
1112

1213
"github.com/golang/protobuf/ptypes"
@@ -72,7 +73,7 @@ func (t *EnclaveChaincode) initEnclave(stub shim.ChaincodeStubInterface) pb.Resp
7273
}
7374

7475
// return credentials
75-
return shim.Success(credentialsBytes)
76+
return shim.Success([]byte(base64.StdEncoding.EncodeToString(credentialsBytes)))
7677
}
7778

7879
func (t *EnclaveChaincode) invoke(stub shim.ChaincodeStubInterface) pb.Response {

ercc/registry/registry.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,9 @@ func (rs *Contract) RegisterEnclave(ctx contractapi.TransactionContextInterface,
229229
return err
230230
}
231231

232-
// TODO check if this enclave is already registered
232+
// TODO check if this enclave is already registered (MVP)
233233

234-
// TODO perform the (enclave) endorsement policy specific tests:
234+
// TODO perform the (enclave) endorsement policy specific tests (MVP/Post-MVP)
235235
// - MVP (designated chaincode): verify no other enclave (of other peers) is registered or fail
236236
// - Post-MVP: check consistency with potentially existing enclaves
237237

@@ -288,10 +288,10 @@ func checkAttestedData(ctx contractapi.TransactionContextInterface, v attestatio
288288
return fmt.Errorf("creator identity evaluation failed: %s", err)
289289
}
290290

291-
// TODO add more checks
292-
// channel_hash should correspond to peers view of channel id (POST-MVP)
293-
// TLCC_MRENCLAVE matches the version baked into ERCC (POST-MVP)
294-
// validate FPC deployment (restriction) policy (POST-MVP)
291+
// TODO add more checks (POST-MVP)
292+
// - channel_hash should correspond to peers view of channel id
293+
// - TLCC_MRENCLAVE matches the version baked into ERCC
294+
// - validate FPC deployment (restriction) policy
295295

296296
return nil
297297
}
@@ -300,25 +300,23 @@ func checkAttestedData(ctx contractapi.TransactionContextInterface, v attestatio
300300
// This method is used during the key generation and key distribution protocol. In particular, during key generation,
301301
// this call sets the chaincode_ek for a chaincode if no chaincode_ek is set yet.
302302
func (rs *Contract) RegisterCCKeys(ctx contractapi.TransactionContextInterface, ccKeyRegistrationMessageBase64 string) error {
303-
// TODO: Implement me for MVP
303+
// TODO: Implement me once we remove spec-short-cut,see QueryChaincodeEncryptionKey (Post-MVP)
304304

305305
//input msg CCKeyRegistrationMessage
306306

307-
// TODO needs to be implemented for tx args/response encryption
308-
309307
return fmt.Errorf("not implemented yet")
310308
}
311309

312310
// key distribution (Post-MVP features)
313311
func (rs *Contract) PutKeyExport(ctx contractapi.TransactionContextInterface, exportMessageBase64 string) error {
314312
// input msg ExportMessage
315-
// TODO implement me
313+
// TODO implement me (Post-MVP)
316314
return fmt.Errorf("not implemented yet")
317315
}
318316

319317
func (rs *Contract) GetKeyExport(ctx contractapi.TransactionContextInterface, chaincodeId, enclaveId string) (string, error) {
320318
//input chaincodeId string, enclaveId string
321319
//return *ExportMessage or error
322-
// TODO implement me
320+
// TODO implement me (Post-MVP)
323321
return "", fmt.Errorf("not implemented yet")
324322
}

fabric/bin/lib/common_ledger.sh

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
: ${FABRIC_PATH:="${FPC_TOP_DIR}/../../hyperledger/fabric/"}
1515
: ${FABRIC_BIN_DIR:="${FABRIC_PATH}/build/bin"}
16+
: ${FABRIC_UTIL_BIN_DIR:="${FPC_TOP_DIR}/utils/fabric"}
1617

1718
FABRIC_SCRIPTDIR="${FPC_TOP_DIR}/fabric/bin/"
1819

@@ -27,6 +28,7 @@ ledger_precond_check() {
2728
[ -x "${FABRIC_BIN_DIR}/peer" ] || die "peer command does not exist in '${FABRIC_BIN_DIR}'"
2829
[ -x "${FABRIC_BIN_DIR}/orderer" ] || die "orderer command does not exist in '${FABRIC_BIN_DIR}'"
2930
[ -x "${FABRIC_BIN_DIR}/configtxgen" ] || die "configtxgen command does not exist in '${FABRIC_BIN_DIR}'"
31+
[ -x "${FABRIC_UTIL_BIN_DIR}/peer-cli-assist" ] || die "peer-cli-assist command does not exist in '${FABRIC_UTIL_BIN_DIR}'"
3032
[ ! -z "${FABRIC_STATE_DIR}" ] || die "Undefined fabric ledger state directory '${FABRIC_STATE_DIR}'"
3133
}
3234

@@ -38,6 +40,7 @@ define_common_vars() {
3840
# use our wrapper for commands, so provide convience functions ..
3941
# note: as we might have defined FABRIC_CFG_PATH in this script, we have the pass it along!
4042
PEER_CMD="env FABRIC_CFG_PATH=${FABRIC_CFG_PATH} ${FABRIC_SCRIPTDIR}/peer.sh"
43+
PEER_ASSIST_CMD="${FABRIC_UTIL_BIN_DIR}/peer-cli-assist"
4144
ORDERER_CMD="env FABRIC_CFG_PATH=${FABRIC_CFG_PATH} ${FABRIC_SCRIPTDIR}/orderer.sh"
4245
CONFIGTXGEN_CMD="env FABRIC_CFG_PATH=${FABRIC_CFG_PATH} ${FABRIC_SCRIPTDIR}/configtxgen.sh"
4346

fabric/bin/peer.sh

+3-19
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,6 @@ handle_lifecycle_chaincode_initEnclave() {
442442
# set the default attestation params
443443
ATTESTATION_PARAMS=$(jq -c -n --arg atype "simulated" '{attestation_type: $atype}' | base64 --wrap=0)
444444
else
445-
die "initEnclave unavailable in HW mode -- need format fix in attestation conversion"
446-
447445
SPID_FILE_PATH="${SGX_CREDENTIALS_PATH}/spid.txt"
448446
SPID_TYPE_FILE_PATH="${SGX_CREDENTIALS_PATH}/spid_type.txt"
449447
[ -f "${SPID_FILE_PATH}" ] || die "no spid file ${SPID_FILE_PATH}"
@@ -483,25 +481,11 @@ handle_lifecycle_chaincode_initEnclave() {
483481
say "initEnclave response (decoded): $(echo "${B64CREDS}" | base64 -d)"
484482

485483
say "Convert credentials"
486-
TMPCREDSFILE=$(mktemp)
487-
say "temp file: ${TMPCREDSFILE}"
488-
echo ${B64CREDS} | base64 -d | protoc --decode fpc.Credentials --proto_path=${FPC_TOP_DIR}/protos/fpc --proto_path=${FPC_TOP_DIR}/protos/fabric ${FPC_TOP_DIR}/protos/fpc/fpc.proto > ${TMPCREDSFILE}
489-
DECODED_CREDENTIALS=$(cat ${TMPCREDSFILE})
490-
ATTESTATION=${DECODED_CREDENTIALS##*attestation: \"}
491-
ATTESTATION=${ATTESTATION%%\"}
492-
ATTESTATION=$(echo ${ATTESTATION} | sed 's/\\//g')
493-
source ${FPC_TOP_DIR}/common/crypto/attestation-api/conversion/attestation_to_evidence.sh
494-
attestation_to_evidence ${ATTESTATION}
495-
# escape non-escaped quotes: (i) escape all quotes, replace double-escaped quotes with single-escaped quotes
496-
EVIDENCE=$(echo ${EVIDENCE} | sed 's/\"/\\\"/g')
497-
EVIDENCE=$(echo ${EVIDENCE} | sed 's/\\\\\"/\\\"/g')
498-
echo "evidence: \"${EVIDENCE}\"" >> ${TMPCREDSFILE}
499-
DECODED_CREDENTIALS=$(cat ${TMPCREDSFILE})
500-
B64CREDS=$(echo ${DECODED_CREDENTIALS} | protoc --encode fpc.Credentials --proto_path=${FPC_TOP_DIR}/protos/fpc --proto_path=${FPC_TOP_DIR}/protos/fabric ${FPC_TOP_DIR}/protos/fpc/fpc.proto | base64 --wrap=0)
501-
say "initEnclave converted response (b64): ${B64CREDS}"
484+
B64CONVCREDS=$(echo "${B64CREDS}" | ${PEER_ASSIST_CMD} attestation2Evidence) || die "could not convert credentials"
485+
say "initEnclave converted response (b64): ${B64CONVCREDS}"
502486

503487
say "Registering with Enclave Registry"
504-
try $RUN ${FABRIC_BIN_DIR}/peer chaincode invoke -o ${ORDERER_ADDR} -C ${CHAN_ID} -n ${ERCC_ID} -c '{"Args":["RegisterEnclave", "'${B64CREDS}'"]}' --waitForEvent
488+
try $RUN ${FABRIC_BIN_DIR}/peer chaincode invoke -o ${ORDERER_ADDR} -C ${CHAN_ID} -n ${ERCC_ID} -c '{"Args":["RegisterEnclave", "'${B64CONVCREDS}'"]}' --waitForEvent
505489

506490
# NOTE: the chaincode encryption key is retrieved here for testing purposes
507491
say "Querying Chaincode Encryption Key"

internal/utils/proto.go

+17-17
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,10 @@ import (
1919
"github.com/hyperledger/fabric/protoutil"
2020
)
2121

22-
func ProtoAsBase64(msg proto.Message) string {
22+
func MarshallProto(msg proto.Message) string {
2323
return base64.StdEncoding.EncodeToString(protoutil.MarshalOrPanic(msg))
2424
}
2525

26-
// returns enclave_id as hex-encoded string of SHA256 hash over enclave_vk.
27-
func GetEnclaveId(attestedData *protos.AttestedData) string {
28-
h := sha256.Sum256(attestedData.EnclaveVk)
29-
return hex.EncodeToString(h[:])
30-
}
31-
32-
func ExtractEndpoint(credentials *protos.Credentials) (string, error) {
33-
attestedData := &protos.AttestedData{}
34-
err := ptypes.UnmarshalAny(credentials.SerializedAttestedData, attestedData)
35-
if err != nil {
36-
return "", err
37-
}
38-
39-
return attestedData.HostParams.PeerEndpoint, nil
40-
}
41-
4226
func UnmarshalCredentials(credentialsBase64 string) (*protos.Credentials, error) {
4327
credentialsBytes, err := base64.StdEncoding.DecodeString(credentialsBase64)
4428
if err != nil {
@@ -56,3 +40,19 @@ func UnmarshalCredentials(credentialsBase64 string) (*protos.Credentials, error)
5640
}
5741
return credentials, nil
5842
}
43+
44+
// returns enclave_id as hex-encoded string of SHA256 hash over enclave_vk.
45+
func GetEnclaveId(attestedData *protos.AttestedData) string {
46+
h := sha256.Sum256(attestedData.EnclaveVk)
47+
return hex.EncodeToString(h[:])
48+
}
49+
50+
func ExtractEndpoint(credentials *protos.Credentials) (string, error) {
51+
attestedData := &protos.AttestedData{}
52+
err := ptypes.UnmarshalAny(credentials.SerializedAttestedData, attestedData)
53+
if err != nil {
54+
return "", err
55+
}
56+
57+
return attestedData.HostParams.PeerEndpoint, nil
58+
}

utils/fabric/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# SPDX-License-Identifier: Apache-2.0
22
get-fabric-container-name
3+
peer-cli-assist

utils/fabric/Makefile

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
TOP = ../..
77
include $(TOP)/build.mk
88

9-
GO_CMDS= get-fabric-container-name
9+
GO_CMDS= get-fabric-container-name peer-cli-assist
1010

11-
build: ${GO_CMDS}
11+
build: $(GO_CMDS)
1212

13-
${GO_CMDS}: ${GO_CMDS:=.go}
14-
$(GO) build $(GOTAGS) $@.go
13+
$(GO_CMDS):
14+
$(GO) build $(GOTAGS) ./$@.src/$@.go
1515

1616
test: build
1717

1818
clean:
19-
$(GO) clean
19+
$(RM) $(GO_CMDS)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2019 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package main
8+
9+
import (
10+
"fmt"
11+
"io/ioutil"
12+
"os"
13+
14+
"github.com/hyperledger-labs/fabric-private-chaincode/client_sdk/go/fpc"
15+
)
16+
17+
func printHelp() {
18+
fmt.Printf(
19+
`Usage: %s [attestation2Evidence | createEncryptRequest | processEncryptedResponse]
20+
- attestation2Evidence: convert attestation to evidence in (base64-encoded) Credentials protobuf
21+
- createEncryptRequest: create a (base64-encoded) encrypted fpc chaincode request protobuf
22+
- processEncryptedResponse: decrypt and validate an (base64-encoded) encrypted fpc chaincode response protobuf
23+
Input and outpus are via stdin and stdout, respectively.`,
24+
os.Args[0])
25+
}
26+
27+
func main() {
28+
29+
if len(os.Args) < 2 {
30+
fmt.Fprintf(os.Stderr, "ERROR: expected a subcommand\n")
31+
printHelp()
32+
os.Exit(1)
33+
}
34+
35+
switch os.Args[1] {
36+
case "attestation2Evidence":
37+
credentialsIn, err := ioutil.ReadAll(os.Stdin)
38+
if err != nil {
39+
fmt.Fprintf(os.Stderr, "ERROR: couldn't read stdin: %v\n", err)
40+
os.Exit(1)
41+
}
42+
credentialsStringOut, err := fpc.ConvertCredentials(string(credentialsIn))
43+
if err != nil {
44+
fmt.Fprintf(os.Stderr, "ERROR: couldn't convert credentials: %v\n", err)
45+
os.Exit(1)
46+
}
47+
fmt.Printf("%s\n", credentialsStringOut)
48+
case "createEncryptRequest":
49+
fmt.Fprintf(os.Stderr, "FATAL: command %s not yet implemented\n", os.Args[1])
50+
os.Exit(1)
51+
case "processEncryptedResponse":
52+
fmt.Fprintf(os.Stderr, "FATAL: command %s not yet implemented\n", os.Args[1])
53+
os.Exit(1)
54+
default:
55+
fmt.Fprintf(os.Stderr, "ERROR: Illegal command '%s'\n", os.Args[1])
56+
printHelp()
57+
os.Exit(1)
58+
}
59+
60+
os.Exit(0)
61+
}

0 commit comments

Comments
 (0)