-
Notifications
You must be signed in to change notification settings - Fork 91
/
fpc-key-dist.puml
304 lines (251 loc) · 12.7 KB
/
fpc-key-dist.puml
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/'
Copyright 2020 Intel Corporation
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
'/
@startuml
!pragma teoz true
hide footbox
title Foot Box removed
title Fabric Private Chaincode - Chaincode Key generation, export, and import
actor "Admin_Org1" as Admin1 order 10
participant "Peer_CLI" as Peer1_CLI order 20
participant "FPC_stub" as ECC1 order 30
participant "FPC_stub_enclave" as Enclave1 order 40 #99FF99
participant "ERCC" as ERCC1 order 50
participant "Ledger_enclave" as TLCC1 order 60 #99FF99
participant Orderer as Orderer order 100
note over TLCC1
"Full" FPC only (Post-MVP)
end note
note right Admin1
References.
- Check out the `fpc-registration` diagram for more details
on the creation and registration of the enclave credentials.
- Check out the fpc-components diagram for more details
on messages, Params and cryptographic keys used below.
end note
Admin1 -> Peer1_CLI ++: lifecycle chaincode\n initEnclave (CC_Id)
ref over Peer1_CLI
Enclave creation and registration as described in fpc-registration diagram.
end ref
note right Peer1_CLI
Once enclave creation and registration are completed,
CLI checks with the help of ERCC if Chaincode Keys are
already available. In that case no key generation is
needed and CLI may continue with Key Import protocol.
In the other case where no chaincode keys are available,
key generation is triggered as described next.
end note
Peer1_CLI -> ERCC1 +: queryChaincodeEncryptionKey(CC_Id)
ERCC1 -> ERCC1 : Chaincode_EK <- get_state(namespaces/chaincode_ek/$CC_Id)
return Chaincode_EK
Peer1_CLI -> Peer1_CLI : if Chaincode_EK empty\n than continue with key generation protocol;\n otherwise abort
group chaincode key generation
Peer1_CLI -> ECC1 ++: generateCCKeys()
ECC1 -> Enclave1 ++: ecall_generate_cc_keys()
note right Enclave1
It is not necessary to enforce that Enclave1 has already been registered in ERCC.
As this is the "first" time that keys are generated,
there is no security-critical state and/or other keys to protect.
end note
Enclave1 -> Enclave1 : check if chaincode keys already exist then abort
note right Enclave1
Generate the State Encryption Key (SEK) and the chaincode-specific encryption/decryption key pair.
end note
Enclave1 -> Enclave1 : SEK, <Chaincode_EK, Chaincode_DK> <- generate keys
note right Enclave1
- SEK denotes the state encryption key
- Chaincode_EK and Chaincode_DK denote the public and private encryption key pair
end note
Enclave1 -> Enclave1 : sealed_cckeys <- seal <SEK, Chaincode_EK, Chaincode_DK>
Enclave1 -> ECC1 ++: store sealed_cckeys
return
note right ECC1
FPC_stub stores sealed chaincode keys with the help of
the external builder on the peer local storage.
end note
Enclave1 -> Enclave1 : Sig_Enclave <- sign Chaincode_EK with Enclave_SK
note right
NOTE: Enclave signing key (Enclave_SK)
is generated during enclave creation.
end note
Enclave1 -> Enclave1 : cckey_registration_message <- <Chaincode_EK, Enclave_VK, Sig_Enclave>
return cckey_registration_message /'ECC1 -> Enclave1 '/
return cckey_registration_message /'Peer1_CLI -> ECC1 '/
loop for all/"enough" endorsers
note right Peer1_CLI
Invoke registerCCKeys() at enough endorsing peers to satisfy
ERCC endorsement policy and collect proposal responses.
end note
Peer1_CLI -> ERCC1 ++: registerCCKeys(cckey_registration_message)
ERCC1 -> ERCC1 : check that tx proposal creator is Admin
ERCC1 -> ERCC1 : check that admin.org and enclave.org match
ERCC1 -> ERCC1 : <Chaincode_EK, Enclave_VK, Sig_Enclave> <- extract from cckey_registration_message
note right ERCC1
Check enclave registration by searching for its Credentials.
end note
ERCC1 -> ERCC1 : Enclave_Id <- Hash(Enclave_VK)
ERCC1 -> ERCC1 : Credentials <- getState(namespaces/credentials/$CC_Id/$Enclave_Id)
note right
if not found; abort
end note
ERCC1 -> ERCC1 : verify Sig_Enclave over Chaincode_EK using Enclave_VK
ERCC1 -> ERCC1 : can_endorse(CC_Id, Enclave_Id)
note right
if false, abort
end note
note right ERCC1
- The can_endorse function validates that according to the chaincode definition,
this enclave is properly registered in ercc for the chaincode and can
indeed sign endorsements according to the chaincodes endorsement policy.
This is nice-to-have feature, primarily useful in the designated peer case to
catch early mismatching endorsement policies with the single registered enclave.
This function is implemented using `queryChaincodeDefinition(CC_Id)`.
end note
ERCC1 -> ERCC1 : extract CC_Id from Credentials
ERCC1 -> ERCC1 : if get_state(namespaces/chaincode_ek/$CC_Id) return empty\n then put_state(namespaces/chaincode_ek/$CC_Id, cckey_registration_message.Chaincode_EK);\n otherwise abort
ERCC1 -> ERCC1 : put_state(namespaces/provisioned/$CC_Id/$Enclave_Id, cckey_registration_message)
note right ERCC1
This is the proof (stored on the ledger) that the enclave has the CC keys.
In a multi-org setting, the proof informs of enclave availability.
end note
return proposal response /'Admin1 -> ERCC1'/
end
Peer1_CLI -> Peer1_CLI : form transaction
Peer1_CLI -> Orderer: submit registerCCKeys transaction
return
end
alt key distribution, "full" FPC only (Post-MVP)
group chaincode key export
note right Admin1
if necessary, upgrade chaincode policy to enable target Enclave endorsements
end note
Admin1 -> Peer1_CLI ++: lifecycle chaincode\n exportcckeys (CC_Id)
Peer1_CLI -> ERCC1 ++: queryListEnclaveCredentials(CC_Id)
return List<Credentials, ...> /'Admin1 -> ERCC1'/
Peer1_CLI -> Peer1_CLI : Enclave2_Credentials <- select non-provisioned (target) enclave
note right Peer1_CLI
The Credentials data structure contains
both the chaincode definition and the enclave's public signing key.
end note
Peer1_CLI -> ECC1 ++: exportCCKeys(Enclave2_Credentials)
ECC1 -> ECC1 : extract Enclave2_VK from Enclave2_Credentials
ECC1 -> Enclave1 ++: ecall_export_cc_keys(Enclave2_VK)
note right Enclave1
See above for the what can_endorse does.
Contrary to above, here we use the Ledger Enclave with
**a secure channel** (as in this context we cannot trust peer)
end note
Enclave1 -> Enclave1 : Enclave2_Id <- Hash(Enclave2_VK)
Enclave1 -> TLCC1 ++: can_endorse(CC_Id, Enclave2_Id)
note right TLCC1
Ledger_enclave checks the endorsement policy to determine
if the recipient enclave is an eligible endorser.
end note
note right TLCC1
See above for the what can_endorse does.
Contrary to above, here we **use a secure channel**
(as in this context we cannot trust peer)
end note
return true/false /'Enclave1 -> TLCC1'/
note left
if false, abort
end note
Enclave1 -> Enclave1 : cckeys_enc <- encrypt <SEK, Chaincode_DK> with Enclave2_EK
note left
Enclave encrypts state encryption key and chaincode private key for target enclave.
end note
Enclave1 -> Enclave1 : Sig_Enclave <- sign <Chaincode_EK, cckeys_enc, Enclave2_VK, Enclave_VK> with Enclave_SK
note left
Enclave signs the encrypted key material it distributes together with the
sender (enclave) and intended recipient (target enclave) identity
end note
Enclave1 -> Enclave1 : export_message <- <Chaincode_EK, cckeys_enc, Enclave2_VK, Enclave_VK, Sig_Enclave>
return export_message /'ECC1 -> Enclave1'/
return export_message /'Peer1_CLI -> ECC1'/
note right Peer1_CLI
At this point, Enclave has completed (its part of) the key distribution,
and the target enclave is waiting for the chaincode keys.
end note
note right Peer1_CLI
Chaincode key distribution is in progress. We need a means to transfer the message with
the encrypted keys to the target enclave. The next step uses the ledger
itself for this data transfer. This additionally allows to log the two phases
of the key distribution: (1) Export: the sender enclave produced the encrypted data blob;
(2) Import: the recipient enclave correctly received it. This can be useful when dealing
with enclaves of two different orgs, to show that the expected actions have been taken.
end note
loop for all/"enough" endorsers
note right Peer1_CLI
Invoke putKeyExport() at enough endorsing peers to satisfy
ERCC endorsement policy and collect proposal responses.
end note
Peer1_CLI -> ERCC1 ++: putKeyExport(export_message)
ERCC1 -> ERCC1 : <Chaincode_EK, cckeys_enc, Enclave2_VK, Enclave_VK, Sig_Enclave> <- extract from export_message
ERCC1 -> ERCC1 : check Enclave_VK's and Enclave2_VK's Credentials are registered
ERCC1 -> ERCC1 : CC_Id <- extract from Enclave_Credentials
ERCC1 -> ERCC1 : check Enclave_Credentials and Enclave2_Credentials have same CC_Id
ERCC1 -> ERCC1 : Enclave2_Id <- Hash(Enclave2_VK)
ERCC1 -> ERCC1 : can_endorse(CC_Id, Enclave2_Id)
note right
if false, abort
end note
ERCC1 -> ERCC1 : verify Sig_Enclave over <Chaincode_EK, cckeys_enc, Enclave2_VK, Enclave_VK> with Enclave_VK
ERCC1 -> ERCC1 : check Enclave previously registered export_message.Chaincode_EK
ERCC1 -> ERCC1 : check export_message.Chaincode_EK and get_state(namespaces/chaincode_ek/$CC_Id) match
ERCC1 -> ERCC1 : put_state(namespaces/exported/$CC_Id/$Enclave2_Id, export_message)
return proposal response /'Admin1 -> ERCC1'/
end loop
Peer1_CLI -> Peer1_CLI : form transaction
Peer1_CLI -> Orderer: submit CCKeysExport transaction
return
end group
group chaincode key import
note right Admin1
NOTE that import is called at another peer to provision a FPC enclave with
the keys exported in the chaincode key export flow above. In order to simplify
this diagram, only a single admin, peer, enclave, ercc is depicted even though
the import flow may involve other entities or the target / recipient enclave.
end note
Admin1 -> Peer1_CLI ++: lifecycle chaincode\n importcckeys (CC_Id)
Peer1_CLI -> ERCC1 ++: queryListEnclaveCredentials(CC_Id)
return List<Credentials, ...> /'Admin1 -> ERCC1'/
Peer1_CLI -> Peer1_CLI : check if enclave registered for this peer;\n otherwise abort
Peer1_CLI -> ECC1 ++: importCCKeys()
ECC1 -> Enclave1 ++: ecall_get_enclave_id()
return Enclave2_Id
ECC1 -> ERCC1 ++: getKeyExport(CC_Id, Enclave2_Id)
return Export_message
ECC1 -> Enclave1 ++: ecall_import_cc_keys(Export_message)
Enclave1 -> Enclave1 : check export_message is consistent with internal CC_Params
Enclave1 -> TLCC1 ++: GetMetadata() for Export_message stored at ERCC namespace; and verify
return
Enclave1 -> Enclave1 : SEK, Chaincode_DK <- decrypt Export_message.cckeys_enc with Enclave2_DK
Enclave1 -> Enclave1 : extract Chaincode_EK from Chaincode_DK
Enclave1 -> Enclave1 : sealed_cckeys <- seal <SEK, Chaincode_EK, Chaincode_DK>
Enclave1 -> ECC1 ++: store sealed_cckeys
return
note right ECC1
FPC_stub stores sealed chaincode keys with the help of
the external builder on the peer local storage.
end note
Enclave1 -> Enclave1 : Sig_Enclave2 <- sign Chaincode_EK with Enclave2_SK
Enclave1 -> Enclave1 : cckey_registration_message <- <Enclave2_VK, Sig_Enclave2, Chaincode_EK>
return cckey_registration_message /'Enclave2 -> ECC2'/
return cckey_registration_message /'ECC2 -> Peer2_CLI'/
loop for all/"enough" endorsers
note right Peer1_CLI
Invoke registerCCKeys() at enough endorsing peers to satisfy
ERCC endorsement policy and collect proposal responses.
end note
ref over Peer1_CLI
run registerCCKeys(cckey_registration_message)
end ref
end loop
Peer1_CLI -> Peer1_CLI : form transaction
Peer1_CLI -> Orderer: submit registerCCKeys transaction
return /'Admin2 -> Peer2_CLI'/
end group
end
@enduml