watchtower/wtdb: only accept properly sized blobs
Modifies the bbolt and mock tower databases to only accept blobs that are the expected size of the session's blob type. This prevents resource exhaustion attacks where a client may provide disproportionately large encrypted blob, even though all supported blob types are of fixed-size.
This commit is contained in:
parent
dce24d1d47
commit
37052f1561
@ -46,6 +46,10 @@ var (
|
|||||||
// ErrNoSessionHintIndex signals that an active session does not have an
|
// ErrNoSessionHintIndex signals that an active session does not have an
|
||||||
// initialized index for tracking its own state updates.
|
// initialized index for tracking its own state updates.
|
||||||
ErrNoSessionHintIndex = errors.New("session hint index missing")
|
ErrNoSessionHintIndex = errors.New("session hint index missing")
|
||||||
|
|
||||||
|
// ErrInvalidBlobSize indicates that the encrypted blob provided by the
|
||||||
|
// client is not valid according to the blob type of the session.
|
||||||
|
ErrInvalidBlobSize = errors.New("invalid blob size")
|
||||||
)
|
)
|
||||||
|
|
||||||
// TowerDB is single database providing a persistent storage engine for the
|
// TowerDB is single database providing a persistent storage engine for the
|
||||||
@ -233,6 +237,13 @@ func (t *TowerDB) InsertStateUpdate(update *SessionStateUpdate) (uint16, error)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that the blob is the correct size for the session's
|
||||||
|
// blob type.
|
||||||
|
expBlobSize := blob.Size(session.Policy.BlobType)
|
||||||
|
if len(update.EncryptedBlob) != expBlobSize {
|
||||||
|
return ErrInvalidBlobSize
|
||||||
|
}
|
||||||
|
|
||||||
// Validate the update against the current state of the session.
|
// Validate the update against the current state of the session.
|
||||||
err = session.AcceptUpdateSequence(
|
err = session.AcceptUpdateSequence(
|
||||||
update.SeqNum, update.LastApplied,
|
update.SeqNum, update.LastApplied,
|
||||||
|
@ -586,6 +586,30 @@ var stateUpdateRevertLastApplied = stateUpdateTest{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateUpdateInvalidBlobSize = stateUpdateTest{
|
||||||
|
session: &wtdb.SessionInfo{
|
||||||
|
ID: *id(0),
|
||||||
|
Policy: wtpolicy.Policy{
|
||||||
|
TxPolicy: wtpolicy.TxPolicy{
|
||||||
|
BlobType: blob.TypeAltruistCommit,
|
||||||
|
},
|
||||||
|
MaxUpdates: 3,
|
||||||
|
},
|
||||||
|
RewardAddress: []byte{},
|
||||||
|
},
|
||||||
|
updates: []*wtdb.SessionStateUpdate{
|
||||||
|
{
|
||||||
|
ID: *id(0),
|
||||||
|
SeqNum: 1,
|
||||||
|
LastApplied: 0,
|
||||||
|
EncryptedBlob: []byte{0x01, 0x02, 0x03}, // too $hort
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updateErrs: []error{
|
||||||
|
wtdb.ErrInvalidBlobSize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestTowerDB(t *testing.T) {
|
func TestTowerDB(t *testing.T) {
|
||||||
dbs := []struct {
|
dbs := []struct {
|
||||||
name string
|
name string
|
||||||
@ -703,6 +727,10 @@ func TestTowerDB(t *testing.T) {
|
|||||||
name: "state update revert last applied",
|
name: "state update revert last applied",
|
||||||
run: runStateUpdateTest(stateUpdateRevertLastApplied),
|
run: runStateUpdateTest(stateUpdateRevertLastApplied),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "invalid blob size",
|
||||||
|
run: runStateUpdateTest(stateUpdateInvalidBlobSize),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "multiple breach matches",
|
name: "multiple breach matches",
|
||||||
run: testMultipleMatches,
|
run: testMultipleMatches,
|
||||||
|
@ -37,6 +37,11 @@ func (db *TowerDB) InsertStateUpdate(update *wtdb.SessionStateUpdate) (uint16, e
|
|||||||
return 0, wtdb.ErrSessionNotFound
|
return 0, wtdb.ErrSessionNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that the blob is the correct size for the session's blob type.
|
||||||
|
if len(update.EncryptedBlob) != blob.Size(info.Policy.BlobType) {
|
||||||
|
return 0, wtdb.ErrInvalidBlobSize
|
||||||
|
}
|
||||||
|
|
||||||
err := info.AcceptUpdateSequence(update.SeqNum, update.LastApplied)
|
err := info.AcceptUpdateSequence(update.SeqNum, update.LastApplied)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info.LastApplied, err
|
return info.LastApplied, err
|
||||||
|
Loading…
Reference in New Issue
Block a user