forked from mautrix/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcross_sign_validation.go
129 lines (122 loc) · 4.78 KB
/
cross_sign_validation.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
// Copyright (c) 2020 Nikos Filippakis
// Copyright (c) 2024 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package crypto
import (
"context"
"maunium.net/go/mautrix/id"
)
func (mach *OlmMachine) ResolveTrust(device *id.Device) id.TrustState {
state, _ := mach.ResolveTrustContext(context.Background(), device)
return state
}
// ResolveTrustContext resolves the trust state of the device from cross-signing.
func (mach *OlmMachine) ResolveTrustContext(ctx context.Context, device *id.Device) (id.TrustState, error) {
if device.Trust == id.TrustStateVerified || device.Trust == id.TrustStateBlacklisted {
return device.Trust, nil
}
theirKeys, err := mach.CryptoStore.GetCrossSigningKeys(ctx, device.UserID)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).
Str("user_id", device.UserID.String()).
Msg("Error retrieving cross-signing key of user from database")
return id.TrustStateUnset, err
}
theirMSK, ok := theirKeys[id.XSUsageMaster]
if !ok {
mach.machOrContextLog(ctx).Debug().
Str("user_id", device.UserID.String()).
Msg("Master key of user not found")
return id.TrustStateUnset, nil
}
theirSSK, ok := theirKeys[id.XSUsageSelfSigning]
if !ok {
mach.machOrContextLog(ctx).Error().
Str("user_id", device.UserID.String()).
Msg("Self-signing key of user not found")
return id.TrustStateUnset, nil
}
sskSigExists, err := mach.CryptoStore.IsKeySignedBy(ctx, device.UserID, theirSSK.Key, device.UserID, theirMSK.Key)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).
Str("user_id", device.UserID.String()).
Msg("Error retrieving cross-signing signatures for master key of user from database")
return id.TrustStateUnset, err
}
if !sskSigExists {
mach.machOrContextLog(ctx).Error().
Str("user_id", device.UserID.String()).
Msg("Self-signing key of user is not signed by their master key")
return id.TrustStateUnset, nil
}
deviceSigExists, err := mach.CryptoStore.IsKeySignedBy(ctx, device.UserID, device.SigningKey, device.UserID, theirSSK.Key)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).
Str("user_id", device.UserID.String()).
Str("device_key", device.SigningKey.String()).
Msg("Error retrieving cross-signing signatures for device from database")
return id.TrustStateUnset, err
}
if deviceSigExists {
if trusted, err := mach.IsUserTrusted(ctx, device.UserID); !trusted {
return id.TrustStateCrossSignedVerified, err
} else if theirMSK.Key == theirMSK.First {
return id.TrustStateCrossSignedTOFU, nil
}
return id.TrustStateCrossSignedUntrusted, nil
}
return id.TrustStateUnset, nil
}
// IsDeviceTrusted returns whether a device has been determined to be trusted either through verification or cross-signing.
func (mach *OlmMachine) IsDeviceTrusted(device *id.Device) bool {
switch mach.ResolveTrust(device) {
case id.TrustStateVerified, id.TrustStateCrossSignedTOFU, id.TrustStateCrossSignedVerified:
return true
default:
return false
}
}
// IsUserTrusted returns whether a user has been determined to be trusted by our user-signing key having signed their master key.
// In the case the user ID is our own and we have successfully retrieved our cross-signing keys, we trust our own user.
func (mach *OlmMachine) IsUserTrusted(ctx context.Context, userID id.UserID) (bool, error) {
csPubkeys := mach.GetOwnCrossSigningPublicKeys(ctx)
if csPubkeys == nil {
return false, nil
}
if userID == mach.Client.UserID {
return true, nil
}
// first we verify our user-signing key
ourUserSigningKeyTrusted, err := mach.CryptoStore.IsKeySignedBy(ctx, mach.Client.UserID, csPubkeys.UserSigningKey, mach.Client.UserID, csPubkeys.MasterKey)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).Msg("Error retrieving our self-signing key signatures from database")
return false, err
} else if !ourUserSigningKeyTrusted {
return false, nil
}
theirKeys, err := mach.CryptoStore.GetCrossSigningKeys(ctx, userID)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).
Str("user_id", userID.String()).
Msg("Error retrieving cross-signing key of user from database")
return false, err
}
theirMskKey, ok := theirKeys[id.XSUsageMaster]
if !ok {
mach.machOrContextLog(ctx).Error().
Str("user_id", userID.String()).
Msg("Master key of user not found")
return false, nil
}
sigExists, err := mach.CryptoStore.IsKeySignedBy(ctx, userID, theirMskKey.Key, mach.Client.UserID, csPubkeys.UserSigningKey)
if err != nil {
mach.machOrContextLog(ctx).Error().Err(err).
Str("user_id", userID.String()).
Msg("Error retrieving cross-signing signatures for master key of user from database")
return false, err
}
return sigExists, nil
}