<?xml version='1.0' encoding='utf-8'?>

<?xml-model href="rfc7991bis.rnc"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
  <!ENTITY zwsp "&#8203;">
  <!ENTITY nbhy "&#8209;">
  <!ENTITY wj "&#8288;">
]>

<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
  category="exp"
  docName="draft-irtf-icnrg-flic-07"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IRTF"
  xml:lang="en"
  tocInclude="true"
  tocDepth="3"
  symRefs="true"
  sortRefs="true"
  version="3">

  <!-- ***** FRONT MATTER ***** -->
  <front>
    <title abbrev="FLIC">File-Like ICN Collections (FLIC)</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-icnrg-flic-07" />

    <author fullname="Christian Tschudin" initials="C." surname="Tschudin">
      <organization>University of Basel</organization>
      <address>
        <email>christian.tschudin@unibas.ch</email>
      </address>
    </author>

    <author fullname="Christopher A. Wood" initials="C.A." surname="Wood">
      <organization>Cloudflare</organization>
      <address>
        <email>caw@heapingbits.net</email>
      </address>
    </author>

    <author fullname="Marc Mosko" initials="M.E." surname="Mosko">
      <organization></organization>
      <address>
        <email>marc@mosko.org</email>
      </address>
    </author>

    <author fullname="David Oran" initials="D." surname="Oran" role="editor">
      <organization>Network Systems Research &amp; Design</organization>
      <address>
        <email>daveoran@orandom.net</email>
      </address>
    </author>

    <date />
    <area>IRTF</area>
    <workgroup>ICNRG</workgroup>
    <keyword>Information Centric Networking</keyword>

    <abstract>
      <t>This document describes how to encode an application data objet into a structured <em>
        manifest</em> using Information Centric Networking (ICN) data objects, creating a File-Like
        ICN Collection (FLIC). The manifest is an "index table" of objects that make up the manifest
        itself and the application data. It records the hash value (content object hash) of each
        item so a consumer using the manifest may request each piece by a complete hash name. The
        manifest is hierarchical and may be encoded into realtively small ICN objects to fit within
        network MTU sizes. FLIC has several methods to guide a consumer in constructing appropriate
        Interest names based on the manifest. It also supports encryption of the manifest data. FLIC
        may be used in CCNx or Named Data Networking, or other ICNs. </t>
    </abstract>
  </front>

  <middle>
    <section>
      <name>Introduction</name>
      <t>ICN architectures, such as Content-Centric Networking (CCNx)<xref target="RFC8569"
          format="default" /> and Named Data Networking <xref target="NDN" format="default" />, are
        well suited for static content distribution. Each piece of (possibly immutable) static
        content is assigned a name by its producer. Consumers fetch this content using said name.
        Optionally, consumers may specify the full name of content, which includes its name and a
        cryptographic digest of said content, so the reques is self-verifying. </t>

      <aside>
        <t>Note: The reader is assumed to be familiar with general ICN concepts from CCNx or NDN.
          For general ICN terms, this document uses the terminology defined in <xref
            target="RFC7927" format="default" />. Where more specificity is needed, we utilize <xref
            target="RFC8569" format="default">CCNx</xref> terminology where a Content Object is the
          data structure that holds application payload. Terms defined specifically for FLIC are
          enumerated below in <xref target="Terminology"
          />.</t>

        <t>
          In this document, we prefer the CCNx terminology. We will use the CCNx term
          Content Object, where NDN would use the term Data packet. The term Content Objec Hash
          in CCNx corresponds to the NDN Implicit Digest.
        </t>
      </aside>

      <t>To enable requests with full names, consumers need <em>a priori</em> knowledge of content digests.
        A Manifest, a form of catalog, is a data structures commonly employed to store and transport
        this information. Typically, ICN manifests are signed content objects (data) which carry a
        collection of hash digests. As content objects, a manifest itself may be
        fetched by full name. A manifest may contain either hash digests of, or pointers to,
        either other manifests or content objects. A collection of manifests and content objects
        represents a large piece of application data, e.g., one that cannot otherwise fit in a
        single content object. Because a manifest contains a collection of hashes, it is by
        definition non-circular because one cannot hash the manifest before filling it in.</t>

      <t>Structurally, this relationship between manifests and content objects is reminiscent of the
        UNIX inode concept with index tables and memory pointers. In this document, we specify a
        simple, yet extensible, manifest data structure called FLIC - <em>File-Like ICN
          Collection</em>. FLIC is suitable for ICN protocol suites such as CCNx and NDN. We
        describe the FLIC design, grammar, and various use cases, e.g., ordered fetch, seeking,
        de-duplication, extension, and variable-sized encoding. We also include FLIC encoding
        examples for CCNx and NDN.</t>

      <t>The purpose of a manifest is to concisely name, and hence point to, the constituent pieces
        of a larger object. A FLIC manifest does this by using a <em>root</em> manifest to name and
        cryptographically sign the data structure and then use concise lists of hash-based names to
        indicate the constituent pieces. This maintains strong security from a single signature. A
        Manifest entry gives one enough information to create an <em>Interest</em> for that entry,
        so it must specify the name, the hash digest, and if needed, the locators.</t>

      <t>FLIC is not an archive format, like <em>tar</em> or <em>LTFS</em> or <em>iso</em>.  FLIC represents a single object that may be reconstructed by concatenating all the data pieces.  Future extensions could
      define a new type of structure that aggregates multiple FLIC manifests into an archive.</t>

      <t> FLIC is a distributed data structure illustrated by the following picture. The FLIC
        manifest is encoded in the Payload of a Content Object. A <em>root manifest</em> has a name
        and a publisher signature. Subsequent manifests, because they hare in a cryptographic hash
        tree using SHA256 pointers, do not need to be signed; they have implicit trust. In the
        figure we call out "data pointer" and "manifest pointer", but in the actual encoding they
        are all just hash values and the consumer does not necessarily know what it is fetching
        until it has fetched it. </t>

      <figure anchor="example_manifest">
        <name>Simplified FLIC Content Object and acyclic graph example</name>
        <artset>
          <artwork type="svg" name="example_manifest.svg" align="center">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="80%" viewBox="0 0 672 272"
              class="diagram" text-anchor="middle" font-family="monospace" font-size="13px"
              stroke-linecap="round">
              <path d="M 8,16 L 8,256" fill="none" stroke="black" />
              <path d="M 24,80 L 24,224" fill="none" stroke="black" />
              <path d="M 288,80 L 288,136" fill="none" stroke="black" />
              <path d="M 288,184 L 288,224" fill="none" stroke="black" />
              <path d="M 304,16 L 304,136" fill="none" stroke="black" />
              <path d="M 304,184 L 304,256" fill="none" stroke="black" />
              <path d="M 344,128 L 344,160" fill="none" stroke="black" />
              <path d="M 368,176 L 368,224" fill="none" stroke="black" />
              <path d="M 528,128 L 528,160" fill="none" stroke="black" />
              <path d="M 8,16 L 88,16" fill="none" stroke="black" />
              <path d="M 224,16 L 304,16" fill="none" stroke="black" />
              <path d="M 24,80 L 104,80" fill="none" stroke="black" />
              <path d="M 176,80 L 288,80" fill="none" stroke="black" />
              <path d="M 344,128 L 528,128" fill="none" stroke="black" />
              <path d="M 240,144 L 328,144" fill="none" stroke="black" />
              <path d="M 344,160 L 528,160" fill="none" stroke="black" />
              <path d="M 272,176 L 320,176" fill="none" stroke="black" />
              <path d="M 368,176 L 384,176" fill="none" stroke="black" />
              <path d="M 624,176 L 640,176" fill="none" stroke="black" />
              <path d="M 328,192 L 352,192" fill="none" stroke="black" />
              <path d="M 624,192 L 664,192" fill="none" stroke="black" />
              <path d="M 624,208 L 664,208" fill="none" stroke="black" />
              <path d="M 24,224 L 288,224" fill="none" stroke="black" />
              <path d="M 368,224 L 640,224" fill="none" stroke="black" />
              <path d="M 8,256 L 304,256" fill="none" stroke="black" />
              <polygon class="arrowhead" points="672,208 660,202.4 660,213.6" fill="black"
                transform="rotate(0,664,208)" />
              <polygon class="arrowhead" points="672,192 660,186.4 660,197.6" fill="black"
                transform="rotate(0,664,192)" />
              <polygon class="arrowhead" points="360,192 348,186.4 348,197.6" fill="black"
                transform="rotate(0,352,192)" />
              <polygon class="arrowhead" points="336,144 324,138.4 324,149.6" fill="black"
                transform="rotate(0,328,144)" />
              <g class="text">
                <text x="156" y="20">Content Object</text>
                <text x="40" y="36">Name:</text>
                <text x="148" y="36">/icn/manifest/name</text>
                <text x="104" y="52">Payload Type: Maniest</text>
                <text x="52" y="68">Payload:</text>
                <text x="140" y="84">Manifest</text>
                <text x="96" y="100">HashGroup (HG):</text>
                <text x="108" y="116">optional metadata:</text>
                <text x="168" y="132">overall digest, locator, etc.</text>
                <text x="132" y="148">hash-valued data pointer</text>
                <text x="432" y="148">data Content Object</text>
                <text x="64" y="164">...</text>
                <text x="296" y="164">| |</text>
                <text x="148" y="180">hash-valued manifest pointer</text>
                <text x="504" y="180">sub manifest Content Object</text>
                <text x="156" y="212">optional additional HashGroups</text>
                <text x="92" y="244">optional signature</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art" align="center" name="example_manifest.txt">
            <![CDATA[
.--------Content Object (CO)---------.
| Name:  /icn/manifest/name          |
| Payload Type: Maniest              |
| Payload:                           |
| +----------Manifest--------------+ |
| | HashGroup (HG):                | |
| | optional metadata:             | |
| |   overall digest, locator, etc.| |    .---------.
| | hash-valued data pointer -----------> | data CO |
| |   ...                          | |    `---------'
| | hash-valued manifest pointer ------.     .---sub manifest CO----.
| |                                | |  `--> |                     ----->
| | optional additional HashGroups | |       |                     ----->
| +--------------------------------+ |       `----------------------'
| optional signature                 |
`------------------------------------'
                ]]>
          </artwork>
        </artset>
      </figure>

      <t>A key design decision is how one names the root manifest, the application data, and
        subsidiary manifests. FLIC uses the concept of a Name Constructor. The root manifest (in
        fact, any FLIC manifest) may include a Name Constructor that instructs a manifest reader how
        to properly create Interests for the associated application data and subsidiary manifests.
        The Name Constructors allow interest construction using a well-known,
        application-independent set of rules. Some name constructor forms are tailored towards
        specific ICN protocols, such as CCNx or NDN; some are more general and could work with many
        protocols. We describe the allowed Name Constructor methods in <xref
          target="nameconstructors" format="default" />. There are also particulars of how to encode
        the name schema in a given ICN protocol, which we describe in <xref target="encodings"
          format="default" />.</t>

      <t>FLIC has encodings for <xref target="CCNxEncoding" format="default">CCNx</xref> as per <xref
          target="RFC8609" /> and for <xref target="NDNEncoding"
          format="default">NDN</xref>. For the implementor, the section <xref target="CCNxTlvs" />
        succintly defines the CCNx TLV structures and the format of each TLV value.</t>

      <t>An example implementation in Python may be found at <xref target="ccnpy"
          format="default" />.</t>

      <section>
        <name>FLIC as an ICN experimental tool</name>
        <t>FLIC enables experimentation with how to structure and retrieve large data objects
         in ICN. By having a common data structure applications can rely on, with a
          common library of code that can be used to create and parse manifest data structures,
          applications using ICN protocols can both avoid unnecessary reinvention and also have
          enhanced interoperability. Since the design attempts to balance simplicity, universality,
          and extensibility, there are a number of important experimental goals to achieve that may
          wind up in conflict with one another. We provide a partial list of these experimental
          issues in <xref target="experiments" />. It is also important for users of FLIC to
          understand that some flexibility and extensions might be removed if use cases do not
          materialize to justify their inclusion in an eventual standard.</t>
      </section>

      <section>
        <name>Requirements Language</name>
        <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>",
          "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD
          NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>"
          in this document are to be interpreted as described in BCP 14 <xref target="RFC2119" />
          <xref target="RFC8174" /> when, and only when, they appear in all capitals, as shown here.</t>
      </section>
    </section>

    <section anchor="overview">
      <name>Design Overview</name>
      <t>The FLIC design adopts the proven UNIX inode concept of direct and indirect pointers, but
        without the specific structural forms of direct versus indirect. FLIC is a collection of
        pointers, and when one de-references the pointer it could be an application object or
        another FLIC manifest.
        The pointers in FLIC use
        hash-based naming of Content Objects analogous to the function block numbers play in UNIX
        inodes. </t>

      <t> Because FLIC uses hash-based pointers as names, FLIC graphs are inherently acyclic. Both
        CCNx and NDN support hash-based naming, though the details differ (see <xref
          target="CCNxEncoding" format="default" /> and <xref target="NDNEncoding" format="default"
        />
        ).</t>

      <t>The FLIC data structure is an acyclic digraph of Content Objects. In this document, our
        examples are mostly trees, but that is not a requirement. For example, a de-duplication
        representation might have a common object or common sub-graph that is
        referenced from multiple parents in the tree. As another example, there could be
        a common sub-collection of objects organized in a Manifest, and that sub-manifest
        could be included in multiple places.  Each node has a total order of all its children
        and they are visited in a specific traversal order.  This leads to an unambiguous
        traversal even if a node has multiple in-edges.</t>

        <t>A FLIC manifest graph does not need to have a unique root.  When a publisher initially
        creates a FLIC manifest, it likely creates a unique root manifest.  Over time, however,
        there may be additional root manifests.  These could be used to update the root
        (e.g. replace an expired key or use a new certificate).  Or the root might be renamed,
        or new locators used because the location of the data changed.  An updated root
        might even point to the prior roots to maintain a history or access to prior
        cryptographic signatures or co-signatures.</t>

      <t>In FLIC terms, a direct pointer links to application-level data, which is a Content Object
        with application data in the Payload. An indirect pointer links to a Content Object with a
        FLIC Manifest in the Payload.  There is no distinction in the manifest between these
        two types of pointers.</t>

      <aside>
        <t>Note: A substantial advantage of using hash-based naming is that it permits block-level
          de-duplication of application data because two blocks with the same payload may have the
          same hash name if encoded that way. </t>
      </aside>

      <t>A publisher creating a FLIC manifest may choose one of many permissible acyclic graph
      structures.  Some examples are:</t>
      <dl newline="false" spacing="normal">
        <dt>Chain:</dt>
        <dd>where each manifest has many direct pointers and at most only one indirect pointer.</dd>

        <dt>Regular n-ary tree</dt>
        <dd>where there are m direct pointers and k indirect pointers at internal nodes (m+k=n) 
        and n direct pointers at leaf manifests.</dd>

        <dt>A leaf-only tree</dt>
        <dd>where interior nodes only have indirect pointers and leaf manifest nodes only
        have direct pointers.</dd>
      </dl>

      <t>As an example of choosing graph structure, the <xref target="ccnpy"/> implementation has a <tt>TreeOptimizer</tt> 
      that calculates an optimal number of indirect and direct pointers per manifest node, given the limitations
      of a maximum object size and the overhead of necessary fields in each manifest object.
      The optimizer will find a set of tree parameters that minimizes the tree height and
      minimizes the number of wasted pointers due to the size of the application data.</t>

      <t>A <bcp14>RECOMMENDED</bcp14> FLIC structure is to use a distinguished root manifest with exactly one
      pointer to the top manifest of a regular n-ary graph.  The root manifest is signed by
      the publisher and contains links to certificates or public keys.  It also specifies
      the Name Constructors used in the manifest.  If using RSA-OAEP key wrapping, it
      contains the wrapped key.  These one-time data structures take significant space,
      so off-loading them to the root manifest is needed to use a regular n-ary graph for
      the rest of the manifest.  In CCNx, the root manifest is the only one in the graph
      that needs to have a name if using nameless objects.
      </t>

      <t>This method allows an intermediary service to
        respond to client requests with its own signed root Manifest that then points to the original root
        manifest. The client trusts the intermediary's response because of the intermediary's
        signature, and then trusts the content because of the Root manifest. In some cases, the
        intermediary could embed the original root manifest and avoid additional round
        trips before beginning download. This technique is used in a <xref target="ProjectOrigin">peer-to-peer
        sharing protocol</xref>.</t>

      <t>FLIC supports manifest encryption separate from application payload encryption (See <xref
          target="encryption" />). It has a flexible encryption envelope to support various
        encryption algorithms and key discovery mechanisms. The byte layout allows for in-place
        encryption and decryption.</t>

      <t>A limitation of this approach is that one cannot construct a hash-based name for a child
        until one knows the payload of that child. In practical terms, this means that one must have
        the complete application payload available at the time of manifest creation.  One workaround
        is to batch publication of a block of data, then extend that manifest tree as the top-left-child
        of a subsequent manifest tree.  This results in multiple, signed, root manifests with
        two pointers (to the prior root manifest and the new manifest tree).</t>

      <t>FLIC's design allows straightforward applications that just need to traverse a set
        of related objects.  FLIC has two extensibility mechanisms that allow for
        more sophisticated uses: manifest metadata, and pointer annotations. These are described in <xref
          target="metadata" format="default" /> and <xref target="annotations" /> respectively.</t>

      <t anchor="libraries">FLIC goes to considerable lengths to allow creation and parsing by
        application-independent library code. Therefore, any options used by applications in the
        data structure or encryption capabilities <bcp14>MUST NOT</bcp14> require applications to
        have application-specific Manifest traversal algorithms to correctly re-construct
        the original data. This ensures that such application
        agnostic libraries can always successfully parse and traverse any FLIC Manifest by ignoring
        the optional capabilities.  An application MAY include optimization or other hints to
        allow an application to use that data in different ways.</t>

      <t>The reader may find it useful to refer to Section <xref target="Usage">Example Usages</xref>
        from time to time to see worked out examples.</t>
    </section>

    <section anchor="structure">
      <name>FLIC Structure</name>
      <section anchor="Terminology">
        <name>Terminology</name>
        <dl newline="false" spacing="normal">
          <dt>Data Object:</dt>
          <dd>a CCNx nameless Content Object that usually only has Payload. It might also have an
            ExpiryTime to limit the lifetime of the data.</dd>

          <dt>Direct Pointer:</dt>
          <dd>borrowed from inode terminology, it is a CCNx link using a content object hash
            restriction and a locator name to point to a Data Object.</dd>

          <dt>Hash Group:</dt>
          <dd>KA collection of pointers. A Manifest should have at least one Hash Group.
            A Hash Group may have its own associated meta data and Name Constructor.</dd>

          <dt>Indirect Pointer:</dt>
          <dd>borrowed from inode terminology, it is a CCNx link using a content object hash
            restriction and a locator name to point to a manifest content object.</dd>

          <dt>Internal Manifest:</dt>
          <dd>some or all pointers are indirect. The order and number of each is up to the manifest
            builder. By convention, all the direct manifests come first, then the indirect.</dd>

          <dt>Leaf Manifest:</dt>
          <dd>all pointers are direct pointers.</dd>

          <dt>Locator:</dt>
          <dd>a routing hint in an Interest used by forwarding to get the Interest to where it can
            be matched based on its Name Constructor-derived name.</dd>

          <dt>Manifest:</dt>
          <dd>a CCNx ContentObject with PayloadType 'Manifest' and a Payload of the encoded
            manifest. A leaf manifest only has direct pointers. An internal manifest has a mixture
            of direct and indirect pointers. The outer TLV type of the payload identifies
            the manifest specifically as a FLIC manifest.</dd>

          <dt>Manifest Waste:</dt>
          <dd>a metric used to measure the amount of waste in a manifest tree. Waste is the number
            of unused pointers. For example, a leaf manifest might be able to hold 40 direct
            pointers, but only 30 of them are used, so the waste of this node is 10. Manifest tree
            waste is the sum of waste over all manifests in a tree.</dd>

          <dt>Name Constructor:</dt>
          <dd>The specification of how to construct an Interest for a Manifest entry.</dd>

          <dt>Node</dt>
          <dd>The <tt>Node</tt> section of a manifest holds the manifest information. It has
            node-wide metadata in a <tt>NodeData</tt> section, and then a series of <tt>HashGroups</tt>
            .</dd>

          <dt>EncryptedNode</dt>
          <dd>A <tt>Node</tt> that is encrypted as specified in the Manifest's <tt>SecurityCtx</tt>.
            It is opaque octets.</dd>

          <dt>Root Manifest:</dt>
          <dd>A signed, named, manifest that points to manifest nodes.  The root manifest typically also 
          defines the name constructors and encryption context data, if needed.  The other manifest
          nodes may be CCNx nameless objects.</dd>

          <dt>Top Manifest:</dt>
          <dd>One useful manifest structure is to use a Root manifest that points to a single
            Internal manifest called the Top Manifest. The Top manifest the begins the structure
            used to organize manifests. It is also possible to combine the two and use only a root
            manifest that also serves in the role of the top manifest.</dd>
        </dl>
      </section>

      <section anchor="locators">
        <name>Locators</name>

        <t>Locators are routing hints used by forwarders to get an Interest to a node in the network
          that can resolve the Interest's name. In some naming conventions, the name might only be a
          hash-based name so the Locator is the only available routing information. Locators exist
          in both CCNx and NDN, though the specific protocol mechanisms differ. A FLIC manifest
          represents locators in the same way for both ICN protocols inside <xref
            target="nameconstructors" format="default">Name Constructors</xref>, though they are
          encoded differently in the underlying protocol. See <xref target="encodings"
            format="default" /> for encoding differences.</t>

        <t>CCNx only uses locators with nameless objects, whereas NDN may use multiple
          ForwardingHints per interest.</t>

        <t>A name constructor definition may define one or more Locator prefixes that can be used in
          the construction of Interests from the pointers in the manifest. The Locators are
          inherited when walking a manifest tree, so they do not need to be defined everywhere. It
          is <bcp14>RECOMMENDED</bcp14> that only the Root manifest contain Locators so that a
          single operation can update the locators. One use case when storing application payloads
          at different replicas is to replace the Root manifest with a new one that contains
          locators for the current replicas.</t>
      </section>

      <section anchor="nameconstructors">
        <name>Name Constructors</name>
        <t>A manifest organizes pointers inside Hash Groups. Each Hash Group uses an NCID to
            indicate what Name Constructor to use to generate the name of an Interest for
            pointers inside that Hash Group.</t>

        <t>A Manifest may define zero or more name constructors in Name Constructor Definitions (NCDs)
          located in the Manifest Node. An NCD associates a Name Constructor Id (NCID) to a Name
          Constructor definition. The NCID is used in other parts of the Manifest to refer to that specific
          definition.</t>

        <t>A name constructor definition, <tt>NcDef</tt>, is placed in a <tt>NodeData</tt> field.
        An <tt>NcDef</tt> applies to that <tt>Node</tt> and all subsequent nodes along that manifest branch,
        until superceded by a new <tt>NcDef</tt> with the same <tt>NcId</tt>.  A subsequent <tt>NcDef</tt>
        applies from that point onward in the manifest branch.  It does not affect its ancestors.</t>

        <t>In a non-tree FLIC graph, a node may have multiple parents, with different <tt>NcDef</tt> for
        the same <tt>NcId</tt> (i.e. parent 1 has NcDef A for the NcID and
        parent 2 has NcDef B for the same NcID).  This is allowed.  
        A consumer traversing the tree performs a specific
        traversal order.  It must apply its current branch's name constructor to its visited children.
        Of course, if a consumer has already visited a sub-tree, it likely already has the hash named
        objects fetched and does not need to re-fetch them.</t>

        <t>A common practice is to have the manifest nodes in one namespace and the application data objects
        in a different namespace.  For example, <tt>ccnx:/foo/photo.jpg/manifest/ManifestId=N</tt> for a manifest tree and 
        <tt>ccnx:/foo/photo.jpg/Chunk=M</tt> for the application data.  Or if using nameless objects, the manifest
        tree and data objects might have different locators.  In these cases, a FLIC manifest usually has
        two name constructor definitions (e.g. NCID 0 for the data and NCID 1 for the manifest tree).  This results
        in the direct pointers being in one hash group and then the indirect pointers being in a second
        hash group.</t>

        <t>If a traversal of a FLIC manifest encounters an unknown NCID, the <bcp14>RECOMMENDED</bcp14> action is to report a
            malformed manifest to the user and abort the traversal.</t>

        <t>It is <bcp14>RECOMMENDED</bcp14> to have <tt>NcDef</tt> fields only in the root or top manifest.
        It is <bcp14>RECOMMENDED</bcp14> to not re-define <tt>NcId</tt> values within the same manifest.</t>

        <t>An explicit name constructor has an <tt>NcDef</tt> in a <tt>NodeData</tt> and a corresponding <tt>NcId</tt>
          in a <tt>HashGroup</tt>.
          <tt>NcId</tt> 0 is a special NCID that may be used implicitly.</t>

        <section anchor="ImplicitNameConstructor">
          <name>Implicit Name Constructor</name>
          <t>NCID 0 is an implicit name constructor.  If a Hash Group does not have a <tt>GroupData</tt> 
          with an <tt>NcId</tt> element, it is assumed to use NCID 0.</t>

          <t>NCID 0 has an implicit definition as a Hash Schema.  If NCID 0 has no <tt>NcDef</tt>, it is
          assumed to be a HashSchema with no locators.  It is RECOMMENDED to define NCID with Locators
          to avoid repeatedly defining locators elsewhere.</t>

          <t>It is more efficient, encoding-wise, to always have an <tt>NcDef</tt> for NCID 0 (if it is used) that enumerates
          its <tt>Locators</tt> once rather than having to put them in each <tt>NodeData</tt> or <tt>GroupData</tt>.</t>

          <t>NCID 0 <bcp14>MAY</bcp14> be re-defined as any name constructor type.  It does not need to remain a Hash Schema.
          In this case, a publisher may be able to omit a <tt>GroupData</tt> for a group that uses NCID 0, 
          or at least omit the 5 bytes of an <tt>NcId</tt> field within a <tt>GroupData</tt>.</t>        
        </section>

        <section anchor="NameConstructorSchemas">
          <name>Name Constructor Schemas</name>
          <t>FLIC defines the following types of Name Constructors.
            Additional name constructor types may be specified in a subsequent revision of the
            specification. The section <xref target="grammar" /> specifies the encoding of each name constructor.</t>

          <dl newline="false" spacing="normal">
            <dt>Hash Schema:</dt>
            <dd>The children of a Hash Group using the Hash Schema are fetched using the <tt>Locators</tt>
            of the <tt>NcDef</tt>, or the <tt>HashGroup</tt>, or the <tt>NodeData</tt>, in that order
            if the more specific definition does not exist.  CCNx can only use one locator per Interest (in the Name),
            so if there are more than one available Locator, it must choose one, such as in the order listed.</dd>

            <dt>Prefix Schema:</dt>
            <dd>The <tt>NcDef</tt>> specifies a <tt>name</tt>, which will appear in every content object for that
              name constructor. The consumer uses it in an interest with the appropriate hash. The NCD
              may specify locators, which NDN uses as ForwardingHints. They are not used by CCNx, as
              these are not nameless objects.  In Prefix Schema, all object have an identical name and
              are only differentiated by their hash.</dd>

            <dt>Segmented Schema:</dt>
            <dd>Every content object has a different name, denoted by the last name component.
            FLIC allows the publisher to specify the TLV type of that last name component
            (e.g. ManifestId or ChunkNumber in CCNx).  The publisher <bcp14>MUST</bcp14> include a
            mechanism to tell the consumer the ID of each content object.  FLIC provides two
            methods: use a <tt>StartSegmentId</tt> field in the <tt>HashGroup</tt> or use
            a <em>SegmentIdAnnotation</em> for each pointer.  The consumer will use
            the <tt>Name</tt> in the <tt>NcDef</tt> as a prefix, append a TLV of the given
            type, and set the TLV value to the segment ID.  The resulting name is used
            in the Interest.  For NDN, <tt>Locators</tt> may also be used as Forwarding Hints.</dd>
          </dl>
        </section>

        <section anchor="explain_segmented">
          <name>Segmented Schema Details</name>
          <t>The Segmented Prefix schema uses a different name in all Content Objects and
            distinguishes them via their ContentObjectHash. Note that in CCNx, using a
            SegmentedPrefixSchema means that only the Root Manifest has a Locator for
            the Segmented Prefix (minus the segment ID).</t>
            
          <t>The consumer must determine the segment ID to use in the name. Typically, the
            application data would use a chunk number in the content name, which is a
            compact sequence number. These could be computed based on the in-order traversal,
            assuming one knows which manifests point to data versus other manifests.
            Manifests, however, may not use a compact sequence number and there is no simple
            way to predict the names.</t>

          <t>The SegmentedSchema uses a name component suffix to distinguish each content object.
            This name component will be of type <tt>SuffixComponentType</tt>. In CCNx, this would
            be a <tt>ChunkNumber</tt> or <tt>ManifestId</tt> type (<tt>T_MANIFEST_ID</tt> is defined in
            this document's <xref target="IANA">IANA section</xref>), though one may specify different types. 
            The reason for specifying the 
            <tt>SuffixComponentType</tt> in the name definition is that application data would
            typically use chunked names with sequential identifiers and the FLIC manifest tree
            would typically use the <tt>ManifestId</tt>.</t>

          <t>A publisher may name the manifest tree and the application data as desired, as long
            as the consumer can generate the required Interest names. FLIC provides two mechanisms: 
            <tt>AnnotatedPointers</tt> and <tt>StartSegmentId</tt>. One could use an annotated pointer
            to specify the exact name or name suffix for each pointer, so the consumer does not
            need to calculate anything; it simply uses the name specified. The downside is there
            is an annotation for each pointer, which reduces the number possible pointers in a
            given MTU. The <tt>StartSegmentId</tt> is a single integer per hash group that indicates the
            beginning ID for the pointer array. The consumer calculates each pointer's name suffix
            from the start segment ID plus pointer offset, and then wraps it in a name component
            of type <tt>SuffixComponentType</tt>.</t>

          <t>Because FLIC uses a preorder tree traversal, the node IDs of a manifest's children
            in the traversal order are not compact. They will skip around based on the preorder recursion. This means one
            needs a different ID for each manifest if one wants to use the <tt>StartSegmentId</tt>
            hint. A publisher may use any form of integer ID in the <tt>ManifestId</tt> name
            component so long as it is locally (within a hash group) sequential and globally
            unique.</t>

          <t>As an example, the <xref target="ccnpy"/> implementation uses the regular k-ary tree
          IDs per tree height as the manifest IDs (where k is the number of allowed indirect
          pointers per manifest).  These are globally unique and locally sequential
          for all the children of a manifest.</t>

          <t>There are two methods to guide a consumer in generating segment IDs for
            hash pointers:</t>
          <ul spacing="normal">
            <li>If fetching a pointer with a <tt>SegmentIdAnnotation</tt> (see <xref target="annotations"/>), 
            the consumer <bcp14>MUST</bcp14> use that segment ID for the pointer.</li>
            <li>If the GroupData has a <tt>StartSegmentId</tt> parameter, then the segment ID of each pointer
            is calculated the <tt>StaretSegmentId</tt> plus the offset of the pointer from the first
            pointer of the Hash Group.  Pointers with a <tt>SegmentIdAnnotation</tt> still count against
            the offset even though the annotation takes precedence.
            </li>
          </ul>

          <t>As an example, consider the manifest shown in <xref target="SegmentIdExample"/>.  The Interests generated, in order, have
          these names and hash restrictions.  We have used short example hash values for the sake of clarity.</t>
          <ol spacing="compact">
            <li><tt>/foo/7=10, hash=0x0001</tt></li>
            <li><tt>/foo/7=20, hash=0x0002</tt></li>
            <li><tt>/foo/7=12, hash=0x0003</tt></li>
            <li><tt>/bar/8=0, hash=0x0004</tt></li>
            <li><tt>/bar/8=1, hash=0x0005</tt></li>
            <li><tt>/bar/8=2, hash=0x0006</tt></li>
          </ol>

        <figure anchor="SegmentIdExample">
          <name>Segment ID Example</name>
          <artwork align="left" name="" type="ascii-art" alt=""><![CDATA[
Meanifest
  Node
    NodeData
      NcDef NcId 1 SegmentedSchema Name '/foo' SuffixComponentType 7
      NcDef NcId 2 SegmentedSchema Name '/bar' SuffixComponentType 8
    HashGroup
      GroupData NcId 1 StartSegmentId 10
      AnnotatedPtrs
        PointerBlock
          Ptr HashValue(0x0001) 
          Ptr HashValue(0x0002) SegmentIdAnnotation(20)
          Ptr HashValue(0x0003) 
    HashGroup
      GroupData NcId 2 StartSegmentId 0
      Ptrs
          HashValue(0x0004) 
          HashValue(0x0005)
          HashValue(0x0006) 
]]>
          </artwork>
        </figure>

          <t>Every group of a segmented NcId <bcp14>MUST</bcp14> have either a GroupData with a
            StartSegmentId, or use annotated pointers with SegmentIdAnnotation.</t>

          <t>A producer <bcp14>MUST</bcp14> ensure that a segment ID names exactly one data item. That is, the
            producer <bcp14>MUST NOT</bcp14> duplicate the segment ID in an object name for
            a different object. The object hash <bcp14>MUST</bcp14> be the same for the same segment
            ID of a name, within the longest of the <tt>ExpiryTime</tt> of the manifest or the named object.
            In other words, there is a one-to-one correspondence between a segment ID and a hash
            for the lifetime of the manifest and the constituent objects.
            Note that a <em>consumer</em> should not assume this is true, as a bad actor could
            violate this rule.  A consumer should only assume the uniqueness of cryptographic hashes.</t>

          <t>It is allowed to have multiple manifest entries with the same segment ID (see
            below).</t>

          <t>While a producer <bcp14>MAY</bcp14> mix using GroupData <tt>StartSegmentId</tt> and
            <tt>SegmentIdAnnotation</tt>, we in general do not consider that a good idea. It is up to the
            manifest producer to ensure that every segment may be fetched, and fetch in the right
            order. Segments, when fetched in the <strong>manifest order</strong> reconstruct the
            original data. </t>

          <t>Let us make this clear, the original data is constructed by the in-order manifest
            traversal, not the segment ID order. The consumer should make no assumptions about
            reconstructing the original data and the names of those data elements.</t>

          <t>A consumer <bcp14>MAY</bcp14> skip fetching some segments. A consumer <bcp14>MAY</bcp14>> fetch segments in any
            order it chooses. It may skip around or omit segments.</t>

          <t>A manifest <bcp14>MAY</bcp14> have multiple pointers to the same segment ID (and thus same hash). This
            can be used for data de-duplication, e.g. multiple occurrences of the same binary string
            within
            the reconstructed data object. If the producer uses this method, then the original data
            cannot be reconstructed by simply fetching the segment IDs in order.</t>
        </section>
      </section>

      <section anchor="metadata">
        <name>Manifest Metadata</name>
        <t>The FLIC Manifest may be extended by defining TLVs that apply to the Manifest as a whole,
          or alternatively, individually to every data object pointed to by the Manifest. This basic
          specification does not specify any, but metadata TLVs may be defined through additional
          RFCs or via Vendor TLVs. FLIC uses a Vendor TLV structure identical to <xref
            target="RFC8609" format="default" /> for vendor-specific annotations that require no
          standardization process.</t>

        <t>For example, some applications may find it useful to allow specialized consumers such as <em>
          repositories</em> (for example <xref target="repository" />) or enhanced forwarder caches
          to pre-place, or adaptively pre-fetch data in order to improve robustness and/or retrieval
          latency. Metadata can supply hints to such entities about what subset of the compound
          object to fetch and in what order.</t>

        <aside>
          <t>Note: FLICs ability to use separate namespaces for the Manifest and the underlying Data
            allows different encryption keys to be used, hence giving a network element like a cache
            or repository access to the Manifest data does not as a side effect reveal the contents
            of the application data itself.</t>
        </aside>

        <section anchor="digests">
          <name>SubtreeDigest and LeafDigest</name>
          <t>It is <bcp14>RECOMMENDED</bcp14> that the root manifest have a <tt>SubtreeDigest</tt>
          field in the <tt>NodeData</tt> with the cryptographic hash of the entire application data.  This allows the
          manifest consumer to validate that the final reconstructed data is correct.</t>

          <t>A consumer <bcp14>SHOULD</bcp14> validate the outer-most <tt>SubtreeDigest</tt>, if any.  If this digest
          does not validate, a consumer <bcp14>SHOULD</bcp14> validate nested <tt>SubtreeDigest</tt> or <tt>LeafDigest</tt>
          to help pinpoint where there is a discrepancy.
          </t>

          <t>As an example, a publisher might include a <tt>SubtreeDigest</tt> in the root manifest <tt>NodeData</tt>
          and then a <tt>LeafDigest</tt> in every manifest with direct pointers.  It is not necessary to validate every
          <tt>LeafDigest</tt> if the overall <tt>SubtreeDigest</tt> checks.  If the <tt>SubtreeDigest</tt> does not check,
          then the consumer could locate where the problem is by validating the <tt>LeafDigests</tt>.</t>

          <t>A consumer <bcp14>SHOULD</bcp14> inform the user when a digest does not validate.</t>

          <t>A discrepancy in a digest should be considered an error condition.</t>
        </section>

        <section anchor="sizes">
          <name>SubtreeSize and LeafSize</name>
          <t>The <tt>SubtreeSize</tt> and <tt>LeafSize</tt> fields are provided to help a consumer seek
          through a manifest to specific locations.  They are not intended to validate the application
          data.</t>

          <t>A consumer <bcp14>MAY</bcp14> compare the sizes in <tt>SubtreeSize</tt> and <tt>LeafSize</tt> to
          the true application payload sizes retrieved from the manifest nodes and report any discrepancies to
          the user.</t>
        </section>
      </section>

      <section anchor="annotations">
        <name>Pointer Annotations</name>
        <t>FLIC allows each manifest pointer to be annotated with extra data. Annotations allow
          applications to exploit metadata about each Data Object pointed to without having to first
          fetch the corresponding Content Object. This specification defines three annotations: <tt>
          SizeAnnotation</tt>, <tt>SegmentIdAnnotation</tt>, and <tt>LinkAnnotation</tt>.</t>


        <t>The <tt>SizeAnnotation</tt> specifies the number of application layer octets covered by
          the pointer.</t>

        <t>The <tt>SegmentIdAnnotation</tt> is a unique suffix for the pointer for use with the
          Segmented Schema name constructor. Using annotations allows non-sequential segment IDs,
          which could happen if manifest trees are named in the traversal order.  See 
          <xref target="explain_segmented"/> details on using the annotation.</t>

        <t>The <tt>LinkAnnotation</tt> is a link to be used to name the pointer (less the pointer
          itself). For NDN, the pointer would be appended to the name for a complete name. In CCNx,
          the name would be used in the Interest along with the pointer in the
          ContentObjectHashRestriction field. The link may include a KeyId restriction.</t>

        <aside>
          <t>One may include a KeyId restriction in the generated interest by also using the 
            <tt>ProtocolFlags</tt> option of a name constructor. This would be more space efficient
            than using annotated pointers.</t>
        </aside>

        <t>Other annotation may, for example, give hints about a desirable traversal order for
          fetching
          the data, or an importance/precedence indication to aid applications that do not require
          every content object pointed to in the manifest to be fetched. This can be very useful for
          real-time or streaming media applications that can perform error concealment when
          rendering the media.</t>

        <t>Additional annotations may be defined through additional specifications or via Vendor
          TLVs.</t>
      </section>

      <section anchor="grammar">
        <name>Manifest Grammar (ABNF)</name>
        <t>The manifest grammar is mostly, but not entirely independent of the ICN protocol used to
          encode and transport it. The TLV encoding therefore follows the corresponding ICN
          protocol, so for CCNx FLIC uses 2 octet length, 2 octet type and for NDN uses the 1/3/5
          octet types and lengths (see <xref target="NDNTLV" /> for details). There are also some
          differences in how one structures and resolves links. <xref target="RFC8609"
            format="default" /> defines HashValue and Link for CCNx encodings. The NDN
          ImplicitSha256DigestComponent defines HashValue and NDN Delegation (from Link Object)
          defines Link for NDN. <xref target="encodings" /> below specifies these differences.</t>

        <t>The basic structure of a FLIC manifest comprises a security context, a node, and an
          authentication tag. The security context and authentication tag are not needed if the node
          is unencrypted. A node is made up of a set of metadata, the <tt>NodeData</tt>, that
          applies to the entire node, and one or more <tt>HashGroups</tt> that contain pointers.</t>

        <t>The <tt>NodeData</tt> element defines the namespaces used by the manifest. There may be
          multiple namespaces, depending on how one names subsequent manifests or data objects. Each <tt>
          HashGroup</tt> may reference a single namespace to control how one forms Interests from
          the <tt>HashGroup</tt>. If one is using separate namespaces for manifests and application
          data, one needs at least two hash groups. For a manifest structure of "MMMDDD," (where M
          means manifest (indirect pointer) and D means data (direct pointer)) for example, one
          would have a first <tt>HashGroup</tt> for the child manifests with its namespace and a
          second <tt>HashGroup</tt> for the data pointers with the other namespace. If one used a
          structure like "MMMDDDMMM," then one would need three hash groups.</t>

        <figure anchor="flicgrammar">
          <name>FLIC Grammar</name>
          <sourcecode type="abnf"><![CDATA[
TYPE = 2OCTET / {1,3,5}OCTET ; As per CCNx or NDN TLV
LENGTH = 2OCTET / {1,3,5}OCTET ; As per CCNx or NDN TLV

Manifest = T_FLIC_MANIFEST LENGTH
              [SecurityCtx] (EncryptedNode / Node) [AuthTag]

SecurityCtx = T_SECURITY_CTX LENGTH AlgorithmCtx
AlgorithmCtx = AEADCtx / RsaWrapCtx
AuthTag = T_AUTH_TAG LENGTH *OCTET ; e.g. AEAD authentication tag
EncryptedNode = T_ENCRYPTED_NODE LENGTH *OCTET ; Encrypted Node

Node = T_NODE LENGTH [NodeData] 1*HashGroup [Pad]
NodeData = T_NODE_DATA LENGTH [SubtreeSize] [SubtreeDigest]
              [Locators] 0*Vendor 0*NcDef
SubtreeSize = T_SUBTREE_SIZE LENGTH INTEGER
SubtreeDigest = T_SUBTREE_DIGEST LENGTH HashValue
Pad = T_PAD LENGTH 0*OCTET ; as per RFC8609

NcDef = T_NCDEF LENGTH NcId NcSchema
NcId = T_NCID LENGTH INTEGER
NcSchema = InterestDerivedSchema / DataDerivedSchema /
           PrefixSchema / SegmentedSchema / HashSchema

InterestDerivedSchema = TYPE LENGTH [ProtocolFlags]
DataDerivedSchema = TYPE LENGTH [ProtocolFlags]

PrefixSchema = T_PrefixSchema LENGTH Name [Locators] [ProtocolFlags]
SegmentedSchema = T_SegmentedSchema LENGTH Name SuffixComponentType
                     [Locators] [ProtocolFlags]
SuffixComponentType = T_SUFFIX_TYPE LENGTH 1*OCTET
HashSchema = T_HashSchema LENGTH Locators [ProtocolFlags]

Locators = T_LOCATORS LENGTH 1*Locator
HashValue = TYPE LENGTH *OCTET ; As per ICN Protocol
Locator = TYPE LENGTH Link ; Link As per ICN protocol

ProtocolFlags = T_PROTOCOL_FLAGS LENGTH *OCTET
                ; ICN-specific flags, e.g. must be fresh

HashGroup = T_HASH_GROUP LENGTH [GroupData] (Ptrs / AnnotatedPtrs)
Ptrs = T_PTRS LENGTH *HashValue
AnnotatedPtrs = T_ANNOTATED_PTRS LENGTH *PointerBlock
PointerBlock = T_PTR_BLOCK LENGTH *Annotation Ptr
Ptr = T_PTR LENGTH HashValue

Annotation = SizeAnnotation / SegmentIdAnnotation / 
             LinkAnnotation / Vendor
SizeAnnotation = T_ANN_SIZE LENGTH Integer
SegmentIdAnnotation = T_ANN_SEGMENT_ID LENGTH Integer
LinkAnnotation = T_LINK LENGTH Link
Vendor = T_ORG LENGTH PEN *OCTET
PEN = 3OCTET ; IANA Private Enterprise Number

GroupData = TYPE LENGTH [NcId] [LeafSize] [LeafDigest]
            [SubtreeSize] [SubtreeDigest] [StartSegmentId]
            [Locators] 0*Vendor
LeafSize = T_LEAF_SIZE LENGTH INTEGER
LeafDigest = T_LEAF_DIGEST LENGTH HashValue
StartSegmentId = T_START_SEGMENT_ID LENGTH Integer

AEADCtx = T_AEAD_CTX LENGTH AEADData
AEADData = KeyNum AEADNonce AEADMode [KDFData]
KeyNum = T_KEYNUM LENGTH INTEGER
AEADNonce = T_NONCE LENGTH 1*OCTET
AEADMode = T_AEADMode LENGTH (AEAD_AES_128_GCM / AEAD_AES_256_GCM /
           AEAD_AES_128_CCM / AEAD_AES_128_CCM) 
           ; RFC5116 definitions
KDFData = T_KDF_DATA LENGTH KDFAlg [KDFInfo]
KDFAlg = T_KDF_ALG LENGTH INTEGER
    ; IANA "HPKE KDF Identifiers" [RFC9180]
KDFInfo = T_KDF_INFO LENGTH 1*OCTET
    ; Passed to the KDF Info

RsaOaepCtx = T_RSAOAEP_CTX LENGTH RsaOaepData
RsaOaepData = AEADData [RsaOaepWrapper]
RsaOaepWrapper = KeyId [KeyLink] HashAlg WrappedKey  
    ; KeyId as pre RFC8609 for CCNx
    ; KeyLink as pre RFC8609 for CCNx
HashAlg = T_HASH_ALG LENGTH alg_number        
    ; alg_number from IANA "CCNx Hash Function Types"
WrappedKey = T_WRAPPED_KEY LENGTH RsaOaepEnc{4OCTET 1*OCTET}
    ; Encrypted 4-byte salt plus AES key
]]>
			</sourcecode>
        </figure>

        <dl newline="false" spacing="normal">
          <dt>SecurityCtx:</dt>
          <dd>information about how to decrypt an <tt>EncryptedNode</tt>. The structure will depend
            on the specific encryption algorithm.</dd>

          <dt>AEADMode</dt>
          <dd>"AEAD Algorithms" values from IANA "Authenticated Encryption with Associated Data
            (AEAD) Parameters."
            FLIC only specifies the use of four basic algorithms with full authentication tag.</dd>

          <dt>AlgorithmId:</dt>
          <dd>The ID of the encryption method (e.g. preshared key, a broadcast encryption scheme,
            etc.)</dd>
          <dt>AlgorithmData:</dt>
          <dd>The context for the encryption algorithm.</dd>

          <dt>EncryptedNode:</dt>
          <dd>An opaque octet string with an optional authentication tag (i.e. for AEAD
            authentication tag)</dd>

          <dt>Node:</dt>
          <dd>A plain-text manifest node. The structure allows for in-place encryption/decryption.</dd>

          <dt>NodeData:</dt>
          <dd>the metadata about the Manifest node</dd>

          <dt>SubtreeSize:</dt>
          <dd>The size of all application data at and below the Node or Group</dd>

          <dt>SubtreeDigest:</dt>
          <dd>The cryptographic digest of all application data at and below the Node or Group</dd>

          <dt>Locators:</dt>
          <dd>An array of routing hints to find the manifest components</dd>

          <dt>HashGroup:</dt>
          <dd>A set of child pointers and associated metadata</dd>

          <dt>Ptrs:</dt>
          <dd>A list of one or more Hash Values</dd>

          <dt>Pad:</dt>
          <dd>The Node may include a Pad, as per <xref target="RFC8609" section="3.3.1" />. This
            allows the publisher to hide the plaintext length in an encrypted manifest. </dd>

          <dt>GroupData:</dt>
          <dd>Metadata that applies to a HashGroup</dd>

          <dt>LeafSize:</dt>
          <dd>Size of all application data immediately under the Group (i.e. via direct pointers)</dd>

          <dt>LeafDigest:</dt>
          <dd>Digest of all application data immediately under the Group</dd>

          <dt>StartSegmentId:</dt>
          <dd>
            If using a name constructor that requires a chunk number (segment ID), this field
            indicates the starting value
            for the group. Using the StartSegmentId means that a consumer does not need to track the
            segment id between
            manifests and simplifies interest name generation.
          </dd>

          <dt>Ptr:</dt>
          <dd>The ContentObjectHash of a child, which may be a data ContentObject (i.e. with
            Payload) or another Manifest Node.</dd>
        </dl>
      </section>

      <section anchor="Graphs">
        <name>Manifest Graphs</name>
        <t>As mentioned in the introduction, FLIC uses a directed acyclic graphs that is not necessarily a tree.
        A tree requires a unique path to each node.  FLIC allows multiple pointers to the same subtrees or
        application data.</t>

        <t>The FLIC traversal rule for a given manifest is to visit each of its Hash Groups, in  
        order, and within each Hash Group to visit each pointer, in order.  It is a left-to-right reading
        of the pointers.  We will use the term "child" for each pointer in a FLIC <tt>Node</tt>, where
        each child has an implicit order based on its position with a hash group, and the order of the
        hash groups within the node.</t>

        <t>If the FLIC manifest is a tree, and all direct pointers occur before all indirect pointers,
        then the traversal is pre-order.  This is the <tt>RECOMMENDED</tt> encoding order, as it minimizes
        the time to the first application data object (assuming one is not using leaf-only storage).</t>

        <t>The pre-order encoding and decoding of a FLIC manifest works even if the manifest is not a tree.
        The <xref target="ccnpy"/> README file has examples of data de-duplication where both manifest
        nodes and application data nodes are de-duplicated and appear more than once in the traversal.
        There is no special encoding or decoding: it is all pre-order, but it does not build a tree.</t>

        <section anchor="traversal">
          <name>Traversal Example</name>
          <t>FLIC manifests use a pre-order traversal. This means pointers are read top to bottom, left
            to right. The algorithms in <xref target="pseudocode" /> show the pre-order forward
            traversal code and the reverse-order traversal code, which we use below to construct
            such a graph. This document does not mandate how to build FLIC graphs. The function <tt>visit(node)</tt>
            means to enumerate the direct pointers of the node before the loop visits the indirect pointers.
            <xref target="building-graphs" /> provides a detailed example of building FLIC graphs.</t>

          <figure anchor="pseudocode">
            <name>Traversal Pseudocode</name>
            <sourcecode type="c"><![CDATA[
 preorder(node)
    if (node = null)
       return
    visit(node)
    for (i = 0, i &lt; node.child.length, i++)
       preorder(node.child[i])

reverse_preorder(node)
   if (node = null)
       return
   for (i = node.child.length - 1, i &gt;= 0, i-- )
       reverse_preorder(node.child[i]) 
       visit(node)
]]>
            </sourcecode>
          </figure>

          <t>In terms of the FLIC grammar, one expands a node into its hash groups, visiting each
            hash group in order. In each hash group, one follows each pointer in order. <xref
              target="expansion" /> shows how hash groups inside a manifest expand like virtual
            children in the tree. The in-order traversal is M0, HG1, M1, HG3, D0, D1, D2, HG2, D3,
            D4.</t>


          <figure anchor="expansion">
            <name>Node Expansio</name>
            <artset>
              <artwork type="svg" name="expansion.svg" align="center">
                <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="20%"
                  viewBox="0 0 112 160" class="diagram" text-anchor="middle" font-family="monospace"
                  font-size="13px" stroke-linecap="round">
                  <path d="M 60,24 L 64,32" fill="none" stroke="black" />
                  <path d="M 28,24 L 60,24" fill="none" stroke="black" />
                  <g class="text">
                    <text x="12" y="20">M0</text>
                    <text x="8" y="36">|</text>
                    <text x="16" y="52">HG1</text>
                    <text x="72" y="52">HG2</text>
                    <text x="16" y="68">| \</text>
                    <text x="64" y="68">|</text>
                    <text x="88" y="68">\</text>
                    <text x="24" y="84">M1 D2</text>
                    <text x="68" y="84">D3</text>
                    <text x="100" y="84">D4</text>
                    <text x="8" y="100">|</text>
                    <text x="16" y="116">HG3</text>
                    <text x="8" y="132">|</text>
                    <text x="32" y="132">\</text>
                    <text x="24" y="148">D0 D1</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art" align="center" name="expansion.txt">
                <![CDATA[
M0 ____
|      \
HG1    HG2
| \    |  \
M1 D2  D3  D4
|
HG3
|  \
D0 D1
                ]]>
              </artwork>
            </artset>
          </figure>

          <t>Using the example manifest tree shown in <xref target="leafonly" />, the in-order
            traversal would be: Root, M0, M1, D0, D1, D2, M2, D3, D4, D5, M3, D6, D7, D8. </t>
        </section>
      </section>

      <section anchor="encryption">
        <name>Manifest Encryption Modes</name>
        <t>This document specifies two encryption modes. The first is a preshared key mode, where
          the parties are assumed to have the decryption keys already. It uses AES-GCM or AES-CCM.
          This is useful, for example, when using a key agreement protocol such as <xref
            target="I-D.wood-icnrg-ccnxkeyexchange">CCNxKE</xref>. The second is an RSA key wrapping
          mode using RSA-OAEP, similar to <xref target="RFC8017" />. This may be used for group
          keying. </t>

        <t>Additional modes may be defined in subsequent specifications. We expect that an RSA-KEM
          mode and Elliptic Curve mode should be specified.</t>

        <t>To distribute a decryption key with the manifest itself, FLIC uses RSA-OAEP to wrap the <tt>WrappedKey</tt>
          element. This specification only details the pertinent aspects of the encryption. It
          describes how a consumer locates the appropriate keys in the ICN namespace. It does not
          specify aspects of a key manager which may be used as part of key distribution
          and management, nor does it specify the protocol between a key manager and a publisher. In
          its simplest form, the publisher could be the key manager, in which case there is no
          extra protocol needed between the publisher and key manager.</t>

        <t>The manifest is always encrypted with an AEAD algorithm. The difference between the
          preshared key mode and the RSA wrapped mode is how the parties communicate the AES
          decryption key. The RSA OAEP mechanism facilitates the distribution of the shared key
          without an on-line key agreement protocol like (the expired draft) <xref
            target="I-D.wood-icnrg-ccnxkeyexchange">CCNxKE</xref>.</t>

        <section anchor="aead">
          <name>AEAD Mode</name>
          <t>This mechanism uses <xref target="NIST-800-38D">AES-GEM</xref> or <xref target="RFC3310"
            >
            AES-CCM</xref> for manifest encryption. A publisher creating a <tt>SecurityCtx</tt>
            <bcp14>
            SHOULD</bcp14> use the mechanisms in <xref target="RFC6655" /> for AES-CCM IV generation
            and <xref target="RFC5288" /> for AES-GCM IV generation.</t>

          <t>When the publisher and consumer establish the <tt>KeyNum</tt>, they <bcp14>SHOULD</bcp14>
            also establish a salt. This results in a 4-byte salt and 8-byte nonce. If no salt
            exists, the AEADNonce may be the entire IV. </t>

          <t>The scope of the <tt>KeyNum</tt> is upto the publisher and consumer agreement. It may
            be for a specific manifest, or a specific session (e.g. a CCNxKE session), or some
            longer period. FLIC does not specify how the publisher and consumer agree on shared
            keys, their lifespan, or scope. See the <xref target="Security" /> section for a
            discussion.</t>

          <t>As these references specify, the publisher <bcp14>MUST</bcp14> use unique nonces on each
            Manifest that uses the same key or derived KDF key.  A publisher <bcp14>MAY</bcp14>
            use the mechanisms of <xref target="RFC5116" section="3.2"/> for nonce generation 
            (what we cal "salt" is termed "fixed-common" therein).
            </t>

          <t>The AEAD Mode uses <xref target="RFC5116" /> defined symbols AEAD_AES_128_CCM,
            AEAD_AES_128_GCM, AEAD_AES_256_CCM and AEAH_AES_256_GCM to specify the key length and
            algorithm.</t>

          <t> The <tt>KeyNum</tt> identifies a key on the receiver. The key <bcp14>MUST</bcp14> be
            exactly of the length specific by the Mode. Many receivers may have the same key with
            the same <tt>KeyNum</tt>.</t>

          <t>The publisher <bcp14>MAY</bcp14> use a KDF for the manifest. If <tt>KDFData</tt> is
            present, the consumer <bcp14>MUST</bcp14> derive a manifest-specific key from the shared
            key identified by <tt>KeyNum</tt>. The <tt>KDFAlg</tt> is taken from the IANA registry
            for <xref target="RFC9180" />. If <tt>KDFInfo</tt> is present, the consumer uses that
            string as in the KDF's <tt>info</tt> parameter. If the <tt>KDFInfo</tt> is not present,
            then the consumer must use the <tt>Name</tt> TLV of the enclosing Content Object. This
            option is only possible for <tt>Segmented Schema</tt> name constructors, where each
            manifest has a unique name. If the publisher and consumer have agreed on a salt to be
            associated with the key for use in the AEAD algorithm, this salt should not be used in
            the KDF. The publisher and consumer may agree on a separate random salt as part of their
            key agreement on the <tt>KeyNum</tt> for use in the KDF.</t>

          <t>Within a single manifest tree, a publisher <bcp14>MAY</bcp14> use the same <tt>KDFData</tt>
            and <tt>KDFInfo</tt> over multiple manifests, so long as it uses unique <tt>Nonce</tt>.
            This allows a consumer to cache a single derived key based on the <tt>(KeyNum, KDFInfo)</tt>
            pair. This is the normal use of the KDF mode: the publisher only needs to track a single
            unique value for each manifest using <tt>KeyNum</tt>, not all the individual Nonces used
            with in a manifest tree. If the publisher uses a sequence number or timestamp, it does
            not even need to record previous <tt>KDFInfo</tt>, so long as they are unique.</t>

          <t>When a Consumer reads a manifest that specifies a <tt>KeyNum</tt>, the consumer SHOULD
            verify that the Manifest's publisher is an expected one for the KeyNum's usage. This
            trust mechanism employed to ascertain whether the publisher is expected is beyond the
            scope of this document, but we provide an outline of one such possible trust mechanism.
            When a consumer learns a shared key and <tt>KeyNum</tt>, it associates that <tt>KeyNum</tt>
            with the publisher ID used in a public key signature. When the consumer receives a
            signed manifest (e.g. the root manifest of a manifest tree), the consumer matches the
            KeyNum's publisher with the Manifest's publisher.</t>

          <t> Each encrypted manifest node has a full security context (<tt>KeyNum, Nonce,
              Mode</tt>). The AEAD decryption is independent for each manifest so Manifest objects
            can be fetched and decrypted in any order. This design also ensures that if a manifest
            tree points to the same subtree repeatedly, such as for deduplication, the decryptions
            are all idempotent.</t>

          <t>If <tt>KDFData</tt> is present, one derives a manifest-specific key as:</t>
          <ol>
            <li>If <tt>KDFInfo</tt> is present, the TLV (not just the value) is used as the <tt>
              Label</tt> below. Otherwise, the Content Object <tt>Name</tt> TLV (including type type
              and length fields) is used as the <tt>Label</tt>. If the content object does not have
              a name, it is an error.</li>
            <li><tt>FixedInfo = "FLIC" || KeyNum || AEADMode || Label</tt>, where <tt>KeyNum</tt>
              and <tt>AEADMode</tt> are the respective TLVs (including type and length).</li>
            <li>If the publisher and consumer have agreed on a KDF-specific salt, it is used as the <tt>
              Salt</tt>. Otherwise, the KDF's default salt is used. </li>
            <li>The derived key will use the left <tt>bits</tt> of the KDF output to satisfy the <tt>
              AEADMode</tt> key length (typically 128 or 256 bits).</li>
            <li>DerivedKey = LEFT(KDF(Shared Key, FixedInfo, KDF Salt), bits).</li>
          </ol>

          <t>To encrypt a Manifest, the publisher:</t>
          <ol>
            <li>Removes any <tt>SecurityCtx</tt> or <tt>AuthTag</tt> from the Manifest.</li>
            <li>Creates a <tt>SecurityCtx</tt> and adds it to the Manifest.</li>
            <li>If <tt>KDFData</tt> is present, derives a key as above.</li>
            <li>If the publisher and consumer shared a salt, it is used in the encryption.</li>
            <li>Treats the Manifest TLV through the end of the Node TLV Length as unencrypted
              authenticated Header. That includes anything from the start of the Manifest up to but
              not including the start of the Node's body.</li>
            <li>Treats the body of the Node to the end of the Manifest as encrypted data.</li>
            <li>Appends the AEAD <tt>AuthTag</tt> to the end of the Manifest, increasing the
              Manifest's length</li>
            <li>Changes the TLV type of the Node to <tt>EncryptedNode</tt>.</li>
          </ol>

          <t>To decrypt a Manifest, the consumer:</t>
          <ol>
            <li>Verifies that the <tt>KeyNum</tt> exists and the publisher is trusted for that <tt>
              KeyNum</tt>.</li>
            <li>Saves the <tt>AuthTag</tt> and removes it from the Manifest, decreasing the Manifest
              length.</li>
            <li>Changes the <tt>EncryptedNode</tt> type to <tt>Node</tt>.</li>
            <li>Treats everything from the Manifest TLV through the end of the Node Length as
              unencrypted authenticated Header. That is, all bytes from the start of the Manifest up
              to but not including the start of the Node's body.</li>
            <li>Treats the body of the Node to the end of the Manifest as encrypted data.</li>
            <li>If <tt>KDFData</tt> is present, derives a key as above.</li>
            <li>If the publisher and consumer shared a salt, it is used in the decryption.</li>
            <li>Verifies and decrypts the data using the key and saved <tt>AuthTag</tt>.</li>
            <li>If the decryption fails, the consumer <bcp14>SHOULD</bcp14> notify the user and stop
              further processing of the manifest.</li>
          </ol>
        </section>

        <section anchor="rsa_wrap">
          <name>RSA-OAEP Key Transport Mode</name>
          <t>The <tt>RsaOaepCtx</tt>> mode uses RSA-OAEP (see <xref target="RFC8017" section="7.1"
              format="default" /> and <xref target="NIST-800-56Br2" />) to encrypt a symmetric key
            that is used to encrypt the Manifest. We call this RSA public key the Key Encryption Key (KEK)
            and the consumer has the private key. A separate key distribution system is
            responsible for distributing the KEK.  The publisher <bcp14>MAY</bcp14> include a
            <tt>KeyLink</tt> to help a consumer find the corresponding private key, such as from a
            key distribution service.  An ICN system may use the RSA-OAEP mode as part of a group keying
            protocol.  Key distribution and group keying are both beyond the scope of FLIC.</t>

          <t>This usage of RSA-OAEP is intended to be compliant with KTS-OAEP <xref target="NIST-800-56Br2"/>. 
            See <xref target="OAEP_Security" /> for a discussion of compliance with
            NIST recommendations.</t>

          <t><tt>T_RSA_WRAP_CTX</tt> uses <xref target="RFC8017">RSA-OAEP</xref> with mask
            generation function <xref target="RFC8017">MGF1</xref> and the specified hash algorithm.
            The hash algorithm number is taken from the IANA registry "CCNx Hash Function Types,"
            which are all NIST approved hash functions.</t>

          <t>The <tt>RsaOaepData</tt> includes an <tt>AEADData</tt> that indicates how to use the
            wrapped key to decrypt the manifest. It optionally includes the wrapped key itself. A
            publisher using <tt>RsaWrapCtx</tt> <bcp14>MUST</bcp14> include the optional wrapped key
            information in the first manifest node that uses it. The publisher <bcp14>MAY</bcp14>
            include the wrapped key in other manifest nodes. It <bcp14>MUST</bcp14> use distinct 
            <tt>KeyNum</tt> for distinct <tt>WrappedKey</tt>.</t>

          <t>The RSA-OAEP <tt>KeyNum</tt> is only significant within a given manifest.</t>

          <t>The <tt>AEADData</tt> <bcp14>MAY</bcp14> include a <tt>KDFData</tt> element, in which
            case it is used the same was as with AEAD Mode.</t>

          <t>In a typical usage, the publisher would begin encryption at the root manifest. It must
            include the full <tt>WrapedData</tt> here, as it is the first usage of the <tt>KeyNum</tt>.
            In subsequent manifests, the publisher may only include the <tt>AEADData</tt> in the <tt>
            RsaOaepData</tt> to save space.</t>

          <t>The <tt>KeyId</tt> identifies the KEK. If the consumer already has the private key
            corresponding to <tt>KeyId</tt> locally, it does not need to fetch it from the 
            <tt>KeyLink</tt>. The <tt>KeyId</tt> is similar to the Content Object KeyId field <xref
              target="RFC8609" />.</t>

          <t>The symmetric key <bcp14>MUST</bcp14> be one that is compatible with the AEAD Mode,
            i.e. a 128-bit or 256-bit random number. Further, the symmetric key <bcp14>MUST</bcp14>
            fit in the OAEP envelope. Note that for a 128-bit key (16 bytes) plus a 4-byte salt
            requires a minimum 688-bit RSA key and a 256-bit key requires a minimum 816-bit RSA key.
            So in practical terms, a 1024-bit RSA key is the minimum for the RSA-OAEP encryption
            with a SHA-256 hash algorithm (it is recommended to use at least 2048-bit RSA keys <xref
              target="NIST-800-131Ar2" />).</t>

          <t>Any group key protocol and system needed are outside the scope of this document. We
            assume there is a Key Manager (KM) and a Publisher (P) and a set of group members.
            Through some means, the Publisher therefore has at its disposal:</t>
          <ul>
            <li>A Content Encryption Key (CEK), i.e. the symmetric key.</li>
            <li>The RSA-OAEP wrapped CEK.</li>
            <li>The KeyId of the KEK used to wrap the CEK.</li>
            <li>The Locator of the KEK, which is shared under some group key protocol.</li>
          </ul>

          <t>This specification requires that if a group member fetches the KEK key at Locator, it
            can decrypt the <tt>WrappedKey</tt> and retrieve the CEK. The <tt>WrappedKey</tt>
            includes a 4-byte salt plus an AES key. The 4-byte salt is used by the AEAD algorithm as
            part of the IV, and <bcp14>MUST</bcp14> remain the same for the given <tt>KeyNum</tt>. </t>

          <t>In one example, a publisher could request a key for a group and the Key Manager could
            securely communicate (<tt>CEK, Wapped_CEK, KeyId, KeyLink</tt>) back to the publisher.
            The Key Manager is responsible for publishing the link. In another example, the
            publisher could be a group member and have a group private key in which case the
            publisher can create their own key encryption key, publish it under the Locator and
            proceed. The publisher generates <tt>CEK, Wrapped_CEK, KeyId</tt>, and a KeyLink on its
            own.</t>

          <t>The RSA-OAEP "label" ("additional information" in <xref target="NIST-800-131Ar2" />) is
            constructed as shown in <xref target="AdditionalInfo"/>. It is the concatenation of
            several TLVs from the <tt>RsaOaepCtx</tt>.  The <tt>AEADData, KeyId,
            KeyLink, HashAlg</tt> TLVs are from the <tt>RsaOaepWrapper</tt> field. The label is
            hashed via the <tt>HashAlg</tt>, so the length of the label does not affect the size of
            the encryption.  To tightly bind the encryption to the manifest, the publisher
            <bcp14>SHOULD</bcp14> choose a unique <tt>KeyNum</tt> and <tt>KDFInfo</tt> pair.</t>

          <figure anchor="AdditionalInfo">
            <name>OAEP Label</name>
            <sourcecode type='pseudocode'><![CDATA[
AdditionalInfo = "FLIC RSA-OAEP" ||
                 KeyNum || AeadMode || [KDFData] ||
                 KeyID || HashAlg ||
                 KeyLink (if present in RsaOaepWrapper)]]>
            </sourcecode>
          </figure>

          <t>To create the wrapped key using a Key Encryption Key:</t>
          <ol>
            <li>Obtain the CEK in binary format (e.g. 32 bytes for 256 bits)</li>
            <li>RSA encrypt the <tt>WrappedKey</tt> value using the KEK public key with OAEP padding
              and the OAEP label (additional information), following <xref
                target="NIST-800-131Ar2" />. The encryption is not signed or authenticated because
              the root Manifest must have been signed by the publisher already. Or the encapsulating
              Content Object (Data Object) is signed via ICN mechanisms.</li>
          </ol>

          <t>To decrypt the wrapped key using a Key Encryption Key:</t>
          <ol>
            <li>RSA decrypt the <tt>WrappedKey</tt> value using the KEK private key with OAEP
              padding and OAEP label, following <xref target="NIST-800-131Ar2" />.</li>
            <li>Verify the unwrapped key is a valid length for the AEADMode.</li>
          </ol>

          <t>To encrypt a Manifest, the publisher:</t>
          <ol>
            <li>Acquires the set of (CEK, salt, WrappedKey, KeyId, Locator). The publisher may
              generate these values itself, or acquire them from a key manager.</li>
            <li>Creates a <tt>SecurityCtx</tt> and adds it to the Manifest. The <tt>SecurityCtx</tt>
              includes an <tt>AEADNonce</tt> and <tt>AEADMode</tt>, as per AEAD mode.</li>
            <li>It is <bcp14>RECOMMENDED</bcp14> to also include the use of a KDF in the <tt>AEADData</tt>
              .</li>
            <li>Encrypts the Manifest as per AEAD Mode using the RSA-OAEP SecurityCtx and CEK.</li>
          </ol>

          <t>To decrypt a Manifest, the consumer:</t>
          <ol>
            <li>Acquires the RSA private key corresponding to <tt>KeyId</tt> via the <tt>KeyLink</tt>
              or whatever means the publisher and consumers use to distribute keys.</li>
            <li>It <bcp14>SHOULD</bcp14> verify that it trusts the Manifest publisher to use the
              provided wrapping key.</li>
            <li>Decrypts the <tt>WrappedKey</tt> to get the CEK and salt. If the consumer has
              already decrypted the same exact WrappedKey TLV block, it may use that cached CEK and
              salt. The same wrapping key is determined by the publisher's signing KeyId, the
              wrapping key KeyId, and the AEADData.</li>
            <li>Using the <tt>CEK</tt> and <tt>AEADData</tt>, decrypt the Manifest as per AEAD Mode.</li>
          </ol>
        </section>
      </section>

      <section anchor="encodings">
        <name>Protocol Encodings</name>

        <section anchor="CCNxEncoding">
          <name>CCNx Encoding</name>
          <t>The CCNx type values are defined in <xref target="IANA" />. The section <xref
              target="CCNxTlvs" /> goes over every TLV structure.</t>

          <t>In CCNx, application data content objects use a PayloadType of T_PAYLOADTYPE_DATA. In
            order to clearly distinguish FLIC Manifests from application data, a different payload
            type is required. Therefore this specification defines a new payload type of
            T_PAYLOADTYPE_MANIFEST.</t>

          <figure anchor="CCNxGrammer">
            <name>CCNx Embedding Grammar</name>
            <sourcecode type="abnf"><![CDATA[
ManifestContentObject = TYPE LENGTH [Name] [ExpiryTime]
                        PayloadType Payload
Name = TYPE LENGTH *OCTET ; As per RFC8569
ExpiryTime = TYPE LENGTH *OCTET ; As per RFC8569
PayloadType = TYPE LENGTH T_PAYLOADTYPE_MANIFEST ; Value TBD
Payload : TYPE LENGTH *OCTET ; the serialized Manifest object]]>
            </sourcecode>
          </figure>

          <section anchor="HashNamingStrategy">
            <name>CCNx Hash Naming Strategy</name>
            <t>The Hash Naming Strategy uses CCNx nameless content objects and the HashSchema name
              constructor. This means that
              only the Root Manifest should have a name embedded in the Content object. All other
              are CCNx nameless objects. The Manifest should provide a set of Locators that the
              client
              may use to form the Interests. </t>
            <t>It proceeds as follows:</t>
            <ul>
              <li>The Root Manifest content object bound to a name assigned by the publisher and
                signed by the publisher. It also may have a set of Locators used to fetch the
                remainder of the manifest. The root manifest has a single HashPointer that points to
                the Top Manifest. It may also have cache control directives, such as
                ExpiryTime.</li>

              <li>The Root Manifest has an NsDef that specifies HashSchema. Its GroupData uses that
                NsId. All internal and leaf manifests use the same GroupData NsId. A Manifest Tree <bcp14>
                MAY</bcp14> omit the NsDef and NsId elements and rely on the default being
                HashSchema.</li>

              <li>The Top Manifest is a nameless CCNx content object. It may have cache control
                directives.</li>

              <li>Internal and Leaf manifests are nameless CCNx content objects, possibly with cache
                control directives.</li>

              <li>The Data content objects are nameless CCNx content objects, possibly with cache
                control directives.</li>

              <li>To form an Interest for a direct or indirect pointer, use a Name from one of the
                Locators and put the pointer HashValue into the ContentObjectHashRestriction.</li>
            </ul>
          </section>

          <section anchor="SinglePrefixStrategy">
            <name>CCNx Single Prefix Strategy</name>
            <t>The Single Prefix strategy uses a named Root manifest and then all
              other data and sub-manifest objects use the same Name. They are differentiated only by
              their hash.
              The single prefix name should be different than the root manifest name, to not confuse
              them, as one may wish to use a discovery mechanism on the root manifest and fetch
              it without a hash restriction.</t>

            <t>It proceeds as follows:</t>
            <ul>
              <li>The Root Manifest content object has a name used to fetch the manifest. It is
                signed by the publisher. It has a single Locator used to fetch the remainder of the
                manifest using the common Single Prefix name. It has a single HashPointer that
                points to the Top Manifest. It may also
                have cache control directives, such as ExpiryTime.</li>

              <li>The Root Manifest has an NsDef that specifies PrefixSchema with the Locator for
                the
                single prefix.</li>

              <li>The Top Manifest has the name SinglePrefixName. It may have cache control
                directives. Its GroupData elements must have an NsId that references the NsDef.</li>

              <li>An Internal or Leaf manifest has the name SinglePrefixName, possibly with cache
                control directives. Its GroupData elements must have an NsId that references the
                NsDef.</li>

              <li>The Data content objects have the name SinglePrefixName, possibly with cache
                control directives.</li>

              <li>To form an Interest for a direct or indirect pointer, use SinglePrefixName as the
                Name and put the pointer HashValue into the ContentObjectHashRestriction.</li>
            </ul>
          </section>

          <section anchor="SegmentedPrefixStrategy">
            <name>CCNx Segmented Prefix Strategy</name>
            <t>It proceeds as follows:</t>
            <ul spacing="normal">
              <li>The Root Manifest content object has a name used to fetch the manifest. It is
                signed by the publisher. It has a set of Locators used to fetch the remainder of the
                manifest. It has a single HashPointer that points to the Top Manifest. It may also
                have cache control directives, such as ExpiryTime.</li>

              <li>The Root Manifest has an NsDef that specifies SegmentedPrefix and the
                SegmentedPrefixSchema element specifies the SegmentedPrefixName.</li>

              <li>The publisher tracks the chunk number of each content object within the NsId.
                Objects are be numbered in their traversal order. Within each manifest, the name can
                be constructed from the SegmentedPrefixName plus a Chunk name component.</li>

              <li>The Top Manifest has the name SegmentedPrefixName plus chunk number. It may have
                cache control directives. It's GroupData elements must have an NsId that references
                the NsDef.</li>

              <li>An Internal or Leaf manifest has the name SegmentedPrefixName plus chunk number,
                possibly with cache control directives. Its GroupData elements must have an NsId
                that references the NsDef.</li>

              <li>The Data content objects have the name SegmentedPrefixName plus chunk number,
                possibly with cache control directives.</li>

              <li>To form an Interest for a direct or indirect pointer, use SegmentedPrefixName plus
                chunk number as the Name and put the pointer HashValue into the
                ContentObjectHashRestriction. A consumer must track the chunk number in traversal
                order for each SegmentedPrefixSchema NsId.</li>
            </ul>
          </section>

          <section anchor="HybridStrategy">
            <name>CCNx Hybrid Strategy</name>
            <t>A manifest may use multiple schemas. For example, the application payload in data
              content objects might use SegmentedPrefix while the manifest content objects might use
              HashNaming.</t>

            <t>The Root Manifest should specify an NsDef with a first NsId (say 1) as the HashNaming
              schema and a second NsDef with a second NsId (say 2) as the SegmentedPrefix schema
              along with the SegmentedPrefixName.</t>

            <t>Each manifest (Top, Internal, Leaf) uses two or more HashGroups, where each HashGroup
              has only Direct (with the second NsId) or Indirect (with the first NsId). The number
              of hash groups will depend on how the publisher wishes to interleave direct and
              indirect pointers.</t>

            <t>Manifests and data objects derive their names according to the application's naming
              schema.</t>
          </section>

          <section anchor="CCNxTlvs">
            <name>CCNx TLV Encodings</name>
            <t>This section defines each CCNx TLV encoding and the format of the TLV values.</t>

            <t>FLIC uses variable length integer encodings in several places. We use the term <tt>
              varint</tt> to be a network byte order unsigned integer of length 1 - 8 octets. This
              applies to all fields defined as "INTEGER" in the grammar: <tt>T_SUBTREE_SIZE,
              T_LEAF_SIZE, T_NCID, T_KEYNUM</tt>.</t>

            <t>FLIC encodes hash values as per <xref target="RFC8609" section="3.3.3" />. That is,
              as a hash algorithm type, the length, and the hash output in the value. This applies
              to any field in the grammar defined as "HashValue": <tt>T_SUBTREE_DIGEST,
              T_LEAF_DIGEST, T_PTRS (an array of HashValue), T_PTR, T_KEYID</tt>.</t>

            <t>The CCNx encoding allows for vendor extensions (<tt>T_ORG</tt>) in several places, as
              per <xref target="RFC8609" section="3.3.2" />. A parser may skip over any <tt>T_ORG</tt>
              it does not implement. Where appropriate, we show an optional <tt>T_ORG</tt> tlv where
              allowed.</t>

            <t>The CCNx encoding allows for experimental type identifiers (0x1000-0x1FFF) in most
              TLV contexts. A parser may skip over any experimental TLV it does not implement.
              We do not show experimental TLVs in the artwork below.</t>

            <t>There is no required order of TLV blocks within a TLV context. We show the <bcp14>
              RECOMMENDED</bcp14> ordering of TLV blocks. TLV blocks <bcp14>MUST NOT</bcp14> repeat
              unless specifically allowed in the <xref target="grammar">grammar</xref>.</t>

            <section anchor="tlv_manifest" title="Manifest TLV">
              <t>A Manifest has an outer TLV type that identifies type kind of manifest inside a
                Content Object with a payload type of <tt>T_PAYLOADTYPE_MANIFEST</tt>. FLIC is
                defined as type <tt>T_FLIC_MANIFEST</tt>.</t>

              <t>A FLIC Manifest may be plaintext or encrypted. A plaintext manifest usually only
                has a Node. But it may also have a Security Context, Node, and Authentication Tag.
                This can happen when a manifest is in-place decrypted. In place decryption operates
                on the body of the <tt>EncryptedNode</tt> TLV and then changes the type from <tt>
                T_ENCRYPTED_NODE</tt> to <tt>T_NODE</tt>.</t>
              <figure>
                <name>FLIC manifest TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|        T_FLIC_MANIFEST        |             Length            |
+---------------+---------------+---------------+---------------+
/                       [Security Context]                      /
+---------------+---------------+---------------+---------------+
/                      Node or EncryptedNode                    /
+---------------+---------------+---------------+---------------+
/                      [Authentication Tag]                     /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_security_ctx" title="SecurityCtx TLV">
              <t>The <tt>SecurityCtx</tt> TLV wraps an <tt>AlgroithmCtx</tt>, which may be either a
                symmetric key encryption context <tt>AEADCtx</tt> or an asymmetric key wrapping of
                the decryption key, <tt>RsaWrapCtx</tt>.</t>
              <figure>
                <name>FLIC Security Context TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|        T_SECURITY_CTX         |             Length            |
+---------------+---------------+---------------+---------------+
/                      AEADCtx or RsaWrapCtx                    /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>


            <section anchor="tlv_aead_ctx" title="AEAD Context TLV">
              <t>The <tt>AEADCtx</tt> identifies a symmetric key shared by the publisher and
                consumer. It is identified by a <tt>KeyNum</tt>, which may be an small integer (e.g.
                within a TLS-like session) or a longer integer. CCNx uses up to a 64-bit integer.</t>
              <t>The <tt>AEADNonce</tt> is used to generate the encryption IV, as described in <xref
                  target="aead" />. It is an octet string.</t>
              <t>The <tt>AEADMode</tt> is an integer that identifies the encryption algorithm. All
                defined values fit within 1 octet. The IANA registry "AEAD Algorithms" allows for up
                to 2 octets.</t>
              <figure>
                <name>FLIC AEAD Context TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|           T_AEAD_CTX          |             Length            |
+---------------+---------------+---------------+---------------+
|           T_KEY_NUM           |             Length            | 
+---------------+---------------+---------------+---------------+
/                           <varint>                            /
+---------------+---------------+---------------+---------------+
|           T_NONCE             |             Length            | 
+---------------+---------------+---------------+---------------+
/                           1*OCTET                             /
+---------------+---------------+---------------+---------------+
|          T_AEAD_MODE          |             Length            | 
+---------------+---------------+---------------+---------------+
/                           <varint>                            /
+---------------+---------------+---------------+---------------+
/                           [KDFData]                           /
+---------------+---------------+---------------+---------------+
]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_rsa_wrap_ctx" title="RSA-OAEP Context TLV">
              <t>The <tt>RsaOaepData</tt> has a mandatory <tt>AEADData</tt> section plus optional <tt>
                RsaOaepData</tt>. Note that in the grammar, those are not TLV containers, but simply
                data records. The figure below shows an <tt>RsaOaepCtx</tt> with all parameters.</t>

              <t>The HashAlg value is an unsigned 16-bit integer in
                network byte order.</t>

              <t>The wrapped key value is the RSA-OAEP ciphertext of the <tt>WrappedKey</tt> record.</t>


              <figure>
                <name>FLIC RSA-OAEP TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|         T_RSAOAEP_CTX         |             Length            |
