RFC 9219
S/MIME Signature Verification Extension to the JSON Meta Application Protocol (JMAP)
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 Notice
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.nullmeans 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 amultipart/signedmessage 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.nullmeans 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.nullmeans 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, requestingsmimeStatus,smimeStatusAtDelivery, and/orsmimeErrorswould 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
- ietf: rfc9219 2022-04
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms