AES encrypted filesystem.

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

AES encrypted filesystem.

Irad K
My case is rather simple to explain, and I'm struggling to find in which layer should I implement it. 

Basically I've got files that are rather sensitive so I keep them encrypted, and I'd like to let only certain processes the ability to 
interact with them as they were regular files (all other processes who attempt to touch those files, will see them as encrypted). 

For that I'm willing to use AES256 which is a simple encryption method with symmetric key. 

Now, for every access to a file contents (either read/write or map) I want to be able to perform the following flow : 

1. READ: after reading the raw data (encrypted), it will get decrypted with the symmetric key that the process has.
2. WRITE: before writing, the contents get encrypted with the symmetric key that the process has. 
3. MMAP: the same for file mmap, I wish to decrypt the file contents before they mapped to memory. 

I'm asking is just some direction about where to start from .. which layer should I apply to implement these ideas disregarding the OS (osx or linux). 

After I read the manuals I found out that the only way to control file actions is using the API in fuse_lowlevel.h or fuse.h, both let you set a vector of file operations called fuse_operation or fuse_lowlevel_ops. 

I've tried to play with these api's, but when I tested it, it seems that when I read or write or map the file, it doesn't goes through the operation I just defined in the vector I mentioned above. 

thanks 
Irad

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AES encrypted filesystem.

Nikolaus Rath
On Jun 11 2017, Irad K <[hidden email]> wrote:

> My case is rather simple to explain, and I'm struggling to find in which
> layer should I implement it.
>
> Now, for every access to a file contents (either read/write or map) I want
> to be able to perform the following flow :
>
> 1. READ: after reading the raw data (encrypted), it will get decrypted with
> the symmetric key that the process has.
> 2. WRITE: before writing, the contents get encrypted with the symmetric key
> that the process has.
> 3. MMAP: the same for file mmap, I wish to decrypt the file contents before
> they mapped to memory.
>
> I'm asking is just some direction about where to start from .. which layer
> should I apply to implement these ideas disregarding the OS (osx or linux).

FUSE is able to do what you outline here.

> Basically I've got files that are rather sensitive so I keep them
> encrypted, and I'd like to let only certain processes the ability to
> interact with them as they were regular files (all other processes who
> attempt to touch those files, will see them as encrypted).

Keep in mind that there are a lot of ways for the sensitive information
to leak once it is in memory unencrypted, even if you restrict access to
some processes.

> After I read the manuals I found out that the only way to control file
> actions is using the API in fuse_lowlevel.h or fuse.h, both let you set a
> vector of file operations called fuse_operation or fuse_lowlevel_ops.
>
> I've tried to play with these api's, but when I tested it, it seems that
> when I read or write or map the file, it doesn't goes through the operation
> I just defined in the vector I mentioned above.

You'll need to be a little more specific than that, otherwise there's
very little we can do to help. Did you take a look at the example
filesystems? Are they working for you?

Best,
-Nikolaus

--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             »Time flies like an arrow, fruit flies like a Banana.«

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AES encrypted filesystem.

Irad K
Hi Nikolaus and thank your for your response. 

Here are the specific challenges I'm currently facing with :

1. How to pass the AES key for encrypting/decrypting. I want to be able to allow certain processes read / write the data after encryption. However, when calling the system call read / write /mmap, none of them contain extra argument for supplying the AES block key (the symmetric key). Therefore, I need to communicate the filesystem about the key and whose process does it belong. I also want that this channel to be secure and make it hard to eavesdrop by unwanted entities. Do you have any idea how to do it ? 
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
2. On which software layer to perform the decryption/encryption. the Osxfuse API contain 2 APIs as explain in the documentation :  a "high-level", synchronous API, and a "low-level" asynchronous API. I've read the documentation, but I'm still not sure I fully understand the difference between them. which I/F did you use in your implementation and what was the motivation for choosing it upon the other one ? in addition, I assumed the the encryption layer should be reside on the driver, because it needs to be secure and untraceable as much as possible. do you know if there's an API for osxfuse kernel extension (kext).

3. Understanding the data flow. I wish to base my solution on the loopback filesystem, where I can easily add my encryption layer on top of root filesystem. If I'm looking at the read command in struct fuse operation, it seems that the only thing that it does is calling 'pread' (see code below). 

So as I see the flow, when I invoke read sys call, it reaches the fuse driver in kernel layer, which pass it back to user-space to the callback fuse_operations.read() in fuse daemon, and then it return back to the kernel using 'pread' sys call which perform the actual task of reading the file. 
The Question here's is how does the kernel knows to pass the first sys call to daemon, and to do the read on the second sys call.