+---------------+---------------+---------------+---------------+
|           T_KEY_NUM           |             Length            | 
+---------------+---------------+---------------+---------------+
/                           <varint>                            /
+---------------+---------------+---------------+---------------+
|           T_NONCE             |             Length            | 
+---------------+---------------+---------------+---------------+
/                           1*OCTET                             /
+---------------+---------------+---------------+---------------+
|          T_AEAD_MODE          |             Length            | 
+---------------+---------------+---------------+---------------+
/                           <varint>                            /
+---------------+---------------+---------------+---------------+
|          T_KDF_DATA           |             Length            | 
+---------------+---------------+---------------+---------------+
/                       <kdf structure>                         /
+---------------+---------------+---------------+---------------+
|            T_KEYID            |             Length            |
+---------------+---------------+---------------+---------------+
/                            1*OCTET                            /
+---------------+---------------+---------------+---------------+
|            T_KEYLINK          |             Length            |
+---------------+---------------+---------------+---------------+
/                          <ccnx link>                          /
+---------------+---------------+---------------+---------------+
|           T_HASH_ALG          |               2               |
+---------------+---------------+---------------+---------------+
|           16-bit int          |
+---------------+---------------+---------------+---------------+
|         T_WRAPPED_KEY         |             Length            |
+---------------+---------------+---------------+---------------+
/                  <RSA-OAEP encrypted octets>                  /
+---------------+---------------+---------------+---------------+

   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_node" title="Node TLV">
              <t>The <tt>Node</tt> contains the manifest information. It has an optional NodeData,
                plus one or more hash groups.</t>

              <figure>
                <name>FLIC Node TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|            T_NODE             |             Length            |
