Subject: [regext] Benjamin Kaduk's Discuss on draft-ietf-regext-secure-authinfo-transfer-06: (with DISCUSS and COMMENT)

From: Benjamin Kaduk via Datatracker <[email-masked]>
Date: Wed, 21 Apr 2021 11:23:51 -0700

Benjamin Kaduk has entered the following ballot position for
draft-ietf-regext-secure-authinfo-transfer-06: Discuss

When responding, please keep the subject line intact and reply to all
email addresses included in the To and CC lines. (Feel free to cut this
introductory paragraph, however.)

Please refer to https://www.ietf.org/iesg/statement/discuss-criteria.html
for more information about DISCUSS and COMMENT positions.

The document, along with other ballot positions, can be found here:
https://datatracker.ietf.org/doc/draft-ietf-regext-secure-authinfo-transfer/

----------------------------------------------------------------------
DISCUSS:
----------------------------------------------------------------------

(1) RFC 4086 does not state that "a high-security password must have at
least 49 bits of randomness or entropy" as is claimed in Section 4.1 of
this document.  It merely says that so much entropy is needed to have a
one-in-a-billion chance of success for successfully guessing in the
model laid out, and makes no statement about (absolute) "high" security.
I don't think we need to spend as much time on what RFC 4086 says as we
currently do, and could probably get to the "use at least 128 bits of
entropy" advice much sooner.

(2) There's also some text in Section 5.3 that I'd like to discuss briefly:

   The registry MUST NOT return any indication of whether the
   authorization information is set or unset to the non-sponsoring
   registrar by not returning the authorization information element in
   the response.  The registry MAY return an indication to the
   sponsoring registrar that the authorization information is set by
   using an empty authorization information value.  The registry MAY
   return an indication to the sponsoring registrar that the
   authorization information is unset by not returning the authorization
   information element.

This seems to be assigning semantics to both absent-authinfo and
empty-authinfo in the <info> response, but is giving *different* semantics
to the response-to-sponsoring-registrar and
response-to-non-sponsoring-registrar cases.  Is there precedent for
changing the semantics of the response based on the identity of the
client like this (not just changing the content of the response)?  Can
we come up with a scheme that provides consistent semantics to all
clients, perhaps based on <domain:null> vs empty <domain:pw> for
unset/set, leaving "element is absent" for the deliberately ambiguous
case?

(3) We may also need to discuss the efficacy of the transition plan, per
my comments in Sections 6.1 and 6.3 -- my current understanding is that
the proposed plan will break some existing workflows.  I am not sure if
that is intended, desirable, and/or tolerable, and welcome further
insight.

----------------------------------------------------------------------
COMMENT:
----------------------------------------------------------------------

I think that the introduction would benefit from expanding on the
high-level motivation for this work (which I assume to include): the
current/original lifecycle for authorization information involves
long-term storage of encrypted (not hashed) passwords, which presents a
significant latent risk of password compromise and is not consistent
with current best practices.  The mechanisms in this document provide a
way to avoid long-term password storage entirely, and to only require
the storage of hashed (not retrievable) passwords instead of encrypted
passwords.  (Or, in a more colloquial language, "passwords suck, and we
want to get out of the business of handling them to the extent
possible".)  The third paragraph does talk about the "overall goal", but
doesn't say much about what we're moving *away* from (and why).

I think giving some explicit consideration of the lifecycle and protocol
interactions for the password 'salt' would be helpful.  (That is, that
it's picked at random by the registry per password when a password is
set and never goes on the wire, but is stored alongside the hashed
password.)

The treatment in the introduction of "[use] the existing features of the
EPP RFCs" made me wonder why this needed to be on the standards-track,
as opposed to being an informational description of how to use what's
already there.  The actual core of the spec, which includes changes to
the semantics of some XML elements (e.g., in the info response), is
clearly protocol work, though, so perhaps the abstract/introduction
could be revisited to clarify the scope of the work.

Section 1

   "Strong Random Authorization Information":  The EPP RFCs define the
       password-based authorization information value using an XML
       schema "normalizedString" type, so they don't restrict what can
       be used in any way.  This operational practice defines the

I suggest s/in any way/in any substantial way/ (not being able to use
CR/LF/TAB is in some sense a restriction).

   "Short-Lived Authorization Information":  The EPP RFCs don't
       [...]
       upon a successful transfer.  All of these features can be
       supported by the EPP RFCs.

They can be supported, sure, but what about in practice?  Can we rely on
such functionality being present?

Section 3

   namespace URI in the login and greeting extension services.  The
   namespace URI "urn:ietf:params:xml:ns:epp:secure-authinfo-transfer-
   1.0" is used to signal support for the operational practice.  The

Written in this way this is codepoint squatting, assuming that the
requested XML namespace value will be assigned.  Given that Section 8
implies this stuff is deployed already, there really should have been an
early allocation made.

   A client that receives the namespace URI in the server's Greeting
   extension services, can expect the following supported behavior by
   the server:

   1.  Support an empty authorization information value with a create
       command.
   [...]

It's interesting to compare this to RFC 5731, that says "Authorization
information as described in Section 2.6 is REQUIRED to create a domain
object.  [...]  Failure to protect authorization information from
inadvertent disclosure can result in unauthorized transfer operations
and unauthorized information release.  [...]"  In some sense we are
introducing a rather significant philosophical change in the nature of
authorization information, that might be called out more prominently.

   7.  Support automatically unsetting the authorization information
       upon a successful completion of transfer.

Just "support", or actually will in practice?
(Probably applies to some of the other enumerated points as well, for
both client and server, though I think not to all of them.)

Section 4

   with the <contact:pw> element).  Other EPP objects that support
   password-based authorization information for transfer can use the
   Secure Authorization Information defined in this document.  For the

