* Key management in Reiser4
@ 2005-09-20 19:12 Edward Shishkin
2005-09-21 15:38 ` David Howells
0 siblings, 1 reply; 3+ messages in thread
From: Edward Shishkin @ 2005-09-20 19:12 UTC (permalink / raw)
To: Reiserfs developers mail-list, David Howells; +Cc: Reiserfs List
Hello everyone.
Any comments are welcome.
David, would you please review the following:
KEY MANAGEMENT IN REISER4
I suggest to consider The KRS (Kernel Key Retention Service, (c) Red
Hat) for
keeping/accessing the keys. The KRS includes a number of syscalls and kernel
services described in linux/Documentation/keys.txt. It seems quite universal
and contains almost all we need. Also we can make the keys to be
persistent in
flush time by managing extra-references.
Registering the key type
Reiser4 will register its own key type during mount (in accordance with
the KRS design such registration is possible only in the kernel). I will not
provide all details, just note, that ->instantiate() method of reiser4
key_type
calls linux crypto-api and allocates a struct crypto_tfm, so instantiated
payload is a pointer to struct reiser4_crypto_stat which contains a
pointer to
the allocated crypto_tfm. The uninstantiated payload should contain the
following:
. actual key;
. passphrase (to create/check stat-data keyid);
. cipher transform plugin id;
. digest transform plugin id;
. compression transform plugin id;
Then user can add a key of registered type and given description to the
process
using add_key() syscall. The description is used for matching key in a
search
and can be observed in procfs with other attributes. If the key of this
description already exists, then add_key() will try to update it with given
payload (payload is a blob of data which represents actual key and maybe
something else). So, as I understand, description is a "name" of a key
in the
system, that can be changed by add_key() syscall.
Creating a cryptcompress file
We will add a new mount option so reiser4_create() first will check
for the
keys of registered reiser4-specific type in the target keyring if this
option
is on. If such keys are present, then cryptcompress regular file will be
created. If no, then the file plugin will be inherited from parent (unix
file
by default). If the number of attached keys (of all types) is small, this
operation will not be expensive).
create_cryptcompress() looks for a key of some magic description (say
"default"), then calculates and writes the keyid to disk stat-data.
(keyid is a 32-bit or greater word created by the actual key and passphrase
using strong hash).
So if you want to create a file ciphered by some key, make sure that
this key
is present in the keyring and currently labeled as "default" (it can be
provided
by using add_key() syscall (*).
Opening a cryptcompress file
The ->open() method of cryptcompress plugin looks for a key in the target
keyring by stat-data keyid (**), checks its validness (by validate_key()
kernel service of KRS), then increments a reference counter and adds the
pointer
to reiser4 part of inode (if it is absent). The ->destroy_inode() method of
cryptcompress plugin decrements the reference counter and releases
reiser4-specific payload (if the counter became zero). So even in the
case when
the key became invalid, it can not be evicted, and flush algorithm can
use it
for ciphering, while it is impossible say to open files with this key.
____________________
(*) Actually it is inconvenient: if there is a lot of keys in the
keyring, then
it would be better to keep a description and mark key as "default" by some
another way. I found that currently it is possible only for the
"keyring" key
type (The KRS consider keyrings like the keys of this special type). I
think to
prepare a patch against KRS to enable default keys of _all_ types (not
only for
keyrings). However it requires a linear search per target keyring
(currently the
KRS avoids a linear search using additional pointer in task_struct for
"default"
keyrings).
(**) All we have when trying to open a file is a keyid extracted from disk
stat-data. However the kernel service request_key() currently implements
only
matching by description. IMHO the last is not enough for the file
system: we can
supply different descriptions for the same payload when creating files,
so the
question is what a description should match in a search when opening a file?
One of the possible solutions is to add a new method (->match_pattern())
in the
struct key_type and a new kernel service request_key_by_pattern():
int (*match_pattern)(const struct key *key,
const void *pattern);
This method is to match the @pattern with another one constructed by the
payload
of the @key.
struct key *request_key_by_pattern(const struct key_type *type,
const void *pattern);
This kernel service is to request a key with a pattern that matches the
pattern specified according to the key type's ->match_pattern() function
(matching by stat-data keyid in the case of reiser4).
So our needs within the KRS are the following:
1. ->match_pattern() method in struct key_type;
2. request_key_by_pattern() kernel service;
3. a pair of new keyctls to set/get default key of _any_ types;
4. a kernel service to get default key of _any_ types.
If there is no objections, I will prepare a patch for the features above.
Thanks,
Edward.
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: Key management in Reiser4
2005-09-20 19:12 Key management in Reiser4 Edward Shishkin
@ 2005-09-21 15:38 ` David Howells
2005-09-23 18:29 ` Edward Shishkin
0 siblings, 1 reply; 3+ messages in thread
From: David Howells @ 2005-09-21 15:38 UTC (permalink / raw)
To: Edward Shishkin
Cc: Reiserfs developers mail-list, David Howells, Reiserfs List,
keyrings
Edward Shishkin <edward@namesys.com> wrote:
> David, would you please review the following:
>
> KEY MANAGEMENT IN REISER4
There's a mailing list for such discussions:
keyrings@linux-nfs.org
I should update the MAINTAINERS file to reflect this.
> Reiser4 will register its own key type during mount (in accordance with
> the KRS design such registration is possible only in the kernel).
Since the operations may get called a lot, may get called from uninterruptible
contexts and need to handle the construction and destruction of kernel
objects, sticking them in userspace would seem to be a bad idea.
Edward Shishkin <edward@namesys.com> wrote:
> so instantiated
> payload is a pointer to struct reiser4_crypto_stat which contains a pointer to
> the allocated crypto_tfm. The uninstantiated payload should contain the
> following:
> . actual key;
> . passphrase (to create/check stat-data keyid);
> . cipher transform plugin id;
> . digest transform plugin id;
> . compression transform plugin id;
You may wish to talk to Michael Halcrow of IBM as he is dealing with
eCryptFS. You may be able to borrow some of his stuff.
> Then user can add a key of registered type and given description to the
> process using add_key() syscall.
That's one way of getting a key into the keyring. The other way is by the
filesystem calling request_key(). There are improvements coming to avoid the
need to call /sbin/request-key if there's an already running service daemon
that can do the key instantiation.
> (payload is a blob of data which represents actual key and maybe something
> else)
The payload blob may be structured internally, and the instantiate and update
operations may take it apart and attach to the key in various places and in
various ways.
> So, as I understand, description is a "name" of a key in the system, that
> can be changed by add_key() syscall.
The description of a key may not be changed, not even by the add_key()
syscall. All add_key() can do is add a new key of a different name or update
the payload of an existing key of the same name.
> create_cryptcompress() looks for a key of some magic description (say
> "default"), then calculates and writes the keyid to disk stat-data.
> (keyid is a 32-bit or greater word created by the actual key and passphrase
> using strong hash).
I presume the "keyid" you mention isn't the struct key serial number.
> So if you want to create a file ciphered by some key, make sure that this
> key
> is present in the keyring and currently labeled as "default" (it can be
> provided
> by using add_key() syscall (*).
Are you thinking of getting one struct key per file?
> (*) Actually it is inconvenient: if there is a lot of keys in the keyring,
> then
> it would be better to keep a description and mark key as "default" by some
> another way. I found that currently it is possible only for the "keyring" key
> type (The KRS consider keyrings like the keys of this special type). I think
> to
> prepare a patch against KRS to enable default keys of _all_ types (not only
> for
> keyrings). However it requires a linear search per target keyring (currently
> the
> KRS avoids a linear search using additional pointer in task_struct for
> "default"
> keyrings).
What do you mean by default keyrings? The only "default" keyring is the
default target for request_key().
> (**) All we have when trying to open a file is a keyid extracted from disk
> stat-data. However the kernel service request_key() currently implements only
> matching by description. IMHO the last is not enough for the file system: we
> can
> supply different descriptions for the same payload when creating files, so the
> question is what a description should match in a search when opening a file?
> One of the possible solutions is to add a new method (->match_pattern()) in
> the
> struct key_type and a new kernel service request_key_by_pattern():
You don't need to do that. The description is an amorphous blob of text and
the key type is the only thing that matches it against the pattern supplied by
the searcher. You don't have to make the match() method call strcmp() if you
don't want to; you can do something totally wild and different instead if you
wish.
David
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Key management in Reiser4
2005-09-21 15:38 ` David Howells
@ 2005-09-23 18:29 ` Edward Shishkin
0 siblings, 0 replies; 3+ messages in thread
From: Edward Shishkin @ 2005-09-23 18:29 UTC (permalink / raw)
To: David Howells; +Cc: Reiserfs developers mail-list, Reiserfs List, keyrings
David Howells wrote:
>Edward Shishkin <edward@namesys.com> wrote:
>
>
>
>>David, would you please review the following:
>>
>> KEY MANAGEMENT IN REISER4
>>
>>
>
>There's a mailing list for such discussions:
>
> keyrings@linux-nfs.org
>
>I should update the MAINTAINERS file to reflect this.
>
>
>
>>Reiser4 will register its own key type during mount (in accordance with
>>the KRS design such registration is possible only in the kernel).
>>
>>
>
>Since the operations may get called a lot, may get called from uninterruptible
>contexts and need to handle the construction and destruction of kernel
>objects, sticking them in userspace would seem to be a bad idea.
>
>Edward Shishkin <edward@namesys.com> wrote:
>
>
>
>>so instantiated
>>payload is a pointer to struct reiser4_crypto_stat which contains a pointer to
>>the allocated crypto_tfm. The uninstantiated payload should contain the
>>following:
>> . actual key;
>> . passphrase (to create/check stat-data keyid);
>> . cipher transform plugin id;
>> . digest transform plugin id;
>> . compression transform plugin id;
>>
>>
>
>You may wish to talk to Michael Halcrow of IBM as he is dealing with
>eCryptFS. You may be able to borrow some of his stuff.
>
>
>
>>Then user can add a key of registered type and given description to the
>>process using add_key() syscall.
>>
>>
>
>That's one way of getting a key into the keyring. The other way is by the
>filesystem calling request_key(). There are improvements coming to avoid the
>need to call /sbin/request-key if there's an already running service daemon
>that can do the key instantiation.
>
>
>
>>(payload is a blob of data which represents actual key and maybe something
>>else)
>>
>>
>
>The payload blob may be structured internally, and the instantiate and update
>operations may take it apart and attach to the key in various places and in
>various ways.
>
>
>
>>So, as I understand, description is a "name" of a key in the system, that
>>can be changed by add_key() syscall.
>>
>>
>
>The description of a key may not be changed, not even by the add_key()
>syscall. All add_key() can do is add a new key of a different name or update
>the payload of an existing key of the same name.
>
>
>
>>create_cryptcompress() looks for a key of some magic description (say
>>"default"), then calculates and writes the keyid to disk stat-data.
>>(keyid is a 32-bit or greater word created by the actual key and passphrase
>>using strong hash).
>>
>>
>
>I presume the "keyid" you mention isn't the struct key serial number.
>
>
>
Yes, this is not a serial number. The keyid can be calculated only by
instantiated payload. This is a "fingerprint" of a cipher key, and we need
to check it every time when opening a file (to not allow users modify file
with invalid key)
>> So if you want to create a file ciphered by some key, make sure that this
>> key
>>is present in the keyring and currently labeled as "default" (it can be
>>provided
>>by using add_key() syscall (*).
>>
>>
>
>Are you thinking of getting one struct key per file?
>
>
>
Yes. Each file is supposed to be ciphered with its own key, but most likely
that in real life all files will be ciphered by a small number of keys.
>> (*) Actually it is inconvenient: if there is a lot of keys in the keyring,
>> then
>>it would be better to keep a description and mark key as "default" by some
>>another way. I found that currently it is possible only for the "keyring" key
>>type (The KRS consider keyrings like the keys of this special type). I think
>>to
>>prepare a patch against KRS to enable default keys of _all_ types (not only
>>for
>>keyrings). However it requires a linear search per target keyring (currently
>>the
>>KRS avoids a linear search using additional pointer in task_struct for
>>"default"
>>keyrings).
>>
>>
>
>What do you mean by default keyrings? The only "default" keyring is the
>default target for request_key().
>
>
>
We need a property for each instantiated key to be marked as "unique
target" in
its key type (there can not be more then one target for this type in the
system)
The defaul target for request_key() looks like the one which possesses this
property, but perhaps is it not a good idea to mix this.
>>(**) All we have when trying to open a file is a keyid extracted from disk
>>stat-data. However the kernel service request_key() currently implements only
>>matching by description. IMHO the last is not enough for the file system: we
>>can
>>supply different descriptions for the same payload when creating files, so the
>>question is what a description should match in a search when opening a file?
>>One of the possible solutions is to add a new method (->match_pattern()) in
>>the
>>struct key_type and a new kernel service request_key_by_pattern():
>>
>>
>
>You don't need to do that. The description is an amorphous blob of text and
>the key type is the only thing that matches it against the pattern supplied by
>the searcher. You don't have to make the match() method call strcmp() if you
>don't want to; you can do something totally wild and different instead if you
>wish.
>
>
>
Actually in our case in order to calculate such pattern (keyid) before
matching
we need the key to be instantiated, whereas the keyring can contain
uninstantiated keys. So I thought to add a simple kernel search service
which
first checks if the key is instantiated, then calls the ->match() if
true, and
returns"not found" otherwise.
Next trouble is that the ->match() is called everywhere, including places
where uninstantiated keys are also expected, whereas we can not
calculate the
pattern of uninstantiated keys. It makes me think about another match method
(for instantiated keys only).
Thanks,
Edward.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-09-23 18:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-20 19:12 Key management in Reiser4 Edward Shishkin
2005-09-21 15:38 ` David Howells
2005-09-23 18:29 ` Edward Shishkin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.