Subject: [Sidrops] ASPA Profile

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 13 Oct 2021 10:04:08 +0200

Dear all,

Whilst implementing a proof of concept we found some issues in the ASPA -06
profile that we believe could be improved on.

The current definition in -06 is as follows:

    ct-ASPA CONTENT-TYPE ::=
        { ASProviderAttestation IDENTIFIED BY id-ct-ASPA }

    id-ct-ASPA OBJECT IDENTIFIER ::= { id-ct TBD }

    ASProviderAttestation ::= SEQUENCE {
        version [0] ASPAVersion DEFAULT v0,
        aFI  AddressFamilyIdentifier,
        customerASID  ASID,
        providerASSET  SEQUENCE (SIZE(1..MAX)) OF ASID }

    ASPAVersion ::= INTEGER  { v0(0) }

    AddressFamilyIdentifier ::= OCTET STRING (SIZE (2))

    ASID ::= INTEGER

This implies that we need one object for each AFI. The size of the providerASSET
sequence can become very large. Plus, theoretically, one could have a sequence of
AS0-4294967295, resulting in a 16GB sequence. I understand this would be an
extreme and perhaps non-sensical case, but still there is room for improvement
here.

We propose to change the profile to the following:

    ct-ASPA CONTENT-TYPE ::=
        { ASProviderAttestation IDENTIFIED BY id-ct-ASPA }

    id-ct-ASPA OBJECT IDENTIFIER ::= { id-ct TBD }

    ASProviderAttestation ::= SEQUENCE {
        version [0] ASPAVersion DEFAULT v0,
        customerASID  ASId,
        providerASID  CHOICE {
             ProviderASSet,
             SET OF FamilyProvider
        }
    }

    ASPAVersion ::= INTEGER  { v0(0) }

    FamilyProvider ::= SEQUENCE {
        aFI AddressFamilyIdentifier,
        providerASSet ProviderASSet
    }

    AddressFamilyIdentifier ::= INTEGER

    ProviderASSet ::= SEQUENCE OF ASIdOrRange

    ASIdOrRange         ::= CHOICE {
       id                  ASId,
       range               ASRange }

    ASRange             ::= SEQUENCE {
       min                 ASId,
       max                 ASId }

    ASId                ::= INTEGER
        
    aFI  AddressFamilyIdentifier,

This definition uses the same approach defined in RFC 3779 sections 3.2.3.4
and below to allow encoding ASNs more efficiently.

Furthermore, it allows that we have one ASPA object per customerASID, and
that we do not need to repeat ourselves in case the ProviderASSet is the
same for all AFIs.

One more question.. does it make sense to allow AFI values other than IPv4
and IPv6? Looking at the RTR draft ASPA PDU it does not, and therefore we
should perhaps limit the valid choices in the profile as well.

Kind regards

Tim

---

From: Claudio Jeker <[email-masked]>
Date: Wed, 13 Oct 2021 12:41:25 +0200

> should perhaps limit the valid choices in the profile as well.

Adding ranges here does not solve your porblem of extremly large
sequences. There is no enforcement that consecutive ASIds need to be
range encoded so if I want I can still encode 1..4294967295 as individual
ASids. It also does not solve the problem of 16GB cer files being
deployed clogging up all RP clients. All it does is adding extra
complexity.

There is indeed a need for limits not only in the ASPA object but also all
other RPKI X.509 profiles. You can play the same games with .roa, .cer,
.mft files.
-- 
:wq Claudio

---

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 13 Oct 2021 14:48:10 +0200

> On 13 Oct 2021, at 12:41, Claudio Jeker <[email-masked]> wrote:
> 

I'd say you can play different games with all those types. You can go wide,
deep and large. I think it would be useful to discuss those things as well
but I will leave it aside for now.

Where this was coming from is that we have this definition in -06:

And no mention of a limit. So my suggestion was done on the premise that
large ranges could be valid - and even non malicious.

If we would have the following instead then the discussion would be very
different:

       providerASSET  SEQUENCE (SIZE(1..N)) OF ASID }

If N<1000 ranges are overkill. If N == 65535 as the RTR PDU allows, then
we could consider leveraging the tried and tested compression mechanism
from RFC 3779, already implemented and understood by all RPKI CAs and RPs.

