Astro~/0.4
** Conformance / BPSec * PAGE 06 / 30
** Astro * Conformance
** /conformance/bpsec

Bundle Protocol Security

Coverage matrix: what this package implements, clause by clause.

Conformance Statement for pkg/bpsec, RFC 9172 and RFC 9173

RFC 9172 ships no PICS proforma, so what follows is a coverage matrix in the same shape as the rest of this section. Status M marks what the RFC makes mandatory for an implementation of the feature, O what it leaves optional.


A1.1 GENERAL INFORMATION

A1.1.1 Identification

FieldValue
Date of Statement (DD/MM/YYYY)04/09/2026
Serial NumberASTRO-BPSEC-COV-001
System Conformance Statement Cross-ReferenceThis document

A1.1.2 Identification of Implementation Under Test (IUT)

FieldValue
Implementation Nameastro/pkg/bpsec
Implementation VersionSee go.mod / latest commit on main
Special ConfigurationNone
Other InformationGo library implementing the BPSec block formats and the two default security contexts of RFC 9173: the Abstract Security Block, the Block Integrity Block, the Block Confidentiality Block, both canonicalization algorithms, and AES Key Wrap. Security policy and key management are out of scope, as are bundle agent behaviour and any convergence layer.

A1.1.3 Identification of Supplier

FieldValue
SupplierRavi Suhag
Contact Point for QueriesGitHub, github.com/ravisuhag/astro
Implementation Name(s) and Version(s)astro/pkg/bpsec (Go package)
System Name(s)Astro

A1.1.4 Identification of Specification

FieldValue
SpecificationRFC 9172 (Bundle Protocol Security, Standards Track, January 2022) with RFC 9173 (Default Security Contexts for BPSec, Standards Track, January 2022) and RFC 3394 (AES Key Wrap, Informational, September 2002)
Have any exceptions been required?Yes [X] No [ ], see A1.6

A1.2 SECURITY BLOCK STRUCTURE

FeatureReferenceStatusSupport
BIB block type code 119172 clause 11.1MY
BCB block type code 129172 clause 11.1MY
Security blocks use the canonical block format9172 clause 3.5MY: they are bp.CanonicalBlock values
Abstract Security Block field order9172 clause 3.6MY
Targets as a CBOR array of unsigned integers9172 clause 3.6MY
At least one target9172 clause 3.6MY: ErrNoTargets
No duplicate targets9172 clause 3.6MY: ErrDuplicateTarget
Every target names a block that exists9172 clause 3.6MY: ErrTargetNotInBundle
Targets named by block number9172 clause 3.4MY: block number 0 is the primary block
Context flags bit 0 means parameters present9172 clause 3.6MY
Reserved context flag bits written as zero9172 clause 3.6MY: ErrReservedContextFlag on encode
Reserved context flag bits ignored on read9172 clause 3.6MN: refused instead, see A1.6
Security source as an endpoint ID9172 clause 3.6MY: decoded by pkg/bp, so the dtn and ipn rules are shared
Parameters as [id, value] two-tuples9172 clause 3.6MY: values held as raw CBOR
Results ordered to match the targets9172 clause 3.6MY: one set per target, ErrResultCountMismatch otherwise
One security block may carry several operations9172 clause 3.3OY

A1.3 BLOCK INTERACTION RULES

FeatureReferenceStatusSupport
Security operations in a bundle are unique9172 clause 3.2MY: ErrDuplicateSecurityOperation
A BIB must not target a security block9172 clause 3.7MY: ErrIntegrityTargetsSecurityBlock
A BCB must not target another BCB9172 clause 3.8MY: ErrConfidentialityTargetsBCB
A BCB must not target the primary block9172 clause 3.8MY: ErrConfidentialityTargetsPrimary
A BCB targets a BIB only when they share a target9172 clause 3.8MY: ErrBCBTargetsUnsharedBIB
A BCB targeting the payload sets the fragment replication flag9172 clause 3.8MY: ErrBCBFragmentFlag
A BCB must not set the discard-if-unprocessable flag9172 clause 3.8MY: ErrBCBRemovableFlag
A BIB must not be added for a target a BCB encrypts9172 clause 3.9MY: ErrIntegrityAfterConfidentiality
A BIB is not checked when its target is encrypted9172 clause 3.9MY: Verify refuses
A BIB is not checked when the BIB itself is encrypted9172 clause 3.9MY: an encrypted BIB is skipped when scanning, not treated as malformed
A BCB encrypts its target in place9172 clause 3.8MY
When a BIB is encrypted at the same time, both go in one bundle9172 clause 3.9MY: either as a second BCB target or a separate BCB, at the caller's choice
Automatic splitting of a partly-covered BIB9172 clause 3.9MN: refused instead, see A1.6

