[Cbor] Re: Bundle protocol RFC 9171 design problems

Brian Sipos <brian.sipos+ietf@gmail.com> Sun, 12 July 2026 00:32 UTC

Return-Path: <brian.sipos@gmail.com>
X-Original-To: cbor@mail2.ietf.org
Delivered-To: cbor@mail2.ietf.org
Received: from localhost (localhost [127.0.0.1]) by mail2.ietf.org (Postfix) with ESMTP id A05B911535F15 for <cbor@mail2.ietf.org>; Sat, 11 Jul 2026 17:32:50 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1; t=1783816370; bh=jDeVdMZovpx81ufiQcRpd7PMYPfwycPAUc7eIkdsnj4=; h=References:In-Reply-To:From:Date:Subject:To:Cc; b=lb8HcygXPxsv2cdRYycdjqtiWJq3N7JEBRuBViaU7DlcIcoOs2/75T8N2j+Tjoun1 QiodGTzabgcoKYSs3siXVsKO6xWjlkAxD887t4ktlwKn72Vgj5CPSwz9oeu4mu1nqm 8KQ1OAiL/L+rM5QTskd1CR42HeaOVRB0LRi0uNLA=
X-Virus-Scanned: amavisd-new at ietf.org
X-Spam-Flag: NO
X-Spam-Score: -2.098
X-Spam-Level:
X-Spam-Status: No, score=-2.098 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: mail2.ietf.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail2.ietf.org ([166.84.6.31]) by localhost (mail2.ietf.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Khu8hGwHUyHX for <cbor@mail2.ietf.org>; Sat, 11 Jul 2026 17:32:49 -0700 (PDT)
Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256) (No client certificate requested) by mail2.ietf.org (Postfix) with ESMTPS id 8F9F811535F07 for <cbor@ietf.org>; Sat, 11 Jul 2026 17:32:49 -0700 (PDT)
Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-47dec32798aso2112669f8f.1 for <cbor@ietf.org>; Sat, 11 Jul 2026 17:32:49 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1783816362; cv=none; d=google.com; s=arc-20260327; b=BOZvGKNYowqBCXy2xwKLv+IoTtNpyDx8Oe3TU87lI/U+f6Z66ZUM/EkGfH/zz4+mbW K0ae+cQSZDgxYTESvk+5PSmpMo56rkRgCSVW8hacx489YWzCjsu5EDrCmrh6uk0peTiW U4oI1Y5ghkXn2dwXstdNY+Bj3hKqpixGHbxrg8lBiONxPevAEDNoed1feiZbHJ2T4g0J C7VxVeTWWslSyI760FlzoMIRxdVYQhJJqGzc/EmTfhLYO+WdLYI9gORJ2lTYcOMbcM+s azzX2Yfd2xbDMR9jR1joDiMiaEkqMgySrSeGbtnhflynaUJQ8wBsbdOP7x/eTqkbzygq mspw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=ku0t936bA5JcQoBaODe3feeSUxHq+6F7vwkx2yw3DdE=; fh=hXlwsRxi41+e1WjhVyDC204R3UDt9xSJ4bvXYRCna1g=; b=qqX6Lgpfv7oL7DiHbG6+e3yyhMQmqdNrjzoXoWojJVBpRoXX641n8n3Nlxv7slVayH /ELmzZ/W65xozIqE8SJ9XPU4eFOGpPs/mc+V31t2pvvkmzbwt/sOO0R3Z6wFdbz8FU0y wtnJPNyqzlY0DMkVAJvUHfeNvneGlrywninEDTH20p/+7pvybeamcHDCtUhCUzw7gGZS lp2XIVhfdN15VE9acE3lESHiztUMaklV29bdwORi03Pd9xfj36sXjslvirTFqWCbSHvo kYxcIcXTXEppi4Uh/bEO0NGTlF2sy/fTYaqBzDlOSMIzZHAk7TUpLokx3L/M+slOm/0/ sYeA==; darn=ietf.org
ARC-Authentication-Results: i=1; mx.google.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783816362; x=1784421162; darn=ietf.org; h=content-type:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ku0t936bA5JcQoBaODe3feeSUxHq+6F7vwkx2yw3DdE=; b=Ato3uRp2bfAYB55rvdgVdOUHNNikO3ZlajDEXbn5A1sMXewLs9QLErWpTIGWkYfoLJ PJzedoLUtFn983P6SQFBQfn9RKaRBylK23bcA5QMXWEXixTQ2KFxmjlLf+XlSLWdfiwR BWF12xnhCfJKw3RRU4Jnk1A4oz38qu0BPN0s3kOshYPQ5DgCbOMBOg6MyDo4rxxHzbJ+ q4xj8Qkf9tis+zeKbT28d8t4vIWUGD3JM2Mc4pKRguGla5VBe0CVcXK2mVQYV2KuGSAR UOr3hUqkYXXW+v4iPh/b3vVq3x5uubOhNtPW38ic3RrHMtlblUprneXBIGNG8U423GKI qbPA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783816362; x=1784421162; h=content-type:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=ku0t936bA5JcQoBaODe3feeSUxHq+6F7vwkx2yw3DdE=; b=ciPvm9HH8p9EylUqOOTuVeE+taPaV4+rcKrqucCgtslkmuKazq0gJucM6j/hf8j58o 5heLXUHrnmuyJUa/KejtdTQJzW6+n4xvB8WkGjps5JDHNectt6jS0IRCYnzmHsKKU0BE zCxS9rJRjp717jNNtmsq8oZU0fOESNBd28R1PaMFHstVp4WQ89UdaOAc2vBcCcYvA5Bc Eueq+vGYI8+HMeD1D1t0UgkAp3mF0KeciNl9dFsbWCi5YaLtGJLIxFA/xSdjgp0Z9EM8 3kKRc1f3n+VN0RmtfDnAUTRsYnJc+UoT0nGqVZAJJqV+pYCukprBs2G/qIZwLY+p0xka Ff5A==
X-Forwarded-Encrypted: i=1; AHgh+RodkXI4pyxkPicl8Q5RBQA1o4Q4ymVDnv9CSPboL3ZnOhBC1z2EckAFjxc7+BttdAaUvqJ9@ietf.org
X-Gm-Message-State: AOJu0Yw+WK0QVoa0JZfb98tS6keoGjVaDNcFtQV0a7g7I93y93on+r7D MIoR43WO78Z8BQZDJj7GxccpTjluQ5pYxIZVL6HadUwkIrBV+2f48driKMaSa64GBMlpGzUEolg 2TRWlh9u5z6Hmzu/wsBb/Yc1xwQurTbM=
X-Gm-Gg: AfdE7ck7qdQkOzTot81+hqvZbwPCmUz8eqYpGCfAW2TRs9hJ9rjlXRxSVQkUT4YY7rO 7cA3V0KepPfVdBlBm7pbVbQsQMHgezz1NDkEV675T2vSMBDqUTKi32JnITFQapKUXDCTp+cYuOU 8D/x3+M0LSvMiaOyJkYG4F0XLX29sbixXZDPiTXxjq7YUroOcwnF5aD1xHWU9gL5JbLDpDzBoIi 8VJqPGMsIvHyLXLX5IyOpRhcHoeTvjb0br18AeXtLon1DPYWAmq8W5lnA5ZdvBuH9EVvRFi4v8v vibZLOOpdNWi6Iigw5paeU3sjxnPco5C0b+njvG07g==
X-Received: by 2002:a05:6000:607:b0:46f:7d90:811c with SMTP id ffacd0b85a97d-47f2dc9b83fmr4907970f8f.13.1783816362428; Sat, 11 Jul 2026 17:32:42 -0700 (PDT)
MIME-Version: 1.0
References: <572F183F-6B0B-415D-8850-9F8C090D4BC1@island-resort.com> <64E3E47C-5651-4D70-881C-308A6E67D3DA@island-resort.com> <CAM1+-gjF+8mm0fPWbhWsi08pWMO_6mtg0ko0JZu1FG_YVvhgHg@mail.gmail.com> <97C46888-9346-4C13-BD59-1D44A309CD01@island-resort.com> <CAM1+-gj2CHga8axP9HMTx5VR-1pnnTc7WzhN+v0B3Uzm6vnSog@mail.gmail.com> <B1F9873D-4559-4574-9817-C99BA07387B0@island-resort.com> <20260712014720.140899ef@nuclight.lan>
In-Reply-To: <20260712014720.140899ef@nuclight.lan>
From: Brian Sipos <brian.sipos+ietf@gmail.com>
Date: Sat, 11 Jul 2026 20:32:31 -0400
X-Gm-Features: AUfX_mwOPresRuA3gnsTUTLNwRpqSMsz-fMyHb1zg59Q1cB4hB7mDGik68zPklM
Message-ID: <CAM1+-giVg9MncxXRE4QfHbm=_WiZtTcqHHE7V=D5S8kpBGKL2w@mail.gmail.com>
To: Vadim Goncharov <vadimnuclight@gmail.com>
Content-Type: multipart/alternative; boundary="000000000000a08be106565f1cfe"
Message-ID-Hash: HW5STSJZ56ANDH2E3RQOI4RZX2BAOCSJ
X-Message-ID-Hash: HW5STSJZ56ANDH2E3RQOI4RZX2BAOCSJ
X-MailFrom: brian.sipos@gmail.com
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-cbor.ietf.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Laurence Lundblade <lgl@island-resort.com>, CBOR <cbor@ietf.org>
X-Mailman-Version: 3.3.9rc6
Precedence: list
Subject: [Cbor] Re: Bundle protocol RFC 9171 design problems
List-Id: "Concise Binary Object Representation (CBOR)" <cbor.ietf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/cbor/kj5IE5qwK6iMNagu-lOY-z9fCiU>
List-Archive: <https://mailarchive.ietf.org/arch/browse/cbor>
List-Help: <mailto:cbor-request@ietf.org?subject=help>
List-Owner: <mailto:cbor-owner@ietf.org>
List-Post: <mailto:cbor@ietf.org>
List-Subscribe: <mailto:cbor-join@ietf.org>
List-Unsubscribe: <mailto:cbor-leave@ietf.org>

