Subject: [nfsv4] SSV

From: Nicolas Williams <[email-masked]>
Date: Wed, 15 Aug 2007 15:42:49 -0500

I've looked at the -13 revision of the NFSv4.1 I-D and I have some
comments on the SSV thing.

I will not tell you to radically change the scheme, though I might have
done it differently (but you knew that :)

I think the SSV scheme is mostly reasonable, but it has some issues:

a) The SSV is used as the cipher and HMAC key for the SSV GSS mechanism
   without any further key derivation.

   I recommend using a KDF (key derivation function) to derive separate
   keys for the integrity and confidentiality algorithms.

   See (b) below.

b) The same keys are used in both directions and there is no
   directionality flag in the per-message tokens.

   This means that there's a reflection attack on the SSV GSS mech.

   I suspect that reflecting these messages cannot be of much use to any
   attacker because of the context in which this mech is used, but it's
   much easier to analyze the security of the whole if you either add a
   directionality flag or, better yet, use a KDF to derive separate keys
   for each direction.  See (a) above.

c) The SSV GSS mech's per-message tokens send both, a confounder and an
   IV.  This is redundant.  The IV should be constant or else it should be
   negotiated in the SET_SSV operation; the confounder MUST be picked
   randomly and must not be reused (implementors typically don't bother
   with the latter because it's hard; one way to implement random
   confounder w/o reuse is to use a randomly selected number to seed a
   long-period PRNG and then use the output of the PRNG to get the
   confounders, but that PRNG had better be secure).

[Re-using the Kerberos V mechanism's per-message tokens here would
certainly avoid these issues, and others too.  Fortunately the SSV GSS
mech looks relatively simple to implement.]

d) The RPCSEC_GSS context handles really need to be assigned when the
   SSV keys are set, else there's a potential race in re-keying the SSV
   of a given context handle.

   Alternatively the per-message tokens should include a key ID or
   number.

e) A separate section on implementation notes related to RPCSEC_GSS
   would be nice.

   One could not implement this protocol atop a naive implementation of
   ONC RPC and RPCSEC_GSS because no implementor of RPCSEC_GSS would
   think to provide the application with precise control over RPCSEC_GSS
   context handles and associated GSS contexts.

   The aspects of NFSv4.1 that are relevant to RPCSEC_GSS implementors
   are:  the backchannel RPCSEC_GSS contexts, and the EXCHANGE_ID and
   SET_SSV operations, and the SSV GSS mechanism.

f) The Security Considerations section needs more text :)

Nico
-- 

_______________________________________________
nfsv4 mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/nfsv4

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 11:38:22 -0500

More comments:

 - I mis-read the purpose of *_ssv_seq -- these are not pper-msg token
   sequence numbers but what I would call "key IDs"  -- this addresses
   one of my comments from yesterday, but it creates another problem:
   there's no replay protection in the SSV GSS mech.

 - Also, what the heck is the purpose of requesting more than one
   RPCSEC_GSS context handle in EXCHANGE_ID?!

   I had thought that it was to avoid contention over a per-msg token
   sequence number, but evidently that's not the case since SSV doesn't
   support per-msg token sequence numbers.

   It would seem that a single SSV is shared across all the RPCSEC_GSS
   context handles created in EXCHANGE_ID, which presents key re-use
   issues (since there's no KDF, no nonces, no context token exchange,
   nada).

My advice, with a view to sticking to the current design so as not to be
too disruptive, is as follows:

 - have only one RPCSEC_GSS context, or else have SET_SSV bind an SSV to
   a given context handle

 - add a KDF to provide for different integrity and confidentiality keys
   and for different keys in each direction (alternatively, use a
   directionality indicator)

 - add a per-msg token sequence number for replay protection

 - you might want to say that the length of an SSV must correspond to
   the required length of the negotiated cipher's key (assuming it's got
   a fixed key length -- but the AES ciphers used here obviously do), OR
   provide a desired key length argument to the KDF.

The SSV mech description needs to be moved so that it shows up in the
table of contents.  This I-D is HUGE, it shouldn't be so hard to find
this needle in it -- I should be able to glance at the ToC to find it.

The motivation for the SSV needs to be made very plain, and it needs to
be mentioned in the Security Considerations section.  Correct me if I'm
wrong, but as I see it the motivation is to provide a bit more
protection to "multi-user clients that don't have their own GSS
initiator credentials."  I'm not sure that this motivation is worthwhile
given other issues; a detailed treatment of the matter would help.

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 11:59:36 -0500

Also, though this isn't strictly necessary, like the text I requested
with advice to RPCSEC_GSS implementors, I'd like to see some advice
about how one might implement a GSS mechanism that has no context token
exchange.  I think the answer is "make an exported security context
token and call GSS_Import_sec_context() to get a real SECURITY CONTEXT
handle."  That's the closest we can come using GSS semantics.

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 15:07:04 -0500

>  - have only one RPCSEC_GSS context, or else have SET_SSV bind an SSV to

