SMTP Message Routing


A sender transfers a message to an SMTP Server by issuing SMTP commands in this order:
MAIL FROM:<bob@nhind.source.example.org>
RCPT TO:<alice@nhind.dest.example.com>
DATA
< raw ASCII encoded message, including all headers>

It is important to note is that all source and destination addresses used by the SMTP Server are separate from the message itself. The SMTP Server does not need to parse the message to route it.

  1. Servers do not use message Destination Headers - To, CC or BCC - to determine the list of message recipients. All recipients must be specified using one or more rcpt to commands.
  2. Servers do not use message Originator Headers – From or Sender - to determine message sender. The message sender must be specified using the mail from command.

Consequently:
  1. The recipients specified using RCPT TO might not be found in the message Destination headers
  2. The sender specified using MAIL FROM need not match the sender in the message Originator headers

Both scenarios can occur legitimately, such as for implementing features like mailing lists and BCC.

SMTP Message Envelope


To process a message, the SMTP Server creates an internal message envelope. This envelope contains:
  1. Recipients – the list of all recipients submitted using the RCPT TO command.
  2. Sender – the message sender submitted using the MAIL FROM command.
  3. Message – exactly the message data submitted by the user.

The message envelope is conceptually represented by an MessageEnvelope pseudo class:
//
// Pseudo Class
//
public class MessageEnvelope
{
    public MailAddressCollection Recipients;
    public MailAddress Sender;
    public MailMessage Message;
}

SMTP Local Domain


SMTP Servers are configured with their local domain.

A mail message may be sent to addresses in multiple domains. Some of these addresses are local (internal) and others may be remote (external). The mail client transfers the message to its SMTP Server, which categorizes each address as local or remote – by comparing their address domain to its configured local domain. Mail sent to local addresses is delivered to the message store of IMAP/POP3 server or even a file folder. Messages sent to remote addresses are relayed to the SMTP Servers for those domains, which is discovered by resolving DNS MX records.

S/MIME Overview


The following represents a high level overview to RFC 3851, which should be referred to for details. This section assumes a solid understanding of MIME and standard cryptographic methods.

Details such as S/MIME’s usage of Cryptographic Message Syntax (CMS) and PKS7 standards are not discussed. Please refer to RFC 3851 as necessary as well as widely available documentation on cryptographic methods.

This section is non-normative.

What is secured?


S/MIME secures MIME entities.

A MIME entity is defined as:
  1. The MIME specific headers and
  2. The MIME content/body (the portion consisting of the empty line and the subsequent body content)

MIME specific headers have names that begin with Content- . These include:
  • Content-Type
  • Content-Transfer-Encoding
  • Content-Disposition

All non-content header – i.e. any headers whose name does not begin with “Content-“ - are not secured.

S/MIME secures the entity as is – the raw “wire” octets of both MIME Body Content and Headers. S/MIME implementations must avoid accidental loss of wire text fidelity during entity serialization.

Header Fidelity



Encryption


S/MIME encrypts entities by combining symmetric and asymmetric encryption. S/MIME can encrypt an entity for multiple recipients without creating a separate copy of the entity for each recipient. It does so using facilities provided by CMS. The concepts behind the algorithm are explained below.

Encryption Algorithm

  1. Get all public keys for each recipient
  2. Generate a secret symmetric encryption key
  3. Use the symmetric key to encrypt the MIME entity into encrypted bytes
  4. Encrypt the secret symmetric key with each public key (separately) to create an encrypted key collection
  5. Combine the encrypted bytes, the encrypted key collection into an envelope

Decryption Algorithm

  1. Scan encrypted key collection to locate an encrypted key that was encrypted with the recipient’s public key
  2. Decrypt the encrypted key using the associated recipient private key to get the secret symmetric key
  3. Get the encrypted bytes from the envelope.
  4. Decrypt encrypted bytes using the secret symmetric key to obtain original MIME entity.

Signatures

This specification follows the S/MIME specification recommendation by requiring use of so-called "detached signatures", which separate the signature data from the original signed content by use of the multipart/signed content type. (It sometimes causes confusion that the "detached" signatures show up as attachments in e-mail clients, because such clients interpret multipart/signed as multipart/mixed, and thus interpret the signature as an unknown attachment type).

Signature Creation

  1. Get all the (private key, public certificate) pairs for each signer
  2. Compute a digest of the entity
  3. Create a signature for each signer by encrypting the digest using their private key.
  4. Attach information about each signer (their public certificates) to each signature
  5. Combine all signatures into a signature MIME entity (of type application/pkcs7-signature)
  6. Create a new container Multipart MIME entity of Content-Type: multipart/signed
  7. Insert the original entity as the first part of the Signed Entity.
  8. Insert the signature entity as the second part of the Signed Entity

Signature Verification

  1. Get the signature envelope from the Signed Entity
  2. Get the original entity from the first part of the Signed Entity
  3. Compute a digest of the entity
  4. Decrypt each signature using the attached signer public certificate
  5. Compare the digest to the signature value

Content Security Algorithm Specification