+---------------+---------------+---------------+---------------+
/                           [NodeData]                          /
+---------------+---------------+---------------+---------------+
/                          1*HashGroup                          /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_node_data" title="Node Data TLV">
              <t><tt>NodeData</tt> has no mandatory fields, but several optional fields. If no
                fields are present, a publisher should omit the entire <tt>NodeData</tt> TLV
                container.</t>
              <t>SubtreeSize, SubtreeDigest, and Vendor are encoded as previously specified (<tt>
                INTEGER</tt>, <tt>HashValue</tt>, and <tt>T_ORG</tt>, respectively).</t>

              <figure>
                <name>FLIC NodeData TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|          T_NODE_DATA          |             Length            |
+---------------+---------------+---------------+---------------+
/                         [SubtreeSize]                         /
+---------------+---------------+---------------+---------------+
/                         [SubtreeDigest]                       /
+---------------+---------------+---------------+---------------+
/                           [Locators]                          /
+---------------+---------------+---------------+---------------+
/                             0*NcDef                           /
+---------------+---------------+---------------+---------------+
/                            0*Vendor                           /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>


            <section anchor="tlv_locators" title="Locators TLV">
              <t><tt>Locators</tt> is a TLV container around a list s <tt>Locator</tt> entries. Each <tt>
                Locator</tt> wraps a CCN x Link <xref target="RFC8609" section="3.3.4" />. In the
                CCNx draft, "Link" does not have its own TLV type, but rather is embedded inside a
                type with specific meaning, such as KeyLink or PublicKeyLocator.</t>

              <figure>
                <name>FLIC Locators TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|          T_LOCATORS           |             Length            |
