Subject: [Anima] PKCS7 certificate SignerData certificates

From: Michael Richardson <[email-masked]>
Date: Tue, 05 Sep 2017 20:09:28 -0400

PKCS7 artifacts have three things in them:
1) the content (technically optional, but we need them)
2) a set of SignerInfo objects on the content.
3) within the SignerData, a bag of certificates, one or more of which has
   signed the content, and the rest which may be useful to establish a trust
   path to a CA.

Max and Kent do we need to say anything about what's in this bag of
certificates, or whether or not they can/should be used to validate a voucher
or voucher request.

Both the JRC (Registrar) and the MASA SHOULD validate signed requests are in
fact signed by the key they claim is making the request.

In a signed voucher request from the pledge to the registrar the
pinned-domain-cert is that of the *PLEDGE* (signed with it's IDevID).
  a) is that certificate also included in the PKCS7 bag of certificates?
     I think the answer SHOULD be yes.
  b) is there any operationally valid reason why there should be additional
     certificates in the PKCS7 bag?
     I can not come up with one. The registrar is never going to validate
     any chain that the manufacturer might have used internally to set up
     their CA for their IDevID.  It cares about the end-certificate only.

In a signed voucher request from the JRC (registrar) to the MASA the
pinned-domain-cert is that of the *Registrar* (signed with it's cmcRA marked
certificate from the domain owner's CA).

  a) is that certificate also included in the PKCS7 bag of certificates?
     I think the answer SHOULD be yes.

  b) is there any operationally valid reason why there should be additional
     certificates in the PKCS7 bag?

     Yes.  At least the domain owner's CA and any certificates in between
     the Registrar and the CA SHOULD be presented.
     Should the domain owner be using a WebPKI of some sort, I think that
     it SHOULD send it all.

     Given pinned-domain-cert (vs our previous ideas), the issued voucher
     is going to be pinned to the Registrar's cert (not some DN specified
     chain).  But, the audit log probably ought to include the entire chain.

     Additionally, the entire chain MAY be needed in order to properly invoke
     the sales channel integration.

If you agree with my analysis, I will cook up some text for the newly
created 3.2 Examples section to explain this.  Some adaptation of the text above.

In my code I'm doing:

i.  extract the first certificate from the PKCS7 bag, and use it to
    verify the PKCS7, telling the verifyer not to validate the chain,
    and not to use any certificates from the PKCS7.
    I found that I could not find a way to access the content of the PKCS7
    content without verifying first.  I don't know if this is a ruby-openssl,
    or underlying libssl limitation yet.

ii.  I look at the content now, parse the JSON, pull pinned-domain-cert out.
iii. I then use the pinned-domain-cert to verify the PKCS7 again.  Perhaps
     I could do a memcpy() against what I had in step (i), and avoid the
     second signature check if it was the same.

