Subject: PRF comments

From: Ken Raeburn <[email-masked]>
Date: Thu, 23 Jun 2005 16:40:34 -0400

Going over the -04 drafts today, I was struck by a few things:

draft-ietf-kitten-gssapi-prf-04.txt:

   Mechanisms MUST be able to consume all the provided prf_in input data
   that is 2^14 or fewer octets.

   If a mechanism cannot consume as much input data as provided by the
   caller, then GSS_Pseudo_random() MUST return GSS_S_FAILURE.

We should probably add explicitly: "Mechanism PRF specifications may
not truncate the supplied input data."

   If the implementation cannot produce the desired output due to lack
   of resources then it MUST output what it can and still return
   GSS_S_COMPLETE.

This makes "mechanism spec said to output only X bytes"
indistinguishable from "out of resources".  If the output is being
used as protocol keying material or something comparable, then the
exchange may eventually fail because one side generated less data than
the other.

I'd suggest either this should fail, or return some magic error code
that means "truncated output" and we provide some way to resume where
it left off.  (Probably the former, though that may mean that
small-memory systems simply cannot satisfy some requests.)

In fact, it's probably worth explicitly stating that the mechanism
definitions must indicate what the only correct output length is, for
a given input.

   Additional major status codes for the C-bindings:

   o  GSS_S_CALL_INACCESSIBLE_READ

   o  GSS_S_CALL_INACCESSIBLE_WRITE

   See [RFC2744].

These status codes are very poorly described in RFC 2744, and are not
explicitly noted as status returns for any functions in RFC 2744, so I
don't think they need to be called out specially here.  And why would
they be "additional" major status codes?

I'm not sure when they could come up, anyways, unless you're checking
memory mappings for validity of the supplied pointers.  It looks like
the MIT code never returns them.

   For Java GSS_Pseudo_random() maps to a GSSContext method, 'prf':

I'm not familiar with Java interface definitions.  Is it considered
okay to simply add a new method to a standardized interface?

Add a comma after "Java".

   Callers of GSS_Pseudo_random() should avoid accidentally calling it
   with the same inputs.

"... for different purposes [or uses]."  There are certainly cases
where you'd want different calls to use the same inputs, and not by
accident.

   presence of short cycles, etc), you limit the amount of the PRF
   output used to the necessary minimum.

I think "minimum necessary" sounds better.  "Necessary minimum" sounds
to me like it is necessary that a minimum exists, whereas we want the
minimum amount of output that is necessary.  (I.e., "minimum" and
"necessary" modify "amount"; "necessary" doesn't modify "minimum".)

draft-ietf-kitten-krb5-gssapi-prf-04.txt:

Section 2, move [RFC3961] up to the first paragraph where the PRF
function is first mentioned.  Should the [RFC1964] reference be
updated to CFX?

   The computational cost of computing this PRF+ may vary depending on
   the Kerberos V encryption types being used, but generally the
   computation of this PRF+ gets more expensive as the input and output
   [...]

With some rewording ("a mechanism that uses a PRF+ construction...",
or just "for many PRF constructions..."), this would be appropriate
for draft-ietf-kitten-gssapi-prf instead.

Ken

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

---

From: Martin Rex <[email-masked]>
Date: Thu, 23 Jun 2005 23:12:03 +0200 (MET DST)

> the MIT code never returns them.

RFC-2743 originally mentioned that some gssapi mechanisms may be
part of a TCB, and there you would certainly expect pointers
to be tested against valid/mapped memory address ranges before
they're accessed/dereferenced in order not to cause an
exception within the TCB or scribbling over normally protected
memory, i.e. where gss_buffer_t is used as an input parameter
(affecting both, the base pointer and the value pointer),
or where gss_buffer_t is used as an output parameter (here
only the the base structure pointer is interesting, because
the value will be allocated by the gssapi mechanism).

The much more common gssapi mechanisms--as an application library
living entirely in the application's process space is unlikely
to test for more than !=NULL (if at all), I expect.

-Martin

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 23 Jun 2005 16:17:18 -0500

> not truncate the supplied input data."

I thought that "[m]echanisms MUST be able to consume all the provided
prf_in..." meant exactly that.

How could it mean otherwise?

> indistinguishable from "out of resources".  If the output is being

Ah.

> small-memory systems simply cannot satisfy some requests.)

