Subject: [netmod] SSH keys - draft-ietf-netmod-system-mgmt

From: Martin Bjorklund <[email-masked]>
Date: Tue, 29 Apr 2014 22:05:05 +0200 (CEST)

Hi,

The NETMOD WG has produced draft-ietf-netmod-system-mgmt-15, which
contains a YANG data model for system management.  This document today
enters a second IETF Last Call.

Among other things, it has a data model for the definition of SSH
public keys for local users on a device.

Stephen Farrell suggested that this list might be able to help us with
an SSH-specific question.  We would be very grateful for any expert
help.

First some background.

The data model in question has this structure (objects unrelated to
SSH keys removed)

           +--rw user* [name]
               +--rw name        string
               +--rw ssh-key* [name]
                  +--rw name         string
                  +--rw algorithm    string
                  +--rw key-data     binary

This means that there is a list of users, identified by name.  Each
user has a list of public SSH keys, identified by an arbitrary name.

Zooming in on the ssh-key list, it looks like this:

         list ssh-key {
           key name;
           description
             "A list of public SSH keys for this user.";
           reference
             "RFC 4253: The Secure Shell (SSH) Transport Layer
                        Protocol";

           leaf name {
             type string;
             description
               "An arbitrary name for the ssh key.";
           }
           leaf algorithm {
             type string;
             mandatory true;
             description
               "The public key algorithm name for this ssh key.

                Valid values are the values in the IANA Secure Shell
                (SSH) Protocol Parameters registry, Public Key
                Algorithm Names";
             reference
               "IANA Secure Shell (SSH) Protocol Parameters registry,
                Public Key Algorithm Names";
           }
           leaf key-data {
             type binary;
             mandatory true;
             description
               "The binary key data for this ssh key.";
           }
         }

Now to the problem.

During implementation of ssh key handling, we realized that the
description of these objects need at least some clarification.

The intention was that the separation of the key with two leafs,
"algorithm" and "key-data" makes it easy to cut-and-paste from keys
generated with ssh-keygen etc.  (The encoding of type binary in YANG
is base64, which happen to match the key format.  So the operator can
set the "algorithm" and pase the base64 encoded blob into "key-data".)

First of all, it is not entirely clear what goes into the "key-data"
leaf.  Common file formats (open ssh proprietary,
RFC4716) follow the same rules; defined in RFC4716:

   The body of a public key file is the base64 encoded ([RFC2045])
   public key data as specified by [RFC4253], Section 6.6:

         string    certificate or public key format identifier
         byte[n]   key/certificate data

The open ssh internal format is this:

  <algorithm> <base64 key data>

e.g.:

  ssh-rsa  AAAAB3NzaC1yc2EAAAADAQABAAABAQDBNX...

The base64 blob is encoded as described above, i.e. it contains
the string "ssh-rsa", even though this is already specified at the
start of the line.  So this format is redundant, and it seems the
implementation detects and rejects keys that have different values for
the <algorithm> and the public key format identifier.

The RFC 4716 format does not have this redundancy:

    ---- BEGIN SSH2 PUBLIC KEY ----
    AAAAB3NzaC1yc2EAAAADAQABAAABAQDBNX...
    ...
    ---- END SSH2 PUBLIC KEY ----

So we have some options:

1)  Clarify that the leaf "key-data" contains:

         string    certificate or public key format identifier
         byte[n]   key/certificate data

    This allows for simple copy-and-paste from normal open ssh and
    rfc4716 files.

    However, if we also keep the leaf algorithm, we need to specify
    what happens if the leaf algorithm has a value that is different
    from the value embedded in the key blob.

2)  Like 1, but remove the "leaf algorithm".

3)  Keep "leaf algorithm" and specify that the leaf "key-data" contains:

         byte[n]   key/certificate data

    This is NOT copy-and-paste friendly and probably pretty
    confusing to operators.

Some other issues, probably less important.

o  If we do 1 or 2 above, is the name "key-data" really correct;
   shouldn't it be changed to just "key", in order to use the same
   terminology as RFC 4253:

     Certificates and public keys are encoded as follows:

        string    certificate or public key format identifier
        byte[n]   key/certificate data

   Which says that a "key" is encoded as "format id" + "key data".

o  Should list "ssh-key" be called "ssh-public-key"?

   The description says it is public keys only, so shouldn't this be
   reflected in the name of the list?

We are leaning towards option 2 above, and would very much appreciate
any comments on this matter!

/martin

---

From: [email-masked] (Niels Möller)
Date: Wed, 30 Apr 2014 08:49:06 +0200

>     from the value embedded in the key blob.

Right, eliminating this redundancy makes things simpler.

