RFC 6476

Using Message Authentication Code (MAC) Encryption in the Cryptographic Message Syntax (CMS)

πŸ“… published January 2012, from ietf

Using Message Authentication Code (MAC) Encryption in the Cryptographic Message Syntax (CMS) πŸŽ€

okay bestie, so this is RFC 6476 πŸ’– It's a Standards Track doc, which is the IETF's category for real protocol specs. P. Gutmann from the University of Auckland wrote it, and it was published in January 2012 (ISSN 2070-1721). The title block doesn't list anything it obsoletes or updates, so it stands on its own ✨

Abstract 🌈

okay so this doc explains how to use MAC encryption with the CMS authenticated-enveloped-data content type πŸ¦‹ The move here is copying a combo that's already everywhere: a MAC paired with an encryption algorithm, which shows up in IPsec, Secure Socket Layer / Transport Layer Security (SSL/TLS), and Secure SHell (SSH). It's supported in tons of crypto libraries and hardware, and the crypto community has analysed it extensively. Iconic reuse, honestly πŸ’…


Status of This Memo πŸ“œ

This is an Internet Standards Track document.

It's a product of the Internet Engineering Task Force (IETF), so it reflects the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check out Section 2 of RFC 5741 🧚

For the current status, any errata, and where to send feedback, go to http://www.rfc-editor.org/info/rfc6476 πŸ”—

Copyright (c) 2012 IETF Trust and the persons identified as the document authors. All rights reserved. πŸŽ€

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info), as in effect on the date this document was published. Please read these carefully because they spell out your rights and restrictions for this document. Code Components pulled out of this doc need to include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They come without warranty, as described in the Simplified BSD License πŸ“œ


Table of Contents πŸ“‹

1. Introduction ....................................................2
   1.1. Conventions Used in This Document ..........................2
2. Background ......................................................2
3. CMS Encrypt-and-Authenticate Overview ...........................3
   3.1. Rationale ..................................................3
4. CMS Encrypt-and-Authenticate ....................................4
   4.1. Encrypt-and-Authenticate Message Processing ................5
   4.2. Rationale ..................................................6
   4.3. Test Vectors ...............................................8
5. SMIMECapabilities Attribute ....................................12
6. Security Considerations ........................................12
7. IANA Considerations ............................................13
8. Acknowledgements ...............................................14
9. References .....................................................14
   9.1. Normative References ......................................14
   9.2. Informative References ....................................14

1. Introduction ✨

okay so the whole point here is MAC-authenticated encryption with CMS's authenticated-enveloped-data content type πŸ’œ It's the same move as IPsec, SSL/TLS, and SSH: a MAC plus an encryption algorithm. That combo is widely supported in crypto libraries and hardware, and it's been extensively analysed by the crypto community. Main character energy πŸ‘‘

1.1. Conventions Used in This Document πŸ“š

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. Those are the official BCP 14 key words, so when you see them, they carry real weight 🫢


2. Background 🌸

okay bestie, so integrity-protected encryption is a standard feature of session-oriented security protocols like [IPsec], [SSH], and [TLS] πŸ”’ But until pretty recently, it just wasn't there for message-based security protocols like CMS. [OpenPGP] did add a form of integrity protection, though: it encrypts a SHA-1 hash of the message alongside the contents, which gives authenticate-and-encrypt protection πŸ™ˆ

Here's the tea: usability studies show that users expect encryption to come with integrity protection [Garfinkel]. When the security mechanisms don't actually deliver that, you get cognitive dissonance problems, and nobody wants that πŸ’€

This document takes the same encrypt-and-authenticate mechanism that IPsec, SSH, and SSL/TLS already use and applies it to CMS. Technically, some of those protocols actually use authenticate-and-encrypt rather than encrypt-and-authenticate, since what gets authenticated is the plaintext and not the ciphertext 🧚 The mechanism is widely supported in crypto libraries and hardware, and it's been extensively analysed by the crypto community [EncryptThenAuth] πŸ’–


3. CMS Encrypt-and-Authenticate Overview πŸ¦‹

