Subject: [kitten] GSS & krb5 mutual auth flags aren't -- they are about key confirmation

From: Nico Williams <[email-masked]>
Date: Mon, 6 May 2019 01:34:09 -0500

See subject.

I assert that:

 - GSS_C_MUTUAL_FLAG is badly misnamed

 - GSS_C_MUTUAL_FLAGis not, never was, and never could have been about
   mutual authentication in the sense of authenticating two peers to
   each other,

 - and GSS_C_MUTUAL_FLAGis, always was, and only could have been about
   key confirmation.

It is understandable that "mutual authentication" had a somewhat
confusing definition back when RFCs 1508, 1509, and 1510 were written
(huh, notice the sequential RFC numbers...).  But it's time to nail it
down.

First off, a high-level observation: GSS (and Kerberos) always deals in
*two* principal names, so GSS and Kerberos are *always* about mutual
authentication.

Even if the initiator's name is some sort of anonymous name
authentication can still be said to be mutual.  Consider that an
anonymous name's credential might still convey some authorization
information.  E.g., some of a user's group memberships, just not the
user's name.  I.e., not all anonymous identities need be the same.
Indeed, for PK-based mechanisms we could use an initiator's bare public
key as its name even if they are "anonymous", which makes it more
"pseudonymous" than "anonymous" authentication, and still mutual.  (More
on this below.)

Even if both names are anonymous... the same argument about pseudonymity
holds.

The API by its very own nature implies mutual authentication even when
one or the other (or both) name can be anonymous or pseudonymous.

Second, we can look at all the mechanisms we know well enough, and all
the mechanisms we can posit, and see that the above assertions hold:

 - Mechanisms that can have just one, or just two context tokens:

    - Kerberos

      Mutual really only means key confirmation.

      Mutual authentication is obtained naturally in that the acceptor
      cannot GSS_Unwrap() (or GSS_VerifyMIC()) without having the
      requested target acceptor's credentials.

    - Solaris' mech_dh (the GSS form of the old AUTH_DH)

      Same as Kerberos (even though it's based on DH).

      Any variant that works the same way (specifically: having a
      directory of all initiator and acceptor names and public keys) but
      uses other crypto could have the same semantics.  E.g., a
      mechanism where the initiator uses RSA key transport using an
      acceptor's long-term public key, and signs the encrypted session
      key with the initiator's long-term private key.

    - a GSS version of SASL PLAIN

      There cannot be any real mutual authentication in either sense of
      the term.

 - Mechanisms that need more than 2 context tokens:

   For these mechanisms there's not much value in omitting key
   confirmation, and it isn't wise anyways, so I would argue that they
   must all always have key confirmation.

    - SCRAM
    
      Always mutual in that one password authenticates a pair of peers.
    
      Always mutual in that key confirmation cannot be elided (per the
      RFC).
    
      One could construct a SCRAM-like mechanism where the last message
      from the acceptor can be omitted if GSS_C_MUTUAL_FLAG is not
      requested, but one probably shouldn't.
    
    - Some GSS-PAKE
    
      Pretty much the same analysis as SCRAM.
    
    - NTLM
    
      Pretty much the same analysis as SCRAM.
    
    - Some PKIX-based mechanism (SPKM, GSS-TLS, PKU2U) w/o directories
      (i.e., not like mech_dh)
    
      Some such mechanisms truly could support non-mutual authentication
      in that one peer needs no credentials, not even anonymous
      credentials.  E.g., an RSA key transport mechanism needs nothing
      like an initiator credential.  Even if EDH is used, unless one
      thinks of the initiator's private EDH key as a credential, there's
      no need to authenticate an anonymous initiator name to the
      acceptor.
    
      Again, key confirmation is not wise to omit.

Did I miss any mechanisms?  Yes: OAuth/SAML mechanisms.  Any OAuth/SAML
mechanism constructions that end up needing no more than 2 context
tokens will look a lot like Kerberos, and could have optional key
confirmation.  Any OAuth/SAML mechanism constructions that end up
needing more than 2 context tokens because they do DH or similar key
agreement should not omit key confirmation.

Thirdly and lastly, I propose the following:

 - That we rename the GSS and Kerberos "mutual auth" flags to denote key
   confirmation rather than mutual authentication.

   We should explain the motivation for making key confirmation
   optional.  This is ex-post, but still, the motivation is clearly
   protocol optimization.

   Note that GSS has a second mechanism for protocol optimization:
   PROT_READY.  This one is akin to various TLS early application data
   schemes.

 - Recommend that any mechanism that needs more than one full round trip
   for security context establishment SHOULD NOT ever omit key
   confirmation.

 - That we clarify that authentication is always mutual except in the
   case that one or the other of the initiator or acceptor names is an
   anonymous name with no link to any authenticate user, and that no
   flag can alter this.

We might also want to clarify / re-think PROT_READY.

We should start a separate thread to cover a case that came up recently:
the desire for a way to name a target principal but not authenticate it
in the sense of not require having trust anchors for authenticating it.

Applications that want to use an anonymous name, should use... a
GSS_C_NT_ANONYMOUS name, or use GSS_C_ANON_FLAG to request that the
initiator be anonymous (more about this flag in some other thread).

If a mechanism always cannot authenticate the initiator, then it is a
mechanism that doesn't provide mutual authentication (and notice that
key confirmation has nothing to do with it, and that no flag could make
the mechanism provide mutual authentication).