+---------------+---------------+---------------+---------------+
/                           1*Locator                           /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>

              <figure>
                <name>FLIC Locator TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|          T_LOCATOR            |             Length            |
+---------------+---------------+---------------+---------------+
/                             LINK                              /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_ncdef" title="Name Constructor Definition TLV">
              <t><tt>NcDef</tt> provides the information needed for a consumer to construct an
                Interest from a manifest pointer. The information is in a Name Constructor Schema.</t>
              <t><tt>NcId</tt> is encoded as an INTEGER, as previously defined.</t>
              <t><tt>NcSchema</tt> may include <tt>ProtocolFlags</tt>, which are TLVs intended to be
                included in an Interest. These may control discovery or response freshness. The
                value of protocol flags is ICN specific.</t>

              <figure>
                <name>FLIC Name Constructor Definition TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|            T_NCDEF            |             Length            |
+---------------+---------------+---------------+---------------+
/                              NcId                             /
+---------------+---------------+---------------+---------------+
/                            NcSchema                           /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_hash_schema" title="Hash Schema TLV">
              <t>The <tt>HashSchema</tt> uses CCNx nameless objects. It must have one or more
                locators.</t>

              <figure>
                <name>FLIC Hash Schema TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|         T_HASH_SCHEMA         |             Length            |
