Subject: Re: [COSE] Questions about signatures and countersignatures

From: Jonathan Hammell <[email-masked]>
Date: Tue, 12 Apr 2022 13:33:28 -0400

Hi Christian,
A while ago, I produced some of the countersignature examples for the I-D.
I've been reviewing my code in light of the questions you have raised and
some discussion that I had with Russ, and I believe that there is ambiguity
remaining in the I-D that is leading to these different interpretations.

I would love to work with you to do some interoperability testing and
ensure the examples are correct before the I-D is published.

Jonathan

On Fri, Mar 25, 2022 at 4:25 PM Christian Flach <cmfcmf=
[email-masked]> wrote:

> Got it, thanks!
>
> On Fri, Mar 25, 2022 at 9:03 PM Russ Housley <[email-masked]> wrote:
>
>> No, I'm not suggesting a change.  I'm trying to describe the reason one
>> performs a countersignature.
>>
>> Russ
>>
>> On Mar 25, 2022, at 10:20 AM, Christian Flach <
>> cmfcmf=[email-masked]> wrote:
>>
>> Hi Russ,
>>
>> Thanks a lot for your answers!
>>
>> Regarding my second question, you write 'However, a countersignature is a
>> signature over a previous signature, another approach would be to put the
>> signature_value bstr in the payload'. You are suggesting a change to
>> draft-ietf-cose-countersign here, correct? Currently, if I read the draft
>> correctly, the COSE_Sign1.signature field is present in
>> Countersign_structure.other_fields and Countersign_structure.payload
>> contains the message payload.
>>
>> Christian
>>
>> On Mon, Mar 14, 2022 at 10:15 PM Russ Housley <[email-masked]>
>> wrote:
>>
>>> Christian:
>>>
>>> I have been very slow in responding.  Apologies.  I hope this late
>>> response is helpful.
>>>
>>> 1.  I think that RFC 8152, Section 4.3 is the place to look.  I think
>>> the detached payload is placed in the 'payload' field for signature
>>> calculation.
>>>
>>> 2.  Countersignatures are signatures over another previously calculated
>>> signature. That said, we probably should be more clear in the
>>> draft-ietf-cose-countersign about what goes in the payload field. Checking
>>> with one implementer, that person also used COSE_Sign1.payload of nil in
>>> when the payload is detached.  However, a countersignature is a signature
>>> over a previous signature, another approach would be to put the
>>> signature_value bstr in the payload.  I am thinking that the second
>>> approach make the most sense, and it is parallel to this part of the
>>> specification:
>>>
>>> "When done on a COSE_Mac or COSE_Mac0, the payload is included as well
>>> as the MAC value".
>>>
>>> 3.  This seems right to me.  In RFC 5652, I added text to be very clear
>>> what a "signature value" means.  It does not include the tag and length.
>>> Is there something that we need to in draft-ietf-cose-countersign to
>>> provide similar clarity?
>>>
>>> 4. Section 3 of draft-ietf-cose-countersign says:
>>>
>>>  "When done on
>>> a COSE_Sign, this is the same as applying a second signature to the
>>> payload and adding a parallel signature as a new COSE_Signature is
>>> the preferred method."
>>>
>>> I think you are pointing out that COSE_Sign does not appear in the list
>>> of COSE structures in Section 2, where it says:
>>>
>>> "The countersignature header
>>>       parameter can occur as an unprotected attribute in any of the
>>>       following structures: COSE_Sign1, COSE_Signature, COSE_Encrypt,
>>>       COSE_recipient, COSE_Encrypt0, COSE_Mac, and COSE_Mac0."
>>>
>>> I think we should add COSE_Sign in Section 2.
>>>
>>> 5.  A countersignture covers one previously calculated signature.  It
>>> does not match the semantics in the question.  One approach would be to
>>> define an application that signs another COSE document that already has
>>> multiple signatures.  A second approach would be to use countersignature
>>> for each of the previously calculated signatures.
>>>
>>> The alternative would be for a countersignature to cover the array of
>>> signatures.  I have not thought about that, and I wonder what about the
>>> semantics of doing so.
>>>
>>> 6.  I do not know why this document is not an RFC yet.  The approval
>>> process is going very slowly.
>>>
>>> Russ
>>>
>>>
>>> On Feb 11, 2022, at 8:58 AM, Christian Flach <
>>> cmfcmf=[email-masked]> wrote:
>>>
>>> Hi everyone,
>>>
>>> We are looking into using COSE for signing some CBOR data. After reading
>>> the latest versions of the drafts, we had a few questions and were
>>> wondering whether you could provide us some clarification:
>>>
>>>
>>>    1. We have a COSE_Sign1 / COSE_Sign structure with a “payload” field
>>>    set to nil, because we want the payload to not be part of the structure.
>>>    I’m a bit confused about how to correctly construct the Sig_structure,
>>>    specifically the “external_aad” and “payload” fields. The description of
>>>    Sig_structure.external_aad says “The externally supplied data from the
>>>    application encoded in a bstr type”, and the description of
>>>    Sig_structure.payload says “The payload to be signed encoded in a bstr
>>>    type. The payload is placed here independent of how it is transported.”.
>>>    Both descriptions sound like they would match our detached payload.
>>>    The Java COSE implementation seems to place the detached payload in
>>>    `payload` and an empty byte string in `external_aad`. Is this the correct
>>>    way to build the Sig_structure for a COSE_Sign1 / COSE_Sign with a detached
>>>    payload?
>>>
>>>
>>> Section 4.3, which, I think, is about “external_aad”, begins with “One
>>> of the features offered in the COSE document is the ability for
>>> applications to provide additional data to be authenticated, but that is
>>> not carried as part of the COSE object.“. I would appreciate a clearer
>>> distinction between “detached payloads” and “externally supplied data”,
>>> since both appear to achieve similar goals, namely the data to not be part
>>> of the COSE structure. When would an application use one or the other?
>>>
>>> The following questions are all about counter signatures v2.
>>>
>>>
>>>    1. I’d like to double check whether I understood the construction of
>>>    the Countersign_structure correctly: If I want to countersign a COSE_Sign1
>>>    structure with a detached payload (COSE_Sign1.payload = nil), is the
>>>    following correct?
>>>
>>>
>>> Countersign_structure = [
>>>   context : "CounterSignatureV2", ; Identifier
>>>   body_protected : empty_or_serialized_map, ; Protected headers of
>>> COSE_Sign1
>>>   sign_protected : empty_or_serialized_map, ; Protected headers of
>>> COSE_Countersignature
>>>   external_aad : bstr, ; Empty
>>>   payload : bstr, ; The detached payload
>>>   other_fields : [ bstr ] ; An array with a single element: the
>>> signature field of COSE_Sign1
>>> ]
>>>
>>>
>>>    1. Similarly, if I wanted to countersign a COSE_Signature that is
>>>    part of a COSE_Sign structure with a detached payload (COSE_Sign.payload =
>>>    nil), is the following correct?
>>>
>>>
>>> Countersign_structure = [
>>>   context : "CounterSignature", ; Identifier
>>>   body_protected : empty_or_serialized_map, ; Protected headers of
>>> COSE_Signature
>>>   sign_protected : empty_or_serialized_map, ; Protected headers of
>>> COSE_Countersignature
>>>   external_aad : bstr, ; Empty
>>>   payload : bstr, ; The signature field of COSE_Signature
>>> ]
>>>
>>> If this is correct, is it intentional that the detached payload IS part
>>> of the Countersign_structure when countersigning COSE_Sign1, but not when
>>> countersigning a COSE_Signature that is part of the COSE_Sign signatures
>>> array?
>>>
>>>
>>>    1. Section 3 “Version 2 Countersignatures” says “This document
>>>    extends the context of a countersignature to allow it to be applied to all
>>>    of the security structures defined”. This sounds like it would be allowed
>>>    to countersign COSE_Sign (even if it doesn’t make much sense, as is also
>>>    described in section 3). However, section 2 “Countersignature Header
>>>    Parameters” says that the countersignature header can only occur on a
>>>    selected subset of COSE structures, and specifically does not list
>>>    COSE_Sign as a possible structure to countersign.
>>>
>>>
>>>
>>>    1. There does not currently seem to be a way to correctly
>>>    countersign a COSE_Sign structure with a single countersignature. Let’s
>>>    take the notary analogy: Two people sign a contract, and the notary places
>>>    their (single) countersignature on the same document, confirming that the
>>>    two persons signed the contract. The same would not be possible with COSE,
>>>    I think. With COSE, the notary would need to countersign both signatures
>>>    separately, i.e. add a countersignature header to both COSE_Signature
>>>    entries of the the COSE_Sign.signatures array. Is my understanding correct?
>>>    2. Has there been progress on registering temporary code points in
>>>    the COSE Header parameters table for counter signatures v2? I found an
>>>    email from 2020 about this topic (
>>>    https://mailarchive.ietf.org/arch/msg/cose/88jwAsA4Rh61oP3XR9KGtasNlwo/),
>>>    which seems to have been in favor of registering these, but from what I can
>>>    tell, they haven’t been registered yet.
>>>
>>>
>>> Christian
>>>
>>> --
>>>
>>> Christian Flach (he/him)
>>> Software Engineer
>>> [email-masked]
>>>
>>> Google Germany GmbH
>>> Erika-Mann-Straße 33
>>> 80636 München
>>>
>>> Geschäftsführer: Paul Manicle, Liana Sebastian
>>> Registergericht und -nummer: Hamburg, HRB 86891
>>> Sitz der Gesellschaft: Hamburg
>>>
>>> Diese E-Mail ist vertraulich. Falls Sie diese fälschlicherweise erhalten
>>> haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter,
>>> löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen,
>>> dass die E-Mail an die falsche Person gesendet wurde.
>>>
>>>
>>> This e-mail is confidential. If you received this communication by
>>> mistake, please don't forward it to anyone else, please erase all copies
>>> and attachments, and please let me know that it has gone to the wrong
>>> person.
>>> _______________________________________________
>>> COSE mailing list
>>> [email-masked]
>>> https://www.ietf.org/mailman/listinfo/cose
>>>
>>>
>>>
>>
>> --
>>
>> Christian Flach (he/him)
>> Software Engineer
>> [email-masked]
>>
>> Google Germany GmbH
>> Erika-Mann-Straße 33
>> 80636 München
>>
>> Geschäftsführer: Paul Manicle, Liana Sebastian
>> Registergericht und -nummer: Hamburg, HRB 86891
>> Sitz der Gesellschaft: Hamburg
>>
>> Diese E-Mail ist vertraulich. Falls Sie diese fälschlicherweise erhalten
>> haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter,
>> löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen,
>> dass die E-Mail an die falsche Person gesendet wurde.
>>
>>
>> This e-mail is confidential. If you received this communication by
>> mistake, please don't forward it to anyone else, please erase all copies
>> and attachments, and please let me know that it has gone to the wrong
>> person.
>> _______________________________________________
>> COSE mailing list
>> [email-masked]
>> https://www.ietf.org/mailman/listinfo/cose
>>
>>
>>
>
> --
>
> Christian Flach (he/him)
> Software Engineer
> [email-masked]
>
> Google Germany GmbH
>
> Erika-Mann-Straße 33
>
> 80636 München
>
> Geschäftsführer: Paul Manicle, Liana Sebastian
>
> Registergericht und -nummer: Hamburg, HRB 86891
>
> Sitz der Gesellschaft: Hamburg
>
> Diese E-Mail ist vertraulich. Falls Sie diese fälschlicherweise erhalten
> haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter,
> löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen,
> dass die E-Mail an die falsche Person gesendet wurde.
>
>
>
> This e-mail is confidential. If you received this communication by
> mistake, please don't forward it to anyone else, please erase all copies
> and attachments, and please let me know that it has gone to the wrong
> person.
> _______________________________________________
> COSE mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/cose
>

---

From: Jonathan Hammell <[email-masked]>
Date: Tue, 12 Apr 2022 15:38:03 -0400

Hi Russ,
I agree with you that a countersignature on COSE_Sign1 must have the
signature_value of the underlying message in the ToBeSigned input for the
countersignature; however, my interpretation of the current text for the
payload of the Countersign_structure is aligned with Christian's (for
COSE_Sign1).