A mechanisms that always cannot authenticate an acceptor is probably not
a very useful mechanis, so I won't think of such a thing.

Comments?

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Mon, 6 May 2019 01:54:40 -0500

On Mon, May 06, 2019 at 01:34:09AM -0500, Nico Williams wrote:
> [...]

Also: IAKERB.  Omitting key confirmation for IAKERB is a lot like
omitting it for Kerberos, even though IAKERB necessarily needs more than
one round trip.

Also, any multi-round trip mechanism that can use something like TLS
session resumption tickets to shorten subsequence security context
establishments can be like Kerberos and support omission of key
confirmation.

I tend to think that PROT_READY is a much more fruitful way to optimize
GSS mechanisms security context establishment.  It also forces one to
think long and hard about the security semantics and properties of
"early data".

The only protocols I can imagine where a single context establishment
token is desirable and useful are stateless blind logging protocols.  I
know of no such protocols.  But even if there were any, the overhead of
sending {init_context_token, wrap_token} messages all the time would
surely drive the protocol designer to opt for a more stateful design so
that most messages can be just {context_ID, wrap_token}.

Nico
--

---

From: [email-masked] (Martin Rex)
Date: Wed, 8 May 2019 04:53:51 +0200 (CEST)

>  - GSS_C_MUTUAL_FLAG is badly misnamed

Not really.

Original GSS-API implied initator towards acceptor authentication,
and GSS_C_MUTUAL_FLAG was used to request acceptor towards initiator
authentication.

The better terminology would have been to indicate the actually desired
(additional) function, rather than describing the addition of what is
requested, and what has been silently implied/assumed.

The difference became obvious when the "Anoymous" authentication was
added in GSS-APIv2, i.e. no authentication of initiator towards acceptor.

Web Browsers using TLS usually do what at the GSS-API would be the
combination of (GSS_C_ANON_FLAG|GSS_C_MUTUAL_FLAG), i.e.
unidirectional authentication, acceptor towards initiator.

>    mutual authentication in the sense of authenticating two peers to

Until GSS_C_ANON_FLAG was invented, MUTUAL was an implied requirement.

>  - and GSS_C_MUTUAL_FLAGis, always was, and only could have been about

GSS-API is about authentication of name-based entities.
There is no concept of keys in GSS-API.

> *two* principal names, so GSS and Kerberos are *always* about mutual

Nope.  Kerberos has always been about unidirectional authentication,
and most of the time, MUTUAL is still unidirectional.

Performing server name canonicalization through insecure DNS
has been insecure and a well-known bad idea in 1996.

You may want to check what Microsoft does 23 years later when encountering
DNS CNAME records for rfc4559 SPNEGO authentication...

(spoiler: insecure server name canonicalization through DNS)

Essentially, Kerberos 5 never provided mutual authentication in the
past, and you probably should not hold your breath until it happens.

>       Pretty much the same analysis as SCRAM.

Definite *NO* for NTLM.  NTLM is unidirectional initiator to target,
and susceptible to man-in-the-middle.  This was obvious in 1995,
and causes some amount of headaches earlier this year.

  https://www.theregister.co.uk/2019/01/25/microsoft_exchange_domain_admin_eop/

