lkml.org 
[lkml]   [2003]   [Aug]   [22]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
/
DateFri, 22 Aug 2003 09:19:27 -0700 (PDT)
FromLinus Torvalds <>
SubjectRe: authentication / encryption key retention
On Fri, 22 Aug 2003, David Howells wrote:
> 
> I think the best way is to have a stack of "personae" attached to a
> process. Each persona would then have an identity (UID) and a sequence of keys.

I don't know if UID helps much. What would you use it for?

The UID is already used to index into the "struct user" thing, and that
can (and probably should) contain a set of keys associated with that user.  
That implies that we _already_ have a UID -> set-of-key translation,
without actually mixing the UID with the keys themselves.

> The top persona on the stack would define what the process looked like to other
> processes - controlling access to the process by signal and ptrace.

This is what we do have UID's for, and changing that would break a lot of 
existing security-conscious programs potentially very badly. Another 
reason not to mix up the uid/key concepts.

> One of the personae on the stack would be elected to be the "effective" one -
> the one that gets attached to newly opened files, and is used to specify access
> to other processes for signal and ptrace.

You really want the "file open" part to be the thing that decides which 
key or bunch of keys are relevant to that file open. And I don't think it 
would have anything to do with a persona: a file open will care about the 
particular keys needed for that connection/filesystem/file, not about 
"persons".

While a person will want to have keys associated with multiple _different_ 
filesystems or connections. 

So there is no 1:1 relationship there.

So my suggestion boils down to:

 - do _not_ mix up current uid/gid issues with key management. It will 
   only cause untold pain for programs that expect to care only about 
   uids. 

   So uid/group changes would happen exactly like they do now: and they 
   would result only in _purely_ uid/gid-related security elevation. 

   Of course, since we can have uid/gid-specific key bunches (ie the 
   "struct user" thing), when you have a setuid program that switches to 
   another user, you may implicitly get access to that users keys. But 
   that is only a direct result of the setuid itself, and doesn't change 
   the security model of setuid. It's 100% equivalent.

 - For "group of key management", I do think you want to have your 
   "persona", but not because you want to associate them directly with 
   uid/gid issues, but because you would need to have some mechanism to 
   pass many unrelated keys around, without having to pass around _all_ 
   your own keys.

   And also, probably more importantly, it would also be the way to
   invalidate a bunch of keys (ie the security deamon that gave you a 
   particular bucket because you identified yourself to it can invalidate
   the whole bucket without actually having to invalidate each key 
   separately).

   So it would be just a "bucket of keys" you got from somewhere. Maybe 
   you get a couple of buckets as part of your login, and maybe you have 
   to do some strong authentication to a security server to get another
   "bucket".

   But "two buckets" would not make "one larger bucket".

My personal favourite would actually be to allow "buckets of buckets of 
[buckets of] keys". The reason you may want this is:

 - it must _not_ be possible to read out a key just because you have 
   access to it. In networked filesystems, keys don't have any specific 
   relevance (they're just random bits), but in many other cases they _do_ 
   have special relevance (ie they could be somebody's private key that he
   gave you temporary access to).

 - this means that once you get a key or a "bucket of keys", you can't 
   just re-create it. The only thing you can do is to create another 
   reference to it. So if you want to pass off the keys you got to some 
   third party, together with a few new keys of your own, you'd really 
   need to create a new "bucket" that contains a pointer to the old bucket
   along with the new keys.

(disallowing recursive buckets is an issue, but is pretty trivial)

So the data structures could be something really trivial, like

	struct key_bucket {
		int type;	/* bucket or individual key */
		atomic_t count;	/* reference count */
		int valid;
		char *name;	/* identifier of creator of this bucket */
		union {
			struct key *key;
			struct bucket *bucket;
		}
	};
	struct key {
		int type;
		atomic_t count;
		const char *description;
		const char *blob;
	};
	struct bucket {
		int entries;
		struct key_bucket *list[];
	};
and now "struct key_bucket" can be just a single key, or it can be a 
bucket of single keys, or it can be a bucket of mixed keys/buckets.

(Yeah, the contents of "struct key" are totally made-up. The "blob" is the 
content-dependent part of the key, but they will obviusly depend on what 
kind of key it is, so you need some higher-level description of the key so 
that the _users_ of the key can search for a key they are interested in.)

And notice how you can invalidate an arbitrary bucket by just marking it
"invalid" - that doesn't invalidate any of the keys contained within, but
it just means that the key_bucket cannot be searched/looked up any more,
and thus it's effectively disabled.

What I really care about is:

 - the data structure/mechanism should be totally agnostic about the kind 
   of keys you hide in there. The only thing that should be contained in 
   the keys/buckets (apart from the key blob itself) is enough meta-data 
   that we can have an a sane "look up keys of type xxx" operation. 

 - you do _not_ depend on "read the keys, duplicate them, write them out 
   again as a new bunch" as a maintenance operation. That does _not_work_ 
   for keys that are supposed to be private. If I give somebody else my 
   key, that does not mean that he can read it. He can use it, but he 
   can't make a copy.

With the straw-man bucket-of-buckets proposals, you can now endow _any_ 
data structure with any random collection of keys by just adding a

	struct key_bucket *keys;

entry to it.

(And I'm carefully staying out of guessing what functions we want to have 
to iterate over all keys of a specific type. But it doesn't look 
impossible).

		Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:48    [from the cache]
©2003-2008