A1.4 CANONICAL FORMS

FeatureReferenceStatusSupport
Deterministic CBOR in canonical forms9172 clause 4MY: shared with pkg/bp, which emits shortest-form arguments
A canonical data field includes its own CBOR encoding9172 clause 4MY: the IPPT quotes the block-type-specific data with its byte string head
No enclosing CBOR in a canonical field9172 clause 4MY: the array framing around a block is not included
Reserved and unassigned block flags zeroed in canonical form9172 clause 4MY: masked to bits 0, 1, 2 and 4
Only the block-type-specific data is encrypted9172 clause 4MY
IPPT step order and content9173 clause 3.7MY: pinned to appendices A.1, A.3 and A.4
IPPT skips the primary and target header steps when the target is the primary block9173 clause 3.7MY: pinned to appendix A.3
AAD step order and content9173 clause 4.7.2MY: pinned to appendices A.2 and A.4
Scope flags always included in the IPPT and the AAD9173 clauses 3.7, 4.7.2MY
BCB plaintext excludes the CBOR byte string head9173 clause 4.7.1MY

A1.5 SECURITY CONTEXTS

BIB-HMAC-SHA2, context identifier 1

FeatureReferenceStatusSupport
HMAC 256/256, 384/384, 512/5129173 clause 3.3.1MY: variants 5, 6 and 7
Output length equals the SHA-2 size9173 clause 3.1MY: checked on verify, ErrHMACLength
Default variant 6 when the parameter is absent9173 clause 3.3.1OY
Wrapped key parameter, number 29173 clause 3.3.2OY: RFC 3394
Integrity scope flags, number 39173 clause 3.3.3OY
Default scope 7 when the parameter is absent9173 clause 3.3.3OY
Reserved and unassigned scope bits zeroed9173 clause 3.3.3MY: ErrReservedScopeFlag
Expected HMAC as security result 19173 clause 3.4MY
Constant-time tag comparison9173 clause 3.6OY: hmac.Equal
Target CRC removed before the hash9173 clause 3.8.1MY
Key length equal to the HMAC output9173 clause 3.5MN: not enforced, see A1.6
CRC restored at a non-destination security acceptor9173 clause 3.8.2MN: not implemented, see A1.6

BCB-AES-GCM, context identifier 2

FeatureReferenceStatusSupport
A128GCM and A256GCM9173 clause 4.3.2MY: variants 1 and 3. Value 2 is not assigned and is refused
Default variant 3 when the parameter is absent9173 clause 4.3.2OY
Initialisation vector 8 to 16 octets, number 19173 clause 4.3.1OY: ErrIVLength
A missing IV treated as an error9173 clause 4.8.2OY: ErrMissingIV
Wrapped key parameter, number 39173 clause 4.3.3OY: RFC 3394
AAD scope flags, number 49173 clause 4.3.4OY
Authentication tag of 128 bits9173 clause 4.4.1MY: ErrTagLength
Tag carried as security result 19173 clause 4.4OY: always, rather than appended to the ciphertext
Tag appended to the ciphertext instead9173 clause 4.4ON: not implemented, see A1.6
Ciphertext replaces the plaintext in place9173 clause 4.8.1MY
Target CRC removed before encryption9173 clause 4.8.1MY
Plaintext restored on decryption9173 clause 4.8.2MY
A failed authentication yields no plaintext9173 clause 4.8.2MY: the bundle is left as it arrived