COSE's countersignature was generalized to apply to all COSE structures, so
the payload may not always be a signature_value as one might intuitively
expect.

The design discussions for CounterSignatureV2 is in this thread:
https://mailarchive.ietf.org/arch/msg/cose/6-vyoetZboIdrwwEYoYlj9QY_3Q/
My recollection was that the group decided to proceed with the third
option, that is including every bstr value in the structure.  I believe
this is consistent with step 6 in Section 3.3.

As Jim discussed in the above thread, countersignature on COSE_Sign1 was an
example where the original method defined in RFC 8152 failed because there
was no way to capture the signature_value bstr since it was the third bstr
in the COSE message structure.

I disagree with the interpretation that I believe you and Christian have
for applying a countersignature to the COSE_Sign structure.  You may find
it surprising, but that countersignature will not actually sign the
signature_value of any of the signers.  As written in Section 3 of the I-D,
"When done on a COSE_Sign, this is the same as applying a second signature
to the payload and adding a parallel signature as a new COSE_Signature is
the preferred method."  I have confirmed that the message payload is
included and not the signature_values nor signature array by validating the
countersignature in the example from C.1.3 of RFC 8152.  In order to do the
traditional countersignature logic of signing a signature value, one would
apply the countersignature on the specific COSE_Signature structure in the
signatures array of COSE_Sign.