Thank you for this analysis. I can explain the rationale for the Wireshark
implementation is twofold: the BPv7 addition just used existing crc
functions (which are one shot, not incremental), and accessing contiguous
data from a tvbuff_t structure will usually involve a buffer copy anyway
because these PDUs will usually be the result of segmentation reassembly
from multiple capture frames.

If there were a pressing need, the Wireshark CRC API could be made to act
on a tvbuff hierarchy directly and be zero-copy. But that is a substantial
change to that API.

Brian S.

On Sat, Jul 11, 2026, 18:47 Vadim Goncharov <vadimnuclight@gmail.com> wrote:

> On Thu, 9 Jul 2026 12:29:57 -0700
> Laurence Lundblade <lgl@island-resort.com> wrote:
>
> > I go on too long; summary:
> >  - Brian is right. Modifying the decode input buffer is not needed with
> > incremental (sequential, chunked…) hash/crc implementations
> >  - Seems possible to support Bundle with some generally useful and
> long-term
> > maintainable APIs
> >  - Byte string wrapping would have allowed implementation with every CBOR
> > library, even simple-minded ones
> >
> > For decode, what is needed is the pointer and length of the CBOR items
> that
> > are input to the hash/crc. In the case of the array holding a bundle
> block,
> > that means decoding everything in the array. An API that returns the
> start
> > (a pointer) and length of a full CBOR item like an array with all its
> member
> > items seems like a general and useful design. This seems OK as a
> long-term
> > supported general feature for QCBOR.
>
> Actually, as you will see below, this is enough for Bundle *when* there is
> no
> 0xFF after CRC field (and even then, you just have to branch on two
> possible
> values), for which may be errata needed, I don't sure. This is
> continuation of
> https://mailarchive.ietf.org/arch/msg/cbor/_NdRMMh6LMB4GA60ahJ0IV7tjz8/
> message with research about CRC and Bundle implementations.
>
> > This API should work for CBOR::Core too.
> >
> > But, Bundle has one more issue. The hash/crc calculation can’t be done
> over
> > all the members in the array because the CRC, which has to be substituted
> > with zeros, is in the array. The Bundle design recognized this and always
> > puts the CRC last, so you can just subtract 2 or 4 from the full length.
>
> It can, if you're about decoder, see below.
>
> > If byte string wrapping were used, the recursive decode is not needed
> > because the length is (redundantly) present. The byte string can be
> > efficiently decoded and hashed with any simple-minded CBOR library
> without
> > any extra API. (Score card: fxamaker has the advanced API, QCBOR will add
> > it, Python cbor2 doesn’t)
> >
> > I expect to support any API I put in my library forever with full
> backwards
> > compatibility, regression tests, and documentation. I expect Bundle
> > implementations to want that from libraries they use and want to provide
> > that to their consumers.  I don’t want future features to be pinned in by
> > backwards compatibility for dumb APIs that weren’t thought through.
> That’s
> > why I’m fussing more here and why byte string wrapping is beneficial.
> >
> > On the encode side:
> >     AddRewritableBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes,
> > QCBORRewriteHandle *Handle); RewriteBytes(QCBOREncodeContext *pCtx,
> > QCBORRewriteHandle Handle, UsefulBufC Bytes);
> >
> > The Handle and Rewrite API are to provide pointer safety and a way to
> manage
> > future features that might interact where just returning a target pointer
> > and length wouldn’t.
>
> So, continuing message about Wireshark and other, I've played with CRC,
> and I
> now can say you *can* check whether CRC32c is correct because it is last
> field.
>
> Bundle refers to RFC 7143 for CRC32c (which has same definition that CRC is
> put in last 4 bytes which are filled with 0's during calculation) and it
> (p. 231) states:
>
>    - The CRC bits are mapped into the digest word.  The x**31
>      coefficient is mapped to bit 7 of the lowest numbered byte of the
>      digest, and the mapping continues with successive coefficients and
>      bits so that the x**24 coefficient is mapped to bit 0 of the lowest
>      numbered byte.  The mapping continues further with the x**23
>      coefficient mapped to bit 7 of the next byte in the digest until
>      the x**0 coefficient is mapped to bit 0 of the highest numbered
>      byte of the digest.
>
>    - Computing the CRC over any segment (data or header) extended to
>      include the CRC built using the generator 0x11edc6f41 will always
>      get the value 0x1c2d19ed as its final remainder (R(x)).  This value
>      is given here in its polynomial form (i.e., not mapped as the
>      digest word).
>
> [... p.260]
>
> A.4.  CRC Examples
>
>    Note: All values are hexadecimal.
>
>    32 bytes of zeroes:
>
>       Byte:        0  1  2  3
>
>          0:       00 00 00 00
>        ...
>         28:       00 00 00 00
>
>        CRC:       aa 36 91 8a
>
>    32 bytes of ones:
>
>       Byte:        0  1  2  3
>
>          0:       ff ff ff ff
>        ...
>         28:       ff ff ff ff
>
>        CRC:       43 ab a8 62
>
> That is, if CRC is calculated over data with CRC put into it, where prior
> CRC
> was of that data plus four zero bytes, then such calculation will always
> result in SAME number iff CRC is correct (data not corrupted)
>
> There is some play with mapping of CRC word (above definition),
> little-endian
> vs big-endian, so playing with Perl module which allows different CRCs by
> proper configuring, have following results:
>
> $ perl -MDigest::CRC -e '
>   my $ctx1 = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
> $ctx1->add("\x00"
> x 32); print sprintf("Step 1 (CRC for 32 zero): %08x\n", $ctx1->digest);
> '
>
> Step 1 (CRC for 32 zero): 8a9136aa
>
> $ perl -MDigest::CRC -e '
>   my $ctx1 = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
> $ctx1->add("\xff"
> x 32); print sprintf("Step 1 (CRC for 32 1): %08x\n", $ctx1->digest);
> '
>
> Step 1 (CRC for 32 1): 62a8ab43
>
> --> this is what you get for RFC 7143 first two test vectors, so here we
> know
>     that initialization parameters were correct.
>
> $ perl -MDigest::CRC -e '
>   my $ctx1 = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
> $ctx1->add("FreeBSD"); print sprintf("Step 1 (CRC for FreeBSD): %08x\n",
> $ctx1->digest); '
>
> Step 1 (CRC for FreeBSD): f0883564
>
> $ perl -MDigest::CRC -e '
>   my $ctx = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
>
>   # Add four bytes of CRC in reversed order
>   my $data = "FreeBSD" . pack("C*", 0x64, 0x35, 0x88, 0xf0);
>
>   $ctx->add($data);
>   print sprintf("End-to-end verification result: %08x\n", $ctx->digest);
> '
>
> End-to-end verification result: 48674bc7
>
> $ perl -MDigest::CRC -e '
>   my $ctx1 = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1); $ctx1->add("yet
> another test"); print sprintf("Step 1 (CRC for yet another test): %08x\n",
> $ctx1->digest);
> '
>
> Step 1 (CRC for yet another test): 7b165e79
>
> $ perl -MDigest::CRC -e '
>   my $ctx = Digest::CRC->new(width => 32, poly => 0x1EDC6F41, init =>
> 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
>   # Add four bytes of CRC in reversed order
>   my $data = "yet another test" . pack("C*", 0x79, 0x5e, 0x16, 0x7b);
>
>   $ctx->add($data);
>   print sprintf("End-to-end verification result: %08x\n", $ctx->digest);
> '
>
> End-to-end verification result: 48674bc7
>
> As you can see, it is always 48674bc7 !
>
> What is 48674bc7 ?
>
> See, original from RFC 7143 = 0x1c2d19ed which is
>
>    0001 1100 0010 1101 0001 1001 1110 1101
>
> mirror reflection of it (see "mapping digest word") is
>
>    1011 0111 1001 1000 1011 0100 0011 1000
>
> or 0xb798b438, and
>
>    0xb798b438 XOR 0xFFFFFFFF = 0x48674bc7
>
>
> To conclude, IF the CRC field in Bundle is definite-length array, then all
> the
> API you have to have in decoder is just to feed entire array's
> representation,
> even incremental adding is not needed. But IF if is INDEFINITE-length
> array,
> then you'll also get stable number - given that of state of the
> accumulating
> register and single FF byte, which is always same in such situation.
>
> I am not sure if an Errata should filed against 9171 stating that array of
> block must be of definite-length, so that optimization using this CRC
> property
> for non-copy could be used without branching. Two implementations (Go and
> Wireshark) I've digged in previous message - do not use it and instead copy
> memory.
>
> --
> WBR, @nuclight
>