Subject: Re: [netconf] ietf crypto types - permanently hidden

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Wed, 1 May 2019 10:17:27 +0000

Hi Kent,

I’m slightly lost here, so my comments may not be that helpful 😊

I don’t understand why do we need an explicit action to create/install the key?  In particular, why can’t there just be a regular (intend based) configuration leaf that is “use-system-defined-key”?  The key values could be reported in <intended> and/or <operational>, suitably protected via NACM, or they could be kept entirely hidden.

I also agree with Martin/Andy that it is highly desirable to allow a device to be configured with a single configuration input file, provided from <startup> or <edit-config|data>.  I think that anything that would require, or encourage, multiple RPC interactions to setup the device would seem to be a big backwards step in terms of device management.

I’m not opposed to RPCs or actions to manage hidden keys on the device if:

(i)               these don’t get written to <running> (because they are not regular configuration), and

(ii)              there is a sensible/secure mechanism to configure the device without requiring any extra RPCs/actions to configure the device.  I.e. the RPCs/actions should only be used for exceptional management of the keys on the device.

Thanks,
Rob

From: netconf <[email-masked]> On Behalf Of Kent Watsen
Sent: 30 April 2019 18:57
To: Martin Bjorklund <[email-masked]>
Cc: [email-masked]
Subject: Re: [netconf] ietf crypto types - permanently hidden

I (still) object to this.  Actions shouldn't create config.  We
already have generic protcol operations to do this.  We go from a
document-oriented configuration model towards a command-oriented
model.  Not good.  In RESTCONF, the generic methods support things
like ETags, which I suspect you don't want to replicate in this
action?   Will the action support all error-options of edit-config,
like rollback-on-error?

The specifics for how this could work would need to be defined.  Given that it is a special case, I think that we could constrain it heavily and target simple solution.   Depending how much text is required to describe it, it might be good to define an extension statement that could be placed on the actions.  While an extension statement may seem like it opens the gates for general use, we could further define the extension statement as being something that MUST NOT be used when general purpose operations are suitable such that, at least with the IETF, it could only be used in extraordinary circumstances.

Some comments on the new text:

In action generate-hidden-key, it should be stated that the public-key
will be populated, and that the private-key will exist but report
'permanently-hidden'.

Okay, but before making the edit, see comment below about lifetimes...

In action install-hidden-key, shouldn't both public-key and
private-key be mandatory?  Also state that the private-key will report
'permanently-hidden'.

Indeed, fixed.

In leaf private-key, the type binary part of the union doesn't have a
description, and the description for the leaf itself says:

      A binary that contains the value of the private key.

which is not quite correct.

I think we should state that the enum 'permanently-hidden' is only
reported in operational state.

The 'type' statement doesn't have 'description' as a substatement,
but, point taken, two updates:

In leaf private-key:
  OLD:
      A binary that contains the value of the private key.
  NEW:
      Either a binary that contains the value of the private key or, in
      the case of a hidden key, the value 'permanently-hidden'.

In enum permanently-hidden:
  OLD:
       The private key is inaccessible due to being protected by the
       system (e.g., a cryptographic hardware module).
  NEW:
       The private key is inaccessible due to being protected by the
       system (e.g., a cryptographic hardware module).  Since hidden
       keys are only ever reported in <operational>, the value
       'permanently-hidden' never appears in <intended>.

The new descriptions say:

           [...] present only in
           <operational> and bound to the lifetime of the parent
           'config true' node.

Aren't all nodes bound to the lifetime of their parent?
The action is invoked in a node that exists in <operational> and it
creates a key.  What does the statement tell me?

This seems like something new (and maybe wrong) and hence needs to be explained.  This seems new because we are saying that the lifetime of an operational value is tied to the lifetime of a configured value.  Normally we talk about how operational values exist on their own and that, if one wants to override/extend them (e.g., associate a certificate to the private key created by the manufacturer), configuration would overlay the operational values.  By extension, if the configuration is removed, the operational values go back to their original state (i.e., existing on their own).   Here we're saying that, if the configuration (for the parent node) is removed, the operational values are removed as well.

Note that this statement was added because Juergen asked about how hidden keys could be removed/replaced.   We iterated towards not wanting to support the "replace" case, and this seemed like an easy way to handle the "remove" case.  Another way to do this would be via another action such as 'remove-hidden-key'.   What do you think would be best?

Kent // contributor

---

From: Andy Bierman <[email-masked]>
Date: Wed, 1 May 2019 09:19:38 -0700

On Wed, May 1, 2019 at 3:17 AM Rob Wilton (rwilton) <[email-masked]>
wrote:

> I don’t understand why do we need an explicit action to create/install the
> key?  In particular, why can’t there just be a regular (intend based)
> configuration leaf that is “use-system-defined-key”?  The key values could
> be reported in <intended> and/or <operational>, suitably protected via
> NACM, or they could be kept entirely hidden.
>
>
>
> I also agree with Martin/Andy that it is highly desirable to allow a
> device to be configured with a single configuration input file, provided
> from <startup> or <edit-config|data>.  I think that anything that would
> require, or encourage, multiple RPC interactions to setup the device would
> seem to be a big backwards step in terms of device management.
>
>
>
> (ii)              there is a sensible/secure mechanism to configure the
> device without requiring any extra RPCs/actions to configure the device.
> I.e. the RPCs/actions should only be used for exceptional management of the
> keys on the device.
>
>
The document-oriented configuration came from a requirement identified
at the IAB Network Management Workshop (way back when).
It is critical for rebooting, swapping out a defective device, etc.

This seems to be a good test for whether NMDA is useful as designed.
It seems obvious that something has to be stored in <running> and
then transformed as it is applied to <intended>.

I don't see how an action or RPC approach meets the operator requirements
identified in RFC 3535.

The "server created config" problem could be viewed as an access control
problem.
There are proprietary YANG extensions that implement this approach.

> Rob

Andy

>
>
> *From:* netconf <[email-masked]> *On Behalf Of *Kent Watsen
> *Sent:* 30 April 2019 18:57
> *To:* Martin Bjorklund <[email-masked]>
> *Cc:* [email-masked]
> *Subject:* Re: [netconf] ietf crypto types - permanently hidden
>
>
>
>
>
>
>
> The specifics for how this could work would need to be defined.  Given
> that it is a special case, I think that we could constrain it heavily and
> target simple solution.   Depending how much text is required to describe
> it, it might be good to define an extension statement that could be placed
> on the actions.  While an extension statement may seem like it opens the
> gates for general use, we could further define the extension statement as
> being something that MUST NOT be used when general purpose operations are
> suitable such that, at least with the IETF, it could only be used in
> extraordinary circumstances.
>
>
>
>
>
> This seems like something new (and maybe wrong) and hence needs to be
> explained.  This seems new because we are saying that the lifetime of an
> operational value is tied to the lifetime of a configured value.  Normally
> we talk about how operational values exist on their own and that, if one
> wants to override/extend them (e.g., associate a certificate to the private
> key created by the manufacturer), configuration would overlay the
> operational values.  By extension, if the configuration is removed, the
> operational values go back to their original state (i.e., existing on their
> own).   Here we're saying that, if the configuration (for the parent node)
> is removed, the operational values are removed as well.
>
>
>
> Note that this statement was added because Juergen asked about how hidden
> keys could be removed/replaced.   We iterated towards not wanting to
> support the "replace" case, and this seemed like an easy way to handle the
> "remove" case.  Another way to do this would be via another action such as
> 'remove-hidden-key'.   What do you think would be best?
>
>
>
>
>
> Kent // contributor
>
>
> _______________________________________________
> netconf mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netconf
>

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 1 May 2019 20:05:53 +0200

> then transformed as it is applied to <intended>.

The issue here seems to be that you create a resource that you would
like to be partially accessible as config and partially not accessible
at all or only as applied config in operational state. The question is
how to model that, i.e., the binding between config part and the
internal state part. Do we have any other similar resources or is this
really a very special case?

We discussed the 'create user account' case where often users ids are
allocated as a side effect of creating an account but the allocated
ids then becomes regular config, i.e., the config can be copied and
restored as one would expect. This is not really the same case that we
have with locally created keys.

An alternative might be to consider a locally generated key entirely
operational state (applied config): You invoke an RPC to create a key
and you give it a name and then it exists as named operational state
(applied config) until you delete that named operational state. If you
want to configure a transport that refers to such a key, you do this
via a name binding, pretty much in the way we apply interface
configuration to an interface with a matching name. Perhaps this is a
model that could work.

Perhaps Martin has even better ideas.

/js

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

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 01 May 2019 23:06:22 +0200 (CEST)

Hi,

Juergen Schoenwaelder <[email-masked]> wrote:
> On Tue, Apr 30, 2019 at 02:49:30PM +0200, Martin Bjorklund wrote:
> > Kent Watsen <[email-masked]> wrote:
> > > 
> > > Correct, as I didn’t think there was consensus yet.  Perhaps there is
> > > rough-consensus, and it may be that the only way to gauge that is to
> > > try and see how much push back there is.
> > > 
> > > Okay, so how about this, based on this thread, there appears to be
> > > support to add a flag to control if a key should be “permanently
> > > hidden” or not, in which case configuration is created.
> > 
> Martin,
> do you have any proposal how to support the requirement to generate a
> key on the device that is workable with a document-oriented
> configuration model? Do you propose that the action/rpc returns the
> public key information as result data that then needs to be written
> back to the server and somehow matched to the key that is cached on
> the device? Perhaps you have other ideas I can't think of?
> 
> I think I would be happy to not have this special hack but then we
> need a workable alternative. Key generation on devices is something
> that is being used - and may be even more used in the future the more
> we get special hardware support for storing keys.

So the current draft supports two use cases:

  1.  The client configures the private and public keys explicitly
      (simple case).  Both keys are availible in the config and
      operaional state.

  2.  The client asks the device to generate a "hidden" key which may
      be a key in special TPM hardware.

For 2, the client configures the name of the key (in <running>).  Then
the client invokes the action (in <operational>).  The device
generates a new key pair (perhaps in tpm-hw).  In <operational>, the
public key is now visible and the private key has the special enum
"permanently-hidden".

A device that doesn't have special hardware can still implement 2, but
store the keys in the filesystem.  Perhaps this info needs to be
visible for the client, or even controlled by the client.

What I object to is a third use case, where the action would modify
the config with the generated keys.

/martin

---

From: Kent Watsen <[email-masked]>
Date: Thu, 2 May 2019 00:34:20 +0000

> It is critical for rebooting, swapping out a defective device, etc.

Regarding the document-model concern, here is a line of thinking that may help this discussion:

We recently removed the "cannot be backed-up language" because there may be a way for a device to backup a permanently hidden key, even when protected by a TPM.

Specifically, a TPM (I don't know about other crypto processors) is able to encrypt TPM-protected keys (using yet another TPM-protected key called the storage root key, SRK), thus the key (albeit encrypted) CAN be backed up, but it CAN ONLY be restored on the device having the originating TPM.

Thus, instead of using the enum "permanently-hidden", the value of the *encrypted* key could be safely provided.

Perhaps we could model the 'private-key' value after iana-crypt-hash and prefix the base64-encoded binary private key value with some special (not legal base64) value indicating that the key is 1) encrypted and 2) can only be restored on the originating device.  Ideally, the prefix identifies the device (or, better, the crypto processor), lest there is any confusion.

As for "swapping out a defective device", the above idea doesn't support that workflow, but I think that the inability to do a full RMA is given with the meaning of a "permanently-hiddden" key already and, anyone that creates such a key does so with that understanding.   What it does support, though, is the full restoration of the device after a hard-drive replacement (or reformat) using a standard "configuration" document, which seems better than what we have now with the "permanently-hidden" enum.

> The "server created config" problem could be viewed as an access control problem.

I don't understand, can you provide examples?

Kent // contributor

---

From: Andy Bierman <[email-masked]>
Date: Wed, 1 May 2019 17:43:39 -0700

On Wed, May 1, 2019 at 5:34 PM Kent Watsen <[email-masked]> wrote:

> We recently removed the "cannot be backed-up language" because there may
> be a way for a device to backup a permanently hidden key, even when
> protected by a TPM.
>
> Specifically, a TPM (I don't know about other crypto processors) is able
> to encrypt TPM-protected keys (using yet another TPM-protected key called
> the storage root key, SRK), thus the key (albeit encrypted) CAN be backed
> up, but it CAN ONLY be restored on the device having the originating TPM.
>
> Thus, instead of using the enum "permanently-hidden", the value of the
> *encrypted* key could be safely provided.
>
> Perhaps we could model the 'private-key' value after iana-crypt-hash and
> prefix the base64-encoded binary private key value with some special (not
> legal base64) value indicating that the key is 1) encrypted and 2) can only
> be restored on the originating device.  Ideally, the prefix identifies the
> device (or, better, the crypto processor), lest there is any confusion.
>
> As for "swapping out a defective device", the above idea doesn't support
> that workflow, but I think that the inability to do a full RMA is given
> with the meaning of a "permanently-hiddden" key already and, anyone that
> creates such a key does so with that understanding.   What it does support,
> though, is the full restoration of the device after a hard-drive
> replacement (or reformat) using a standard "configuration" document, which
> seems better than what we have now with the "permanently-hidden" enum.
>
>

This requirement led directly to the ability in NETCONF to do a simple
<get-config> and
stuff the returned data into an <edit-config> or <copy-config> request.

> I don't understand, can you provide examples?

We have a "user-write" extension that can override NACM and prevent client
access to server-created configuration.

http://www.netconfcentral.org/modules/yuma-ncx/2015-10-16#user-write.704

Andy

---

From: Kent Watsen <[email-masked]>
Date: Thu, 2 May 2019 01:56:47 +0000

> the config with the generated keys.

What is your proposal for how to address the best practice and, in some cases, 
government requirement, that a private key never exists outside of a device 
(controlled backups aside)?

From https://revocent.com/best-practices-for-securing-private-keys: <https://revocent.com/best-practices-for-securing-private-keys:>

    "It’s crucial that the generation of the key be done on the same system and the same
     local filesystem as the storage location.  Generating the key on a server and then
     transferring the key back to the local system and storing it just adds multiple points
     of vulnerability.  Why would you want to increase the chance of your private key
     being compromised?"

Additionally, SC-12(3) of NIST 800-53 says:   (note: the word "produce" is key here)

    "Produce, control, and distribute asymmetric cryptographic keys using [Selection: 
     NSA-approved key management technology and processes; approved DoD PKI
     Class 3 certificates; prepositioned keying material; approved DoD PKI Class 3 or
     Class 4 certificates and hardware security tokens that protect the user’s private
     key; certificates issued in accordance with organization-defined requirements]."

Many networking devices include an SSL-protected web-interface.

    1) Typically the interface is initially secured via a self-signed certificate, which
         causes the browser to display a nagging message when connecting,
         thus prompting remediation.

    2) Almost all products include an ability to upload the 2-tuple of a private key
         and a signed certificate.  This resolves the self-sign cert issue, but the
         best practice and government compliance concerns are not addressed.

    3) The better products have an ability to:
          a) let the device generate the private key
          b) let the device generate a certificate signing request using its private key
          c) upload to the device a certificate generated by an external CA signing the CSR.   
          [FWIW, Juniper's SRX device introduced this ability in 2011.]

The current model supports (2), as well as (3b) and (3c), we're just missing (3a), 
which is what the original `generate-asymmetric-key` action was for.

FWIW, from a product perspective, supporting (3a) is more important then supporting
`generate-hidden-key` or `install-hidden-key` (so long as manufacturer-generated
hidden keys are still supported, e.g., for IDevID certificates).   While client-generated
permanently-hidden keys is goodness, it's not widely implemented.

Kent

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 02 May 2019 08:31:51 +0200 (CEST)

Hi,

> (controlled backups aside)?

Use the current "generate-hidden-key".  Note that the proposed 3rd
alternative does not address this requirement, since the private key will be
part of the normal config, and thus can be read by anyone (with the right
access).

>     "It’s crucial that the generation of the key be done on the same
>      system and the same local filesystem as the storage location.
>      Generating the key on a server and then transferring the key
>      back to the local system and storing it just adds multiple
>      points of vulnerability.  Why would you want to increase the
>      chance of your private key being compromised?"
> 
> 
>     "Produce, control, and distribute asymmetric cryptographic keys
>      using [Selection: NSA-approved key management technology and
>      processes; approved DoD PKI Class 3 certificates; prepositioned
>      keying material; approved DoD PKI Class 3 or Class 4
>      certificates and hardware security tokens that protect the
>      user’s private key; certificates issued in accordance with
>      organization-defined requirements]."
> 
> 
>     1) Typically the interface is initially secured via a
>          self-signed certificate, which causes the browser to
>          display a nagging message when connecting, thus prompting
>          remediation.
> 
>     2) Almost all products include an ability to upload the 2-tuple
>          of a private key and a signed certificate.  This resolves
>          the self-sign cert issue, but the best practice and
>          government compliance concerns are not addressed.
> 

There must be some misunderstanding.  IMO, the current
"generate-hidden-key" clearly supports 3a.  The device generates the
key when this action is invoked.

> FWIW, from a product perspective, supporting (3a) is more important
> then supporting `generate-hidden-key` or `install-hidden-key` (so
> long as manufacturer-generated hidden keys are still supported,
> e.g., for IDevID certificates).  While client-generated

/martin

---

From: tom petch <[email-masked]>
Date: Thu, 2 May 2019 09:39:09 +0000

----- Original Message -----
From: "Juergen Schoenwaelder" <[email-masked]>
Sent: Wednesday, May 01, 2019 7:05 PM

> really a very special case?

I wonder if IPv6 privacy addresses are similar, generated on the device
using random or pseudo-random input and which may also use device
specific data such as MAC address; and which may derive from the
device's public key.

If the hardware is replaced, and the configuration is restored, should
the address stay the same or is it a breach of privacy to carry the
address across? I do not know but would guess the latter.

Tom Petch

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 2 May 2019 11:49:16 +0200

> address across? I do not know but would guess the latter.

My understanding is that privacy addresses are temporary addresses and
hence they exist in the <operational> datastore but not in regular
configuration datastores. Since they are created and garbage collected
automatically, there is most likely no need for a management interface
for them.

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 02 May 2019 12:09:44 +0200 (CEST)

Hi,

Kent Watsen <[email-masked]> wrote:
> that it is a special case, I think that we could constrain it heavily
> and target simple solution.  Depending how much text is required to
> describe it, it might be good to define an extension statement that
> could be placed on the actions.  While an extension statement may seem
> like it opens the gates for general use, we could further define the
> extension statement as being something that MUST NOT be used when
> general purpose operations are suitable such that, at least with the
> IETF, it could only be used in extraordinary circumstances.

Let's first agree on the issue about whether this action should exist
at all.

>        'permanently-hidden' never appears in <intended>.

Ok, but perhaps s/<intended>/conventional configuration datastores/?

> explained.  This seems new because we are saying that the lifetime of
> an operational value is tied to the lifetime of a configured value.
> Normally we talk about how operational values exist on their own and
> that, if one wants to override/extend them (e.g., associate a
> certificate to the private key created by the manufacturer),
> configuration would overlay the operational values.  By extension, if
> the configuration is removed, the operational values go back to their
> original state (i.e., existing on their own).  Here we're saying that,
> if the configuration (for the parent node) is removed, the operational
> values are removed as well.
> 
> Note that this statement was added because Juergen asked about how
> hidden keys could be removed/replaced.  We iterated towards not
> wanting to support the "replace" case

But why?  If an operator wants to replace, why should the list entry
first be deleted and then created and then the key can be generated?
This seems like a CLR to me.

> and this seemed like an easy
> way to handle the "remove" case.  Another way to do this would be via
> another action such as 'remove-hidden-key'.  What do you think would
> be best?

Ok, I see.  I think the text needs some clarification; make it more
explicit.  It needs to say that if a "permanently-hidden" private key
exists in <operational> under a parent config true node and this
parent node is deleted, the private key is supposed to be (MUST be?)
deleted from the system as well.

A remove-hidden-key action can be problematic b/c if you forget to
call this action and then delete the config, presumably you have
lingering keys in the system that you can't remove.

/martin

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Thu, 2 May 2019 12:21:19 +0000

Hi Martin,

> -----Original Message-----
> From: netconf <[email-masked]> On Behalf Of Martin Bjorklund
> Sent: 01 May 2019 22:06
> To: [email-masked]
> Cc: [email-masked]
> > > > Correct, as I didn’t think there was consensus yet.  Perhaps there
> > > > is rough-consensus, and it may be that the only way to gauge that
> > > > is to try and see how much push back there is.
> > > >
> For 2, the client configures the name of the key (in <running>).  Then the client
> invokes the action (in <operational>).  The device generates a new key pair
> (perhaps in tpm-hw).  In <operational>, the public key is now visible and the
> private key has the special enum "permanently-hidden".

Why is a separate action required to create the keys? 

Why is the configuration to generate a hidden key not sufficient for the device to automatically allocate a key in the TPM module?

Thanks,
Rob

> 
> A device that doesn't have special hardware can still implement 2, but store the
> keys in the filesystem.  Perhaps this info needs to be visible for the client, or
> even controlled by the client.
> 
> What I object to is a third use case, where the action would modify the config
> with the generated keys.
> 
> 
> /martin

---

From: Kent Watsen <[email-masked]>
Date: Thu, 2 May 2019 16:19:22 +0000

> Ok, but perhaps s/<intended>/conventional configuration datastores/?

Fixed in my local copy.

> This seems like a CLR to me.

https://mailarchive.ietf.org/arch/msg/netconf/ZwXll9BtAv61EvVXtFDLLzTkljE <https://mailarchive.ietf.org/arch/msg/netconf/ZwXll9BtAv61EvVXtFDLLzTkljE>

> deleted from the system as well.

Added, with a MUST.

> lingering keys in the system that you can't remove.

I don't think this is true.  Even if an asymmetric key only exists in <operational> (i.e., the corresponding "config true" parent node is deleted), it seems that a 'remove-hidden-key' could still remove it.  In fact, this is the most consistent thing, to have an 'action' act on values in <operational>.

Kent // contributor

---

From: Kent Watsen <[email-masked]>
Date: Thu, 2 May 2019 16:59:04 +0000

Hi Rob,

> Why is the configuration to generate a hidden key not sufficient for the device to automatically allocate a key in the TPM module?

I seem to be failing with words. 
Hopefully a picture will do the trick...

THIS IS WHAT WE HAVE CURRENTLY
==============================

                         |  Client is okay with the      |  Client is NOT okay with the  |
                         |  private key being in config  |  private key being in config  |
                         |  w/ nacm:default-deny-all.    |  i.e., wants "hidden" key.    |
                         |  (doc model not impacted.)    |  (doc model impacted!)        |
                         |  (this col more important)    |  (this col less important)    |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+
                         |                               |                               |
Client is okay with      |                               |                               |
generating the private   |  <edit-config> can be used.   |  use <install-hidden-key>     |
key (not best practice)  |                               |                               |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+
                         |                               |                               |
Client is NOT okay with  |                               |                               |
generating the private   |  Currently no solution !!!    |  use <generate-hidden-key>    |
key (best practice)      |                               |                               |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+

PROPOSAL: move "hidden" from action names to an input parameter, and let an action gen config
=============================================================================================

                         |  Client is okay with the      |  Client is NOT okay with the  |
                         |  private key being in config  |  private key being in config  |
                         |  w/ nacm:default-deny-all.    |  i.e., wants "hidden" key.    |
                         |  (doc model not impacted.)    |  (doc model impacted!)        |
                         |  (this col more important)    |  (this col less important)    |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+
                         |                               |                               |
Client is okay with      |  Either <edit-config> or      |  Use <install-key> with       |
generating the private   |  <install-key> with input     |  input "hidden".              |
key (not best practice)  |  NOT "hidden".                |                               |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+
                         |                               |                               |
Client is NOT okay with  |  Use <generate-key> with      |  Use <generate-key> with      |
generating the private   |  with input NOT "hidden".     |  with input "hidden".         |
key (best practice)      |                               |                               |
                         |                               |                               |
-------------------------+-------------------------------+-------------------------------+

Other proposals welcomed.

Kent // contributor

---

From: Balázs Kovács <[email-masked]>
Date: Fri, 3 May 2019 06:09:57 +0000

Hi,

https://mailarchive.ietf.org/arch/msg/netconf/ZwXll9BtAv61EvVXtFDLLzTkljE

I might back off from this one. I guess mismatched key pairs can occur with regular configuration case too, so it all depends on the operator to provide the right pair, and it should be the operator's decision to do a graceful key switch by creating a new key instance or do an instant renewal on the same instance. If the peer device does not have to be reconfigured, the renewal on same instance could be a better choice.

Br,
Balazs

From: Kent Watsen <[email-masked]>
Sent: Thursday, May 2, 2019 6:19 PM
To: Martin Bjorklund <[email-masked]>
Cc: Balázs Kovács <[email-masked]>; [email-masked]
Subject: Re: [netconf] ietf crypto types - permanently hidden

Fixed in my local copy.

https://mailarchive.ietf.org/arch/msg/netconf/ZwXll9BtAv61EvVXtFDLLzTkljE

Added, with a MUST.

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 03 May 2019 08:47:57 +0200 (CEST)

"Rob Wilton (rwilton)" <[email-masked]> wrote:
> > the client
> Why is the configuration to generate a hidden key not sufficient for
> the device to automatically allocate a key in the TPM module?

This is a very good question.  Why don't we have actions for
"create-interface', "create-user" or "create-acl"?  In all these cases
we have config that a device internally parses and translates to
some internal procedure (perhaps ifconfig, adduser, iptables etc).

In a way, this case is different b/c the client needs control of
*when* the key is generated.  We cannot copy & paste some config to
another device and expect it to work exactly the same.  OTOH that
probably is true for other things as well; if a user has been created
in the config there might be files owned by that user stored in the
home directory.

