Expose master and self-signing keys on /devices/list hopefully

This commit is contained in:
Neil Alexander 2021-08-05 16:50:10 +01:00
parent ce5d9ecd3b
commit f4d1b50b0d
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
6 changed files with 84 additions and 17 deletions

View file

@ -52,6 +52,13 @@ func GetUserDevices(
Devices: []gomatrixserverlib.RespUserDevice{}, Devices: []gomatrixserverlib.RespUserDevice{},
} }
if masterKey, ok := sigRes.MasterKeys[userID]; ok {
response.MasterKey = &masterKey
}
if selfSigningKey, ok := sigRes.SelfSigningKeys[userID]; ok {
response.SelfSigningKey = &selfSigningKey
}
for _, dev := range res.Devices { for _, dev := range res.Devices {
var key gomatrixserverlib.RespUserDeviceKeys var key gomatrixserverlib.RespUserDeviceKeys
err := json.Unmarshal(dev.DeviceKeys.KeyJSON, &key) err := json.Unmarshal(dev.DeviceKeys.KeyJSON, &key)

View file

@ -252,6 +252,11 @@ type QuerySignaturesRequest struct {
type QuerySignaturesResponse struct { type QuerySignaturesResponse struct {
// A map of target user ID -> target key/device ID -> origin user ID -> origin key/device ID -> signatures // A map of target user ID -> target key/device ID -> origin user ID -> origin key/device ID -> signatures
Signatures map[string]map[gomatrixserverlib.KeyID]types.CrossSigningSigMap Signatures map[string]map[gomatrixserverlib.KeyID]types.CrossSigningSigMap
// A map of target user ID -> cross-signing master key
MasterKeys map[string]gomatrixserverlib.CrossSigningKey
// A map of target user ID -> cross-signing self-signing key
SelfSigningKeys map[string]gomatrixserverlib.CrossSigningKey
// The request error, if any
Error *KeyError Error *KeyError
} }

View file

@ -105,7 +105,7 @@ func (a *KeyInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.P
// If the user hasn't given a new master key, then let's go and get their // If the user hasn't given a new master key, then let's go and get their
// existing keys from the database. // existing keys from the database.
if !hasMasterKey { if !hasMasterKey {
existingKeys, err := a.DB.CrossSigningKeysForUser(ctx, req.UserID) existingKeys, err := a.DB.CrossSigningKeysDataForUser(ctx, req.UserID)
if err != nil { if err != nil {
res.Error = &api.KeyError{ res.Error = &api.KeyError{
Err: "Retrieving cross-signing keys from database failed: " + err.Error(), Err: "Retrieving cross-signing keys from database failed: " + err.Error(),
@ -405,17 +405,11 @@ func (a *KeyInternalAPI) crossSigningKeysFromDatabase(
continue continue
} }
for keyType, keyData := range keys { for keyType, key := range keys {
b64 := keyData.Encode() var keyID gomatrixserverlib.KeyID
keyID := gomatrixserverlib.KeyID("ed25519:" + b64) for id := range key.Keys {
key := gomatrixserverlib.CrossSigningKey{ keyID = id
UserID: userID, break
Usage: []gomatrixserverlib.CrossSigningKeyPurpose{
keyType,
},
Keys: map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{
keyID: keyData,
},
} }
sigs, err := a.DB.CrossSigningSigsForTarget(ctx, userID, keyID) sigs, err := a.DB.CrossSigningSigsForTarget(ctx, userID, keyID)
@ -465,7 +459,26 @@ func (a *KeyInternalAPI) crossSigningKeysFromDatabase(
func (a *KeyInternalAPI) QuerySignatures(ctx context.Context, req *api.QuerySignaturesRequest, res *api.QuerySignaturesResponse) { func (a *KeyInternalAPI) QuerySignatures(ctx context.Context, req *api.QuerySignaturesRequest, res *api.QuerySignaturesResponse) {
for targetUserID, forTargetUser := range req.TargetIDs { for targetUserID, forTargetUser := range req.TargetIDs {
for _, targetKeyID := range forTargetUser { for _, targetKeyID := range forTargetUser {
keyMap, err := a.DB.CrossSigningSigsForTarget(ctx, targetUserID, targetKeyID) keyMap, err := a.DB.CrossSigningKeysForUser(ctx, targetUserID)
if err != nil {
if err == sql.ErrNoRows {
continue
}
res.Error = &api.KeyError{
Err: fmt.Sprintf("a.DB.CrossSigningKeysForUser: %s", err),
}
}
for targetPurpose, targetKey := range keyMap {
switch targetPurpose {
case gomatrixserverlib.CrossSigningKeyPurposeMaster:
res.MasterKeys[targetUserID] = targetKey
case gomatrixserverlib.CrossSigningKeyPurposeSelfSigning:
res.SelfSigningKeys[targetUserID] = targetKey
}
}
sigMap, err := a.DB.CrossSigningSigsForTarget(ctx, targetUserID, targetKeyID)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
continue continue
@ -476,7 +489,7 @@ func (a *KeyInternalAPI) QuerySignatures(ctx context.Context, req *api.QuerySign
return return
} }
for sourceUserID, forSourceUser := range keyMap { for sourceUserID, forSourceUser := range sigMap {
for sourceKeyID, sourceSig := range forSourceUser { for sourceKeyID, sourceSig := range forSourceUser {
if res.Signatures == nil { if res.Signatures == nil {
res.Signatures = map[string]map[gomatrixserverlib.KeyID]types.CrossSigningSigMap{} res.Signatures = map[string]map[gomatrixserverlib.KeyID]types.CrossSigningSigMap{}

View file

@ -78,7 +78,8 @@ type Database interface {
// MarkDeviceListStale sets the stale bit for this user to isStale. // MarkDeviceListStale sets the stale bit for this user to isStale.
MarkDeviceListStale(ctx context.Context, userID string, isStale bool) error MarkDeviceListStale(ctx context.Context, userID string, isStale bool) error
CrossSigningKeysForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error) CrossSigningKeysForUser(ctx context.Context, userID string) (map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey, error)
CrossSigningKeysDataForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error)
CrossSigningSigsForTarget(ctx context.Context, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error) CrossSigningSigsForTarget(ctx context.Context, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error)
StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error

View file

@ -159,7 +159,46 @@ func (d *Database) MarkDeviceListStale(ctx context.Context, userID string, isSta
} }
// CrossSigningKeysForUser returns the latest known cross-signing keys for a user, if any. // CrossSigningKeysForUser returns the latest known cross-signing keys for a user, if any.
func (d *Database) CrossSigningKeysForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error) { func (d *Database) CrossSigningKeysForUser(ctx context.Context, userID string) (map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey, error) {
keyMap, err := d.CrossSigningKeysTable.SelectCrossSigningKeysForUser(ctx, nil, userID)
if err != nil {
return nil, fmt.Errorf("d.CrossSigningKeysTable.SelectCrossSigningKeysForUser: %w", err)
}
results := map[gomatrixserverlib.CrossSigningKeyPurpose]gomatrixserverlib.CrossSigningKey{}
for purpose, key := range keyMap {
keyID := gomatrixserverlib.KeyID("ed25519:" + key.Encode())
result := gomatrixserverlib.CrossSigningKey{
UserID: userID,
Usage: []gomatrixserverlib.CrossSigningKeyPurpose{purpose},
Keys: map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{
keyID: key,
},
}
sigMap, err := d.CrossSigningSigsTable.SelectCrossSigningSigsForTarget(ctx, nil, userID, keyID)
if err != nil {
continue
}
for sigUserID, forSigUserID := range sigMap {
if userID != sigUserID {
continue
}
if result.Signatures == nil {
result.Signatures = map[string]map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{}
}
if _, ok := result.Signatures[sigUserID]; !ok {
result.Signatures[sigUserID] = map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{}
}
for sigKeyID, sigBytes := range forSigUserID {
result.Signatures[sigUserID][sigKeyID] = sigBytes
}
}
results[purpose] = result
}
return results, nil
}
// CrossSigningKeysForUser returns the latest known cross-signing keys for a user, if any.
func (d *Database) CrossSigningKeysDataForUser(ctx context.Context, userID string) (types.CrossSigningKeyMap, error) {
return d.CrossSigningKeysTable.SelectCrossSigningKeysForUser(ctx, nil, userID) return d.CrossSigningKeysTable.SelectCrossSigningKeysForUser(ctx, nil, userID)
} }

View file

@ -49,6 +49,8 @@ func (k *mockKeyAPI) QueryDeviceMessages(ctx context.Context, req *keyapi.QueryD
} }
func (k *mockKeyAPI) InputDeviceListUpdate(ctx context.Context, req *keyapi.InputDeviceListUpdateRequest, res *keyapi.InputDeviceListUpdateResponse) { func (k *mockKeyAPI) InputDeviceListUpdate(ctx context.Context, req *keyapi.InputDeviceListUpdateRequest, res *keyapi.InputDeviceListUpdateResponse) {
}
func (k *mockKeyAPI) QuerySignatures(ctx context.Context, req *keyapi.QuerySignaturesRequest, res *keyapi.QuerySignaturesResponse) {
} }
type mockRoomserverAPI struct { type mockRoomserverAPI struct {