okay so conventional CMS encryption uses a content-encryption key (CEK) to encrypt the message payload. The CEK usually gets encrypted in turn by a key-encryption key (KEK) πŸ—οΈ Authenticated encryption needs two keys: one for encryption and another for authentication.

Like other authenticated-encryption mechanisms, this doc uses a pseudorandom function (PRF) to turn one block of keying material into the two keys needed for encryption and authentication ✨ So the standard CMS encryption operation:

KEK( CEK ) || CEK( data )

becomes:

KEK( master_secret ) || MAC( CEK( data ) )

The MAC key (MAC-K) and the encryption key (CEK-K) both come out of the master_secret like this:

MAC-K := PRF( master_secret, "authentication" );
CEK-K := PRF( master_secret, "encryption" );

3.1. Rationale 🧠

okay so there are a bunch of ways to get the two keys needed for encrypt-and-authenticate out of the single key that the key exchange or key transport mechanism normally hands you. A few of them have security or practical problems 😬 For example, if a mechanism uses the single exchanged key in its entirety for encryption (say, with PRF( key ) as the MAC key), then someone can strip off the outer MAC layer, rewrite the CMS envelope back to plain EnvelopedData or EncryptedData, and the data is unauthenticated again. Oof. Applying the PRF intermediate step fixes that: any attempt at a rollback attack ends in a decryption failure 🚫

The option picked here is using a PRF to derive the keying material from a master secret. It's well-established because IPsec, SSH, and SSL/TLS already do it, and it's widely supported in both crypto libraries and encryption hardware 🌈

The PRF used is Password-Based Key Derivation Function 2 (PBKDF2), because CMS already uses it, which makes it the most obvious candidate. Later on, if a universal PRF, like [HKDF], gets adopted, it can be swapped in for PBKDF2 by specifying it in the prfAlgorithm field covered in Section 4 πŸ¦„

Last bit: the processing operations are a mix of the operations already used for the existing CMS content types EncryptedData and AuthenticatedData. That means they're pretty simple to implement with existing code πŸ’…


4. CMS Encrypt-and-Authenticate πŸ”

okay so the encrypt-and-authenticate mechanism lives inside the existing CMS RecipientInfo framework. It does that by defining a new pseudo-algorithm type, authEnc, which takes the place of a monolithic encrypt and hash algorithm πŸŽ€ The RecipientInfo acts as a key container for the master secret the pseudo-algorithm uses. From that master secret, you derive the encryption and authentication keys for the existing single-purpose encrypt-only and MAC-only algorithms. So instead of carrying an AES or HMAC-SHA1 key, the RecipientInfo carries a master secret, and the required AES encryption and HMAC-SHA1 authentication keys come from that πŸ”‘

The authEnc pseudo-algorithm comes in two flavours: one that conveys 128 bits of keying material and one that conveys 256 bits 🌸 Here are the identifiers:

    id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
                us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }

    id-alg  OBJECT IDENTIFIER ::= { id-smime 3 }

    id-alg-authEnc-128 OBJECT IDENTIFIER ::= { id-alg 15 }
    id-alg-authEnc-256 OBJECT IDENTIFIER ::= { id-alg 16 }

And the algorithm parameters look like this:

    AuthEncParams ::= SEQUENCE {
        prfAlgorithm   [0] AlgorithmIdentifier DEFAULT PBKDF2,
        encAlgorithm       AlgorithmIdentifier,
        macAlgorithm       AlgorithmIdentifier
        }

Here's the breakdown of each field 🧁

  • prfAlgorithm is the PRF algorithm used to turn the master secret into the encryption and MAC keys. The default PRF is [PBKDF2], which in turn has a default PRF algorithm of HMAC-SHA1. With this default, the PBKDF2-params 'salt' parameter is an empty string, and the 'iterationCount' parameter is one, which turns the KDF into a pure PRF ✨
  • encAlgorithm is the encryption algorithm, plus its associated parameters, used to encrypt the content πŸ”
  • macAlgorithm is the MAC algorithm, plus its associated parameters, used to authenticate and integrity-protect the content πŸ›‘οΈ