AES Key Wrap

FeatureReferenceStatusSupport
Wrap and unwrap, index-based form3394 clauses 2.2.1, 2.2.2MY
Default initial value A6A6A6A6A6A6A6A63394 clause 2.2.3.1MY
Key data of at least two 64-bit blocks3394 clause 2MY: ErrKeyDataLength
No key data returned when the check fails3394 clause 2.2.2MY: ErrIntegrityCheck
Alternative initial values3394 clause 2.2.3.2ON: the default only

A1.6 EXCEPTIONS AND UNSUPPORTED FEATURES

Security policy is not implemented. RFC 9172 clause 7 leaves to each deployment which security operations are required, which are optional, and what happens when one fails. This package reports success or failure and takes no action on the result. The status report reason codes of clause 7.1 are therefore not generated here either; they belong to whatever layer holds the policy.

Key management is not implemented. RFC 9172 clause 6 places it out of scope, and this package agrees. Keys are supplied by the caller.

Reserved security context flag bits are refused rather than ignored. Clause 3.6 asks a reader to ignore them. This package returns ErrReservedContextFlag. The reasoning matches the rest of astro: a flag this package does not understand may change how the block should be processed, and silently proceeding is the failure mode the project exists to avoid. A deployment that needs the lenient behaviour can read the raw block instead.

A partly-covered BIB is not split automatically. Clause 3.9 says that when a BCB covers some but not all of a BIB's targets, the affected results must be moved into a new BIB and that new BIB encrypted. Doing this on the caller's behalf would silently restructure their bundle and re-source a security block this node did not originate. Confidentiality.Add returns ErrBCBTargetsUnsharedBIB instead, and the caller does the split.

The HMAC key length rule of clause 3.5 is not enforced. The clause requires a key as long as the hash output. RFC 9173 appendix A.1 then signs with HMAC 512/512 under a 16-octet key. Enforcing the clause would reject the document's own worked example and every implementation pinned to it. HMAC accepts any key length by construction, so a short key works and is weaker than the clause intends. Callers who want the rule check before calling.

The authentication tag is always a security result. Clause 4.4 allows a tag to be appended to the ciphertext instead, and requires the target block to be resized when it is. This package always writes the tag as security result 1, which is what every worked example in appendix A does. It reads only that form too, and returns ErrMissingTag for a BCB that carries none.

A CRC is not restored when a security service is removed. Clauses 3.8.2 and 4.8.2 say that a security acceptor which is not the bundle destination must add a CRC back to a target it has finished with. The CRC type is a policy choice those clauses defer to the deployment, and this package holds no policy. The caller sets CRCType on the target after calling Verify or Decrypt.

Fragmentation of a bundle carrying security blocks is not handled here. RFC 9172 clause 5.2 leaves the rules to the bundle agent, and fragmentation lives in pkg/bp.


A1.7 IMPLEMENTATION LIMITS

LimitValueSource
Security context identifier0 to 2^64 - 1 as decoded
Scope flags16 bits
Initialisation vector8 to 16 octets
Authentication tag16 octets
Key data for AES Key Wrapa whole number of 8-octet blocks, at least two
Targets per security blockbounded by the input slice

Wire test vectors

The octets backing this statement live in the vector corpus — 13 vectors, plus 6 more for AES Key Wrap. Each names the clause it comes from and carries the derivation that produced it.

File
bpsec/security.json13 vectors
keywrap/keywrap.json6 vectors

Nearly all of them are published octets rather than derived values. RFC 9173 appendix A prints four worked examples with their keys, their intermediate canonical forms and the blocks that come out; RFC 3394 clause 4 prints six key wrap cases. Both are outside corroboration — different working groups wrote those bytes.

Two vectors run against a bundle assembled from pieces the appendix prints separately rather than one it prints whole, and say so in their own note.

These are data files, so any implementation can check itself against the same octets. See CONTRACT.md for how, and how this is verified for what rests on a published vector versus a reading of the clause.