aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/root_node.go
diff options
context:
space:
mode:
authorAleksey Vasenev2024-11-17 23:14:36 +0300
committerJakob Unterwurzacher2025-11-22 21:24:20 +0100
commited1c5e4a9f5ce1921f3ec03b32e591ce828ec5b9 (patch)
treea2e1f64e772e2af169df3ce4ac955fbf3ec8c83b /internal/fusefrontend_reverse/root_node.go
parentbe34b9822bea4ce3b717c1b9bf5076f1118427ec (diff)
Xattrs support in reverse mode
Fixes https://github.com/rfjakob/gocryptfs/issues/827
Diffstat (limited to 'internal/fusefrontend_reverse/root_node.go')
-rw-r--r--internal/fusefrontend_reverse/root_node.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go
index 9c2de28..420ed22 100644
--- a/internal/fusefrontend_reverse/root_node.go
+++ b/internal/fusefrontend_reverse/root_node.go
@@ -182,3 +182,38 @@ func (rn *RootNode) uniqueStableAttr(mode uint32, ino uint64) fs.StableAttr {
func (rn *RootNode) RootIno() uint64 {
return rn.rootIno
}
+
+// encryptXattrValue encrypts the xattr value "data".
+// The data is encrypted like a file content block, but without binding it to
+// a file location (block number and file id are set to zero).
+// Special case: an empty value is encrypted to an empty value.
+func (rn *RootNode) encryptXattrValue(data []byte, nonce []byte) (cData []byte) {
+ if len(data) == 0 {
+ return []byte{}
+ }
+ return rn.contentEnc.EncryptBlockNonce(data, 0, nil, nonce)
+}
+
+// encryptXattrName transforms "user.foo" to "user.gocryptfs.a5sAd4XAa47f5as6dAf"
+func (rn *RootNode) encryptXattrName(attr string) (string, error) {
+ // xattr names are encrypted like file names, but with a fixed IV.
+ cAttr, err := rn.nameTransform.EncryptXattrName(attr)
+ if err != nil {
+ return "", err
+ }
+ return xattrStorePrefix + cAttr, nil
+}
+
+func (rn *RootNode) decryptXattrName(cAttr string) (attr string, err error) {
+ // Reject anything that does not start with "user.gocryptfs."
+ if !strings.HasPrefix(cAttr, xattrStorePrefix) {
+ return "", syscall.EINVAL
+ }
+ // Strip "user.gocryptfs." prefix
+ cAttr = cAttr[len(xattrStorePrefix):]
+ attr, err = rn.nameTransform.DecryptXattrName(cAttr)
+ if err != nil {
+ return "", err
+ }
+ return attr, nil
+}