Subject: Re: [Netconf] Mandatory local configuration in Keystore groupings

From: Martin Bjorklund <[email-masked]>
Date: Tue, 21 Aug 2018 12:57:09 +0200 (CEST)

Hi,

I have started to look at implementing the client/server/keystore
modules, specifically the SSH server model for NETCONF.  In this
process, I have some comments on the model.

Do we need to support the "local" or inline key configuration at all?
I would prefer to make the keystore model mandatory and remove the
local cases from the client server models.  It seems better from a
security pow to handle all keys in one place in the model, instead of
having (possibly) private keys exposed in various places in the
model.  Also, the keystore has operations to generate new keys, which
the local case doesn't have, so the local case also lacks some
capabilities.  I think the model(s) will be less complex w/o the local
case.  (At the very least, I think there should be a feature
for the local cases, probably your case (2) below).

I am looking at implementing the keystore model on a regular device
for something like OpenSSH.  I don't want to expose the private keys
at all.  I think this is possible, by not implementing ietf-keystore
in the conventional configuration datastores, but only in
<operational>.  New keys can still be generated with the action
"generate-asymmetric-key".  Two questions:

  1)  Is the enum "hardware-protected" really a good name in this
      case?

  2)  Wouldn't it make sense to add a new operation to install an
      existing key into the keystore, with params "name", "algorithm",
      "private-key", "public-key"?

And a question about certificates.  Keys that are proteced by TPM are
not present in the configuration, only in <operational>, right?  If
so, how can I install a certificate for such a key?  Would it be
better if the certificate list was separated from the key list?

/martin

Kent Watsen <[email-masked]> wrote:
> Hi Balazs,
> 
> This issue is (was?) also being discussed here:
> https://mailarchive.ietf.org/arch/msg/netconf/tpmAeH9KLBWF0YglZ8CJmm4MW4o.
> 
> Expanding on (c) on that page, assuming we do this at all, the choices
> are:
> 
>   1: add "if-defined 'not keystore-implemented'" to the "local" choice.
>   This would
>        be a *global* on/off switch, not per use of the grouping.
> 
>   2: add "if-defined 'local-keys-supported'" to the "local" choice.
>   This would be a
>        *global* on/off switch, not per use of the grouping.
> 
>   3: do nothing; let downstream modules augment-in their own if-feature
>   statements
>       for the "choice" statement when the groupings are used.  This would
>       allow define
>        for *local* (not global) on/off switch.
> 
>   4. remove support for keystore being optional to implement.  That is,
>   regarding your
>       comment in the link below to support keys that are not shared, we
>       could require
>        that the keys still exist in keystore and leave it to the application
>        to ensure it doesn't
>        reference such keys more than once.
> 
>       https://mailarchive.ietf.org/arch/msg/netconf/xYYf0NSeT9mgtJ1KH-h7SYLSmXA
> 
> Thoughts?
> 
> Kent
> 
> 
> On 7/4/18, 7:26 AM, "Netconf on behalf of Balazs Lengyel"
> <[email-masked]<mailto:[email-masked]> on behalf
> of [email-masked]<mailto:[email-masked]>>
> wrote:
> 
> 
> Hello Kent,
> I was reading draft-ietf-netconf-keystore-05. I noticed that in the
> groupings
> local-or-keystore-end-entity-certificate-grouping,
> local-or-keystore-asymmetric-key-grouping and
> local-or-keystore-asymmetric-key-with-certs-grouping
> the keystore case is qualified with an
> if-feature "keystore-implemented"
> statement. However the local case is not qualified with if-feature. In
> ,many of our network nodes we want to implement a central keystore,
> and do NOT want to allow local security configuration. So please add
> if-feature "not keystore-implemented"
> or
> if-feature "local-keystore-allowed"
> to the local case of these groupings.
> 
> regards Balazs Lengyel
> 
> --
> 
> Balazs Lengyel                       Ericsson Hungary Ltd.
> 
> Senior Specialist
> 
> Mobile: +36-70-330-7909 email:
> [email-masked]<mailto:[email-masked]>

---

From: Kent Watsen <[email-masked]>
Date: Tue, 21 Aug 2018 17:28:31 +0000

> Do we need to support the "local" or inline key configuration at all?

The two attached slides were presented at the IETF 102 meeting.

