Re: [netconf] latest update to crypto-types and keystore drafts

Martin Bjorklund <mbj@tail-f.com> Fri, 28 June 2019 12:22 UTC

Return-Path: <mbj@tail-f.com>
X-Original-To: netconf@ietfa.amsl.com
Delivered-To: netconf@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 6D4AE12009E for <netconf@ietfa.amsl.com>; Fri, 28 Jun 2019 05:22:29 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.899
X-Spam-Level:
X-Spam-Status: No, score=-1.899 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CUwVGOBtbnFm for <netconf@ietfa.amsl.com>; Fri, 28 Jun 2019 05:22:26 -0700 (PDT)
Received: from mail.tail-f.com (mail.tail-f.com [46.21.102.45]) by ietfa.amsl.com (Postfix) with ESMTP id 249AF120058 for <netconf@ietf.org>; Fri, 28 Jun 2019 05:22:26 -0700 (PDT)
Received: from localhost (unknown [173.38.220.61]) by mail.tail-f.com (Postfix) with ESMTPSA id 4BFAE1AE0351; Fri, 28 Jun 2019 14:22:21 +0200 (CEST)
Date: Fri, 28 Jun 2019 14:22:25 +0200
Message-Id: <20190628.142225.1179923611746773969.mbj@tail-f.com>
To: kent+ietf@watsen.net
Cc: netconf@ietf.org
From: Martin Bjorklund <mbj@tail-f.com>
In-Reply-To: <0100016b9b765508-5742ab05-ca2b-4d94-b040-75a2eed52d42-000000@email.amazonses.com>
References: <0100016b962706ee-c3b245b6-a9ad-45cb-a7a2-b9fe44dd33c3-000000@email.amazonses.com> <20190627.173012.789366833379165040.mbj@tail-f.com> <0100016b9b765508-5742ab05-ca2b-4d94-b040-75a2eed52d42-000000@email.amazonses.com>
X-Mailer: Mew version 6.7 on Emacs 25.2 / Mule 6.0 (HANACHIRUSATO)
Mime-Version: 1.0
Content-Type: Text/Plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Archived-At: <https://mailarchive.ietf.org/arch/msg/netconf/tu66LIOJHi4PRKagk-5sccA885U>
Subject: Re: [netconf] latest update to crypto-types and keystore drafts
X-BeenThere: netconf@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: NETCONF WG list <netconf.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netconf>, <mailto:netconf-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netconf/>
List-Post: <mailto:netconf@ietf.org>
List-Help: <mailto:netconf-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netconf>, <mailto:netconf-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 28 Jun 2019 12:22:29 -0000

Kent Watsen <kent+ietf@watsen.net> wrote:
> 
> Hi Martin,
> 
> >>>> 2) privileged admin copies manufacturer generated key from
> >>>> <operational> to <running>
> >>> 
> >>> The device could also store this key (or rather just the name) in its
> >>> factory configuration.
> >> 
> >> Sure, but only if it's immutable.
> > 
> > No I disagree.  If an admin can create it, it could be part of the
> > factory default config, for convenience.  A user with the right access
> > can delete it from the config, just as if it had been created by an
> > admin.
> 
> Based on your later comments, it seems that we're more in agreement
> than not.

Good!


> Let me rephrase, if the manufacturer generated keys (with
> 'hidden-key' or 'hidden-private-key') are stored in the factory
> default datastore, per draft-ietf-netmod-factory-default, they would
> be read-only and hence immutable.

Well, I wouldn't express this as "the key is immutable", but rather
that the factory defaults configuration datastore is immutable /
read-only.

