Subject: [smime] PKCS#7 v1.5 vs. CMS / ContentInfo vs. EncapsulatedContentInfo based on version

From: [email-masked] (Martin Rex)
Date: Fri, 3 Nov 2017 17:04:51 +0100 (CET)

There is a somewhat confusing ruleset around the "SignedData" PDU
version field in the CMS specification, and insufficient guidance
about the ramifications for the Encoder/Decoder for ContentInfo
when version 1 vs. 3 is chosen.

The organization responsible for certain legally mandated data exchanges
in Germany is rev'ving their requirements, intoducing RSA-PSS signatures
on certificates plus RSA-OAEP encryption for AppData.

Previously, they've been using PKCS#7 v1.5 PDUs with RSA PKCS#1 v1.5
transforms.

The confusion I'm seeing is about the choice of the SignedData "version"
field, and the resulting consequences for the (ASN.1) PDU encoder/decoder
for the ContentInfo vs. EncapsulatedContentInfo in SignedData.

For the encoder/decoder, the reasonable interpretation would be,
that whenever version=1, then the PKCS#7 ContentInfo encoding will be
used, and only for version>=3, the CMS EncapsulatedContentInfo encoding
will be encoded or decoded.

However the current reading of the CMS standard by that organization is
that they want to specify version=1 in combination with EncapsulatedContentInfo
encoding -- something that looks extremely weird to me, and would require
significant contortions in the ASN.1 encoder and decoder.

For the encoder, it will require a laying violation from within the encoder,
looking at later elements and semantics of higher level PDUs.

For the decoder, it essentially will require heuristics (trial-and-error)
decoding if the PDU version will no longer matter, and the data determining
which encoding is appropriate, has not been decoded yet at this point
requiring a retroactive verification of whether the heuristically determined
encoding was actually a _valid_ encoding.

Any comments from folks more experienced with CMS ?

-Martin

---

From: Russ Housley <[email-masked]>
Date: Fri, 3 Nov 2017 12:26:45 -0400

The version is structure in this manner so that an implementation that checks the version number and then does a decode will never get a decode error on a properly constructed message.

If the only changes are (migrate from PKCS#1 v1.5 to RSA-PSS) and (migrate from PKCS#1 v1.5 to PRS-OAEP), then the change should be very straightforward.

If you are not using any version 1 attribute certificates, identifying the signer with the subject public key identifier, or using a content type other than id-data, then the version for Signed-Data should not change.

I am assuming that you are not mixing RSA-OAEP with other key management algorithms.  If you are not using unprotect attributes or identifying the signer with the subject public key identifier, then the version number for Enveloped-Data should not change.

Russ

> On Nov 3, 2017, at 12:04 PM, Martin Rex <[email-masked]> wrote:
> 
> _______________________________________________
> smime mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/smime

---

From: [email-masked] (Martin Rex)
Date: Fri, 3 Nov 2017 18:01:28 +0100 (CET)

Russ,

It seems I wasn't sufficiently clear.

This is about a third-party specification refering to CMS/rfc5652.

That organization specifically refers to SignedData structure and
members as defined in section 5.1 of RFC 5652, it quotes that structure
definition, and describes contents for the structure elements.

For the version element, since they _not_ doing any of the fancy
stuff, they came up with "version=1" from the pseudo-code.

  https://tools.ietf.org/html/rfc5652#section-5.1

   5.1.  SignedData Type

   The following object identifier identifies the signed-data content
   type:

      id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
         us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }

   The signed-data content type shall have ASN.1 type SignedData:

      SignedData ::= SEQUENCE {
        version CMSVersion,
        digestAlgorithms DigestAlgorithmIdentifiers,
        encapContentInfo EncapsulatedContentInfo,
        certificates [0] IMPLICIT CertificateSet OPTIONAL,
        crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
        signerInfos SignerInfos }

      DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier

      SignerInfos ::= SET OF SignerInfo

However, the use of version=1 would IMHO imply the use of the original
PKCS#7 v1.5 structure instead:

  https://tools.ietf.org/html/rfc2315#section-9.1

and more specifically, the use of the original PKCS#7 v1.5 ContentInfo rather
than the CMS version 3 EncapsulatedContentInfo.

The organization is currently assuming that CMS (rfc5652) would suggest
combining "version=1" with CMS 3+ SignedData with EncapsulatedContentInfo.

To me, this looks "underspecified".  I.e. rfc5652 section 5.1 fails to
describe what exactly version=1 means for the ContentInfo vs.
EncapsulatedContentInfo encoding of SignedData.

-Martin