+---------------+---------------+---------------+---------------+
|           T_LOCATORS          |             Length            |
+---------------+---------------+---------------+---------------+
/                           1*LOCATOR                           /
+---------------+---------------+---------------+---------------+
/                         [ProtocolFlags]                       /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_prefix_schema" title="Prefix Schema TLV">
              <t>The <tt>PrefixSchema</tt> uses named content objects. CCNx uses the provided name
                and does not use locators.</t>
              <t>The <tt>Name</tt> is encoded as <xref target="RFC8609" section="3.6.1" />.</t>

              <figure>
                <name>FLIC Prefix Schema TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|        T_PREFIX_SCHEMA        |             Length            |
+---------------+---------------+---------------+---------------+
/                              Name                             /
+---------------+---------------+---------------+---------------+
/                         [ProtocolFlags]                       /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_segmented_schema" title="Segmented Schema TLV">
              <t>The <tt>SegmentedSchema</tt> uses named content objects. Each object has a name
                prefix plus a unique suffix. The suffix is encoded with NameComponent type <tt>
                SuffixComponentType</tt>. CCNx uses the provided name and does not use locators.</t>
              <t>The <tt>Name</tt> is encoded as <xref target="RFC8609" section="3.6.1" />.</t>
              <t>In CCNx, the <tt>SuffixComponentType</tt> must be 2 octets, as per the CCNx TLV
                type size.</t>

              <figure>
                <name>FLIC Segmented Schema TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|       T_SEGMENTED_SCHEMA      |             Length            |
+---------------+---------------+---------------+---------------+
/                              Name                             /
+---------------+---------------+---------------+---------------+
|         T_SUFFIX_TYPE         |               2               |
+---------------+---------------+---------------+---------------+
|       Name Component Type     |             
+---------------+---------------+---------------+---------------+
/                         [ProtocolFlags]                       /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_hash_group" title="Hash Group TLV">
              <t>A <tt>HashGroup</tt> encloses a series of hash values. It has an optional <tt>
                GroupData</tt> that applies to all the pointers in the group.</t>
              <t>The pointers are bundled in either a <tt>Ptrs</tt> list or an <tt>AnnotatedPtrs</tt>
                list. </t>
              <t><tt>Ptrs</tt> is an array of raw CCNx hash values entries (i.e. SHA256 TLVs), as
                per <xref target="RFC8609" section="3.3.3" />. Each entry <bcp14>MAY</bcp14> be a
                different hash type and different TLV length, so a parser must use the hash TLV type
                and TLV length fields of each entry.</t>
              <t><tt>AnotatedPtrs</tt> is a list of annotations for each pointer.</t>
              <figure>
                <name>FLIC Hash Group TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|          T_HASH_GROUP         |             Length            |