The ensuing discussion is captured in lines 279-312 here:
http://etherpad.tools.ietf.org:9000/p/notes-ietf-102-netconf.

> model.

I don't believe there is a security issue.  NACM or equivalent can
be used in either case.

> Also, the keystore has operations to generate new keys, which
> capabilities.

True, but the generate-private-key operation is really only 
intended to be used to direct an HSM (i.e. a TPM) to generate
a key.  

That said, the current action has no input parameter to direct 
the device to use an HSM or filesystem.  Perhaps there is a
need for a feature indicating the device has an HSM?

>  I think the model(s) will be less complex w/o the local

Yes, from the minutes, we want to add the feature "local-keys-supported".

BTW, I think that I misspoke before about it being a global on/off
switch (not per-use).  RFC 7950 says in Section 7.20.2:

   If a prefix is present on a feature name in the boolean expression,
   the prefixed name refers to a feature defined in the module that was
   imported with that prefix, or the local module if the prefix matches
   the local module's prefix.  Otherwise, a feature with the matching
   name MUST be defined in the current module or an included submodule.

So, if ietf-keystore.yang has this (note the "local-keys-supported"):

  grouping local-or-keystore-asymmetric-key-grouping {
    description
      "A grouping that expands to allow the key to be either stored
       locally within the using data model, or be a reference to an
       asymmetric key stored in the keystore.";
    choice local-or-keystore {
      mandatory true;
      if-feature "local-keys-supported";
      case local {
        uses asymmetric-key-pair-grouping;
      }
      case keystore {
        if-feature "keystore-implemented";
        leaf reference {
          type ks:asymmetric-key-ref;
          mandatory true;
          description
            "A reference to a value that exists in the keystore.";
        }
      }
      description
        "A choice between an inlined definition and a definition
         that exists in the keystore.";
    }
  }

and that grouping is used by the "ssh-server-grouping" in 
ietf-ssh-server.yang, which it is, and that grouping is used by the 
"netconf-server-grouping" in ietf-netconf-server.yang, which it is, 
and that grouping is used by some application-level module called 
"example-foo-bar.yang" that defines prefix "fb", then it seems that
maybe the foo-bar module could itself define a feature called 
"local-keys-supported" to control the underlying feature?

> "generate-asymmetric-key".

Keystore can be implemented in both datastores.  Keys created by the
action are only present in <operational>.  The last sentence of
the action's description statement says this.

> Two questions:

As opposed to what?  In -02, this enum was called "INACCESSIBLE", 
and in -01 there was another enum called "RESTRICTED" with description
statement "The private key is restricted due to access-control".
  
We removed RESTRICTED because we said it was an access-control 
implementation thing as to how filtered-out nodes are represented 
(e.g., a dummy parameter or just missing).  And we changed 
INACCESSBLE to hardware-protected in an attempt to be more specific.

Reaching back in time, there was a thread where we discussed the 
need to support backup/restore workflows, and then a subsequent 
discussion about those keys needing to be editable outside a 
recovery session (Security Considerations on page 22). Thus, we
reasoned the only time the private key is truly not available is
when it's being shielded by something outside the control of the
system, which led us to "hardware".

>      "private-key", "public-key"?

Unsure what you mean.  Currently all these values are configurable.
Or are you trying to find a way to only "configure" them in 
<operational>?

> not present in the configuration, only in <operational>, right?  

Right.

> If so, how can I install a certificate for such a key?  Would it be

The idea is to use the approach that was taken with the I2RS topology
model, using require-instance false.  Specifically, the 
"local-or-keystore-asymmetric-key-with-certs-grouping" has leaf 
"reference" of type "asymmetric-key-ref":

     typedef asymmetric-key-ref {
       type leafref {
         path "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key"
              + "/ks:name";
         require-instance false;
       }
       description
         "This typedef enables modules to easily define a reference
          to an asymmetric key stored in the keystore. The require
          instance attribute is false to enable the referencing of
          asymmetric keys that exist only in <operational>.";
       reference
         "RFC 8342: Network Management Datastore Architecture (NMDA)";
     }

Makes sense?

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 22 Aug 2018 10:24:52 +0200 (CEST)

Hi,

> I don't believe there is a security issue.  NACM or equivalent can

Yes, but it may be desirable to keep all keys in a single place,
instead of scattered around.  But I'm ok with using a feature.

BTW, all private keys should have nacm:default-deny-all.