It would really help to get operator and/or researcher feedback on what a
reasonable value for N could be. But I would say that even choosing some
value now, would allow us to build up experience before making this an RFC.

Now that you are here, how about the AFI question? I believe that we really
only need IPv4 and IPv6. So, if it's pure simplicity you want without the
use of 'CHOICE', and you do not mind duplication (in most cases this would
just be handful), then you could also have:

   ct-ASPA CONTENT-TYPE ::=

   ASProviderAttestation ::= SEQUENCE {
       version [0] ASPAVersion DEFAULT v0,
       customerASID  ASId,
       providersV4   ProviderASSet,
       providersV6   ProviderASSet,
   }

   providerASSET  SEQUENCE (SIZE(1..N)) OF ASID }

   ASID                ::= INTEGER

Where N = some reasonable value.

> -- 
> :wq Claudio
> 
> _______________________________________________
> Sidrops mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/sidrops

---

From: Job Snijders <[email-masked]>
Date: Wed, 13 Oct 2021 15:41:45 +0200

On Wed, Oct 13, 2021 at 02:48:10PM +0200, Tim Bruijnzeels wrote:
> If N<1000 ranges are overkill. If N == 65535 as the RTR PDU allows,
> then we could consider leveraging the tried and tested compression
> mechanism from RFC 3779, already implemented and understood by all
> RPKI CAs and RPs.

What compression mechanism are you referring to?

> It would really help to get operator and/or researcher feedback on
> what a reasonable value for N could be. But I would say that even
> choosing some value now, would allow us to build up experience before
> making this an RFC.

I don't think we can know any reasonable value for N. I'm not really in
favor of adding arbitrary limits to the protocol specification itself. 

>    providerASSET  SEQUENCE (SIZE(1..N)) OF ASID }

Is the above ASN.1 complete?

Kind regards,

Job

---

From: Job Snijders <[email-masked]>
Date: Wed, 13 Oct 2021 15:49:57 +0200

On Wed, Oct 13, 2021 at 03:41:45PM +0200, Job Snijders wrote:
> > then you could also have:
> >
> >    ct-ASPA CONTENT-TYPE ::=

Ah, you replaced an 'afi' field with 'providersV4' and 'providersV6'.
That indeed introduces a fair bit of duplication.

How about an optional 'afi' field per provider AS?

If the field is absent, the Relying Party will apply the information to
both IPv4 and IPv6. If the 'afi' field is present, the value of the
field specifies the only AFI for which the provider is providing to
customerASID.

Given that generally folks acquire dual-stack transit services, it might
make sense to put the 'burden' on those operating with different sets of
providers for IPv4 compared to IPv6.

Kind regards,

Job

---

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 13 Oct 2021 15:58:16 +0200

> On 13 Oct 2021, at 15:49, Job Snijders <[email-masked]> wrote:
> 

Works for me as well.

> providers for IPv4 compared to IPv6.

Sure, in the end of the day the burden of encoding/decoding will be on the
software. But I like the idea of applies-to-both-unless-stated-otherwise.
The burden on the operator will be to do the stating rather than the actual
encoding if you see what I mean.

Tim

---

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 13 Oct 2021 16:09:29 +0200

> On 13 Oct 2021, at 15:41, Job Snijders <[email-masked]> wrote:
> 

https://datatracker.ietf.org/doc/html/rfc3779#section-3.2.3.4

I called this 'compression'. I think that it's what it's trying to do,
but perhaps it was cryptic.

This says that contiguous series of AS identifiers MUST be combined into
a single range. A range of two elements would a SEQUENCE containing two
INTEGERS. This still takes more space than two single INTEGERs. But for
ranges of 3 or more elements this saves space.

By itself this does not enable listing 2^32 providers, but it enables
doing so in a small object, which is more likely to be parsed and validated.

You could disallow ranges of course, but then you just get large objects.
You could consider this a feature, because at some point they become too
large to swallow and this shields the remaining stack. But there is no saying
really which part of the chain will fail first.

> favor of adding arbitrary limits to the protocol specification itself. 

Generally speaking I agree with that. But if no limit is specified then
things will break in different ways for different implementations.