Also, we might need the option to re-generate the key (even though the
current version doesn't support this).  But *this* could be done w/ an
action (if we need to support it).

What did I miss; what makes this case special so that it can't be
handled like other config?

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 03 May 2019 08:49:58 +0200 (CEST)

Kent Watsen <[email-masked]> wrote:
> <https://mailarchive.ietf.org/arch/msg/netconf/ZwXll9BtAv61EvVXtFDLLzTkljE>
> 
> 
> 
> I don't think this is true.  Even if an asymmetric key only exists in
> <operational> (i.e., the corresponding "config true" parent node is
> deleted), it seems that a 'remove-hidden-key' could still remove it.
> In fact, this is the most consistent thing, to have an 'action' act on
> values in <operational>.

You're right.  If we have "create" action it makes sense to have a
"delete" action.  But see the mail from Rob W.  Perhaps we shouldn't
have these actions at all?

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 03 May 2019 09:08:09 +0200 (CEST)

> THIS IS WHAT WE HAVE CURRENTLY

I don't think the last column is less important.  That's the TPM case, right?

For the "no solution" case, it means that the client doesn't want to
write the private key, but it wants to read it.  Why should it read it
if it never writes it?  The whole point would be to be able to
re-generate the config on another device - but this would mean that
the client would use <edit-config> to pass the key, and it would be in
the upper left cell in table above.

> PROPOSAL: move "hidden" from action names to an input parameter, and let an action gen config

An option could perhaps be to let the "generate-key" with option
"not-hidden" create the private key in <operational> (still with
nacm:default-deny-all).  To re-create the key on another device, the
client would use install-key.

/martin

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Fri, 3 May 2019 09:15:40 +0000

> From: Martin Bjorklund <[email-masked]>
> Sent: 03 May 2019 07:48
> To: Rob Wilton (rwilton) <[email-masked]>
> Cc: [email-masked]; [email-masked]
> > > > > > Correct, as I didn’t think there was consensus yet.  Perhaps
> > > > > > there is rough-consensus, and it may be that the only way to
> > > > > > gauge that is to try and see how much push back there is.
> > > > > >
> > > > > > Okay, so how about this, based on this thread, there appears
> > > > > > to be support to add a flag to control if a key should be
> > > > > > “permanently hidden” or not, in which case configuration is created.
> > > > >
> > > > > already have generic protcol operations to do this.  We go from
> > > > > a document-oriented configuration model towards a
> > > > > command-oriented model.  Not good.  In RESTCONF, the generic
> > > > > methods support things like ETags, which I suspect you don't want to
> replicate in this
> > > > do you have any proposal how to support the requirement to
> > > > generate a key on the device that is workable with a
> > > > document-oriented configuration model? Do you propose that the
> > > > action/rpc returns the public key information as result data that
> > > > then needs to be written back to the server and somehow matched to
> > > > the key that is cached on the device? Perhaps you have other ideas I can't
> think of?
> > > >
> > > > need a workable alternative. Key generation on devices is
> > > > something that is being used - and may be even more used in the
> > > > future the more we get special hardware support for storing keys.
> > >
> > > For 2, the client configures the name of the key (in <running>).
> > > Then the client invokes the action (in <operational>).  The device
> This is a very good question.  Why don't we have actions for "create-interface',
> "create-user" or "create-acl"?  In all these cases we have config that a device
> internally parses and translates to some internal procedure (perhaps ifconfig,
> adduser, iptables etc).

For me, the ideal goal is that the configuration is intent based.  I.e. rather than telling the device what sequence of steps it should perform, it is telling the device what state the device should be trying to get into.

So for an interface, the intent of the interface configuration is "I want interface XXX to exist on the device, be enabled, have this IPv4 address configured on it".  As a client, I don't care what internal steps the device needs to take to reach this state, if it gets to this desired state.  Similarly, if something transiently goes wrong on the device, then it should always try to recover towards the desired state expressed in the intended configuration.

I think that users is a slightly orthogonal issue.  I think that the external primary manageability key for users should be unique usernames.  Certainly, whenever I log into any machine it is my username that I use to identify myself.  When I look folks up in the directory I do it via their name, not their userid.  In some cases, it might be desirable to use the same userid across multiple machines.  This can be achieved by having extra optional configuration to express this.  Otherwise, I think that userids should primarily be treated as internal user identifiers that need to persisted along with any files associated with the user.

> *when* the key is generated.  We cannot copy & paste some config to another
> device and expect it to work exactly the same.  OTOH that probably is true for
> other things as well; if a user has been created in the config there might be files
> owned by that user stored in the home directory.
> 
> Also, we might need the option to re-generate the key (even though the current
> version doesn't support this).  But *this* could be done w/ an action (if we need
> to support it).

Exactly.  Using an action to regenerate an internally managed key is fine.  This is equivalent to an action to reboot a linecard or clear some statistics.  This hasn't changed the intent of what the desired state the system should be in.

The alternative to the action would be to remove the config, wait until the device has confirmed that the key is removed (in operational), and then configure it again.

> 
> What did I miss; what makes this case special so that it can't be handled like
> other config?

For me, I think that the special cases are:
 (i) The ability to force a key to be recreated (i.e. the action described above)
 (ii) The ability to program a client defined key pair in a private way that is not visible in the configuration.  Have we considered a solution that puts these into the configuration but has them encrypted with a device specific public/private key pair.

Thanks,
Rob

---

From: tom petch <[email-masked]>
Date: Fri, 3 May 2019 10:48:20 +0000

----- Original Message -----
From: "Martin Bjorklund" <[email-masked]>
Sent: Friday, May 03, 2019 7:47 AM

> > > > > > Correct, as I didn’t think there was consensus yet.  Perhaps
there
> > > > > > Okay, so how about this, based on this thread, there appears
to be
> > > > do you have any proposal how to support the requirement to
generate a
> > > > need a workable alternative. Key generation on devices is
something
> > > For 2, the client configures the name of the key (in <running>).
Then
> > > the client
> > > invokes the action (in <operational>).  The device generates a new
key
> > > pair
> > > (perhaps in tpm-hw).  In <operational>, the public key is now
visible
> > > and the

If I configure an interface, I am providing at least part of the
information and anything that the device generates - interface name,
MTU, privacy address - I can then see and may or may not be able to
change.

When I generate a key pair, yes I want to see the public key but I have
no interest in the private key.  I want the device, and it is the device
not an individual user, to be able to do things with the private key,
notably to generate a certificate for the device; I now see
organisations where every device that is attached to the network must
have its own certificate regardless of what the device is, who owns it,
who is logged onto it etc.

So generate a key pair, keep the private private, use it for a
certificate, but I will never change it, don't want to know it is, I
just want it securely hidden - and it is unlikely that the notepad,
smartPhone, laptop etc will have a TPM.

This is the policy of the most security-conscious organisation I know,
the only one whose passwords would meet the criteria laid down in RFC,
but it has only been around for a year or so so I expect others will
follow suit.

Tom Petch

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Fri, 3 May 2019 11:00:02 +0000

Hi Tom,

Thanks for the insight.  Some comments inline ...

> From: tom petch <[email-masked]>
> Sent: 03 May 2019 11:48
> To: Rob Wilton (rwilton) <[email-masked]>; Martin Bjorklund <mbj@tail-
> f.com>
> Cc: [email-masked]
> > we have config that a device internally parses and translates to some
> > internal procedure (perhaps ifconfig, adduser, iptables etc).
> >
> information and anything that the device generates - interface name, MTU,
> privacy address - I can then see and may or may not be able to change.
> 
> When I generate a key pair, yes I want to see the public key but I have no
> interest in the private key.  I want the device, and it is the device not
> an individual user, to be able to do things with the private key, notably
> to generate a certificate for the device; I now see organisations where
> every device that is attached to the network must have its own certificate
> regardless of what the device is, who owns it, who is logged onto it etc.
> 
> So generate a key pair, keep the private private, use it for a certificate,
> but I will never change it, don't want to know it is, I just want it
> securely hidden - and it is unlikely that the notepad, smartPhone, laptop
> etc will have a TPM.
> 
> This is the policy of the most security-conscious organisation I know, the
> only one whose passwords would meet the criteria laid down in RFC, but it
> has only been around for a year or so so I expect others will follow suit.

This is all fine and sounds sensible to me.

The public key can be published in <operational>.

But why does there need to be a separate YANG action required to generate the public/private key pair on the device?

Why is the configuration intent of "I want you to use a securely allocated public/private key pair" (which could be in the configuration) not sufficient?

If the issue is that these keys need to persist over device restart, then I would think that the solution is for the device to securely persist these keys independently of the YANG configuration.

Thanks,
Rob

---

From: tom petch <[email-masked]>
Date: Fri, 3 May 2019 11:31:38 +0000

---- Original Message -----
From: "Rob Wilton (rwilton)" <[email-masked]>
To: "tom petch" <[email-masked]>; "Martin Bjorklund"
<[email-masked]>
Cc: <[email-masked]>
Sent: Friday, May 03, 2019 12:00 PM
Subject: RE: [netconf] ietf crypto types - permanently hidden

> > > > > > > > is rough-consensus, and it may be that the only way to
gauge
> > that
> > > > > > > I (still) object to this.  Actions shouldn't create
config.
> > We
> > > > > > > model.  Not good.  In RESTCONF, the generic methods
support
> > things
> > > > > > configuration model? Do you propose that the action/rpc
returns
> > the
> > > > > > back to the server and somehow matched to the key that is
cached
> > on
> > > > > > I think I would be happy to not have this special hack but
then
> > we
> > > > > > that is being used - and may be even more used in the future
the
> > more
> > > > >   2.  The client asks the device to generate a "hidden" key
which
> > may
some
> > information and anything that the device generates - interface name,
MTU,
> > So generate a key pair, keep the private private, use it for a
certificate,
> But why does there need to be a separate YANG action required to
generate the public/private key pair on the device?

How else is the key pair going to come into existence?  The device is
not shipped with one (although it is the sort of the thing that a
Microsoft might organise if it becomes the norm).  A user (with suitable
credentials) brings in his device, the organisation says 'generate key
pair', and certificate, and the user is then good to go for however long
they use the organisation's network, could be years; and yes, the public
key, and certificate, must persist in the device across restarts but
not, of course, if the hardware is replaced by fresh hardware - it is a
device certificate, not a user certificate.

Tom Petch

> Why is the configuration intent of "I want you to use a securely
allocated public/private key pair" (which could be in the configuration)
not sufficient?
>
> If the issue is that these keys need to persist over device restart,
then I would think that the solution is for the device to securely
persist these keys independently of the YANG configuration.

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 03 May 2019 13:37:43 +0200 (CEST)

"Rob Wilton (rwilton)" <[email-masked]> wrote:
> > "create-interface',
> For me, the ideal goal is that the configuration is intent based.

Absolutely.  These were rhetorical questions.

> I.e. rather than telling the device what sequence of steps it should
> perform, it is telling the device what state the device should be
> trying to get into.
> 
> So for an interface, the intent of the interface configuration is "I
> want interface XXX to exist on the device, be enabled, have this IPv4
> address configured on it".  As a client, I don't care what internal
> steps the device needs to take to reach this state, if it gets to this
> desired state.  Similarly, if something transiently goes wrong on the
> device, then it should always try to recover towards the desired state
> expressed in the intended configuration.
> 
> I think that users is a slightly orthogonal issue.  I think that the
> external primary manageability key for users should be unique
> usernames.  Certainly, whenever I log into any machine it is my
> username that I use to identify myself.  When I look folks up in the
> directory I do it via their name, not their userid.  In some cases, it
> might be desirable to use the same userid across multiple machines.
> This can be achieved by having extra optional configuration to express
> this.  Otherwise, I think that userids should primarily be treated as
> internal user identifiers that need to persisted along with any files
> associated with the user.
> 
> > 
> > *another
> > current
> Exactly.  Using an action to regenerate an internally managed key is
> fine.  This is equivalent to an action to reboot a linecard or clear
> some statistics.  This hasn't changed the intent of what the desired
> state the system should be in.
> 
> The alternative to the action would be to remove the config, wait
> until the device has confirmed that the key is removed (in
> operational), and then configure it again.

Not very nice, since you may have leafrefs to the keys that would have
to be removed as well, and so on.

>  (i) The ability to force a key to be recreated (i.e. the action

Ok.

>  (ii) The ability to program a client defined key pair in a private way
>  that is not visible in the configuration.  Have we considered a
>  solution that puts these into the configuration but has them encrypted
>  with a device specific public/private key pair.

I don't think so.  I'm not sure this itself solves the problem
though.  FWIW, we have tailf-specific types that work like this.  They
are similar to iana-crypt-hash in syntax and semantics, but they use
encryption rather than hashing.

/martin

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Fri, 3 May 2019 13:46:42 +0000

Hi Tom, 

> Sent: 03 May 2019 12:32
<snipped>
> How else is the key pair going to come into existence?  The device is not
> shipped with one (although it is the sort of the thing that a Microsoft
> might organise if it becomes the norm).  A user (with suitable
> key, and certificate, must persist in the device across restarts but not,
> of course, if the hardware is replaced by fresh hardware - it is a device
> certificate, not a user certificate.

Sorry, I still don't get it, I'm missing something 😉

list crypto-keys {
  config true;
  key "name";
  leaf "name" { type string; }
  choice key-type {
     case explicit {
        leaf private-key { type binary; }
        leaf public-key { type binary; }
     }
     case auto-generated {
        leaf auto-generated { type boolean; default false; }
        leaf public-key { type binary; config false; }
     }
  }
}

If the client configures an entry in the list with explicit keys then that is what the server uses.

However, if the client configures an entry in the list with leaf "auto-generated" set that the device generates a public/private key pair and persists them internally.  The public-key is available via the config false leaf.  The private key is kept private.  No separate YANG action is required to instantiate the keys - it happens automatically due to the configuration.  What is the obvious step that I am missing as to why this doesn't work? 😉

Thanks,
Rob

> then I would think that the solution is for the device to securely persist
> these keys independently of the YANG configuration.
> >
> > Thanks,
> > Rob
> >
> >
> > >
> > > Tom Petch
> > >
> > > > /martin
> > > >

---

From: Kent Watsen <[email-masked]>
Date: Fri, 3 May 2019 16:09:55 +0000

> I don't think the last column is less important.  That's the TPM case, right?

Yes, the last column is the TPM case, which are very important to support, but there's a subtly between:

a) there exists a TPM that the manufacturer uses to generate a protected private key, e.g., in order to pre-provision the device with an IDevID certificate.  (this is a hyper-critical use case to support)

and

b) there exists a TPM that average clients can use to generate a protected private key.  The motivation behind this is unclear to me, but perhaps because 1) the owner wants to use an LDevID certificate instead of the IDevID certificate, 2) the owner requires that the private key is TPM-protected, and 3) the device is unable to generate a second CSR using the same private key used for the IDevID certificate.  (given that I believe #3 SHOULD be supported, this use case seems less important, bordering on not important).

> the upper left cell in table above.

We have to envision different classes of clients: regular-access and special-access.  Regular access clients should be able to ask the system the generate a private key to which they have no read-access.  Special access clients have read (and write) access, but presumably are only ever used to perform backup/restore operations.

> client would use install-key.

Yes, this is the goal, to enable not-hidden keys to be migrated to another device (but only by a special-access client).

Kent // contributor

---

From: Kent Watsen <[email-masked]>
Date: Fri, 3 May 2019 16:15:26 +0000

> encryption rather than hashing.

Encrypting "hidden" keys is a viable option that would enable such keys to appear in standard config and hence support the "document model" (backup/restore operations using, e.g., <copy-config>).  The only catch is that the restore-operation *only* works on the same device (or, more specifically, the same crypto-processor).  Still, this would help the scenario where the device needs to be restored after having its non-volatile memory reformatted or replaced.

I was also thinking about the relation to crypt-hash, but the scenarios is different in that the crypt-hash operation is idempotent; passing in a "$0$" prefixed password will always produce the same result.  In the "best practice" scenario, no private-key data is passed in, and just asking the device to generate a random key each time will give different results each time (not idempotent).

Kent // contributor

---

From: Kent Watsen <[email-masked]>
Date: Fri, 3 May 2019 16:23:40 +0000

I had an idea last night that might inch us closer to a solution.  

Essentially, the generate/install-key operations always populate <operational>, even for keys that are not-hidden, but then a follow-up operation (something like <copy-config>) replicates the not-hidden key in <operational> to <running>.    Two options:

1) A regular-access admin executes the actions to generate the key, get a CSR, configure a resulting signed certificate, etc. and then, as a second step later in time, a special-access admin replicates the key to <running> (perhaps using standard <get-confg> and <edit-config>), so that it can be included in a standard backup and restored to *any* device (since this key is "not-hidden", it isn't encrypted with a device-specific key and hence can be migrated).

2) A regular-access admin executes the actions to generate the key, get a CSR, configure a resulting signed certificate, etc. and then, as a second step (ideally immediately after), the regular-access admin executes a command like <copy-config>, but rather than copying the entire datastore, it just copies a subtree.   