> intended to be used to direct an HSM (i.e. a TPM) to generate

Editorial issue: the draft uses both names "generate-private-key" and
"generate-asymmetric-key".

> need for a feature indicating the device has an HSM?

I think that this is an implementation choice that doesn't have to be
visible to the operator.  I.e., if there's special hw it will be used,
else a filesystem (or something else) will be used.

> Yes, from the minutes, we want to add the feature "local-keys-supported".

Ok.

> "local-keys-supported" to control the underlying feature?

No, this won't work.  Note the text you quoted:

     Otherwise [no prefix], a feature with the matching
     name MUST be defined in the current module or an included submodule.

the current module is the module that has the if-feature statement,
i.e., ietf-keystore.

But I think a global feature is fine.  Models can always add their own
additional if-fetaure expressions via refinement.

> Keystore can be implemented in both datastores.

Of course.

> Keys created by the

Exactly.

> As opposed to what?

In my use case I would implement "generate-asymmetric-key" and it
would create the keys in the file system, and the public key would be
available in <operational>.  I don't want to expose the private key in
<operational>, so I would have to return "hardware-protected".  But it
isn't hardware protected...

> In -02, this enum was called "INACCESSIBLE", 

I think this is the real issue.  So it might be that my use case of
not wanting to expose private keys at all even if there's no TPM is
explicitly not supported.  I.e., unless there's special hw present,
all private keys MUST be exposed (but NACM-protected).

> Or are you trying to find a way to only "configure" them in 

Yes, *if* my use case of not exposing the private keys is supported,
then it would be useful to be able to generate the keys off-box, and
install them into <operational>.

>          "RFC 8342: Network Management Datastore Architecture (NMDA)";

Isn't the idea that once I have a certificate, I will write it into
/keystore/asymmetric-keys/asymmetric-key/certificates/certificate?

My question is how this is supposed to work for a hardware-protected
key that only exists in <operational>?

/martin

---

From: Kent Watsen <[email-masked]>
Date: Fri, 24 Aug 2018 20:25:55 +0000

> instead of scattered around.  But I'm ok with using a feature.

Yes, let's go with the feature.  I've added it to my local copy.

> BTW, all private keys should have nacm:default-deny-all.

I'd agree if we were only talking about backup/restore operations, 
which match the definition of a "recovery session", but here we're
trying to support workflows that would occur during normal operation
of the device, by administrators having sufficient permission.  The
Security Considerations section provides guidance on this too.

> "generate-asymmetric-key".

fixed.

> I think that this is an implementation choice that doesn't have
> to be visible to the operator.  I.e., if there's special hw it
> will be used, else a filesystem (or something else) will be used.

No, what I meant was that generate-asymmetric-key could take an
input parameter (enum?), protected by a feature, that the client
could use to indicate the key needs to be permanently hidden, or
define the entire RPC to have that behavior?

Regarding the name, s/hardware-protected/permanently-hidden/?

> the current module is the module that has the if-feature statement,

okay.  I was hoping that is could be the module using the grouping.

> additional if-fetaure expressions via refinement.

True.

> isn't hardware protected...

Would "permanently-hidden" be better?

> <snip/>

Now you have me second-guessing this.  Maybe a device, without special
hardware, could present the illusion of a permanently-hidden private
key - it's completely inaccessible from the device's supported 
interfaces, though actually present on the filesystem.

> install them into <operational>.

Hmmm, sounds like *configuration*, not something goes into <operational>.

And, even if you did, that doesn't mean the keys are permanently-hidden.
I suppose the model could let them client set that parameter as well,
but it somewhat defeats to goal of *never* having the private key exposed,
not even as a once in a lifetime kind of thing.  That’s just my opinion,
we should ask for more opinions if you're not convinced.

>> <snip/>

Sorry, I think my example was wrong.  A better example might be the
interfaces example in Section C.3.2 in RFC 8342 [1], where the
configs overlay each other (e.g., matching keys).

For a hardware-protected key, the "asymmetric-key" (in keystore) still
appears in <operational> with an exposed "key" name, the "private-key"
value is set to "hardware-protected".  So the thinking is that a similar
path can be constructed in <intended>, while only adding/configuring the
certificates.

