mirror of https://github.com/mautrix/go.git
110 lines
4.1 KiB
Go
110 lines
4.1 KiB
Go
// 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"
|
|
|
|
"go.mau.fi/util/exzerolog"
|
|
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/crypto/signatures"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
func (mach *OlmMachine) storeCrossSigningKeys(ctx context.Context, crossSigningKeys map[id.UserID]mautrix.CrossSigningKeys, deviceKeys map[id.UserID]map[id.DeviceID]mautrix.DeviceKeys) {
|
|
log := mach.machOrContextLog(ctx)
|
|
for userID, userKeys := range crossSigningKeys {
|
|
log := log.With().Str("user_id", userID.String()).Logger()
|
|
currentKeys, err := mach.CryptoStore.GetCrossSigningKeys(ctx, userID)
|
|
if err != nil {
|
|
log.Error().Err(err).
|
|
Msg("Error fetching current cross-signing keys of user")
|
|
}
|
|
if currentKeys != nil {
|
|
for curKeyUsage, curKey := range currentKeys {
|
|
log := log.With().Str("old_key", curKey.Key.String()).Str("old_key_usage", string(curKeyUsage)).Logger()
|
|
// got a new key with the same usage as an existing key
|
|
for _, newKeyUsage := range userKeys.Usage {
|
|
if newKeyUsage == curKeyUsage {
|
|
if _, ok := userKeys.Keys[id.NewKeyID(id.KeyAlgorithmEd25519, curKey.Key.String())]; !ok {
|
|
// old key is not in the new key map, so we drop signatures made by it
|
|
if count, err := mach.CryptoStore.DropSignaturesByKey(ctx, userID, curKey.Key); err != nil {
|
|
log.Error().Err(err).Msg("Error deleting old signatures made by user")
|
|
} else {
|
|
log.Debug().
|
|
Int64("signature_count", count).
|
|
Msg("Dropped signatures made by old key as it has been replaced")
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, key := range userKeys.Keys {
|
|
log := log.With().Str("key", key.String()).Array("usages", exzerolog.ArrayOfStrs(userKeys.Usage)).Logger()
|
|
for _, usage := range userKeys.Usage {
|
|
log.Trace().Str("usage", string(usage)).Msg("Storing cross-signing key")
|
|
if err = mach.CryptoStore.PutCrossSigningKey(ctx, userID, usage, key); err != nil {
|
|
log.Error().Err(err).Msg("Error storing cross-signing key")
|
|
}
|
|
}
|
|
|
|
for signUserID, keySigs := range userKeys.Signatures {
|
|
for signKeyID, signature := range keySigs {
|
|
_, signKeyName := signKeyID.Parse()
|
|
signingKey := id.Ed25519(signKeyName)
|
|
log := log.With().
|
|
Str("sign_key_id", signKeyID.String()).
|
|
Str("signer_user_id", signUserID.String()).
|
|
Str("signing_key", signingKey.String()).
|
|
Logger()
|
|
// if the signer is one of this user's own devices, find the key from the key ID
|
|
if signUserID == userID {
|
|
ownDeviceID := id.DeviceID(signKeyName)
|
|
if ownDeviceKeys, ok := deviceKeys[userID][ownDeviceID]; ok {
|
|
signingKey = ownDeviceKeys.Keys.GetEd25519(ownDeviceID)
|
|
log.Trace().
|
|
Str("device_id", signKeyName).
|
|
Msg("Treating key name as device ID")
|
|
}
|
|
}
|
|
if len(signingKey) != 43 {
|
|
log.Trace().Msg("Cross-signing key has a signature from an unknown key")
|
|
continue
|
|
}
|
|
|
|
log.Trace().Msg("Verifying cross-signing key signature")
|
|
if verified, err := signatures.VerifySignatureJSON(userKeys, signUserID, signKeyName, signingKey); err != nil {
|
|
log.Warn().Err(err).Msg("Error verifying cross-signing key signature")
|
|
} else {
|
|
if verified {
|
|
log.Trace().Err(err).Msg("Cross-signing key signature verified")
|
|
err = mach.CryptoStore.PutSignature(ctx, userID, key, signUserID, signingKey, signature)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Error storing cross-signing key signature")
|
|
}
|
|
} else {
|
|
log.Warn().Err(err).Msg("Cross-siging key signature is invalid")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clear internal cache so that it refreshes from crypto store
|
|
if userID == mach.Client.UserID && mach.crossSigningPubkeys != nil {
|
|
log.Debug().Msg("Resetting internal cross-signing key cache")
|
|
mach.crossSigningPubkeys = nil
|
|
mach.crossSigningPubkeysFetched = false
|
|
}
|
|
}
|
|
}
|