Neither option seems great.  #1 is unappealing being it necessitates coordination between clients.  #2 is unappealing because defining a generic operation for this special case seems too much.   

IMO, allowing <generate-key> to create the configuration directly is the only client-friendly answer.

Kent // contributor

---

From: Kent Watsen <[email-masked]>
Date: Fri, 3 May 2019 21:48:10 +0000

[WARNING: wide-screen needed]

> IMO, allowing <generate-key> to create the configuration directly is the only client-friendly answer.

Speaking of friendly solutions, the current solution struggles on another point too.  In particular, it is troubling that public-key-grouping and asymmetric-key-grouping nodes aren't "mandatory true".  The reason these fields are not "mandatory true" is captured in ietf-crypto-types:

       [These] nodes are not
       mandatory because they MAY be defined in <operational>.
       Implementations SHOULD assert that these values are
       either configured or that they exist in <operational>.";

How did we get here?   

1) We needed to support manufacturer-generated private key and IDevID certificate, which would be in <operational> with origin="system" and, in order to support leafrefs to the manufacturer-generated IDevID cert, we said that the client needs to create an "overlay" key in <running> (by "name" only).   [note that this was after exploring a solution using "require-instance false"]

2) We felt that, in order to use the `generate/install-hidden-key` actions, the "config true" parent node should be created first and then these actions would only populate descendent values in <operational>.