+---------------+---------------+---------------+---------------+
/                          [GroupData]                          /
+---------------+---------------+---------------+---------------+
/                      Ptrs or AnnotatedPtrs                    /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>

              <figure>
                <name>FLIC Ptrs TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|             T_PTRS            |             Length            |
+---------------+---------------+---------------+---------------+
/                          1*HashValue                          /
+---------------+---------------+---------------+---------------+
   ]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_group_data" title="Group Data TLV">
              <t>The <tt>GroupData</tt> is a set of optional fields. The encoding of these fields
                has been previously described (NcId, INTEGER, HashValue, T_ORG).</t>

              <figure>
                <name>FLIC Group Data TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|         T_GROUP_DATA          |             Length            |
+---------------+---------------+---------------+---------------+
/                             [NcId]                            /
+---------------+---------------+---------------+---------------+
/                          [LeafSize]                           /
+---------------+---------------+---------------+---------------+
/                         [LeafDigest]                          /
+---------------+---------------+---------------+---------------+
/                         [SubtreeSize]                         /
+---------------+---------------+---------------+---------------+
/                        [SubtreeDigest]                        /
+---------------+---------------+---------------+---------------+
/                        [StartSegmentId]                       /
+---------------+---------------+---------------+---------------+
/                            0*Vendor                           /
+---------------+---------------+---------------+---------------+
]]></artwork>
              </figure>
            </section>

            <section anchor="tlv_annotated_ptrs" title="Annotated Pointers TLV">
              <t><tt>AnnotatedPtrs</tt> is a list of one or more <tt>PointerBlocks</tt>. Each
                pointer block is one pointer plus zero or more annotations.</t>
              <t>Annotations should not repeat in the same pointer block, unless specifically
                allowed by the annotation.</t>
              <t>The defined annotations (SizeAnnotation, SegmentIdAnnotation, and LinkAnnotation)
                all use previously defined encodings (INTEGER or Name) and are not shown here.</t>
              <figure>
                <name>FLIC Annotated Pointers TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|       T_ANNOTATED_PTRS        |             Length            |
+---------------+---------------+---------------+---------------+
/                         1*PointerBlock                        /
+---------------+---------------+---------------+---------------+
]]></artwork>
              </figure>

              <figure>
                <name>FLIC Pointer Block TLV container</name>
                <artwork align="left"><![CDATA[
                    1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+---------------+---------------+
|          T_PTR_BLOCK          |             Length            |
+---------------+---------------+---------------+---------------+
|             T_PTR             |             Length            |
+---------------+---------------+---------------+---------------+
/                           HashValue                           /
+---------------+---------------+---------------+---------------+
/                          *Annotation                          /
+---------------+---------------+---------------+---------------+
]]></artwork>
              </figure>
            </section>


          </section>
        </section>

        <section anchor="NDNEncoding">
          <name>NDN Encoding</name>
          <t>In NDN, all Manifest Data objects use a ContentType of FLIC (1024), while all
            application data content objects use a PayloadType of Blob.</t>

          <section anchor="NDNHashNaming">
            <name>NDN Hash Naming</name>
            <t>In NDN Hash Naming, a Data Object has a 0-length name. This means that an Interest
              will only have an ImplicitDigest name component in it. This method relies on using NDN
              Forwarding Hints. </t>

            <t>It proceeds as follows:</t>
            <ul>
              <li>The Root Manifest Data has a name used to fetch the manifest. It is signed by the
                publisher. It has a set of Locators used to fetch the remainder of the manifest. It
                has a single HashPointer that points to the Top Manifest. It may also have cache
                control directives.</li>

              <li>The Root Manifest has an NsDef that specifies HashSchema. Its GroupData uses that
                NsId. All internal and leaf manifests use the same GroupData NsId. A Manifest Tree <bcp14>
                MAY</bcp14> omit the NsDef and NsId elements and rely on the default being
                HashSchema.</li>

              <li>The Top Manifest has a 0-length Name. It may have cache control directives.</li>

              <li>Internal and Leaf manifests has a 0-length Name, possibly with cache control
                directives.</li>

              <li>The application Data use a 0-length name, possibly with cache control
                directives.</li>

              <li>To form an Interest for a direct or indirect pointer, the name is only the
                Implicit Digest name component derived from a pointer's HashValue. The
                ForwardingHints come from the Locators. In NDN, one may use one or more locators
                within a single Interest.</li>
            </ul>
          </section>

          <section anchor="NDNSinglePrefix">
            <name>NDN Single Prefix</name>
            <t>In Single Prefix, the Data name is a common prefix used between all objects in that
              namespace, without a Segment or other counter. They are distinguished via the Implicit
              Digest name component. The FLIC Locators go in the ForwardingHints.</t>

            <t>It proceeds as follows:</t>
            <ul spacing="normal">
              <li>The Root Manifest Data object has a name used to fetch the manifest. It is signed
                by the publisher. It has a set of Locators used to fetch the remainder of the
                manifest. It has a single HashPointer that points to the Top Manifest. It may also
                have cache control directives.</li>

              <li>The Root Manifest has an NsDef that specifies SinglePrefix and the
                SinglePrefixSchema element specifies the SinglePrefixName.</li>

              <li>The Top Manifest has the name SinglePrefixName. It may have cache control
                directives. Its GroupData elements must have an NsId that references the NsDef.</li>

              <li>An Internal or Leaf manifest has the name SinglePrefixName, possibly with cache
                control directives. Its GroupData elements must have an NsId that references the
                NsDef.</li>

              <li>The Data content objects have the name SinglePrefixName, possibly with cache
                control directives.</li>

              <li>To form an Interest for a direct or indirect pointer, use SinglePrefixName as the
                Name and append the pointer's HashValue into an ImplicitDigest name component. Set
                the ForwardingHints from the FLIC locators.</li>
            </ul>
          </section>

          <section anchor="NDNSegmentedPrefix">
            <name>NDN Segmented Prefix</name>
            <t>In Segmented Prefix, the Data name is a common prefix plus a segment number, so each
              manifest or application data object has a unique full name before the implicit digest.
              This means the consumer must maintain a counter for each SegmentedPrefix
              namespace.</t>
            <aside>
              <t><strong>Optional</strong>: Use AnnotatedPointers to indicate the segment number of
                each hash pointer to avoid needing to infer the segment numbers.</t>
              <t><strong>Optional</strong>: Use StartSegmentId in GroupData to indicate the segment
                number of for each group. The producer must ensure that each subsequent GroupData
                starts at the correct offset.</t>
            </aside>

            <t>It proceeds as follows:</t>
            <ul spacing="normal">
              <li>The Root Manifest Data object has a name used to fetch the manifest. It is signed
                by the publisher. It has a set of Locators used to fetch the remainder of the
                manifest. It has a single HashPointer that points to the Top Manifest. It may also
                have cache control directives.</li>

              <li>The Root Manifest has an NsDef that specifies SegmentedPrefix and the
                SegmentedPrefixSchema element specifies the SegmentedPrefixName.</li>

              <li>The publisher tracks the segment number of each Data object within a
                SegmentedPrefix NsId. Data is numbered in traversal order. Within each manifest, the
                name is constructed from the SegmentedPrefixName plus a Segment name component.</li>

              <li>The Top Manifest has the name SegmentedPrefixName plus segment number. It may have
                cache control directives. Its GroupData elements must have an NsId that references
                the NsDef.</li>

              <li>An Internal or Leaf manifest has the name SegmentedPrefixName plus segment number,
                possibly with cache control directives. Its GroupData elements must have an NsId
                that references the NsDef.</li>

              <li>The Data content objects have the name SegmentedPrefixName plus chunk number,
                possibly with cache control directives.</li>

              <li>To form an Interest for a direct or indirect pointer, use SegmentedPrefixName plus
                segment number as the Name and put the pointer HashValue into the ImplicitDigest
                name component. A consumer must track the segment number in traversal order for each
                SegmentedPrefixSchema NsId.</li>
            </ul>
          </section>

          <section anchor="NDNHybrid">
            <name>NDN Hybrid Schema</name>
            <t>A manifest may use multiple schemas. For example, the application payload in data
              content objects might use SegmentedPrefix while the manifest content objects might use
              HashNaming.</t>

            <t>The Root Manifest should specify an NsDef with a first NsId (say 1) as the HashNaming
              schema and a second NsDef with a second NsId (say 2) as the SegmentedPrefix schema
              along with the SegmentedPrefixName.</t>

            <t>Each manifest (Top, Internal, Leaf) uses two or more HashGroups, where each HashGroup
              has only Direct (with the second NsId) or Indirect (with the first NsId). The number
              of hash groups will depend on how the publisher wishes to interleave direct and
              indirect pointers.</t>

            <t>Manifests and data objects derive their names according to the application's naming
              schema.</t>

          </section>
        </section>
      </section>

      <section>
        <name>Example Structures</name>
        <section>
          <name>Leaf-only data</name>

          <figure anchor="leafonly">
            <name>Leaf-only manifest tree</name>
            <artset>
              <artwork type="svg" name="leafonly.svg">
                <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 216 128"
                  width="60%" class="diagram" text-anchor="middle" font-family="monospace"
                  stroke-linecap="round">
                  <path d="M 164,56 L 168,64" fill="none" stroke="black" />
                  <path d="M 40,64 L 44,56" fill="none" stroke="black" />
                  <path d="M 44,56 L 92,56" fill="none" stroke="black" />
                  <path d="M 124,56 L 164,56" fill="none" stroke="black" />
                  <g class="text">
                    <text x="108" y="20">Root</text>
                    <text x="104" y="36">|</text>
                    <text x="108" y="52">M0</text>
                    <text x="104" y="68">|</text>
                    <text x="36" y="84">M1</text>
                    <text x="108" y="84">M2</text>
                    <text x="180" y="84">M3</text>
                    <text x="32" y="100">/ | \</text>
                    <text x="104" y="100">/ | \</text>
                    <text x="176" y="100">/ | \</text>
                    <text x="108" y="116">D0 D1 D2 D3 D4 D5 D6 D7 D8</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art" align="center" name="leafonly.txt">
                <![CDATA[
           Root
            |
     ______ M0 _____
    /       |       \
   M1       M2       M3
 / | \    / | \    / | \
D0 D1 D2 D3 D4 D5 D6 D7 D8
                ]]>
              </artwork>
            </artset>
          </figure>
        </section>

        <section>
          <name>Linear (chain)</name>
          <t>Of special interest are "skewed trees" where a pointer to a manifest may only appear as
            last pointer of (sub-) manifests. Such a tree becomes a sequential list of manifests
            with a maximum of data pointers per manifest packet. Beside the tree shape we also show
            this data structure in form of packet content where D stands for a data pointer and M is
            the hash of a manifest packet.</t>
          <artwork align="left" name="" type="ascii-art" alt=""><![CDATA[
Root -> M0 ----> M1 ----> ...
|->DDDD  |->DDDD  |- ...
                        ]]></artwork>
        </section>
      </section>
    </section>

    <section anchor="experiments" numbered="true" toc="default">
      <name>Experimenting with FLIC</name>
      <t>FLIC is expected to enable a number of salient experiments in the use of ICN protocols by
        applications. These experiments will help not only to inform the desirable structure of ICN
        applications but reflect back to the features included in FLIC to evaluate their usefulness
        to those applications. While many interesting design aspects of FLIC remain to be discovered
        through experience, a number of important questions to be answered through experimentation
        include:</t>
      <ul>
        <li>use for just files or other collections like directories</li>
        <li>use for particular applications, like streaming media manifests</li>
        <li>utility of pointer annotations to optimize retrieval</li>
        <li>utility of the encryption options for use by repositories and forwarders</li>
        <li>need for application metadata in manifests</li>
      </ul>
    </section>

    <section anchor="IANA">
      <name>IANA Considerations</name>
      <t>FLIC adds two values to existing registries and defines two new registry in the
        "Content-Centric Networking (CCNx)" group.</t>

      <t>The FLIC registries follow the CCNx convention of reserving the namespace 0x1000 - 0x1FFF
        for experimental use. It also uses the T_ORG (0x0FFF) definition for organizational (vendor)
        extensions in the <tt>NodeData</tt> and <tt>GroupData</tt> fields.</t>

      <t>IANA will assign value "0x0004" to "T_MANIFEST_ID" in the "CCNx Name Segment Types"
        registry.</t>

      <t>IANA will assign value "0x0003" to "T_PAYLOADTYPE_MANIFEST" in the "CCNx Payload Types"
        registry.</t>


      <t>IANA will add the following new registry to the
        "Content-Centric Networking (CCNx)" registry group at
        https://www.iana.org/assignments/ccnx):
      </t>

      <ul spacing="compact">
        <li>Registry Name: CCNx Manifest Type</li>
        <li>Registration Procedure: Specification Required</li>
        <li>This defines the TLV type of a Manifest inside a CCNx Payload.</li>
      </ul>

      <table align="left">
        <name>Manifest Type</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_FLIC_MANIFEST</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001-0x0FFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>


      <t>IANA will add the following new registry and sub-registries to the
        "Content-Centric Networking (CCNx)" registry group at
        https://www.iana.org/assignments/ccnx):
      </t>

      <ul spacing="compact">
        <li>Registry Name: FLIC Manifest</li>
        <li>Registration Procedure: Specification Required</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_SECURITY_CTX</td>
            <td align="center"></td>
          </tr>

          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_NODE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0002</td>
            <td align="center">T_ENCRYPTED_NODE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0003</td>
            <td align="center">T_AUTH_TAG</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0004-0x0FFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (SecurityCtx)</li>
        <li>Registration Procedure: Specification Required</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest (SecurityCtx)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_AEAD_CTX</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_RSAOAEP_CTX</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0002-0x0FFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (Node)</li>
        <li>Registration Procedure: Specification Required</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest (Node)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_NODE_DATA</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_HASH_GROUP</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0002</td>
            <td align="center">T_SUBTREE_SIZE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0003</td>
            <td align="center">T_SUBTREE_DIGEST</td>
            <td align="center">Value is in CCNx Hash Format <xref target="RFC8609" section="3.3.3" /></td>
          </tr>
          <tr>
            <td align="center">0x0004</td>
            <td align="center">T_NCDEF</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0005</td>
            <td align="center">T_NCID</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0006</td>
            <td align="center">T_LOCATORS</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0007</td>
            <td align="center">T_PTRS</td>
            <td align="center">Value is array of CCNx Hash Format <xref target="RFC8609"
                section="3.3.3" /></td>
          </tr>
          <tr>
            <td align="center">0x0008</td>
            <td align="center">T_ANNOTATED_PTRS</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0009</td>
            <td align="center">T_PTR_BLOCK</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x000A</td>
            <td align="center">T_PTR</td>
            <td align="center">Value is in CCNx Hash Format <xref target="RFC8609" section="3.3.3" /></td>
          </tr>
          <tr>
            <td align="center">0x000B</td>
            <td align="center">T_GROUP_DATA</td>
            <td align="center"></td>
          </tr>

          <tr>
            <td align="center">0x000C-0x000F</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0010</td>
            <td align="center">T_HashSchema</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0011</td>
            <td align="center">T_PrefixSchema</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0012</td>
            <td align="center">T_SegmentedSchema</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0013-0x0FFD</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0FFE</td>
            <td align="center">T_PAD</td>
            <td align="center">
              <xref target="RFC8609" section="3.3.1" />
            </td>
          </tr>
          <tr>
            <td align="center">0x0FFF</td>
            <td align="center">T_ORG</td>
            <td align="center">
              <xref target="RFC8609" section="3.3.2" />
            </td>
          </tr>

          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>

      </table>

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (NcSchema)</li>
        <li>Registration Procedure: Specification Required</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest (NcSchema)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_NAME</td>
            <td align="center">
              <xref target="RFC8609" />
            </td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_PROTOCOL_FLAGS</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0002</td>
            <td align="center">T_SUFFIX_TYPE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0003-0x0005</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0006</td>
            <td align="center">T_LOCATORS</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0007-0x000C</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x000D</td>
            <td align="center">T_LINK</td>
            <td align="center">Value is a Link <xref target="RFC8609" section="3.3.4" /></td>
          </tr>
          <tr>
            <td align="center">0x000E-0x0FFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (Group Data)</li>
        <li>Registration Procedure: Expert Review</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest (Group Data)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_LEAF_SIZE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_LEAF_DIGEST</td>
            <td align="center">Value is a CCNx Hash Format <xref target="RFC8609" section="3.3.3" /></td>
          </tr>
          <tr>
            <td align="center">0x0002</td>
            <td align="center">T_SUBTREE_SIZE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0003</td>
            <td align="center">T_SUBTREE_DIGEST</td>
            <td align="center">Value is in CCNx Hash Format <xref target="RFC8609" section="3.3.3" /></td>
          </tr>
          <tr>
            <td align="center">0x0004</td>
            <td align="center">T_START_SEGMENT_ID</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0005-0x0FFE</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0FFF</td>
            <td align="center">T_ORG</td>
            <td align="center">
              <xref target="RFC8609" section="3.3.2" />
            </td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>

        </tbody>
      </table>

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (SecurityCtx Parameters)</li>
        <li>Registration Procedure: Expert Review</li>
      </ul>

      <table align="left">
        <name>FLIC Manifest (SecurityCtx Parameters)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_KEYNUM</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_NONCE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0002</td>
            <td align="center">T_AEADMode</td>
            <td align="center">Value a per IANA "AEAD Algorithms" <xref target='RFC5116' />
            </td>
          </tr>

          <tr>
            <td align="center">0x0003</td>
            <td align="center">T_HASH_ALG</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0004</td>
            <td align="center">T_WRAPPED_KEY</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0005</td>
            <td align="center">T_KDF_DATA</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0006</td>
            <td align="center">T_KDF_ALG</td>
            <td align="center">Value as per IANA "HPKE KDF Identifiers" <xref target="RFC9180" /></td>
          </tr>
          <tr>
            <td align="center">0x0007</td>
            <td align="center">T_KDF_INFO</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0008</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0009</td>
            <td align="center">T_KEYID</td>
            <td align="center">As per <xref target="RFC8609" section="3.6.4.1.4" /></td>
          </tr>
          <tr>
            <td align="center">0x000A-0x000D</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x000E</td>
            <td align="center">T_KEYLINK</td>
            <td align="center">As per <xref target="RFC8609" section="3.6.4.1.4" /></td>
          </tr>
          <tr>
            <td align="center">0x000F-0x0FFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>

      <!--
        <aside><t>Do we need to reproduce this here, or is it sufficent to refer to the IANA AEAD
      table?</t></aside>

        <table align="left"><name>FLIC Manifest (AEADMode Values)</name>
          <thead>
          <tr>
            <th align='center'>Numeric ID</th>
            <th align='center'>Name</th>
            <th align='center'>Reference</th>
          </tr>
           </thead>
          <tbody>
            <tr>
              <td align='center'>1</td>
              <td align='center'>AEAD_AES_128_GCM</td>
              <td align='center'><xref target='RFC5116'/> </td>
            </tr>
             <tr>
              <td align='center'>2</td>
              <td align='center'>AEAD_AES_256_GCM</td>
              <td align='center'><xref target='RFC5116'/> </td>
            </tr>
            <tr>
              <td align='center'>3</td>
              <td align='center'>AEAD_AES_128_CCM</td>
              <td align='center'><xref target='RFC5116'/> </td>
            </tr>
             <tr>
              <td align='center'>4</td>
              <td align='center'>AEAD_AES_256_CCM</td>
              <td align='center'><xref target='RFC5116'/> </td>
            </tr>
          </tbody>
        </table>
