mas: revert cross_signing_keys.updatable_without_uia_before_ms field and related logic

This commit is contained in:
Roman Isaev 2025-01-25 00:38:24 +00:00
parent 453445695c
commit 0b4cf3badd
No known key found for this signature in database
GPG key ID: 7BE2B6A6C89AEC7F
11 changed files with 41 additions and 212 deletions

View file

@ -689,11 +689,6 @@ type ClientKeyAPI interface {
QueryKeys(ctx context.Context, req *QueryKeysRequest, res *QueryKeysResponse) QueryKeys(ctx context.Context, req *QueryKeysRequest, res *QueryKeysResponse)
QueryMasterKeys(ctx context.Context, req *QueryMasterKeysRequest, res *QueryMasterKeysResponse) QueryMasterKeys(ctx context.Context, req *QueryMasterKeysRequest, res *QueryMasterKeysResponse)
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse) error PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse) error
PerformAllowingMasterCrossSigningKeyReplacementWithoutUIA(
ctx context.Context,
req *PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest,
res *PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse,
) error
PerformUploadDeviceSignatures(ctx context.Context, req *PerformUploadDeviceSignaturesRequest, res *PerformUploadDeviceSignaturesResponse) PerformUploadDeviceSignatures(ctx context.Context, req *PerformUploadDeviceSignaturesRequest, res *PerformUploadDeviceSignaturesResponse)
// PerformClaimKeys claims one-time keys for use in pre-key messages // PerformClaimKeys claims one-time keys for use in pre-key messages
@ -922,15 +917,6 @@ type PerformUploadDeviceKeysResponse struct {
Error *KeyError Error *KeyError
} }
type PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest struct {
UserID string
Duration time.Duration
}
type PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse struct {
Timestamp int64
}
type PerformUploadDeviceSignaturesRequest struct { type PerformUploadDeviceSignaturesRequest struct {
Signatures map[string]map[gomatrixserverlib.KeyID]fclient.CrossSigningForKeyOrDevice Signatures map[string]map[gomatrixserverlib.KeyID]fclient.CrossSigningForKeyOrDevice
// The user that uploaded the sig, should be populated by the clientapi. // The user that uploaded the sig, should be populated by the clientapi.
@ -968,7 +954,7 @@ type QueryMasterKeysRequest struct {
} }
type QueryMasterKeysResponse struct { type QueryMasterKeysResponse struct {
Key *types.CrossSigningKey Key spec.Base64Bytes
// Set if there was a fatal error processing this query // Set if there was a fatal error processing this query
Error *KeyError Error *KeyError
} }

View file

@ -96,16 +96,6 @@ func sanityCheckKey(key fclient.CrossSigningKey, userID string, purpose fclient.
return nil return nil
} }
func (a *UserInternalAPI) PerformAllowingMasterCrossSigningKeyReplacementWithoutUIA(
ctx context.Context,
req *api.PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest,
res *api.PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse,
) error {
var err error
res.Timestamp, err = a.KeyDatabase.UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx, req.UserID, req.Duration)
return err
}
// nolint:gocyclo // nolint:gocyclo
func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.PerformUploadDeviceKeysRequest, res *api.PerformUploadDeviceKeysResponse) { func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.PerformUploadDeviceKeysRequest, res *api.PerformUploadDeviceKeysResponse) {
// Find the keys to store. // Find the keys to store.
@ -124,9 +114,7 @@ func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.
byPurpose[fclient.CrossSigningKeyPurposeMaster] = req.MasterKey byPurpose[fclient.CrossSigningKeyPurposeMaster] = req.MasterKey
for _, key := range req.MasterKey.Keys { // iterates once, see sanityCheckKey for _, key := range req.MasterKey.Keys { // iterates once, see sanityCheckKey
toStore[fclient.CrossSigningKeyPurposeMaster] = types.CrossSigningKey{ toStore[fclient.CrossSigningKeyPurposeMaster] = key
KeyData: key,
}
} }
hasMasterKey = true hasMasterKey = true
} }
@ -142,9 +130,7 @@ func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.
byPurpose[fclient.CrossSigningKeyPurposeSelfSigning] = req.SelfSigningKey byPurpose[fclient.CrossSigningKeyPurposeSelfSigning] = req.SelfSigningKey
for _, key := range req.SelfSigningKey.Keys { // iterates once, see sanityCheckKey for _, key := range req.SelfSigningKey.Keys { // iterates once, see sanityCheckKey
toStore[fclient.CrossSigningKeyPurposeSelfSigning] = types.CrossSigningKey{ toStore[fclient.CrossSigningKeyPurposeSelfSigning] = key
KeyData: key,
}
} }
} }
@ -159,9 +145,7 @@ func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.
byPurpose[fclient.CrossSigningKeyPurposeUserSigning] = req.UserSigningKey byPurpose[fclient.CrossSigningKeyPurposeUserSigning] = req.UserSigningKey
for _, key := range req.UserSigningKey.Keys { // iterates once, see sanityCheckKey for _, key := range req.UserSigningKey.Keys { // iterates once, see sanityCheckKey
toStore[fclient.CrossSigningKeyPurposeUserSigning] = types.CrossSigningKey{ toStore[fclient.CrossSigningKeyPurposeUserSigning] = key
KeyData: key,
}
} }
} }
@ -214,7 +198,7 @@ func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.
changed = true changed = true
break break
} }
if !bytes.Equal(old.KeyData, new.KeyData) { if !bytes.Equal(old, new) {
// One of the existing keys for a purpose we already knew about has // One of the existing keys for a purpose we already knew about has
// changed. // changed.
changed = true changed = true
@ -226,7 +210,7 @@ func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.
} }
// Store the keys. // Store the keys.
if err := a.KeyDatabase.StoreCrossSigningKeysForUser(ctx, req.UserID, toStore, nil); err != nil { if err := a.KeyDatabase.StoreCrossSigningKeysForUser(ctx, req.UserID, toStore); err != nil {
res.Error = &api.KeyError{ res.Error = &api.KeyError{
Err: fmt.Sprintf("a.DB.StoreCrossSigningKeysForUser: %s", err), Err: fmt.Sprintf("a.DB.StoreCrossSigningKeysForUser: %s", err),
} }

View file

@ -243,7 +243,7 @@ func (a *UserInternalAPI) QueryMasterKeys(ctx context.Context, req *api.QueryMas
return return
} }
if key, ok := crossSigningKeyMap[fclient.CrossSigningKeyPurposeMaster]; ok { if key, ok := crossSigningKeyMap[fclient.CrossSigningKeyPurposeMaster]; ok {
res.Key = &key res.Key = key
} }
} }