I could probably be more flexible in (i) by permitting it to use the bag of
certificates, but telling it not to validate any chain.   I feel like there
may be an attack lurking here because I wouldn't know which certificate
actually validated the object, but that's just a gut instinct.
{But, the above change makes the same code directly useable on the MASA as
well.  But, really, it's only four lines}

Alternatively, in step (i), I should try all the certificates until one
works, guarding aginst there being more than one.

--
Michael Richardson <[email-masked]>, Sandelman Software Works
 -= IPv6 IoT consulting =-

---

From: "Max Pritikin (pritikin)" <[email-masked]>
Date: Wed, 6 Sep 2017 04:03:26 +0000

> On Sep 5, 2017, at 6:09 PM, Michael Richardson <[email-masked]> wrote:
> 
> 

The voucher-request has this additional requirement:

s3.3 of BRSKI-07,
      The request is a "YANG-defined JSON
      document that has been signed using a PKCS#7 structure" as
      described in [I-D.ietf-anima-voucher] using the JSON encoded
      described in [RFC7951].  The Registrar MUST sign the request.  The
      entire Registrar certificate chain, up to and including the Domain
      CA, MUST be included in the PKCS#7 structure.

> fact signed by the key they claim is making the request.

s3.3 of BRSKI-07,

      The MASA validation checks before issuing a voucher are as follows:
      [additional requirements removed for brevity]

      Voucher signature consistency:  The MASA MUST verify that the voucher
      request is signed by a Registrar.  This is confirmed by verifying
      that the id-kp-cmcRA extended key usage extension field (as
      detailed in EST RFC7030 section 3.6.1) exists in the certificate
      of the entity that signed the voucher request.  This verification
      is only a consistency check that the unauthenticated domain CA
      intended this to be a Registrar.  Performing this check provides
      value to domain PKI by assuring the domain administrator that the
      MASA service will only respect claims from authorized Registration
      Authorities of the domain.  (The requirement for the Registrar to
      include the Domain CA certificate in the signature structure was
      stated above).

> pinned-domain-cert is that of the *PLEDGE* (signed with it's IDevID).

Actually this pinned-domain-cert is thus, from s3.2 of BRSKI-07,

   pinned-domain-cert:  In a Pledge voucher request this is the
      Registrar certificate as extracted from the TLS handshake (for
      example the first certificate in the TLS 'certificate_list'
      sequence (see [RFC5246]).  This MUST be populated in a Pledge's
      voucher request if the "proximity" assertion is populated.

I was wondering earlier today if this was confusing. We could add a leaf for “tls-domain-cert” or something. An additional point is that the *assumption* is that this is the same cert as the id-kp-cmcRA cert in the chain discussed above and in s3.3 but maybe that is an assumption too far and we should support bags of certs and arbitrary complexity? I’m tired of this PKI mess.

>     their CA for their IDevID.  It cares about the end-certificate only.

The reason s3.3. mandates the entire chain, including the domain CA certificate, is to allow the above consistency checks. But originally this was so that the domainCA certificate would be used for the pinned cert. Moving to just the RA cert in the pinned-domain-cert field would be a simplification? The text of the voucher-05 leaf description seems to allow this.

>     I think the answer SHOULD be yes.

This is the current language and *not* that the pinned-domain-cert is populated at all. In fact if you look at the new voucher-request-yang branch and Example (2) of the voucher requests you see:

   {
       "ietf-voucher-request:voucher": {
           "created-on": "2017-01-01T00:00:02.000Z",
           "assertion": "TBD",
           "idevid-issuer": "base64encodedvalue=="
           "serial-number": "JADA123456789"
       }
   }

I was considering opening an issue about this TBD and the resulting uncertainty about the meaning of the pinned-domain-cert in this situation. 

> created 3.2 Examples section to explain this.  Some adaptation of the text above.

I think we’re close to agreeing. Some comments: 

I like the jwt approach to certs where they include an entire “x5c” chain rather than a single cert. Maybe we should be copying that? In particular I like it better than trying to specify extra stuff in the certificate bag. The less we depend on the pkcs#7 structure the better and I’m willing to change the above uses to meet that goal. 

>    or underlying libssl limitation yet.

This is an important point. In openssl I believe I was able to crack into the details without verifying and then go back and verify once I’d extracted the cert bags. 

> works, guarding aginst there being more than one.

Dunno the options. I brought my code up this evening to relook at the pinned-cert discussion in this exact area but didn’t make any progress. I’ll try and look at it tomorrow. 

- max

---

From: Kent Watsen <[email-masked]>
Date: Wed, 6 Sep 2017 19:56:49 +0000

>   signed the content, and the rest which may be useful to establish a trust

Not that it matters to BRSKI, but:

   The PKCS#7 structure MAY also contain revocation objects for any
   intermediate CAs between the voucher-issuer and the trust anchor
   known to the recipient.

> certificates, or whether or not they can/should be used to validate a voucher

S6 in the voucher draft says:

   The PKCS#7 structure SHOULD also contain all the certificates leading
   up to and including the signer's trust anchor certificate known to
   the recipient.

and S5.4 in the NETCONF zerotouch draft says:

   The device MUST first authenticate the ownership voucher by
   validating the signature on it to one of its preconfigured trust
   anchors (see Section 5.1).

Perhaps it should add "using any addiiotional intermediate certificates
stapled to the voucher"?

> fact signed by the key they claim is making the request.

Indeed, and what Max posted seems to show that it's covered.

>     I think the answer SHOULD be yes.

Yes, see the SHOULD from S6 above.

>     their CA for their IDevID.  It cares about the end-certificate only.

None that I can think of.

>     I think the answer SHOULD be yes.

The signer of the PKCS7 SHOULD put its certificate into the SignedData
struct.   Whether the same certificate is also in the payload of the
PKCS7 is inconsequential.

> I like the jwt approach to certs where they include an entire “x5c” chain
> rather than a single cert. Maybe we should be copying that? In particular
> I like it better than trying to specify extra stuff in the certificate bag.
> The less we depend on the pkcs#7 structure the better and I’m willing to
> change the above uses to meet that goal. 

I like a chain more than a single cert as well.  I'm ambivalent to the
TA cert being provided, but I'm okay with it if it alignd better with
x5c.

> This is an important point. In openssl I believe I was able to crack into the
> details without verifying and then go back and verify once I’d extracted the
> cert bags. 

Wah?  First, we can't assume the 1st cert is the one you want.  In ASN.1
parlance, it is a SET (not a SEQUENCE).  Next, my code [1] validated the
voucher's signature first - I don't understand the need to be out-of-order
here.  Last, yes, you can access the contents without verification using
the smime -noverify flag.

[1] https://github.com/netconf-wg/zero-touch/blob/master/openssl-test/device/removable-storage-device/Makefile

> Dunno the options. I brought my code up this evening to relook at the 
> pinned-cert discussion in this exact area but didn’t make any progress. 
> I’ll try and look at it tomorrow. 

If you have separately verified the signer cert (e.g.,  valid chain, etc.),
then you can use `smime -noverify -signer ...` which *only* verifies that
the signer cert signed the content (but skips verifying if the signer cert
is itself valid).

K.

---

From: Michael Richardson <[email-masked]>
Date: Thu, 07 Sep 2017 11:19:20 -0400

> CA, MUST be included in the PKCS#7 structure.

I feel dumb, because I was sure that I looked for such a sentence, and I
didn't find it.  Good that it is there.

    > voucher request if the "proximity" assertion is populated.

Huh, this is actually surprising...
I guess we need the Registrar to keep the same thing there, and really the
voucher *HAS* to be issued for this key in order for the Pledge to get out of
provisional state...

    > I was wondering earlier today if this was confusing. We could add a
    > leaf for “tls-domain-cert” or something. An additional point is that
    > the *assumption* is that this is the same cert as the id-kp-cmcRA cert
    > in the chain discussed above and in s3.3 but maybe that is an
    > assumption too far and we should support bags of certs and arbitrary
    > complexity? I’m tired of this PKI mess.

Yes, that's an assumption.
The *VOUCHER* that results has to match the certificate in the TLS.
So it makes sense for the PLEDGE to indicate what certificate it is
expecting.

That lets the Registrar be built using a variety of certificates for
load balancing purposes, and deals with a race condition that could occur if
the Registrar's certificate is renewed during the imprinting process.

If a Registrar wants/needs to update it's cmcRA cert, it could present
the previously signed voucher to the MASA with previous...

    > The reason s3.3. mandates the entire chain, including the domain CA
    > certificate, is to allow the above consistency checks. But originally
    > this was so that the domainCA certificate would be used for the pinned
    > cert. Moving to just the RA cert in the pinned-domain-cert field would
    > be a simplification? The text of the voucher-05 leaf description seems
    > to allow this.

I would like it to be just the RA cert.

    > This is the current language and *not* that the pinned-domain-cert is
    > populated at all. In fact if you look at the new voucher-request-yang
    > branch and Example (2) of the voucher requests you see:

Are you saying that pinned-domain-cert should not be populated in the
voucher request ("VR") from Registrar->MASA?

    > I like the jwt approach to certs where they include an entire “x5c”
    > chain rather than a single cert. Maybe we should be copying that? In
    > particular I like it better than trying to specify extra stuff in the
    > certificate bag. The less we depend on the pkcs#7 structure the better
    > and I’m willing to change the above uses to meet that goal.

So, our pinned-domain-cert in the VR would include the entire chain?
What format would we use?  Is it just concatenated DER of certificates?

    > This is an important point. In openssl I believe I was able to crack
    > into the details without verifying and then go back and verify once I’d
    > extracted the cert bags.

I believe it should be possible, but that I may not have access to the right
API from ruby-openssl.  I've now upstreamed one patch for ruby-openssl, so
I'll probably fix that and upstream and another patch.

    > pinned-cert discussion in this exact area but didn’t make any
    > progress. I’ll try and look at it tomorrow.

---

From: Michael Richardson <[email-masked]>
Date: Thu, 07 Sep 2017 11:27:54 -0400

> up to and including the signer's trust anchor certificate known to

Agreed.
And the MASA should know exactly what that list is for each device.

    > Perhaps it should add "using any addiiotional intermediate certificates

It would be worth saying:

   "It may need to use additional intermediate certificates included
   with the signature artifact (such as PKCS7 SignerData certificates)"

    > TA cert being provided, but I'm okay with it if it alignd better with

I think it's useful for intermediary auditing if the TA cert is included,
(and ignored by the pledge).  We have an existing situation with WebPKI where
some browsers complain if any TA is passed down.  During the SHA1->SHA256
switch over for intermediate CAs, it was sometimes necessary to pass
extra things that the browsers' would eventually have built-in.

    > the smime -noverify flag.

I agree, I shouldn't be assuming it's the first certificate.
I'm going in via API, not CLI.

And btw, the noverify flag in the API still checks that the content is signed
by the provided certificate, it just doesn't check that the certificate is
valid.

---

From: "Max Pritikin (pritikin)" <[email-masked]>
Date: Fri, 8 Sep 2017 21:24:26 +0000

I’ve commented inline about these discussion. 

I’ve also prepared a set of diffs to help bring clarity as per the discussion. The diffs are in this branch:
	https://github.com/anima-wg/anima-bootstrap/commit/bec6d97207aa8faaa600d60622c9b4650ee04934

> On Sep 7, 2017, at 9:19 AM, Michael Richardson <[email-masked]> wrote:
> 
> 
> provisional state…

The registrar “keeps” this field by populating the prior-signed-voucher-request (also preserving the Pledges signature over the proximity assertion).  

> the previously signed voucher to the MASA with previous…

There are two places where consistent use of Registrar cert on both legs is referenced.  

First BRSKI-08 s4.3 indicates the MASA "MAY verify” the pledge’s proximity assertion is “consistent with the [Registrar’s Registrar's 'TLS client certificate]”. The Registrar’s TLS client certificate chain root certificate is then used to populate the ‘pinned-domain-cert’ (final paragraph s4.3).

Second BRSKI-08 s4.4 indicates how the Pledge completes the provisional TLS authentication: "The 'pinned-domain-cert' element of the voucher contains the domain CA's public key. The Pledge MUST use the 'pinned-domain-cert' trust anchor to immediately complete authentication of the provisional TLS connection."

The normative language here allows for Pledges that don’t make the proximity assertion. This also allows a Registrar to present a cert to the Pledge that is *different* than the cert it presents to the MASA; so long as they are issued by the same CA and so long as the MASA allows for the discrepancy. We *could* strengthen this normative statement like so:

	“If the Pledge provides a proximity assertion then the MASA MUST verify…”

> I would like it to be just the RA cert.

Where “just the RA cert” is a simplification, true. I think the current language of using the pinned-domain-cert provides a set of benefits:

	a) allows the RAs to change certs as needed between voucher requests and deployments
	b) simplifies log verification as its always root CA certs in the log
	c) Ensures Pledges “pin” a root cert instead of a subcert within the tree
	d) For Pledges that don’t do EST they have a CA cert rather than just an RA
		(note: s4.7 indicates only that Pledges “SHOULD” continue with EST)