>     - Some PKIX-based mechanism (SPKM, GSS-TLS, PKU2U) w/o directories

I know PKIX-based mechanisms that perform mutual properly.
But for convenience, some of them contain various tweaks/cheats to
perform just uni-directional authentication.

>       Again, key confirmation is not wise to omit.

Security guarantees of GSS-API apply only to application data that
has been protected by the GSS-API message protection primitives.

If someome abuses the GSS-API context token exchange for an OTP-scheme,
and then transfers application data without GSS-API message protection,
that's spoiling between most and all of the security
(again, rfc4559 HTTP Negotiate comes to mind).

> in the sense of not require having trust anchors for authenticating it.

which is almost what Kerberos has been doing for the past 30 years thanks
to canonicalizing service names through insecure DNS...

> initiator be anonymous (more about this flag in some other thread).

The "Applications that want to use an anonymous name," above
sort of implies that the entire information conveyed must be
public and free.

Or were you also considering "pseudonymous", which GSS-API currently
does not address, such as a "one from a certain group", such as an
"unnamed paying customer".

> a very useful mechanis, so I won't think of such a thing.

these things are called "Web Browsers".  I'm not sure the folks from
CABforum share your view.

Have you noticed how poorly some browsers work with TLS client certificates?
Almost indistinguishable from malice.  Like "Enrollment"?

Ever tried to make your Google Chrome automatically select a TLS client
cert for accessing a Web Server that wants TLS client certs?
Maybe not exactly "Beware of the leopard"-style, but sufficiently close.
(stuff from Apple Inc. and TLS client certs?  even worse).

-Martin

---

From: Nico Williams <[email-masked]>
Date: Wed, 8 May 2019 15:18:56 -0500

> and GSS_C_MUTUAL_FLAG was used to request acceptor towards initiator

I believe that conflates "mutual" with key confirmation.

Assuming the cryptosystems are secure, an exchange of this form:

I->A: init sec context token w/o "mutual" (AP-REQ)
I->A: wrap token w/ confidentiality

keeps the plaintext confidential even if the recipient is not the
intended acceptor.

Kerberos ensures that only the intended acceptor can unwrap that token.

Moreover, in an exchange like this

I->A: init sec context token w/o "mutual" (AP-REQ)
A->I: sec context token (AP-REP)
I->A: wrap token w/ confidentiality

there is no assurance that there is not a party on-path that can observe
the ciphertext of these tokens.

Thus the only thing GSS_C_MUTUAL_FLAG can do in the case of Kerberos is
provide key confirmation and, in RFC4121, a new sub-session key.

In both cases there are *two* principal names, and they are
cryptographically bound by the init sec context token alone.