We have GSS_S_UNAVAILABLE.  So return that and still output prf_out.

> definitions must indicate what the only correct output length is, for

How would they?

> they be "additional" major status codes?

RFC2743 doesn't define them -- they are an artifact of the C bindings,
needed to indicate calling errors where the caller passed in a NULL
pointer where a non-NULL pointer to a basic GSS type variable was
needed.

> the MIT code never returns them.

See above.  Solaris' libgss returns those errors as described above.

> okay to simply add a new method to a standardized interface?

Seema, can you look at this?

> where you'd want different calls to use the same inputs, and not by

Right, but since those wouldn't be accidents I think no change is
needed.

> "necessary" modify "amount"; "necessary" doesn't modify "minimum".)

Sure.

> function is first mentioned.  Should the [RFC1964] reference be

Er, yes, now that CFX is at Proposed Standard.

> for draft-ietf-kitten-gssapi-prf instead.

Well, I suppose.  If one mechanism may have a PRF that gets slower the
longer the inputs and required outputs then so may others, and that's
worth warning about, so:

   For some mechanisms the computational cost of computing
   GSS_Pseudo_random() may increase exponentially as the length of the
   prf_in data and/or the desired_output_length increase.  This means
   that if an application can be tricked into providing very large input
   octet strings and requesting very long output octet strings then that
   may constitute a denial of service attack on the application;
   therefore applications SHOULD place appropriate limits on the size of
   any input octet strings received from their peers without integrity
   protection.

Nico
--

---

From: Ken Raeburn <[email-masked]>
Date: Thu, 23 Jun 2005 21:41:57 -0400

> How could it mean otherwise?

Can a mechanism define "consume" as "discard/ignore everything after X 
bytes"?  I guess that's what I'm getting at.  I don't think it should 
be allowed to.

> We have GSS_S_UNAVAILABLE.  So return that and still output prf_out.

"The operation or option is unavailable", when it's a size problem 
(presumably, unable to allocate)?  Doesn't sound like a great match, 
but I'm not sure what else to suggest.

And it seems to me like this is only useful if the application protocol 
specifies up-front generation of more pseudorandom data than may be 
needed, "just in case", and the application will only succeed if the 
excess data is in fact not needed.

>> definitions must indicate what the only correct output length is, for

Well, indirectly, I guess, by way of specifying what the complete, 
deterministic output should be.  I.e., if the implementation's output 
is the wrong length, then it's wrong.

> pointer where a non-NULL pointer to a basic GSS type variable was

Right, but I don't think we need to call them out explicitly here; the 
generic codes that apply to the rest of the C bindings should be 
understood to apply here, just as the type definitions do.

> See above.  Solaris' libgss returns those errors as described above.

Makes sense.  As does Martin's point about TCB implementations.  Thanks.

> Right, but since those wouldn't be accidents I think no change is

Just trying to make it very clear... :-)

>    GSS_Pseudo_random() may increase exponentially as the length of the

Exponentially would surprise me, but I could certainly see 
O(inlen*outlen) behavior being common.  Maybe "significantly"... 
otherwise, it looks good.

One more thing I just noticed in looking at RFC 2744:  The minor_status 
output is defined as being mechanism-specific or 
implementation-specific, on a function by function basis.  So this 
draft should do likewise.

Ken

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 23 Jun 2005 22:08:56 -0500

> bytes"?  I guess that's what I'm getting at.  I don't think it should 

I see no other interpretation than it should use all the input octets to
compute the PRF.  That said, you're welcome to propose better language.

> excess data is in fact not needed.

Er, hmmm.  Perhaps it's best to say that the PRF has to output as much
as requested or fail altogether.  I see no harm in that.

> is the wrong length, then it's wrong.

BTW, there's not supposed to be a correlation between input and output
sizes -- both are in the application's control.

> understood to apply here, just as the type definitions do.

Ah, got it.  I'm just as happy leaving the C-bindings calling errors out
as in.

> Makes sense.  As does Martin's point about TCB implementations.  Thanks.

NP.

> Just trying to make it very clear... :-)

