Browse Source

lib/protocol: Handle encrypted requests without encrypted hash (fixes #8277) (#8827)

The layout of the request differs based on whether it comes from an
untrusted device or a trusted device with encrypted enabled. Handle
both.

Closes #8819.
Jakob Borg 2 years ago
parent
commit
f378e63147
1 changed files with 19 additions and 11 deletions
  1. 19 11
      lib/protocol/encryption.go

+ 19 - 11
lib/protocol/encryption.go

@@ -96,18 +96,26 @@ func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo,
 		return nil, errors.New("short request")
 	}
 
-	// Decrypt the block hash.
-
+	// Attempt to decrypt the block hash; it may be nil depending on what
+	// type of device the request comes from. Trusted devices with
+	// encryption enabled know the hash but don't bother to encrypt & send
+	// it to us. Untrusted devices have the hash from the encrypted index
+	// data and do send it. The model knows to only verify the hash if it
+	// actually gets one.
+
+	var realHash []byte
 	fileKey := e.keyGen.FileKey(realName, folderKey)
-	var additional [8]byte
-	binary.BigEndian.PutUint64(additional[:], uint64(realOffset))
-	realHash, err := decryptDeterministic(hash, fileKey, additional[:])
-	if err != nil {
-		// "Legacy", no offset additional data?
-		realHash, err = decryptDeterministic(hash, fileKey, nil)
-	}
-	if err != nil {
-		return nil, fmt.Errorf("decrypting block hash: %w", err)
+	if len(hash) > 0 {
+		var additional [8]byte
+		binary.BigEndian.PutUint64(additional[:], uint64(realOffset))
+		realHash, err = decryptDeterministic(hash, fileKey, additional[:])
+		if err != nil {
+			// "Legacy", no offset additional data?
+			realHash, err = decryptDeterministic(hash, fileKey, nil)
+		}
+		if err != nil {
+			return nil, fmt.Errorf("decrypting block hash: %w", err)
+		}
 	}
 
 	// Perform that request and grab the data.