Subject: Re: [Suit] Introducing draft-moran-suit-manifest-04

From: Brendan Moran <[email-masked]>
Date: Thu, 13 Jun 2019 15:42:25 +0000

Hi Øyvind,
I’ve done a run through your comments. Thanks for your review.

Thanks,
Brendan

On 11 Apr 2019, at 16:02, Rønningstad, Øyvind <[email-masked]<mailto:[email-masked]>> wrote:

I did a full pass through the document today, and wrote down (quite a few) comments, see below. I think this document is very exciting!

- Øyvind

The digest-algorithm-ids list is missing the following SHA-2 family functions:
- SHA224
- SHA512/224
- SHA512/256
Also, the functions that are truncated to 128 and fewer bits will not be secure against brute-force attacks, so I question their inclusion here.

The algorithm identifiers are borrowed directly from the Naming Things with Hashes RFC (RFC 6920). https://www.iana.org/assignments/named-information/named-information.xhtml. If possible, I would like to avoid constructing another IANA registry for digest algorithm identifiers. I confess, I do find it a bit strange that RFC 6920 has IDs for SHA3-224 and SHA256-128, but not for SHA224. If we need to construct a new registry, so be it, however I would rather not. Perhaps there is another digest algorithm registry that is appropriate?

The requirement that all manifests must have a sequence number higher than their dependencies might be inconvenient when dependencies are validated by version ranges, since a dependency might be updated to something that is created after the root manifest, but still fulfills the check. Comparing sequence number dependency<->dependent might be superfluous, since the dependency is already referenced quite specifically in other ways. Alternatively, the requirement can be valid only up to and including installation.
Also, the text should probably mention that if a manifest is replaced by an update, the new manifest must have a higher sequence number.

Currently, the design calls for manifests to be referenced by digest. If that is the case, then a manifest’s digest (and, therefore, sequence number) must be known at time of creation. For fuzzy dependencies, such as those based on version matching, the direct dependency mechanism clearly doesn’t work. This was originally modelled as mutually independent components (those that are not updated together). Does this need to be made more explicit, or does it require a new or modified dependency mechanism?

What directives/conditions can apply to components in suit-dependency-components? I don't quite understand the purpose of the suit-dependency-components list.

The purpose of suit-dependency-components is to enumerate the components that are described by the dependencies. This may or may not be necessary. As I have described it in draft-moran-suit-manifest-04, it is a list of all components that are affected by all dependencies. This is useful for three reasons: 1) it allows the device to evaluate whether or not it implements the targeted components prior to downloading the whole manifest tree, 2) for a single-pass processor, it allows the device to verify that it has enough storage to store the variables that will be used by each component. For a multi-pass processor, it allows the device to iterate through affected components, handling each one in turn.

There are tradeoffs here. If many components are listed in a deeply nested tree, it will make the top-level manifest enormous. This is a problem that is not well-addressed by this model. It was chosen for small numbers of components in a small tree on small devices. We may need to consider whether it will continue to be the correct choice for larger systems. Perhaps we should consider the option of making the field optional and specifically for multi-pass processors.

I read it many times now, but I don't really understand the last paragraph of "8.4.  SUIT_Component". Can you elaborate on the assumptions? How are the values dependent on installation offset? Who updates the parameters to match what? What does "defining a component" mean?

I think this probably needs some rewording. The idea was that each component is only permitted to exist in a single SUIT_Component, whereas it could exist in zero or more SUIT_Component_Reference elements. The unique feature would be that only a manifest that defines a SUIT_Component for a particular component ID would be allowed to set the digest for that component ID.

However, I’m not certain this is necessary. Where ACLs are present, this should be implemented as an ACL for the digest parameter. Where ACLs are not present, this should be implemented by setting the digest with Override Parameters in the same manifest as the Verify command. If we make the assumption that manifests deeper in the tree are typically more privileged, then it should be adequate in either a single-signer environment or a an ACL-environment.

I might have missed something, but can you elaborate on how scoping of parameters work, specifically when are they unset? For example Encryption Info, does it become unset after being used once? Which parameters are inherited into a Run_Sequence or Process_Dependency? Does a Set_Component_Index/Set_Manifest_Index effectively unset all parameters that have scope "Component"/"Dependency". How does scoping affect parallell processing (how to keep track of the value of a parameter for a given Directive/Conditition if they are executed out of order)?

Parameters are scoped to a specific component ID. Parameter lifetime isn’t well-defined in the draft. It should be. This is an area where there is some work left to do.

The fundamental assumption is that two successive commands should be presented with the same set of parameters (exceptions: set_parameters, override_parameters). However, there are use-cases for Run_Sequence that break this assumption: conditional set. However, where out-of-order/parallel processing is used (Strict order = false) it can be very beneficial to be able to modify a local copy of parameters, rather than creating synchronisation points for setting those parameters, so there are two use-cases for Run_Sequence with different expectations.

