# 07. ROA（Route Origin Authorization）

## 7.1 对象定位

ROA 是一种 RPKI Signed Object，用于声明“某 AS 被授权起源某些前缀”。RFC 9582 §1；RFC 9582 §4。

ROA 由 CMS 外壳 + ROA eContent 组成：

- 外壳：RFC 6488（更新：RFC 9589）
- eContent：RFC 9582

## 7.2 原始载体与编码

- 外壳：CMS SignedData DER（见 `05_signed_object_cms.md`）。RFC 9582 §1（引用 RFC 6488）。
- eContentType：`id-ct-routeOriginAuthz`，OID `1.2.840.113549.1.9.16.1.24`。RFC 9582 §3。
- eContent：DER 编码 ASN.1 `RouteOriginAttestation`。RFC 9582 §4。

### 7.2.1 eContentType 与 eContent 的 ASN.1 定义（RFC 9582 §3；RFC 9582 §4）

ROA 是一种 RPKI signed object（CMS 外壳见 `05_signed_object_cms.md`）。RFC 9582 定义了其 `eContentType` 以及 `eContent`（payload）的 ASN.1。RFC 9582 §3-§4。

**eContentType（OID）**：RFC 9582 §3。

```asn1
id-ct-routeOriginAuthz OBJECT IDENTIFIER ::=
  { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
    pkcs-9(9) id-smime(16) id-ct(1) routeOriginAuthz(24) }
```

**eContent（ROA ASN.1 模块）**：RFC 9582 §4。

```asn1
RPKI-ROA-2023
  { iso(1) member-body(2) us(840) rsadsi(113549)
  pkcs(1) pkcs9(9) smime(16) mod(0)
  id-mod-rpkiROA-2023(75) }

DEFINITIONS EXPLICIT TAGS ::=
BEGIN

IMPORTS
  CONTENT-TYPE
  FROM CryptographicMessageSyntax-2010 -- in [RFC6268]
    { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
      pkcs-9(9) smime(16) modules(0) id-mod-cms-2009(58) } ;

ct-routeOriginAttestation CONTENT-TYPE ::=
  { TYPE RouteOriginAttestation
    IDENTIFIED BY id-ct-routeOriginAuthz }

id-ct-routeOriginAuthz OBJECT IDENTIFIER ::=
  { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
    pkcs-9(9) id-smime(16) id-ct(1) routeOriginAuthz(24) }

RouteOriginAttestation ::= SEQUENCE {
  version [0]   INTEGER DEFAULT 0,
  asID          ASID,
  ipAddrBlocks  SEQUENCE (SIZE(1..2)) OF ROAIPAddressFamily }

ASID ::= INTEGER (0..4294967295)

ROAIPAddressFamily ::= SEQUENCE {
  addressFamily ADDRESS-FAMILY.&afi ({AddressFamilySet}),
  addresses     ADDRESS-FAMILY.&Addresses
                               ({AddressFamilySet}{@addressFamily}) }

ADDRESS-FAMILY ::= CLASS {
  &afi          OCTET STRING (SIZE(2)) UNIQUE,
  &Addresses
} WITH SYNTAX { AFI &afi ADDRESSES &Addresses }

AddressFamilySet ADDRESS-FAMILY ::=
  { addressFamilyIPv4 | addressFamilyIPv6 }

addressFamilyIPv4 ADDRESS-FAMILY ::=
  { AFI afi-IPv4 ADDRESSES ROAAddressesIPv4 }
addressFamilyIPv6 ADDRESS-FAMILY ::=
  { AFI afi-IPv6 ADDRESSES ROAAddressesIPv6 }

afi-IPv4 OCTET STRING ::= '0001'H
afi-IPv6 OCTET STRING ::= '0002'H

ROAAddressesIPv4 ::= SEQUENCE (SIZE(1..MAX)) OF ROAIPAddress{ub-IPv4}
ROAAddressesIPv6 ::= SEQUENCE (SIZE(1..MAX)) OF ROAIPAddress{ub-IPv6}

ub-IPv4 INTEGER ::= 32
ub-IPv6 INTEGER ::= 128

ROAIPAddress {INTEGER: ub} ::= SEQUENCE {
  address       BIT STRING (SIZE(0..ub)),
  maxLength     INTEGER (0..ub) OPTIONAL }

END
```

编码/解码要点（与上面 ASN.1 结构直接对应）：

- `addressFamily` 仅允许 IPv4/IPv6 两种 AFI，并且每个 AFI 最多出现一次。RFC 9582 §4.3.1。
- `address` 是 BIT STRING 表示的前缀，语义与 RFC 3779 的 `IPAddress` 一致（按前缀长度截断，DER unused bits 置零）。RFC 9582 §4.3.2.1（引用 RFC 3779 §2.2.3.8）。
- `maxLength` 为可选字段，出现与否会影响语义与编码规范约束（例如等于前缀长时不建议编码）。RFC 9582 §4.3.2.2。