The ASPA object could become too large to the taste of Publication Server X,
but not Y. Or RP A, but not B. The resulting RTR PDU could be too large for
router by vendor M, but not router by vender N.

---

From: Stephen Kent <[email-masked]>
Date: Wed, 13 Oct 2021 10:38:18 -0400

Tim,
> ranges of 3 or more elements this saves space.

the representation specified in 3779 was intended to yield a canonical 
form, essential for DER.

Steve

---

From: Tim Bruijnzeels <[email-masked]>
Date: Wed, 13 Oct 2021 16:47:39 +0200

> On 13 Oct 2021, at 16:38, Stephen Kent <stkent=[email-masked]> wrote:
> 
> Tim,
> the representation specified in 3779 was intended to yield a canonical form, essential for DER.

Sure. That is the most important goal.

For it to be canonical it just matters that it's clear what applies. But,
I am sure that it's not listing every single AS a separate INTEGER 
by accident. That said, if compression indeed was the higher goal then
it would have been best to encode series of 3 or more contiguous elements
as ranges and series of 2 elements as separate integers.

Anyway, it is what is. I think it's relatively easy to apply here and
might save some space here and there, but I am fine either way as long
as large ranges are not supposed to be supported - which is what I am
getting from the WG.

---

From: Tim Bruijnzeels <[email-masked]>
Date: Thu, 14 Oct 2021 14:00:02 +0200

> On 13 Oct 2021, at 15:58, Tim Bruijnzeels <[email-masked]> wrote:
> 
> 
> 

Let me try to write out an updated section 3 capturing this and see if
it works for you and others. Obvisously, feel free to change it, but it
may help to look at text.

I left the providerASSET max sequence size at MAX.

As Claudio pointed out we can have a similar discussion on other limits.

Perhaps it could be an idea to have a separate draft where limits are
specified, which can then also be updated in future. I know that limits
are arbitrary, but without them we will get issues because implementations
and various components in the chain enforce their own, different, limits.
So, on the whole I think it would still be best to specify them.

updated text:

3.  The ASPA eContent

   The content of an ASPA identifies the Customer AS (CAS) as well as
   the Set of Provider ASes (SPAS) that are authorized to further
   propagate announcements received from the customer.  If customer has
   multiple providers they MUST be registered in a single ASPA object.
   This rule is important to avoid possible race conditions during
   updates.  An ASPA is formally defined as:

       ct-ASPA CONTENT-TYPE ::=

           providers     ProviderASSet,
       }

       ASID           ::= INTEGER

       providerASSET  ::= SEQUENCE (SIZE(1..MAX)) OF ProviderAS }

       providerAS     ::= {
           providerASID ::= ASID,
           afiLimit     ::= OCTET STRING (SIZE (2)) OPTIONAL
       }

   Note that this content appears as the eContent within the
   encapContentInfo as specified in [RFC6488].

3.1.  version

   The version number of the ASProviderAttestation MUST be v0.

3.2.  customerASID

   The customerASID field contains the AS number of the Autonomous
   System that authorizes an upstream providers (listed in the
   providerASSET) to propagate prefixes in the specified address family
   other ASes.

3.4.  providerASSET

   The providerASSET contains the sequence (set) of providerAS that are
   authorized to further propagate announcements from the customer.

3.5   providerAS

   The providerAS contains the providerASId which specifies the
   AS number of a provider. Optionally it contains an afiLimit
   field which specifies an IP address family limit, in which
   case the provider is only authorized to propagate announcments
   for the specified address familiy. This specification only
   supports IPv4 and IPv6.  Therefore, afiLimit MUST be either
   0001 or 0002.

---

From: Tim Bruijnzeels <[email-masked]>
Date: Mon, 18 Oct 2021 11:07:02 +0200

Hi,

There was a small bug in my proposed structure. We will need a sequence
in the 'ProviderAs' definition, like so:

  providerAS     ::= SEQUENCE {
      providerASID ::= ASID,
      afiLimit     ::= OCTET STRING (SIZE (2)) OPTIONAL
  }

Note that this means that the efficiency in terms of encoding is lowered
a bit. In typical cases where users would specify a list of providers
without any limitation with regards to AFI, we will get a sequence of
sequence of asid. This imposes a slight overhead.