This is phrased just as "can use" (not "will use"), but we are
supposedly defining an XML namespace used for capability negotiation in
the initial EPP exchange, which really ought to have well-specified
semantics.  *Must* the secure authorization information defined in this
document be used for any applicable transfer, when the XML namespace we
define is in effect for the capabilities to use?

Section 4.1

   The strength of the random authorization information is dependent on
   the actual entropy of the underlying random number generator.  For
   the random number generator, the practices defined in [RFC4086] and
   section 4.7.1 of the NIST Federal Information Processing Standards
   (FIPS) Publication 140-2 [FIPS-140-2] SHOULD be followed to produce
   random values that will be resistant to attack.  A random number
   generator (RNG) is preferable over the use of a pseudorandom number
   generator (PRNG) to reduce the predictability of the authorization
   information.  The more predictable the random number generator is,
   the lower the true entropy, and the longer the required length for
   the authorization information.

This is not really the advice that I would be giving, myself.
For one, using a true RNG is not necessarily better than a PRNG, since a
good PRNG will have a lot of well-thought-out "whitening" functionality
that makes the output fairly uniform.  A true RNG can be a true RNG
while still sampling from a non-uniform distribution and leaving
patterns in the output.  But more importantly, implementors of EPP are
highly unlikely to need to care about the entropy gathering practices
specified by NIST SP 140-2 and RFC 4086 -- they can and should just use
/dev/urandom!  RFC 4086 was written in a time when /dev/urandom was not
as reliable as it is nowadays, but the advice of "to obtain randon
numbers under Linux, Solaris, [...] all an application has to do is open
either /dev/random or /dev/urandom and read the desired number of
bytes" is arguably the most important guidance in it.  (There's also a
corresponding Windows API.)  If we don't think people will want to
implement a 94-character alphabet themselves, we can suggest the widely
available base64 encoding and say something like "read 18 bytes from
/dev/random and base64 encode it, which will produce 24 characters of
encoded output" or give the ROUNDUP(128/log2 64) math.  (I use 18 bytes
because that avoids base64 padding characters.)

Section 4.2

I strongly suggest giving some guidance to registrars on how to set the
TTL (presumably a week or a few days is doable for common/generic domain
transfers?).  The requirements in §4.3 are not really aligned with
current best practices for password hashing for long term storage
(which, admittedly, are designed for human-selected passwords and not
random ones), so clamping down the TTL is going to be helpful for
putting bounds on some classes of attack.

Section 4.3

I note that draft-ietf-kitten-password-storage is underway to write
down best practices for password hashing and storage.  It is probably
not mature enough to be used as a definitive reference yet, but could be
useful information.

   1.  The authorization information MUST be stored by the registry
       using a strong one-way cryptographic hash, with at least a
       256-bit hash function such as SHA-256 [FIPS-180-4], and with a
       random salt.

