@@ -13,6 +13,7 @@ import (
13
13
"crypto/hmac"
14
14
"crypto/rand"
15
15
"crypto/sha256"
16
+ "crypto/subtle"
16
17
"encoding/base64"
17
18
"encoding/json"
18
19
"errors"
@@ -336,13 +337,7 @@ func (vh *VerificationHelper) onVerificationKey(ctx context.Context, txn Verific
336
337
return
337
338
}
338
339
if ! bytes .Equal (commitment , txn .Commitment ) {
339
- err := vh .sendVerificationEvent (ctx , txn , event .InRoomVerificationCancel , & event.VerificationCancelEventContent {
340
- Code : event .VerificationCancelCodeKeyMismatch ,
341
- Reason : "The key was not the one we expected." ,
342
- })
343
- if err != nil {
344
- log .Err (err ).Msg ("Failed to send cancellation event" )
345
- }
340
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeKeyMismatch , "The key was not the one we expected" )
346
341
return
347
342
}
348
343
} else {
@@ -593,12 +588,15 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn Verific
593
588
// Verifying Keys MAC
594
589
log .Info ().Msg ("Verifying MAC for all sent keys" )
595
590
var hasTheirDeviceKey bool
591
+ var masterKey string
596
592
var keyIDs []string
597
593
for keyID := range macEvt .MAC {
598
594
keyIDs = append (keyIDs , keyID .String ())
599
595
_ , kID := keyID .Parse ()
600
596
if kID == txn .TheirDeviceID .String () {
601
597
hasTheirDeviceKey = true
598
+ } else {
599
+ masterKey = kID
602
600
}
603
601
}
604
602
slices .Sort (keyIDs )
@@ -617,6 +615,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn Verific
617
615
}
618
616
619
617
// Verify the MAC for each key
618
+ var theirDevice * id.Device
620
619
for keyID , mac := range macEvt .MAC {
621
620
log .Info ().Str ("key_id" , keyID .String ()).Msg ("Received MAC for key" )
622
621
@@ -627,8 +626,11 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn Verific
627
626
}
628
627
629
628
var key string
630
- var theirDevice * id.Device
631
629
if kID == txn .TheirDeviceID .String () {
630
+ if theirDevice != nil {
631
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeInvalidMessage , "two keys found for their device ID" )
632
+ return
633
+ }
632
634
theirDevice , err = vh .mach .GetOrFetchDevice (ctx , txn .TheirUserID , txn .TheirDeviceID )
633
635
if err != nil {
634
636
vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to fetch their device: %w" , err )
@@ -653,22 +655,60 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn Verific
653
655
vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to calculate key MAC: %w" , err )
654
656
return
655
657
}
656
- if ! bytes . Equal (expectedMAC , mac ) {
658
+ if subtle . ConstantTimeCompare (expectedMAC , mac ) == 0 {
657
659
vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeSASMismatch , "MAC mismatch for key %s" , keyID )
658
660
return
659
661
}
662
+ }
663
+ log .Info ().Msg ("All MACs verified" )
660
664
661
- // Trust their device
662
- if kID == txn .TheirDeviceID .String () {
663
- theirDevice .Trust = id .TrustStateVerified
664
- err = vh .mach .CryptoStore .PutDevice (ctx , txn .TheirUserID , theirDevice )
665
+ // Trust their device
666
+ theirDevice .Trust = id .TrustStateVerified
667
+ err = vh .mach .CryptoStore .PutDevice (ctx , txn .TheirUserID , theirDevice )
668
+ if err != nil {
669
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to update device trust state after verifying: %w" , err )
670
+ return
671
+ }
672
+
673
+ if txn .TheirUserID == vh .client .UserID {
674
+ // Self-signing situation.
675
+ //
676
+ // If we have the cross-signing keys, then we need to sign their device
677
+ // using the self-signing key. Otherwise, they have the master private
678
+ // key, so we need to trust the master public key.
679
+ if vh .mach .CrossSigningKeys != nil {
680
+ err = vh .mach .SignOwnDevice (ctx , theirDevice )
665
681
if err != nil {
666
- vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to update device trust state after verifying : %w" , err )
682
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to sign our own new device : %w" , err )
667
683
return
668
684
}
685
+ } else {
686
+ err = vh .mach .SignOwnMasterKey (ctx )
687
+ if err != nil {
688
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeUser , "failed to sign our own master key: %w" , err )
689
+ return
690
+ }
691
+ }
692
+ } else if masterKey != "" {
693
+ // Cross-signing situation.
694
+ //
695
+ // The master key was included in the list of keys to verify, so verify
696
+ // that it matches what we expect and sign their master key using the
697
+ // user-signing key.
698
+ theirSigningKeys , err := vh .mach .GetCrossSigningPublicKeys (ctx , txn .TheirUserID )
699
+ if err != nil {
700
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeKeyMismatch , "couldn't get %s's cross-signing keys: %w" , txn .TheirUserID , err )
701
+ return
702
+ } else if theirSigningKeys .MasterKey .String () != masterKey {
703
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeKeyMismatch , "master keys do not match" )
704
+ return
705
+ }
706
+
707
+ if err := vh .mach .SignUser (ctx , txn .TheirUserID , theirSigningKeys .MasterKey ); err != nil {
708
+ vh .cancelVerificationTxn (ctx , txn , event .VerificationCancelCodeInternalError , "failed to sign their master key: %w" , err )
709
+ return
669
710
}
670
711
}
671
- log .Info ().Msg ("All MACs verified" )
672
712
673
713
txn .ReceivedTheirMAC = true
674
714
if txn .SentOurMAC {
0 commit comments