> Now, upon that configuration being
> copied into <running>, the configuration would become editable and
> said keys could be removed.
> 
> 
> 
> >>> I don't think the public key and alg needs to go into the config.
> >> 
> >>> Or in general, if the key is configured as hidden, I think it should
> >>> NOT have a public key and alg in the config (can be ensured with
> >>> "must").  However, they must be present in the operational state.
> >> 
> >> Okay, but in thinking about going down that route, I'd rather use a
> >> special enum/union type values to denote the absence of these fields
> >> than to mark the nodes mandatory false.  Personally, I think it's
> >> better to duplicate the values into configuration as it does no harm
> >> and it makes them easier and more consistent to work with
> > 
> > I think it makes them more difficult to work with.  Why should I be
> > able to modify the public key of a hw-stored key?  It is just error
> > prone.
> 
> Assuming that the manufacturer generated keys are in <factory-default>
> then, when copied to <running>, they have identical values as they
> were in <factory-default> (i.e., all three fields are present)

It is enough if just the name and "hidden" enum is present in
factory-defaults, and thus just these fields are copied to running.

> >> (e.g.,
> >> clients need the public key in order to encrypt data destined to the
> >> device).  Really, I don't want any keys in <operational>
> > 
> > If you need the public key why is it a problem to read it from
> > <operational>?
> 
> It's not, but my comment was about keys as a whole (not the key's
> inner values).  The <factory-default> approach is nice because it
> normalizes all key access to one approach (intended configuration).
> 
> 
> 
> >>>> 3) privileged admin encrypts a well-known (secret to the organization)
> >>>> symmetric key using the public key from the manufacturer generated
> >>>> asymmetric key, and stores the result (i.e., <edit-config> into
> >>>> keystore.
> >>> 
> >>> Ok.  However, if the device doesn't have a hidden
> >>> manufacturer-supplied key from step 1 (no tpm), it would be useful if
> >>> the admin could install this symmetric key so that it becomes hidden.
> >>> But that action is no longer present in the model.
> >> 
> >> True, but it seems strange that a device would have the ability to
> >> store hidden keys without itself being shipped with a hidden key.
> > 
> > Hasn't the previous discussion shown that it is quite common to store
> > keys separate from the normal config?
> 
> My assertion is that any device that has the ability to install
> "hidden" keys surely would ship with preconfigured hidden keys that
> could subsequently be used by admins to encrypt any keys they create
> later, hence negating the need for the device to support a feature to
> install hidden keys.

Ok.  This makes sense.

> > I like the new design of this module, where all keys (but one!) are
> > stored encrypted.  But that one key needs to be as protected as
> > possible.
> 
> Agreed.
> 
> 
> 
> >> We
> >> could add a set of RPCs to manage the life-cycle of hidden keys
> > 
> > Or perhaps state that the management of such keys are out of scope
> > (for now)?
> 
> This is my preference.  In particular, the current model defines the
> ability for keys to be hidden, and specifically says "How such keys
> are created is outside the scope of this module."  It is my
> hope/intention to not define any module defining an ability to
> create/install hidden keys, thus restricting their creation to
> manufacturing-time magic and vendor-specific modules defining
> proprietary RPCs.

Ok!

> >>> Or does this model *require* the device to have such a key?  If no tpm
> >>> exists, then it can exist on disk?
> >> 
> >> Not required.  For devices that don't have hidden keys, plain old NACM
> >> could protect the encryption-key used to protect all the other keys in
> >> the configuration.  The primary benefit would still be present, that
> >> keys subsequently generated by the device would be protected by the
> >> encryption key.
> > 
> > I think this benefit goes away if the encryption key itself it present
> > in clear text in the config.  In this case we could as well use NACM
> > to protect *all* keys.
> 
> Yes and no.  Yes, in the sense that NACM is the ultimate protection
> mechanism but, no, in the sense that this fails to have value.
> Specifically, regular admins can still ask the device to generate a
> key, encrypted by another key that they don't have access to.
> Similarly, regular admins can operate in (copy/paste/reference)
> encrypted keys without ever being able to access the secret data.
> 
> FWIW, in JUNOS, the DDL/YANG modeling language has a special "secret
> data" annotation that switches on logic to encrypt said data at-rest
> and over-the-wire for all except users in the "super-user" class.
> JUNOS users are typically configured in the "operator" class, and
> sometimes in the "read-only" class.  This is effectively the NACM
> model we're discussing here, and it's been shipping for a long time.
> 
> 
> 
> >> The downside would be that the encryption key itself,
> >> when generated, could not be protected in the same way.  For such
> >> situations, it would be recommended that this key be installed from a
> >> known-safe connection (i.e., via an air-gapped system).
> > 
> > Perhaps this is the "out-of-scope" that I mentioned above?
> 
> No, this part would be best practice. That is, if one must handle
> private keys in the clear, at least be sure to do so via a secure
> system and via a secure network.
> 
> 
> 
> >> What is meant is that the symmetric key would be created once on the
> >> second device, in step (3), but because the old encrypted symmetric
> >> key was stored in configuration (on the first device), when loading
> >> the configuration here in step (4), it is as if the symmetric key is
> >> being created again on the second device.  But the logic on the second
> >> device should be able to detect this anomaly (because the key would've
> >> been encrypted by the first device's private key, and hence decryption
> >> should fail on the second device) and thus the "duplicate" symmetric
> >> key would be discarded.
> > 
> > Hmm, I still don't see how this is supposed to work.  Are you
> > suggesting special treatment for this list entry by the edit-config /
> > copy-config operations?  I strongly object to such a hack, but perhaps
> > you meant something else?
> 
> I'm unsure if I'd call it special treatment, so much as logical
> outcome - see below.
> 
> 
> THIS IS THE CONFIG FROM THE FIRST DEVICE
> 
> <keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
>     <asymmetric-keys>
> 
>         <!-- a device-unique asymmetric key -->
>         <asymmetric-key>
>             <name>tpm-protected-key</name>      <----  name value may differ
>             <algorithm>rsa2048</algorithm>
>             <public-key>base64encodedvalue==</public-key>
>             <hidden-private-key/>
>         </asymmetric-key>
> 
>         <!-- operator-wide symmetric key, protected by the device-specific key
>         -->
>         <!-- this key must be created for each device (i.e., via step #3) -->
>         <symmetric-key>
>             <name>operator-protected-key</name>
>             <algorithm>aes-256-cbc</algorithm>
>             <public-key>base64encodedvalue==</public-key>
>             <encrypted-private-key>
>                 <asymmetric-key-ref>tpm-protected-key</asymmetric-key-ref>
>                 <value>base64encodedvalue==</value>
>             </encrypted-private-key>
>         </symmetric-key>
> 
>         <!-- a migratable key, protected by the operator-wide key -->
>         <asymmetric-key>
>             <name>ex-encrypted-key</name>
>             <algorithm>rsa2048</algorithm>
>             <public-key>base64encodedvalue==</public-key>
>             <encrypted-private-key>
>                 <symmetric-key-ref>operator-protected-key</symmetric-key-ref>
>                 <value>base64encodedvalue==</value>
>             </encrypted-private-key>
>         </asymmetric-key>
> 
>     </asymmetric-keys>
> </keystore>
> 
> 
> THIS IS THE CONFIG ON A SECOND DEVICE, AFTER STEP #3
> 
> <keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
>     <asymmetric-keys>
> 
>         <!-- a device-unique asymmetric key -->
>         <asymmetric-key>
>             <name>tpm-protected-key</name>      <---- name value may differ
>             <algorithm>rsa2048</algorithm>
>             <public-key>base64encodedvalue==</public-key>
>             <hidden-private-key/>
>         </asymmetric-key>
> 
>         <!-- operator-wide symmetric key, protected by the device-specific key
>         -->
>         <!-- this key must be created for each device (i.e., via step #3) -->
>         <symmetric-key>
>             <name>operator-protected-key</name>
>             <algorithm>aes-256-cbc</algorithm>
>             <public-key>base64encodedvalue==</public-key>
>             <encrypted-private-key>
>                 <asymmetric-key-ref>tpm-protected-key</asymmetric-key-ref>
>                 <value>base64encodedvalue==</value>
>             </encrypted-private-key>
>         </symmetric-key>
> 
>     </asymmetric-keys>
> </keystore>
> 
> 
> Now, when this configuration from the first device is loaded onto the
> second device, one of two things might happen:
> 
>   1) if the manufacturer gives the same name to each device's
>   TPM-protected keys (i.e., <name>tpm-protected-key</name>)
> 
>       a) <running> (copied from <factory-default>), would contain a key
>       having the 'key' value as the incoming key.
>       b) this should fail, because it's not possible to change the
>       <public-key> for a key having <hidden-private-key/>.