When the prfAlgorithm AlgorithmIdentifier is used with PBKDF2 to specify a PRF other than the default PBKDF2-with-HMAC-SHA1, the PBKDF2-params need two additional algorithm parameters. The 'salt' parameter MUST be an empty (zero-length) string, and the 'iterationCount' parameter MUST be one, because those values aren't used in the PRF process πŸ™…β€β™€οΈ In their encoded form, as used for the PBKDF2-params, these two parameters have the value 08 00 02 01 01 πŸ’œ

As a guideline for authors who specify PRFs other than PBKDF2, any additional parameters such as salts, tags, and identification strings SHOULD be set to empty strings, and any iteration count SHOULD be set to one 🌈 It's a good habit to follow this 🫢

4.1. Encrypt-and-Authenticate Message Processing πŸ”

okay so the randomly generated master secret (the one that gets shipped over in the RecipientInfo(s) πŸ“¦) gets split into separate encryption and authentication keys, and then it goes through the encrypt-and-authenticate process like this ✨. The notation "PRF( key, salt, iterations )" just means we run the PRF on that keying value and salt for the given number of iterations, bestie 🧚

  1. The MAC algorithm key gets derived from the master secret like so:
MAC-K ::= PRF( master_secret, "authentication", 1 );
  1. The encryption algorithm key gets derived from the master secret like so:
Enc-K ::= PRF( master_secret, "encryption", 1 );
  1. The data gets processed as described in [AuthEnv], and specifically, since the mechanisms used are a union of EncryptedData and AuthenticatedData, as per [CMS]. The one exception is that the EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier data is MACed before the encrypted content is MACed. The EncryptedData processing is applied to the data first, and then the AuthenticatedData processing is applied to the result, so the nesting goes like this 🌸:
MAC( contentEncrAlgoID || encrypt( content ) );
  1. If authenticated attributes are present, they get encoded as described in [AuthEnv] and MACed after the encrypted content, so the processing goes like this πŸ’…:
MAC( contentEncrAlgoID || encrypt( content ) || authAttr );

4.2. Rationale πŸ’­

okay so when you're choosing between encrypt-and-authenticate and authenticate-and-encrypt, the more secure option is encrypt-and-authenticate, no cap πŸ”₯. There has been extensive analysis of this in the literature, and the best coverage is probably [EncryptThenAuth] πŸ“š.

The EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier is the SEQUENCE containing the id-alg-authEnc-128/id-alg-authEnc-256 OBJECT IDENTIFIER and its associated AuthEncParams. This data is MACed exactly as encoded, without any attempt to re-code it into a canonical form like DER πŸŽ€.

The EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier must be protected alongside the encrypted content, or else an attacker could manipulate the encrypted data indirectly by messing with the encryption algorithm parameters, and that wouldn't be detected by MACing the encrypted content alone 😭. For example, by changing the encryption IV, it's possible to modify the results of the decryption after the encrypted data has been verified via a MAC check. Not me... being sneaky like that πŸ™ˆ.

The authEnc pseudo-algorithm has two "key sizes" rather than the one-size-fits-all that the PRF impedance-matching would provide. This is done to address real-world experience with AES keys, where users demanded AES-256 alongside AES-128 because of some perception that the former was "twice as good" as the latter πŸ’€. Giving people an option for keys that go to 11 avoids potential user acceptance problems when someone notices that the authEnc pseudo-key has "only" 128 bits when they expect their AES keys to be 256 bits long πŸ‘‘.

Using a fixed-length key rather than making it a user-selectable parameter is done for the same reason as AES's quantised key lengths. There's no benefit to allowing, say, 137-bit keys over basic 128- and 256-bit lengths, it adds unnecessary complexity, and if the lengths are user-defined, then there'll always be someone who wants keys that go up to 12 πŸ˜‚. Providing a choice of two commonly used lengths gives users the option of choosing a "better" key size should they feel the need, while not overloading the system with unneeded flexibility πŸ¦‹.