I somehow doubt folks are going to be getting this wrong.  The text
seems clear to me, but, again, I don't oppose clarification if the WG
thinks it's needed.

> otherwise, it looks good.

Ok, "significantly" then.

> draft should do likewise.

Well, RFC2743 does that, and it's a normative reference; you have to
read the base specs to figure out how to display major and minor status
codes anyways.  And the text in draft-ietf-kitten-gssapi-prf-04 kinda
mentions it already:

   o  GSS_S_FAILURE indicates general failure, possibly due to the given
      input data being too large or of zero length, or due to the
      desired_output_len being zero; the minor status code may provide
      additional information.

Nico
--

---

From: Ken Raeburn <[email-masked]>
Date: Thu, 23 Jun 2005 23:34:02 -0400

> compute the PRF.  That said, you're welcome to propose better language.

I'll think on it...

> sizes -- both are in the application's control.

Sure.  I guess I'm not expressing myself well today... :-(

>       desired_output_len being zero; the minor status code may provide

In the descriptions of individual functions in RFC 2744, minor_status 
described as one or the other -- either it's mechanism-specific for 
this function, or it's implementation-specific.  For GSS_Pseudo_random, 
which one is it?

That aspect of RFC 2744 bothers me, actually.  Seems to me that it 
implies that mechanism-specific and implementation-specific minor 
status codes would have to partition the number space or risk 
duplicating values.  Maybe it's just a bug in the RFC and it should've 
been mechanism-specific always?

Ken

---

From: Nicolas Williams <[email-masked]>
Date: Thu, 23 Jun 2005 22:44:21 -0500

> this function, or it's implementation-specific.  For GSS_Pseudo_random, 

Grrr.  RFC2744 says this about it in the description of
gss_create_empty_oid_set()

   minor_status      Integer, modify
                     Mechanism specific status code

Clearly a mistake -- there's NO MECHANISM INVOLVED in creating an empty
OID set, at least not in a multi-mechanism implementation.

The problem here is not RFC2744's fault, but 2743's.  There are GSS
functions that don't obviously involve a mechanism but which nonetheless
output a minor_status, and it's not at all clear how to display them,
because GSS_C_NULL_OID is allowed to mean the default mechanism!

Which is why I'd like to introduce an OID for the multi-mechglue itself
-- just so it can be used in calls to gss_display_status().

But, look, I refuse :) to have to deal with this problem in this I-D --
it's quite clear that GSS_Pseudo_random() involves a mechanism, so the
minor_status code must, implicitly, be a mechanism-specific code, and,
anyways, the app can currently do nothing more than call
gss_display_status() with the actual mechanism of the context in order
to display it.

> been mechanism-specific always?

See above.  It's a bug in the RFC.

Nico
--

---

From: Ken Raeburn <[email-masked]>
Date: Fri, 24 Jun 2005 00:06:57 -0400

> gss_display_status() with the actual mechanism of the context in order

Ah, but just as clearly, a call from C code to gss_pseudo_random() 
involves an implementation.  :-)

> See above.  It's a bug in the RFC.

Okay, I can believe that...

Ken

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 24 Jun 2005 10:49:24 -0500

> involves an implementation.  :-)

Yeah, in general, a pluggable multi-mech implementation will have to
reserve a chunk of the minor_status namespace in order to be able to
distinguish between implementation and mechanism minor status codes in
the cases of functions like this one that involve both.

> Okay, I can believe that...

Heh.

---

From: Martin Rex <[email-masked]>
Date: Sat, 25 Jun 2005 01:55:11 +0200 (MET DST)

>       desired_output_len being zero; the minor status code may provide

GSS_S_FAILURE is supposed to be the indicator that an error occured
for which no generic error code was defined.  That means a mechanism
(close to) "must" supply a minor_status code in order to give a clue
why the call failed.

The general rule is that this minor_status code needs to translate into
something that a human can comprehend (at least a human with clue),
because portable applications will not be able to programmatically
react to individual minor_status codes and instead will present the
output of gss_display_status(MECH_CODE,minor_status) either to a human
user or (in case of unattended servers) write it to a logfile and consider
the operation or transaction failed.

-Martin

---

From: Martin Rex <[email-masked]>
Date: Sat, 25 Jun 2005 02:15:35 +0200 (MET DST)

