@@ -61,6 +61,88 @@ func validateAttestation(attestation *identity.Attestation, messageBytes string)
6161 return nil
6262}
6363
64+ // Parse 'identity.CounterAttestedMembership' object and extract structures
65+ func parseCounterAttestedMembership (counterAttestedMembershipSerialized string ) (* identity.CounterAttestedMembership , * identity.CounterAttestedMembership_AttestedMembershipSet , * common.Membership , error ) {
66+ counterAttestedMembership , err := decodeCounterAttestedMembership (counterAttestedMembershipSerialized )
67+ if err != nil {
68+ return nil , nil , nil , fmt .Errorf ("Counter Attested Membership Unmarshal error: %s" , err )
69+ }
70+ decodedAttestedMembershipSet , err := base64 .StdEncoding .DecodeString (counterAttestedMembership .AttestedMembershipSet )
71+ if err != nil {
72+ return nil , nil , nil , fmt .Errorf ("Attested membership set could not be decoded from base64: %s" , err .Error ())
73+ }
74+ var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
75+ err = protoV2 .Unmarshal (decodedAttestedMembershipSet , & attestedMembershipSet )
76+ if err != nil {
77+ return nil , nil , nil , fmt .Errorf ("Unable to unmarshal attested membership set: %s" , err .Error ())
78+ }
79+ decodedForeignMembership , err := base64 .StdEncoding .DecodeString (attestedMembershipSet .Membership )
80+ if err != nil {
81+ return nil , nil , nil , fmt .Errorf ("Foreign membership could not be decoded from base64: %s" , err .Error ())
82+ }
83+ var foreignMembership common.Membership
84+ err = protoV2 .Unmarshal (decodedForeignMembership , & foreignMembership )
85+ if err != nil {
86+ return nil , nil , nil , fmt .Errorf ("Unable to unmarshal membership: %s" , err .Error ())
87+ }
88+ return counterAttestedMembership , & attestedMembershipSet , & foreignMembership , nil
89+ }
90+
91+ // Validate 'identity.CounterAttestedMembership' object and its embedded structures
92+ func validateCounterAttestedMembership (s * SmartContract , ctx contractapi.TransactionContextInterface , counterAttestedMembership * identity.CounterAttestedMembership , attestedMembershipSet * identity.CounterAttestedMembership_AttestedMembershipSet , foreignMembership * common.Membership ) error {
93+ var err error
94+
95+ // Match nonces across all attestations, local and foreign
96+ matchedNonce := ""
97+ for _ , attestation := range append (counterAttestedMembership .Attestations , attestedMembershipSet .Attestations ... ) {
98+ if matchedNonce == "" {
99+ matchedNonce = attestation .Nonce
100+ } else {
101+ if matchedNonce != attestation .Nonce {
102+ return fmt .Errorf ("Mismatched nonces across two attestations: %s, %s" , matchedNonce , attestation .Nonce )
103+ }
104+ }
105+ }
106+
107+ // Ensure valid attestations from all local IIN Agents
108+ for _ , attestation := range counterAttestedMembership .Attestations {
109+ err = validateAttestation (attestation , counterAttestedMembership .AttestedMembershipSet + attestation .Nonce )
110+ if err != nil {
111+ return err
112+ }
113+ }
114+
115+ // Validate foreign membership cert chains
116+ err = validateMemberCertChains (foreignMembership )
117+ if err != nil {
118+ return err
119+ }
120+
121+ // Ensure authentic and valid attestations from all foreign IIN Agents
122+ for _ , attestation := range attestedMembershipSet .Attestations {
123+ if attestation .UnitIdentity .SecurityDomain != foreignMembership .SecurityDomain {
124+ return fmt .Errorf ("Foreign agent security domain %s does not match attested membership security domain %s" ,
125+ attestation .UnitIdentity .SecurityDomain , foreignMembership .SecurityDomain )
126+ }
127+ attesterCert , err := parseCert (attestation .Certificate )
128+ if err != nil {
129+ return fmt .Errorf ("Unable to parse attester certificate" )
130+ }
131+ err = verifyMemberInSecurityDomain2 (s , ctx , "" , attesterCert , foreignMembership , attestation .UnitIdentity .MemberId )
132+ if err != nil {
133+ return fmt .Errorf ("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v" ,
134+ attesterCert , attestation .UnitIdentity .MemberId , attestation .UnitIdentity .SecurityDomain , err )
135+ }
136+ // Validate signature
137+ err = validateAttestation (attestation , attestedMembershipSet .Membership + attestation .Nonce )
138+ if err != nil {
139+ return err
140+ }
141+ }
142+
143+ return nil
144+ }
145+
64146// CreateLocalMembership cc is used to store the local security domain's Membership in the ledger
65147func (s * SmartContract ) CreateLocalMembership (ctx contractapi.TransactionContextInterface , membershipJSON string ) error {
66148 // Check if the caller has network admin privileges
@@ -162,27 +244,10 @@ func (s *SmartContract) CreateMembership(ctx contractapi.TransactionContextInter
162244 return fmt .Errorf ("Caller with identity %+v is not a designated IIN Agent of org %s: %+v" , callerId , callerMemberUnit , err )
163245 }
164246
165- counterAttestedMembership , err := decodeCounterAttestedMembership (counterAttestedMembershipSerialized )
247+ // Parse the counter attested membership structure and extract the relevant objects
248+ counterAttestedMembership , attestedMembershipSet , foreignMembership , err := parseCounterAttestedMembership (counterAttestedMembershipSerialized )
166249 if err != nil {
167- return fmt .Errorf ("Counter Attested Membership Unmarshal error: %s" , err )
168- }
169- decodedAttestedMembershipSet , err := base64 .StdEncoding .DecodeString (counterAttestedMembership .AttestedMembershipSet )
170- if err != nil {
171- return fmt .Errorf ("Attested membership set could not be decoded from base64: %s" , err .Error ())
172- }
173- var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
174- err = protoV2 .Unmarshal (decodedAttestedMembershipSet , & attestedMembershipSet )
175- if err != nil {
176- return fmt .Errorf ("Unable to unmarshal attested membership set: %s" , err .Error ())
177- }
178- decodedForeignMembership , err := base64 .StdEncoding .DecodeString (attestedMembershipSet .Membership )
179- if err != nil {
180- return fmt .Errorf ("Foreign membership could not be decoded from base64: %s" , err .Error ())
181- }
182- var foreignMembership common.Membership
183- err = protoV2 .Unmarshal (decodedForeignMembership , & foreignMembership )
184- if err != nil {
185- return fmt .Errorf ("Unable to unmarshal membership: %s" , err .Error ())
250+ return err
186251 }
187252
188253 // Check presence of membership on ledger first
@@ -195,54 +260,12 @@ func (s *SmartContract) CreateMembership(ctx contractapi.TransactionContextInter
195260 return fmt .Errorf ("Membership already exists for membership id: %s. Use 'UpdateMembership' to update." , foreignMembership .SecurityDomain )
196261 }
197262
198- // Match nonces across all attestations, local and foreign
199- matchedNonce := ""
200- for _ , attestation := range append (counterAttestedMembership .Attestations , attestedMembershipSet .Attestations ... ) {
201- if matchedNonce == "" {
202- matchedNonce = attestation .Nonce
203- } else {
204- if matchedNonce != attestation .Nonce {
205- return fmt .Errorf ("Mismatched nonces across two attestations: %s, %s" , matchedNonce , attestation .Nonce )
206- }
207- }
208- }
209-
210- // Ensure valid attestations from all local IIN Agents
211- for _ , attestation := range counterAttestedMembership .Attestations {
212- err = validateAttestation (attestation , counterAttestedMembership .AttestedMembershipSet + attestation .Nonce )
213- if err != nil {
214- return err
215- }
216- }
217-
218- // Validate foreign membership cert chains
219- err = validateMemberCertChains (& foreignMembership )
263+ // Validate the counter attested membership structure and the structures embedded in it
264+ err = validateCounterAttestedMembership (s , ctx , counterAttestedMembership , attestedMembershipSet , foreignMembership )
220265 if err != nil {
221266 return err
222267 }
223268
224- // Ensure authentic and valid attestations from all foreign IIN Agents
225- for _ , attestation := range attestedMembershipSet .Attestations {
226- if attestation .UnitIdentity .SecurityDomain != foreignMembership .SecurityDomain {
227- return fmt .Errorf ("Foreign agent security domain %s does not match attested membership security domain %s" ,
228- attestation .UnitIdentity .SecurityDomain , foreignMembership .SecurityDomain )
229- }
230- attesterCert , err := parseCert (attestation .Certificate )
231- if err != nil {
232- return fmt .Errorf ("Unable to parse attester certificate" )
233- }
234- err = verifyMemberInSecurityDomain2 (s , ctx , "" , attesterCert , & foreignMembership , attestation .UnitIdentity .MemberId )
235- if err != nil {
236- return fmt .Errorf ("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v" ,
237- attesterCert , attestation .UnitIdentity .MemberId , attestation .UnitIdentity .SecurityDomain , err )
238- }
239- // Validate signature
240- err = validateAttestation (attestation , attestedMembershipSet .Membership + attestation .Nonce )
241- if err != nil {
242- return err
243- }
244- }
245-
246269 membershipBytes , err := json .Marshal (foreignMembership )
247270 if err != nil {
248271 return fmt .Errorf ("Marshal error: %s" , err )
@@ -310,27 +333,10 @@ func (s *SmartContract) UpdateMembership(ctx contractapi.TransactionContextInter
310333 return fmt .Errorf ("Caller with identity %+v is not a designated IIN Agent: %+v" , callerId , err )
311334 }
312335
313- counterAttestedMembership , err := decodeCounterAttestedMembership (counterAttestedMembershipSerialized )
314- if err != nil {
315- return fmt .Errorf ("Counter Attested Membership Unmarshal error: %s" , err )
316- }
317- decodedAttestedMembershipSet , err := base64 .StdEncoding .DecodeString (counterAttestedMembership .AttestedMembershipSet )
318- if err != nil {
319- return fmt .Errorf ("Attested membership set could not be decoded from base64: %s" , err .Error ())
320- }
321- var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
322- err = protoV2 .Unmarshal (decodedAttestedMembershipSet , & attestedMembershipSet )
323- if err != nil {
324- return fmt .Errorf ("Unable to unmarshal attested membership set: %s" , err .Error ())
325- }
326- decodedForeignMembership , err := base64 .StdEncoding .DecodeString (attestedMembershipSet .Membership )
327- if err != nil {
328- return fmt .Errorf ("Foreign membership could not be decoded from base64: %s" , err .Error ())
329- }
330- var foreignMembership common.Membership
331- err = protoV2 .Unmarshal (decodedForeignMembership , & foreignMembership )
336+ // Parse the counter attested membership structure and extract the relevant objects
337+ counterAttestedMembership , attestedMembershipSet , foreignMembership , err := parseCounterAttestedMembership (counterAttestedMembershipSerialized )
332338 if err != nil {
333- return fmt . Errorf ( "Unable to unmarshal membership: %s" , err . Error ())
339+ return err
334340 }
335341
336342 // Check presence of membership on ledger first
@@ -340,54 +346,12 @@ func (s *SmartContract) UpdateMembership(ctx contractapi.TransactionContextInter
340346 return getErr
341347 }
342348
343- // Match nonces across all attestations, local and foreign
344- matchedNonce := ""
345- for _ , attestation := range append (counterAttestedMembership .Attestations , attestedMembershipSet .Attestations ... ) {
346- if matchedNonce == "" {
347- matchedNonce = attestation .Nonce
348- } else {
349- if matchedNonce != attestation .Nonce {
350- return fmt .Errorf ("Mismatched nonces across two attestations: %s, %s" , matchedNonce , attestation .Nonce )
351- }
352- }
353- }
354-
355- // Ensure valid attestations from all local IIN Agents
356- for _ , attestation := range counterAttestedMembership .Attestations {
357- err = validateAttestation (attestation , counterAttestedMembership .AttestedMembershipSet + attestation .Nonce )
358- if err != nil {
359- return err
360- }
361- }
362-
363- // Validate foreign membership cert chains
364- err = validateMemberCertChains (& foreignMembership )
349+ // Validate the counter attested membership structure and the structures embedded in it
350+ err = validateCounterAttestedMembership (s , ctx , counterAttestedMembership , attestedMembershipSet , foreignMembership )
365351 if err != nil {
366352 return err
367353 }
368354
369- // Ensure authentic and valid attestations from all foreign IIN Agents
370- for _ , attestation := range attestedMembershipSet .Attestations {
371- if attestation .UnitIdentity .SecurityDomain != foreignMembership .SecurityDomain {
372- return fmt .Errorf ("Foreign agent security domain %s does not match attested membership security domain %s" ,
373- attestation .UnitIdentity .SecurityDomain , foreignMembership .SecurityDomain )
374- }
375- attesterCert , err := parseCert (attestation .Certificate )
376- if err != nil {
377- return fmt .Errorf ("Unable to parse attester certificate" )
378- }
379- err = verifyMemberInSecurityDomain2 (s , ctx , "" , attesterCert , & foreignMembership , attestation .UnitIdentity .MemberId )
380- if err != nil {
381- return fmt .Errorf ("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v" ,
382- attesterCert , attestation .UnitIdentity .MemberId , attestation .UnitIdentity .SecurityDomain , err )
383- }
384- // Validate signature
385- err = validateAttestation (attestation , attestedMembershipSet .Membership + attestation .Nonce )
386- if err != nil {
387- return err
388- }
389- }
390-
391355 membershipBytes , err := json .Marshal (foreignMembership )
392356 if err != nil {
393357 return fmt .Errorf ("Marshal error: %s" , err )
@@ -521,7 +485,7 @@ func verifyMemberInSecurityDomain1(s *SmartContract, ctx contractapi.Transaction
521485// This takes a decoded X.509 certificate as argument (and optionally the certificate in PEM format too).
522486// It takes a membership structure as argument.
523487func verifyMemberInSecurityDomain2 (s * SmartContract , ctx contractapi.TransactionContextInterface , certPEM string , cert * x509.Certificate , membership * common.Membership , requestingOrg string ) error {
524- err := isCertificateWithinExpiry (cert )
488+ err := isCertificateWithinExpiry (cert )
525489 if err != nil {
526490 return err
527491 }
0 commit comments