Further, SET_SSV as written in -13 assumes that a GSS-API security
context can be updates on the fly.  This may be true for some
implementations, but for those of us who are starting from a code base
based on the RFC2744 C bindings of the GSS-API this assumption means
doing a lot more work than if we just allocated a new RPCSEC_GSS context
handle on every SET_SSV operation.

Frankly, the whole context token avoidance thing seems like a vary bad
idea to me -- it does a lot more violence to the RPCSEC_GSS and GSS-API
frameworks that we *already* have in Solaris (and, I bet, Linux, and
elsewhere) than it has to.  Keep in mind that there is nothing about the
GSS-API that makes it fundamentally non-reentrant, and it would be a lot
easier to spec and implement SSV as a GSS mechanism that uses another
GSS mechanism to protect its negotiation of algorithms and its shared
secret.  But, at any rate, if we'll not pursue that path then the very
least we could do is keep the level of pain down -- see my various
suggestions from yesterday and today.

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 15:16:59 -0500

> suggestions from yesterday and today.

I should add that magically instantiating a fully established GSS
security context as called for in -13 is at least feasible using
GSS_Import_sec_context() -- no changes needed to the GSS framework.

Magically updating internal details of a fully established GSS security
context is NOT possible through any existing GSS-API functions.  And
some implementors would have to do that or else do violence to other
existing code because, for example, there might be an assumption that
the gss_ctx_id_t associated with a given RPCSEC_GSS context handle
doesn't change while an RPC in being processed, so that replacing a
gss_ctx_id_t as a result of a SET_SSV operation would be impossible, so
either change that assumption or extend the GSS framework.  Not fun.

Nico
--

---

From: Mike Eisler <[email-masked]>
Date: Thu, 16 Aug 2007 13:47:13 -0700 (PDT)

>    there's no replay protection in the SSV GSS mech.

RFC 2203:

   When GSS_Init_sec_context() is called, the parameters
   replay_det_req_flag and sequence_req_flag must be turned off.

Since the SSV mechanism is being used only for RPCSEC_GSS, replay
protection is not needed; RPCSEC_GSS has its own replay detection.
 
>    RPCSEC_GSS context handle in EXCHANGE_ID?!

RPCSEC_GSS has a maximum window size. In some server implementations
this derived from the number of bits in the maximum unsigned integer
data type; the unsigned integer is used as a bit mask to keep track
of which requests have been received (replay detection).

In addition in some client implementations, the use of the RPCSEC_GSS
auth handle is single threaded; a single clnt_call() thus freezes
the RPCSEC_GSS handle.

>    context handles created in EXCHANGE_ID, which presents key re-use

Yes it is shared.

>    issues (since there's no KDF, no nonces, no context token

I don't see the issues. The SSV mech's state consists of the key,
and the key version.

>  - add a KDF to provide for different integrity and confidentiality

OK.

>    directionality indicator)

Yes, this is definitely a security hole; thanks for catching it.

>    provide a desired key length argument to the KDF.

OK.

> this needle in it -- I should be able to glance at the ToC to find

OK.

> be mentioned in the Security Considerations section.  Correct me if

OK

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 15:56:38 -0500

> protection is not needed; RPCSEC_GSS has its own replay detection.

Right, there's a sequence number window in RPCSEC_GSS.  Thanks for
reminding me of that.

> auth handle is single threaded; a single clnt_call() thus freezes

This is about what I expected.

> I don't see the issues. The SSV mech's state consists of the key,

Well, we have multiple GSS contexts with the same keys.  The particular
way in which they are being used in NFSv4.1 might mean that this is OK,
but then again...  The whole confounder issue comes in here too.
Particularly if someone wants to use a PRNG as a source of confounders.
That all might be addressed with some text rather than protocol changes,
but see my other comment about magic updating of established GSS
contexts -- me no likey.

> Yes, this is definitely a security hole; thanks for catching it.

NP.

Nico
--

---

From: Mike Eisler <[email-masked]>
Date: Thu, 16 Aug 2007 14:26:10 -0700 (PDT)

> Well, we have multiple GSS contexts with the same keys.  The

We have one GSS context with one key (and in -14, it will be 5 keys;
the SSV, and 4 keys derived from it for directionality and integrity
vs. privacy).

Multiple RPCSEC_GSS handles share the same GSS context.
Since there is no per MIC or WRAP token state, multithreading the
MIC (and WRAP) token generating function is fairly simple:

  lock(), 
    store the SSV sequence and the derived key(s) in a local 
       variable,
  unlock(), 
  use the SSV and derived key(s) to compute the token

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 16:49:02 -0500

> the SSV, and 4 keys derived from it for directionality and integrity

Oh, I see.  That helps.

And I think we can just torture kgss_import_sec_context() to treat its
output parameter (context_handle) as an input/output parameter so the
SSV can be updated on a SET_SSV.

> Multiple RPCSEC_GSS handles share the same GSS context.

Well.  Not until now.  But yes, that should work.

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 16 Aug 2007 17:09:29 -0500

>   use the SSV and derived key(s) to compute the token

You might as well not bother with a KDF and derived keys -- just demand
that the SSV be long enough (and randomly-generated) to be partitioned
into four keys of the correct lengths.