View file

@ -10,7 +10,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"time"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/fclient"
@ -231,9 +230,8 @@ type KeyDatabase interface {
CrossSigningKeysDataForUserAndKeyType(ctx context.Context, userID string, keyType fclient.CrossSigningKeyPurpose) (types.CrossSigningKeyMap, error) CrossSigningKeysDataForUserAndKeyType(ctx context.Context, userID string, keyType fclient.CrossSigningKeyPurpose) (types.CrossSigningKeyMap, error)
CrossSigningSigsForTarget(ctx context.Context, originUserID, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error) CrossSigningSigsForTarget(ctx context.Context, originUserID, targetUserID string, targetKeyID gomatrixserverlib.KeyID) (types.CrossSigningSigMap, error)
StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap, updatableWithoutUIABeforeMs *int64) error StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error
StoreCrossSigningSigsForTarget(ctx context.Context, originUserID string, originKeyID gomatrixserverlib.KeyID, targetUserID string, targetKeyID gomatrixserverlib.KeyID, signature spec.Base64Bytes) error StoreCrossSigningSigsForTarget(ctx context.Context, originUserID string, originKeyID gomatrixserverlib.KeyID, targetUserID string, targetKeyID gomatrixserverlib.KeyID, signature spec.Base64Bytes) error
UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, userID string, duration time.Duration) (int64, error)
DeleteStaleDeviceLists( DeleteStaleDeviceLists(
ctx context.Context, ctx context.Context,

View file

@ -10,9 +10,6 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"time"
"github.com/element-hq/dendrite/userapi/storage/postgres/deltas"
"github.com/element-hq/dendrite/internal" "github.com/element-hq/dendrite/internal"
"github.com/element-hq/dendrite/internal/sqlutil" "github.com/element-hq/dendrite/internal/sqlutil"
@ -32,29 +29,23 @@ CREATE TABLE IF NOT EXISTS keyserver_cross_signing_keys (
` `
const selectCrossSigningKeysForUserSQL = "" + const selectCrossSigningKeysForUserSQL = "" +
"SELECT key_type, key_data, updatable_without_uia_before_ms FROM keyserver_cross_signing_keys" + "SELECT key_type, key_data FROM keyserver_cross_signing_keys" +
" WHERE user_id = $1" " WHERE user_id = $1"
const selectCrossSigningKeysForUserAndKeyTypeSQL = "" + const selectCrossSigningKeysForUserAndKeyTypeSQL = "" +
"SELECT key_type, key_data, updatable_without_uia_before_ms FROM keyserver_cross_signing_keys" + "SELECT key_type, key_data FROM keyserver_cross_signing_keys" +
" WHERE user_id = $1 AND key_type = $2" " WHERE user_id = $1 AND key_type = $2"
const upsertCrossSigningKeysForUserSQL = "" + const upsertCrossSigningKeysForUserSQL = "" +
"INSERT INTO keyserver_cross_signing_keys (user_id, key_type, key_data, updatable_without_uia_before_ms)" + "INSERT INTO keyserver_cross_signing_keys (user_id, key_type, key_data)" +
" VALUES($1, $2, $3, $4)" + " VALUES($1, $2, $3, $4)" +
" ON CONFLICT (user_id, key_type) DO UPDATE SET key_data = $3" " ON CONFLICT (user_id, key_type) DO UPDATE SET key_data = $3"
const updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL = "" +
"UPDATE keyserver_cross_signing_keys" +
" SET updatable_without_uia_before_ms = $1" +
" WHERE user_id = $2 AND key_type = $3"
type crossSigningKeysStatements struct { type crossSigningKeysStatements struct {
db *sql.DB db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt upsertCrossSigningKeysForUserStmt *sql.Stmt
updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt *sql.Stmt
} }
func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) { func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) {
@ -66,12 +57,6 @@ func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, erro
return nil, err return nil, err
} }
m := sqlutil.NewMigrator(db) m := sqlutil.NewMigrator(db)
m.AddMigrations(
sqlutil.Migration{
Version: "userapi: add x-signing updatable_without_uia_before_ms",
Up: deltas.UpAddXSigningUpdatableWithoutUIABeforeMs,
},
)
err = m.Up(context.Background()) err = m.Up(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
@ -80,7 +65,6 @@ func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, erro
{&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL}, {&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL},
{&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL}, {&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL},
{&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL}, {&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL},
{&s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt, updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL},
}.Prepare(db) }.Prepare(db)
} }
@ -96,18 +80,14 @@ func (s *crossSigningKeysStatements) SelectCrossSigningKeysForUser(
for rows.Next() { for rows.Next() {
var keyTypeInt int16 var keyTypeInt int16
var keyData spec.Base64Bytes var keyData spec.Base64Bytes
var updatableWithoutUIABeforeMs *int64 if err = rows.Scan(&keyTypeInt, &keyData); err != nil {
if err = rows.Scan(&keyTypeInt, &keyData, &updatableWithoutUIABeforeMs); err != nil {
return nil, err return nil, err
} }
keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt] keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt]
if !ok { if !ok {
return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt) return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt)
} }
r[keyType] = types.CrossSigningKey{ r[keyType] = keyData
UpdatableWithoutUIABeforeMs: updatableWithoutUIABeforeMs,
KeyData: keyData,
}
} }
err = rows.Err() err = rows.Err()
return return
@ -129,45 +109,28 @@ func (s *crossSigningKeysStatements) SelectCrossSigningKeysForUserAndKeyType(
for rows.Next() { for rows.Next() {
var keyTypeInt int16 var keyTypeInt int16
var keyData spec.Base64Bytes var keyData spec.Base64Bytes
var updatableWithoutUIABeforeMs *int64 if err = rows.Scan(&keyTypeInt, &keyData); err != nil {
if err = rows.Scan(&keyTypeInt, &keyData, &updatableWithoutUIABeforeMs); err != nil {
return nil, err return nil, err
} }
keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt] keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt]
if !ok { if !ok {
return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt) return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt)
} }
r[keyType] = types.CrossSigningKey{ r[keyType] = keyData
UpdatableWithoutUIABeforeMs: updatableWithoutUIABeforeMs,
KeyData: keyData,
}
} }
err = rows.Err() err = rows.Err()
return return
} }
func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser( func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser(
ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes, updatableWithoutUIABeforeMs *int64, ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes,
) error { ) error {
keyTypeInt, ok := types.KeyTypePurposeToInt[keyType] keyTypeInt, ok := types.KeyTypePurposeToInt[keyType]
if !ok { if !ok {
return fmt.Errorf("unknown key purpose %q", keyType) return fmt.Errorf("unknown key purpose %q", keyType)
} }
if _, err := sqlutil.TxStmt(txn, s.upsertCrossSigningKeysForUserStmt).ExecContext(ctx, userID, keyTypeInt, keyData, updatableWithoutUIABeforeMs); err != nil { if _, err := sqlutil.TxStmt(txn, s.upsertCrossSigningKeysForUserStmt).ExecContext(ctx, userID, keyTypeInt, keyData); err != nil {
return fmt.Errorf("s.upsertCrossSigningKeysForUserStmt: %w", err) return fmt.Errorf("s.upsertCrossSigningKeysForUserStmt: %w", err)
} }
return nil return nil
} }
func (s *crossSigningKeysStatements) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error) {
keyTypeInt := types.KeyTypePurposeToInt[fclient.CrossSigningKeyPurposeMaster]
ts := time.Now().Add(duration).UnixMilli()
result, err := sqlutil.TxStmt(txn, s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt).ExecContext(ctx, ts, userID, keyTypeInt)
if err != nil {
return -1, err
}
if n, _ := result.RowsAffected(); n == 0 {
return -1, sql.ErrNoRows
}
return ts, nil
}

