Subject: Re: [Sidrops] I-D Action: draft-ietf-sidrops-6486bis-06.txt

From: Russ Housley <[email-masked]>
Date: Fri, 1 Oct 2021 15:30:09 -0400

> On Oct 1, 2021, at 2:47 AM, Tim Bruijnzeels <[email-masked]> wrote:
> 
> Hi,
> 
> I saw this:
> 
>> On 30 Sep 2021, at 23:11, Russ Housley <[email-masked]> wrote:
>> 
>>     version        [0] INTEGER DEFAULT 0,
> 
> This is how it was done, and also what the e.g. the ROA profile uses.
> 
> However, reading the ASPA profile I came across another way, like:
> 
>     version        [0] VERSION DEFAULT v0,
> 
>     VERSION ::= INTEGER { v0(0) }
> 
> 
> This does not change the profile really afaik, but I believe this
> explicitly limits the available options of 'version' to just 'v0',
> i.e. an INTEGER with value 0. So, this may be a bit better in that
> regard.

Tim:

These produce the same bits on the wire.  The difference is that the various versions have names ifor each of the integer version values.  In that case, the name is "v0".

When v1 gets defined, the definition needs to be expanded to:

   VERSION ::= INTEGER { v0(0), v1(1) }

For example, RFC 5652 has:

  CMSVersion ::= INTEGER  { v0(0), v1(1), v2(2), v3(3), v4(4), v5(5) }

Russ

---

From: Ben Maddison <[email-masked]>
Date: Fri, 1 Oct 2021 21:35:27 +0200

Hi Tim,

> i.e. an INTEGER with value 0. So, this may be a bit better in that
The DER encoding would be unchanged using either definition.

The primary difference is that any future change that required a version
bump, but otherwise left the object structure unchanged, would have to
publish an updated module.

Similarly, an implementation strictly adhering to your version would be
unable to process an object with a updated version number.

It's hard to think of a change to the manifest spec that wouldn't end up
touching the ASN.1 definition somehow, so in this context the above is
probably moot.

Cheers,

Ben

---

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 6 Oct 2021 08:52:28 +0200

Russ (and Ben):

> On 1 Oct 2021, at 21:30, Russ Housley <[email-masked]> wrote:
> 
> 
> 

Indeed, I did not mean to suggest that the encoding would be different, just that the set is limited.

So, if there is a version change it would have to be expanded, but presumably other properties would change as well - e.g. we would no longer insist on the value being 0 in validation. So I am not sure that this is an issue.

In any case, I do not have any preference for one or the other but I noticed that it's different between manifests and the proposed ASPA profile. Plain 'INTEGER' is perfectly fine by me as well, but that does make me wonder whether the ASPA profile should just use that as well.

Tim

---

From: Russ Housley <[email-masked]>
Date: Wed, 6 Oct 2021 11:00:37 -0400

> On Oct 6, 2021, at 2:52 AM, Tim Bruijnzeels <[email-masked]> wrote:
> 
> Russ (and Ben):
> 

This is just a matter of style I think.

Russ

---

From: Job Snijders <[email-masked]>
Date: Wed, 6 Oct 2021 17:53:05 +0200

On Wed, Oct 06, 2021 at 08:52:28AM +0200, Tim Bruijnzeels wrote:
> So, if there is a version change it would have to be expanded, but
> presumably other properties would change as well - e.g. we would no
> longer insist on the value being 0 in validation. So I am not sure
> that this is an issue.

In case you are not aware, from X.690, section 11.5:

    "The encoding of a set value or a sequence value shall not include an
     encoding for any component value which is equal to its default value."

In order words: when validating, you have to check that the 0 value is
NOT present (if one is validating an object according to the version 0
profile).

Kind regards,

Job

---

From: Ben Maddison <[email-masked]>
Date: Fri, 8 Oct 2021 09:53:33 +0200

Hi Russ, Tim,

On 10/06, Russ Housley wrote:
> <snip/>
I've been thinking about this some more, and actually I think that this
choice *is* important when considering asn1 -> code compiler friendliness.