The use of the PRF AlgorithmIdentifier presents some problems, because it's usually not specified in a manner that allows it to be easily used as a straight KDF. For example, PBKDF2 has the following parameters:

PBKDF2-params ::= SEQUENCE {
    salt OCTET STRING,
    iterationCount INTEGER (1..MAX),
    prf AlgorithmIdentifier {{PBKDF2-PRFs}}
                            DEFAULT algid-hmacWithSHA1
    }

of which only the prf AlgorithmIdentifier is used here. In order to avoid having to define new AlgorithmIdentifiers for each possible PRF, this specification sets any parameters not required for KDF functionality to no-op values. In the case of PBKDF2, this means that the salt has length zero and the iteration count is set to one, with only the prf AlgorithmIdentifier playing a part in the processing 🧁. Although it's not possible to know what form other PRFs-as-KDFs will take, a general note for their application within this specification is that any non-PRF parameters should similarly be set to no-op values ✨.

Specifying a MAC key size gets a bit tricky πŸ₯². Most MAC algorithms have some de facto standard key size, and for HMAC algorithms, this is usually the same as the hash output size. For example, for HMAC-MD5, it's 128 bits; for HMAC-SHA1, it's 160 bits; and for HMAC-SHA256, it's 256 bits. Other MAC algorithms also have de facto standard key sizes. For example, for AES-based MACs, it's the AES key size, which is 128 bits for AES-128 and 256 bits for AES-256. This situation makes it difficult to specify the key size in a normative fashion, since it depends on the algorithm type that's being used. If there is any ambiguity over which key size should be used, then it's RECOMMENDED that either the size be specified explicitly in the macAlgorithm AlgorithmIdentifier or that an RFC or similar standards document be created that makes the key sizes explicit πŸ“.

As with other uses of PRFs for crypto impedance-matching in protocols, like IPsec, SSL/TLS, and SSH, the amount of input to the PRF generally doesn't match the amount of output. The general philosophical implications of this are covered in various analyses of the properties and uses of PRFs. If you're worried about this, you can try to approximately match the authEnc "key size" to the key size of the encryption algorithm being used, although even there, a perfect match for algorithms like Blowfish (448 bits) or RC5 (832 bits) is going to be difficult 🌈.

The term "master secret" comes from its use in SSL/TLS, which uses a similar PRF-based mechanism to convert its master_secret value into encryption and MAC keys (as do SSH and IPsec). The master_secret value isn't a key in the conventional sense, but merely a secret value that's then used to derive two (or, in the cases of SSL/TLS, SSH, and IPsec, several) keys and related cryptovariables πŸ”‘.

Apart from the extra step added to key management, all of the processing is already specified as part of the definition of the standard CMS content-types Encrypted/EnvelopedData and AuthenticatedData. This significantly simplifies both the specification and the implementation task, as no new content-processing mechanisms are introduced πŸ₯°.

4.3. Test Vectors ✨

okay bestie, these test vectors are how you check your MAC-authenticated encryption actually works πŸ§ͺ they encrypt and authenticate a text string using the ever-popular password "password" via CMS PasswordRecipientInfo πŸ” the first value uses triple DES, and its short block size makes it easier to corrupt bytes on purpose inside the self-healing Cipher Block Chaining (CBC) mode πŸ™ˆ the corrupted data still decrypts correctly but the MAC check fails, which is exactly what we want to see πŸ’… the second value uses AES πŸ’–

for the triple DES data, corrupting a byte at positions 192-208 checks that payload-data corruption gets caught πŸŽ€ and corrupting a byte at positions 168-174 checks that metadata corruption gets caught πŸ¦‹ these corruptions don't mess with normal processing, so they wouldn't usually get noticed, which is literally the whole point πŸ‘‘

the test data has these characteristics:

  • version is set to 0.
  • originatorInfo isn't needed and is omitted.
  • recipientInfo uses passwordRecipientInfo so testing with a fixed text string is easy πŸ“
  • authEncryptedContentInfo uses the authEnc128 pseudo-algorithm, with a 128-bit key used to derive the triple DES/AES and HMAC-SHA1 keys πŸ”‘
  • authAttrs aren't used and are omitted.
  • mac is the 20-byte HMAC-SHA1 MAC value.
  • unauthAttrs aren't used and are omitted.