Actually, check out the example in keystore-05 at the end of page 7:

       <asymmetric-key or:origin="or:system">           <--- system generated
         <name>tpm-protected-key</name>
         <algorithm>ct:rsa2048</algorithm>
         <private-key>hardware-protected</private-key>  <--- hw protected
         <public-key>base64encodedvalue==</public-key>
         <certificates>
           <certificate>
             <name>builtin-idevid-cert</name>
             <cert>base64encodedvalue==</cert>
           </certificate>
           <certificate or:origin="or:intended">        <--- configured cert
             <name>my-ldevid-cert</name>
             <cert>base64encodedvalue==</cert>
           </certificate>
         </certificates>
       </asymmetric-key>

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 27 Aug 2018 10:21:18 +0200 (CEST)

> Security Considerations section provides guidance on this too.

nacm:default-deny-all means that in order to access this node, the
user needs an explicit rule in NACM that covers this node.  It does
_not_ mean that only a "recovery session" can access the node.

This statement is used in e.g. ietf-system to protect radius shared
secrets, and in ietf-snmp to protect community strings and USM keys.

> define the entire RPC to have that behavior?

I think that the operation "generate-asymmetric-key" only affects
"permanently-hidden" keys, doesn't it?  If the client wants visible
keys, it will configure them in the config datastores.

> Regarding the name, s/hardware-protected/permanently-hidden/?

I think this is better.

> interfaces, though actually present on the filesystem.

This is what I would like to support.

> we should ask for more opinions if you're not convinced.

I'm not convinced either way, actually ;-)  It would be good to hear
other opinions as well.

> path can be constructed in <intended>, while only adding/configuring the

This is what I would expect as well, but the model is not quite
designed for this currently.  For example, suppose I generate a
HSM-protected key with "generate-asymmetric-key".  It is then present
in <operational>, with a public key etc.  Now I want to configure a
certification for this key, so I have to create an entry in the
"asymmetric-key" list, where I have to set both the
private-key and public-key leafs (they are both mandatory); so I
assume I jhave to use the exact values reported in <operational>?

Another design could be to have the certificates in a separate list,
with leafrefs (require-instance false) into the "asymmetric-key"
list.

/martin

---

From: Kent Watsen <[email-masked]>
Date: Mon, 27 Aug 2018 23:48:35 +0000

> > BTW, all private keys should have nacm:default-deny-all.

Updated in my local copy.  Added to the "asymmetric-key-pair-grouping"
grouping, so all downstream users inherit it as well.

> keys, it will configure them in the config datastores.

It wasn't so locked down before.  How about the following two changes?

1. Updated the action's description statement:

      action generate-asymmetric-key {
        description
          "Requests the device to generate an asymmetric key using
           the specified asymmetric key algorithm.  This action is
           used to request the system the generate a key that is
           'permanently-hidden', perhaps because it is protected
           by a cryptographic hardware module.  The resulting
           asymmetric key is considered operational state and
           hence present only in <operational>.";

2. updated the enum's description statement:

          enum "permanently-hidden" {
            description
             "The private key is inaccessible due to being
              protected by the system (e.g., a cryptographic
              hardware module).  It is not possible to 
              configure a permanently hidden key, as a real
              private key value must be set.  Permanently
              hidden keys cannot be archived or backed up.";
          }   

> > Regarding the name, s/hardware-protected/permanently-hidden/?

Okay, but maybe it should be just "hidden"?

> This is what I would like to support.

Okay.

>> I suppose the model could let the client set that parameter as well,

We could define a "load-asymmetric-key" action that has that behavior?

> assume I have to use the exact values reported in <operational>?

Hmmm, using the same value could work, but it doesn't seem intuitive
and, from a general modelling perspective, doesn't scale e.g., what 
if there were 100 descendants?

A couple other options:

 a) make each leaf (algorithm, public-key, private-key) type be a
    union having an enumerated value like "in-operational"

 b) replace the three "mandatory true" with three "must" expressions
    that assert either all or none of the leafs are set.

> with leafrefs (require-instance false) into the "asymmetric-key"

Perhaps, but let's see if we can make this work first.

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Tue, 28 Aug 2018 09:06:48 +0200 (CEST)

Ok.

> Okay, but maybe it should be just "hidden"?

Both work for me.

> We could define a "load-asymmetric-key" action that has that behavior?

Yes; if we decide to support this use case.  What do others think?

> if there were 100 descendants?

Exactly my point.

>     union having an enumerated value like "in-operational"

This feels clumsy and also doesn't really scale.

