Subject: [kitten] AD review of draft-ietf-kitten-krb-spake-preauth-06

From: Benjamin Kaduk <[email-masked]>
Date: Thu, 4 Apr 2019 18:58:59 -0500

In general this document is in good shape, but the elephant in the room
is the state of the dependency draft-irtf-cfrg-spake2, which is
apparently not as stable as we thought.  It seems likely that we'll need
to wait until that document is further along before we can finalize our
revisions to this document and go to IETF LC; furthermore, I expect
we'll want to reissue some codepoints so that the current meanings stay
valid (tied to draft-irtf-cfrg-06's behavior) and the new codepoints
match the RFC version of the CFRG spec.  (Except when we consciously
diverge, as for the transcript hash, etc.)

In particular I think we will need to allocate a new PA-SPAKE value.
(I don't think I see a reason to allocate a new KEY_USAGE_SPAKE value.)

Some section-by-section comments follow.

-Ben

Section 1.1

   Password authenticated key exchange (PAKE) algorithms provide several
   properties which are useful to overcome this problem and make them
   ideal for use as a Kerberos pre-authentication mechanism.

We should probably expand out "this problem": offline dictionary
attacks.

Section 1.2

   2.  It can compute the shared key after just one message from each
       party.

I guess we could say a little more about why this is useful (reduced
state on KDC, reduce number of round-trips, etc.)

Section 1.3

We may want to give the reader a bit more help in here:

   Using PAKE in a pre-authentication mechanism also has another benefit
   when used as a component of two-factor authentication (2FA).  2FA
   methods often require the secure transfer of plaintext material to
   the KDC for verification.  This includes one-time passwords,
   challenge/response signatures and biometric data.  Attempting to
   encrypt this data using the long-term secret results in packets that
   are vulnerable to offline brute-force attack if either authenticated
   encryption is used or if the plaintext is distinguishable from random

(because it gives the attacker an authentication tag for offline attack)

   data.  This is a problem that PAKE solves for first factor

(because brute-force attack on the ciphertext yields a success result
when the underlying structure is correct)

We probably want to be more specific about what "this" is that is a
problem.

   authentication.  So a similar technique can be used with PAKE to
   encrypt second-factor data.

I'm not sure if "similar technique can be used with PAKE" is the right
phrasing.  It's similar in that we add onto the PAKE, but it's only sort
of used *with* in that sense.

                  These requirements lead to a scenario where FAST
   cannot be enabled by default without sufficient configuration.  [...]

We leave it pretty vague about what "sufficient configuration" is.
Isn't the point that coordination with the realm administrator or some
similar authority is needed in order to use FAST by default on a given
system?

Section 1.4

   Higher level protocols must define their own verification step.  In

This is a requirement from the SPAKE spec, not one we introduce here.
So we probably want to say something like "SPAKE requires that higher
level protocols [...]".

   the case of this mechanism, verification happens implicitly by a
   successful decryption of the 2FA data.

I'd consider adding a note here that "a placeholder second-factor is
allocated to provide key confirmation when no actual second factor is
available", though I'm not 100% sure it's needed.

Section 2

RFC 8174 has an updated version of the BCP 14 boilerplate text to use
(and every subsequent reviewer that looks at this document will tell you
about it if you don't fix it beforehand).

Section 3.1

   This mechanism requires the initial KDC pre-authentication state to
   contain a singular reply key.  Therefore, a KDC which offers SPAKE
   pre-authentication as a stand-alone mechanism MUST supply a PA-ETYPE-
   INFO2 value containing a single ETYPE-INFO2-ENTRY, as described in
   [RFC6113] section 2.1.  [...]

RFC 6113 section 2.1 doesn't specifically talk about ETYPE-INFO2-ENTRYs
at all, and is instead using a little more abstract language.  So
perhaps we want something like "following the guidance in" to keep our
language precise.

Section 4.2

   The pubkey field indicates the KDC's public key generated using the M
   constant in the SPAKE algorithm, with inputs and conversions as
   specified in Section 5.

I think I want something more concretely tying this to the OCTET STRING
representation of the ASN.1 element, perhaps "conversions to and from
OCTET STRING form".

   The data field contains optional challenge data.  The contents in
   this field will depend upon the second factor type chosen.

I'd suggest a forward reference to the security considerations here,
noting that when these are being processed they are unauthenticated
plaintext.

Section 4.3

Do we need to say that the 'kvno' field of the EncryptedData is absent
(here and elsewhere)?

   The client and KDC will update the transcript hash with the pubkey
   value, and use the resulting hash for all encryption key derivations.

Isn't it the whole message and not just the pubkey value?

Section 4.6

                                                            If the KDC
   cannot continue with SPAKE (either because initial reply key type is
   incompatible with SPAKE or because it does not support any of the
   client's groups) but can offer other pre-authentication mechanisms,
   it MUST respond with a KDC_ERR_PREAUTH_FAILED error containing
   METHOD-DATA.  [...]

(appropriate for the mechanisms in question?)

Section 5

   1.  Determine the length of the multiplier octet string as defined in
       the IANA "Kerberos SPAKE Groups" registry created by this
       document.

If this multiplier length ended up being smaller than the key width for
the initial reply key, it seems like we'd end up losing security
strength.  Should we mention this in the considerations for new
registrations in the IANA section?

   2.  Compose a pepper string by concatenating the string "SPAKEsecret"
       and the group number as a big-endian four-byte two's complement
       binary number.

In a very general sense, we get better prefix isolation if we include
the trailing NUL as a separator, but that's a gratuitously breaking
change that we shouldn't make in the absence of other breaking changes.
(Which, well, we are kind of looking at anyway...)

Section 6

           It therefore incorporates the client's supported groups, the
   KDC's chosen group, the KDC's initial second-factor messages, and the
   client and KDC public values.  Once the transcript hash is finalized,
   it is used without change for all key derivations (Section 7).

I might go so far as to explicitly say "In particular, subsequent
encrypted second-factor exchanges are not included in the transcript
used for key derivation.", though it may be overkill.

Section 7

   First, the hash function associated with the selected group is
   computed over the concatenation of the following values:

Do we want to include the client/server principal names here as well, as
suggested by draft-irtf-cfrg-spake2-08?

   o  The fixed string "SPAKEkey".

(Same as above about NUL separator.)

   o  The SPAKE result K, converted to an octet string as specified in
      Section 5.

I failed to convince myself that I saw where this conversion was
specified in Section 5.  Could you help me out?

Section 9

   A KDC MUST NOT include a PA-SPAKE-HINT message in a pa-value field;

Do we want to say "directly in"?

Section 10

   All of the security considerations from SPAKE [I-D.irtf-cfrg-spake2]
   apply here as well.

Editorially speaking, it might be nice to the reader to say "Additional
considerations specific to this document are discussed in the following
subsections".

One potential additional consideration to note is that the encdata
choice does not indicate which party is sending it so we have to
consider the risk of reflection attacks wherein a message is replayed to
a party that should have sent it instead of receiving it.  I think we're
safe since each party will only attempt to use even or odd numbers in
the K'[x] hierarchy for decryption and thus avoid using the wrong
plaintext, but it's probably worth a mention.

Section 10.1

                        The KDC-REQ-BODY contents are also incorporated
   into key derivation, ensuring their integrity.  The unauthenticated
   plaintext in the KDC-REP message is not protected by this mechanism.

Do we want to have a short note about how this is not expected to cause
problems (as it's the default state for all KDC exchanges)?

   Subsequent factor data, including the data in the response, are
   encrypted in a derivative of the shared secret K.  Therefore, it is
   not possible to exploit the untrustworthiness of the challenge to
   turn the client into an encryption or signing oracle, unless the
   attacker knows the client's long-term key.

I'd consider adding a note "in which case the attacker does not need an
external oracle to encrypt or sign using that key".

Section 10.2

I guess it's a tossup whether this topic is better in 10.1 or 10.2, but
we do send lists of factors in the clear, which can leak whether SF_NONE
is potentially in use (i.e., if the client has a second factor at all).

   [...]
   Others may silently accept such a multiplier, but proceed to perform
   multiplication that is not constant time.  This is a minor risk in
   all known groups, but is a major risk for P-521 due to the extra
   seven high bits in the input octet string.  A common solution to this

I'm having a hard time parsing this middle sentence; the best I can come
up with is that "this is only a minor risk in most known groups".

Section 10.3

We discuss replay of cookie values by attackers, but don't really talk
about the related possibility of splicing cookie values across SPAKE
exchanges.  E.g., if an attacker observes two simultaneous requests and
swaps the cookies between the two before forwarding to the KDC.

Section 10.4

   Although this pre-authentication mechanism is designed to prevent an
   offline dictionary attack by an active attacker posing as the KDC,
   such an attacker can attempt to downgrade the client to encrypted
   timestamp.  [...]

Maybe "or similar preauthentication mechanisms"?

   Client implementations SHOULD assume that encrypted timestamp and
   encrypted challenge are unlikely to succeed if SPAKE pre-
   authentication fails in the second pass and no second factor was
   used.

Maybe s/no second factor/SF_NONE/?

   Like any other pre-authentication mechanism using the client long-
   term key, this pre-authentication mechanism does not prevent online
   password guessing attacks.  The KDC is made aware of unsuccessful
   guesses, and can apply facilities such as password lockout to
   mitigate the risk of online attacks.

I'd suggest "rate limiting" as a suggestion over "password lockout",
which has some downsides in comparison to rate-limiting.

Section 10.6

Is there much that a KDC can do in the face of such an attack?  Will
forcing fallback to the full SPAKE exchange help at all (e.g., with
proof of return routability)?  We can't really suggest reusing ephemeral
key shares to reduce that part of the load.

Section 12

In addition to potentially allocating a new value for the RFC version of
this spec, we probably also want to say a bit more about the
registration procedures.  Should requestors send the request directly to
the list, or to IANA first and IANA sends to the list?  Is the list
publicly archived (and can anyone sign up as a member)?

Section 12.1.2

I think we spell this "SF_NONE" in the body, not "NONE".

Section 12.2

   This section specifies the IANA "Kerberos SPAKE Groups" registry.
   This registry records the number, name, specification, serialization,
   multiplier length, multiplier conversion, SPAKE M constant and SPAKE
   N constant.

We also include a hash.

Section 12.2.1

   Serialization:  Reference to the definition of the method used to
      serialize group elements.

Do we think it's implicit that this is also used for deserializing group
elements?

Section 12.2.2

   o Serialization: [SEC1] section 2.3.3 (compressed).

I'd use a couple more words, e.g., "this specification uses the
'compressed' point format". (multiple occurrences)

I did verify that these listed M and N values match
draft-irtf-cfrg-spake2-08.

Section 13.2

Normally we call these "Informative References".

Appendix B

(the CFRG doc has the M and N values for edwards25519 so we can drop
that bit when we update the reference)

Appendix C

(The test vectors would need to be updated if we make breaking changes
to the protocol, e.g., adopting the prime subgroup changes in
draft-irtf-cfrg-spake2-08.  But it's fine to just leave this section as
an empty placeholder until things settle down, unless lots of people are
planning to implement the intermediate states.)

We use lowercase 'w' for both the PRF+ output and the reduced
multiplier; could we maybe use the majuscule form for one to
disambiguate?

RC4 was deprecated by RFC 8429; do we still need test vectors for it?
Similarly, just "AES128" and "AES256" are not super-unambiguous for
enctype specifiers, given the enctypes in RFC 8009.  (The price we pay
for being slow to publish...)

We don't have any test vectors with non-empty 'data' elements in
SPAKESecondFactor, but that's probably okay (whichever doc adds a factor
that uses it can have test vectors thereof).

---

From: Greg Hudson <[email-masked]>
Date: Thu, 4 Apr 2019 20:58:14 -0400

> (I don't think I see a reason to allocate a new KEY_USAGE_SPAKE value.)

I guess we didn't have the same takeaways regarding the recent revisions
to draft-irtf-cfrg-spake2.  I argued that the changes to cofactor
handling in SPAKE2 were unnecessary, inconsistent with how X25519 was
specified, and should be reverted (though w1 in SPAKE2+ should become a
scaled cofactor instead of an unscaled one).

There are also changes to the requirements for key derivation which I
believe we cannot reasonably meet within the Kerberos protocol; while
these changes can be reasonably justified, I believe they make
draft-irtf-cfrg-spake2 unsuitable as a normative reference for
draft-ietf-kitten-krb-spake-preauth in my opinion.  Instead, we should
describe the SPAKE2 algorithm within the Kerberos draft as it is used
there, using the Abdalla/Pointcheval paper as an informative reference.

I do not at this time understand why we would want or need to allocate
new code points.

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 5 Apr 2019 21:26:23 -0500

> scaled cofactor instead of an unscaled one).

Well, I see draft-irtf-cfrg-spake2 as being somewhat in flux still, in
response to Kenny's review, and I'm reluctant to blindly charge ahead with
this document until some clearer consensus arises there.  I do owe everyone
some responses to the thread for that document, still...

With respect to this document, the main change in draft-irtf-cfrg-spake2
that seems like a "breaking change" would be the cofactor handling, e.g.,
whether we pick a value that's divisible by h and send that vs. sending the
number from [0,p) and having the peer do the multiplication.  IIRC the
latter is "safer" in that it requires each party to perform the needed
check as a matter of course in running the protocol, rather than having an
additional "check step" that might be seen as optional and omitted.

> there, using the Abdalla/Pointcheval paper as an informative reference.

I agree that we don't want (and in fact can't use) the key derivation and
transcript hash from draft-irtf-cfrg-spake2-08, and don't see an issue with
referencing the document just for the core algebraic operations.

I had intended draft-irtf-cfrg-spake2 to have some text along the lines of
"in the absence of a more suitable application-defined transcript and
key-derivation mechanism, the following are defined for generic use", but
in the rush of getting submitted before the draft deadline that didn't
really come through.

-Ben

---

From: Greg Hudson <[email-masked]>
Date: Sat, 6 Apr 2019 01:12:30 -0400

> additional "check step" that might be seen as optional and omitted.

The public value is a point, not a coefficient.  The last step in each
party's computation is to multiply by the private multiplier, e.g.
K=x(S-wN).  If x is divisible by h, then we are implicitly multiplying
by the cofactor, so values of S which are of order 2p, 4p, ..., hp will
be brought into the prime-order subgroup, just as if we multiplied by h
explicitly.  No check step is required.

RFC 7748 uses this same approach to specify X25519.  In section 5, each
party's private scalar is "of the form 2^254 plus eight times a value
between 0 and 2^251 - 1 (inclusive)."  Each party computes the shared
value as its (scaled) coefficient times the counterparty's point,
without explicitly multiplying by h.  (Well, just one coordinate of the
resultant point, since it's using a Montgomery ladder.)

Eike's writeup (the last message in the CFRG thread) is a decent
explanation:

https://mailarchive.ietf.org/arch/msg/cfrg/b1hIQguoaqLw2ioLsBHll06AglI

In this writeup, x is unscaled and x'=h*x is scaled, but x is never used
directly so that's just a minor matter of terminology.