Subject: [lamps] CSRATTRS specifying the SAN

From: Michael Richardson <[email-masked]>
Date: Wed, 09 Jun 2021 16:15:25 -0400

Eliot has suggested that:
      https://datatracker.ietf.org/doc/html/rfc7030#section-4.5.2
does not appear to allow the returned CSR Attributes to contain a value.
Please correct me if I'm understanding the problem wrong.

RFC8994 assignment of IPv6 ULA can not, as far as I can understand, work
without assigning a value.  The Registrar must allocate a prefix for the new
ACP node, and this has to go into the CSR in order for the CA to sign it.

(Yes, the Registrar has to *check* that the CSR contains the right value along
the way too.  Yes, if the Registrar is ALSO the CA, then it can shortcut, but
that's not in general true)

My unit testing code is at:
  https://github.com/AnimaGUS-minerva/fountain/blob/master/spec/models/csr_attributes_spec.rb

I found the ASN.1 code in section 4.5.2 beyond my understanding, so I muddled
through, since fortunately, there was an example.

   CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID
   AttrOrOID ::= CHOICE (oid OBJECT IDENTIFIER, attribute Attribute }
   Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
        type   ATTRIBUTE.&id({IOSet}),
        values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) }

What I think that this says is that one can have:
  a) a Sequence of stuff.
  b) the stuff is either an OID.
  c) or the stuff is a SEQUENCE [ type, value ].

The complicated &id... is just saying that when you have some attribute type
"FOO", then you can have the things that would be valid as values.  I'm
actually rather amazed at this level of meta-programming. (Can CDDL do that?)

An example is provided:
   MEEGCSqGSIb3DQEJBzASBgcqhkjOPQIBMQcGBSuBBAAiMBYGCSqGSIb3DQEJDjEJ
   BgcrBgEBAQEWBggqhkjOPQQDAw==

%echo 'MEEGCSqGSIb3DQEJBzASBgcqhkjOPQIBMQcGBSuBBAAiMBYGCSqGSIb3DQEJDjEJBgcrBgEBAQEWBggqhkjOPQQDAw==' | base64 -d | dumpasn1 -
  0  65: SEQUENCE {
  2   9:   OBJECT IDENTIFIER challengePassword (1 2 840 113549 1 9 7)
 13  18:   SEQUENCE {
 15   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 24   7:     SET {
 26   5:       OBJECT IDENTIFIER secp384r1 (1 3 132 0 34)
       :       }
       :     }
 33  22:   SEQUENCE {
 35   9:     OBJECT IDENTIFIER extensionRequest (1 2 840 113549 1 9 14)
 46   9:     SET {
 48   7:       OBJECT IDENTIFIER '1 3 6 1 1 1 1 22'
       :       }
       :     }
 57   8:   OBJECT IDENTIFIER ecdsaWithSHA384 (1 2 840 10045 4 3 3)
       :   }

At 2, we have the OID "challengePassword", which tells the client that this
attribute should be included (that's [b]).
At 13-26, we have an attributed, ecPublicKey, with a *value* secp384r1.
This tells the client what kind of things to sign with.  (that's [c])
At 33, we have extensionRequest with oid value 1.3.6.1.1.1.1.22. (also [c])
Finally, at 57, we have just the attribute ecdsaWithSHA384, which is telling
the client to use SHA2-384.

In order to get this all right, I used the example above, made sure I could
decode it, and then made sure that I could encode exactly that.

I have an example building the subjectAltName rfc822Name (yes, my code hasn't
caught up to otherName as specified in RFC8994 yet) which is:

obiwan-[projects/pandora/fountain](2.6.6) mcr 10263 %dumpasn1 tmp/hellobulb0.der
  0  32: SEQUENCE {
  2  30:   SEQUENCE {
  4   3:     OBJECT IDENTIFIER subjectAltName (2 5 29 17)
  9  23:     SET {
 11  21:       SEQUENCE {
 13  19:         [1] {
 15  17:           UTF8String [email-masked]'
       :           }
       :         }
       :       }
       :     }
       :   }

I don't know what the [1] is actually, but possibly that's the rfc822Name.
Yup, it is:
  #        rfc822Name                      [1]     IA5String,   <-- this one

So, I think that I'm entirely within spec for CSR Attributes, and I'd like to
understand more from Owen and Eliot as to what problems they are having with
CSR Attributes.

Eliot has suggested we do it all in JSON (CBOR?), and I would certainly be
happy with that.

--
Michael Richardson <[email-masked]>   . o O ( IPv6 IøT consulting )
           Sandelman Software Works Inc, Ottawa and Worldwide

---

From: Eliot Lear <[email-masked]>
Date: Thu, 10 Jun 2021 15:01:29 +0200

Hi Michael,

>          values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) }