-->

      <ul spacing="compact">
        <li>Sub-registry Name: FLIC Manifest (Annotation)</li>
        <li>Registration Procedure: Expert Review</li>
      </ul>


      <table align="left">
        <name>FLIC Manifest (Annotation)</name>
        <thead>
          <tr>
            <th align="center">Type</th>
            <th align="center">Name</th>
            <th align="center">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="center">0x0000</td>
            <td align="center">T_ANN_SIZE</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0001</td>
            <td align="center">T_ANN_SEGMENT_ID</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0003-0x000C</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x000D</td>
            <td align="center">T_LINK</td>
            <td align="center">Value is a Link <xref target="RFC8609" section="3.3.4" /></td>
          </tr>
          <tr>
            <td align="center">0x000E-0x0FFE</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x0FFF</td>
            <td align="center">T_ORG</td>
            <td align="center">
              <xref target="RFC8609" section="3.3.2" />
            </td>
          </tr>
          <tr>
            <td align="center">0x1000-0x1FFF</td>
            <td align="center">Reserved for experimental use</td>
            <td align="center"></td>
          </tr>
          <tr>
            <td align="center">0x2000-0xFFFF</td>
            <td align="center">Unassigned</td>
            <td align="center"></td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="Security">
      <name>Security Considerations</name>

      <section>
        <name>Trust, Security, and Privacy Goals</name>
        <t>A FLIC manifest has it's own security and privacy apart from the underlying application
          data that the manifest describes. The trust and privacy of the application data is not
          considered by FLIC, only the trust, security, and privacy of the manifest itself. The trust of a
          consumer on a manifest is based on the root manifest name, it's publisher's key, the signature on
          the root manifest, and the consumers belief that the given key is trusted to publish the name.</t>

        <t>The security and privacy of a FLIC manifest is for the hash pointers and name
          constructors it contains. FLIC does not provide privacy for: the name of the root manifest
          or any named ICN packet in the tree, the publisher's public key ID in any manifest or
          application data object, the key identifiers used to encrypt a FLIC manifest. The first
          two items are part of the Content Object and thus outside the FLIC security envelope
          (though they are authenticated by the root manifest signature). The FLIC <tt>SecurityCtx</tt>
          information is outside the encryption envelope, so elements like the symmetric <tt>
          KeyNumber</tt> or the RSA-OAEP wrapping <tt>KeyId</tt> are exposed. </t>

        <t> An observer may be able to track, for example, all manifests from a publisher that use
          the same preshared symmetric key by the pair (publisher public key id, key number) in the
          Content Object and FLIC security context. With RSA-OAEP encapsulation, the wrapping key id
          and the wrapped key number are public information and could be used to correlate manifest
          objects. One could use a unique wrapped key (and thus key number) for each manifest. If
          using a KDF, the <tt>KDFInfo</tt> field is public and could be used to correlate manifests
          if kept constant for a single manifest tree or a sequential counter is used. </t>
      </section>

      <section>
        <name>Integrity and Origin Authentication of FLIC Manifests</name>
        <t>A FLIC Manifest is used to describe how to form Interests to access CCNx or NDN
          application data. The Manifest is itself either an individual content object, or a tree of
          content objects linked together via the corresponding content hashes. The NDN and CCnx
          protocol architectures directly provide both individual object integrity (using
          cryptographic strong hashes) and data origin authentication (using signatures). The
          protocol specifications, <xref target="NDN" /> and <xref target="RFC8609">CCNx</xref>
          respectively, provide the protocol machinery and keying to support strong integrity and
          authentication. Therefore, FLIC utilizes the existing protocol specifications for these
          functions, rather than providing its own. There are a few subtle differences in the
          handling of signatures and keys in NDN and CCNx worth recapitulating here:</t>
        <ul>
          <li>NDN in general adds a signature to every individual data packet rather than
            aggregating signatures via some object-level scheme. When employing FLIC Manifests to
            multi-packet NDN objects, it is expected that a consumer will use the FLIC Manifest
            signature to govern the trust of all the application data, rather than the signatures on
            the application data packets.</li>
          <li>In contrast, CCNx is biased to have primitive objects or pieces thereof be "nameless"
            in the sense they are identified only by their hashes rather than each having a name
            directly bound to the content through an individual signature. Therefore, CCNx depends
            heavily on FLIC (or an alternative method) to provide the name and the signed binding of
            the name to the content described in the Manifest</li>
        </ul>
        <t>A FLIC Manifest therefore gets integrity of its individual pieces through the existing
          secure hashing procedures of the underlying protocols. Origin authentication of the entire
          Manifest is achieved through hash chaining and applying a signature <strong>only</strong>
          to the root Manifest of a manifest tree. It is important to note that the Name of the
          Manifest, which is what the signature is bound to, need not bear any particular
          relationship to the names of the application objects pointed to in the Manifest via Name
          Constructors. This has a number of important benefits described in <xref
            target="nameconstructors" />.</t>
      </section>

      <section>
        <name>Confidentiality of Manifest Data</name>
        <t>ICN protocol architectures like CCNx and NDN, while providing integrity and origin
          authentication as described above, leaves confidentiality issues entirely in the domain of
          the ICN application. Therefore, since FLIC is an application-level construct in both NDN
          and CCNx, it is incumbent on this specification for FLIC to provide the desired
          confidentiality properties using encryption. One could leave the specification of Manifest
          encryption entirely in the hands of the individual application utilizing FLIC, but this
          would be undesirable for a number of reasons:</t>
        <ul>
          <li>The sensitivity of the information in a Manifest may be different from the sensitivity
            of the application data it describes. In some cases, it may not be necessary to encrypt
            manifests, or to encrypt them with a different keying scheme from that used for the
            application data</li>
          <li>One of the major capabilities enabled by FLIC is to allow repositories or forwarding
            caches to operate on Manifests (see in particular <xref target="metadata" />). In order
            to allow such intermediaries to interpret manifests without revealing the underlying
            application data, separate encryption and keying is necessary</li>
          <li>A strong design goal of FLIC is <em>universality</em> such that it can be used
            transparently by many different ICN applications. This argues that FLIC should have a
            set of common encryption and keying capabilities that can be delegated to library code
            and not have to be re-worked by each individual application (see <xref
              target="libraries" />)</li>
        </ul>

        <t>Therefore, this specification directly specifies two encryption encapsulations and
          associated links to key management, as described in <xref target="encryption" />. As more
          experience is gained with various use cases, additional encryption capabilities may be
          needed and hence we expect the encryption aspects of this specification to evolve over
          time.</t>
      </section>

      <section anchor="OAEP_Security">
        <name>RSA-OAEP Security</name>
        <t>The RSA-OAEP encryption mechanism follows the recommendations of <xref
            target="NIST-800-56Br2" />, when not used for group keying. FLIC RSA-OAEP does not use
          integral key confirmation (MacKey), but rather signs the root manifest with the sender's
          private key. The RSA-OAEP encryption is of both the transported key, K, but also an AES
          salt, S.</t>

        <t>RSA key generation is assumed to comply with <xref target="NIST-800-56Br2" /> Sec 6., but
          that is outside the control of FLIC.</t>

        <t>The belief of the sender that it is using the correct wrapping public key for the
          receiver, and the sender's belief that the receiver has possession of the private key
          are functions of the key distribution system beyond the scope of FLIC. One possible
          mechanism to bring these beliefs closer to FLIC is to require that the manifest requester
          sign the Interest, such as using the CCNx mechanisms for signing an Interest, and the
          sender (publisher) check that the signature time is recent. This mechanism requires
          that the sender already have the public key and trust the owner of the private key
          to consume the manifest. This mechanism should not be used to distribute the public key.</t>

        <t>The RSA-OAEP mechanism uses approved NIST hash functions (SHA256 or SHA512, as per the
          IANA CCNx hash function registry). It also uses additional information for the OAEP label,
          as recommended by <xref target="NIST-800-56Br2" /> Sec 9.1.</t>
      </section>
      <section>
        <name>Symmetric key lifespan, scope, and use</name>
        <t>The lifespan and scope of symmetric keys, as identified by a <tt>KeyNum</tt>, is
          different between an <tt>AeadCtx</tt> and a <tt>RsaOaepCtx</tt>. In the <tt>AeadCtx</tt>
          case, the lifespan and scope is agreed to by the publisher and consumer out of band. In
          the <tt>RsaOaepCtx</tt> the lifespan and scope is implicitly the current manifest. We will
          discuss the <tt>RsaOaepCtx</tt> case first, as it is the simpler of the two.</t>

        <t>For <tt>RsaOaepCtx</tt>, the first manifest in the tree to use RSA-OAEP must include the
          wrapped key. The <tt>KeyNum</tt> is purely local within the manifest. The only requirement
          is that the <tt>KeyNum</tt> have a one-to-one association with a specific wrapped key
          within the manifest. That is, a publisher <bcp14>MUST NOT</bcp14> reuse a <tt>KeyNum</tt>
          within a single manifest tree for two different AES key and salt combinations. The key
          lifespan is strictly the <tt>ExpiryTime</tt> of the manifest and the scope is that single
          manifest.</t>

        <t>A publisher should use new symmetric keys for each manifest encrypted with RSA-OAEP.</t>

        <t>For <tt>AeadCtx</tt>, a publisher and one or more consumers agree on a shared symmetric
          key out-of-band and share it via some means. The publisher and consumer must agree on both
          the lifespan of the key and its scope. The lifespan of such a key should be no shorter
          than the greatest <tt>ExpiryTime</tt> of a manifest published with the key. The scope of
          use should be, at minimum, manifests signed by the publisher's <tt>KeyId</tt>. The
          publisher and consumer may also add name prefix limitations to a symmetric key's scope.</t>

        <t>Because there is no requirement that an <tt>AeadCtx</tt> <tt>KeyNum</tt> be globally
          unique, one should store them based on their scopes, such as <tt>(Publisher KeyId, KeyNum)</tt>
          or <tt>(Publisher KeyId, Name Prefix, KeyNum)</tt>.</t>

        <t>If a publisher will use a single AES key across multiple manifests, it <bcp14>MUST</bcp14> use
        unique KDF derived keys or ensure that it never re-uses the same nonce.</t>
      </section>

      <section>
        <name>Hiding Plaintext Length</name>
        <t>A publisher <bcp14>MAY</bcp14> include a <tt>Pad</tt> element in the <tt>Node</tt>
          element to hide the true length of a manifest. It is <bcp14>RECOMMENDED</bcp14> that a
          publisher pad all encrypted <tt>Node</tt> to a multiple of 128 bytes, or up to the maximum
          that will fit in the MTU target, to reduce the number of possible manifest sizes. It is
          important that the sequence of manifest sizes within a manifest tree not have an
          identifying sequence of sizes. A publisher of an encrypted manifest <bcp14>SHOULD</bcp14>
          pad all manifests in a tree out to the same largest size.</t>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.3310.xml" />
        <!--    <xi:include
        href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.3394.xml"/> -->
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.5116.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.5288.xml" />
        <!--		<xi:include
        href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.5990.xml"/> -->
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.6655.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.8017.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.8569.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.8609.xml" />
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.9180.xml" />
      </references>

      <references>
        <name>Informative References</name>
        <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.7927.xml" />
        <xi:include
          href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml3/reference.I-D.draft-wood-icnrg-ccnxkeyexchange-02.xml" />

        <reference anchor="NIST-800-38D" target="https://doi.org/10.6028/NIST.SP.800-38D">
          <front>
            <title>Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and
              GMAC</title>
            <author surname="Dworkin" initials="M." />
            <date year="2007" />
          </front>
          <seriesInfo name="National Institute of Standards and Technology" value="SP 800-38D" />
        </reference>

<!--
        <reference anchor="SHS"
          target="https://csrc.nist.gov/publications/fips/fips180-4/
              fips180-4_final.pdf">
          <front>
            <title>Secure Hash Standard, United States of American,
              National Institute of Science and Technology, Federal
              Information Processing Standard (FIPS) 180-4</title>
            <author fullname="National Institute of Science and Technology" />
            <date year="2012" />
          </front>
          <seriesInfo name="National Institute of Standards and Technology" value="SP 180-4" />
        </reference>