To recap, following is an abbreviated version of what's in the current keystore draft:

     +--rw keystore
        +--rw asymmetric-keys
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm?                             <--- optional?
              +--rw public-key?                            <--- optional?
              +--rw private-key?           union           <--- optional?   (note union)
              +---x generate-hidden-key
              +---x install-hidden-key
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

This seems messy.  Let's reconstruct the solution from basics, and build up from there...

First, assuming no hidden-keys or special actions, we would have this:

     +--rw keystore
        +--rw asymmetric-keys
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm                             <--- not optional.
              +--rw public-key                            <--- not optional.
              +--rw private-key            binary         <--- not optional.   (note binary)
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

Note that the private-key type is just "binary", because there isn't a need for a union with the "permanently-hidden" value.

Now, adding back support for manufacturer-generated private key and IDevID certificate (but WITHOUT the ability for clients to create their own TPM-protected keys), we could have this:

     +--rw keystore
        +--rw asymmetric-keys
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm                             <--- not optional.
              +--rw public-key                            <--- not optional.
              +--rw private-key         ct:private-key    <--- not optional.   (note ct:private-key)
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

There are two differences:
  - the private key type is changed (more on that below)
  - there's an implicit assumption that the manufacturer-generated private key and IDevID
    certificate will initially only exist in <operational> (w/ origin="system") and that
    the client MUST first COPY those values into <running> before they can be referenced
    by configuration.

Regarding the "ct:private-key" type, rather then using the "union" we have today (between a binary value and the string "permanently-hidden"), it would be better to accommodate the recently-discussed idea that the device MAY be able to encrypt the TPM-protected private key.  For instance:

   typedef private-key {
     type union {
       type binary;    // the real value of the private key
       type string {
         pattern '<encrypted by="*">[A-Za-z0-9+/]+[=]*' {
           description
             "Used for hidden-keys the device is able to encrypt.
              The base64-encoded encrypted private key, prefixed by
              the sting '<encrypted by=\"*\">', where the 'by' value
              is a device specific value that might represent, e.g.,
              the device's serial number, the TPM's serial number,
              and/or the specific key identifier within the TPM.";
         }
       }
       type enumeration {
         enum permanently-hidden {
           description
             "Used for hidden-keys the device is unable to encrypt.";
         }
       }

     }
   }

Now let's add back the ability for a client to request a "not-hidden" key to be created (note: we only need the 'generate' action, since <edit-config> is effectively the same as an 'install' action):

     +--rw keystore
        +--rw asymmetric-keys
           +--x generate-key      <-- LOOK HERE
           |  +--w input
           |     +--w name         // "name" MUST NOT conflict with any other name in use
           |     +--w algorithm
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm 
              +--rw public-key
              +--rw private-key 
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

Note that the action has been added to the parent "container", to avoid to need for the client to first have to create the "asymmetric-key" in <running>.  Now let's discuss what this action does.  Two options:

1) it generates values in <running>.  This is most friendly, but gives some folks heartburn ;)
2) it generates values in <operational>, thus necessitating that the client MUST first COPY
   those values into <running> before they can be referenced by configuration.  Note that
   this is exactly the same language used above, with respect to a manufacturer-generated
   private key and IDevID certificate.

If we stopped here, I think we'd have a go-to-market solution, but let's enable `generate-key` to be able to create a "hidden" key:

     +--rw keystore
        +--rw asymmetric-keys
           +--x generate-key
           |  +--w input
           |     +--w name
           |     +--w hidden?    boolean  {hidden-keys-supported}?     <--- LOOK HERE
           |     +--w algorithm
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm 
              +--rw public-key 
              +--rw private-key
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

Now the only thing left is the ability to install a hidden key, which could be supported as follows:

     +--rw keystore
        +--rw asymmetric-keys
           +--x generate-key
           |  +--w input
           |     +--w name
           |     +--w hidden?    boolean  {hidden-keys-supported}?
           |     +--w algorithm
           +--x install-hidden-key  {hidden-keys-supported}?     <-- NOTE "hidden" in name and
           |  +--w input                                             no "hidden" input param...
           |     +--w name
           |     +--w algorithm
           |     +--w public-key 
           |     +--w private-key
           +--rw asymmetric-key* [name]
              +--rw name
              +--rw algorithm 
              +--rw public-key 
              +--rw private-key 
              +---x generate-certificate-signing-request
              +--rw certificates
                 +--rw certificate* [name]

Presumably how this action works would be similar to how the `generate-key` action works.

This is what I think we should do.

Kent // contributor

---

From: tom petch <[email-masked]>
Date: Sat, 4 May 2019 11:55:25 +0000

----- Original Message -----
From: "Rob Wilton (rwilton)" <[email-masked]>
To: "tom petch" <[email-masked]>; "Martin Bjorklund"
<[email-masked]>
Cc: <[email-masked]>
Sent: Friday, May 03, 2019 2:46 PM

> > > > When I generate a key pair, yes I want to see the public key but
I
> > have no
> > > > an individual user, to be able to do things with the private
key,
> > notably
> > > > to generate a certificate for the device; I now see
organisations
> > where
> > > > regardless of what the device is, who owns it, who is logged
onto it
> > etc.
> > > > securely hidden - and it is unlikely that the notepad,
smartPhone,
> > laptop
> > > > only one whose passwords would meet the criteria laid down in
RFC,
> > but it
> > > > has only been around for a year or so so I expect others will
follow
> > suit.
not,
> However, if the client configures an entry in the list with leaf
"auto-generated" set that the device generates a public/private key pair
and persists them internally.  The public-key is available via the
config false leaf.  The private key is kept private.  No separate YANG
action is required to instantiate the keys - it happens automatically
due to the configuration.  What is the obvious step that I am missing as
to why this doesn't work? 😉

Rob

I am wanting an action, generate key pair, that I can invoke, as opposed
to e.g. install hidden key.

The scenario I describe is an operational one, the user has a
configured, working device but the network it is now going to be used on
requires that a certificate be generated, which, yes, comes under the
general heading of OAM but is to me a different kind of configuration
compared to the initial configuration or updates driven by other
changes.

And I did comment earlier that I find the references to hidden and to
generate hidden misleading.  What I see generated is always a key pair,
not one half of a key pair. I do find the terminology mutating in a way
that seems unclear to me, something I may comment on once the
functionality has been agreed.

Tom Petch
> > then I would think that the solution is for the device to securely
persist

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Tue, 7 May 2019 11:36:36 +0000

Hi Kent,

The problem that I have with <generate-key> generating configuration directly in <running> is that <running> on the device is now different from what the management system thinks should be in <running> on the device.

I.e. it breaks the architectural simplicity that it is only the client that controls what goes into in <running>, e.g. perhaps that can be summarized by this flow:

"Update client's desired    ->   "Push to
config"                         <running>"
          ^                        |
          |                        \/
"Client notified of         <-   "Apply config,
changes in <operational>"       <operational> updated"

However, I would not be opposed to allowing <generate-key> create configuration that is persisted separately from <running> and injected into <intended> (e.g. merged with <running>), hence allowing leaf-refs in config validation to work as expected.  I think that this would allow device reboot to work as expected.

If the clients would like to see the keys in the configuration then they can monitor <operational> (or <intended>), and then add the keys, either in raw form, or encrypted in some way.  But I still think that it is architecturally cleaner if it is always the client that updates the <running> configuration and never the device.

Thanks,
Rob

Sent: 03 May 2019 17:24
To: [email-masked]

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Tue, 07 May 2019 14:19:26 +0200 (CEST)