A dependency manifest must not change the value of a parameter that is later consumed by the dependent manifest or another dependency. This could be accomplished in two ways: either the environment could be duplicated for the dependency or tooling could be used to ensure non-interference when authoring the dependent manifest, including replacing values that have been overridden.

This seems to indicate the following set of rules:

Parameters:

  1.  Are scoped to a specific component ID
  2.  Are initialised by:
     *   The dependent manifest (ignored for the root manifest)
     *   The common section of the current manifest
  3.  Live for the duration of the current section of the root manifest or the current section of the current manifest and its dependencies (see below)
  4.  Are guaranteed to be unmodified by:
     *   Run_Sequence when Strict_Order = false
     *   Process_Dependency

The guarantee in 4 can be done in one of two ways: either a) the parameters are duplicated prior to the call by the device or, b) the tooling that constructs the manifest parses the manifest tree to ensure that parameters are not overridden and, if they are, the correct values are restored after any invocation that could override a parameter. A) is more suitable for larger systems and b) is more suitable for more constrained systems, but we should have a consistent view of the behaviour of the interpreter. This seems to indicate a capability and a flag that is required. This inconsistency in behaviour between large scale systems and constrained systems is not something we want. I think a better solution is needed, but it’s not clear what would be simpler and still behave as expected.

Set_Component_Index and Set_Manifest_Index effectively just moves a pointer to the current working set between several options. Parallel processing is mostly unaffected. Changing a parameter effectively creates a synchronisation point. If you want to do that and maintain parallelism, the solution is to wrap each parallel process in a Run_Sequence.

SUIT_Unpack_Algorithm_Delta should be split into individual IDs for algorithms like SUIT_Unpack_Algorithm_VCDIFF.

That seems reasonable. The other option would be to break it down into hierarchical IDs, but I don’t think there’s much benefit to that approach.

I think there's a quirk with the versions where comparisons can be subverted. If you have a dependency on version 1.x of something, it's hard (impossible in the general sense) to express those bounds with the greater/lesser comparisons. This is because there is no well-defined highest or lowest version with a given prefix such as "1." (unless the version list has bounded length).  If you have a bound on the length of the version list, you could express the upper bound e.g. as "Lesser or equal than 1.INTMAX.INTMAX..." etc. which isn't very pretty. Can we find some better way? I'm assuming 1.1 is equivalent (equal) to 1.1.0 etc.

I’m not sure I understand the problem. The test is: >=1,<2. In this instance, any version that has a prefix >=1 will pass that comparison, and any version that has a prefix <2 will pass that part of the comparison. The number of elements in the list to process is assumed to be defined by the test.

If SUIT_Directive_Set_Component_Index is set to ALL components, is the order in which it applies to the components well-defined? Same question for SUIT_Directive_Set_Manifest_Index.

The order is defined to be the order in which they are listed in the manifest.

Can you give an example of providing an argument to SUIT_Directive_Fetch?

Certainly. This is primarily intended describe information that the device will use, but is not sent to a remote, making a URI inappropriate for containing it. Several examples would be:

  1.  Broadcast interval
  2.  Key Identifier to use for TLS client authentication
  3.  Transport configuration to use during the download (e.g. MTU)

The CDDL for Condition, Directive and Parameters should have the name as part of the CDDL (i.e. as a label/type, not a comment) to make it more amenable to machine parsing.

Noted. I’ll have a look at that as I prepare draft-moran-suit-manifest-05

*The rest is nitpicking*

The nitpicks make sense. I’ll do my best to incorporate them.

The SUIT_Manifest CDDL references Digest instead of SUIT_Digest.

Should suit-install be MANDATORY if suit-payload-fetch is present?

I suggest being more specific about suit-validate. Something to the effect of: "suit-validate is a SUIT_Command_Sequence to execute in order to validate that the result of applying the update (i.e. the state of the device after suit-install) is correct."

When forwarding a dependency to a component that is capable of parsing its own manifests, the dependency manifest might not be SUIT-formatted, so it should not need to be interpreted. This could be elaborated on in the text.

This sentence should probably be fixed (typo etc.): "It consists of three elemnts: the component identifier that represents a component that will be affected by this manifest."

Can a SUIT_Component_Reference refer to a component in a dependency of a dependency?

For readability, I suggest placing the "name" column (of the manifest parameters table) further to the left.

Can you elaborate on the "Skip" flag for parameters? Even just mentioning that it is TBD.

This could be more specific: "This index is a numeric index into the component ID tables defined at the beginning of the document."

SUIT_Directive_Set_Parameter_State_Append is not mentioned in the table.