> been mechanism-specific always?
 
I agree that it is difficult to partition the number space, but
depending on the architecture it may be impossible to do otherwise.

The minor_status is usually implementation specific, but a mechanism
spec could decide to standardize on a small number of explicit
minor_status codes so that an application that recognizes this
particular mechanism could programmatically recognize and process
the mechanism-specific minor_status code.

All minor_status codes that are not explicitly menitioned/reserved
in the mechanism spec are therefore implementation specific -- which
also means that only the mechanism which produced it can translate
it into a textual message when called via gss_display_message().

Anyone who looked at my gsskrb5 wrapper for Microsoft's SSPI may
have noticed the partitioning of the minor_status number space
that I'm doing there.  In a layered software architecture you
may not want to enumerate every possible error code yourself
with an explanation, but instead try to pass on errors from
lower layers (hoping they fit into a specific number range
as they are or tailoring them for this purpose.

I partitioned the number space on Microsoft Windows so that I could
pass through
 - errno's from ANSI-C functions         which are very low numbers
 - Errors from Win32-API GetLastError()  which are faily low numbers
 - Errors from Winsock-API WSAGetLastError() small range, fairly low base
 - SSPI SecStatus values                 small range, quite high base
 - parsing errors from the generic wrapping layer
 - parsing errors from the mechanism specific wrapping layer

It seems to work fairly well.

Curiously, I have even extended the model quite recently (in a not yet
release version), so that it also Identifies the exact SSPI-call which
failed when an minor_status describing an SSPI-error is returned,
since some of the wrapper functions call several SSPI calls within
a single GSS-API call and it's otherwise too difficult to debug if the
SSPI unexpectedly returns "UNSUPPORTED_FUNCTION" on a new service pack
or a particular customer machine on a function with is working fine
with the same parameters on thousands of other/older machines and
configurations.  So far that happened twice to me ...

-Martin

---

From: Martin Rex <[email-masked]>
Date: Sat, 25 Jun 2005 02:27:35 +0200 (MET DST)

> -- just so it can be used in calls to gss_display_status().

If it wouldn't have been to late, we would have ripped the entire
set of gss_OID_set management function from the GSS-API v2 spec when
we found the serious problems with the gss_OID functions, on the
grounds that these functions are not mechanism specific and therefore
don't really belong into this API.  They're nice helper function for
some purposes, yes, but they're definitely not mechanism specific
and primarily bloat the spec.

A reasonable portable application will bring along its own functions
(not only because it needs them anyway if all it gets is a GSS-API v1
mechanism), but also because it can deal with its own implementation
much more efficiently and 100% predictable and clear regarding the
error handling.

> gss_display_status() with the actual mechanism of the context in order

You could define additional major status codes -- the only difficult
(but solvable) problem is how to assign/reserve numbers for the
different language bindings (and how to make sure new or rev'ed
language bindings and/or high-level spec adopt them on their
next round on the standards track.  :)

> See above.  It's a bug in the RFC.

I don't think it is a bug.

It rather is a tribute to reality that there's no silver bullet
solution and in some scenarios the number space may have to be partitioned
in order to make things work (particularly layering of software).

-Martin

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 24 Jun 2005 22:36:04 -0500

> (close to) "must" supply a minor_status code in order to give a clue

Sigh.  I don't think "MUST" is necessary.  RFCs 2743 and 2744 are
incredibly loose with respect to minor_status codes, and I don't want to
have to address that with each little extension.

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 24 Jun 2005 22:41:58 -0500

> and primarily bloat the spec.

If it makes you feel any better, GSS_Import_name() has exactly the same
problem with respect to minor_status as do the OID set utility
functions.

And so does GSS_Indicate_mechs(), and...

And GSS_Accept_sec_context could return a non-mechanism minor_status
code, e.g., if the OID wrapper on an initial context token is
missing/defective.  And GSS_Import_name() could too when importing a
defective exported name token.

But all this is off-topic.  While we're off-topic, I doubt I'll agree to
removing the OID set utility functions :)

> in order to make things work (particularly layering of software).

The API could have been designed with better error reporting facilities
-- e.g., with an opaque error output object instead of an integer type.

But this is off-off-topic.

Nico
--