ietf-smime
[Top] [All Lists]

Re: [smime] Problems with versions

2022-05-02 08:12:20
Peter:

The version should be helping the recipient.  If the sender follows the MUST 
statements, the recipient should not find themselves in a situation where the 
cannot parse past the version number.  That is, an unrecognized version can 
save the recipient for getting a parsing error.

Russ


On May 1, 2022, at 11:46 AM, Peter Gutmann 
<pgut001(_at_)cs(_dot_)auckland(_dot_)ac(_dot_)nz> wrote:

This issue has just come up in the OpenPGP WG but it affects CMS as well: What
happens if you find data structures with an unexpected version number, e.g. in
SignedData or SignerInfos?  Currently the spec says, for SignedData:

 IF ((certificates is present) AND
    (any certificates with a type of other are present)) OR
    ((crls is present) AND
    (any crls with a type of other are present))
   THEN version MUST be 5
   ELSE
     IF (certificates is present) AND
        (any version 2 attribute certificates are present)
     THEN version MUST be 4
     ELSE
       IF ((certificates is present) AND
          (any version 1 attribute certificates are present)) OR
          (any SignerInfo structures are version 3) OR
          (encapContentInfo eContentType is other than id-data)
       THEN version MUST be 3
       ELSE version MUST be 1

and for SignerInfos:

     version is the syntax version number.  If the SignerIdentifier is
     the CHOICE issuerAndSerialNumber, then the version MUST be 1.  If
     the SignerIdentifier is subjectKeyIdentifier, then the version
     MUST be 3.

For SignerInfos this explicitly excludes any future updates because it says
the only permitted values are 1 or 3, and for SignedData 1, 3, 4, or 5,
although I can't imagine anything ever producing a signature with a version or
4 or 5 and have never seen one used.  Given that 5 refers to undefined
certificate types I can't even see *how* it could be used, and I've never seen
attribute certs used with CMS so I assume 4 is never used either.

For the RecipientInfos the versions are similarly hardcoded, although it's a
bit more complex there, I'll skip that bit and let people refer to the spec.

The problem this causes, apart from excluding ever updating the format, is
that there are situations when you need to process versions other than the
ones allowed in the spec.  Consider a message in the following format:

 SignedData {
   version = 7,
   digestAlgorithms,
   content,
   signerInfos {
     signerInfo version = 7,
     signerInfo version = 6,
     signerInfo version = 1
     }
   }

So there's a signature in there that can be processed by something that
understands version 1, but the SignedData has a version that says it can't.
In fact the SignedData spec sets a dangerous precedent:

 IF ((certificates is present) AND
     (any version 1 attribute certificates are present)) OR
     (any SignerInfo structures are version 3) OR
     (encapContentInfo eContentType is other than id-data)
   THEN version MUST be 3
   ELSE version MUST be 1

Assuming you have an implementation that understands version n (in this
example 1) but not n + m (in this case 3), a SignedData with both version 1
and version 3 SignerInfo, of which version 1 can be processed by the
implementation, would be marked with a SignedData version of 3, which can't.
Extending this to some future SignerInfo version x, the SignedData would also
be marked as x even if a version 1 SignerInfo was present alongside the
version x SignerInfo, making it non-processable by an implementation.

To fix at least some of this, the Encrypted/Signed/whateverData versions
should not be dependent on the Signer/RecipientInfo versions: The xxxData
format stays the same no matter what the Signer/RecipientInfo versions are, so
unless the format of the xxxData changes there should only be one version
necessary. This allows future updates for new Signer/RecipientInfo versions
without breaking every implementation that only allows the currently-defined
xxxData versions.

This also fixes the problem with forwards-compatibility, because now if you
see an xxxData with an unknown version type you know that it's something you
actually can't process, rather than an indication that it's something you may
be perfectly capable of processing but that some obscure field fifteen levels
down has been set to A rather than B and so the sender had to change the
version number because of this.

The second issue, currently being debated on OpenPGP, is how you handle a
situation like:

   signerInfos {
     signerInfo version = 7,
     signerInfo version = 6,
     signerInfo version = 1
     }

Do you report a bad-signature result for the first two?  An unknown status?
If the third one verifies, do you report it as an overall verification?  Best
two of three?

If you're having trouble seeing this is anything other than an abstract
problem, assume you're being asked to write a spec for a new key transport or
signature type, i.e. Signer/RecipientInfo, that can't be handled by the
current format.  How will you add this in a manner that doesn't break every
existing implementation?

Peter.

_______________________________________________
smime mailing list
smime(_at_)ietf(_dot_)org
https://www.ietf.org/mailman/listinfo/smime

_______________________________________________
smime mailing list
smime(_at_)ietf(_dot_)org
https://www.ietf.org/mailman/listinfo/smime