View file

@ -1,23 +0,0 @@
package deltas
import (
"context"
"database/sql"
"fmt"
)
func UpAddXSigningUpdatableWithoutUIABeforeMs(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `ALTER TABLE keyserver_cross_signing_keys ADD COLUMN IF NOT EXISTS updatable_without_uia_before_ms BIGINT DEFAULT NULL;`)
if err != nil {
return fmt.Errorf("failed to execute upgrade: %w", err)
}
return nil
}
func DownAddXSigningUpdatableWithoutUIABeforeMs(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `ALTER TABLE keyserver_cross_signing_keys DROP COLUMN IF EXISTS updatable_without_uia_before_ms;`)
if err != nil {
return fmt.Errorf("failed to execute downgrade: %w", err)
}
return nil
}

View file

@ -1136,12 +1136,12 @@ func (d *KeyDatabase) CrossSigningKeysForUser(ctx context.Context, userID string
} }
results := map[fclient.CrossSigningKeyPurpose]fclient.CrossSigningKey{} results := map[fclient.CrossSigningKeyPurpose]fclient.CrossSigningKey{}
for purpose, key := range keyMap { for purpose, key := range keyMap {
keyID := gomatrixserverlib.KeyID("ed25519:" + key.KeyData.Encode()) keyID := gomatrixserverlib.KeyID("ed25519:" + key.Encode())
result := fclient.CrossSigningKey{ result := fclient.CrossSigningKey{
UserID: userID, UserID: userID,
Usage: []fclient.CrossSigningKeyPurpose{purpose}, Usage: []fclient.CrossSigningKeyPurpose{purpose},
Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{ Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{
keyID: key.KeyData, keyID: key,
}, },
} }
sigMap, err := d.CrossSigningSigsTable.SelectCrossSigningSigsForTarget(ctx, nil, userID, userID, keyID) sigMap, err := d.CrossSigningSigsTable.SelectCrossSigningSigsForTarget(ctx, nil, userID, userID, keyID)
@ -1183,10 +1183,10 @@ func (d *KeyDatabase) CrossSigningSigsForTarget(ctx context.Context, originUserI
} }
// StoreCrossSigningKeysForUser stores the latest known cross-signing keys for a user. // StoreCrossSigningKeysForUser stores the latest known cross-signing keys for a user.
func (d *KeyDatabase) StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap, updatableWithoutUIABeforeMs *int64) error { func (d *KeyDatabase) StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap) error {
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
for keyType, key := range keyMap { for keyType, key := range keyMap {
if err := d.CrossSigningKeysTable.UpsertCrossSigningKeysForUser(ctx, txn, userID, keyType, key.KeyData, key.UpdatableWithoutUIABeforeMs); err != nil { if err := d.CrossSigningKeysTable.UpsertCrossSigningKeysForUser(ctx, txn, userID, keyType, key); err != nil {
return fmt.Errorf("d.CrossSigningKeysTable.InsertCrossSigningKeysForUser: %w", err) return fmt.Errorf("d.CrossSigningKeysTable.InsertCrossSigningKeysForUser: %w", err)
} }
} }
@ -1194,18 +1194,6 @@ func (d *KeyDatabase) StoreCrossSigningKeysForUser(ctx context.Context, userID s
}) })
} }
// UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA updates the 'updatable_without_uia_before_ms' attribute of the master cross-signing key.
// Normally this attribute depending on its value marks the master key as replaceable without UIA.
func (d *KeyDatabase) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, userID string, duration time.Duration) (int64, error) {
var ts int64
err := d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
var err error
ts, err = d.CrossSigningKeysTable.UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx, txn, userID, duration)
return err
})
return ts, err
}
// StoreCrossSigningSigsForTarget stores a signature for a target user ID and key/device. // StoreCrossSigningSigsForTarget stores a signature for a target user ID and key/device.
func (d *KeyDatabase) StoreCrossSigningSigsForTarget( func (d *KeyDatabase) StoreCrossSigningSigsForTarget(
ctx context.Context, ctx context.Context,

View file

@ -10,9 +10,6 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"time"
"github.com/element-hq/dendrite/userapi/storage/sqlite3/deltas"
"github.com/element-hq/dendrite/internal" "github.com/element-hq/dendrite/internal"
"github.com/element-hq/dendrite/internal/sqlutil" "github.com/element-hq/dendrite/internal/sqlutil"
@ -32,28 +29,22 @@ CREATE TABLE IF NOT EXISTS keyserver_cross_signing_keys (
` `
const selectCrossSigningKeysForUserSQL = "" + const selectCrossSigningKeysForUserSQL = "" +
"SELECT key_type, key_data, updatable_without_uia_before_ms FROM keyserver_cross_signing_keys" + "SELECT key_type, key_data FROM keyserver_cross_signing_keys" +
" WHERE user_id = $1" " WHERE user_id = $1"
const selectCrossSigningKeysForUserAndKeyTypeSQL = "" + const selectCrossSigningKeysForUserAndKeyTypeSQL = "" +
"SELECT key_type, key_data, updatable_without_uia_before_ms FROM keyserver_cross_signing_keys" + "SELECT key_type, key_data FROM keyserver_cross_signing_keys" +
" WHERE user_id = $1 AND key_type = $2" " WHERE user_id = $1 AND key_type = $2"
const upsertCrossSigningKeysForUserSQL = "" + const upsertCrossSigningKeysForUserSQL = "" +
"INSERT OR REPLACE INTO keyserver_cross_signing_keys (user_id, key_type, key_data, updatable_without_uia_before_ms)" + "INSERT OR REPLACE INTO keyserver_cross_signing_keys (user_id, key_type, key_data)" +
" VALUES($1, $2, $3, $4)" " VALUES($1, $2, $3)"
const updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL = "" +
"UPDATE keyserver_cross_signing_keys" +
" SET updatable_without_uia_before_ms = $1" +
" WHERE user_id = $2 AND key_type = $3"
type crossSigningKeysStatements struct { type crossSigningKeysStatements struct {
db *sql.DB db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt upsertCrossSigningKeysForUserStmt *sql.Stmt
updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt *sql.Stmt
} }
func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) { func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) {
@ -65,12 +56,6 @@ func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error)
return nil, err return nil, err
} }
m := sqlutil.NewMigrator(db) m := sqlutil.NewMigrator(db)
m.AddMigrations(
sqlutil.Migration{
Version: "userapi: add x-signing updatable_without_uia_before_ms",
Up: deltas.UpAddXSigningUpdatableWithoutUIABeforeMs,
},
)
err = m.Up(context.Background()) err = m.Up(context.Background())
if err != nil { if err != nil {
return nil, err return nil, err
@ -79,7 +64,6 @@ func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error)
{&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL}, {&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL},
{&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL}, {&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL},
{&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL}, {&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL},
{&s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt, updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL},
}.Prepare(db) }.Prepare(db)
} }
@ -95,18 +79,14 @@ func (s *crossSigningKeysStatements) SelectCrossSigningKeysForUser(
for rows.Next() { for rows.Next() {
var keyTypeInt int16 var keyTypeInt int16
var keyData spec.Base64Bytes var keyData spec.Base64Bytes
var updatableWithoutUiaBeforeMs *int64 if err = rows.Scan(&keyTypeInt, &keyData); err != nil {
if err = rows.Scan(&keyTypeInt, &keyData, &updatableWithoutUiaBeforeMs); err != nil {
return nil, err return nil, err
} }
keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt] keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt]
if !ok { if !ok {
return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt) return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt)
} }
r[keyType] = types.CrossSigningKey{ r[keyType] = keyData
UpdatableWithoutUIABeforeMs: updatableWithoutUiaBeforeMs,
KeyData: keyData,
}
} }
err = rows.Err() err = rows.Err()
return return
@ -128,45 +108,27 @@ func (s *crossSigningKeysStatements) SelectCrossSigningKeysForUserAndKeyType(
for rows.Next() { for rows.Next() {
var keyTypeInt int16 var keyTypeInt int16
var keyData spec.Base64Bytes var keyData spec.Base64Bytes
var updatableWithoutUIABeforeMs *int64 if err = rows.Scan(&keyTypeInt, &keyData); err != nil {
if err = rows.Scan(&keyTypeInt, &keyData, &updatableWithoutUIABeforeMs); err != nil {
return nil, err return nil, err
} }
keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt] keyType, ok := types.KeyTypeIntToPurpose[keyTypeInt]
if !ok { if !ok {
return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt) return nil, fmt.Errorf("unknown key purpose int %d", keyTypeInt)
} }
r[keyType] = types.CrossSigningKey{ r[keyType] = keyData
UpdatableWithoutUIABeforeMs: updatableWithoutUIABeforeMs,
KeyData: keyData,
}
} }
err = rows.Err() err = rows.Err()
return return
} }
func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser( func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser(
ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes, updatableWithoutUIABeforeMs *int64, ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes) error {
) error {
keyTypeInt, ok := types.KeyTypePurposeToInt[keyType] keyTypeInt, ok := types.KeyTypePurposeToInt[keyType]
if !ok { if !ok {
return fmt.Errorf("unknown key purpose %q", keyType) return fmt.Errorf("unknown key purpose %q", keyType)
} }
if _, err := sqlutil.TxStmt(txn, s.upsertCrossSigningKeysForUserStmt).ExecContext(ctx, userID, keyTypeInt, keyData, updatableWithoutUIABeforeMs); err != nil { if _, err := sqlutil.TxStmt(txn, s.upsertCrossSigningKeysForUserStmt).ExecContext(ctx, userID, keyTypeInt, keyData); err != nil {
return fmt.Errorf("s.upsertCrossSigningKeysForUserStmt: %w", err) return fmt.Errorf("s.upsertCrossSigningKeysForUserStmt: %w", err)
} }
return nil return nil
} }
func (s *crossSigningKeysStatements) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error) {
keyTypeInt := types.KeyTypePurposeToInt[fclient.CrossSigningKeyPurposeMaster]
ts := time.Now().Add(duration).UnixMilli()
result, err := sqlutil.TxStmt(txn, s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt).ExecContext(ctx, ts, userID, keyTypeInt)
if err != nil {
return -1, err
}
if n, _ := result.RowsAffected(); n == 0 {
return -1, sql.ErrNoRows
}
return ts, nil
}