Consider:
    Foo ::= SEQUENCE {
        bar Bar,
        baz Baz,
        qux INTEGER
    }

    Bar ::= INTEGER

    Baz ::= INTEGER {
        a(0), b(1), c(2)
    }

Compiling this to (for the sake of example) rust would be expected to
produce something like:
    struct Foo {
        bar: Bar,
        baz: Baz,
        qux: usize,
    }

    struct Bar(usize);

    enum Baz {
        a = 0,
        b,
        c,
    }

Of course other language type systems have more-or-less direct
parallels.

Each has advantages and disadvantages:

-   the "qux" style can be used directly as an integer with no
    additional work, but you get no safeguards from the type system to
    prevent using a bare integer where you expected a "qux" value;

-   the "baz" style gives the type system the ability to distinguish Baz
    integers from other integers, at the expense of some extra work to
    define the operations on Baz types that are permitted; and

-   the "bar" style is not usable as an integer at all (at least not
    conveniently). The integer value is just there to distinguish the
    variants in memory.

I think this leads to the following general guidance:

1.  Use a bare INTEGER ("qux"-style) for unit-less, context-less integer
    values, that can be sensibly combined in an operation with any other
    integer value.
    This seems to be rare in practise to me, so should probably be
    limited to situations where simplicity is more important than
    correctness.

2.  Use a named type of type INTEGER ("bar"-style) for numbers that
    can be combined or compared with other numbers of a particular type.

    For example:
        bob.age != sue.age          # makes sense
        bob.height + sue.shoe_size  # probably a bug!

3.  Use enumerations ("baz"-style) when the *only* sensible operation
    that exists on the underlying numbers is equality comparison.

In the present case, I would suggest that the 'version' field falls
under category #2, since `foo.version < bar.version` could make sense in
some situations.

So, I would suggest:

    Manifest ::= SEQUENCE {
        version [0] Version DEFAULT 0,
        ...
    }
    Version ::= INTEGER

Note that this is orthogonal to whether we explicitly limit the
permitted value to 0, which can be done in any of the three schemes.
I have no particular view on whether that is a good idea or not.

Cheers,

Ben

---

From: Russ Housley <[email-masked]>
Date: Fri, 8 Oct 2021 11:29:19 -0400

Ben:

Different ASN.1 libraries are better at checking various constraints.

For example, in pyasn1, these two are equivalent:

   ver = rfc5280.Version(2)
   ver = rfc5280.Version('v3')

However, it does not complain if a value that does not have a name is encoded.  That is, it just uses the named values as a more readable way to set specific INTEGER values.

RFC 5280 uses:

   TBSCertificate  ::=  SEQUENCE  {
        version         [0]  Version DEFAULT v1,
        ...

   Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }

RFC 5652 uses:

   SignedData ::= SEQUENCE {
      version CMSVersion,
      ...

RFC 6486:

   Manifest ::= SEQUENCE {

I think all of them are roughly the same to implement, but I tend to like the ability to talk about values like "v2" in the text.

Russ

> On Oct 8, 2021, at 3:53 AM, Ben Maddison <benm=[email-masked]> wrote:
> 
> Signed PGP part
> Hi Russ, Tim,
>

---

From: Ben Maddison <[email-masked]>
Date: Sat, 9 Oct 2021 17:22:17 +0200

Hi Russ,

On 10/08, Russ Housley wrote:
> However, it does not complain if a value that does not have a name is
> encoded.  That is, it just uses the named values as a more readable
> way to set specific INTEGER values.
> 
Yup. But it was not accidental that I didn't use python for my example!

> <snip/>
> 
> I think all of them are roughly the same to implement, but I tend to
> like the ability to talk about values like "v2" in the text.
> 
I absolutely agree in the case that one implements the necessary data
structures by hand.

However an ASN.1 compiler will usually generate the implementation for
you, and will need to choose how to represent the ASN.1 types in the
language's native types.

My point was that we (module authors) should consider the hints that we
give to compilers in order that they can make good choices.

Cheers,

Ben