## 7.3 解析规则（eContent 语义层）

输入：`RpkiSignedObject`。

1) 解析 CMS 外壳，得到 `econtent_type` 与 `econtent_der`。RFC 6488 §3；RFC 9589 §4。  
2) 要求 `econtent_type == 1.2.840.113549.1.9.16.1.24`。RFC 9582 §3。  
3) 将 `econtent_der` 以 DER 解析为 `RouteOriginAttestation` ASN.1。RFC 9582 §4。  
4) 将 `ipAddrBlocks` 解析为“前缀集合”的语义结构，并建议按 RFC 9582 给出的 canonicalization 过程做去重/排序/归一化（以便后续处理一致）。RFC 9582 §4.3.3。

## 7.4 抽象数据模型（接口）

### 7.4.1 `RoaObject`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `signed_object` | `RpkiSignedObject` | CMS 外壳 | 外壳约束见 RFC 6488/9589 | RFC 9582 §1；RFC 6488 §3；RFC 9589 §4 |
| `econtent_type` | `Oid` | eContentType | 必须为 `1.2.840.113549.1.9.16.1.24` | RFC 9582 §3 |
| `roa` | `RoaEContent` | eContent 语义对象 | 见下 | RFC 9582 §4 |

### 7.4.2 `RoaEContent`（RouteOriginAttestation）

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `version` | `int` | version | MUST 为 0 | RFC 9582 §4.1 |
| `as_id` | `int` | asID | 0..4294967295 | RFC 9582 §4（ASID 定义）；RFC 9582 §4.2 |
| `ip_addr_blocks` | `list[RoaIpAddressFamily]` | ipAddrBlocks | `SIZE(1..2)`；最多 IPv4/IPv6 各一个；建议 canonicalize | RFC 9582 §4；RFC 9582 §4.3.1；RFC 9582 §4.3.3 |

### 7.4.3 `RoaIpAddressFamily`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `afi` | `enum { ipv4, ipv6 }` | Address Family | MUST 为 IPv4(0001) 或 IPv6(0002) | RFC 9582 §4.3.1 |
| `addresses` | `list[RoaIpAddress]` | 前缀列表 | `SIZE(1..MAX)`；每项为前缀 + 可选 maxLength | RFC 9582 §4（ROAAddressesIPv4/IPv6）；RFC 9582 §4.3.2 |

### 7.4.4 `RoaIpAddress`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `prefix` | `IpPrefix` | 前缀 | address 以 BIT STRING 表示前缀（同 RFC 3779 IPAddress 表示） | RFC 9582 §4.3.2.1（引用 RFC 3779 §2.2.3.8） |
| `max_length` | `optional[int]` | 最大允许前缀长 | 若存在：必须 `>= prefix_len` 且 `<= 32/128`；并且 `maxLength == prefix_len` 时 **SHOULD NOT** 编码（未来 RP 可能视为编码错误） | RFC 9582 §4.3.2.2 |

## 7.5 字段级约束清单（实现对照）

- eContentType 必须为 `id-ct-routeOriginAuthz`（OID `1.2.840.113549.1.9.16.1.24`），且该 OID 必须同时出现在 eContentType 与 signedAttrs.content-type。RFC 9582 §3（引用 RFC 6488）。
- eContent 必须 DER 编码并符合 `RouteOriginAttestation` ASN.1。RFC 9582 §4。
- `version` 必须为 0。RFC 9582 §4.1。
- `ipAddrBlocks` 长度为 1..2；每种 AFI 最多出现一次；仅支持 IPv4/IPv6。RFC 9582 §4；RFC 9582 §4.3.1。
- `maxLength` 若存在必须在范围内，且不应出现“等于前缀长”的冗余编码。RFC 9582 §4.3.2.2。
- 建议按 canonical form 归一化/排序以利一致处理。RFC 9582 §4.3.3。

## 7.6 与 EE 证书的语义约束（为后续验证准备）

ROA 的外壳包含一个 EE 证书，用于验证 ROA 签名；RFC 对该 EE 证书与 ROA payload 的匹配关系提出要求：

- ROA 的 EE 证书必须是有效的 RPKI EE 证书（路径从 TA 到 EE 可建立），并用于验证 CMS 签名。RFC 9582 §1（引用 RFC 6488）；RFC 6488 §3(2)-(3)。
- ROA EE 证书中的 IP 资源扩展必须存在且不得使用 inherit。RFC 9582 §5。
- ROA EE 证书中 AS 资源扩展不得出现。RFC 9582 §5。
- ROA payload 中每个前缀必须包含在 EE 证书的 IP 资源集合内（资源包含语义来自 RFC 3779）。RFC 9582 §5；RFC 3779 §2.3。