Russ Housley <[email-masked]> wrote:
> The version is structure in this manner so that an implementation
> that checks the version number and then does a decode will never
> get a decode error on a properly constructed message.
> 
> If the only changes are (migrate from PKCS#1 v1.5 to RSA-PSS) and
> (migrate from PKCS#1 v1.5 to PRS-OAEP), then the change should be
> very straightforward.
> 
> If you are not using any version 1 attribute certificates, identifying
> the signer with the subject public key identifier, or using a content
> type other than id-data, then the version for Signed-Data should not change.
> 
> I am assuming that you are not mixing RSA-OAEP with other key management
> algorithms.  If you are not using unprotect attributes or identifying
> the signer with the subject public key identifier, then the version
> number for Enveloped-Data should not change.

---

From: Jim Schaad <[email-masked]>
Date: Fri, 3 Nov 2017 11:25:20 -0700

There was never any intent that a version number of one would indicate that
this was PKCS#7 rather than CMS.

To begin with, this is only a problem if you are looking at wrapping
contents other than id-data, for id-data there is no difference.  In both
cases there is an OCTET wrapper.

For things which are not id-data, there is going to be a difference between
the two encodings in that for one an octet wrapper is there and for the
other case it is not.  I would say that you need to look at the content type
and the type of the field and then make a decision about what you are doing.
I will note that there is a security problem with the PKCS#7 encoding where
the content and length bytes are not correctly protected.  This is one of
the reasons that CMS added the OCTET wrapper in all cases rather than just
in the case of id-data.  

Jim

> -----Original Message-----
> From: smime [mailto:[email-masked]] On Behalf Of Martin Rex
> Sent: Friday, November 3, 2017 9:05 AM
> To: [email-masked]
> Subject: [smime] PKCS#7 v1.5 vs. CMS / ContentInfo vs.
> EncapsulatedContentInfo based on version
> 
> There is a somewhat confusing ruleset around the "SignedData" PDU version
> field in the CMS specification, and insufficient guidance about the
ramifications
> for the Encoder/Decoder for ContentInfo when version 1 vs. 3 is chosen.
> 
in
> Germany is rev'ving their requirements, intoducing RSA-PSS signatures on
> certificates plus RSA-OAEP encryption for AppData.
> 
for
> the ContentInfo vs. EncapsulatedContentInfo in SignedData.
> 
> 
> For the encoder/decoder, the reasonable interpretation would be, that
> whenever version=1, then the PKCS#7 ContentInfo encoding will be used, and
> only for version>=3, the CMS EncapsulatedContentInfo encoding will be
> encoded or decoded.
> 
> 
that
> they want to specify version=1 in combination with EncapsulatedContentInfo
decoding
> if the PDU version will no longer matter, and the data determining which
> encoding is appropriate, has not been decoded yet at this point requiring
a
> retroactive verification of whether the heuristically determined encoding
was
> actually a _valid_ encoding.
> 
>

---

From: Russ Housley <[email-masked]>
Date: Fri, 3 Nov 2017 14:30:36 -0400

As Jim already said, that is not the point of the version number.  The point is to avoid decode errors.

Russ

> On Nov 3, 2017, at 1:01 PM, Martin Rex <[email-masked]> wrote:
> 
> Russ,
>

---

From: [email-masked] (Martin Rex)
Date: Fri, 3 Nov 2017 22:43:27 +0100 (CET)

Hi Jim,

Thanks for the reply, but this leaves me even more confused now.

Admittedly my personal implementors experience is tiny.  I once patched
support for processing rfc3161 TimeStamps into an existing PKCS#7 v1.5
implementation, and I needed a few tweaks for the ASN.1 encoder & decoder
-- but rfc3161 uses id-ct-TSTInfo content type and version 3 rather than
id-data and version 1, so I needed tweaks for processing of
EncapsulatedContentInfo.

> cases there is an OCTET wrapper.

This statement looks like a self-contradiction.  Either there is _no_
difference between PKCS#7 v1.5 SignedData for id-data, then there is
no wrapper.  Or there is a difference, and EncapsulatedContentInfo is used.

> and the type of the field and then make a decision about what you are doing.

Do you mean that while the PDU encoding for SignedData with id-data
ContentInfo is the same for PKCS#7 v1.5 and CMS, the actual signature
(or more precisely the hash over that id-data) is computed _differently_
for PKCS#7 v1.5 and CMS (covering the 0x04 plus ASN.1 length field for
CMS, and omitting this for PKCS#7 v1.5) ?

I wouldn't like a heuristic on decoding because it results in needlessly
complex code and seems to have an ambituity for certain id-data that
conicidentally matches the beginning of an ASN.1 DER OctetString.

But requiring a heuristic on SignedData would be magnitudes worse,
because of significantly higher CPU cycles impact for computing and
verifying two different hashes.

> the reasons that CMS added the OCTET wrapper in all cases rather than just

But "in all cases rather than just in the case of id-data" is a contradiction
to the above (with respect to the encoding).  Or is this comment _not_
about the encoding, but rather about the data which gets signed (hashed) ?

> this was PKCS#7 rather than CMS.

That sounds wrong to me.  At least my copy of PKCS#7 v1.5
(rfc2315) is _explicit_ that this version indicates PDU/protocol, and
version==1 therefore implies PKCS#7 (rfc2315) syntax/encoding
**AND** processing rules (semantics).

   The fields of type SignedData have the following meanings:

        o    version is the syntax version number. It shall be
             1 for this version of the document.

The PKCS#7 v1.5 PDU was *ALWAYS* supposed to be self-describing,
and later revisions of it to identify different syntax as well as
different processing rules by using a different version in the PDU.

For the particular (governmentally mandated) data exchange scenario in
Germany, they're currently using PKCS#7 v1.5 with RSA PKCS#1 v1.5,
and they want to transition to using RSA-PSS (signatures on certs
and PKCS#7/CMS SignedData) and RSA-OAEP (EvelopedData), with
EndEntity certs that carry rsaEncryption keys (so that the keys
can be used for both, signature and encryption).

-Martin

---

From: Jim Schaad <[email-masked]>
Date: Fri, 3 Nov 2017 22:13:11 -0700

> From: Martin Rex [mailto:[email-masked]]
> Sent: Friday, November 3, 2017 2:43 PM
> To: Jim Schaad <[email-masked]>
> Cc: [email-masked]; [email-masked]
> Subject: Re: [smime] PKCS#7 v1.5 vs. CMS / ContentInfo vs.
id-data
> and version 1, so I needed tweaks for processing of
EncapsulatedContentInfo.
> > contents other than id-data, for id-data there is no difference.  In
> > both cases there is an OCTET wrapper.
> 
difference
> between PKCS#7 v1.5 SignedData for id-data, then there is no wrapper.  Or
> there is a difference, and EncapsulatedContentInfo is used.

There is zero difference in the bytes outputted by the encoder.  

For PKCS#7 v1.5 - id-data is defined to be an OCTET STRING - thus the
emitted content is an OCTET wrapped data string
For CMS - id-data is defined to not have an ASN.1 type - instead the data is
directly wrapped by the OCTET wrapper that present in all SignedData objects

> 
> >
> > For things which are not id-data, there is going to be a difference
> > between the two encodings in that for one an octet wrapper is there
> > and for the other case it is not.  I would say that you need to look
> > at the content type and the type of the field and then make a decision
about
> what you are doing.
> ContentInfo is the same for PKCS#7 v1.5 and CMS, the actual signature (or
> more precisely the hash over that id-data) is computed _differently_ for
> PKCS#7 v1.5 and CMS (covering the 0x04 plus ASN.1 length field for CMS,
and
> omitting this for PKCS#7 v1.5) ?

For PKCS #7 v1.5 - the outer ASN.1 length and tag are not included in the
signature computation.  This means that the exact same set of bytes are
going to be hashed for an id-data object.

For a non-id-data object, the bytes that would be hashed ARE different.  For
PKCS #7 v1.5 the tag and length are not included in the signature
computation.  For CMS the OCTET wrapper is not included, but all of the
contents are included.  This means that for CMS the tag and length of the
data are included in the hash computation. 

Does this answer your questions?

> I wouldn't like a heuristic on decoding because it results in needlessly
complex
> code and seems to have an ambituity for certain id-data that
conicidentally
> matches the beginning of an ASN.1 DER OctetString.
> 
> But requiring a heuristic on SignedData would be magnitudes worse, because
> of significantly higher CPU cycles impact for computing and verifying two
> different hashes.
> 
> 
> > I will note that there is a security problem with the PKCS#7 encoding
> > where the content and length bytes are not correctly protected.  This
> > is one of the reasons that CMS added the OCTET wrapper in all cases
> > rather than just in the case of id-data.
> 
> But "in all cases rather than just in the case of id-data" is a
contradiction to the
> above (with respect to the encoding).  Or is this comment _not_ about the
> encoding, but rather about the data which gets signed (hashed) ?
> 
> 
> >
> > There was never any intent that a version number of one would indicate
> > that this was PKCS#7 rather than CMS.
> 
> The PKCS#7 v1.5 PDU was *ALWAYS* supposed to be self-describing, and later
> revisions of it to identify different syntax as well as different
processing rules by
> using a different version in the PDU.
> 
> 
> Germany, they're currently using PKCS#7 v1.5 with RSA PKCS#1 v1.5, and
they
> want to transition to using RSA-PSS (signatures on certs and PKCS#7/CMS
> SignedData) and RSA-OAEP (EvelopedData), with EndEntity certs that carry
> rsaEncryption keys (so that the keys can be used for both, signature and
> encryption).
> 
> 
> -Martin