static int

loopback_read(const char *path, char *buf, size_t size, off_t offset,

              struct fuse_file_info *fi)

{

    int res;

    

    (void)path;

    res = pread(fi->fh, buf, size, offset);

    if (res == -1) {

        res = -errno;

    }

    

    return res;

}


Thanks in advance, 
Irad

On Tue, Jun 13, 2017 at 5:24 AM, Nikolaus Rath <[hidden email]> wrote:
On Jun 11 2017, Irad K <[hidden email]> wrote:
> My case is rather simple to explain, and I'm struggling to find in which
> layer should I implement it.
>
> Now, for every access to a file contents (either read/write or map) I want
> to be able to perform the following flow :
>
> 1. READ: after reading the raw data (encrypted), it will get decrypted with
> the symmetric key that the process has.
> 2. WRITE: before writing, the contents get encrypted with the symmetric key
> that the process has.
> 3. MMAP: the same for file mmap, I wish to decrypt the file contents before
> they mapped to memory.
>
> I'm asking is just some direction about where to start from .. which layer
> should I apply to implement these ideas disregarding the OS (osx or linux).

FUSE is able to do what you outline here.

> Basically I've got files that are rather sensitive so I keep them
> encrypted, and I'd like to let only certain processes the ability to
> interact with them as they were regular files (all other processes who
> attempt to touch those files, will see them as encrypted).

Keep in mind that there are a lot of ways for the sensitive information
to leak once it is in memory unencrypted, even if you restrict access to
some processes.

> After I read the manuals I found out that the only way to control file
> actions is using the API in fuse_lowlevel.h or fuse.h, both let you set a
> vector of file operations called fuse_operation or fuse_lowlevel_ops.
>
> I've tried to play with these api's, but when I tested it, it seems that
> when I read or write or map the file, it doesn't goes through the operation
> I just defined in the vector I mentioned above.

You'll need to be a little more specific than that, otherwise there's
very little we can do to help. Did you take a look at the example
filesystems? Are they working for you?

Best,
-Nikolaus

--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             »Time flies like an arrow, fruit flies like a Banana.«

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AES encrypted filesystem.

Michael Theall-2
Hi Irad,

1) The only way you'd be able to do this through fuse is via ioctl(2) or setxattr(2). If you're really worried someone could intercept the keys (like via gdb breaking on these syscalls and looking at the arguments) you'll need to secure this message passing too. An alternative would be your fuse implementation listening on a socket or something and communicating over that, but this will be much more complicated to correlate the file/process. Of course, all of these ways means that your end applications need to know about your filesystem and how to trade encryption keys with it.

2) This is irrelevant to encryption. Use the high-level interface if you want path-based operations or for simplicity. Use the low-level interface for inode-based operations or you need more advanced functionality.

3) pread(2) is used here because it directly takes an offset. It just makes it easier to implement in the example code. You could use read(2), fread(3), mmap(2), or really any way you are able to read the file at all. Depending on what you use, you might need to do it in some type of critical section for consistency if you have simultaneous access.

PLEASE NOTE: Once you have sent unencrypted data to the kernel, then when some other process tries to read that file it may read the unencrypted data directly from the kernel, bypassing your fuse implementation. If you want to avoid this, you need to ensure that the kernel never caches your data.

The only truly secure way to do what you want is to do all encryption/decryption at the application layer where the kernel and your fuse implementation (which would become unnecessary) never see unencrypted data.

Regards,
Michael Theall


On Thu, Jun 15, 2017 at 2:22 AM Irad K <[hidden email]> wrote:
Hi Nikolaus and thank your for your response. 

Here are the specific challenges I'm currently facing with :

1. How to pass the AES key for encrypting/decrypting. I want to be able to allow certain processes read / write the data after encryption. However, when calling the system call read / write /mmap, none of them contain extra argument for supplying the AES block key (the symmetric key). Therefore, I need to communicate the filesystem about the key and whose process does it belong. I also want that this channel to be secure and make it hard to eavesdrop by unwanted entities. Do you have any idea how to do it ? 
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
2. On which software layer to perform the decryption/encryption. the Osxfuse API contain 2 APIs as explain in the documentation :  a "high-level", synchronous API, and a "low-level" asynchronous API. I've read the documentation, but I'm still not sure I fully understand the difference between them. which I/F did you use in your implementation and what was the motivation for choosing it upon the other one ? in addition, I assumed the the encryption layer should be reside on the driver, because it needs to be secure and untraceable as much as possible. do you know if there's an API for osxfuse kernel extension (kext).