"Rob Wilton (rwilton)" <[email-masked]> wrote:
> Hi Kent,
> 
> The problem that I have with <generate-key> generating configuration
> directly in <running> is that <running> on the device is now different
> from what the management system thinks should be in <running> on the
> device.
> 
> I.e. it breaks the architectural simplicity that it is only the client
> that controls what goes into in <running>, e.g. perhaps that can be
> summarized by this flow:
> 
> However, I would not be opposed to allowing <generate-key> create
> configuration that is persisted separately from <running> and injected
> into <intended> (e.g. merged with <running>)

But this isn't really allowed by the architecture in 8342, imo.  If
this would have been the case, we'd have another box with config going
into "intended".  8342 allows "configuration transformations" between
running and intended.

> , hence allowing leaf-refs
> in config validation to work as expected.  I think that this would
> allow device reboot to work as expected.
> 
> If the clients would like to see the keys in the configuration then
> they can monitor <operational> (or <intended>), and then add the keys,
> either in raw form, or encrypted in some way.  But I still think that
> it is architecturally cleaner if it is always the client that updates
> the <running> configuration and never the device.

I agree.  I think it would be worthwile to explore the
"non-action-based" solution that Rob proposed.  Is there anything in
that solution that doesn't work?

/martin

> Essentially, the generate/install-key operations always populate
> <operational>, even for keys that are not-hidden, but then a follow-up
> operation (something like <copy-config>) replicates the not-hidden key
> in <operational> to <running>.  Two options:
> 
> 1) A regular-access admin executes the actions to generate the key,
> get a CSR, configure a resulting signed certificate, etc. and then, as
> a second step later in time, a special-access admin replicates the key
> to <running> (perhaps using standard <get-confg> and <edit-config>),
> so that it can be included in a standard backup and restored to *any*
> device (since this key is "not-hidden", it isn't encrypted with a
> device-specific key and hence can be migrated).
> 
> 2) A regular-access admin executes the actions to generate the key,
> get a CSR, configure a resulting signed certificate, etc. and then, as
> a second step (ideally immediately after), the regular-access admin
> executes a command like <copy-config>, but rather than copying the
> entire datastore, it just copies a subtree.
> 
> Neither option seems great.  #1 is unappealing being it necessitates
> coordination between clients.  #2 is unappealing because defining a
> generic operation for this special case seems too much.
>

---

From: "Rob Wilton (rwilton)" <[email-masked]>
Date: Tue, 7 May 2019 13:34:20 +0000

> Sent: 07 May 2019 13:19
> Cc: [email-masked]; [email-masked]
> But this isn't really allowed by the architecture in 8342, imo.  If this
> would have been the case, we'd have another box with config going into
> "intended".  8342 allows "configuration transformations" between running
> and intended.

I'm not sure.  The definition of a configuration transformation is quite broad:
   o  configuration transformation: The addition, modification, or
      removal of configuration between the <running> and <intended>
      datastores.  Examples of configuration transformations include the
      removal of inactive configuration and the configuration produced
      through the expansion of templates.

In the NMDA discussions, we considered the idea of a template on the device that injects configuration into intended, and this case doesn't seem miles away from there.

However, I'm not sure that now is the right time for a discussion for what transformations between <running> and <intended> are allowed.  If we can agree on a solution that doesn't require it, and doesn't update <running>, then I would probably be OK with that as well.

> I agree.  I think it would be worthwile to explore the "non-action-based"
> solution that Rob proposed.  Is there anything in that solution that
> doesn't work?
> 
> 
> /martin

Thanks,
Rob

---

From: Kent Watsen <[email-masked]>
Date: Tue, 7 May 2019 21:13:44 +0000

>> that controls what goes into in <running>

I'm confused.  At least it seems that, regardless if the client uses <edit-config> or <generate-key>, the client is performing the operation and can be fully aware of what it is <running>.  For other clients, presumable they receive a yang-push notification alerting them to the update to <running>.

Before I thought the objection regarded non-compliance to the document model, but that's not true in that, once the configuration is set (via an action), it becomes part of the document, even if nacm:default-deny-all.

Now I'm unclear what the objection is.  Martin has twice identified some issues, and both times I replied that it is acceptable to constrain the actions so as to avoid those issues.

> that solution that doesn't work?

I discussed this option in my "wide-screen needed" email from last Friday.
There are 3 cases to consider:

1) the manufacturer creates the (most likely "hidden") key pair and associated certificate.
      - these nodes MUST originate in <operational> (origin="system")
      - clients MUST replicate their (potentially encrypted or "permanently-hidden"
        enumerated) content into <running> in order reference the key and/or cert.

2) the client wishes to generate a key (hidden or not) without ever touching the
    private key.
      - presumably this occurs via a "generate-key" action (open to ideas)
      - this key ultimately MUST be in <running> in order to be referenced by config.
      - ideally it shows up in <running> as consequence of invoking the action.
      - less ideal, as in (1), a <get-data>/<edit-data> sequence could be used
        to bring the key into <running>.

3) the client wished to installed a hidden key.
      - note that we don't discuss installing a non-hidden key here, because
        that is exactly what a standard <edit-config> operation does.
      - presumably this occurs via a "install-key" action (open to ideas)
      - this is a weird case because the client is initially okay with touching the
        private key, but thereafter wants it to be protected by the system.
      - again, as with (2), ideally the key shows up in running as consequence
        of the action, but a round-trip could also get it there.

Kent // contributor

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Wed, 8 May 2019 07:46:22 +0200

>         enumerated) content into <running> in order reference the key and/or cert.

The question is what or how much needs replication. We refer to
hardware interfaces created by the manufacturer (and identified during
system startup - or during hotplug procedures) by having a name
binding of config in <running> to operational state in <operational>.
If you configure eth0, then this config binds to an <operational>
interface with the same name. So if there is a key pair created by the
vendor, perhaps all we need is a kind of a name that can be used to
bind the config to the key.
 
>       - this key ultimately MUST be in <running> in order to be referenced by config.

Perhaps the question is whether this is 'the key' or 'the name of the
key'.

>         to bring the key into <running>.

Would it help if "generate-key" simply returns a name for the new key?

/js

---

From: Kent Watsen <[email-masked]>
Date: Sat, 11 May 2019 16:18:38 +0000

Hi Juergen,

> bind the config to the key.

True, it could to a handle, but it's unclear what the handle would be.  We'd probably have to create one just to resolve this issue.

> Perhaps the question is whether this is 'the key' or 'the name of the

Same as above.

> Would it help if "generate-key" simply returns a name for the new key?

Perhaps, I'd have to think through it more but, first, I want to dig a little more on the "crypt-hash" approach (see below).

>>        of the action, but a round-trip could also get it there.

Switching gears, I'd like to explore more the idea of reverting the 3-tuple back to "mandatory true" as discussed here: https://mailarchive.ietf.org/arch/msg/netconf/P-xcpHqUNq3LfX5meOCpNQMJusY but, instead of using `action` statements, perhaps we can use something similar to "crypt-hash".

