Re: [netconf] ietf crypto types - permanently hidden

Kent Watsen <kent+ietf@watsen.net> Fri, 03 May 2019 21:48 UTC

Return-Path: <0100016a7fab3d80-cc7c913b-9ef7-4c37-b2f2-a38bb5b3a91c-000000@amazonses.watsen.net>
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 0C2F9120130 for <netconf@ietfa.amsl.com>; Fri, 3 May 2019 14:48:14 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.9
X-Spam-Level:
X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=amazonses.com
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 8tKpVwVTj0PG for <netconf@ietfa.amsl.com>; Fri, 3 May 2019 14:48:12 -0700 (PDT)
Received: from a8-64.smtp-out.amazonses.com (a8-64.smtp-out.amazonses.com [54.240.8.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B17C7120162 for <netconf@ietf.org>; Fri, 3 May 2019 14:48:11 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=6gbrjpgwjskckoa6a5zn6fwqkn67xbtw; d=amazonses.com; t=1556920090; h=From:Content-Type:Content-Transfer-Encoding:Mime-Version:Subject:Date:References:To:In-Reply-To:Message-Id:Feedback-ID; bh=tFEC6/RaYpzsghgcNzxAxBRW2PjSv+nl8Kqb/s1x+Z8=; b=XUx7cXyb9XOYIXqxv6W/jcSAWNzTuXLgNCptcC6WBrSlV4U1GyHy9T3FUCPJJdsB pnj+H3W35veAs+d3dfx/UazuJ2ovLNi6a5XLZc0MukVybmwHigoF1bCE14qaVrISwLI JI33VA1GHAfHC07k3f6d1jDdPSSy09jCH+8v2lFM=
From: Kent Watsen <kent+ietf@watsen.net>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\))
Date: Fri, 03 May 2019 21:48:10 +0000
References: <e30aa60f31ba40e8abc9cfaeffad7802@XCH-RCD-007.cisco.com> <20190503.084757.791827158808672980.mbj@tail-f.com> <3208a877354745fa85188b81a3d8aa24@XCH-RCD-007.cisco.com> <20190503.133743.1149689382943153005.mbj@tail-f.com> <0100016a7e7a9e54-d4987061-96d8-49f3-a2bf-36b98851b3a3-000000@email.amazonses.com> <0100016a7e822689-e6fdbdbe-ba84-43e1-aefe-47196fe692e3-000000@email.amazonses.com>
To: "netconf@ietf.org" <netconf@ietf.org>
In-Reply-To: <0100016a7e822689-e6fdbdbe-ba84-43e1-aefe-47196fe692e3-000000@email.amazonses.com>
Message-ID: <0100016a7fab3d80-cc7c913b-9ef7-4c37-b2f2-a38bb5b3a91c-000000@email.amazonses.com>
X-Mailer: Apple Mail (2.3445.102.3)
X-SES-Outgoing: 2019.05.03-54.240.8.64
Feedback-ID: 1.us-east-1.DKmIRZFhhsBhtmFMNikgwZUWVrODEw9qVcPhqJEI2DA=:AmazonSES
Archived-At: <https://mailarchive.ietf.org/arch/msg/netconf/P-xcpHqUNq3LfX5meOCpNQMJusY>
Subject: Re: [netconf] ietf crypto types - permanently hidden
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, 03 May 2019 21:48:14 -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