Jonathan

On Fri, Mar 25, 2022 at 4:03 PM Russ Housley <[email-masked]> wrote:

>> 1.  I think that RFC 8152, Section 4.3 is the place to look.  I think the
>> detached payload is placed in the 'payload' field for signature calculation.
>>
>> "When done on a COSE_Mac or COSE_Mac0, the payload is included as well as
>> the MAC value".
>>
>> Section 4.3, which, I think, is about “external_aad”, begins with “One of
>> the features offered in the COSE document is the ability for applications
>> to provide additional data to be authenticated, but that is not carried as
>> part of the COSE object.“. I would appreciate a clearer distinction between
>> “detached payloads” and “externally supplied data”, since both appear to
>> achieve similar goals, namely the data to not be part of the COSE
>> structure. When would an application use one or the other?
>>
>>    1. There does not currently seem to be a way to correctly countersign
>>    a COSE_Sign structure with a single countersignature. Let’s take the notary
>>    analogy: Two people sign a contract, and the notary places their (single)
>>    countersignature on the same document, confirming that the two persons
>>    signed the contract. The same would not be possible with COSE, I think.
>>    With COSE, the notary would need to countersign both signatures separately,
>>    i.e. add a countersignature header to both COSE_Signature entries of the
>>    the COSE_Sign.signatures array. Is my understanding correct?