View file

@ -1,23 +0,0 @@
package deltas
import (
"context"
"database/sql"
"fmt"
)
func UpAddXSigningUpdatableWithoutUIABeforeMs(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `ALTER TABLE keyserver_cross_signing_keys ADD COLUMN updatable_without_uia_before_ms BIGINT DEFAULT NULL;`)
if err != nil {
return fmt.Errorf("failed to execute upgrade: %w", err)
}
return nil
}
func DownAddXSigningUpdatableWithoutUIABeforeMs(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `ALTER TABLE keyserver_cross_signing_keys DROP COLUMN updatable_without_uia_before_ms;`)
if err != nil {
return fmt.Errorf("failed to execute downgrade: %w", err)
}
return nil
}

View file

@ -199,8 +199,7 @@ type StaleDeviceLists interface {
type CrossSigningKeys interface { type CrossSigningKeys interface {
SelectCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string) (r types.CrossSigningKeyMap, err error) SelectCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string) (r types.CrossSigningKeyMap, err error)
SelectCrossSigningKeysForUserAndKeyType(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose) (r types.CrossSigningKeyMap, err error) SelectCrossSigningKeysForUserAndKeyType(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose) (r types.CrossSigningKeyMap, err error)
UpsertCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes, updatableWithoutUIABeforeMs *int64) error UpsertCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes) error
UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error)
} }
type CrossSigningSigs interface { type CrossSigningSigs interface {

View file

@ -37,13 +37,8 @@ var KeyTypeIntToPurpose = map[int16]fclient.CrossSigningKeyPurpose{
3: fclient.CrossSigningKeyPurposeUserSigning, 3: fclient.CrossSigningKeyPurposeUserSigning,
} }
type CrossSigningKey struct {
UpdatableWithoutUIABeforeMs *int64
KeyData spec.Base64Bytes
}
// Map of purpose -> public key // Map of purpose -> public key
type CrossSigningKeyMap map[fclient.CrossSigningKeyPurpose]CrossSigningKey type CrossSigningKeyMap map[fclient.CrossSigningKeyPurpose]spec.Base64Bytes
// Map of user ID -> key ID -> signature // Map of user ID -> key ID -> signature
type CrossSigningSigMap map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes type CrossSigningSigMap map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes