appstate,handshake,pair: use constant-time byte comparisons

This commit is contained in:
Tulir Asokan
2026-04-21 19:26:56 +03:00
parent 75186f8052
commit c26a4c538c
3 changed files with 10 additions and 10 deletions
+7 -6
View File
@@ -9,6 +9,7 @@ package appstate
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/json"
"fmt"
@@ -122,7 +123,7 @@ func (out *patchOutput) RemoveMAC(indexMAC []byte) {
out.RemovedMACs = append(out.RemovedMACs, indexMAC)
// If the mutation was previously added in this patch, remove it from AddedMACs
out.AddedMACs = slices.DeleteFunc(out.AddedMACs, func(mac store.AppStateMutationMAC) bool {
return bytes.Equal(mac.IndexMAC, indexMAC)
return hmac.Equal(mac.IndexMAC, indexMAC)
})
}
@@ -149,7 +150,7 @@ func (proc *Processor) decodeMutation(
content, valueMAC = content[:len(content)-32], content[len(content)-32:]
if validateMACs {
expectedValueMAC := generateContentMAC(mutation.GetOperation(), content, keyID, keys.ValueMAC)
if !bytes.Equal(expectedValueMAC, valueMAC) {
if !hmac.Equal(expectedValueMAC, valueMAC) {
err = fmt.Errorf("failed to verify mutation #%d: %w", i+1, ErrMismatchingContentMAC)
return
}
@@ -169,7 +170,7 @@ func (proc *Processor) decodeMutation(
indexMAC = mutation.GetRecord().GetIndex().GetBlob()
if validateMACs {
expectedIndexMAC := concatAndHMAC(sha256.New, keys.Index, syncAction.Index)
if !bytes.Equal(expectedIndexMAC, indexMAC) {
if !hmac.Equal(expectedIndexMAC, indexMAC) {
err = fmt.Errorf("failed to verify mutation #%d: %w", i+1, ErrMismatchingIndexMAC)
return
}
@@ -248,7 +249,7 @@ func (proc *Processor) validateSnapshotMAC(ctx context.Context, name WAPatchName
return
}
snapshotMAC := currentState.generateSnapshotMAC(name, keys.SnapshotMAC)
if !bytes.Equal(snapshotMAC, expectedSnapshotMAC) {
if !hmac.Equal(snapshotMAC, expectedSnapshotMAC) {
err = fmt.Errorf("failed to verify patch v%d: %w", currentState.Version, ErrMismatchingLTHash)
}
return
@@ -321,7 +322,7 @@ func (proc *Processor) validatePatch(
newState.Version = version
warn, err = newState.updateHash(patch.GetMutations(), func(indexMAC []byte, maxIndex int) ([]byte, error) {
for i := maxIndex - 1; i >= 0; i-- {
if bytes.Equal(patch.Mutations[i].GetRecord().GetIndex().GetBlob(), indexMAC) {
if hmac.Equal(patch.Mutations[i].GetRecord().GetIndex().GetBlob(), indexMAC) {
if patch.Mutations[i].GetOperation() == waServerSync.SyncdMutation_SET {
value := patch.Mutations[i].GetRecord().GetValue().GetBlob()
return value[len(value)-32:], nil
@@ -345,7 +346,7 @@ func (proc *Processor) validatePatch(
return
}
patchMAC := generatePatchMAC(patch, patchName, keys.PatchMAC, patch.GetVersion().GetVersion())
if !bytes.Equal(patchMAC, patch.GetPatchMAC()) {
if !hmac.Equal(patchMAC, patch.GetPatchMAC()) {
err = fmt.Errorf("failed to verify patch v%d: %w", version, ErrMismatchingPatchMAC)
return
}
+2 -2
View File
@@ -7,8 +7,8 @@
package whatsmeow
import (
"bytes"
"context"
"crypto/hmac"
"fmt"
"time"
@@ -173,7 +173,7 @@ func verifyServerCert(certDecrypted, staticDecrypted []byte) error {
return fmt.Errorf("failed to unmarshal noise certificate details: %w", err)
} else if leafCertDetails.GetIssuerSerial() != intermediateCertDetails.GetSerial() {
return fmt.Errorf("unexpected leaf issuer serial %d (expected %d)", leafCertDetails.GetIssuerSerial(), intermediateCertDetails.GetSerial())
} else if !bytes.Equal(leafCertDetails.GetKey(), staticDecrypted) {
} else if !hmac.Equal(leafCertDetails.GetKey(), staticDecrypted) {
return fmt.Errorf("cert key doesn't match decrypted static")
} else if err = checkCertValidity(&leafCertDetails); err != nil {
return fmt.Errorf("leaf cert cert %w", err)
+1 -2
View File
@@ -7,7 +7,6 @@
package whatsmeow
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha256"
@@ -125,7 +124,7 @@ func (cli *Client) handlePair(ctx context.Context, deviceIdentityBytes []byte, r
}
h.Write(deviceIdentityContainer.Details)
if !bytes.Equal(h.Sum(nil), deviceIdentityContainer.HMAC) {
if !hmac.Equal(h.Sum(nil), deviceIdentityContainer.HMAC) {
cli.Log.Warnf("Invalid HMAC from pair success message")
cli.sendPairError(ctx, reqID, 401, "hmac-mismatch")
return ErrPairInvalidDeviceIdentityHMAC