> 2)  Like 1, but remove the "leaf algorithm".

I'm not sure I understand the context, but this sounds like the best
option to me. If one wants a human-readable algorithm identifier, one
could include that in the name field (but ideally, any tools handling
this data should be able to extract the algorithm id from the key blob).

>     This is NOT copy-and-paste friendly and probably pretty

I would recommend *not* picking apart the ssh key (unless you really
want to convert it to some other reasonable representation, say, an
spki-style s-expression).

>    shouldn't it be changed to just "key", in order to use the same

Makes sense.

>    reflected in the name of the list?

I think it would make more sense to have a name that reflects the
*purpose* of the list of keys, rather than just the data type. E.g., if
it's authorization keys for logging in to the users account, it could be
"authorized-ssh-keys" or something like that.

Regards,
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
Internet email is subject to wholesale government surveillance.

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Wed, 30 Apr 2014 12:32:50 -0400

> Right, eliminating this redundancy makes things simpler.

It would, except you can't eliminate it.  The second copy of the
algorithm name is part of the key data format for _certain public key
algorithms_, but not necessarily for all of them.

The right thing here is to leave it as defined - the "algorithm" is a
string naming the public key algorithm, and the "key-data" is an
_opaque_ base64 blob.  The fact that for certain kinds of keys the
opaque blob happens to contain a copy of the algorithm name is
irrelevant.

As for what happens when they're different -- it doesn't work!  If you
say you're providing a key for one algorithm and actually provide key
data for a different one, it's simply not going to work.  You could
check when setting a key that the provided key data is valid for the
specified algorithm, but I would very strongly recommend against that.
Doing so requires that whatever's doing the validation understand all
possible key algorithms, which is impossible, since public key algorithm
names are a vendor-extensible namespace.

> "authorized-ssh-keys" or something like that.

Yes.

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 30 Apr 2014 19:50:31 +0200

> algorithms_, but not necessarily for all of them.

Hm. Are you saying RFC 4716 is broken or only applicable to certain
subset of public key algorithms? In which case would the public key
not follow [RFC4253], Section 6.6:

I am just trying to understand this.

/js

-- 
Juergen Schoenwaelder           Jacobs University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1, 28759 Bremen, Germany
Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Wed, 30 Apr 2014 14:14:19 -0400

> I am just trying to understand this.

Section 6.6 is actually quite specific on this:

   The key type MUST always be explicitly known (from algorithm
   negotiation or some other source).  It is not normally included in
   the key blob.

It then goes on to define two key types ("ssh-dss" and "ssh-rsa") which
each begin with a fixed string that is the same as the key type name,
and two more which are unfortunately rather vague, but which I don't
think are commonly used.

I seem to recall this being an issue in the past, because someone made
an assumption that keys would always be self-describing when in fact
they were not.  Unfortunately, I no longer remember the exact
circumstances.  But yes, I believe RFC4716 is broken, because it relies
on the encoding described above, rather than being consistent with the
requirement "The key type MUST always be explicitly known."

IMHO, things that are not implementations of SSH should not need to be
aware of SSH's encoding or of the details of particular public key
formats.  They should treat the opaque key data as opaque, and separate
from the key type.

-- Jeff

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 30 Apr 2014 21:20:00 +0200

> and two more which are unfortunately rather vague, but which I don't

Well, but the text in section 6.6 also says this (right after the text
you quoted):

:   Certificates and public keys are encoded as follows:
:
:      string    certificate or public key format identifier
:      byte[n]   key/certificate data

This text does not look conditional and perhaps this is where the
confusion comes from? For me, as a reader who has no prior involvement
in this, these two paragraphs look a bit like a contradiction...

> requirement "The key type MUST always be explicitly known."

OK. I am happy to follow you advice to keep the algorithm type leaf.
 
> formats.  They should treat the opaque key data as opaque, and separate

Yes, I think we agree. I do not expect a NETCONF server to try to
validate whether the key blob is valid.

/js

---

From: [email-masked] (Niels Möller)
Date: Wed, 30 Apr 2014 22:06:06 +0200

Jeffrey Hutzelman <[email-masked]> writes:

> It would, except you can't eliminate it.

Hmm. I think you're right. So then then the "algorithm" leaf would be
the name being used in algorithm negotiation and the like, and the "key"
leaf would be the key blob. The key blob typically starts with a string
containing the algorithm identifier, but nothing but the ssh
implementation is expected to care about that detail.

So then the right choice is 1),

: 1)  Clarify that the leaf "key-data" contains:
: 
:          string    certificate or public key format identifier
:          byte[n]   key/certificate data
: 
:     This allows for simple copy-and-paste from normal open ssh and
:     rfc4716 files.

Regards,
/Niels