Should "dependent-components" be "dependency-components" instead?

For the sake of completeness: In "Access Control Lists" I envision another situation, where ACL is implemented as a function that e.g. takes the Component ID and returns the identities that can manipulate it. This is for when Component IDs can alias each other, or the component ID contains a flash address, so it doesn't make sense to store every conceivable component ID in a list.

The names in the example in "Creating conditional sequences" don't look right, are they outdated?

An example with dependencies would of course be useful.

-----Original Message-----
From: Suit <[email-masked]<mailto:[email-masked]>> On Behalf Of Brendan Moran
Sent: Tuesday, March 12, 2019 11:35
To: [email-masked]<mailto:[email-masked]>
Subject: [Suit] Introducing draft-moran-suit-manifest-04

draft-moran-suit-manifest-04 has now been published.

https://tools.ietf.org/html/draft-moran-suit-manifest-04

This draft is the result of combining the information model in draft-moran-suit-behavioural-manifests-00 (the 01 version fixes example formatting only) with that in draft-ietf-suit-information-model, then serialising the result in CBOR. This is a significant departure from previous drafts. It attempts to preserve flexibility, fully define the behaviour of recipient, simplify the manifest structure, reduce code-size of the recipient, and reduce the size of the manifest. This ambitious set of goals required a significant change in approach as compared to draft-moran-suit-manifest-03 and before. In order to outline the approach clearly, we have separately published draft-moran-suit-behavioural-manifests-00. draft-moran-suit-manifest-04 focuses more on the serialisation of the manifest.

I look forward to discussing this draft in more detail.

Best Regards,
Brendan
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

_______________________________________________
Suit mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/suit

IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

---

From: Brendan Moran <[email-masked]>
Date: Mon, 17 Jun 2019 08:37:48 +0000

> On 2 May 2019, at 22:50, David Brown <[email-masked]> wrote:
>
> On Thu, Apr 11, 2019 at 01:17:35PM -0400, Michael Richardson wrote:
>
>> Very nice animation.
>> It really seems like the swap operation does by MCUboot ought to be below the
>> level of the manifest instructions.
>>
>>   > One difficulty I see following steps in the manifest is that the code
>>   > currently maintains state out-of-band from the manifest.  The current
>>   > state is:
>>
>> That suggests to me that maybe we need to make the state explicit in the
>> information model associated with the manifest.
>
> Although, I think if the swap operation itself is "below" the scope of
> the manifest, perhaps the state it keeps is also below that.

I agree. There should be a swap operation and it should be responsible for its own state.

Brendan

---

From: Rønningstad, Øyvind <[email-masked]>
Date: Fri, 21 Jun 2019 08:31:58 +0000

Hi Brendan, thanks for the in-depth answers. I have some more questions/comments below.

Thanks,
Øyvind

From: Brendan Moran <[email-masked]>
Sent: Thursday, June 13, 2019 17:42
To: Rønningstad, Øyvind <[email-masked]>
Cc: [email-masked]; Kvamtrø, Frank Audun <[email-masked]>
Subject: Re: Introducing draft-moran-suit-manifest-04

Why do we need an IANA registry? I imagine two possible reasons, both of which are invalid in my opinion (for this case):

  1.  As a source of algorithm identifiers (numbers). Since we create our own type (SUIT_Digest), there’s nothing to retain compatibility with. Doesn’t this make the numbers arbitrary?
  2.  So the list will be curated without the need to make new RFCs. This would indeed be good to have. The thing is that RFC 6920 contains algorithms that should NEVER EVER be used by SUIT implementations, so they should not be part of SUIT_Digest. This means we need to curate the curated list, which makes using the Named Information registry no better than not using a registry. This is obvious when looking at the goals of the registry (naming things), compared to our goal (security): They don’t align at all.
If you want to take IDs from the registry, that’s no problem, but do remove the algorithms known to be insecure. It’s not worth the chance that even a single user uses them.

One solution is to amend the Named Information registry so it also covers security use cases. I think this was mentioned by David Waltermire.
Another solution is to follow TLS’s recommendations, or to copy their process of specifying exactly what combinations of algorithms are supported in each version.
If we create or amend a registry ourselves, we should probably attempt to cooperate with other WGs, since such a registry would be useful beyond just SUIT.

I think I misunderstood the purpose of the version condition. So to clarify: Version conditions are checked only against existing components? That makes sense for upgrade manifests, but how do you envision it for when SUIT is used for boot manifests?

I haven’t thought deeply about it, but making it optional makes sense to me.

Ok, so when comparing versions with different lengths, the longest is to be truncated? That does indeed solve the problem nicely. That rule should be explicit in the document (I assumed incorrectly that the shortest was to be padded with 0s). To make sure I understand: Could I actually achieve my example with a single condition: ==1?