here's the triple DES dump (iykyk the structure is everything 🧚):

 0  227: SEQUENCE {
 3   11:   OBJECT IDENTIFIER id-ct-authEnvelopedData
                             (1 2 840 113549 1 9 16 1 23)
16  211:   [0] {
19  208:     SEQUENCE {
22    1:       INTEGER 0
25   97:       SET {
27   95:         [3] {
29    1:           INTEGER 0
32   27:           [0] {
34    9:             OBJECT IDENTIFIER pkcs5PBKDF2
                                       (1 2 840 113549 1 5 12)
45   14:             SEQUENCE {
47    8:               OCTET STRING B7 EB 23 A7 6B D2 05 16
57    2:               INTEGER 5000
       :               }
       :             }
61   35:           SEQUENCE {
63   11:             OBJECT IDENTIFIER pwriKEK
                                       (1 2 840 113549 1 9 16 3 9)

76   20:             SEQUENCE {
78    8:               OBJECT IDENTIFIER des-EDE3-CBC
                                         (1 2 840 113549 3 7)
88    8:               OCTET STRING 66 91 02 45 6B 73 BB 99
       :               }
       :             }
98   24:           OCTET STRING
       :             30 A3 7A B5 D8 F2 87 50 EC 41 04 AE 89 99 26 F0
       :             2E AE 4F E3 F3 52 2B A3
       :           }
       :         }
124   82:       SEQUENCE {
126    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
137   51:         SEQUENCE {
139   11:           OBJECT IDENTIFIER authEnc128
                                     (1 2 840 113549 1 9 16 3 15)
152   36:           SEQUENCE {
154   20:             SEQUENCE {
156    8:               OBJECT IDENTIFIER des-EDE3-CBC
                                         (1 2 840 113549 3 7)
166    8:               OCTET STRING D2 D0 81 71 4D 3D 9F 11
       :               }
176   12:             SEQUENCE {
178    8:               OBJECT IDENTIFIER hmacSHA (1 3 6 1 5 5 8 1 2)
188    0:               NULL
       :               }
       :             }
       :           }
190   16:         [0] 3A C6 06 61 41 5D 00 7D 11 35 CD 69 E1 56 CA 10
       :         }
208   20:       OCTET STRING
       :         33 65 E8 F0 F3 07 06 86 1D A8 47 2C 6D 3A 1D 94
       :         21 40 64 7E
       :       }
       :     }
       :   }

and the PKCS7 wrapper for that one 🎁

-----BEGIN PKCS7-----
MIHjBgsqhkiG9w0BCRABF6CB0zCB0AIBADFho18CAQCgGwYJKoZIhvcNAQUMMA4E
CLfrI6dr0gUWAgITiDAjBgsqhkiG9w0BCRADCTAUBggqhkiG9w0DBwQIZpECRWtz
u5kEGDCjerXY8odQ7EEEromZJvAurk/j81IrozBSBgkqhkiG9w0BBwEwMwYLKoZI
hvcNAQkQAw8wJDAUBggqhkiG9w0DBwQI0tCBcU09nxEwDAYIKwYBBQUIAQIFAIAQ
OsYGYUFdAH0RNc1p4VbKEAQUM2Xo8PMHBoYdqEcsbTodlCFAZH4=
-----END PKCS7-----