3. Understanding the data flow. I wish to base my solution on the loopback filesystem, where I can easily add my encryption layer on top of root filesystem. If I'm looking at the read command in struct fuse operation, it seems that the only thing that it does is calling 'pread' (see code below). 

So as I see the flow, when I invoke read sys call, it reaches the fuse driver in kernel layer, which pass it back to user-space to the callback fuse_operations.read() in fuse daemon, and then it return back to the kernel using 'pread' sys call which perform the actual task of reading the file. 
The Question here's is how does the kernel knows to pass the first sys call to daemon, and to do the read on the second sys call.


static int

loopback_read(const char *path, char *buf, size_t size, off_t offset,

              struct fuse_file_info *fi)

{

    int res;

    

    (void)path;

    res = pread(fi->fh, buf, size, offset);

    if (res == -1) {

        res = -errno;

    }

    

    return res;

}


Thanks in advance, 
Irad

On Tue, Jun 13, 2017 at 5:24 AM, Nikolaus Rath <[hidden email]> wrote:
On Jun 11 2017, Irad K <[hidden email]> wrote:
> My case is rather simple to explain, and I'm struggling to find in which
> layer should I implement it.
>
> Now, for every access to a file contents (either read/write or map) I want
> to be able to perform the following flow :
>
> 1. READ: after reading the raw data (encrypted), it will get decrypted with
> the symmetric key that the process has.
> 2. WRITE: before writing, the contents get encrypted with the symmetric key
> that the process has.
> 3. MMAP: the same for file mmap, I wish to decrypt the file contents before
> they mapped to memory.
>
> I'm asking is just some direction about where to start from .. which layer
> should I apply to implement these ideas disregarding the OS (osx or linux).

FUSE is able to do what you outline here.

> Basically I've got files that are rather sensitive so I keep them
> encrypted, and I'd like to let only certain processes the ability to
> interact with them as they were regular files (all other processes who
> attempt to touch those files, will see them as encrypted).

Keep in mind that there are a lot of ways for the sensitive information
to leak once it is in memory unencrypted, even if you restrict access to
some processes.

> After I read the manuals I found out that the only way to control file
> actions is using the API in fuse_lowlevel.h or fuse.h, both let you set a
> vector of file operations called fuse_operation or fuse_lowlevel_ops.
>
> I've tried to play with these api's, but when I tested it, it seems that
> when I read or write or map the file, it doesn't goes through the operation
> I just defined in the vector I mentioned above.

You'll need to be a little more specific than that, otherwise there's
very little we can do to help. Did you take a look at the example
filesystems? Are they working for you?

Best,
-Nikolaus

--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             »Time flies like an arrow, fruit flies like a Banana.«

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AES encrypted filesystem.

Nikolaus Rath
In reply to this post by Irad K
On Jun 15 2017, Irad K <[hidden email]> wrote:

> Hi Nikolaus and thank your for your response.
>
> Here are the specific challenges I'm currently facing with :
>
> 1. *How to pass the AES key for encrypting/decrypting*. I want to be able
> to allow certain processes read / write the data after encryption. However,
> when calling the system call read / write /mmap, none of them contain extra
> argument for supplying the AES block key (the symmetric key). Therefore, I
> need to communicate the filesystem about the key and whose process does it
> belong. I also want that this channel to be secure and make it hard to
> eavesdrop by unwanted entities. Do you have any idea how to do it ?

That seems pointless to me. If, in the ideal case, you want the process
to supply the key in the read/write call, why can't the process simply
do the encryption itself? That will be faster and less complex to
implement. For example, you could write a small library that provides
read_encrypted() and write_encrypted() functions with exactly the
semantics that you want.

> 2. *On which software layer to perform the decryption/encryption.* the
> Osxfuse API contain 2 APIs as explain in the documentation :  a
> "high-level", synchronous API, and a "low-level" asynchronous API. I've
> read the documentation, but I'm still not sure I fully understand the
> difference between them.
> which I/F did you use in your implementation

What implementation do you mean? Did you take a look at the examples/
directory in libfuse? It contains a passthrough filesystem implemented
once using the high- and once using the low-level API. That might help.


Best,
-Nikolaus

--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             »Time flies like an arrow, fruit flies like a Banana.«

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Loading...