---

From: Russ Housley <[email-masked]>
Date: Wed, 13 Apr 2022 10:26:47 -0400

Jonathan:

> I agree with you that a countersignature on COSE_Sign1 must have the signature_value of the underlying message in the ToBeSigned input for the countersignature; however, my interpretation of the current text for the payload of the Countersign_structure is aligned with Christian's (for COSE_Sign1).  
> 
> COSE's countersignature was generalized to apply to all COSE structures, so the payload may not always be a signature_value as one might intuitively expect.  
> 
> The design discussions for CounterSignatureV2 is in this thread: https://mailarchive.ietf.org/arch/msg/cose/6-vyoetZboIdrwwEYoYlj9QY_3Q/ <https://mailarchive.ietf.org/arch/msg/cose/6-vyoetZboIdrwwEYoYlj9QY_3Q/> 
> My recollection was that the group decided to proceed with the third option, that is including every bstr value in the structure.  I believe this is consistent with step 6 in Section 3.3.  

That is consistent with my memory too.

> As Jim discussed in the above thread, countersignature on COSE_Sign1 was an example where the original method defined in RFC 8152 failed because there was no way to capture the signature_value bstr since it was the third bstr in the COSE message structure.

Yes, Jim was seeking a general solution.

> I disagree with the interpretation that I believe you and Christian have for applying a countersignature to the COSE_Sign structure.  You may find it surprising, but that countersignature will not actually sign the signature_value of any of the signers.  As written in Section 3 of the I-D, "When done on a COSE_Sign, this is the same as applying a second signature to the payload and adding a parallel signature as a new COSE_Signature is the preferred method."  I have confirmed that the message payload is included and not the signature_values nor signature array by validating the countersignature in the example from C.1.3 of RFC 8152.  In order to do the traditional countersignature logic of signing a signature value, one would apply the countersignature on the specific COSE_Signature structure in the signatures array of COSE_Sign.

Do you think anything needs to change in the document?

Russ

---

From: Jonathan Hammell <[email-masked]>
Date: Sat, 16 Apr 2022 10:35:16 -0400

Hi Russ,

> Do you think anything needs to change in the document?

After re-reading the description in Section 3, I think the semantics
are clear for an implementer.  The warning needs to be heeded that one
must consider the security properties when applying it.  If one is
using a software library for COSE, I suppose that the resulting
security properties may not be obvious to the user, particularly in
the case of COSE_Sign.  That said, any text we add in the RFC is
likely not to be read by a software library user, so it is the
responsibility of the library to provide a proper API to prevent
misuse.

The case of detached signatures might be a little unclear, as
Christian originally raised.  Section 4.1 of RFC 8152 says that "If
the payload is transported separately ("detached content"), then a nil
CBOR object is placed in [the payload]..."  A nil value is a different
CBOR type than an empty bstr (Section 1.3 of RFC 8152).  However, Step
5 of Section 3.3 says that "the payload is placed [in the payload of
Countersign_structure] independent of how it is transported."  I
believe this implies that the detached payload is indeed included here
for the purpose of countersigning, similar to externally supplied
data.  But would an implementer then misinterpret Step 6 given that
the payload of the original structure was nil and not a bstr, and thus
not include the signature bstr in the other_fields?

The examples in the I-D certainly need to be updated.  The first
example was taken from RFC 8152.  It is odd given that it is a
countersignature on a COSE_Sign, which is discouraged in Section 3 for
the reasons discussed before, and it uses the same key to countersign
as was used in the original signature.  That is, it has two ECDSA
signatures with the same key.

The early allocations that I requested for the countersignature header
parameters were never actioned, but the values chosen still seem to be
unassigned by IANA.

However, I will need to update the examples that I generated for
Appendix A since in a recent review of my code I believe I found a
bug.  It would be nice to do an interoperability test with another
implementer, so please let me know if anyone wishes to test with me.

Best regards,
Jonathan