But, to me this is not problematic. I think it's a small price to pay for
having the simple concept of having a single list of providers, where
any provider may be restricted if desired. These concepts tend to leak
into the API and UI so I would optimize for understandability rather than
byte level encoding efficiency.

What I would want to add though is that each provider ASID MUST NOT
occur more than once and that the providers MUST be sorted (low to high).
Having them sorted makes it much easier for parsers to verify that each
ASID occurs only once.

Please let me know what you think. I am working on prototype code to
support this model. I can share an example object if desired.

Tim

> On 14 Oct 2021, at 14:00, Tim Bruijnzeels <[email-masked]> wrote:
> 
> 
>

---

From: Tim Bruijnzeels <[email-masked]>
Date: Mon, 25 Oct 2021 14:27:59 +0200

Job, all,

I have running code - in a development branch - that adds basic ASPA support
to Krill. See attachment for an example object.

However, I have some open questions that I need answered before I can merge
this, and deliver on my promise done at the last IETF that I would provide a
public testbed.

- Do we have an OID now?

Sorry, if I missed it. I know one has been requested.. the attached object
hijacks the ROA OID - so I could keep coding - but I need a real OID before
merging.

- Profile?

I got no more replies to my suggested profile update.

Any thoughts? I am happy to change this of course, but I have to say that
I really like the user facing concept of having a single object for all
provider ASNs with optional AFI restrictions for each *unique* provider ASN.

As long as this concept does not change, I can easily change the underlying
encoding.

And, yes, if there are reasons to do this all differently after all then
those changes could and would be made as well..

Kind regards,
Tim

> On 18 Oct 2021, at 11:07, Tim Bruijnzeels <[email-masked]> wrote:
> 
> Hi,
>

---

From: Job Snijders <[email-masked]>
Date: Mon, 25 Oct 2021 15:29:12 +0200

Hi Tim,

To me this seems an improvement over the -06 profile. Thank you for
putting this together. Russ? Ben? Azimov? Randy?

One note in-line below

>        providerASSET  ::= SEQUENCE (SIZE(1..MAX)) OF ProviderAS }

hmmm... shouldn't SIZE(1..MAX) be SIZE(0..MAX) to accomodate so-called
"transit-free" providers?

---

From: Ben Maddison <[email-masked]>
Date: Mon, 25 Oct 2021 15:45:01 +0200

Hi Job, Tim,

> putting this together. Russ? Ben? Azimov? Randy?
Agreed. I think making per-afi distinctions the exception rather than
the rule is a substantial improvement.

> > <snip/>
I still don't love the enum-style version, as we discussed in the
context of manifests previously.

Moreover, I can live with either enum-style or typedef-style, but we
should probably pick *one* as a WG for consistency.

> "transit-free" providers?
Yes! For practical purposes, these are likely to be some of the most
import objects that get issued.

> >            afiLimit     ::= OCTET STRING (SIZE (2)) OPTIONAL

Cheers,

Ben

---

From: Job Snijders <[email-masked]>
Date: Mon, 25 Oct 2021 16:02:11 +0200

> import objects that get issued.

Hmmm, I just now remembered the verification doc suggests to use 'AS 0'
instead of 'empty': https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification#section-6

Using 'AS 0' permits one to publish a statement that one is
'transit-free' in IPv6, but not in IPv4, or vice versa.

I'm not enthusiast about how 'AS 0' is more and more overloaded,
especially with negative trust anchors floating around.

Kind regards,

Job

---

From: Ben Maddison <[email-masked]>
Date: Mon, 25 Oct 2021 16:03:12 +0200

Hi Tim,

>    to Krill. See attachment for an example object.
Great news!
What version of the profile does your demo object use? I guess your
new proposed version, since I can't decode it using the -06 module?

>    hijacks the ROA OID - so I could keep coding - but I need a real OID
rpkimancer-aspa is currently squatting on .73 for the module OID and .49
for the content-type OID. Perhaps use those in the interim, so that we
can at least read each other's objects?

>    I got no more replies to my suggested profile update.
See my last email.

Cheers,

Ben

---

