On Thursday, 26 October 2017 06:03:41 PDT Carsten Bormann wrote:
> On Oct 26, 2017, at 03:40, Thiago Macieira <[email protected]> 
wrote:
> > Also note that COSE requires that the protected maps also conform to the
> > canonical format (RFC 7049 section 3.9), but our map doesn't.
> 
> Actually, COSE doesn’t require that.

You're right, that's not the protected map exactly that requires it, but 
effectively by construction you'd do that.

> The fact that we didn’t want to require canonicalization of the map is the
> exact reason we use cbor-in-cbor: The sender can encode in any way you
> want, but the resulting exact byte string becomes part of the signed
> message.

Then you forgot to remove the wording for that.

RFC 8159 section 14 "CBOR Encoder Restrictions" says 

   o  The restriction applies to the encoding of the Sig_structure, the
      Enc_structure, and the MAC_structure.

   o  The rules for "Canonical CBOR" (Section 3.9 of RFC 7049) MUST be
      used in these locations. [...]

Because the same protected map appears in both these three structures and in 
the actual payload, any implementation that is attempting to save memory will 
just copy from one point to the other. So, as I said, effectively this makes 
the pmap canonical.

In any case, this CBOR-in-CBOR makes it extremely hard to make an 
implementation that streams out the content, without memory allocation and 
with as much zero-copy as it can. To do it, you need to either:

1) save the pmap to a scratch buffer, then memcpy it twice

2) backtrack in the streaming: that is, first encode a Byte String information 
for a MUCH bigger entity since you don't know the size, then encode the 
protected map, calculate the size of that map, backtrack to where you encoded 
the long byte string and patch it with the actual size. And then memcpy it to 
the {Enc,Sig,MAC}_Structure, since it needs to be canonical.

3) [the solution I chose] break down the {Enc,Sig,MAC}_Structures so that 
instead of sending a linear buffer, the encoding/signing/verifying function 
gets a struct iovec array. That way, we can create the structures in canonical 
form without memcpy. Then we encode the pmap only once as a Byte String to the 
payload.

In my mind, that choice is a design flaw in COSE.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

_______________________________________________
iotivity-dev mailing list
[email protected]
https://lists.iotivity.org/mailman/listinfo/iotivity-dev

Reply via email to