Typical password-hashing recommendations these days are things like
Argon2 (winner of https://www.password-hashing.net/) or PBKDF2 (for
somewhat more legacy systems).  The iteration count (and other
parameters, for Argon2) can be tweaked depending on the systems in
question and the esteimated strength of the password, but nobody is
doing just a single-iteration of (salted) SHA256.  I note that we
recently approved draft-ietf-lamps-crmf-update-algs that leaves in place
a requirement that the iteration count MUST be at least 100 (and adds
"SHOULD be as large as server performance will allow, typically at least
10,000").  If the intent is to take advantage of the special
considerations here about the nature of the passwords in question, in
order to diverge from password-hashing best practice, we should be
explicit about the intentional divergence.

   5.  The plain text version of the authorization information MUST NOT
       be written to any logs by the registrar or the registry, nor

nit: "the registrar" is perhaps ambiguous in this scenario where we have
both losing and gaining registrars.

Section 4.4

   1.  Any input authorization information value MUST NOT match an unset
       authorization information value.

Does this only apply to non-empty input authorization information?

   3.  A non-empty input authorization information value MUST be hashed
       and matched against the set authorization information value,
       which is stored using the same hash algorithm.

It might be worth a few sentences (not necessarily here) about
password-hashing-algorithm agility and what an algorithm transition
would look like.

Section 5.2

   Because of this, registries may validate the randomness of the
   authorization information based on the length and character set
   required by the registry.  For example, validating an authorization
   value contains a combination of upper-case, lower-case, and non-
   alphanumeric characters, in an attempt to assess the strength of the
   value, and return an EPP error result of 2202 if the check fails.

   Such checks are, by their nature, heuristic and imperfect, and may
   identify well-chosen authorization information values as being not
   sufficiently strong.  Registrars, therefore, must be prepared for an
   error response of 2202, "Invalid authorization information", and
   respond by generating a new value and trying again, possibly more
   than once.

I note for the record that we had an earlier conversation about this
behavior, and I still believe that it does not reflect a best practice
for minimizing the use of weak passwords.  That said, it is a
non-normative example, and we basically already had our discussion on
this topic, so there is no need to rehash it again -- this is a
non-blocking comment.

Section 6

   3.  Losing registrar retrieves the stored authorization information
       locally or queries the registry for authorization information

nit: I think s/retrieves the stored authorization information
locally/retrieves the locally stored authorization information/ helps
readability.

Section 6.1

How do these features interact with the presence (or absence) of the
secure-authinfo-transfer XML namespace in the <login>/greeting exchange?

It seems like at least the "don't return the authorization information
in the info response" change, if unilaterally implemented by the
registry, would break the classic workflow for registrars that do not
store the authorization information locally and require retrieving it
from the registry.  (Or are they required to implement the ability to
re-set the authorization information with an update, so that recovery is
possible?)

Section 6.2

   Hash New Authorization Information Values:  Change the create command
      and the update command to hash instead of encyrpting the

nit: s/encyrpting/encrypting/

   Supporting Comparing Against Encrypted and Hashed Authorization
   Information:  Change the info command and the transfer request
      command to be able to compare a passed authorization information
      value with either a hashed or encyrpted authorization information
      value.

This seems to leave it implicit that the stored values in the registry
include an indication of whether they are encrypted or hashed.  This is
probably trivial to ensure, just by virtue of being formatted
differently, but is an important enough property that I would suggest
mentioning it specifically.

Section 6.3

As for the case in Section 6.1, are these changes contingent on the
negotiation of the use of secure-authinfo-transfer?  Disallowing the
creation of entries with non-empty authorization information values
seems like it would break existing clients that do not implement
secure-authinfo-transfer.  Is there some mechanism in place that is
going to make secure-authinfo-transfer (e.g., contractually) required to
implement for registrars?

Section 9

   Section 4.1 defines the use a secure random value for the generation
   of the authorization information.  The server SHOULD define policy
   related to the length and set of characters that are included in the
   randomization to target the desired entropy level, with the
   recommendation of at least 128 bits for entropy.  The authorization
   information server policy is communicated to the client using an out-
   of-band process.  The client SHOULD choose a length and set of
   characters that results in entropy that meets or exceeds the server
   policy.  A random number generator (RNG) is preferable over the use
   of a pseudorandom number generator (PRNG) when creating the
   authorization information value.

[my comment from above about RNG vs PRNG applies here as well.]

I am a little uneasy about the "SHOULD define policy", which may just
reflect a misundersanding of the text.  If this is just an
administrative policy that is written and read by humans, that is
probably useful, but how it interacts with mechanical enforcement (per
my previous comments) could spill over into a regime of giving normative
recommendations to do things that I do not believe are best practice.

   Section 4.2 defines the use of an authorization information Time-To-
   Live (TTL).  The registrar SHOULD only set the authorization
   information during the transfer process by the server support for

I guess I don't understand why this is only a SHOULD (and this same
requirement seems to appear in Section 4.2 as well).  Given that we
propose for the registry to reject creation with non-empty authorization
information, it doesn't seem too big of a change to require that
registrars also comply with this workflow.

   the end of the transfer process.  The registry MUST store the
   authorization information using a one-way cryptographic hash of at
   least 256 bits and with a random salt.  All communication that

[this text might have to change if the earlier comment about password
hashing techniques results in a textual change]

Section 11.1

(If my suggestion about RNG guidance is accepted, FIPS-140-2 will no
longer need to be a normative reference.)

I don't really understand why RFC 3688 is listed as normative but RFC
7451 is listed as informative -- on both cases they're only referenced
as the specification that created an IANA registry that we're getting
an allocation in.