RFC 9219

S/MIME Signature Verification Extension to the JSON Meta Application Protocol (JMAP)

๐Ÿ“… published April 2022, from ietf

RFC 9219: S/MIME Signature Verification Extension to the JSON Meta Application Protocol (JMAP) ๐Ÿ’Œ

Okay bestie, this is RFC 9219 ๐ŸŽ€ It's a Standards Track doc from the Internet Engineering Task Force (IETF), written by A. Melnikov of Isode Ltd, dated April 2022, with ISSN 2070-1721. The header doesn't list anything it obsoletes or updates, so it stands on its own โœจ

Abstract

This doc specifies an extension to "The JSON Meta Application Protocol (JMAP) for Mail" (RFC 8621) that lets a server return the S/MIME signature verification status ๐Ÿฆ‹

Status of This Memo

This is an Internet Standards Track document ๐Ÿ”ฅ

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841 ๐Ÿ“š

Info about the current status of this doc, any errata, and how to send feedback is at https://www.rfc-editor.org/info/rfc9219 ๐Ÿ’œ

Copyright (c) 2022 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 (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Revised BSD License ๐Ÿซถ

Table of Contents

1.  Introduction
2.  Conventions Used in This Document
3.  Addition to the Capabilities Object
4.  Extension for S/MIME Signature Verification
  4.1.  Extension to Email/get
    4.1.1.  "smimeStatus" Response Property Extensibility
  4.2.  Extension to Email/query
  4.3.  Interaction with Email/changes
5.  IANA Considerations
  5.1.  JMAP Capability Registration for "smimeverify"
6.  Security Considerations
7.  References
  7.1.  Normative References
  7.2.  Informative References
Acknowledgements
Author's Address

1. Introduction โœจ

JMAP for Mail [RFC8621] is a JSON-based application protocol for syncing email data between a client and a server ๐Ÿ’–

This doc describes an extension to JMAP that lets a server return the S/MIME signature verification status [RFC8551]. The client doesn't have to download the signature body part and all the signed body parts (when the multipart/signed media type [RFC1847] is used), and it doesn't have to download and decode the Cryptographic Message Syntax (CMS) (when the application/pkcs7-mime media type (Section 3.2 of [RFC8551]) is used). That's the whole glow-up ๐ŸŒธ

Using the extension means the client trusts the JMAP server's S/MIME signature verification code and configuration. This is lowkey the move when cutting network bandwidth and client-side code complexity matters more than security concerns about trusting the JMAP server to do the S/MIME signature verifications. One possible use case is when the same organization controls both the JMAP server and the JMAP client ๐Ÿงš

2. Conventions Used in This Document ๐Ÿ“–

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐ŸŽ€

Type signatures, examples, and property descriptions in this document follow the conventions established in Section 1.1 of [RFC8620]. Data types defined in the core specification are also used in this document ๐Ÿ’…

3. Addition to the Capabilities Object ๐Ÿ“

The capabilities object is returned as part of the standard JMAP Session object; see Section 2 of [RFC8620]. Servers supporting this specification MUST add a property called urn:ietf:params:jmap:smimeverify to the capabilities object ๐Ÿ”ฅ

The value of this property is an empty object in both the JMAP Session capabilities property and an account's accountCapabilities property ๐Ÿฆ‹

4. Extension for S/MIME Signature Verification โœจ

4.1. Extension to Email/get ๐Ÿ“ฌ

okay so [RFC8621] gives us the Email/get method for pulling message-specific info, and this doc adds some extra pseudo values you can put in the properties argument ๐Ÿ’…

  • smimeStatus: if "smimeStatus" is in your list of requested properties, the server MUST treat it as a request to return the "smimeStatus" response property. ๐Ÿ”
  • smimeStatusAtDelivery: if "smimeStatusAtDelivery" is in your list, the server MUST treat it as a request to return the "smimeStatusAtDelivery" response property. (It's basically the same as the "smimeStatus" value, just calculated at the date/time of delivery, as specified by "receivedAt". ๐Ÿ•ฐ๏ธ)
  • smimeErrors: if "smimeErrors" is in your list, the server MUST treat it as a request to return the "smimeErrors" response property. ๐Ÿ™ˆ
  • smimeVerifiedAt: if "smimeVerifiedAt" is in your list, the server MUST treat it as a request to return the "smimeVerifiedAt" response property. โฐ

Now the response properties themselves. The "smimeStatus" one is giving main character energy โœจ

  • smimeStatus: this is a "String|null" that the server sets. null means the message doesn't contain any signature. Otherwise, it holds the S/MIME signature and certificate verification status, calculated according to [RFC8551], [RFC8550], and [RFC5280]. Here are the possible string values. Servers MAY return other values not defined below, as defined in extensions to this document. Clients MUST treat unrecognized values as "unknown" or "signed/failed". Also, heads up: this value might change over time ๐Ÿ‘€
    • unknown: an S/MIME message that was neither signed nor encrypted. This can also show up for a multipart/signed message that uses an unrecognized signing protocol (for example, OpenPGP).
    • signed: an S/MIME signed message, but the signature hasn't been verified yet. Some servers won't attempt verification until the client actually requests that specific message. (This is a super useful optimization for a JMAP server, since it avoids doing work until the exact info is needed. A JMAP client that only needs to show an icon for the presence of an S/MIME signature can still use this value.) JMAP servers compliant with this document SHOULD attempt signature verification and return "signed/verified" or "signed/failed" instead of this signature status. ๐Ÿง
    • signed/verified: an S/MIME signed message, and the sender's signature was successfully verified according to [RFC8551] and [RFC8550]. On top of that, the signer email address pulled from the S/MIME certificate matches the From header field value, and the signer certificate SHOULD be checked for revocation. โœ…
    • signed/failed: an S/MIME signed message, but the signature failed to verify according to [RFC8551] and [RFC8550]. This might be because of a policy-related decision (e.g., the message signer email address doesn't match the From header field value), the message was modified, the signer's certificate has expired or was revoked, etc. ๐Ÿ’€
    • encrypted+signed/verified: this value is reserved for future use. It's typically handled the same way as "signed/verified". ๐Ÿ”ฎ
    • encrypted+signed/failed: this value is reserved for future use. It's typically handled the same way as "signed/failed". ๐Ÿ”ฎ

The smimeStatusAtDelivery response property has the same syntax as smimeStatus, but it's calculated in relation to the "receivedAt" date/time. Unlike smimeStatus, its value doesn't change unless trust anchors are added. (For example, adding a trust anchor can change a message's smimeStatusAtDelivery from "signed/failed" to "signed/verified". Removing a trust anchor doesn't affect this response property. ๐Ÿ™ƒ) This is what lets clients compare the S/MIME verification status at delivery with the current status returned by smimeStatus, which helps answer questions like "was the signature valid at the time of delivery?" ๐Ÿ•ต๏ธโ€โ™€๏ธ

Heads up though: the smimeStatusAtDelivery value doesn't have to be calculated at delivery time. A JMAP server can defer calculating it until someone explicitly asks for it. Once it's calculated, though, its value is remembered for later use ๐Ÿง 

The smimeErrors response property is next ๐Ÿซถ

  • smimeErrors: this is a "String[]|null" that the server sets. null means the message doesn't contain any signature, or there were no errors when verifying the S/MIME signature. (So this property is only non-null when the matching "smimeStatus" value is "signed/failed" or "encrypted+signed/failed". Future extensions to this document can define other "smimeStatus" values that work with "smimeErrors".) Each string in the array is a human-readable description (in the language given in the Content-Language header field, if there is one) of a problem with the signature, the signing certificate, or the signing certificate chain. (See Section 3.8 of [RFC8620] for how language selection affects this.) For example, the signing certificate might be expired, and the message From email address might not match any of the email addresses in the signing certificate. Or the certificate might be expired and the JMAP server might be unable to retrieve a Certificate Revocation List (CRL) for it. In both of those cases, the array would have 2 elements. ๐Ÿ“

And finally, the smimeVerifiedAt response property ๐Ÿ—“๏ธ

  • smimeVerifiedAt: this is a "UTCDate|null" that the server sets. null means the message doesn't contain any S/MIME signature, or there is one but nobody tried to verify it. (You can use retrieval of the "smimeStatus" value to tell those two cases apart.) In every other case, it's set to the date and time when the S/MIME signature was most recently verified. Also, requesting smimeStatus, smimeStatusAtDelivery, and/or smimeErrors would force this property to be non-null if an S/MIME signature exists. ๐Ÿ”„

The smimeStatus and smimeErrors values are calculated when the matching JMAP request is processed (but check out the note below about result caching), not when the message was generated, according to its Date header field value. In every case, smimeVerifiedAt is set to the time that smimeStatus and smimeErrors were last updated. Recalculating these is expensive for the server, so they MAY be cached for up to 24 hours from the moment they were calculated. โณ

Example 1: retrieving minimal info about a message, including its From, Subject, and Date header fields, plus the S/MIME signature verification status at delivery and the date/time the message was received ๐Ÿ“จ

["Email/get", {
"ids": [ "fe123u457" ],
"properties": [ "mailboxIds", "from", "subject", "date",
 "smimeStatusAtDelivery", "receivedAt" ]
}, "#1"]

This might result in the following response:

[["Email/get", {
   "accountId": "abc",
   "state": "51234123231",
   "list": [
     {
       "id": "fe123u457",
       "mailboxIds": { "f123": true },
       "from": [{"name": "Joe Bloggs",
               "email": "joe@bloggs.example.net"}],
       "subject": "Dinner tonight?",
       "date": "2020-07-07T14:12:00Z",
       "smimeStatusAtDelivery": "signed/verified",
       "receivedAt": "2020-07-07T14:15:18Z"
     }
   ]
}, "#1"]]

Example 2: retrieving minimal info about a message, including its From, Subject, and Date header fields, plus the latest S/MIME signature verification status, any S/MIME verification errors, and when the signature status was last verified. This response has 2 S/MIME errors related to signature verification ๐Ÿšจ

["Email/get", {
"ids": [ "ag123u123" ],
"properties": [ "mailboxIds", "from", "subject", "date",
 "smimeStatus", "smimeErrors", "smimeVerifiedAt" ]
}, "#1"]

This might result in the following response:

[["Email/get", {
   "accountId": "abc",
   "state": "47234123231",
   "list": [
     {
       "id": "ag123u123",
       "mailboxIds": { "f123": true },
       "from": [{"name": "Jane Doe",
               "email": "jdoe@example.com"}],
       "subject": "Company takeover",
       "date": "2020-01-31T23:00:00Z",
       "smimeStatus": "signed/failed",
       "smimeErrors": [
         "From email address doesn't match the certificate",
         "Can't retrieve CRL from the CRL URL"],
       "smimeVerifiedAt": "2020-03-01T12:11:19Z"
     }
   ]
}, "#1"]]

4.1.1. "smimeStatus" Response Property Extensibility ๐Ÿงฉ

Future extensions to this document can specify extra allowed values for the "smimeStatus" response property. All values (whether defined in this document or in extensions to it) MUST be in ASCII. (Since this response property contains tokens, it isn't subject to internationalization or localization. ๐Ÿ”ค)

New "smimeStatus" values defined in extensions may affect how other properties behave, like the "smimeErrors" response property of Email/get (see Section 4.1) or the "hasVerifiedSmime" property of Email/query (see Section 4.2). In particular, the new values can be treated similarly to the values defined in this document. ๐Ÿ’–

For example, a hypothetical JMAP extension for automatically decrypting S/MIME messages could add two new values. One would say a message is both encrypted and signed with a valid S/MIME signature (e.g. "encrypted+signed/verified"), and the other would say it's both encrypted and signed with an invalid S/MIME signature (e.g. "encrypted+signed/failed"). The former can be treated as "signed/verified" (and would therefore affect "hasVerifiedSmime"), and the latter can be treated as "signed/failed" (and therefore can be used with "smimeErrors"). this is the kind of design that makes me so happy ๐ŸŒˆ

4.2. Extension to Email/query โœจ

okay so [RFC8621] already defines the Email/query method for searching for messages with specific properties ๐Ÿ”. this doc adds three new properties to the FilterCondition object, and they're honestly so useful ๐Ÿ’–

hasSmime: Boolean. if hasSmime is true, only messages whose smimeStatus is something other than null match. if it's false, only messages with smimeStatus equal to null match ๐ŸŒธ

hasVerifiedSmime: Boolean. if hasVerifiedSmime is true, only messages with smimeStatus equal to "signed/verified" or "encrypted+signed/verified" () match. if it's false, only messages where smimeStatus is not "signed/verified" and not "encrypted+signed/verified" () match, and that includes messages where it's null ๐Ÿงš

heads up though, this one can be pricey for a JMAP server, because it has to work out the smimeStatus value for every single message ๐Ÿ˜ญ caching the smimeStatus values should help with that cost a bit, so it's not all doom ๐Ÿ’…

(*) plus any smimeStatus values added by future extensions to this document that are explicitly specified as having a similar effect to "signed/verified" as far as hasVerifiedSmime calculation is concerned ๐Ÿฆ‹

hasVerifiedSmimeAtDelivery: Boolean. this one works basically the same as hasVerifiedSmime, except it checks the value of smimeStatusAtDelivery instead of smimeStatus to decide whether a message matches ๐ŸŽ€

4.3. Interaction with Email/changes ๐Ÿ”„

okay bestie, pay attention to this part ๐Ÿ‘‘ a change to the smimeVerifiedAt response property value MUST NOT cause the message to be included in the updated argument of the Email/changes response ๐Ÿ™…โ€โ™€๏ธ but changes to smimeStatus, smimeStatusAtDelivery, and/or smimeErrors MUST result in the message being included in the updated argument of the Email/changes response ๐Ÿ”ฅ

5. IANA Considerations ๐ŸŒˆ

5.1. JMAP Capability Registration for "smimeverify" ๐ŸŽ€

IANA has registered the "smimeverify" JMAP capability, and the registration looks like this ๐Ÿ’œ

Capability Name:  urn:ietf:params:jmap:smimeverify
Specification document:  RFC 9219
Intended use:  common
Change Controller:  IETF
Security and privacy considerations:  RFC 9219, Section 6

6. Security Considerations ๐Ÿ”

okay this section is serious, so I'm going to be serious too ๐Ÿ˜ญ using the server-side S/MIME signature verification JMAP extension means the client has to trust the server's signature verification code, the server's configuration, and the server's operational practices for doing S/MIME signature verification. the client also has to trust that the channel between client and server is integrity protected. (for example, if the server isn't configured with some trust anchors, some messages will show the "signed/failed" status instead of "signed/verified".) a malicious or compromised server could return a false verification status to a client ๐Ÿ’€ a successful verification could be shown to a client for a forged or altered message, and a properly signed message could be signaled as having a failed signature verification or as having no signature at all ๐Ÿ™ˆ

for that last attack, where a properly signed message gets shown as unsigned, no new attack surface shows up because of this extension. a malicious or compromised server could already do that by stripping or tampering with the S/MIME information in the message anyway ๐Ÿฅฒ for the former attack, where a forged or altered message gets shown as verified, client software that's able to do S/MIME signature verification could detect it. whether that client-side verification should happen is up to the local configuration of the client. for clients without local verification capabilities, this kind of attack would be really hard to detect ๐Ÿ˜ฑ

integrity protection for the channel between the client and the server is provided by TLS, which the JMAP specification requires (see Section 8.1 of [RFC8620]) ๐Ÿ”’

constantly recalculating the S/MIME signature status can lead to a denial-of-service condition ๐Ÿšจ because of that, servers are RECOMMENDED to cache results of signature verification for up to 24 hours โฐ

7. References ๐Ÿ“š

7.1. Normative References ๐Ÿ’…

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC5280]  Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
           Housley, R., and W. Polk, "Internet X.509 Public Key
           Infrastructure Certificate and Certificate Revocation List
           (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
           <https://www.rfc-editor.org/info/rfc5280>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8550]  Schaad, J., Ramsdell, B., and S. Turner, "Secure/
           Multipurpose Internet Mail Extensions (S/MIME) Version 4.0
           Certificate Handling", RFC 8550, DOI 10.17487/RFC8550,
           April 2019, <https://www.rfc-editor.org/info/rfc8550>.

[RFC8551]  Schaad, J., Ramsdell, B., and S. Turner, "Secure/
           Multipurpose Internet Mail Extensions (S/MIME) Version 4.0
           Message Specification", RFC 8551, DOI 10.17487/RFC8551,
           April 2019, <https://www.rfc-editor.org/info/rfc8551>.

[RFC8620]  Jenkins, N. and C. Newman, "The JSON Meta Application
           Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July
           2019, <https://www.rfc-editor.org/info/rfc8620>.

[RFC8621]  Jenkins, N. and C. Newman, "The JSON Meta Application
           Protocol (JMAP) for Mail", RFC 8621, DOI 10.17487/RFC8621,
           August 2019, <https://www.rfc-editor.org/info/rfc8621>.

7.2. Informative References ๐Ÿง 

[RFC1847]  Galvin, J., Murphy, S., Crocker, S., and N. Freed,
           "Security Multiparts for MIME: Multipart/Signed and
           Multipart/Encrypted", RFC 1847, DOI 10.17487/RFC1847,
           October 1995, <https://www.rfc-editor.org/info/rfc1847>.

Acknowledgements ๐Ÿซถ

this doc is a product of the JMAP Working Group ๐ŸŒธ huge thank you to Bron Gondwana, Neil Jenkins, Murray Kucherawy, Kirsty Paine, Benjamin Kaduk, Roman Danyliw, Peter Yee, Robert Wilton, Erik Kline, and Menachem Dodge for the suggestions, comments, and corrections that made this document better โœจ

Author's Address ๐Ÿฆ‹

Alexey Melnikov
Isode Ltd
14 Castle Mews
Hampton, Middlesex
TW12 2NP
United Kingdom
Email: Alexey.Melnikov@isode.com
๐Ÿ“ฆ where this page comes from