diff options
author | Jakob Unterwurzacher | 2020-07-14 19:55:20 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-07-14 19:55:20 +0200 |
commit | 57d572dbc10cfb1d14642598b0827d4119b26b64 (patch) | |
tree | 16e46ff7a7746edfc471ba06ef0570db92fd09fe /internal/fusefrontend/root_node.go | |
parent | 4a0966e79efb157b612e4f5867ec6f111571546c (diff) |
v2api: implement Getxattr, Setxattr, Removexattr, Listxattr
gocryptfs/tests/xattr passes.
Diffstat (limited to 'internal/fusefrontend/root_node.go')
-rw-r--r-- | internal/fusefrontend/root_node.go | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/internal/fusefrontend/root_node.go b/internal/fusefrontend/root_node.go index 72d5581..5870c97 100644 --- a/internal/fusefrontend/root_node.go +++ b/internal/fusefrontend/root_node.go @@ -265,3 +265,55 @@ func (rn *RootNode) encryptSymlinkTarget(data string) (cData64 string) { cData64 = rn.nameTransform.B64EncodeToString(cData) return cData64 } + +// 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) (cData []byte) { + if len(data) == 0 { + return []byte{} + } + return rn.contentEnc.EncryptBlock(data, 0, nil) +} + +// decryptXattrValue decrypts the xattr value "cData". +func (rn *RootNode) decryptXattrValue(cData []byte) (data []byte, err error) { + if len(cData) == 0 { + return []byte{}, nil + } + data, err1 := rn.contentEnc.DecryptBlock([]byte(cData), 0, nil) + if err1 == nil { + return data, nil + } + // This backward compatibility is needed to support old + // file systems having xattr values base64-encoded. + cData, err2 := rn.nameTransform.B64DecodeString(string(cData)) + if err2 != nil { + // Looks like the value was not base64-encoded, but just corrupt. + // Return the original decryption error: err1 + return nil, err1 + } + return rn.contentEnc.DecryptBlock([]byte(cData), 0, nil) +} + +// encryptXattrName transforms "user.foo" to "user.gocryptfs.a5sAd4XAa47f5as6dAf" +func (rn *RootNode) encryptXattrName(attr string) (cAttr string) { + // xattr names are encrypted like file names, but with a fixed IV. + cAttr = xattrStorePrefix + rn.nameTransform.EncryptName(attr, xattrNameIV) + return cAttr +} + +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.DecryptName(cAttr, xattrNameIV) + if err != nil { + return "", err + } + return attr, nil +} |