This would be special treatment.  And IMO it is not needed; if the
public key and alg are not present in the config this is not an
issue.

>   2) if the manufacturer gives unique names to the tpm-protected-keys
>   (i.e., <name>key3124235234</name>)
> 
>       a) <running> (copied from <factory-default>), would NOT contain a key
>       having the 'key' value as the incoming key.
>       b) this should fail, because it's not possible to config a new key
>       having <hidden-private-key/>.

For this use case I think it is a prerequisite that the key has the
same name.

> The specific failure error isn't as interesting as knowing that it
> will fail somehow, and implementations will need to handle the
> possibility.
> 
> That said, the general recommendation, which would both be correct and
> avoid any potential failures, would be for the client to remove the
> device-specific and operator-wide keys first, leaving just the
> migratable keys in the config uploaded to the second device.

THIS IS THE CONFIG FROM THE FIRST DEVICE (A)

<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
    <asymmetric-keys>

        <!-- a device-unique asymmetric key -->
        <asymmetric-key>
            <name>tpm-protected-key</name>
            <hidden-private-key/>
        </asymmetric-key>

        <!-- operator-wide symmetric key, protected by the device-specific key
        -->
        <!-- this key must be created for each device (i.e., via step #3) -->
        <symmetric-key>
            <name>operator-protected-key</name>
            <algorithm>aes-256-cbc</algorithm>
            <encrypted-key>
                <asymmetric-key>tpm-protected-key</asymmetric-key>
                <value>base64encodedvalue-1==</value>
            </encrypted-private-key>
        </symmetric-key>

        <!-- a migratable key, protected by the operator-wide key -->
        <asymmetric-key>
            <name>ex-encrypted-key</name>
            <algorithm>rsa2048</algorithm>
            <public-key>base64encodedvalue-2==</public-key>
            <encrypted-private-key>
                <symmetric-key>operator-protected-key</symmetric-key>
                <value>base64encodedvalue-3==</value>
            </encrypted-private-key>
        </asymmetric-key>

    </asymmetric-keys>
</keystore>


THIS IS THE CONFIG ON A SECOND DEVICE, AFTER STEP #3 (B)

<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
    <asymmetric-keys>

        <!-- a device-unique asymmetric key -->
        <asymmetric-key>
            <name>tpm-protected-key</name>
            <hidden-private-key/>
        </asymmetric-key>

        <!-- operator-wide symmetric key, protected by the device-specific key
        -->
        <!-- this key must be created for each device (i.e., via step #3) -->
        <symmetric-key>
            <name>operator-protected-key</name>
            <algorithm>aes-256-cbc</algorithm>
            <encrypted-private-key>
                <asymmetric-key>tpm-protected-key</asymmetric-key>
                <value>base64encodedvalue-4==</value>
            </encrypted-private-key>
        </symmetric-key>

    </asymmetric-keys>
</keystore>


If we edit-config (A) into (B), we'll trash "operator-protected-key";
specifically its "encrypted-private-key/value" leaf must not be
changed.

If we remove "operator-protected-key" from (A) we can then merge the
rest of (A) into (B).

So this requires the client to pacth the config a bit.  Perhaps this
is ok.



> >> These identities (now enumerations) are coming from the crypto-types
> >> module in a section maintained by my co-author from Huawei who has
> >> even more crypto-clue than I.  My guess is that this is what they're
> >> called in IANA registries for historical reasons.
> > 
> > Ok, but you agree that "symmetric-key-algorithm" would be better,
> > unless there's some strong historical reason for keeping
> > "encryption-algorithm"?
> 
> Yes, I agree, it would be best if it were called a symmetric key, as
> even asymmetric keys can do encryption.

Ok, let's have that discussion in the crypto-types thread.


/martin