add vendoring
This commit is contained in:
223
vendor/maunium.net/go/mautrix/crypto/cross_sign_signing.go
generated
vendored
Normal file
223
vendor/maunium.net/go/mautrix/crypto/cross_sign_signing.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright (c) 2020 Nikos Filippakis
|
||||
// Copyright (c) 2022 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"maunium.net/go/mautrix"
|
||||
"maunium.net/go/mautrix/crypto/olm"
|
||||
"maunium.net/go/mautrix/event"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCrossSigningKeysNotCached = errors.New("cross-signing private keys not in cache")
|
||||
ErrUserSigningKeyNotCached = errors.New("user-signing private key not in cache")
|
||||
ErrSelfSigningKeyNotCached = errors.New("self-signing private key not in cache")
|
||||
ErrSignatureUploadFail = errors.New("server-side failure uploading signatures")
|
||||
ErrCantSignOwnMasterKey = errors.New("signing your own master key is not allowed")
|
||||
ErrCantSignOtherDevice = errors.New("signing other users' devices is not allowed")
|
||||
ErrUserNotInQueryResponse = errors.New("could not find user in query keys response")
|
||||
ErrDeviceNotInQueryResponse = errors.New("could not find device in query keys response")
|
||||
ErrOlmAccountNotLoaded = errors.New("olm account has not been loaded")
|
||||
|
||||
ErrCrossSigningMasterKeyNotFound = errors.New("cross-signing master key not found")
|
||||
ErrMasterKeyMACNotFound = errors.New("found cross-signing master key, but didn't find corresponding MAC in verification request")
|
||||
ErrMismatchingMasterKeyMAC = errors.New("mismatching cross-signing master key MAC")
|
||||
)
|
||||
|
||||
func (mach *OlmMachine) fetchMasterKey(device *id.Device, content *event.VerificationMacEventContent, verState *verificationState, transactionID string) (id.Ed25519, error) {
|
||||
crossSignKeys, err := mach.CryptoStore.GetCrossSigningKeys(device.UserID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to fetch cross-signing keys: %w", err)
|
||||
}
|
||||
masterKey, ok := crossSignKeys[id.XSUsageMaster]
|
||||
if !ok {
|
||||
return "", ErrCrossSigningMasterKeyNotFound
|
||||
}
|
||||
masterKeyID := id.NewKeyID(id.KeyAlgorithmEd25519, masterKey.Key.String())
|
||||
masterKeyMAC, ok := content.Mac[masterKeyID]
|
||||
if !ok {
|
||||
return masterKey.Key, ErrMasterKeyMACNotFound
|
||||
}
|
||||
expectedMasterKeyMAC, _, err := mach.getPKAndKeysMAC(verState.sas, device.UserID, device.DeviceID,
|
||||
mach.Client.UserID, mach.Client.DeviceID, transactionID, masterKey.Key, masterKeyID, content.Mac)
|
||||
if err != nil {
|
||||
return masterKey.Key, fmt.Errorf("failed to calculate expected MAC for master key: %w", err)
|
||||
}
|
||||
if masterKeyMAC != expectedMasterKeyMAC {
|
||||
err = fmt.Errorf("%w: expected %s, got %s", ErrMismatchingMasterKeyMAC, expectedMasterKeyMAC, masterKeyMAC)
|
||||
}
|
||||
return masterKey.Key, err
|
||||
}
|
||||
|
||||
// SignUser creates a cross-signing signature for a user, stores it and uploads it to the server.
|
||||
func (mach *OlmMachine) SignUser(userID id.UserID, masterKey id.Ed25519) error {
|
||||
if userID == mach.Client.UserID {
|
||||
return ErrCantSignOwnMasterKey
|
||||
} else if mach.CrossSigningKeys == nil || mach.CrossSigningKeys.UserSigningKey == nil {
|
||||
return ErrUserSigningKeyNotCached
|
||||
}
|
||||
|
||||
masterKeyObj := mautrix.ReqKeysSignatures{
|
||||
UserID: userID,
|
||||
Usage: []id.CrossSigningUsage{id.XSUsageMaster},
|
||||
Keys: map[id.KeyID]string{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, masterKey.String()): masterKey.String(),
|
||||
},
|
||||
}
|
||||
|
||||
signature, err := mach.signAndUpload(masterKeyObj, userID, masterKey.String(), mach.CrossSigningKeys.UserSigningKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mach.Log.Trace("Signed master key of %s with user-signing key: `%v`", userID, signature)
|
||||
|
||||
if err := mach.CryptoStore.PutSignature(userID, masterKey, mach.Client.UserID, mach.CrossSigningKeys.UserSigningKey.PublicKey, signature); err != nil {
|
||||
return fmt.Errorf("error storing signature in crypto store: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SignOwnMasterKey uses the current account for signing the current user's master key and uploads the signature.
|
||||
func (mach *OlmMachine) SignOwnMasterKey() error {
|
||||
if mach.CrossSigningKeys == nil {
|
||||
return ErrCrossSigningKeysNotCached
|
||||
} else if mach.account == nil {
|
||||
return ErrOlmAccountNotLoaded
|
||||
}
|
||||
|
||||
userID := mach.Client.UserID
|
||||
deviceID := mach.Client.DeviceID
|
||||
masterKey := mach.CrossSigningKeys.MasterKey.PublicKey
|
||||
|
||||
masterKeyObj := mautrix.ReqKeysSignatures{
|
||||
UserID: userID,
|
||||
Usage: []id.CrossSigningUsage{id.XSUsageMaster},
|
||||
Keys: map[id.KeyID]string{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, masterKey.String()): masterKey.String(),
|
||||
},
|
||||
}
|
||||
signature, err := mach.account.Internal.SignJSON(masterKeyObj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sign JSON: %w", err)
|
||||
}
|
||||
masterKeyObj.Signatures = mautrix.Signatures{
|
||||
userID: map[id.KeyID]string{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, deviceID.String()): signature,
|
||||
},
|
||||
}
|
||||
mach.Log.Trace("Signed own master key with device %v: `%v`", deviceID, signature)
|
||||
|
||||
resp, err := mach.Client.UploadSignatures(&mautrix.ReqUploadSignatures{
|
||||
userID: map[string]mautrix.ReqKeysSignatures{
|
||||
masterKey.String(): masterKeyObj,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while uploading signatures: %w", err)
|
||||
} else if len(resp.Failures) > 0 {
|
||||
return fmt.Errorf("%w: %+v", ErrSignatureUploadFail, resp.Failures)
|
||||
}
|
||||
|
||||
if err := mach.CryptoStore.PutSignature(userID, masterKey, userID, mach.account.SigningKey(), signature); err != nil {
|
||||
return fmt.Errorf("error storing signature in crypto store: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SignOwnDevice creates a cross-signing signature for a device belonging to the current user and uploads it to the server.
|
||||
func (mach *OlmMachine) SignOwnDevice(device *id.Device) error {
|
||||
if device.UserID != mach.Client.UserID {
|
||||
return ErrCantSignOtherDevice
|
||||
} else if mach.CrossSigningKeys == nil || mach.CrossSigningKeys.SelfSigningKey == nil {
|
||||
return ErrSelfSigningKeyNotCached
|
||||
}
|
||||
|
||||
deviceKeys, err := mach.getFullDeviceKeys(device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deviceKeyObj := mautrix.ReqKeysSignatures{
|
||||
UserID: device.UserID,
|
||||
DeviceID: device.DeviceID,
|
||||
Algorithms: deviceKeys.Algorithms,
|
||||
Keys: make(map[id.KeyID]string),
|
||||
}
|
||||
for keyID, key := range deviceKeys.Keys {
|
||||
deviceKeyObj.Keys[id.KeyID(keyID)] = key
|
||||
}
|
||||
|
||||
signature, err := mach.signAndUpload(deviceKeyObj, device.UserID, device.DeviceID.String(), mach.CrossSigningKeys.SelfSigningKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mach.Log.Trace("Signed own device %s with self-signing key: `%v`", device.UserID, device.DeviceID, signature)
|
||||
|
||||
if err := mach.CryptoStore.PutSignature(device.UserID, device.SigningKey, mach.Client.UserID, mach.CrossSigningKeys.SelfSigningKey.PublicKey, signature); err != nil {
|
||||
return fmt.Errorf("error storing signature in crypto store: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getFullDeviceKeys gets the full device keys object for the given device.
|
||||
// This is used because we don't cache some of the details like list of algorithms and unsupported key types.
|
||||
func (mach *OlmMachine) getFullDeviceKeys(device *id.Device) (*mautrix.DeviceKeys, error) {
|
||||
devicesKeys, err := mach.Client.QueryKeys(&mautrix.ReqQueryKeys{
|
||||
DeviceKeys: mautrix.DeviceKeysRequest{
|
||||
device.UserID: mautrix.DeviceIDList{device.DeviceID},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error querying device keys for %s: %w", device.DeviceID, err)
|
||||
}
|
||||
userKeys, ok := devicesKeys.DeviceKeys[device.UserID]
|
||||
if !ok {
|
||||
return nil, ErrUserNotInQueryResponse
|
||||
}
|
||||
deviceKeys, ok := userKeys[device.DeviceID]
|
||||
if !ok {
|
||||
return nil, ErrDeviceNotInQueryResponse
|
||||
}
|
||||
_, err = mach.validateDevice(device.UserID, device.DeviceID, deviceKeys, device)
|
||||
return &deviceKeys, err
|
||||
}
|
||||
|
||||
// signAndUpload signs the given key signatures object and uploads it to the server.
|
||||
func (mach *OlmMachine) signAndUpload(req mautrix.ReqKeysSignatures, userID id.UserID, signedThing string, key *olm.PkSigning) (string, error) {
|
||||
signature, err := key.SignJSON(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign JSON: %w", err)
|
||||
}
|
||||
req.Signatures = mautrix.Signatures{
|
||||
mach.Client.UserID: map[id.KeyID]string{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, key.PublicKey.String()): signature,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := mach.Client.UploadSignatures(&mautrix.ReqUploadSignatures{
|
||||
userID: map[string]mautrix.ReqKeysSignatures{
|
||||
signedThing: req,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while uploading signatures: %w", err)
|
||||
} else if len(resp.Failures) > 0 {
|
||||
return "", fmt.Errorf("%w: %+v", ErrSignatureUploadFail, resp.Failures)
|
||||
}
|
||||
return signature, nil
|
||||
}
|
||||
Reference in New Issue
Block a user