>     that assert either all or none of the leafs are set.

Better, but also has scaling issues in the general case.

> Perhaps, but let's see if we can make this work first.

Ok, let's look at the alternatives:

(A)

  container keystore {
    container asymmetric-keys {
      list asymmetric-key {
        key name;

        leaf name { ... }
        leaf algorithm { ... }
        leaf public-key { ... }
        leaf private-key { ... }

        must "(algorithm and public-key and private-key)
              or not (algorithm or public-key or private-key)";

        container certificates {
          list certificate { ... }
        }
    }
  }

(B)

  container keystore {
    container asymmetric-keys {
      list asymmetric-key {
        key name;

        leaf name { ... }
        leaf algorithm { mandatory true; ... }
        leaf public-key { mandatory true; ... }
        leaf private-key { mandatory true; ... }

    }

    container certificates {
      list certificate {
        ...
        leaf key {
          leafref {
            path "../../../asymmetric-keys/asymmetric-key/name";
          }
          require-instance false;
          mandatory true;
        }
        ...
      }
    }
  }

I think model B is cleaner.

/martin

---

From: Balázs Kovács <[email-masked]>
Date: Tue, 28 Aug 2018 13:59:47 +0000

Hi,

> >> > Yes, *if* my use case of not exposing the private keys is 
> >> > supported, then it would be useful to be able to generate the 
> >> > keys off-box, and install them into <operational>.
> >> 
> >> I suppose the model could let the client set that parameter as 
> >> well, but it somewhat defeats to goal of *never* having the private 
> >> key exposed, not even as a once in a lifetime kind of thing.
> >> That’s just my opinion, we should ask for more opinions if you're not convinced.
> >

Balazs> Would this action have 'name' and 'private-key' binary input and the purpose to avoid setting the key via configuration and handling it directly in <operational>? Is it an implementation risk to handle the binary input via configuration but not via action?

> > HSM-protected key with "generate-asymmetric-key".  It is then 
> > present in <operational>, with a public key etc.  Now I want to 
> > configure a certification for this key, so I have to create an entry 
> > in the "asymmetric-key" list, where I have to set both the 
> and, from a general modelling perspective, doesn't scale e.g., what if 
> there were 100 descendants?

Exactly my point.

Balazs> In our opinion with Balazs L., we think it would be disadvantageous to change the model by ruining the containment relationship between certificate and corresponding asymmetric key. The action of 'generate-asymmetric-key' is typically something that should have effect on the 'running' configuration too (by setting the mandatory leaves) since the user wants to continue working with the result by deploying certificates or anything else related to the created asymmetric key that needs configuration. 

Balazs L.> In the NMDA RFC it is specifically indicated that actions/rpcs MAY modify the content of other datastores.
https://tools.ietf.org/html/rfc8342#section-6.2
In my view this is a general pattern that an action/rpc creates some configuration that the operator (CLI/Netconf/Restconf) may need to extend or change. In this case the action/rpc shall modify the running config not just operational.

Br,
Balazs K. and Balazs L.

-----Original Message-----
From: Netconf <[email-masked]> On Behalf Of Martin Bjorklund
Sent: Tuesday, August 28, 2018 9:07 AM
To: [email-masked]
Cc: [email-masked]
Subject: Re: [Netconf] Mandatory local configuration in Keystore groupings

Ok.

Both work for me.

> >> Now you have me second-guessing this.  Maybe a device, without 
> >> special hardware, could present the illusion of a 
> >> permanently-hidden private key - it's completely inaccessible from 
> >> the device's supported interfaces, though actually present on the filesystem.
> >
> >> > Yes, *if* my use case of not exposing the private keys is 
> >> > supported, then it would be useful to be able to generate the 
> >> > keys off-box, and install them into <operational>.
> >> 
> >> I suppose the model could let the client set that parameter as 
> >> well, but it somewhat defeats to goal of *never* having the private 
> >> key exposed, not even as a once in a lifetime kind of thing.  
> >> That’s just my opinion, we should ask for more opinions if you're not convinced.
> >

> > HSM-protected key with "generate-asymmetric-key".  It is then 
> > present in <operational>, with a public key etc.  Now I want to 
> > configure a certification for this key, so I have to create an entry 
> > in the "asymmetric-key" list, where I have to set both the 
> and, from a general modelling perspective, doesn't scale e.g., what if 
> there were 100 descendants?

Exactly my point.

(A)

  container keystore {

        leaf name { ... }
        leaf algorithm { ... }
        leaf public-key { ... }
        leaf private-key { ... }

        container certificates {
          list certificate { ... }
        }
    }
  }

(B)

  container keystore {

        leaf name { ... }

    }

    container certificates {
      list certificate {
        ...
        leaf key {
          leafref {

/martin
_______________________________________________
Netconf mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netconf

---

From: Kent Watsen <[email-masked]>
Date: Tue, 28 Aug 2018 19:11:27 +0000

> Would this action have 'name' and 'private-key' binary input and the 
> purpose to avoid setting the key via configuration and handling it 
> directly in <operational>? Is it an implementation risk to handle 
> the binary input via configuration but not via action?

The proposed "load-asymmetric-key" action would take 4 mandatory 
input parameters (name, alg, pub-key, and priv-key) and have no
output other than the key showing up in <operational> with the
private key "permanently-hidden".

To make things clearer, we might rename these actions to:
  - generate-permanently-hidden-asymmetric-key(...)
  - load-permanently-hidden-asymmetric-key(...)

Yes, use of these actions would be more secure since the private key
is thereafter permanently hidden.  If the goal is to have the private
key in configuration, then the action should not be used.

> In our opinion with Balazs L., we think it would be disadvantageous
> to change the model by ruining the containment relationship between
> certificate and corresponding asymmetric key. 

Can you say some more about this?  Is it mostly that the containment
is really intuitive?  That the relationship is linked both ways, 
whereas a leadref only goes one way?

Martin makes a case for 'B', but he also said that my 'b' was "Better"
but has scaling issues in the general case.  Perhaps we don't worry
about the general case here?

> The action of 'generate-asymmetric-key' is typically something that
> should have effect on the 'running' configuration too (by setting 
> the mandatory leaves) since the user wants to continue working with
> the result by deploying certificates or anything else related to 
> the created asymmetric key that needs configuration. 

Okay, but why use an action at all then?  Everything can be done via
standard configuration, right?

Kent // contributor

---

From: Martin Bjorklund <[email-masked]>
Date: Tue, 28 Aug 2018 21:23:38 +0200 (CEST)

Hi,

Balázs Kovács <[email-masked]> wrote:

[...]

> Balazs> In our opinion with Balazs L., we think it would be
> disadvantageous to change the model by ruining the containment
> relationship between certificate and corresponding asymmetric key. The
> action of 'generate-asymmetric-key' is typically something that should
> have effect on the 'running' configuration too (by setting the
> mandatory leaves) since the user wants to continue working with the
> result by deploying certificates or anything else related to the
> created asymmetric key that needs configuration.
> 
> Balazs L.> In the NMDA RFC it is specifically indicated that
> actions/rpcs MAY modify the content of other datastores.
> In my view this is a general pattern that an action/rpc creates some
> configuration that the operator (CLI/Netconf/Restconf) may need to
> extend or change. In this case the action/rpc shall modify the running
> config not just operational.

I think that special actions/rpc that modify config should be avoided
in probably all cases.  The text in 8342 handles generic rpcs like
"edit-data" etc.

*if* you design an action to modify config, it needs to take at least
the datastore as an input parameter.

In this particular case, I see no reason to have a special action to
modify the configuration of keys.

/martin

---

From: Balázs Kovács <[email-masked]>
Date: Wed, 29 Aug 2018 08:22:30 +0000

Hi Kent,

See below.
Br,
Balazs

-----Original Message-----
From: Kent Watsen <[email-masked]> 
Sent: Tuesday, August 28, 2018 9:11 PM
To: Balázs Kovács <[email-masked]>; Martin Bjorklund <[email-masked]>; Balázs Lengyel <[email-masked]>
Cc: [email-masked]
Subject: Re: [Netconf] Mandatory local configuration in Keystore groupings

> directly in <operational>? Is it an implementation risk to handle the 
> binary input via configuration but not via action?

The proposed "load-asymmetric-key" action would take 4 mandatory input parameters (name, alg, pub-key, and priv-key) and have no output other than the key showing up in <operational> with the private key "permanently-hidden".

Yes, use of these actions would be more secure since the private key is thereafter permanently hidden.  If the goal is to have the private key in configuration, then the action should not be used.

Balazs> I preferred the original short name and for me it was clear that this action produces a 'hidden' key. I actually like the idea of changing the 'hardware-protected' enum literal to 'hidden'.

Balazs> I myself just started to realize that you intend to maintain an operational tree that is out-of-sync with the configuration tree. For example, a public key can be determined from the private key. It is ok to require an instance of public key (with must) for a private key, but why is it mandatory to configure it? I did expect the public key filled in either by generate-asymmetric-key action, or by configuring private key. Also the private-key, the public-key, and the algorithm leaves need to be in sync (all valid in respect to the other).

> In our opinion with Balazs L., we think it would be disadvantageous to 
> change the model by ruining the containment relationship between 

Can you say some more about this?  Is it mostly that the containment is really intuitive?  That the relationship is linked both ways, whereas a leadref only goes one way?

Balazs> The certificates in keystore are useless without a corresponding private key, so certificates of a key cannot be in the configuration tree once the corresponding key is removed. By the way, how would a private key be removed from <operational> if it does not exist in configuration? If you do it with an action too, how would the corresponding certificates be removed from the configuration?

Martin makes a case for 'B', but he also said that my 'b' was "Better"
but has scaling issues in the general case.  Perhaps we don't worry about the general case here?

Balazs> Was it so? I saw an A and B model, A containing 
must "(algorithm and public-key and private-key)
              or not (algorithm or public-key or private-key)";
and B containing the keys and the certificates in separate container, and a note "I think model B is cleaner".
If I got it well, model A would keep the containment and produce the key name after invoking the action (affecting the configuration tree!?) at least covering the key removal use case properly.

Balazs> If the key generation and load only affects the <operational> only, I would rather vote for model A having the containment relationship between key and certificate(s). Plus, I would also think about the mandatory statements in the configuration tree whether all 4 leaves (name, private-key, public-key, alg) or just name and private key needs to be configured.

> should have effect on the 'running' configuration too (by setting the 

Okay, but why use an action at all then?  Everything can be done via standard configuration, right?

Balazs> That is actually a good question. Until the enum had the literal 'hardware-protected' only the configuration use case of the private-key was a bit unclear. Now I assume configuring the private-key as 'hidden' could do the same as generate-private-key, but in that case the operator has no means to configure the public key (the removal of the mandatory condition for the public key could solve this). Regarding 'alg', I guess if hidden private key is asked, then algorithm is an input, but if binary private-key is configured, then it is rather implicit. Would the action be needed then?

Balazs> The action in this case seem to make sense only if the purpose of the actions is really to only affect <operational>. But based on the above, I doubt yet how affecting configuration can be avoided (even with alt A -> to maintain consistent composition of key and cert) I think this question goes back to some YANG principles and is beyond my YANG competence.

Kent // contributor

---

From: Balázs Kovács <[email-masked]>
Date: Wed, 29 Aug 2018 08:25:48 +0000

Hi Martin,

I provided answers to Kent, which is mainly around modeling concerns I anticipate based on your previous discussion. Let's continue there.
Br,
Balazs

-----Original Message-----
From: Martin Bjorklund <[email-masked]> 
Sent: Tuesday, August 28, 2018 9:24 PM
To: Balázs Kovács <[email-masked]>
Cc: [email-masked]; Balázs Lengyel <[email-masked]>; [email-masked]
Subject: Re: [Netconf] Mandatory local configuration in Keystore groupings

Hi,

[...]

> config not just operational.

I think that special actions/rpc that modify config should be avoided in probably all cases.  The text in 8342 handles generic rpcs like "edit-data" etc.

*if* you design an action to modify config, it needs to take at least the datastore as an input parameter.

In this particular case, I see no reason to have a special action to modify the configuration of keys.

/martin

> > > "permanently-hidden" keys, doesn't it?  If the client wants 
> > > visible keys, it will configure them in the config datastores.
> > 
> > >> permanently-hidden private key - it's completely inaccessible 
> > >> from the device's supported interfaces, though actually present 
> > >> on the filesystem.
> > >
> > >> well, but it somewhat defeats to goal of *never* having the 
> > >> private key exposed, not even as a once in a lifetime kind of thing.
> > > I'm not convinced either way, actually ;-)  It would be good to 
> > > hear other opinions as well.
> > 
> > > configure a certification for this key, so I have to create an 
> > > entry in the "asymmetric-key" list, where I have to set both the 
> > > Another design could be to have the certificates in a separate 
> > > list, with leafrefs (require-instance false) into the "asymmetric-key"
> > > list.
> >

---

From: Kent Watsen <[email-masked]>
Date: Thu, 30 Aug 2018 21:14:51 +0000

> Balazs> I preferred the original short name and for me it was clear
> that this action produces a 'hidden' key. I actually like the idea 
> of changing the 'hardware-protected' enum literal to 'hidden'.

okay

> Balazs> I myself just started to realize that you intend to maintain 
> an operational tree that is out-of-sync with the configuration tree. 

unsure what you mean here.

> For example, a public key can be determined from the private key. It 
> is ok to require an instance of public key (with must) for a private
> key, but why is it mandatory to configure it? 

In most asymmetrical crypto system implementation, the only fact that 
is ensured is that you cannot find the private key from the public key.
The other way around, finding the public key from the private key is
trivial, but not guaranteed, in most cases.

> I did expect the public key filled in either by generate-asymmetric-key
> action, or by configuring private key. 

You want the public key to be automatically computed from the private
key, right?   It might be possible, but it's always possible that the
client can pass both, so the thinking is just do that - makes sense?

> Also the private-key, the public-key, and the algorithm leaves need to
> be in sync (all valid in respect to the other)

True.  I think you're making a case for letting the server derive the
public key, as the client might pass a mismatched set.  Deriving the
pubkey vs verifying a passed pubkey: both ops require crypto clue,
but only one is guaranteed to always work.

> Balazs> The certificates in keystore are useless without a corresponding
> private key, so certificates of a key cannot be in the configuration 
> tree once the corresponding key is removed. By the way, how would a 
> private key be removed from <operational> if it does not exist in 
> configuration? If you do it with an action too, how would the 
> corresponding certificates be removed from the configuration?

Good points.

>> Martin makes a case for 'B', but he also said that my 'b' was 
>> "Better" but has scaling issues in the general case.  Perhaps 
>> we don't worry about the general case here?
>

Right, but if you scroll up higher, I had previously had an (a) and (b)
[note lowercase] to which he said (b) was "better".  Maybe it's moot,
since his (A) was effectively my (b).

My point is that the containment approach 1) does resolve the he primary
goal (configuring a cert for a key in <operational> and 2) I'm not concerned
about the general scaling problem.  By "perhaps we don't worry about the
general case here?", I mean to say that I prefer keeping the containment
approach.

> If I got it well, model A would keep the containment and produce
> the key name after invoking the action (affecting the configuration 
> tree!?) at least covering the key removal use case properly.

Invoking the generate/load-asymmetric key actions, as thus far dscribed,
would NOT affect the config tree (i.e., <intended>), only <operational>.

> Balazs> If the key generation and load only affects the <operational>
> only, I would rather vote for model A having the containment relationship
> between key and certificate(s). 

This is my preferred approach as well.

> Plus, I would also think about the mandatory statements in the
> configuration tree whether all 4 leaves (name, private-key,
> public-key, alg) or just name and private key needs to be configured.

I'm think all four are needed.  Only public-key is possibly not needed,
but it's trivial to ask a client to pass it, so why not?

> ...but why use an action at all then?  Everything can be done via 
> Balazs> That is actually a good question. Until the enum had the 
> literal 'hardware-protected' only the configuration use case of 
> the private-key was a bit unclear. Now I assume configuring the 
> private-key as 'hidden' could do the same as generate-private-key,
> but in that case the operator has no means to configure the public
> key (the removal of the mandatory condition for the public key
> could solve this). Regarding 'alg', I guess if hidden private key
> is asked, then algorithm is an input, but if binary private-key
> is configured, then it is rather implicit. Would the action be
> needed then?

There are a few things off in what you write, but the most important
thing is that there is no way to *configure* (via <intended>) a hidden
key.  Trying to do so, by passing the "hidden" enum, means that the
real private key raw data would NOT be set!

> Balazs> The action in this case seem to make sense only if the 
> purpose of the actions is really to only affect <operational>. 

Yes, that is the intent.

> But based on the above, I doubt yet how affecting configuration 
> can be avoided (even with alt A -> to maintain consistent composition
> of key and cert) I think this question goes back to some YANG 
> principles and is beyond my YANG competence.

I'm not following, can you say a different way?

Kent // contributor