Moreover, the GSS-API always has two principal names involved in every
security context.  I suppose you could argue it's "up to two names", but
I wouldn't agree.  First, the initiator's credential (default or not)
supplies one name (the initiator's) to GSS_Init_sec_context().  Second,
GSS_Init_sec_context() requires a target_name (the acceptor's).  Even if
the initiator wishes to be anonymous, it still has a NAME as indicated
by GSS_Inquire_context() -- that name will be of GSS_C_NT_ANONYMOUS
type, indeed, but it will be a NAME.

> requested, and what has been silently implied/assumed.

If I understand this, you might actually be agreeing with me.  But I
probably didn't understand it.  What alternative terminology would you
propose?

> added in GSS-APIv2, i.e. no authentication of initiator towards acceptor.

Has this been implemented by any mechanisms?

(Kerberos is the only Internet mechanism that has this specified, but
it's not yet been implemented, much less as specified.)

A better design would have been to have the initiator application supply
GSS_Inquire_context() with an input_cred_handle for a GSS_C_NT_ANONYMOUS
desired_name.  No flag should have been needed or specified.

> unidirectional authentication, acceptor towards initiator.

This would seem like a contradiction in terms.  Unless you take
GSS_C_MUTUAL_FLAG to be about key confirmation, which is not optional in
TLS, and so we're down to just GSS_C_ANON_FLAG (about which see above).

> There is no concept of keys in GSS-API.

Key confirmation is a term of art referring to an aspect of the chosen
mechanism's context token protocol.  "Key confirmation" is certainly not
about exposing keys to applications.

But certainly, too, the existence of cryptographic keys is strongly
implied by the GSS-API, at least assuming classical cryptography (and we
can't assume quantum cryptography because while there are quantum key
exchange systems, there are no quantum authentication systems).

> and most of the time, MUTUAL is still unidirectional.

I strongly disagree as explained above.

> has been insecure and a well-known bad idea in 1996.

I'd rather not distract this thread with that issue.

Nico
--

---

From: [email-masked] (Martin Rex)
Date: Thu, 9 May 2019 05:40:42 +0200 (CEST)

> I believe that conflates "mutual" with key confirmation.

Again, there is *NO* concept of keys in GSS-API, and adding this
is a bad idea.  You can do that within a particular gssapi mechanism,
if you want to, but that is an implementation detail of a mechanism.

> Kerberos ensures that only the intended acceptor can unwrap that token.

plus the trusted third party (the Kerberos KDC)

I'm just wondering about the MitM-unsafe GSS-API mechanism like
Microsoft NTLM, because there is no "target name" parameter,
and no binding to any target.  Every MitM attacker with access
to a domain member PC should be able to unwrap the tokens.
So the "Seal" security level for RPC when negotiate drops to NTLM
is potentially not quite what one expects.

> provide key confirmation and, in RFC4121, a new sub-session key.

Frankly, I don't know and I don't care what you mean by key confirmation.
At the GSS-API level the term "key confirmation" has *NO* meaning.
What is done within a gss-api mechanism, is irrelevant here.

> cryptographically bound by the init sec context token alone.

"by the init sec context token alone" -- sorry that is non-sensical.

There can be any number of context-level tokens, and which context level
token is bound to which particular name, is entirely mechanism specific.

In particular, if the initiator happens to connect with a different
entity that what it wanted to talk to, the token will be bound to
some other name.

Technically, GSS-API mechanisms may use a completely different approach,
and start trying to perform mutual authentication of unspecified names,
and when authentication succeeds, perform discovery of the names
involved in the authentication, and match the result up with expectations.

Even Kerberos knows such a scheme. It is called user2user authentication.
It's not described in rfc1964/rfc4121, but Microsoft implemented it.

> Has this been implemented by any mechanisms?

I'm pretty sure it has been implemented.  I've seen a (proprietary) GSS-API
mechanism wrapping TLS records in to GSS-API tokens about 18 years ago.  

We also have one (but its cheating on the flags at the API because
that was easier for drop-in into installed base).  The application
on top recognizes when this happens, and drops back to traditional
user&password authentication for initiator towards acceptor authentication.

> desired_name.  No flag should have been needed or specified.

This statement has at least two typos/confusions.

> TLS, and so we're down to just GSS_C_ANON_FLAG (about which see above).

Nope.  It says "mutual authentication minus initiator towards acceptor
authentication".

That like asking for a "virgin Cuba libre"  (a Coke).

> exchange systems, there are no quantum authentication systems).

No, GSS-API does *NOT* have this implication _at_all_.
Making this implication at the GSS-API level, rather than at the
level of a specific mechanism, is a terribly bad idea. You're using
a whole dimension of what GSS-API can be.

conceptually, there do not need to be any crypto inside the context
level tokens at all (could all be out-of-band, potentially limiting
the environment where such a gssapi mechanism can be used).

However, I currently don't see how to provide the message protection
services (integrity protection and confidentiality protection) without 
crypto in the per-message tokens.

-Martin

---

From: Robbie Harwood <[email-masked]>
Date: Wed, 15 May 2019 14:57:11 -0400

Nico Williams <[email-masked]> writes:

> First off, a high-level observation: GSS (and Kerberos) always deals
> in *two* principal names, so GSS and Kerberos are *always* about
> mutual authentication.
>

This is true assuming it *does* call those functions.
Authentication-only use is not only possible but (unfortunately, in my
view) quite common: HTTP Negotiate, or GSSAPI auth in ssh, etc..  In
those cases, without mutual authentication, any authentication of (for
example) the HTTP server to the client must happen at another point
(from the TLS channel in HTTPS).

Of course, operating with mutual authentication along an untrusted
channel won't buy you much since it's not tamper-proof.  However, it
does help against passive observers when opportuniustic (untrusted)
encryption is used (as well as TOFU schemes).  I realize this is a bit
in the weeds and possibly not practically relevant, but this is a
conversation about definitions, so...

Thanks,
--Robbie