From: Tim Bruijnzeels <[email-masked]>
Date: Mon, 25 Oct 2021 20:37:46 +0200

Hi,

> On 25 Oct 2021, at 15:45, Ben Maddison <[email-masked]> wrote:
> 
> Hi Job, Tim,
> 

I left this unchanged (I think, did I?). In any case, I agree that for
consistency it's probably best to pick one. This is what triggered me
to bring it up wrt manifests. But, I do not have strong preferences.

---

From: Tim Bruijnzeels <[email-masked]>
Date: Mon, 25 Oct 2021 20:38:41 +0200

Hi Ben,

> On 25 Oct 2021, at 16:03, Ben Maddison <benm=[email-masked]> wrote:
> 
> Hi Tim,
> 

It uses the proposed structure.

> can at least read each other's objects?

I can make a new version by the end of the week. The kids have school holidays,
so that means double shifts for the parents..

---

From: Tim Bruijnzeels <[email-masked]>
Date: Mon, 25 Oct 2021 20:55:19 +0200

> On 25 Oct 2021, at 16:02, Job Snijders <[email-masked]> wrote:
> 

If I had to make a guess I would say that this was done to simplify
the data structures in routers and/or RTR PDUs. But it's a guess..

My preference would be to go for explicit, rather than an overloaded
AS 0. So an explicit empty SEQUENCE would work better for me. It also
avoids the issue where one might find both AS0 and other provider ASNs.
On the other hand it would no longer be possible to express 'transit-free'
in IPv6, but not in IPv4, or vice versa.

I don't have a strong preference here... I think this should come from
router implementers and network operators - what would be most intuitive
to them?

---

From: Alexander Azimov <[email-masked]>
Date: Mon, 25 Oct 2021 23:49:01 +0300

Hi all,

My reason for keeping ASPA0 was not about the technical side. It's about
'expected behavior'.
We have ROA0, and developers and network engineers that got used to it and
its semantics.
ASPA0 has much in common here, and originally it even shared very similar
text structures in its description.

We can make it as EMPTY SEQUENCE, we will have a better structure but
sacrifice 'expected behavior'.
IMO we don't need an 'ideal' structure, we need an easily understandable
structure, and a corresponding link to ROA0 will be helpful.

PS: the combination of ASPA0 and other provider ASNs doesn't look like an
issue for me.

пн, 25 окт. 2021 г. в 21:55, Tim Bruijnzeels <[email-masked]>:

> > instead of 'empty':
> https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification#section-6
> >

-- 
Best regards,
Alexander Azimov

---

From: Randy Bush <[email-masked]>
Date: Mon, 25 Oct 2021 14:43:48 -0700

> especially with negative trust anchors floating around.

indeed.  using a special value as a sentinel also has an interesting
history.

randy

---

From: Ben Maddison <[email-masked]>
Date: Tue, 26 Oct 2021 11:10:06 +0200

Hi Alexander, Tim,

> structure, and a corresponding link to ROA0 will be helpful.
I understand the inclination to re-use the ROA semantics, but I think
that an empty SEQUENCE OF is preferable in this situation.

Intuitively, I'd say that the most natural way to assert that a set is
empty is to create a signature over an empty set.

This is different to the ROA case in a couple of respects:
- ASId is an INTEGER type, which doesn't have a natural null-variant.
  The only way to introduce this would have been to make it OPTIONAL,
  which I would find confusing. A SEQUENCE OF on the other hand has a
  natural empty (and non-null) variant.
- The semantics of the set {0, 65000} seem weird (and possibly
  contradictory). We don't run into this with ASId, since it's a
  primitive type.

> > avoids the issue where one might find both AS0 and other provider ASNs.

Agreed.

> > in IPv6, but not in IPv4, or vice versa.

I don't follow. Surely { (65000, ipv4), (65001, ipv4) } means transit
free in ipv6 but not in ipv4?

Cheers,

Ben

---

From: Tim Bruijnzeels <[email-masked]>
Date: Fri, 29 Oct 2021 18:38:04 +0200

Hi Ben

> On 26 Oct 2021, at 11:10, Ben Maddison <[email-masked]> wrote:
> 
>>> 

Yes, that makes sense. This implies an empty sequence wrt v6.

Tim