From RFC 7317:

     typedef crypt-hash {
       type string {
         pattern
           '$0$.*'
         + '|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}'
         + '|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}'
         + '|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}';
       }
       description
         "The crypt-hash type is used to store passwords using
          a hash function.  The algorithms for applying the hash
          function and encoding the result are implemented in
          various UNIX systems as the function crypt(3).

          A value of this type matches one of the forms:

            $0$<clear text password>
            $<id>$<salt>$<password hash>
            $<id>$<parameter>$<salt>$<password hash>

          The '$0$' prefix signals that the value is clear text.  When
          such a value is received by the server, a hash value is
          calculated, and the string '$<id>$<salt>$' or
          $<id>$<parameter>$<salt>$ is prepended to the result.  This
          value is stored in the configuration data store.
     <snip/>

Note that the last sentence says "stored in the configuration data store".
So how about this (note: all 3 values are "mandatory true"):

    leaf algorithm {
      nacm:default-deny-write;
      type asymmetric-key-algorithm-ref;
      mandatory true;
      description
        "Identifies the key's algorithm.";
    }

    leaf public-key {
      nacm:default-deny-write;
      type union {
        type binary;
        type string {
          pattern
          + '<value-to-be-generated(-and-hidden)?>'
          + '|<value-to-be-hidden>[A-Za-z0-9+/]+[=]{1,3}';
        }
      mandatory true;
      description
        "
        Binary is used for a standard configuration value.

        Prefix values are used to support special use-cases as follows:

          <value-to-be-generated(-and-hidden)?>

            An input value that is used to request the system to 
            generate the key-pair.

            Without the optional '-and-hidden' postfix, the generated
            key pair is stored in the configuration data store.  This
            is used to support the security best practice use case
            whereby the client doesn't touch the private key.

            With the optional '-and-hidden' postfix, the key pair is
            generated in such a way that it will thereafter be reported
            either using '<permanently-hidden>' or '<encrypted by='*'>'.            
            
            When the '<value-to-be-generated(-and-hidden)?>' prefix is
            used, it MUST be used in both the 'public-key' and 'private-
            key' values.

          <value-to-be-hidden>[A-Za-z0-9+/]+[=]{1,3}

            An input value that is used to request the system to 
            store the provided key-pair in such a way that it will
            thereafter be reported either as '<permanently-hidden>'
            or '<encrypted by='*'>*'.

            Following the prefix is the base64-encoded value of the
            public key.

            When the '<value-to-be-hidden>' prefix is used, it MUST be 
            used in both the 'public-key' and 'private-key' values.
        ";
    }

    leaf private-key {
      nacm:default-deny-all;
      type union {
        type binary;
        type string {
          pattern
            '<permanently-hidden>'
          + '|<encrypted by="*">[A-Za-z0-9+/]+[=]{1,3}'
          + '|<value-to-be-generated(-and-hidden)?>'
          + '|<value-to-be-hidden>[A-Za-z0-9+/]+[=]{1,3}';
        }
      mandatory true;
      description
        "
        Binary is used for a standard configuration value.

        Prefix values are used to support special use-cases as follows:

          <permanently-hidden>

            An output value that is used by the system to indicate
            that the private key value is not available in any form.

          <encrypted by='*'>[A-Za-z0-9+/]+[=]{1,3}

            An output value that is used by the system to indicate
            that the private key value is encrypted using the key
            identified by the 'by' attribute.

            Following the prefix is the base64-encoded value of the
            encrypted private key. 

          <value-to-be-generated(-and-hidden)?>

            An input value that is used to request the system to 
            generate the key-pair.

            Without the optional '-and-hidden' postfix, the generated
            key pair is stored in the configuration data store.  This
            is used to support the security best practice use case
            whereby the client doesn't touch the private key.

            With the optional '-and-hidden' postfix, the key pair is
            generated in such a way that it will thereafter be reported
            either using '<permanently-hidden>' or '<encrypted by='*'>'.

            When the '<value-to-be-generated(-and-hidden)?>' prefix is
            used, it MUST be used in both the 'public-key' and 'private-
            key' values.

          <value-to-be-hidden>[A-Za-z0-9+/]+[=]{1,3}

            An input value that is used to request the system to 
            store the provided key-pair in such a way that it will
            thereafter be reported either as '<permanently-hidden>'
            or '<encrypted by='*'>*'.

            Following the prefix is the base64-encoded value of the
            private key.

            When the '<value-to-be-hidden>' prefix is used, it MUST be 
            used in both the 'public-key' and 'private-key' values.
        ";
    }

Kent // contributor

---

From: Kent Watsen <[email-masked]>
Date: Fri, 24 May 2019 20:18:42 +0000

The message below was sent two weeks ago.   As a matter of expediency, I will assume there are no objections to this "crypt-hash"-like proposal.

Thanks,
Kent  // contributor

> On May 11, 2019, at 12:18 PM, Kent Watsen <[email-masked]> wrote:
> 
> 
> Hi Juergen,
> 
>

---

From: Balázs Kovács <[email-masked]>
Date: Thu, 30 May 2019 09:48:34 +0000

Hi Kent,

In case of crypt-hash, I can accept the extension of the crypt(3) schemes with a $0$ that sort of represents a hash() action, since it matches the original crypt(3) syntax.

In this case, I find it awkward to tell what to do with the data (verbs) as prefixes of the data. I personally preferred actions better for this purpose. I assume that this representation also does not change the matter of "actions" affecting configuration (see 'output' values). Also validation of required input and output seems more complicated to me.

The generate action returning the name of the key or optionally creating configuration sounded so far the closest match to me.

I'm also thinking do we need the 'generate-and-not-hide' and the 'install-and-hide' use cases?

Br,
Balazs

From: netconf <[email-masked]> On Behalf Of Kent Watsen
Sent: Friday, May 24, 2019 10:19 PM
To: [email-masked]
Subject: Re: [netconf] ietf crypto types - permanently hidden

Thanks,
Kent  // contributor

On May 11, 2019, at 12:18 PM, Kent Watsen <[email-masked]<mailto:[email-masked]>> wrote:

Hi Juergen,

Same as above.

/js

    typedef crypt-hash {
      type string {
        pattern
          '$0$.*'

           $0$<clear text password>

   leaf algorithm {
     nacm:default-deny-write;

   leaf public-key {
     nacm:default-deny-write;
     type union {
       type binary;
       type string {
         pattern

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

         <permanently-hidden>

Kent // contributor

_______________________________________________
netconf mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/netconf

---

From: Kent Watsen <[email-masked]>
Date: Thu, 30 May 2019 14:14:22 +0000

Hi Balazs,

> In this case, I find it awkward to tell what to do with the data (verbs) as prefixes of the data.

Agreed, but we seem to be at an impasse and I thought this approach could get us over the line.

> I personally preferred actions better for this purpose.

It is my preference to use actions as well, but there's pushback there.  Maybe we could claim that the pushback is "in the rough" and press ahead regardless, but I'd rather avoid that if possible. 

> I assume that this representation also does not change the matter of “actions” affecting configuration (see ‘output’ values).

You mean, exploring this solution leaves the "is it possible for actions to affect configuration" as unresolved?  - correct, that discussion would remain open.

> Also validation of required input and output seems more complicated to me.

How so?

> The generate action returning the name of the key or optionally creating configuration sounded so far the closest match to me.

Understood.

>  I’m also thinking do we need the ‘generate-and-not-hide’ and the ‘install-and-hide’ use cases?

Actually, I view  ‘generate-and-not-hide’ as a very common case.  That is, ask the system to generate the key (because clients are lazy and security best practice), and let standard NACM rules protect the key.   I think that systems supporting user-generated "hidden" keys will be somewhat rare, to the extent that there should feature statements enabling servers to indicate if they support the ability or not.

---

I'm growing weary of this discussion.  Perhaps we should do even less for the first release of the crypto-types module.  That is, instead of:

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

we have:

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

This removes the "verbs" (as you call them) and thus leaves open possibility for either "verbs" or action statements to be added in some future revision.   This subset still supports the critical use-case of a manufacturer-generated private key for a secure device identifier (i.e., IDevID).    Unfortunately, it does not support the security best practice use-case of having the device generate the private key.  The IESG (Security Directorate) may or may not be okay with this (obviously the shepherd would have to bring it to their attention), but perhaps it's worth testing their resolve and see what happens?

Kent // contributor

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Thu, 30 May 2019 16:47:15 +0200

> This removes the "verbs" (as you call them) and thus leaves open possibility for either "verbs" or action statements to be added in some future revision.   This subset still supports the critical u…

Some comments:

- Not sure what security best practice is and where it is defined.
  Creating the key on the device has the benefit that the key may
  never have to leave the device but it also requires that I can trust
  the device to create good keys. (People recall the glitch that led
  to weak openssh keys on many Linux systems? And given todays world,
  which devices should I trust to generate strong keys?) I might
  decide that creating keys with known software I am willing to trust
  is far better than trusting a key generator shipped by a random
  device manufacturer.

- Side effects are bad and should be avoided. If something requires an
  rpc/action, make it an rpc/action.

- If you create something, give it a name; once things are named (or
  have other unique properties), config can then refer to these named
  objects. A create key operation might simply return a fingerprint
  for the key as the key's name.

/js

---

From: Balázs Kovács <[email-masked]>
Date: Fri, 31 May 2019 07:40:15 +0000

Hi Kent,

How so?

The ‘value-to-be-generated’ “action” would require both the private-key and public-key set to the same, plus the algorithm be configured. Besides, if there is a must statement on any of these, does the must statement consider the ‘input’ or the ‘output’ values? I got a bit confused while thinking on these.

Maybe generate-and-not-hide would be widespread, but it is not my preferred choice of key handling due to that it opens up to the client to manage the key blob after first generation. So maybe all of these should be optional with features?

we have:

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

If so, can you clarify the configuration use case of client configuring <permanently-hidden>, does that produce a valid end-result? Or would that be only an output pattern created as the result of a ‘generate-hidden-key’ action that may be added by an implementation augmenting the model?
Regarding ‘encrypted by’, would that be only used when the device allows to back up encrypted keys to later restore it to same device (or any other that may get hold of the same encryption key in some way)?

Br,
Balazs

From: Kent Watsen <[email-masked]>
Sent: Thursday, May 30, 2019 4:14 PM
To: Balázs Kovács <[email-masked]>
Cc: [email-masked]
Subject: Re: [netconf] ietf crypto types - permanently hidden

Hi Balazs,

How so?

Understood.

---

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

we have:

   leaf private-key {
     nacm:default-deny-all;
     type union {
       type binary;
       type string {
         pattern
           '<permanently-hidden>'

Kent // contributor