forked from hyperledger/fabric-private-chaincode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathercc.go
187 lines (157 loc) · 5.85 KB
/
ercc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"strings"
"github.com/hyperledger-labs/fabric-private-chaincode/ercc/attestation"
"github.com/hyperledger/fabric-chaincode-go/shim"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/flogging"
)
var logger = flogging.MustGetLogger("ercc")
func main() {
// start chaincode
// err := shim.Start(NewTestErcc())
err := shim.Start(NewErcc())
if err != nil {
logger.Errorf("Error starting registry chaincode: %s", err)
}
}
// EnclaveRegistryCC ...
type EnclaveRegistryCC struct {
ra attestation.Verifier
ias attestation.IntelAttestationService
}
// NewErcc is a helpful factory method for creating this beauty
func NewErcc() *EnclaveRegistryCC {
logger.Debug("NewErcc called")
return &EnclaveRegistryCC{
ra: attestation.GetVerifier(),
ias: attestation.GetIAS(),
}
}
func NewTestErcc() *EnclaveRegistryCC {
return &EnclaveRegistryCC{
ra: &attestation.MockVerifier{},
ias: &attestation.MockIAS{},
}
}
// Init setups the EnclaveRegistry by initializing intel verification key. Currently this is hardcoded!
func (ercc *EnclaveRegistryCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
logger.Debug("Init called")
return shim.Success(nil)
}
// Invoke receives transactions and forwards to op handlers
func (ercc *EnclaveRegistryCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
logger.Debugf("Invoke(function=%s, %s) called", function, args)
if function == "registerEnclave" {
return ercc.registerEnclave(stub, args)
} else if function == "getAttestationReport" { //get enclave attestation report
return ercc.getAttestationReport(stub, args)
} else if function == "getSPID" { //get SPID
return ercc.getSPID(stub, args)
}
return shim.Error("Received unknown function invocation: " + function)
}
// ============================================================
// registerEnclave -
// ============================================================
func (ercc *EnclaveRegistryCC) registerEnclave(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// args:
// 0: enclavePkBase64
// 1: quoteBase64
// 2: apiKey
// if apiKey not available as argument we try to read them from decorator
if len(args) < 2 {
return shim.Error("Incorrect number of arguments. Expecting enclave pk and quote to register")
}
enclavePkAsBytes, err := base64.StdEncoding.DecodeString(args[0])
if err != nil {
return shim.Error("Can not parse enclavePkHash: " + err.Error())
}
quoteBase64 := args[1]
quoteAsBytes, err := base64.StdEncoding.DecodeString(quoteBase64)
if err != nil {
return shim.Error("Can not parse quoteBase64 string: " + err.Error())
}
// get ercc api key for IAS
var apiKey string
if len(args) >= 3 {
apiKey = args[2]
} else {
apiKey = string(stub.GetDecorations()["apiKey"])
}
apiKey = strings.TrimSpace(apiKey) // make sure there are no trailing newlines and alike ..
logger.Debugf("registerEnclave: api-key: %s / len(args)=%d", apiKey, len(args))
// send quote to intel for verification
attestationReport, err := ercc.ias.RequestAttestationReport(apiKey, quoteAsBytes)
if err != nil {
return shim.Error("Error while retrieving attestation report: " + err.Error())
}
// TODO get verification public key from ledger
verificationPK, err := ercc.ias.GetIntelVerificationKey()
if err != nil {
return shim.Error("Can not parse verifiaction key: " + err.Error())
}
// verify attestation report
isValid, err := ercc.ra.VerifyAttestationReport(verificationPK, attestationReport)
if err != nil {
return shim.Error("Error while attestation report verification: " + err.Error())
}
if !isValid {
return shim.Error("Attestation report is not valid")
}
// first verify that enclavePkHash matches the one in the attestation report
isValid, err = ercc.ra.CheckEnclavePkHash(enclavePkAsBytes, attestationReport)
if err != nil {
return shim.Error("Error while checking enclave PK: " + err.Error())
}
if !isValid {
return shim.Error("Enclave PK does not match attestation report!")
}
// set enclave public key in attestation report
attestationReport.EnclavePk = enclavePkAsBytes
// store attestation report under enclavePk hash in state
attestationReportAsBytes, err := json.Marshal(attestationReport)
if err != nil {
return shim.Error(err.Error())
}
// create hash of enclave pk
enclavePkHash := sha256.Sum256(enclavePkAsBytes)
enclavePkHashBase64 := base64.StdEncoding.EncodeToString(enclavePkHash[:])
err = stub.PutState(enclavePkHashBase64, attestationReportAsBytes)
return shim.Success(nil)
}
// ============================================================
// getAttestationReport -
// ============================================================
func (ercc *EnclaveRegistryCC) getAttestationReport(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var err error
// 0
// "enclavePkHashBase64"
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting pk of the enclave to query")
}
enclavePkHashBase64 := args[0]
attestationReport, err := stub.GetState(enclavePkHashBase64) //get attestationREPORT for enclavePK from chaincode state
if err != nil {
return shim.Error("Failed to get state for " + enclavePkHashBase64)
} else if attestationReport == nil {
return shim.Error("EnclavePK does not exist: " + enclavePkHashBase64)
}
return shim.Success(attestationReport)
}
// ============================================================
// getSPID -
// ============================================================
func (ercc *EnclaveRegistryCC) getSPID(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// return spid from IASCredentialProvider
return shim.Success(stub.GetDecorations()["SPID"])
// return shim.Success(ercc.iascp.GetSPID())
}