Introduction to the S/MIME Toolkit
Newsgroup: mozilla.dev.tech.cryptoMain technical contact: Ian McGreer
Manager: Wan-Teh Chang
Overview
S/MIME Types and Structures
Overview of an S/MIME Application
References
Overview of CMS
This document provides a brief introduction to the S/MIME Toolkit API. More complete descriptions of individual types and functions will be provided at a later time.
The S/MIME Toolkit API reflects the Cryptographic Message Syntax (CMS) Specification (RFC 2630). You should read that document before attempting to use the S/MIME Toolkit API. For information on other relevant RFCs, see Referemces.
CMS, which is based on PKCS #7, describes various message types that can be used to digitally sign and/or encrypt messages transmitted over an unencrypted communications channel. Two of the message types defined by RFC 2630 are relevant for S/MIME: SignedData and EnvelopedData. The corresponding types in the S/MIME Toolkit API are NSSCMSSignedData and NSSCMSSignedData.
This overview uses the RFC names to discuss basic concepts and procedures. The remainder of this document refers to specific S/MIME Toolkit types and functions listed in http://lxr.mozilla.org/mozilla/source/security/nss/lib/smime/cmst.h and http://lxr.mozilla.org/mozilla/source/security/nss/lib/smime/cms.h, respectively.
EnvelopedData
An EnvelopedData message contains an "inner" message that is encrypted for a set of recipients. The "inner" message is encrypted with a random key using a fast symmetric encryption algorithm such as RC2 or 3DES. The random key itself is transmitted with the EnvelopedData, encrypted with each recipient's public key, so that it can be decrypted only by the recipients using their private keys.
An EnvelopedData message includes:
- a set of RecipientInfo structures, each of which contains the encrypted content key and the ID of the recipient's certificate used for this encryption. There is one RecipientInfo per recipient.
- the encrypted "inner" content
- information about the encryption algorithms used
SignedData
A SignedData message contains an unencrypted message, plus one or more "signer" blocks. Each signer block contains the signer’s certificate, digest values for the message that are encrypted using the signer's private key, and other information, such as the signing time.
By decrypting the digest values with the signer's public key, and then checking whether they are equal to newly computed digests, the receiving software can make reasonably sure that (1) the message has not been altered since the signer signed it, and (2) the message was, in fact, signed by the entity/person identified in the message (assuming that the signer's certificate verified correctly and its issuer is trusted by the receiver).
A SignedData message includes:
- the "inner" content
- a set of certificates used in processing the message
- a set of SignerInfo structures, each of which contains signer identification (pointer to signer's certificate), encrypted digest value(s), and other attributes.
- for S/MIME messages, an attribute that specifies S/MIME preferences, including the sender's encryption algorithm preferences and identification of the certificate the sender prefers to be used for sending encrypted mail back to the sender
- information about the algorithms used
Since SignedData messages can contain certificate information, they can also be used for simple transport of certificates. In this case, there is no "inner" content and no SignerInfo structures.
Use of Enveloped Data and SignedData in a MIME Message
Content-Type: application/pkcs7-mime
Depending on the smime-type subheader, MIME messages can be signed or enveloped (encrypted) messages. The content is a DER-encoded CMS message that contains the "inner" content of a SignedData or EnvelopedData structure.
Here's an example of a signed message:
Content-Type: application/pkcs7-mime; smime-type=signed-data; name=smime.p7m Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7m 567GhIGfHfYT6ghyHhHUujpfyF4f8HHGTrfvhJhjH776tbB9HG4VQbnj7 77n8HHGT9HG4VQpfyF467GhIGfHfYT6rfvbnj756tbBghyHhHUujhJhjH HUujhJh4VQpfyF467GhIGfHfYGTrfvbnjT6jH7756tbB9H7n8HHGghyHh 6YT64V0GhIGfHfQbnj75
In this example, the binary data contains a SignedData message, which is the "inner" content plus signature information. The inner content could, for example, expand to this text:
Content-Type: text/plain This is a signed message.
To be displayed appropriately in an email program, the binary data must be fed to a MIME parser and tagged with information about the signatures and their validity.
Alternatively, the inner content can be another S/MIME message, up to arbitrary levels of recursion, with each message in the hierarchy signed or encrypted. A single message that is both signed and encrypted consists of two nested MIME messages.
Binary CMS messages can (but need not) be encoded for 7-bit channels. The information in the Content-Transfer-Encoding header must be used for parsing.
Here's an example of an encrypted message:
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7m rfvbnj756tbBghyHhHUujhJhjH77n8HHGT9HG4VQpfyF467GhIGfHfYT6 7n8HHGghyHhHUujhJh4VQpfyF467GhIGfHfYGTrfvbnjT6jH7756tbB9H f8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4 0GhIGfHfQbnj756YT64V
The binary content is a DER-encoded CMS EnvelopedData message containing inner content that must be decrypted before further processing occurs.
Content-Type: multipart/signed
The multipart/signed content type designates clear-signed messages. [what does this mean?] The content to be signed is in the first part (in readable form, with the appropriate content type), and the signature is in the second part (using a SignedData CMS message without inner content). This format is preferred for generation because it can be used even with non-S/MIME enabled user agents. [generation of original message? does this mean that this content type is readable even if the receiving software doesn’t support S/MIME? whereas the other one isn’t?]
Here’s an example of a multipart/signed CMS message:
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary=boundary42 --boundary42 Content-Type: text/plain
This is a clear-signed message.
--boundary42 Content-Type: application/pkcs7-signature; name=smime.p7s Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7s ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6 4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4 7GhIGfHfYT64VQbnj756 --boundary42--
add the rest of Christian’s text here? heads are:
Advanced Topics Triple-Wrapped Messages Secure Mail Lists Security Labels Signed Receipts Implications for a Mail User Agent Implementation MIME Parser Glue Code MIME Generator Glue Code Message Composition UI Message Presentation UI Address Book Integration S/MIME Preferences
S/MIME Types and Structures
- follows RFC 2630, Cryptographic Message Syntax, exactly.
Basically, you create a NSSCMSMessage structure and populate it with the info re algorithms, data to be signed or encrypted, certs, etc. and then stream your data through it. [???]
A ContentUnion structure is a container that specifies the type of content and the content itself. The content can be unstructured data (SEC_Item), structured data (NSSCMSDigestedData, NSSCMSEncryptedData, NSSCMSEnvelopedData, NSSCMSSignedData), or a pointer to something.
A NSSCMSMessage structure contains an NSSCMSSignedData ocbject
SignedData ::= SEQUENCE { version CMSVersion, digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncapsulatedContentInfo, certificates [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, signerInfos SignerInfos } NSSCMSMessage NSSCMSContentInfo - type & content of “outer” data memory stuff inner stuff: algorithm sectitem (digests) callback for getting decryption key
Overview of an S/MIME Application
[say something about streaming model here? anything else? e.g. process of building up nested messages?]
Initialization
Initialization includes initializing the NSPR and NSS libraries, opening the certificate database, and setting the default certificate database. Functions used in the initialization part of an application can include the following:
- PR_Init. Initializes NSPR. Must be called before any other NSS or S/MIME Toolkit functions.
- SECU_PKCS11Init. [Initializes PKCS #11? not in SSL Ref, where to document?]
- SEC_Init. [Initializes NSS library? not in SSL Ref, where to document? Why this and not NSS_Init?]
- OpenCertDB. Opens the cert database. [Specifies a callback?]
- CERT_SetDefaultCertDB. Sets the opened cert database to be the default cert database. [not documented in SSL Ref; add it to CERT chapter?]
Building the NSSCMSMessage Object
An NSSCMSMessage object in turn contains nested NSSCMSSignedData, NSSCMSEnvelopedData, and other objects. Each of these CMS objects consists of a content type and content, plus other information required for processing. The basic procedure is to create an NSSCMSMessage, which is the outermost container, and build up the nested objects as necessary for signing or encrypting nested messages.
These are the functions that an S/MIME application typically calls initially to create an NSSCMSMessage object and the chain of objects it contains:
- NSS_CMSMessage_Create allocates memory for an empty NSSCMSMessage object.
- NSS_CMSSignedData_Create adds an empty NSSCMSSIgnedData object to an existing NSSCMSMessage object.
- [others here, e.g. NSS_CMSEnvelopedData_Create?]
- NSS_CMSMessage_GetContentInfo returns a pointer to the top level contentInfo structure.
- NSS_CMSSignedData_GetContentInfo returns a pointer to a specified NSSCMSSignedData object's contentinfo. - need to talk more about contentInfo
build chain of objects: create signeddata object (sigd) with a call to NSS_CMSSignedData_Create get ref. to contentinfo of your cmsg (cinfo) with a call to NSS_CMSMessage_GetContentInfo get ref. to contentinfo of your signeddata (sigd) with a call to NSS_CMSSignedData_GetContentInfo set content of your data with a call to NSS_CMSContentInfo_SetContent create and attach signer info with NSS_CMSSignerInfo_Create, passing in a cert and an algorithm if you want to include the cert chain, call NSS_CMSSignerInfo_IncludeCerts NSS_CMSSignerInfo_AddSigningTime adds signing time to signer info NSS_CMSSignerInfo_AddSMIMECaps adds profile info (?) to signerinfo ContentInfo ::= SEQUENCE { contentType ContentType, content [0] EXPLICIT ANY DEFINED BY contentType } ContentType ::= OBJECT IDENTIFIERa name="refs">
References
[formatting to come]
RFC2633 S/MIME v3 Message Specification. The authoritative document. RFC2634 Enhanced Security Services for S/MIME. Some extensions for S/MIME - not required, but growing importance for some. RFC2630 Cryptographic Message Syntax. Describes the format of cryptographic messages used in S/MIME (SignedData, EnvelopedData), plus some others RFC2045-2049 MIME. The basic MIME framework RFC2459 Internet X.509 Public Key Infrastructure.