-->

        <reference anchor="NIST-800-56Br2" target="https://doi.org/10.6028/NIST.SP.800-56Br2">
          <front>
            <title>Recommendation for Pair-Wise Key-Establishment Using Integer Factorization
              Cryptography</title>
            <author surname="Barker" initials="E." />
            <author surname="Chen" initials="L." />
            <author surname="Roginsky" initials="A." />
            <author surname="Vassilev" initials="A." />
            <author surname="Davis" initials="R." />
            <author surname="Simon" initials="S." />
            <date year="2019" />
          </front>
          <seriesInfo name="National Institute of Standards and Technology"
            value="SP 800-56B Rev. 2" />
        </reference>


        <reference anchor="NIST-800-131Ar2" target="https://doi.org/10.6028/NIST.SP.800-131Ar2">
          <front>
            <title>Transitioning the Use of Cryptographic Algorithms and Key Lengths</title>
            <author surname="Barker" initials="E." />
            <author surname="Roginsky" initials="A." />
            <date year="2019" />
          </front>
          <seriesInfo name="National Institute of Standards and Technology"
            value="SP 800-131A Rev. 2" />
        </reference>

        <reference anchor="NDN" target="https://named-data.net/project/execsummary/">
          <front>
            <title>Named Data Networking</title>
            <author surname="NDN team" />
            <date>various</date>
          </front>
        </reference>

        <reference anchor="NDNTLV" target="http://named-data.net/doc/ndn-tlv/">
          <front>
            <title>NDN Packet Format Specification.</title>
            <author surname="NDN Project Team" />
            <date year="2016" />
          </front>
        </reference>

        <reference anchor="repository"
          target="https://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification">
          <front>
            <title>Repo Protocol Specification</title>
            <author surname="NDN Project Team" />
            <date>Various</date>
          </front>
        </reference>

        <reference anchor="venti" target="http://doc.cat-v.org/plan_9/4th_edition/papers/venti/">
          <front>
            <title>Venti: a new approach to archival storage</title>
            <author surname="Sean Quinlan and Sean Dorward" />
            <date year="2002" />
          </front>
          <seriesInfo name="Bell Labs Document Archive" value="/sts/doc" />
        </reference>

        <reference anchor="ccnpy" target="https://github.com/mmosko/ccnpy">
          <front>
            <title>ccnpy: A pure-python CCNx Client</title>
            <author surname="Mosko" initials="M." />
            <date year="2024" />
          </front>
        </reference>


        <reference anchor="ProjectOrigin"
          target="https://github.com/PARC/CCNxReports/blob/master/SelectedTopics/p2pshare.pdf">
          <front>
            <title>Peer-to-Peer Sharing with CCNx 1.0</title>
            <author surname="Mosko" initials="M." />
            <date year="2014" />
          </front>
        </reference>

      </references>
    </references>


    <section anchor="Usage">
      <name>Usage Examples</name>
      <section anchor="Locating">
        <name>Locating FLIC leaf and manifest nodes</name>
        <t>The names of manifest and data objects are often missing or not unique, unless using
          specific naming conventions. In this example, we show how using manifest locators is used
          to generate Interests. Take for example the figure below where the root manifest is named
          by hash h0. It has nameless children with hashes with hashes h1 ... hN. </t>

        <figure anchor="Locating1">
          <name>Data Organization</name>
          <artwork align="left" name="" type="ascii-art" alt=""><![CDATA[
Objects:
manifest(name=/a/b/c, ptr=h1, ptr=hN)  - has hash h0
nameless(data1)                        - has hash h1
...
nameless(dataN)                        - has hash hN

Query for the manifest:
interest(name=/a/b/c, implicitDigest=h0)
                ]]></artwork>
        </figure>

        <t>After obtaining the manifest, the client fetches the contents. In this first instance,
          the manifest does not provide any Locators data structure, so the client must continue
          using the name it used for the manifest.</t>

        <figure anchor="Locating2">
          <name>Data Interests</name>
          <artwork align="left" name="" type="ascii-art" alt=""><![CDATA[
interest(name=/a/b/c, implicitDigest=h1)
...
interest(name=/a/b/c, implicitDigest=hN)
                ]]></artwork>
        </figure>

        <t>Using the locator metadata entry, this behavior can be changed:</t>
        <figure anchor="Locating3">
          <name>Using Locators</name>
          <artwork align="left" name="" type="ascii-art" alt=""><![CDATA[
Objects:
manifest(name=/a/b/c,
hashgroup(loc=/x/y/z, ptr=h1)
hashgroup(ptr=h2)             - has hash h0
nameless(data1)               - has hash h1
nameless(data2)               - has hash h2

Queries:
interest(name=/a/b/c, implicitDigest=h0)
interest(name=/x/y/z, implicitDigest=h1)
interest(name=/a/b/c, implicitDigest=h2)
                ]]></artwork>
        </figure>
      </section>

      <section anchor="Seeking">
        <name>Seeking</name>
        <t>Fast seeking (without having to sequentially fetch all content) works by skipping over
          entries for which we know their size. The following expression shows how to compute the
          byte offset of the data pointed at by pointer <tt>P_i</tt>, call it <tt>offset_i</tt>. In
          this formula, let <tt>P_i.size</tt> represent the Size value of the <em>i</em>-th pointer.</t>

        <sourcecode type="pseudocode"><![CDATA[offset_i = \sum_{k=1}^{i-1} &gt; P_k.size]]></sourcecode>

        <t>With this offset, seeking is done as follows:</t>
        <figure anchor="Seeking1">
          <name>Seeking Algorithm</name>
          <sourcecode type='pseudocode'><![CDATA[
Input: seek_pos P, a FLIC manifest with a hash group having N entries
Output: pointer index i and byte offset o, or out-of-range error
Algorithm:
offset = 0
for i in 1..N do
   if (P &gt; offset + P_i.size)
      return (i, P - offset)
   offset += P_i.size
return out-of-range
]]>
          </sourcecode>
        </figure>

        <t>Seeking in a BlockHashGroup is different since offsets can be quickly computed. This is
          because the size of each pointer P_i except the last is equal to the SizePerPtr value. For
          a BlockHashGroup with N pointers, OverallByteCount D, and SizePerPointer L, the size of
          P_N is equal to the following:</t>
        <artwork align="left" name="" type="" alt="">
<![CDATA[D - ((N - 1) * L)]]>
        </artwork>

        <t>In a BlockHashGroup with k pointers, the size of P_k is equal to:</t>
        <artwork align="left" name="" type="" alt="">
<![CDATA[D - L * (k - 1)]]>
        </artwork>

        <t>Using these, the seeking algorithm can be thus simplified to the following:</t>
        <figure anchor="Seeking2">
          <name>Seeking Algorithm</name>
          <sourcecode type='pseudocode'><![CDATA[
Input: seek_pos P, a FLIC manifest with a hash group having
                   OverallByteCount S and SizePerPointer L.
Output: pointer index i and byte offset o, or out-of-range error
Algorithm:
if (P > S)
   return out-of-range
i = floor(P / L)
if (i > N)
   return out-of-range # bad FLIC encoding
o = P mod L
return (i, o)]]>
          </sourcecode>
        </figure>

        <aside>
          <t><strong>Note</strong>: In both cases, if the pointer at position i is a manifest
            pointer, this algorithm has to be called once more, seeking to seek_pos o inside that
            manifest.</t>
        </aside>

      </section>
      <section anchor="dedup">
        <name>Block-level de-duplication</name>
        <t>Consider a huge file, e.g. an ISO image of a DVD or program in binary be patched. In this
          case, all existing encoded ICN chunks can remain in the repository while only the chunks
          for the patch itself is added to a new manifest data structure, as is shown in the diagram
          below. For example, the <xref target="venti">venti archival file system of Plan9</xref>
          uses this technique.</t>

        <figure anchor="dedup1">
          <name>De-duplications</name>
          <artset>
            <artwork type="svg" name="dedup.svg" align="center">
              <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="80%" viewBox="0 0 472 96" 
                class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 80,16 L 128,16" fill="none" stroke="black"/>
                <path d="M 168,16 L 184,16" fill="none" stroke="black"/>
                <path d="M 280,16 L 296,16" fill="none" stroke="black"/>
                <path d="M 336,16 L 392,16" fill="none" stroke="black"/>
                <path d="M 88,32 L 128,32" fill="none" stroke="black"/>
                <path d="M 168,32 L 184,32" fill="none" stroke="black"/>
                <path d="M 280,32 L 296,32" fill="none" stroke="black"/>
                <path d="M 336,32 L 384,32" fill="none" stroke="black"/>
                <path d="M 280,48 L 296,48" fill="none" stroke="black"/>
                <path d="M 336,48 L 376,48" fill="none" stroke="black"/>
                <path d="M 104,64 L 128,64" fill="none" stroke="black"/>
                <path d="M 168,64 L 184,64" fill="none" stroke="black"/>
                <path d="M 112,80 L 128,80" fill="none" stroke="black"/>
                <path d="M 168,80 L 184,80" fill="none" stroke="black"/>
                <path d="M 280,80 L 296,80" fill="none" stroke="black"/>
                <path d="M 336,80 L 360,80" fill="none" stroke="black"/>
                <path d="M 80,32 L 104,80" fill="none" stroke="black"/>
                <path d="M 368,80 L 392,32" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="344,80 332,74.4 332,85.6" fill="black" transform="rotate(180,336,80)"/>
                <polygon class="arrowhead" points="344,48 332,42.4 332,53.6" fill="black" transform="rotate(180,336,48)"/>
                <polygon class="arrowhead" points="344,32 332,26.4 332,37.6" fill="black" transform="rotate(180,336,32)"/>
                <polygon class="arrowhead" points="344,16 332,10.4 332,21.6" fill="black" transform="rotate(180,336,16)"/>
                <polygon class="arrowhead" points="288,80 276,74.4 276,85.6" fill="black" transform="rotate(180,280,80)"/>
                <polygon class="arrowhead" points="288,48 276,42.4 276,53.6" fill="black" transform="rotate(180,280,48)"/>
                <polygon class="arrowhead" points="288,32 276,26.4 276,37.6" fill="black" transform="rotate(180,280,32)"/>
                <polygon class="arrowhead" points="288,16 276,10.4 276,21.6" fill="black" transform="rotate(180,280,16)"/>
                <polygon class="arrowhead" points="192,80 180,74.4 180,85.6" fill="black" transform="rotate(0,184,80)"/>
                <polygon class="arrowhead" points="192,64 180,58.4 180,69.6" fill="black" transform="rotate(0,184,64)"/>
                <polygon class="arrowhead" points="192,32 180,26.4 180,37.6" fill="black" transform="rotate(0,184,32)"/>
                <polygon class="arrowhead" points="192,16 180,10.4 180,21.6" fill="black" transform="rotate(0,184,16)"/>
                <polygon class="arrowhead" points="136,80 124,74.4 124,85.6" fill="black" transform="rotate(0,128,80)"/>
                <polygon class="arrowhead" points="136,64 124,58.4 124,69.6" fill="black" transform="rotate(0,128,64)"/>
                <polygon class="arrowhead" points="136,32 124,26.4 124,37.6" fill="black" transform="rotate(0,128,32)"/>
                <polygon class="arrowhead" points="136,16 124,10.4 124,21.6" fill="black" transform="rotate(0,128,16)"/>
                <g class="text">
                  <text x="36" y="20">old_mfst</text>
                  <text x="148" y="20">h1</text>
                  <text x="228" y="20">oldData1</text>
                  <text x="316" y="20">h1</text>
                  <text x="436" y="20">new_mfst</text>
                  <text x="148" y="36">h2</text>
                  <text x="228" y="36">oldData2</text>
                  <text x="316" y="36">h2</text>
                  <text x="228" y="52">replace3</text>
                  <text x="316" y="52">h5</text>
                  <text x="148" y="68">h3</text>
                  <text x="228" y="68">oldData3</text>
                  <text x="148" y="84">h4</text>
                  <text x="228" y="84">oldData4</text>
                  <text x="316" y="84">h4</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art" align="center" name="dedup.txt">
                <![CDATA[
old_mfst ------> h1 --> oldData1  <-- h1 <------- new_mfst
         \-----> h2 --> oldData2  <-- h2 <------/
          \             replace3  <-- h5 <-----/
           \---> h3 --> oldData3              /
            \--> h4 --> oldData4  <-- h4 <---/
                ]]>
              </artwork>
          </artset>
        </figure>
      </section>

      <section anchor="GrowingCollections">
        <name>Growing ICN collections</name>
        <t>A log file, for example, grows over time. Instead of having to re-FLIC the grown file it
          suffices to construct a new manifest with a manifest pointer to the old root manifest plus
          the sequence of data hash pointers for the new data (or additional sub-manifests if
          necessary).</t>

          <t>In the example shown in <xref target="Growing"/>, there is a first root
          manifest, Root 1, that has a name <tt>/logfile/v1</tt> with an RsaOaepCtx
          encryption context #1 and a CCNx content object RSA signature #2.  In this example,
          there is only room for 4 pointers per manifest (for the sake of a simple drawing),
          the manifest Top 1 has two direct pointers and one indirect pointer.  Manifest M2
          has four direct pointers.  Thus, the original log file is the concatendation 
          of D0 ... D5 payloads.</t>
          <t>At a later time, the log files is extended with root manifest Root 2.
          This has its own name, /logfile/v2, with a new encryption content RsaOaepCtx #2.
          It has its own Content Object signature, Signature #2.  Root 2 has one pointer
          to the previous root manifest, Root 1, and one pointer to the new FLIC tree,
          Top 2.  The previous manifest stays encrypted with the RsaOaepCtx #1 key and the
          new manifest is encrypted with the new key in RsaOaepCtx #2.</t>
          <t>If the same encryption key were used, Root 2 could point to
          Top 1 instead of Root 1.</t>

        <figure anchor="Growing"><name>Growing A Collection</name>
          <artset>
            <artwork type="ascii-art" align="center" name="grow-collection.txt">
                <![CDATA[
  ┌───────────────┐              ┌───────────────┐
  │    Root 1     │              │    Root 2     │
  │  /logfile/v1  │              │  /logfile/v2  │
  │ RsaOaepCtx #1 │◀──────────┐  │ RsaOaepCtx #2 │
  │ Signature #1  │           │  │ Signature #2  │
  └───────────────┘           │  └───────────────┘
          │                   └──────────┤
          ▼                              ▼
   ┌────────────┐                 ┌────────────┐
   │   Top 1    │                 │   Top 2    │
   └────────────┘                 └────────────┘
   ┌──────┼───────┐               ┌──────┼───────┐
   ▼      ▼       ▼               ▼      ▼       ▼
┌────┐ ┌────┐  ┌────┐          ┌────┐ ┌────┐  ┌────┐
│ D0 │ │ D1 │  │ M2 │          │ D6 │ │ D7 │  │ D8 │
└────┘ └────┘  └────┘          └────┘ └────┘  └────┘
        ┌──────┬──┴───┬──────┐
        ▼      ▼      ▼      ▼
     ┌────┐ ┌────┐ ┌────┐ ┌────┐
     │ D2 │ │ D3 │ │ D4 │ │ D5 │
     └────┘ └────┘ └────┘ └────┘
                ]]>
              </artwork>
          </artset>
        </figure>

        <t>Note that the grown manifest does not need to specifically continue the previous naming.  The old manifest
        (Root 1) might use one set of name constructors for the old manifests and data, and the new manifest
        (Root 2) might use different name constructors.  If the manifests used HashedSchema, then
        naming is not an issue except for the root manfiests.</t>    
      </section>

      <section anchor="Republishing">
        <name>Re-publishing a FLIC under a new name</name>
        <t>There are several use cases for republishing a collection under a new namespace, or
          having one collection exist under several namespaces:</t>
        <ul spacing="normal">
          <li>It can happen that a publisher's namespace is part of a service provider's prefix.
            When switching provider, the publisher may want to republish the old data under a new
            name.</li>

          <li>A publishes wishes to distribute its content to several repositories and would like a
            result to be delivered from the repository for consumers who have good connectivity to
            that repository. For example, the publisher /alpha wishes to place content at /beta and
            /gamma, but routing only to /alpha would not send a request to either /beta or /gamma.
            The operators of of /beta and /gamma could create a named and signed version of the root
            manifest with appropriate keys (or delegate that to /alpha) so the results are always
            delivered by the corresponding repository without having to change the bulk of the
            manifest tree.</li>
        </ul>
        <t>This can easily be achieved with a single nameless root manifest for the large FLIC plus
          arbitrarily many per-name manifests (which are signed by whomever wants to publish this
          data):</t>

        <figure anchor="Relocating">
          <name>Relocating A Collection</name>
          <artwork align="left" name="" type="" alt=""><![CDATA[

data < - nameless_mfst() <-- h  < - mfst(/com/example/east/the/flic)
                                < - mfst(/com/example/west/old/the/flic)
                                < - mfst(/internet/archive/flic234)
                    ]]></artwork>
        </figure>
        <aside>
          <t>Note that the hash computation (of h) only requires reading the nameless root manifest,
            not the entire FLIC.</t>
        </aside>

        <t>This example points out the problem of HashGroups having their own locator metadata
          elements: A retriever would be urged to follow these hints which are "hardcoded" deep
          inside the FLIC but might have become outdated. We therefore recommend to name FLIC
          manifests only at the highest level (where these names have no locator function). Child
          nodes in a FLIC manifest should not be named as these names serve no purpose except
          retrieving a sub-tree's manifest by name, if would be required. </t>
      </section>
    </section>

    <section anchor="building-graphs">
      <name>Building FLIC Graphs</name>
      <t>This appendix describes one method to build FLIC graphs.   We will use the term "tree" here,
      as all the construction and traversal mechanisms work as for trees, even if there are duplicate
      pointers in the graph that cause a node to have multiple parents.</t>

      <t>
      We constructs a pre-order tree in a
        single pass of the application data, going from the tail to the beginning. This allows us to
        work up the right side of the tree in a single pass, then work down each left branch until
        we exhaust the data. Using the reverse-order traversal, we create the right-most-child
        manifest, then its parent, then the indirect pointers of that parent, then the parent's
        direct pointers,then the parent of the parent (repeating). This process uses recursion, as
        it is the clearest way to show the code. A more optimized approach could do it in a true
        single pass.</t>

      <t>Because we build from the bottom up, we use the term 'level' to be the distance from
        the right-most child up. Level 0 is the bottom-most level of the tree, such as where node 7
        is:</t>
      <artwork align="center" name="" type="" alt=""><![CDATA[
      1
  2      3
4  5    6  7
preorder: 1 2 4 5 3 6 7
reverse:  7 6 3 5 4 2 1
                ]]></artwork>

      <t>The <xref target="ccnpy"/> Python code has more complex algorithms to build a FLIC graph
      is one pass while optimizing the tree structure.  Its default is to minimize the tree height
      while fitting within a given packet MTU.  It will use m-indirect and k-direct pointers for
      interior manifest nodes and n-direct pointers (n=m+k) for leaf manifest noides.</t>

      <t>The Python-like pseudocode build_tree(data, n, k, m) algorithm creates a tree of n data
        objects. The data[] array is an array of Content Objects that hold application payload; the
        application data has already been packetized into n Content Object packets.An interior
        manifest node has k direct pointers and m indirect pointers.</t>
      <sourcecode type='python'><![CDATA[
build_tree(data[0..n-1], n, k, m):
  # data is an array of Content Objects (Data in NDN) with app data.
  # n is the number of data items
  # k is the number of direct pointers per internal node
  # m is the number of indirect pointers per internal node

  segment = namedtuple('Segment', 'head tail')(0, n)
  level = 0

  # This bootstraps the process by creating the right most child
  # manifest. A leaf manifest has no indirect pointers, so k+m
  # are direct pointers
  root = leaf_manifest(data, segment, k + m)

  # Keep building subtrees until we're out of direct pointers
  while not segment.empty():
    level += 1
    root = bottom_up_preorder(data, segment, level, k, m, root)

  return root]]>
      </sourcecode>

      <sourcecode type='python'><![CDATA[
bottom_up_preorder(data, segment, level, k, m, right_most_child=None):
  manifest = None
  if level == 0:
    assert right_most_child is None
    # build a leaf manifest with only direct pointers
    manifest = leaf_manifest(data, segment, k + m)
  else:
    # If the number of remaining direct pointers will fit
    # in a leaf node, make one of those. Otherwise, we need to be
    # an interior node
  if right_most_child is None and segment.length() &lt;= k + m:
    manifest = leaf_manifest(data, segment, k+m)
  else:
    manifest = interior_manifest(data, segment, level,
                                 k, m, right_most_child)
  return manifest]]>
      </sourcecode>

      <sourcecode type='python'><![CDATA[
leaf_manifest(data, segment, count):
  # At most count items, but never go before the head
  start = max(segment.head(), segment.tail() - count)
  manifest = Manifest(data[start:segment.tail])
  segment.tail -= segment.tail() - start
  return manifest]]>
      </sourcecode>

      <sourcecode type='python'><![CDATA[
interior_manifest(data, segment, level, k, m, right_most_child)
  children = []
  if right_most_child is not None:
    children.append(right_most_child)

  interior_indirect(data, segment, level, k, m, children)
  interior_direct(data, segment, level, k, m, children)

  manifest = Manifest(children)
  return manifest, tail]]>
      </sourcecode>

      <sourcecode type='python'><![CDATA[
interior_indirect(data, segment, level, k, m, children):
  # Reserve space at the head of the segment for this node's
  # direct pointers before descending to children.  We want
  # the top of the tree packed.
  reserve_count = min(k, segment.tail - segment.head)
  segment.head += reserve_count

  while len(children) &lt; m and not segment.head == segment.tail:
    child = bottom_up_preorder(data, segment, level - 1, k, m)
    # prepend
    children.insert(0, child)

    # Pull back our reservation and put those pointers in
    # our direct children
    segment.head -= reserve_count]]>
      </sourcecode>

      <sourcecode type='python'><![CDATA[
interior_direct(data, segment, level, k, m, children):
  while len(children) &lt; k+m and not segment.head == segment.tail:
    pointer = data[segment.tail() - 1]
    children.insert(0, pointer)
    segment.tail -= 1]]>
      </sourcecode>
    </section>
  </back>
</rfc>