Forgive me, I have indeed misread. the line.  I do still have one question.

I want to understand how to specify the fields that the CA/RA would want 
filled in by the requestor.  For example, how would you say, “please 
provide a SAN of the following form..." such as a serial#?

Eliot

---

From: Michael Richardson <[email-masked]>
Date: Fri, 11 Jun 2021 13:10:26 -0400

Eliot Lear <[email-masked]> wrote:
    >> I found the ASN.1 code in section 4.5.2 beyond my understanding, so I
    >> muddled through, since fortunately, there was an example.
    >>
    >> CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID AttrOrOID ::= CHOICE
    >> (oid OBJECT IDENTIFIER, attribute Attribute } Attribute {
    >> ATTRIBUTE:IOSet } ::= SEQUENCE { type ATTRIBUTE.&id({IOSet}), values
    >> SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) }

    > I want to understand how to specify the fields that the CA/RA would
    > want filled in by the requestor.  For example, how would you say,
    > “please provide a SAN of the following form..." such as a serial#?

So, just to pick a nit... the serialNumber= attribute is part of the SubjectName.
(not SAN).  But, it's all just OIDs as attributes.

You'd make a sequence
      SEQ [ OID-X520SerialNumber, SET["JABA1234"]]

and then you'd add this to your sequence of stuff you want.
I think that "JABA1234" would be of type printableString.

--
]               Never tell me the odds!                 | ipv6 mesh networks [
]   Michael Richardson, Sandelman Software Works        | network architect  [
]     [email-masked]  http://www.sandelman.ca/        |   ruby on rails    [

---

From: Eliot Lear <[email-masked]>
Date: Fri, 11 Jun 2021 19:15:23 +0200

> I think that "JABA1234" would be of type printableString.

I'd want the DEVICE to fill in the serial number.  CSRATTRs was meant to 
be a signal for such things a'la a template, right?

Eliot

---

From: Michael Richardson <[email-masked]>
Date: Fri, 11 Jun 2021 19:01:34 -0400

>> and then you'd add this to your sequence of stuff you want.  I think
    >> that "JABA1234" would be of type printableString.

    > I'd want the DEVICE to fill in the serial number.  CSRATTRs was meant
    > to be a signal for such things a'la a template, right?

Ah.

Then, you'd add the attribute:
      OID-X520SerialNumber

to your sequence.

---

From: Sean Turner <[email-masked]>
Date: Mon, 21 Jun 2021 13:29:32 -0400

Sorry for just getting to this now. I haven’t read upstream so if this gets answer there oops.

> On Jun 9, 2021, at 16:15, Michael Richardson <[email-masked]> wrote:
> 
> Signed PGP part
> 

Oh yeah it does! The whole point of CSRattrs is to allow the client to say “hey RA/CA what do you want my CSR to look like”. The response could just be an OID or it can be an actual attribute with some values:

  Requests for descriptive information from the client are made
  by an attribute, to be represented as Attributes of the CSR, with
  a type indicating the [RFC2985] extensionRequest and the
  values indicating the particular attributes desired to be included
  in the resulting certificate’s extensions. 

Note the word “values” above.

I also figured that there might be brain dead EEs out there so instead of returning a string of attributes the EST server could just return the entire CSR - see Appendix B of RFC 8295. That way the EE would only need sign the request (for PoP).

> What I think that this says is that one can have:

a sequence of stuff that might be empty

> actually rather amazed at this level of meta-programming. (Can CDDL do that?)

So this is the parameterized ASN.1 syntax. What you could so is define an IOSet of attributes. These attributes value values. But, yeah if it’s an attribute it’s an OID and the associated syntax. e.g.,

pKCS7PDU ATTRIBUTE ::= {
       WITH SYNTAX ContentInfo
       ID pkcs-9-at-pkcs7PDU
       }

   pkcs-9-at-pkcs7PDU OBJECT IDENTIFIER ::= {
       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
       pkcs-9-at(25) 5
       }

The OID would be 1.2.840.113549.1.9.25.5

and the values (really only one) is:

PKIData ::= SEQUENCE {
       reqSequence        SEQUENCE SIZE(0..MAX) OF TaggedRequest
       }

> decode it, and then made sure that I could encode exactly that.

Yep!

>  4   3:     OBJECT IDENTIFIER subjectAltName (2 5 29 17)

The one is the tag.