The Content Security Algorithm operates on Message Envelope objects. It implements the following conceptual interface:
    // Conceptual interface
    interface IDirectAgent
    {
        OutgoingMessage ProcessOutgoing(MessageEnvelope messageEnvelope);
        IncomingMessage ProcessIncoming(MessageEnvelope messageEnvelope);
    }
These operations MAY be applied at various points, but typically are applied twice: once prior to sending, and once upon ultimate receipt or preparation for ultimate receipt. The operations MAY be applied by the sender and receiver of the message, or by agents of the sender and receiver. Such agents MAY be embedded in special purpose mail servers created to securely transfer health content.

The ProcessOutgoing step enforces the sender’s Trust setting, then signs and encrypts the outgoing message.
The ProcessIncoming step decrypts the incoming message, verifies signatures, and enforces each recipient’s Trust settings.

For implementations that are implemented as filters in the SMTP processing pipeline, the trust settings SHOULD be enforced on the addresses provided through SMTP in the RCPT TO and MAIL FROM commands, in preference to the header values contained in the RFC 5322 document itself.

Process Outgoing

An outgoing message is a new message being sent to a set of recipients.

The implementation MUST ensure:
  1. The sender is trusted
  2. The message is sent to only those recipients who the sender trusts

To verify that the sender is configured to send Simple Health Transport messages, the implementation retrieves the sender’s private keys and public certificates. If no private key can be found, the implementation can assume that the sender is not configured to send messages and can reject the message.

To verify that the sender trusts a given recipient, the implementation retrieves the recipient’s public certificates. The implementation MUST use the DNS method and MAY use other locally supported methods.

To process outgoing messages, the implementation:

  1. Resolves private keys for messageEnvelope.Sender
  2. Resolves public certificates for each messageEnvelope.Recipients
  3. Enforces the Trust Model
  4. Wraps messageEnvelope.Message (see Message Wrapping)
  5. Signs and Encrypts the wrapped MIME entity with the sender certificates and private key pair and recipient public certificates
  6. Creates a new messageEnvelope.Message with the headers extracted in the message wrapping process and the MIME package created by signing and encrypting

The implementation MUST check recipient certificate trust. If the recipient is un-trusted, the implementation removes the recipient from the recipient list. If a message has no trusted recipients, the implementation MUST reject the message.

The implementation returns the following conceptual object to indicate success:
    // Conceptual Object
    public class OutgoingMessage
    {
        // The secured message
        public MessageEnvelope MessageEnvelope;
        // List of rejected/untrusted recipients
        public MailAddressCollection UntrustedRecipients;
        // Other Status Information for invoking code
        ...
    }
The implementation MUST indicate a rejected message by returning an appropriate error code or throwing an exception.

The mechanism for communicating message rejection and recipient removal to the sender is specific to how the agent is integrated with a message processing pipeline. For example, SMTP integrations MAY send message delivery failure notifications to the sender. Integrations may choose to log the list of untrusted recipients for internal auditing and/or debugging.

Process Incoming


An incoming message is signed and encrypted – i.e. it has passed through the ProcessOutgoing method.

The implementation MUST ensure that the message is delivered only to those recipients who:

  1. Really are the intended recipients of the message
  2. Trust the sender

To verify that a recipient is the intended recipient, the implementation attempts to decrypt the message using each of the recipient’s private keys until decryption succeeds. The implementation then MUST verify that the resulting message is in the expected signed format (e.g., has content type mulitpart/signed and corresponds the the requirements for that content type.

If the recipient has no private keys, or the decryption fails for all recipient keys, the implementation can assume that the message was not encrypted with the recipient’s equivalent public certificate and MUST reject the message.

To ensure that the recipient does not receive the message, The implementation removes the recipient from the message’s recipient list.

To verify if a recipient trusts a sender, the implementation MUST check if the sender signed the message with a certificate that the receiver trusts. A sender can sign the message using the private keys associated with multiple public certificates, each of which may represent its membership in different trust circles. The implementation finds at least one valid signature with a certificate whose trust chain contains an anchor that the recipient trusts.

An implementation MUST perform the following steps:

  1. Resolve private keys for domain recipients
  2. Decrypt messageEnvelope.Message
  3. Extract the signed Signed Entity
  4. Verify the signature
  5. Enforce Trust Model
  6. Unwrap message

Signatures are verified by:

  1. Ensuring the signature has an attached certificate
  2. Checking that the certificate is properly issued
  3. Verifying the signature with the certificate

If the implementation does not find at least one acceptable sender signature, it MUST reject the message.

Finally, the implementation unwraps the message and constructs a new MessageEnvelope with Sender, valid Recipients, and unwrapped message.

The implementation may return the following conceptual object to indicate success.
    // Conceptual object
    public class IncomingMessage
    {
        // The processed message - decrypted, signatures verified
        public MessageEnvelope MessageEnvelope;
        // Recipients in the local domain about to receive this message
        public MailAddressCollection DomainRecipients;
        // Recipients who were removed as Untrusted
        public MailAddressCollection UntrustedRecipients;
    }
The implementation MUST indicate a rejected message by returning an appropriate error code or throwing an exception.

The mechanism for communicating message rejection and recipient removal is specific to how the agent is integrated with a message processing pipeline. For example, SMTP integrations MAY send message delivery failure notifications to the sender. Integrations may also chose to log such events.