now the AES one 🌈 same vibes, different cipher, and the structure is basically the same πŸ’œ

  0  253: SEQUENCE {
  3   11:   OBJECT IDENTIFIER id-ct-authEnvelopedData
                              (1 2 840 113549 1 9 16 1 23)
 16  237:   [0] {
 19  234:     SEQUENCE {
 22    1:       INTEGER 0
 25  114:       SET {
 27  112:         [3] {
 29    1:           INTEGER 0
 32   27:           [0] {
 34    9:             OBJECT IDENTIFIER pkcs5PBKDF2
                                         (1 2 840 113549 1 5 12)
 45   14:             SEQUENCE {
 47    8:               OCTET STRING E7 B7 87 DF 82 1D 12 CC
 57    2:               INTEGER 5000
         :               }
         :             }
 61   44:           SEQUENCE {
 63   11:             OBJECT IDENTIFIER pwriKEK
                                         (1 2 840 113549 1 9 16 3 9)
 76   29:             SEQUENCE {
 78    9:               OBJECT IDENTIFIER aes128-CBC
                                           (2 16 840 1 101 3 4 1 2)
 89   16:               OCTET STRING
         :               11 D9 5C 52 0A 3A BF 22 B2 30 70 EF F4 7D 6E F6
         :               }
         :             }
107   32:           OCTET STRING
         :             18 39 22 27 C3 C2 2C 2A A6 9F 2A B0 77 24 75 AA
         :             D8 58 9C CD BB 4C AE D3 0D C2 CB 1D 83 94 6C 37
         :           }
         :         }
141   91:       SEQUENCE {
143    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
154   60:         SEQUENCE {
156   11:           OBJECT IDENTIFIER authEnc128
                                       (1 2 840 113549 1 9 16 3 15)
169   45:           SEQUENCE {
171   29:             SEQUENCE {
173    9:               OBJECT IDENTIFIER aes128-CBC
                                           (2 16 840 1 101 3 4 1 2)
184   16:               OCTET STRING
         :               B7 25 02 76 84 3C 58 1B A5 30 E2 40 27 EE C3 06
         :               }

202   12:             SEQUENCE {
204    8:               OBJECT IDENTIFIER hmacSHA (1 3 6 1 5 5 8 1 2)
214    0:               NULL
         :               }
         :             }
         :           }
216   16:         [0] 98 36 0F 0C 79 62 36 B5 2D 2D 9E 1C 62 85 1E 10
         :         }
234   20:       OCTET STRING
         :         88 A4 C1 B2 BA 78 1B CA F9 14 B0 E5 FC D1 8D F8
         :         02 E2 B2 9E
         :       }
         :     }
         :   }

and its PKCS7 wrapper 🫢

-----BEGIN PKCS7-----
MIH9BgsqhkiG9w0BCRABF6CB7TCB6gIBADFyo3ACAQCgGwYJKoZIhvcNAQUMMA4E
COe3h9+CHRLMAgITiDAsBgsqhkiG9w0BCRADCTAdBglghkgBZQMEAQIEEBHZXFIK
Or8isjBw7/R9bvYEIBg5IifDwiwqpp8qsHckdarYWJzNu0yu0w3Cyx2DlGw3MFsG
CSqGSIb3DQEHATA8BgsqhkiG9w0BCRADDzAtMB0GCWCGSAFlAwQBAgQQtyUCdoQ8
WBulMOJAJ+7DBjAMBggrBgEFBQgBAgUAgBCYNg8MeWI2tS0tnhxihR4QBBSIpMGy
ungbyvkUsOX80Y34AuKyng==
-----END PKCS7-----

5. SMIMECapabilities Attribute

okay so an S/MIME client SHOULD announce the crypto functions it supports using the SMIMECapabilities attribute [SMIME] πŸ“£ and if the client wants to say it supports MAC-authenticated encryption, the capabilities attribute MUST contain the authEnc128 and/or authEnc256 OID from above, with algorithm parameters ABSENT πŸ™Œ the other algorithms inside authEnc, like the MAC and the encryption algorithm, get picked based on whether they show up in SMIMECapabilities or by mutual agreement 🀝 no cap, that's a lot of moving parts, but it's giving organized πŸ’…


6. Security Considerations

bestie, this section is SERIOUS but also kinda dramatic 😭 unlike other CMS authenticated-data mechanisms, like SignedData and AuthenticatedData, AuthEnv's main job isn't authentication, it's encryption πŸ”“ so AuthEnvData can decrypt successfully (meaning the primary data transformation works), but the secondary authentication step using the MAC value after the encrypted data could still fail πŸ’€ that means an implementation might output decrypted data before it reaches and verifies the MAC value 😱 decryption happens inline and the result is available right away, but the authentication result doesn't show up until all the content has been processed 🫠 if the implementation shows the user data early and then later says "oops, that was tainted," users might have already acted on it πŸ™ˆ

this could totally happen in a streaming implementation where data needs to show up ASAP (so the initial plaintext is emitted before the final ciphertext and MAC value are read) 🌊 or where there's so much data that buffering the recovered plaintext until the MAC can be read and verified just isn't realistic πŸ“¦ and get this, an implementation that tries to be overly helpful might treat missing non-payload trailing data as non-fatal πŸ€¦β€β™€οΈ that lets an attacker truncate the data somewhere before the MAC value and defeat the data authentication 😈 it's extra messy because when an implementation hits truncated data, it may not be able to tell whether the rest (including the MAC value) is just on its way (a non-failure) or whether an attacker chopped it off (and should be treated as a MAC failure) 😡 (also, this same issue affects other kinds of data authentication, like signed and MACed data, since an over-optimistic implementation may return data to the user before a verification failure can even be checked 🫣)

the exact fix is kinda implementation-specific, but here are the suggested mitigations πŸ› οΈ implementations should buffer the entire message if possible and verify the MAC before doing any decryption πŸ”’ if that's not possible because of streaming or message-size constraints, implementations should consider breaking long messages into a sequence of smaller ones, each of which can be processed atomically as above 🧩 if even that isn't possible, implementations should make it obvious to the caller or user that an authentication failure has occurred and that the previously returned or output data shouldn't be used 🚨 and finally, any data-formatting problem, like obviously truncated data or missing trailing data, should be treated as a MAC verification failure even if the rest of the data was processed correctly πŸ’―


7. IANA Considerations

this doc has two algorithm identifiers defined by the S/MIME Working Group Registrar, in an arc delegated by RSA to the S/MIME Working Group πŸ—‚οΈ the arc is iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) modules(0) ✨


8. Acknowledgements

the author would like to thank Jim Schaad and the members of the S/MIME mailing list for their feedback on this document, and David Ireland for help with the test vectors πŸ«ΆπŸŽ€


9. References

9.1. Normative References

  • [AuthEnv] Housley, R., "Cryptographic Message Syntax (CMS) Authenticated-Enveloped-Data Content Type", RFC 5083, November 2007. πŸ“œ
  • [CMS] Housley, R., "Cryptographic Message Syntax (CMS)", STD 70, RFC 5652, September 2009. πŸ“œ
  • [PBKDF2] Kaliski, B., "PKCS #5: Password-Based Cryptography Specification Version 2", RFC 2898, September 2000. πŸ“œ
  • [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. πŸ“œ
  • [SMIME] Ramsdell, B. and S. Turner, "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.2 Message Specification", RFC 5751, January 2010. πŸ“œ

9.2. Informative References πŸ“š

Okay, these are the bonus reads πŸŽ€ Not required to follow along, but they're the sources the spec leans on for the deeper stuff.

[EncryptThenAuth] Krawczyk, H., "The Order of Encryption and Authentication for Protecting Communications (or: How Secure Is SSL?)", Springer-Verlag LNCS 2139, August 2001.

[Garfinkel] Garfinkel, S., "Design Principles and Patterns for Computer Systems That Are Simultaneously Secure and Usable", May 2005.

[HKDF] Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, May 2010.

[IPsec] Kent, S. and K. Seo, "Security Architecture for the Internet Protocol", RFC 4301, December 2005.

[OpenPGP] Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. Thayer, "OpenPGP Message Format", RFC 4880, November 2007.

[SSH] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Transport Layer Protocol", RFC 4253, January 2006.

[TLS] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.


Author's Address πŸ’Œ

Peter Gutmann πŸ¦‹

University of Auckland

Department of Computer Science

New Zealand

EMail: pgut001@cs.auckland.ac.nz πŸ’œ

πŸ“¦ where this page comes from