Point (d) is important. If we change to a ‘registrar-cert’ we’d need to strengthen that recommendation to a “MUST”.

> voucher request ("VR") from Registrar->MASA?

Its populated via the prior-signed-voucher-request (see above).

> What format would we use?  Is it just concatenated DER of certificates?

Current language is *only* the Registrar’s cert. 

1) The Pledge attests to the seen “proximity-registrar-cert” by extracting the Registrar’s TLS server cert from the TLS handshake. This is a single cert not a chain. This new voucher request leaf name is now clearer in this point.

2) The MASA attests to the seen “pinned-domain-cert” by extracting the Registrar’s *root CA certificate* from the PKCS#7 signature.

The changes in the above branch don’t effect the normative behavior but do provide clarity; I suggest we adopt them. Beyond that the question at hand is:

Q1) should we make “registrar-cert” or “domain-cert” consistent around “registrar” or “domain” or maintain the current differences?
Q2) if we move to “chain” should we move all the way to “domain-chain”? [1]

My thinking is to accept my branch’s diffs but not move toward chains. 

- max

[1] What would ‘chain’ look like?

x5c is well defined as a JSON field. I’d use the structure as is. Something like the language of https://tools.ietf.org/html/rfc7515#section-4.1.6 modified to this:
	The "proximity-domain-chain” parameter contains the X.509 public key 
	certificate or certificate chain [RFC5280] corresponding to the key 
	used for TLS server authentication by the Registrar the Pledge is communicating with.
I have NOT made this modification.

---

From: "Max Pritikin (pritikin)" <[email-masked]>
Date: Tue, 19 Sep 2017 14:31:19 +0000

There were two issues,

a) The pinned-domain-cert was used as the MASA statement for the domain root certificate in vouchers but overloaded as the Registrar certificate in voucher requests. This caused confusion and the latest text now adds a “proximity-registrar-cert” to
the voucher request. 

b) Each of these fields is a single certificate while PKI discussions often include chains. We decided that continuing with the single certificate approach is valid and are not transitioning to greater PKI integrations. No change.

The pull request fixing these two was merged with this commit:
	https://github.com/anima-wg/anima-bootstrap/commit/4c4eee67cb367faacc976bce0020830a9daea9bf

c) There was a cut/paste error in the language around pkcs7 signatures (regarding who signs them) that was fixed with this commit:
	https://github.com/anima-wg/anima-bootstrap/commit/d8aeff53fd048c07cebcc88828558c6bafc179df

- max

> On Sep 8, 2017, at 3:24 PM, Max Pritikin (pritikin) <[email-masked]> wrote:
> 
> _______________________________________________
> Anima mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/anima