From f685b4c071a4f144576635a4011d5877d8fb7914 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Fri, 24 Jul 2026 18:21:30 +0200 Subject: [PATCH 01/11] fix(pem): accept OpenSSL headers without a space after the colon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parseTraditionalPem keyed on ': ', so a conformant encapsulated header written 'DEK-Info:AES-256-CBC,...' ended the header scan early and folded into the base64 body. Split on the first ':' and trim the value. Also correct the spec citations the audit flagged, all comment-only: - pkcs7 module doc scopes the RFC 2315 support claim; curve/digest pairing splits RFC 5753 §8 (curves) from RFC 5754 §2 (digests). - PKCS#10 version doc notes the encoded INTEGER is 0 (RFC 2986 §4.1). - inhibitAnyPolicy counts non-self-issued certificates (RFC 5280 §4.2.1.14). - rfc822Name cites RFC 2821 §4.1.2 Mailbox; the DN emailAddress cites PKCS #9 / RFC 2985 §5.2.1; name shorthand drops the X.501 attribution. - OCSP CertID SHA-1 cites RFC 5019 §2.1.1 (RFC 6960 defines no default); the responder attribute map names the X.520 id-at arc plus PKCS #9. - identity cites RFC 9525 with the CN fallback scoped to RFC 6125 §6.4.4; userConstrainedPolicies documents the RFC 9618 §5.5 (g)(5)-(6) superset. - SEC1 ECPrivateKey quotes the constrained RFC 5915 §3 syntax; PBKDF2-params restates the RFC 8018 A.2 salt CHOICE and DEFAULT prf. - PrintableString cites X.680 §41.4 Table 10; OID arcs split X.660 (root) from X.690 §8.19.4 (the <40 packing). Vendor the RFCs these citations reference and add an `rfc` fetch helper. --- CHANGELOG.md | 4 + docs/rfc/rfc2315.txt | 1795 ++++++++++++++ docs/rfc/rfc2821.txt | 4427 ++++++++++++++++++++++++++++++++++ docs/rfc/rfc2986.txt | 787 ++++++ docs/rfc/rfc4055.txt | 7 + docs/rfc/rfc5019.txt | 1235 ++++++++++ docs/rfc/rfc5280.txt | 7 + docs/rfc/rfc5753.txt | 3419 ++++++++++++++++++++++++++ docs/rfc/rfc5754.txt | 563 +++++ docs/rfc/rfc5756.txt | 7 + docs/rfc/rfc5758.txt | 7 + docs/rfc/rfc6125.txt | 7 + docs/rfc/rfc6818.txt | 7 + docs/rfc/rfc6960.txt | 8 +- docs/rfc/rfc8419.txt | 507 ++++ docs/rfc/rfc9525.txt | 1440 +++++++++++ docs/rfc/rfc9549.txt | 40 +- docs/rfc/rfc9598.txt | 4 + docs/rfc/rfc9608.txt | 4 + docs/rfc/rfc9618.txt | 4 + package.json | 1 + src/internal/asn1/der.ts | 5 +- src/internal/crypto/pbes2.ts | 5 +- src/keys/keys.ts | 13 +- src/pkcs/pkcs7.ts | 12 +- src/revocation/ocsp.ts | 4 +- src/verify/identity.ts | 4 +- src/verify/policy.ts | 7 +- src/x509/extensions.ts | 9 +- src/x509/name.ts | 4 +- src/x509/parse.ts | 2 +- test/keys.test.ts | 8 + 32 files changed, 14309 insertions(+), 44 deletions(-) create mode 100644 docs/rfc/rfc2315.txt create mode 100644 docs/rfc/rfc2821.txt create mode 100644 docs/rfc/rfc2986.txt create mode 100644 docs/rfc/rfc5019.txt create mode 100644 docs/rfc/rfc5753.txt create mode 100644 docs/rfc/rfc5754.txt create mode 100644 docs/rfc/rfc8419.txt create mode 100644 docs/rfc/rfc9525.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9910916f..741266af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Legacy OpenSSL-style encrypted PEM (`Proc-Type: 4,ENCRYPTED`) parsing accepts + an encapsulated header with no space after the colon (`DEK-Info:AES-256-CBC,…`). + The parser keyed on `': '`, so a conformant no-space header ended the header + scan early and folded into the base64 body. - `importPkcs8Der` accepts a `OneAsymmetricKey` (RFC 5958 §2 / RFC 8410 §7) that carries both `attributes [0]` and `publicKey [1]`. The parser capped at four elements, so a five-element v2 key that OpenSSL and Node WebCrypto both accept diff --git a/docs/rfc/rfc2315.txt b/docs/rfc/rfc2315.txt new file mode 100644 index 00000000..412e8069 --- /dev/null +++ b/docs/rfc/rfc2315.txt @@ -0,0 +1,1795 @@ + + + + + + +Network Working Group B. Kaliski +Request for Comments: 2315 RSA Laboratories, East +Category: Informational March 1998 + + + PKCS #7: Cryptographic Message Syntax + Version 1.5 + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1998). All Rights Reserved. + +Overview + + This document describes a general syntax for data that may have + cryptography applied to it, such as digital signatures and digital + envelopes. The syntax admits recursion, so that, for example, one + envelope can be nested inside another, or one party can sign some + previously enveloped digital data. It also allows arbitrary + attributes, such as signing time, to be authenticated along with the + content of a message, and provides for other attributes such as + countersignatures to be associated with a signature. A degenerate + case of the syntax provides a means for disseminating certificates + and certificate-revocation lists. + +1. Scope + + This document is compatible with Privacy-Enhanced Mail (PEM) in that + signed-data and signed-and-enveloped-data content, constructed in a + PEM-compatible mode, can be converted into PEM messages without any + cryptographic operations. PEM messages can similarly be converted + into the signed-data and signed-and-enveloped data content types. + + This document can support a variety of architectures for + certificate-based key management, such as the one proposed for + Privacy-Enhanced Mail in RFC 1422. Architectural decisions such as + what certificate issuers are considered "top-level," what entities + certificate issuers are authorized to certify, what distinguished + names are considered acceptable, and what policies certificate + issuers must follow (such as signing only with secure hardware, or + requiring entities to present specific forms of identification) are + left outside the document. + + + +Kaliski Informational [Page 1] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + The values produced according to this document are intended to be + BER-encoded, which means that the values would typically be + represented as octet strings. While many systems are capable of + transmitting arbitrary octet strings reliably, it is well known that + many electronic-mail systems are not. This document does not address + mechanisms for encoding octet strings as (say) strings of ASCII + characters or other techniques for enabling reliable transmission by + re-encoding the octet string. RFC 1421 suggests one possible solution + to this problem. + +2. References + + FIPS PUB 46-1 National Bureau of Standards. FIPS PUB 46-1: + Data Encryption Standard. January 1988. + + PKCS #1 RSA Laboratories. PKCS #1: RSA Encryption. + Version 1.5, November 1993. + + PKCS #6 RSA Laboratories. PKCS #6: Extended-Certificate + Syntax. Version 1.5, November 1993. + + PKCS #9 RSA Laboratories. PKCS #9: Selected Attribute + Types. Version 1.1, November 1993. + + RFC 1421 Linn, J., "Privacy Enhancement for + Internet Electronic Mail: Part I: Message + Encryption and Authentication Procedures," RFC 1421 + February 1993. + + RFC 1422 Kent, S., "Privacy Enhancement for + Internet Electronic Mail: Part II: Certificate- + Based Key Management," RFC 1422, February 1993. + + RFC 1423 Balenson, D., "Privacy Enhancement for + Internet Electronic Mail: Part III: Algorithms, + Modes, and Identifiers," RFC 1423, February 1993. + + RFC 1424 Kaliski, B., "Privacy Enhancement for + Internet Electronic Mail: Part IV: Key + Certification and Related Services," RFC 1424, + February 1993. + + + + + + + + + + +Kaliski Informational [Page 2] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + RFC 1319 Kaliski, B., "The MD2 Message-Digest + Algorithm," RFC 1319, April 1992. + + RFC 1321 Rivest, R., "The MD5 Message-Digest + Algorithm," RFC 1321, April 1992. + + X.208 CCITT. Recommendation X.208: Specification of + Abstract Syntax Notation One (ASN.1). 1988. + + X.209 CCITT. Recommendation X.209: Specification of + Basic Encoding Rules for Abstract Syntax Notation + One (ASN.1). 1988. + + X.500 CCITT. Recommendation X.500: The Directory-- + Overview of Concepts, Models and + Services. 1988. + + X.501 CCITT. Recommendation X.501: The Directory-- + Models. 1988. + + X.509 CCITT. Recommendation X.509: The Directory-- + Authentication Framework. 1988. + + [NIST91] NIST. Special Publication 500-202: Stable + Implementation Agreements for Open Systems + Interconnection Protocols. Version 5, Edition 1, + Part 12. December 1991. + + [RSA78] R.L. Rivest, A. Shamir, and L. Adleman. A method + for obtaining digital signatures and public-key + cryptosystems. Communications of the ACM, + 21(2):120-126, February 1978. + +3. Definitions + + For the purposes of this document, the following definitions apply. + + AlgorithmIdentifier: A type that identifies an algorithm (by object + identifier) and associated parameters. This type is defined in X.509. + + ASN.1: Abstract Syntax Notation One, as defined in X.208. + + Attribute: A type that contains an attribute type (specified by + object identifier) and one or more attribute values. This type is + defined in X.501. + + BER: Basic Encoding Rules, as defined in X.209. + + + + +Kaliski Informational [Page 3] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + Certificate: A type that binds an entity's distinguished name to a + public key with a digital signature. This type is defined in X.509. + This type also contains the distinguished name of the certificate + issuer (the signer), an issuer-specific serial number, the issuer's + signature algorithm identifier, and a validity period. + + CertificateSerialNumber: A type that uniquely identifies a + certificate (and thereby an entity and a public key) among those + signed by a particular certificate issuer. This type is defined in + X.509. + + CertificateRevocationList: A type that contains information about + certificates whose validity an issuer has prematurely revoked. The + information consists of an issuer name, the time of issue, the next + scheduled time of issue, and a list of certificate serial numbers and + their associated revocation times. The CRL is signed by the issuer. + The type intended by this document is the one defined RFC 1422. + + DER: Distinguished Encoding Rules for ASN.1, as defined in X.509, + Section 8.7. + + DES: Data Encryption Standard, as defined in FIPS PUB 46-1. + + desCBC: The object identifier for DES in cipher-block chaining (CBC) + mode, as defined in [NIST91]. + + ExtendedCertificate: A type that consists of an X.509 public-key + certificate and a set of attributes, collectively signed by the + issuer of the X.509 public-key certificate. This type is defined in + PKCS #6. + + MD2: RSA Data Security, Inc.'s MD2 message-digest algorithm, as + defined in RFC 1319. + + md2: The object identifier for MD2, as defined in RFC 1319. + + MD5: RSA Data Security, Inc.'s MD5 message-digest algorithm, as + defined in RFC 1321. + + md5: The object identifier for MD5, as defined in RFC 1321. + + Name: A type that uniquely identifies or "distinguishes" objects in + an X.500 directory. This type is defined in X.501. In an X.509 + certificate, the type identifies the certificate issuer and the + entity whose public key is certified. + + PEM: Internet Privacy-Enhanced Mail, as defined in RFCs 1421-1424. + + + + +Kaliski Informational [Page 4] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + RSA: The RSA public-key cryptosystem, as defined in [RSA78]. + + rsaEncryption: The object identifier for RSA encryption, as defined + in PKCS #1. + +4. Symbols and abbreviations + + No symbols or abbreviations are defined in this document. + +5. General overview + + The following nine sections specify useful types, general syntax, six + content types, and object identifiers. + + The syntax is general enough to support many different content types. + This document defines six: data, signed data, enveloped data, + signed-and-enveloped data, digested data, and encrypted data. Other + content types may be added in the future. The use of content types + defined outside this document is possible, but is subject to + bilateral agreement between parties exchanging content. + + This document exports one type, ContentInfo, as well as the various + object identifiers. + + There are two classes of content types: base and enhanced. Content + types in the base class contain "just data," with no cryptographic + enhancements. Presently, one content type is in this class, the data + content type. Content types in the enhanced class contain content of + some type (possibly encrypted), and other cryptographic enhancements. + For example, enveloped-data content can contain (encrypted) signed- + data content, which can contain data content. The four non-data + content types fall into the enhanced class. The content types in the + enhanced class thus employ encapsulation, giving rise to the terms + "outer" content (the one containing the enhancements) and "inner" + content (the one being enhanced). + + The document is designed such that the enhanced content types can be + prepared in a single pass using indefinite-length BER encoding, and + processed in a single pass in any BER encoding. Single-pass operation + is especially helpful if content is stored on tapes, or is "piped" + from another process. One of the drawbacks of single-pass operation, + however, is that it is difficult to output a DER encoding in a single + pass, since the lengths of the various components may not be known in + advance. Since DER encoding is required by the signed-data, signed- + and-enveloped data, and digested-data content types, an extra pass + may be necessary when a content type other than data is the inner + content of one of those content types. + + + + +Kaliski Informational [Page 5] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +6. Useful types + + This section defines types that are useful in at least two places in + the document. + +6.1 CertificateRevocationLists + + The CertificateRevocationLists type gives a set of certificate- + revocation lists. It is intended that the set contain information + sufficient to determine whether the certificates with which the set + is associated are "hot listed," but there may be more certificate- + revocation lists than necessary, or there may be fewer than + necessary. + + CertificateRevocationLists ::= + SET OF CertificateRevocationList + +6.2 ContentEncryptionAlgorithmIdentifier + + The ContentEncryptionAlgorithmIdentifier type identifies a content- + encryption algorithm such as DES. A content-encryption algorithm + supports encryption and decryption operations. The encryption + operation maps an octet string (the message) to another octet string + (the ciphertext) under control of a content-encryption key. The + decryption operation is the inverse of the encryption operation. + Context determines which operation is intended. + + ContentEncryptionAlgorithmIdentifier ::= + AlgorithmIdentifier + +6.3 DigestAlgorithmIdentifier + + The DigestAlgorithmIdentifier type identifies a message-digest + algorithm. Examples include MD2 and MD5. A message-digest algorithm + maps an octet string (the message) to another octet string (the + message digest). + + DigestAlgorithmIdentifier ::= AlgorithmIdentifier + +6.4 DigestEncryptionAlgorithmIdentifier + + The DigestEncryptionAlgorithmIdentifier type identifies a digest- + encryption algorithm under which a message digest can be encrypted. + One example is PKCS #1's rsaEncryption. A digest-encryption algorithm + supports encryption and decryption operations. The encryption + operation maps an octet string (the message digest) to another octet + .bp string (the encrypted message digest) under control of a digest- + encryption key. The decryption operation is the inverse of the + + + +Kaliski Informational [Page 6] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + encryption operation. Context determines which operation is intended. + + DigestEncryptionAlgorithmIdentifier ::= + AlgorithmIdentifier + +6.5 ExtendedCertificateOrCertificate + + The ExtendedCertificateOrCertificate type gives either a PKCS #6 + extended certificate or an X.509 certificate. This type follows the + syntax recommended in Section 6 of PKCS #6: + + ExtendedCertificateOrCertificate ::= CHOICE { + certificate Certificate, -- X.509 + + extendedCertificate [0] IMPLICIT ExtendedCertificate } + +6.6 ExtendedCertificatesAndCertificates + + The ExtendedCertificatesAndCertificates type gives a set of extended + certificates and X.509 certificates. It is intended that the set be + sufficient to contain chains from a recognized "root" or "top-level + certification authority" to all of the signers with which the set is + associated, but there may be more certificates than necessary, or + there may be fewer than necessary. + + ExtendedCertificatesAndCertificates ::= + SET OF ExtendedCertificateOrCertificate + + Note. The precise meaning of a "chain" is outside the scope of this + document. Some applications of this document may impose upper limits + on the length of a chain; others may enforce certain relationships + between the subjects and issuers of certificates in a chain. An + example of such relationships has been proposed for Privacy-Enhanced + Mail in RFC 1422. + +6.7 IssuerAndSerialNumber + + The IssuerAndSerialNumber type identifies a certificate (and thereby + an entity and a public key) by the distinguished name of the + certificate issuer and an issuer-specific certificate serial number. + + IssuerAndSerialNumber ::= SEQUENCE { + issuer Name, + serialNumber CertificateSerialNumber } + + + + + + + +Kaliski Informational [Page 7] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +6.8 KeyEncryptionAlgorithmIdentifier + + The KeyEncryptionAlgorithmIdentifier type identifies a key-encryption + algorithm under which a content-encryption key can be encrypted. One + example is PKCS #1's rsaEncryption. A key-encryption algorithm + supports encryption and decryption operations. The encryption + operation maps an octet string (the key) to another octet string (the + encrypted key) under control of a key-encryption key. The decryption + operation is the inverse of the encryption operation. Context + determines which operation is intended. + + KeyEncryptionAlgorithmIdentifier ::= + AlgorithmIdentifier + +6.9 Version + + The Version type gives a syntax version number, for compatibility + with future revisions of this document. + + Version ::= INTEGER + +7. General syntax + + The general syntax for content exchanged between entities according + to this document associates a content type with content. The syntax + shall have ASN.1 type ContentInfo: + + ContentInfo ::= SEQUENCE { + contentType ContentType, + content + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + + ContentType ::= OBJECT IDENTIFIER + + The fields of type ContentInfo have the following meanings: + + o contentType indicates the type of content. It is + an object identifier, which means it is a unique string of + integers assigned by the authority that defines the content + type. This document defines six content types (see Section + 14): data, signedData, envelopedData, + signedAndEnvelopedData, digestedData, and encryptedData. + + o content is the content. The field is optional, and + if the field is not present, its intended value must be + supplied by other means. Its type is defined along with the + object identifier for contentType. + + + + +Kaliski Informational [Page 8] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + Notes. + + 1. The methods below assume that the type of content + can be determined uniquely by contentType, so the type + defined along with the object identifier should not be a + CHOICE type. + + 2. When a ContentInfo value is the inner content of + signed-data, signed-and-enveloped-data, or digested-data + content, a message-digest algorithm is applied to the + contents octets of the DER encoding of the content field. + When a ContentInfo value is the inner content of + enveloped-data or signed-and-enveloped-data content, a + content-encryption algorithm is applied to the contents + octets of a definite-length BER encoding of the content + field. + + 3. The optional omission of the content field makes + it possible to construct "external signatures," for + example, without modification to or replication of the + content to which the signatures apply. In the case of + external signatures, the content being signed would be + omitted from the "inner" encapsulated ContentInfo value + included in the signed-data content type. + +8. Data content type + + The data content type is just an octet string. It shall have ASN.1 + type Data: + + Data ::= OCTET STRING + + The data content type is intended to refer to arbitrary octet + strings, such as ASCII text files; the interpretation is left to the + application. Such strings need not have any internal structure + (although they may; they could even be DER encodings). + +9. Signed-data content type + + The signed-data content type consists of content of any type and + encrypted message digests of the content for zero or more signers. + The encrypted digest for a signer is a "digital signature" on the + content for that signer. Any type of content can be signed by any + number of signers in parallel. Furthermore, the syntax has a + degenerate case in which there are no signers on the content. The + degenerate case provides a means for disseminating certificates and + certificate-revocation lists. + + + + +Kaliski Informational [Page 9] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + It is expected that the typical application of the signed-data + content type will be to represent one signer's digital signature on + content of the data content type. Another typical application will be + to disseminate certificates and certificate-revocation lists. + + The process by which signed data is constructed involves the + following steps: + + 1. For each signer, a message digest is computed on + the content with a signer-specific message-digest + algorithm. (If two signers employ the same message-digest + algorithm, then the message digest need be computed for + only one of them.) If the signer is authenticating any + information other than the content (see Section 9.2), the + message digest of the content and the other information are + digested with the signer's message digest algorithm, and + the result becomes the "message digest." + + 2. For each signer, the message digest and associated + information are encrypted with the signer's private key. + + 3. For each signer, the encrypted message digest and + other signer-specific information are collected into a + SignerInfo value, defined in Section 9.2. Certificates and + certificate-revocation lists for each signer, and those not + corresponding to any signer, are collected in this step. + + 4. The message-digest algorithms for all the signers + and the SignerInfo values for all the signers are collected + together with the content into a SignedData value, defined + in Section 9.1. + + A recipient verifies the signatures by decrypting the encrypted + message digest for each signer with the signer's public key, then + comparing the recovered message digest to an independently computed + message digest. The signer's public key is either contained in a + certificate included in the signer information, or is referenced by + an issuer distinguished name and an issuer-specific serial number + that uniquely identify the certificate for the public key. + + This section is divided into five parts. The first part describes the + top-level type SignedData, the second part describes the per-signer + information type SignerInfo, and the third and fourth parts describe + the message-digesting and digest-encryption processes. The fifth part + summarizes compatibility with Privacy-Enhanced Mail. + + + + + + +Kaliski Informational [Page 10] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +9.1 SignedData type + + The signed-data content type shall have ASN.1 type SignedData: + + SignedData ::= SEQUENCE { + version Version, + digestAlgorithms DigestAlgorithmIdentifiers, + contentInfo ContentInfo, + certificates + [0] IMPLICIT ExtendedCertificatesAndCertificates + OPTIONAL, + crls + [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos } + + DigestAlgorithmIdentifiers ::= + + SET OF DigestAlgorithmIdentifier + + SignerInfos ::= SET OF SignerInfo + + The fields of type SignedData have the following meanings: + + o version is the syntax version number. It shall be + 1 for this version of the document. + + o digestAlgorithms is a collection of message-digest + algorithm identifiers. There may be any number of + elements in the collection, including zero. Each + element identifies the message-digest algorithm + (and any associated parameters) under which the + content is digested for a some signer. The + collection is intended to list the message-digest + algorithms employed by all of the signers, in any + order, to facilitate one-pass signature + verification. The message-digesting process is + described in Section 9.3. + + o contentInfo is the content that is signed. It can + have any of the defined content types. + + o certificates is a set of PKCS #6 extended + certificates and X.509 certificates. It is intended that + the set be sufficient to contain chains from a recognized + "root" or "top-level certification authority" to all of the + signers in the signerInfos field. There may be more + certificates than necessary, and there may be certificates + sufficient to contain chains from two or more independent + + + +Kaliski Informational [Page 11] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + top-level certification authorities. There may also be + fewer certificates than necessary, if it is expected that + those verifying the signatures have an alternate means of + obtaining necessary certificates (e.g., from a previous set + of certificates). + + o crls is a set of certificate-revocation lists. It + is intended that the set contain information sufficient to + determine whether or not the certificates in the + certificates field are "hot listed," but such + correspondence is not necessary. There may be more + certificate-revocation lists than necessary, and there may + also be fewer certificate-revocation lists than necessary. + + o signerInfos is a collection of per-signer + information. There may be any number of elements in the + collection, including zero. + + Notes. + + 1. The fact that the digestAlgorithms field comes + before the contentInfo field and the signerInfos field + comes after it makes it possible to process a SignedData + value in a single pass. (Single-pass processing is + described in Section 5.) + + 2. The differences between version 1 SignedData and + version 0 SignedData (defined in PKCS #7, Version 1.4) are + the following: + + o the digestAlgorithms and signerInfos + fields may contain zero elements in version 1, + but not in version 0 + + o the crls field is allowed in version 1, + but not in version 0 + + Except for the difference in version number, version 0 + SignedData values are acceptable as version 1 values. An + implementation can therefore process SignedData values of + either version as though they were version 1 values. It is + suggested that PKCS implementations generate only version 1 + SignedData values, but be prepared to process SignedData + values of either version. + + + + + + + +Kaliski Informational [Page 12] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 3. In the degenerate case where there are no signers + on the content, the ContentInfo value being "signed" is + irrelevant. It is recommended in that case that the content + type of the ContentInfo value being "signed" be data, and + the content field of the ContentInfo value be omitted. + +9.2 SignerInfo type + + Per-signer information is represented in the type SignerInfo: + + SignerInfo ::= SEQUENCE { + version Version, + issuerAndSerialNumber IssuerAndSerialNumber, + digestAlgorithm DigestAlgorithmIdentifier, + authenticatedAttributes + [0] IMPLICIT Attributes OPTIONAL, + digestEncryptionAlgorithm + DigestEncryptionAlgorithmIdentifier, + encryptedDigest EncryptedDigest, + unauthenticatedAttributes + [1] IMPLICIT Attributes OPTIONAL } + + EncryptedDigest ::= OCTET STRING + + The fields of type SignerInfo have the following meanings: + + o version is the syntax version number. It shall be + 1 for this version of the document. + + o issuerAndSerialNumber specifies the signer's + certificate (and thereby the signer's distinguished name + and public key) by issuer distinguished name and issuer- + specific serial number. + + o digestAlgorithm identifies the message-digest + algorithm (and any associated parameters) under which the + content and authenticated attributes (if present) are + digested. It should be among those in the digestAlgorithms + field of the superior SignerInfo value. The message- + digesting process is described in Section 9.3. + + o authenticatedAttributes is a set of attributes + that are signed (i.e., authenticated) by the signer. The + field is optional, but it must be present if the content + type of the ContentInfo value being signed is not data. If + the field is present, it must contain, at a minimum, two + attributes: + + + + +Kaliski Informational [Page 13] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 1. A PKCS #9 content-type attribute having + as its value the content type of the + ContentInfo value being signed. + + 2. A PKCS #9 message-digest attribute, + having as its value the message digest + of the content (see below). + + Other attribute types that might be useful here, such as + signing time, are also defined in PKCS #9. + + o digestEncryptionAlgorithm identifies the digest- + encryption algorithm (and any associated parameters) under + which the message digest and associated information are + encrypted with the signer's private key. The digest- + encryption process is described in Section 9.4. + + o encryptedDigest is the result of encrypting the + message digest and associated information with the signer's + private key. + + o unauthenticatedAttributes is a set of attributes + that are not signed (i.e., authenticated) by the signer. + The field is optional. Attribute types that might be useful + here, such as countersignatures, are defined in PKCS #9. + + Notes. + + 1. It is recommended in the interest of PEM + compatibility that the authenticatedAttributes field be + omitted whenever the content type of the ContentInfo value + being signed is data and there are no other authenticated + attributes. + + 2. The difference between version 1 SignerInfo and + version 0 SignerInfo (defined in PKCS #7, Version 1.4) is + in the message-digest encryption process (see Section 9.4). + Only the PEM-compatible processes are different, reflecting + changes in Privacy-Enhanced Mail signature methods. There + is no difference in the non-PEM-compatible message-digest + encryption process. + + It is suggested that PKCS implementations generate only + version 1 SignedData values. Since the PEM signature method + with which version 0 is compatible is obsolescent, it is + suggested that PKCS implementations be prepared to receive + only version 1 SignedData values. + + + + +Kaliski Informational [Page 14] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +9.3 Message-digesting process + + The message-digesting process computes a message digest on either the + content being signed or the content together with the signer's + authenticated attributes. In either case, the initial input to the + message-digesting process is the "value" of the content being signed. + Specifically, the initial input is the contents octets of the DER + encoding of the content field of the ContentInfo value to which the + signing process is applied. Only the contents octets of the DER + encoding of that field are digested, not the identifier octets or the + length octets. + + The result of the message-digesting process (which is called, + informally, the "message digest") depends on whether the + authenticatedAttributes field is present. When the field is absent, + the result is just the message digest of the content. When the field + is present, however, the result is the message digest of the complete + DER encoding of the Attributes value containted in the + authenticatedAttributes field. (For clarity: The IMPLICIT [0] tag in + the authenticatedAttributes field is not part of the Attributes + value. The Attributes value's tag is SET OF, and the DER encoding of + the SET OF tag, rather than of the IMPLICIT [0] tag, is to be + digested along with the length and contents octets of the Attributes + value.) Since the Attributes value, when the field is present, must + contain as attributes the content type and the message digest of the + content, those values are indirectly included in the result. + + When the content being signed has content type data and the + authenticatedAttributes field is absent, then just the value of the + data (e.g., the contents of a file) is digested. This has the + advantage that the length of the content being signed need not be + known in advance of the encryption process. This method is compatible + with Privacy-Enhanced Mail. + + Although the identifier octets and the length octets are not + digested, they are still protected by other means. The length octets + are protected by the nature of the message-digest algorithm since it + is by assumption computationally infeasible to find any two distinct + messages of any length that have the same message digest. + Furthermore, assuming that the content type uniquely determines the + identifier octets, the identifier octets are protected implicitly in + one of two ways: either by the inclusion of the content type in the + authenticated attributes, or by the use of the PEM-compatible + alternative in Section 9.4 which implies that the content type is + data. + + + + + + +Kaliski Informational [Page 15] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + Note. The fact that the message digest is computed on part of a DER + encoding does not mean that DER is the required method of + representing that part for data transfer. Indeed, it is expected that + some implementations of this document may store objects in other than + their DER encodings, but such practices do not affect message-digest + computation. + +9.4 Digest-encryption process + + The input to the digest-encryption process--the value supplied to the + signer's digest-encryption algorithm--includes the result of the + message-digesting process (informally, the "message digest") and the + digest algorithm identifier (or object identifier). The result of the + digest-encryption process is the encryption with the signer's private + key of the BER encoding of a value of type DigestInfo: + + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest } + + Digest ::= OCTET STRING + + The fields of type DigestInfo have the following meanings: + + o digestAlgorithm identifies the message-digest + algorithm (and any associated parameters) under which the + content and authenticated attributes are digested. It + should be the same as the digestAlgorithm field of the + superior SignerInfo value. + + o digest is the result of the message-digesting + process. + + Notes. + + 1. The only difference between the signature process + defined here and the signature algorithms defined in PKCS + #1 is that signatures there are represented as bit strings, + for consistency with the X.509 SIGNED macro. Here, + encrypted message digests are octet strings. + + 2. The input to the encryption process typically will + have 30 or fewer octets. If digestEncryptionAlgorithm is + PKCS #1's rsaEncryption, then this means that the input can + be encrypted in a single block as long as the length of the + RSA modulus is at least 328 bits, which is reasonable and + consistent with security recommendations. + + + + +Kaliski Informational [Page 16] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 3. A message-digest algorithm identifier is included + in the DigestInfo value to limit the damage resulting from + the compromise of one message-digest algorithm. For + instance, suppose an adversary were able to find messages + with a given MD2 message digest. That adversary could then + forge a signature by finding a message with the same MD2 + message digest as one that a signer previously signed, and + presenting the previous signature as the signature on the + new message. This attack would succeed only if the signer + previously used MD2, since the DigestInfo value contains + the message-digest algorithm. If a signer never trusted + the MD2 algorithm and always used MD5, then the compromise + of MD2 would not affect the signer. If the DigestInfo value + contained only the message digest, however, the compromise + of MD2 would affect signers that use any message-digest + algorithm. + + 4. There is potential for ambiguity due to the fact + that the DigestInfo value does not indicate whether the + digest field contains just the message digest of the + content or the message digest of the complete DER encoding + of the authenticatedAttributes field. In other words, it is + possible for an adversary to transform a signature on + authenticated attributes to one that appears to be just on + content by changing the content to be the DER encoding of + the authenticatedAttributes field, and then removing the + authenticatedAttributes field. (The reverse transformation + is possible, but requires that the content be the DER + encoding of an authenticated attributes value, which is + unlikely.) This ambiguity is not a new problem, nor is it a + significant one, as context will generally prevent misuse. + Indeed, it is also possible for an adversary to transform a + signature on a certificate or certificate-revocation list + to one that appears to be just on signed-data content. + +9.5 Compatibility with Privacy-Enhanced Mail + + Compatibility with the MIC-ONLY and MIC-CLEAR process types in PEM + occurs when the content type of the ContentInfo value being signed is + data, there are no authenticated attributes, the message-digest + algorithm is md2 or md5, and the digest-encryption algorithm is PKCS + #1's rsaEncryption. Under all those conditions, the encrypted message + digest produced here matches the one produced in PEM because: + + 1. The value input to the message-digest algorithm in + PEM is the same as in this document when there are no + authenticated attributes. MD2 and MD5 in PEM are the same + as md2 and md5. + + + +Kaliski Informational [Page 17] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 2. The value encrypted with the signer's private key + in PEM (as specified in RFC 1423) is the same as in this + document when there are no authenticated attributes. RSA + private-key encryption in PEM is the same as PKCS #1's + rsaEncryption. + + The other parts of the signed-data content type (certificates, CRLs, + algorithm identifiers, etc.) are easily translated to and from their + corresponding PEM components. + +10. Enveloped-data content type + + The enveloped-data content type consists of encrypted content of any + type and encrypted content-encryption keys for one or more + recipients. The combination of encrypted content and encrypted + content-encryption key for a recipient is a "digital envelope" for + that recipient. Any type of content can be enveloped for any number + of recipients in parallel. + + It is expected that the typical application of the enveloped-data + content type will be to represent one or more recipients' digital + envelopes on content of the data, digested-data, or signed-data + content types. + + The process by which enveloped data is constructed involves the + following steps: + + 1. A content-encryption key for a particular content- + encryption algorithm is generated at random. + + 2. For each recipient, the content-encryption key is + encrypted with the recipient's public key. + + 3. For each recipient, the encrypted content- + encryption key and other recipient-specific information are + collected into a RecipientInfo value, defined in Section + 10.2. + + 4. The content is encrypted with the content- + encryption key. (Content encryption may require that the + content be padded to a multiple of some block size; see + Section 10.3 for discussion.) + + 5. The RecipientInfo values for all the recipients + are collected together with the encrypted content into a + EnvelopedData value, defined in Section 10.1. + + + + + +Kaliski Informational [Page 18] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + A recipient opens the envelope by decrypting the one of the encrypted + content-encryption keys with the recipient's private key and + decrypting the encrypted content with the recovered content- + encryption key. The recipient's private key is referenced by an + issuer distinguished name and an issuer-specific serial number that + uniquely identify the certificate for the corresponding public key. + + This section is divided into four parts. The first part describes the + top-level type EnvelopedData, the second part describes the per- + recipient information type RecipientInfo, and the third and fourth + parts describe the content-encryption and key-encryption processes. + + This content type is not compatible with Privacy-Enhanced Mail + (although some processes it defines are compatible with their PEM + counterparts), since Privacy-Enhanced Mail always involves digital + signatures, never digital envelopes alone. + +10.1 EnvelopedData type + + The enveloped-data content type shall have ASN.1 type EnvelopedData: + + EnvelopedData ::= SEQUENCE { + version Version, + recipientInfos RecipientInfos, + encryptedContentInfo EncryptedContentInfo } + + RecipientInfos ::= SET OF RecipientInfo + + EncryptedContentInfo ::= SEQUENCE { + contentType ContentType, + contentEncryptionAlgorithm + ContentEncryptionAlgorithmIdentifier, + encryptedContent + [0] IMPLICIT EncryptedContent OPTIONAL } + + EncryptedContent ::= OCTET STRING + + The fields of type EnvelopedData have the following meanings: + + o version is the syntax version number. It shall be + 0 for this version of the document. + + o recipientInfos is a collection of per-recipient + information. There must be at least one element in + the collection. + + o encryptedContentInfo is the encrypted content + information. + + + +Kaliski Informational [Page 19] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + The fields of type EncryptedContentInfo have the following meanings: + + o contentType indicates the type of content. + + o contentEncryptionAlgorithm identifies the content- + encryption algorithm (and any associated + parameters) under which the content is encrypted. + The content-encryption process is described in + Section 10.3. This algorithm is the same for all + recipients. + + o encryptedContent is the result of encrypting the + content. The field is optional, and if the field + is not present, its intended value must be + supplied by other means. + + Note. The fact that the recipientInfos field comes before the + encryptedContentInfo field makes it possible to process an + EnvelopedData value in a single pass. (Single-pass processing is + described in Section 5.) + +10.2 RecipientInfo type + + Per-recipient information is represented in the type RecipientInfo: + + RecipientInfo ::= SEQUENCE { + version Version, + issuerAndSerialNumber IssuerAndSerialNumber, + keyEncryptionAlgorithm + + KeyEncryptionAlgorithmIdentifier, + encryptedKey EncryptedKey } + + EncryptedKey ::= OCTET STRING + + The fields of type RecipientInfo have the following meanings: + + o version is the syntax version number. It shall be + 0 for this version of the document. + + o issuerAndSerialNumber specifies the recipient's + certificate (and thereby the recipient's + distinguished name and public key) by issuer + distinguished name and issuer-specific serial + number. + + + + + + +Kaliski Informational [Page 20] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + o keyEncryptionAlgorithm identifies the key- + encryption algorithm (and any associated + parameters) under which the content-encryption key + is encrypted with the recipient's public key. The + key-encryption process is described in Section + 10.4. + + o encryptedKey is the result of encrypting the + content-encryption key with the recipient's public + key (see below). + +10.3 Content-encryption process + + The input to the content-encryption process is the "value" of the + content being enveloped. Specifically, the input is the contents + octets of a definite-length BER encoding of the content field of the + ContentInfo value to which the enveloping process is applied. Only + the contents octets of the BER encoding are encrypted, not the + identifier octets or length octets; those other octets are not + represented at all. + + When the content being enveloped has content type data, then just the + value of the data (e.g., the contents of a file) is encrypted. This + has the advantage that the length of the content being encrypted need + not be known in advance of the encryption process. This method is + compatible with Privacy-Enhanced Mail. + + The identifier octets and the length octets are not encrypted. The + length octets may be protected implicitly by the encryption process, + depending on the encryption algorithm. The identifier octets are not + protected at all, although they can be recovered from the content + type, assuming that the content type uniquely determines the + identifier octets. Explicit protection of the identifier and length + octets requires that the signed-and-enveloped-data content type be + employed, or that the digested-data and enveloped-data content types + be applied in succession. + + Notes. + + 1. The reason that a definite-length BER encoding is + required is that the bit indicating whether the length is + definite or indefinite is not recorded anywhere in the + enveloped-data content type. Definite-length encoding is + more appropriate for simple types such as octet strings, so + definite-length encoding is chosen. + + + + + + +Kaliski Informational [Page 21] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 2. Some content-encryption algorithms assume the + input length is a multiple of k octets, where k > 1, and + let the application define a method for handling inputs + whose lengths are not a multiple of k octets. For such + algorithms, the method shall be to pad the input at the + trailing end with k - (l mod k) octets all having value k - + (l mod k), where l is the length of the input. In other + words, the input is padded at the trailing end with one of + the following strings: + + 01 -- if l mod k = k-1 + 02 02 -- if l mod k = k-2 + . + . + . + k k ... k k -- if l mod k = 0 + + The padding can be removed unambiguously since all input is + padded and no padding string is a suffix of another. This + padding method is well-defined if and only if k < 256; + methods for larger k are an open issue for further study. + +10.4 Key-encryption process + + The input to the key-encryption process--the value supplied to the + recipient's key-encryption algorithm--is just the "value" of the + content-encryption key. + +11. Signed-and-enveloped-data content type + + This section defines the signed-and-enveloped-data content type. For + brevity, much of this section is expressed in terms of material in + Sections 9 and 10. + + The signed-and-enveloped-data content type consists of encrypted + content of any type, encrypted content-encryption keys for one or + more recipients, and doubly encrypted message digests for one or more + signers. The "double encryption" consists of an encryption with a + signer's private key followed by an encryption with the content- + encryption key. + + The combination of encrypted content and encrypted content-encryption + key for a recipient is a "digital envelope" for that recipient. The + recovered singly encrypted message digest for a signer is a "digital + signature" on the recovered content for that signer. Any type of + content can be enveloped for any number of recipients and signed by + any number of signers in parallel. + + + + +Kaliski Informational [Page 22] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + It is expected that the typical application of the signed-and- + enveloped-data content type will be to represent one signer's digital + signature and one or more recipients' digital envelopes on content of + the data content type. + + The process by which signed-and-enveloped data is constructed + involves the following steps: + + 1. A content-encryption key for a particular content- + encryption algorithm is generated at random. + + 2. For each recipient, the content-encryption key is + encrypted with the recipient's public key. + + 3. For each recipient, the encrypted content- + encryption key and other recipient-specific + information are collected into a RecipientInfo + value, defined in Section 10.2. + + 4. For each signer, a message digest is computed on + the content with a signer-specific message-digest + algorithm. (If two signers employ the same message- + digest algorithm, then the message digest need be + computed for only one of them.) + + 5. For each signer, the message digest and associated + information are encrypted with the signer's + private key, and the result is encrypted with the + content-encryption key. (The second encryption may + require that the result of the first encryption be + padded to a multiple of some block size; see + Section 10.3 for discussion.) + + 6. For each signer, the doubly encrypted message + digest and other signer-specific information are + collected into a SignerInfo value, defined in + Section 9.2. + + 7. The content is encrypted with the content- + encryption key. (See Section 10.3 for discussion.) + + 8. The message-digest algorithms for all the signers, + the SignerInfo values for all the signers and the + RecipientInfo values for all the recipients are + collected together with the encrypted content into + a SignedAndEnvelopedData value, defined in Section + 11.1. + + + + +Kaliski Informational [Page 23] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + A recipient opens the envelope and verifies the signatures in two + steps. First, the one of the encrypted content-encryption keys is + decrypted with the recipient's private key, and the encrypted content + is decrypted with the recovered content-encryption key. Second, the + doubly encrypted message digest for each signer is decrypted with the + recovered content-encryption key, the result is decrypted with the + signer's public key, and the recovered message digest is compared to + an independently computed message digest. + + Recipient private keys and signer public keys are contained or + referenced as discussed in Sections 9 and 10. + + This section is divided into three parts. The first part describes + the top-level type SignedAndEnvelopedData and the second part + describes the digest-encryption process. Other types and processes + are the same as in Sections 9 and 10. The third part summarizes + compatibility with Privacy-Enhanced Mail. + + Note. The signed-and-enveloped-data content type provides + cryptographic enhancements similar to those resulting from the + sequential combination of signed-data and enveloped-data content + types. However, since the signed-and-enveloped-data content type does + not have authenticated or unauthenticated attributes, nor does it + provide enveloping of signer information other than the signature, + the sequential combination of signed-data and enveloped-data content + types is generally preferable to the SignedAndEnvelopedData content + type, except when compatibility with the ENCRYPTED process type in + Privacy-Enhanced Mail in intended. + +11.1 SignedAndEnvelopedData type + + The signed-and-enveloped-data content type shall have ASN.1 type + SignedAndEnvelopedData: + + SignedAndEnvelopedData ::= SEQUENCE { + version Version, + recipientInfos RecipientInfos, + digestAlgorithms DigestAlgorithmIdentifiers, + encryptedContentInfo EncryptedContentInfo, + certificates + [0] IMPLICIT ExtendedCertificatesAndCertificates + OPTIONAL, + crls + [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos } + + + + + + +Kaliski Informational [Page 24] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + The fields of type SignedAndEnvelopedData have the following + meanings: + + o version is the syntax version number. It shall be + 1 for this version of the document. + + o recipientInfos is a collection of per-recipient + information, as in Section 10. There must be at + least one element in the collection. + + o digestAlgorithms is a collection of message-digest + algorithm identifiers, as in Section 9. The + message-digesting process is the same as in + Section 9 in the case when there are no + authenticated attributes. + + o encryptedContentInfo is the encrypted content, as + in Section 10. It can have any of the defined + content types. + + o certificates is a set of PKCS #6 extended + certificates and X.509 certificates, as in Section + 9. + + o crls is a set of certificate-revocation lists, as + in Section 9. + + o signerInfos is a collection of per-signer + information. There must be at least one element in + the collection. SignerInfo values have the same + meaning as in Section 9 with the exception of the + encryptedDigest field (see below). + + Notes. + + 1. The fact that the recipientInfos and + digestAlgorithms fields come before the contentInfo field + and the signerInfos field comes after it makes it possible + to process a SignedAndEnvelopedData value in a single pass. + (Single-pass processing is described in Section 5.) + + 2. The difference between version 1 + SignedAndEnvelopedData and version 0 SignedAndEnvelopedData + (defined in PKCS #7, Version 1.4) is that the crls field is + allowed in version 1, but not in version 0. Except for the + difference in version number, version 0 + SignedAndEnvelopedData values are acceptable as version 1 + values. An implementation can therefore process + + + +Kaliski Informational [Page 25] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + SignedAndEnvelopedData values of either version as though + they were version 1 values. It is suggested that PKCS + implementations generate only version 1 + SignedAndEnvelopedData values, but be prepared to process + SignedAndEnvelopedData values of either version. + +11.2 Digest-encryption process + + The input to the digest-encryption process is the same as in Section + 9, but the process itself is different. Specifically, the process + involves two steps. First, the input to the process is supplied to + the signer's digest-encryption algorithm, as in Section 9. Second, + the result of the first step is encrypted with the content-encryption + key. There is no DER encoding between the two steps; the "value" + output by the first step is input directly to the second step. (See + Section 10.3 for discussion.) + + This process is compatible with the ENCRYPTED process type in + Privacy-Enhanced Mail. + + Note. The purpose of the second step is to prevent an adversary from + recovering the message digest of the content. Otherwise, an + adversary would be able to determine which of a list of candidate + contents (e.g., "Yes" or "No") is the actual content by comparing the + their message digests to the actual message digest. + +11.3 Compatibility with Privacy-Enhanced Mail + + Compatibility with the ENCRYPTED process type of PEM occurs when the + content type of the ContentInfo value being signed and enveloped is + data, the message-digest algorithm is md2 or md5, the content- + encryption algorithm is DES in CBC mode, the digest-encryption + algorithm is PKCS #1's rsaEncryption, and the key-encryption + algorithm is PKCS #1's rsaEncryption. Under all those conditions, + the doubly encrypted message digest and the encrypted content + encryption key match the ones produced in PEM because of reasons + similar to those given in Section 9.5, as well as the following: + + 1. The value input to the content-encryption + algorithm in PEM is the same as in this document. + DES in CBC mode is the same as desCBC. + + 2. The value input to the key-encryption algorithm in + PEM is the same as in this document (see Section + 10.4). RSA public-key encryption in PEM is the + same as PKCS #1's rsaEncryption. + + + + + +Kaliski Informational [Page 26] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + 3. The double-encryption process applied to the + message digest in this document and in PEM are the + same. + + The other parts of the signed-and-enveloped-data content type + (certificates, CRLs, algorithm identifiers, etc.) are easily + translated to and from their corresponding PEM components. (CRLs are + carried in a separate PEM message.) + +12. Digested-data content type + + The digested-data content type consists of content of any type and a + message digest of the content. + + It is expected that the typical application of the digested-data + content type will be to add integrity to content of the data content + type, and that the result would become the content input to the + enveloped-data content type. + + The process by which digested-data is constructed involves the + following steps: + + 1. A message digest is computed on the content with a + message-digest algorithm. + + 2. The message-digest algorithm and the message + digest are collected together with the content + into a DigestedData value. + + A recipient verifies the message digest by comparing the message + digest to an independently computed message digest. + + The digested-data content type shall have ASN.1 type DigestedData: + + DigestedData ::= SEQUENCE { + version Version, + digestAlgorithm DigestAlgorithmIdentifier, + contentInfo ContentInfo, + digest Digest } + + Digest ::= OCTET STRING + + The fields of type DigestedData have the following meanings: + + o version is the syntax version number. It shall be + 0 for this version of the document. + + + + + +Kaliski Informational [Page 27] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + o digestAlgorithm identifies the message-digest + algorithm (and any associated parameters) under which the + content is digested. (The message-digesting process is the + same as in Section 9 in the case when there are no + authenticated attributes.) + + o contentInfo is the content that is digested. It + can have any of the defined content types. + + o digest is the result of the message-digesting process. + + Note. The fact that the digestAlgorithm field comes before the + contentInfo field and the digest field comes after it makes it + possible to process a DigestedData value in a single pass. (Single- + pass processing is described in Section 5.) + +13. Encrypted-data content type + + The encrypted-data content type consists of encrypted content of any + type. Unlike the enveloped-data content type, the encrypted-data + content type has neither recipients nor encrypted content-encryption + keys. Keys are assumed to be managed by other means. + + It is expected that the typical application of the encrypted-data + content type will be to encrypt content of the data content type for + local storage, perhaps where the encryption key is a password. + + The encrypted-data content type shall have ASN.1 type EncryptedData: + + EncryptedData ::= SEQUENCE { + version Version, + encryptedContentInfo EncryptedContentInfo } + + The fields of type EncryptedData have the following meanings: + + o version is the syntax version number. It shall be + 0 for this version of the document. + + o encryptedContentInfo is the encrypted content + information, as in Section 10. + +14. Object identifiers + + This document defines seven object identifiers: pkcs-7, data, + signedData, envelopedData, signedAndEnvelopedData, digestedData, and + encryptedData. + + + + + +Kaliski Informational [Page 28] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + The object identifier pkcs-7 identifies this document. + + pkcs-7 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) US(840) rsadsi(113549) + pkcs(1) 7 } + + The object identifiers data, signedData, envelopedData, + signedAndEnvelopedData, digestedData, and encryptedData, identify, + respectively, the data, signed-data, enveloped-data, signed-and- + enveloped-data, digested-data, and encrypted-data content types + defined in Sections 8-13. + + data OBJECT IDENTIFIER ::= { pkcs-7 1 } + signedData OBJECT IDENTIFIER ::= { pkcs-7 2 } + envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3 } + signedAndEnvelopedData OBJECT IDENTIFIER ::= + { pkcs-7 4 } + digestedData OBJECT IDENTIFIER ::= { pkcs-7 5 } + encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 } + + These object identifiers are intended to be used in the contentType + field of a value of type ContentInfo (see Section 5). The content + field of that type, which has the content-type-specific syntax ANY + DEFINED BY contentType, would have ASN.1 type Data, SignedData, + EnvelopedData, SignedAndEnvelopedData, DigestedData, and + EncryptedData, respectively. These object identifiers are also + intended to be used in a PKCS #9 content-type attribute. + +Security Considerations + + Security issues are discussed throughout this memo. + +Revision history + + + Versions 1.0-1.3 + + Versions 1.0-1.3 were distributed to participants in RSA Data + Security, Inc.'s Public-Key Cryptography Standards meetings in + February and March 1991. + + + Version 1.4 + + Version 1.4 is part of the June 3, 1991 initial public release of + PKCS. Version 1.4 was published as NIST/OSI Implementors' Workshop + document SEC-SIG-91-22. + + + + +Kaliski Informational [Page 29] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + + Version 1.5 + + Version 1.5 incorporates several editorial changes, including updates + to the references and the addition of a revision history. The + following substantive changes were made: + + o Section 6: CertificateRevocationLists type is + added. + + o Section 9.1: SignedData syntax is revised. The new + version allows for the dissemination of + certificate-revocation lists along with + signatures. It also allows for the dissemination + of certificates and certificate-revocation lists + alone, without any signatures. + + o Section 9.2: SignerInfo syntax is revised. The new + version includes a message-digest encryption + process compatible with Privacy-Enhanced Mail as + specified in RFC 1423. + + o Section 9.3: Meaning of "the DER encoding of the + authenticatedAttributes field" is clarified as + "the DER encoding of the Attributes value." + + o Section 10.3: Padding method for content- + encryption algorithms is described. + + o Section 11.1: SignedAndEnvelopedData syntax is + revised. The new version allows for the + dissemination of certificate-revocation lists. + + o Section 13: Encrypted-data content type is added. + This content type consists of encrypted content of + any type. + + o Section 14: encryptedData object identifier is + added. + + Supersedes June 3, 1991 version, which was also published as NIST/OSI + Implementors' Workshop document SEC-SIG-91-22. + + + + + + + + + + +Kaliski Informational [Page 30] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +Acknowledgements + + This document is based on a contribution of RSA Laboratories, a + division of RSA Data Security, Inc. Any substantial use of the text + from this document must acknowledge RSA Data Security, Inc. RSA Data + Security, Inc. requests that all material mentioning or referencing + this document identify this as "RSA Data Security, Inc. PKCS #7". + +Author's Address + + Burt Kaliski + RSA Laboratories East + 20 Crosby Drive + Bedford, MA 01730 + + Phone: (617) 687-7000 + EMail: burt@rsa.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Kaliski Informational [Page 31] + +RFC 2315 PKCS #7: Crytographic Message Syntax March 1998 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1998). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Kaliski Informational [Page 32] + diff --git a/docs/rfc/rfc2821.txt b/docs/rfc/rfc2821.txt new file mode 100644 index 00000000..0eac9118 --- /dev/null +++ b/docs/rfc/rfc2821.txt @@ -0,0 +1,4427 @@ + + + + + + +Network Working Group J. Klensin, Editor +Request for Comments: 2821 AT&T Laboratories +Obsoletes: 821, 974, 1869 April 2001 +Updates: 1123 +Category: Standards Track + + + Simple Mail Transfer Protocol + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2001). All Rights Reserved. + +Abstract + + This document is a self-contained specification of the basic protocol + for the Internet electronic mail transport. It consolidates, updates + and clarifies, but doesn't add new or change existing functionality + of the following: + + - the original SMTP (Simple Mail Transfer Protocol) specification of + RFC 821 [30], + + - domain name system requirements and implications for mail + transport from RFC 1035 [22] and RFC 974 [27], + + - the clarifications and applicability statements in RFC 1123 [2], + and + + - material drawn from the SMTP Extension mechanisms [19]. + + It obsoletes RFC 821, RFC 974, and updates RFC 1123 (replaces the + mail transport materials of RFC 1123). However, RFC 821 specifies + some features that were not in significant use in the Internet by the + mid-1990s and (in appendices) some additional transport models. + Those sections are omitted here in the interest of clarity and + brevity; readers needing them should refer to RFC 821. + + + + + + +Klensin Standards Track [Page 1] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + It also includes some additional material from RFC 1123 that required + amplification. This material has been identified in multiple ways, + mostly by tracking flaming on various lists and newsgroups and + problems of unusual readings or interpretations that have appeared as + the SMTP extensions have been deployed. Where this specification + moves beyond consolidation and actually differs from earlier + documents, it supersedes them technically as well as textually. + + Although SMTP was designed as a mail transport and delivery protocol, + this specification also contains information that is important to its + use as a 'mail submission' protocol, as recommended for POP [3, 26] + and IMAP [6]. Additional submission issues are discussed in RFC 2476 + [15]. + + Section 2.3 provides definitions of terms specific to this document. + Except when the historical terminology is necessary for clarity, this + document uses the current 'client' and 'server' terminology to + identify the sending and receiving SMTP processes, respectively. + + A companion document [32] discusses message headers, message bodies + and formats and structures for them, and their relationship. + +Table of Contents + + 1. Introduction .................................................. 4 + 2. The SMTP Model ................................................ 5 + 2.1 Basic Structure .............................................. 5 + 2.2 The Extension Model .......................................... 7 + 2.2.1 Background ................................................. 7 + 2.2.2 Definition and Registration of Extensions .................. 8 + 2.3 Terminology .................................................. 9 + 2.3.1 Mail Objects ............................................... 10 + 2.3.2 Senders and Receivers ...................................... 10 + 2.3.3 Mail Agents and Message Stores ............................. 10 + 2.3.4 Host ....................................................... 11 + 2.3.5 Domain ..................................................... 11 + 2.3.6 Buffer and State Table ..................................... 11 + 2.3.7 Lines ...................................................... 12 + 2.3.8 Originator, Delivery, Relay, and Gateway Systems ........... 12 + 2.3.9 Message Content and Mail Data .............................. 13 + 2.3.10 Mailbox and Address ....................................... 13 + 2.3.11 Reply ..................................................... 13 + 2.4 General Syntax Principles and Transaction Model .............. 13 + 3. The SMTP Procedures: An Overview .............................. 15 + 3.1 Session Initiation ........................................... 15 + 3.2 Client Initiation ............................................ 16 + 3.3 Mail Transactions ............................................ 16 + 3.4 Forwarding for Address Correction or Updating ................ 19 + + + +Klensin Standards Track [Page 2] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + 3.5 Commands for Debugging Addresses ............................. 20 + 3.5.1 Overview ................................................... 20 + 3.5.2 VRFY Normal Response ....................................... 22 + 3.5.3 Meaning of VRFY or EXPN Success Response ................... 22 + 3.5.4 Semantics and Applications of EXPN ......................... 23 + 3.6 Domains ...................................................... 23 + 3.7 Relaying ..................................................... 24 + 3.8 Mail Gatewaying .............................................. 25 + 3.8.1 Header Fields in Gatewaying ................................ 26 + 3.8.2 Received Lines in Gatewaying ............................... 26 + 3.8.3 Addresses in Gatewaying .................................... 26 + 3.8.4 Other Header Fields in Gatewaying .......................... 27 + 3.8.5 Envelopes in Gatewaying .................................... 27 + 3.9 Terminating Sessions and Connections ......................... 27 + 3.10 Mailing Lists and Aliases ................................... 28 + 3.10.1 Alias ..................................................... 28 + 3.10.2 List ...................................................... 28 + 4. The SMTP Specifications ....................................... 29 + 4.1 SMTP Commands ................................................ 29 + 4.1.1 Command Semantics and Syntax ............................... 29 + 4.1.1.1 Extended HELLO (EHLO) or HELLO (HELO) ................... 29 + 4.1.1.2 MAIL (MAIL) .............................................. 31 + 4.1.1.3 RECIPIENT (RCPT) ......................................... 31 + 4.1.1.4 DATA (DATA) .............................................. 33 + 4.1.1.5 RESET (RSET) ............................................. 34 + 4.1.1.6 VERIFY (VRFY) ............................................ 35 + 4.1.1.7 EXPAND (EXPN) ............................................ 35 + 4.1.1.8 HELP (HELP) .............................................. 35 + 4.1.1.9 NOOP (NOOP) .............................................. 35 + 4.1.1.10 QUIT (QUIT) ............................................. 36 + 4.1.2 Command Argument Syntax .................................... 36 + 4.1.3 Address Literals ........................................... 38 + 4.1.4 Order of Commands .......................................... 39 + 4.1.5 Private-use Commands ....................................... 40 + 4.2 SMTP Replies ................................................ 40 + 4.2.1 Reply Code Severities and Theory ........................... 42 + 4.2.2 Reply Codes by Function Groups ............................. 44 + 4.2.3 Reply Codes in Numeric Order .............................. 45 + 4.2.4 Reply Code 502 ............................................. 46 + 4.2.5 Reply Codes After DATA and the Subsequent . .... 46 + 4.3 Sequencing of Commands and Replies ........................... 47 + 4.3.1 Sequencing Overview ........................................ 47 + 4.3.2 Command-Reply Sequences .................................... 48 + 4.4 Trace Information ............................................ 49 + 4.5 Additional Implementation Issues ............................. 53 + 4.5.1 Minimum Implementation ..................................... 53 + 4.5.2 Transparency ............................................... 53 + 4.5.3 Sizes and Timeouts ......................................... 54 + + + +Klensin Standards Track [Page 3] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + 4.5.3.1 Size limits and minimums ................................. 54 + 4.5.3.2 Timeouts ................................................. 56 + 4.5.4 Retry Strategies ........................................... 57 + 4.5.4.1 Sending Strategy ......................................... 58 + 4.5.4.2 Receiving Strategy ....................................... 59 + 4.5.5 Messages with a null reverse-path .......................... 59 + 5. Address Resolution and Mail Handling .......................... 60 + 6. Problem Detection and Handling ................................ 62 + 6.1 Reliable Delivery and Replies by Email ....................... 62 + 6.2 Loop Detection ............................................... 63 + 6.3 Compensating for Irregularities .............................. 63 + 7. Security Considerations ....................................... 64 + 7.1 Mail Security and Spoofing ................................... 64 + 7.2 "Blind" Copies ............................................... 65 + 7.3 VRFY, EXPN, and Security ..................................... 65 + 7.4 Information Disclosure in Announcements ...................... 66 + 7.5 Information Disclosure in Trace Fields ....................... 66 + 7.6 Information Disclosure in Message Forwarding ................. 67 + 7.7 Scope of Operation of SMTP Servers ........................... 67 + 8. IANA Considerations ........................................... 67 + 9. References .................................................... 68 + 10. Editor's Address ............................................. 70 + 11. Acknowledgments .............................................. 70 + Appendices ....................................................... 71 + A. TCP Transport Service ......................................... 71 + B. Generating SMTP Commands from RFC 822 Headers ................. 71 + C. Source Routes ................................................. 72 + D. Scenarios ..................................................... 73 + E. Other Gateway Issues .......................................... 76 + F. Deprecated Features of RFC 821 ................................ 76 + Full Copyright Statement ......................................... 79 + +1. Introduction + + The objective of the Simple Mail Transfer Protocol (SMTP) is to + transfer mail reliably and efficiently. + + SMTP is independent of the particular transmission subsystem and + requires only a reliable ordered data stream channel. While this + document specifically discusses transport over TCP, other transports + are possible. Appendices to RFC 821 describe some of them. + + An important feature of SMTP is its capability to transport mail + across networks, usually referred to as "SMTP mail relaying" (see + section 3.8). A network consists of the mutually-TCP-accessible + hosts on the public Internet, the mutually-TCP-accessible hosts on a + firewall-isolated TCP/IP Intranet, or hosts in some other LAN or WAN + environment utilizing a non-TCP transport-level protocol. Using + + + +Klensin Standards Track [Page 4] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + SMTP, a process can transfer mail to another process on the same + network or to some other network via a relay or gateway process + accessible to both networks. + + In this way, a mail message may pass through a number of intermediate + relay or gateway hosts on its path from sender to ultimate recipient. + The Mail eXchanger mechanisms of the domain name system [22, 27] (and + section 5 of this document) are used to identify the appropriate + next-hop destination for a message being transported. + +2. The SMTP Model + +2.1 Basic Structure + + The SMTP design can be pictured as: + + +----------+ +----------+ + +------+ | | | | + | User |<-->| | SMTP | | + +------+ | Client- |Commands/Replies| Server- | + +------+ | SMTP |<-------------->| SMTP | +------+ + | File |<-->| | and Mail | |<-->| File | + |System| | | | | |System| + +------+ +----------+ +----------+ +------+ + SMTP client SMTP server + + When an SMTP client has a message to transmit, it establishes a two- + way transmission channel to an SMTP server. The responsibility of an + SMTP client is to transfer mail messages to one or more SMTP servers, + or report its failure to do so. + + The means by which a mail message is presented to an SMTP client, and + how that client determines the domain name(s) to which mail messages + are to be transferred is a local matter, and is not addressed by this + document. In some cases, the domain name(s) transferred to, or + determined by, an SMTP client will identify the final destination(s) + of the mail message. In other cases, common with SMTP clients + associated with implementations of the POP [3, 26] or IMAP [6] + protocols, or when the SMTP client is inside an isolated transport + service environment, the domain name determined will identify an + intermediate destination through which all mail messages are to be + relayed. SMTP clients that transfer all traffic, regardless of the + target domain names associated with the individual messages, or that + do not maintain queues for retrying message transmissions that + initially cannot be completed, may otherwise conform to this + specification but are not considered fully-capable. Fully-capable + SMTP implementations, including the relays used by these less capable + + + + +Klensin Standards Track [Page 5] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + ones, and their destinations, are expected to support all of the + queuing, retrying, and alternate address functions discussed in this + specification. + + The means by which an SMTP client, once it has determined a target + domain name, determines the identity of an SMTP server to which a + copy of a message is to be transferred, and then performs that + transfer, is covered by this document. To effect a mail transfer to + an SMTP server, an SMTP client establishes a two-way transmission + channel to that SMTP server. An SMTP client determines the address + of an appropriate host running an SMTP server by resolving a + destination domain name to either an intermediate Mail eXchanger host + or a final target host. + + An SMTP server may be either the ultimate destination or an + intermediate "relay" (that is, it may assume the role of an SMTP + client after receiving the message) or "gateway" (that is, it may + transport the message further using some protocol other than SMTP). + SMTP commands are generated by the SMTP client and sent to the SMTP + server. SMTP replies are sent from the SMTP server to the SMTP + client in response to the commands. + + In other words, message transfer can occur in a single connection + between the original SMTP-sender and the final SMTP-recipient, or can + occur in a series of hops through intermediary systems. In either + case, a formal handoff of responsibility for the message occurs: the + protocol requires that a server accept responsibility for either + delivering a message or properly reporting the failure to do so. + + Once the transmission channel is established and initial handshaking + completed, the SMTP client normally initiates a mail transaction. + Such a transaction consists of a series of commands to specify the + originator and destination of the mail and transmission of the + message content (including any headers or other structure) itself. + When the same message is sent to multiple recipients, this protocol + encourages the transmission of only one copy of the data for all + recipients at the same destination (or intermediate relay) host. + + The server responds to each command with a reply; replies may + indicate that the command was accepted, that additional commands are + expected, or that a temporary or permanent error condition exists. + Commands specifying the sender or recipients may include server- + permitted SMTP service extension requests as discussed in section + 2.2. The dialog is purposely lock-step, one-at-a-time, although this + can be modified by mutually-agreed extension requests such as command + pipelining [13]. + + + + + +Klensin Standards Track [Page 6] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + Once a given mail message has been transmitted, the client may either + request that the connection be shut down or may initiate other mail + transactions. In addition, an SMTP client may use a connection to an + SMTP server for ancillary services such as verification of email + addresses or retrieval of mailing list subscriber addresses. + + As suggested above, this protocol provides mechanisms for the + transmission of mail. This transmission normally occurs directly + from the sending user's host to the receiving user's host when the + two hosts are connected to the same transport service. When they are + not connected to the same transport service, transmission occurs via + one or more relay SMTP servers. An intermediate host that acts as + either an SMTP relay or as a gateway into some other transmission + environment is usually selected through the use of the domain name + service (DNS) Mail eXchanger mechanism. + + Usually, intermediate hosts are determined via the DNS MX record, not + by explicit "source" routing (see section 5 and appendices C and + F.2). + +2.2 The Extension Model + +2.2.1 Background + + In an effort that started in 1990, approximately a decade after RFC + 821 was completed, the protocol was modified with a "service + extensions" model that permits the client and server to agree to + utilize shared functionality beyond the original SMTP requirements. + The SMTP extension mechanism defines a means whereby an extended SMTP + client and server may recognize each other, and the server can inform + the client as to the service extensions that it supports. + + Contemporary SMTP implementations MUST support the basic extension + mechanisms. For instance, servers MUST support the EHLO command even + if they do not implement any specific extensions and clients SHOULD + preferentially utilize EHLO rather than HELO. (However, for + compatibility with older conforming implementations, SMTP clients and + servers MUST support the original HELO mechanisms as a fallback.) + Unless the different characteristics of HELO must be identified for + interoperability purposes, this document discusses only EHLO. + + SMTP is widely deployed and high-quality implementations have proven + to be very robust. However, the Internet community now considers + some services to be important that were not anticipated when the + protocol was first designed. If support for those services is to be + added, it must be done in a way that permits older implementations to + continue working acceptably. The extension framework consists of: + + + + +Klensin Standards Track [Page 7] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + - The SMTP command EHLO, superseding the earlier HELO, + + - a registry of SMTP service extensions, + + - additional parameters to the SMTP MAIL and RCPT commands, and + + - optional replacements for commands defined in this protocol, such + as for DATA in non-ASCII transmissions [33]. + + SMTP's strength comes primarily from its simplicity. Experience with + many protocols has shown that protocols with few options tend towards + ubiquity, whereas protocols with many options tend towards obscurity. + + Each and every extension, regardless of its benefits, must be + carefully scrutinized with respect to its implementation, deployment, + and interoperability costs. In many cases, the cost of extending the + SMTP service will likely outweigh the benefit. + +2.2.2 Definition and Registration of Extensions + + The IANA maintains a registry of SMTP service extensions. A + corresponding EHLO keyword value is associated with each extension. + Each service extension registered with the IANA must be defined in a + formal standards-track or IESG-approved experimental protocol + document. The definition must include: + + - the textual name of the SMTP service extension; + + - the EHLO keyword value associated with the extension; + + - the syntax and possible values of parameters associated with the + EHLO keyword value; + + - any additional SMTP verbs associated with the extension + (additional verbs will usually be, but are not required to be, the + same as the EHLO keyword value); + + - any new parameters the extension associates with the MAIL or RCPT + verbs; + + - a description of how support for the extension affects the + behavior of a server and client SMTP; and, + + - the increment by which the extension is increasing the maximum + length of the commands MAIL and/or RCPT, over that specified in + this standard. + + + + + +Klensin Standards Track [Page 8] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + In addition, any EHLO keyword value starting with an upper or lower + case "X" refers to a local SMTP service extension used exclusively + through bilateral agreement. Keywords beginning with "X" MUST NOT be + used in a registered service extension. Conversely, keyword values + presented in the EHLO response that do not begin with "X" MUST + correspond to a standard, standards-track, or IESG-approved + experimental SMTP service extension registered with IANA. A + conforming server MUST NOT offer non-"X"-prefixed keyword values that + are not described in a registered extension. + + Additional verbs and parameter names are bound by the same rules as + EHLO keywords; specifically, verbs beginning with "X" are local + extensions that may not be registered or standardized. Conversely, + verbs not beginning with "X" must always be registered. + +2.3 Terminology + + 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 below. + + 1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that + the definition is an absolute requirement of the specification. + + 2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the + definition is an absolute prohibition of the specification. + + 3. SHOULD This word, or the adjective "RECOMMENDED", mean that + there may exist valid reasons in particular circumstances to + ignore a particular item, but the full implications must be + understood and carefully weighed before choosing a different + course. + + 4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean + that there may exist valid reasons in particular circumstances + when the particular behavior is acceptable or even useful, but the + full implications should be understood and the case carefully + weighed before implementing any behavior described with this + label. + + 5. MAY This word, or the adjective "OPTIONAL", mean that an item is + truly optional. One vendor may choose to include the item because + a particular marketplace requires it or because the vendor feels + that it enhances the product while another vendor may omit the + same item. An implementation which does not include a particular + option MUST be prepared to interoperate with another + implementation which does include the option, though perhaps with + reduced functionality. In the same vein an implementation which + + + +Klensin Standards Track [Page 9] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + does include a particular option MUST be prepared to interoperate + with another implementation which does not include the option + (except, of course, for the feature the option provides.) + +2.3.1 Mail Objects + + SMTP transports a mail object. A mail object contains an envelope + and content. + + The SMTP envelope is sent as a series of SMTP protocol units + (described in section 3). It consists of an originator address (to + which error reports should be directed); one or more recipient + addresses; and optional protocol extension material. Historically, + variations on the recipient address specification command (RCPT TO) + could be used to specify alternate delivery modes, such as immediate + display; those variations have now been deprecated (see appendix F, + section F.6). + + The SMTP content is sent in the SMTP DATA protocol unit and has two + parts: the headers and the body. If the content conforms to other + contemporary standards, the headers form a collection of field/value + pairs structured as in the message format specification [32]; the + body, if structured, is defined according to MIME [12]. The content + is textual in nature, expressed using the US-ASCII repertoire [1]. + Although SMTP extensions (such as "8BITMIME" [20]) may relax this + restriction for the content body, the content headers are always + encoded using the US-ASCII repertoire. A MIME extension [23] defines + an algorithm for representing header values outside the US-ASCII + repertoire, while still encoding them using the US-ASCII repertoire. + +2.3.2 Senders and Receivers + + In RFC 821, the two hosts participating in an SMTP transaction were + described as the "SMTP-sender" and "SMTP-receiver". This document + has been changed to reflect current industry terminology and hence + refers to them as the "SMTP client" (or sometimes just "the client") + and "SMTP server" (or just "the server"), respectively. Since a + given host may act both as server and client in a relay situation, + "receiver" and "sender" terminology is still used where needed for + clarity. + +2.3.3 Mail Agents and Message Stores + + Additional mail system terminology became common after RFC 821 was + published and, where convenient, is used in this specification. In + particular, SMTP servers and clients provide a mail transport service + and therefore act as "Mail Transfer Agents" (MTAs). "Mail User + Agents" (MUAs or UAs) are normally thought of as the sources and + + + +Klensin Standards Track [Page 10] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + targets of mail. At the source, an MUA might collect mail to be + transmitted from a user and hand it off to an MTA; the final + ("delivery") MTA would be thought of as handing the mail off to an + MUA (or at least transferring responsibility to it, e.g., by + depositing the message in a "message store"). However, while these + terms are used with at least the appearance of great precision in + other environments, the implied boundaries between MUAs and MTAs + often do not accurately match common, and conforming, practices with + Internet mail. Hence, the reader should be cautious about inferring + the strong relationships and responsibilities that might be implied + if these terms were used elsewhere. + +2.3.4 Host + + For the purposes of this specification, a host is a computer system + attached to the Internet (or, in some cases, to a private TCP/IP + network) and supporting the SMTP protocol. Hosts are known by names + (see "domain"); identifying them by numerical address is discouraged. + +2.3.5 Domain + + A domain (or domain name) consists of one or more dot-separated + components. These components ("labels" in DNS terminology [22]) are + restricted for SMTP purposes to consist of a sequence of letters, + digits, and hyphens drawn from the ASCII character set [1]. Domain + names are used as names of hosts and of other entities in the domain + name hierarchy. For example, a domain may refer to an alias (label + of a CNAME RR) or the label of Mail eXchanger records to be used to + deliver mail instead of representing a host name. See [22] and + section 5 of this specification. + + The domain name, as described in this document and in [22], is the + entire, fully-qualified name (often referred to as an "FQDN"). A + domain name that is not in FQDN form is no more than a local alias. + Local aliases MUST NOT appear in any SMTP transaction. + +2.3.6 Buffer and State Table + + SMTP sessions are stateful, with both parties carefully maintaining a + common view of the current state. In this document we model this + state by a virtual "buffer" and a "state table" on the server which + may be used by the client to, for example, "clear the buffer" or + "reset the state table," causing the information in the buffer to be + discarded and the state to be returned to some previous state. + + + + + + + +Klensin Standards Track [Page 11] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +2.3.7 Lines + + SMTP commands and, unless altered by a service extension, message + data, are transmitted in "lines". Lines consist of zero or more data + characters terminated by the sequence ASCII character "CR" (hex value + 0D) followed immediately by ASCII character "LF" (hex value 0A). + This termination sequence is denoted as in this document. + Conforming implementations MUST NOT recognize or generate any other + character or character sequence as a line terminator. Limits MAY be + imposed on line lengths by servers (see section 4.5.3). + + In addition, the appearance of "bare" "CR" or "LF" characters in text + (i.e., either without the other) has a long history of causing + problems in mail implementations and applications that use the mail + system as a tool. SMTP client implementations MUST NOT transmit + these characters except when they are intended as line terminators + and then MUST, as indicated above, transmit them only as a + sequence. + +2.3.8 Originator, Delivery, Relay, and Gateway Systems + + This specification makes a distinction among four types of SMTP + systems, based on the role those systems play in transmitting + electronic mail. An "originating" system (sometimes called an SMTP + originator) introduces mail into the Internet or, more generally, + into a transport service environment. A "delivery" SMTP system is + one that receives mail from a transport service environment and + passes it to a mail user agent or deposits it in a message store + which a mail user agent is expected to subsequently access. A + "relay" SMTP system (usually referred to just as a "relay") receives + mail from an SMTP client and transmits it, without modification to + the message data other than adding trace information, to another SMTP + server for further relaying or for delivery. + + A "gateway" SMTP system (usually referred to just as a "gateway") + receives mail from a client system in one transport environment and + transmits it to a server system in another transport environment. + Differences in protocols or message semantics between the transport + environments on either side of a gateway may require that the gateway + system perform transformations to the message that are not permitted + to SMTP relay systems. For the purposes of this specification, + firewalls that rewrite addresses should be considered as gateways, + even if SMTP is used on both sides of them (see [11]). + + + + + + + + +Klensin Standards Track [Page 12] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +2.3.9 Message Content and Mail Data + + The terms "message content" and "mail data" are used interchangeably + in this document to describe the material transmitted after the DATA + command is accepted and before the end of data indication is + transmitted. Message content includes message headers and the + possibly-structured message body. The MIME specification [12] + provides the standard mechanisms for structured message bodies. + +2.3.10 Mailbox and Address + + As used in this specification, an "address" is a character string + that identifies a user to whom mail will be sent or a location into + which mail will be deposited. The term "mailbox" refers to that + depository. The two terms are typically used interchangeably unless + the distinction between the location in which mail is placed (the + mailbox) and a reference to it (the address) is important. An + address normally consists of user and domain specifications. The + standard mailbox naming convention is defined to be "local- + part@domain": contemporary usage permits a much broader set of + applications than simple "user names". Consequently, and due to a + long history of problems when intermediate hosts have attempted to + optimize transport by modifying them, the local-part MUST be + interpreted and assigned semantics only by the host specified in the + domain part of the address. + +2.3.11 Reply + + An SMTP reply is an acknowledgment (positive or negative) sent from + receiver to sender via the transmission channel in response to a + command. The general form of a reply is a numeric completion code + (indicating failure or success) usually followed by a text string. + The codes are for use by programs and the text is usually intended + for human users. Recent work [34] has specified further structuring + of the reply strings, including the use of supplemental and more + specific completion codes. + +2.4 General Syntax Principles and Transaction Model + + SMTP commands and replies have a rigid syntax. All commands begin + with a command verb. All Replies begin with a three digit numeric + code. In some commands and replies, arguments MUST follow the verb + or reply code. Some commands do not accept arguments (after the + verb), and some reply codes are followed, sometimes optionally, by + free form text. In both cases, where text appears, it is separated + from the verb or reply code by a space character. Complete + definitions of commands and replies appear in section 4. + + + + +Klensin Standards Track [Page 13] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + Verbs and argument values (e.g., "TO:" or "to:" in the RCPT command + and extension name keywords) are not case sensitive, with the sole + exception in this specification of a mailbox local-part (SMTP + Extensions may explicitly specify case-sensitive elements). That is, + a command verb, an argument value other than a mailbox local-part, + and free form text MAY be encoded in upper case, lower case, or any + mixture of upper and lower case with no impact on its meaning. This + is NOT true of a mailbox local-part. The local-part of a mailbox + MUST BE treated as case sensitive. Therefore, SMTP implementations + MUST take care to preserve the case of mailbox local-parts. Mailbox + domains are not case sensitive. In particular, for some hosts the + user "smith" is different from the user "Smith". However, exploiting + the case sensitivity of mailbox local-parts impedes interoperability + and is discouraged. + + A few SMTP servers, in violation of this specification (and RFC 821) + require that command verbs be encoded by clients in upper case. + Implementations MAY wish to employ this encoding to accommodate those + servers. + + The argument field consists of a variable length character string + ending with the end of the line, i.e., with the character sequence + . The receiver will take no action until this sequence is + received. + + The syntax for each command is shown with the discussion of that + command. Common elements and parameters are shown in section 4.1.2. + + Commands and replies are composed of characters from the ASCII + character set [1]. When the transport service provides an 8-bit byte + (octet) transmission channel, each 7-bit character is transmitted + right justified in an octet with the high order bit cleared to zero. + More specifically, the unextended SMTP service provides seven bit + transport only. An originating SMTP client which has not + successfully negotiated an appropriate extension with a particular + server MUST NOT transmit messages with information in the high-order + bit of octets. If such messages are transmitted in violation of this + rule, receiving SMTP servers MAY clear the high-order bit or reject + the message as invalid. In general, a relay SMTP SHOULD assume that + the message content it has received is valid and, assuming that the + envelope permits doing so, relay it without inspecting that content. + Of course, if the content is mislabeled and the data path cannot + accept the actual content, this may result in ultimate delivery of a + severely garbled message to the recipient. Delivery SMTP systems MAY + reject ("bounce") such messages rather than deliver them. No sending + SMTP system is permitted to send envelope commands in any character + + + + + +Klensin Standards Track [Page 14] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + set other than US-ASCII; receiving systems SHOULD reject such + commands, normally using "500 syntax error - invalid character" + replies. + + Eight-bit message content transmission MAY be requested of the server + by a client using extended SMTP facilities, notably the "8BITMIME" + extension [20]. 8BITMIME SHOULD be supported by SMTP servers. + However, it MUST not be construed as authorization to transmit + unrestricted eight bit material. 8BITMIME MUST NOT be requested by + senders for material with the high bit on that is not in MIME format + with an appropriate content-transfer encoding; servers MAY reject + such messages. + + The metalinguistic notation used in this document corresponds to the + "Augmented BNF" used in other Internet mail system documents. The + reader who is not familiar with that syntax should consult the ABNF + specification [8]. Metalanguage terms used in running text are + surrounded by pointed brackets (e.g., ) for clarity. + +3. The SMTP Procedures: An Overview + + This section contains descriptions of the procedures used in SMTP: + session initiation, the mail transaction, forwarding mail, verifying + mailbox names and expanding mailing lists, and the opening and + closing exchanges. Comments on relaying, a note on mail domains, and + a discussion of changing roles are included at the end of this + section. Several complete scenarios are presented in appendix D. + +3.1 Session Initiation + + An SMTP session is initiated when a client opens a connection to a + server and the server responds with an opening message. + + SMTP server implementations MAY include identification of their + software and version information in the connection greeting reply + after the 220 code, a practice that permits more efficient isolation + and repair of any problems. Implementations MAY make provision for + SMTP servers to disable the software and version announcement where + it causes security concerns. While some systems also identify their + contact point for mail problems, this is not a substitute for + maintaining the required "postmaster" address (see section 4.5.1). + + The SMTP protocol allows a server to formally reject a transaction + while still allowing the initial connection as follows: a 554 + response MAY be given in the initial connection opening message + instead of the 220. A server taking this approach MUST still wait + for the client to send a QUIT (see section 4.1.1.10) before closing + the connection and SHOULD respond to any intervening commands with + + + +Klensin Standards Track [Page 15] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + "503 bad sequence of commands". Since an attempt to make an SMTP + connection to such a system is probably in error, a server returning + a 554 response on connection opening SHOULD provide enough + information in the reply text to facilitate debugging of the sending + system. + +3.2 Client Initiation + + Once the server has sent the welcoming message and the client has + received it, the client normally sends the EHLO command to the + server, indicating the client's identity. In addition to opening the + session, use of EHLO indicates that the client is able to process + service extensions and requests that the server provide a list of the + extensions it supports. Older SMTP systems which are unable to + support service extensions and contemporary clients which do not + require service extensions in the mail session being initiated, MAY + use HELO instead of EHLO. Servers MUST NOT return the extended + EHLO-style response to a HELO command. For a particular connection + attempt, if the server returns a "command not recognized" response to + EHLO, the client SHOULD be able to fall back and send HELO. + + In the EHLO command the host sending the command identifies itself; + the command may be interpreted as saying "Hello, I am " (and, + in the case of EHLO, "and I support service extension requests"). + +3.3 Mail Transactions + + There are three steps to SMTP mail transactions. The transaction + starts with a MAIL command which gives the sender identification. + (In general, the MAIL command may be sent only when no mail + transaction is in progress; see section 4.1.4.) A series of one or + more RCPT commands follows giving the receiver information. Then a + DATA command initiates transfer of the mail data and is terminated by + the "end of mail" data indicator, which also confirms the + transaction. + + The first step in the procedure is the MAIL command. + + MAIL FROM: [SP ] + + This command tells the SMTP-receiver that a new mail transaction is + starting and to reset all its state tables and buffers, including any + recipients or mail data. The portion of the first or + only argument contains the source mailbox (between "<" and ">" + brackets), which can be used to report errors (see section 4.2 for a + discussion of error reporting). If accepted, the SMTP server returns + a 250 OK reply. If the mailbox specification is not acceptable for + some reason, the server MUST return a reply indicating whether the + + + +Klensin Standards Track [Page 16] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + failure is permanent (i.e., will occur again if the client tries to + send the same address again) or temporary (i.e., the address might be + accepted if the client tries again later). Despite the apparent + scope of this requirement, there are circumstances in which the + acceptability of the reverse-path may not be determined until one or + more forward-paths (in RCPT commands) can be examined. In those + cases, the server MAY reasonably accept the reverse-path (with a 250 + reply) and then report problems after the forward-paths are received + and examined. Normally, failures produce 550 or 553 replies. + + Historically, the can contain more than just a + mailbox, however, contemporary systems SHOULD NOT use source routing + (see appendix C). + + The optional are associated with negotiated SMTP + service extensions (see section 2.2). + + The second step in the procedure is the RCPT command. + + RCPT TO: [ SP ] + + The first or only argument to this command includes a forward-path + (normally a mailbox and domain, always surrounded by "<" and ">" + brackets) identifying one recipient. If accepted, the SMTP server + returns a 250 OK reply and stores the forward-path. If the recipient + is known not to be a deliverable address, the SMTP server returns a + 550 reply, typically with a string such as "no such user - " and the + mailbox name (other circumstances and reply codes are possible). + This step of the procedure can be repeated any number of times. + + The can contain more than just a mailbox. + Historically, the can be a source routing list of + hosts and the destination mailbox, however, contemporary SMTP clients + SHOULD NOT utilize source routes (see appendix C). Servers MUST be + prepared to encounter a list of source routes in the forward path, + but SHOULD ignore the routes or MAY decline to support the relaying + they imply. Similarly, servers MAY decline to accept mail that is + destined for other hosts or systems. These restrictions make a + server useless as a relay for clients that do not support full SMTP + functionality. Consequently, restricted-capability clients MUST NOT + assume that any SMTP server on the Internet can be used as their mail + processing (relaying) site. If a RCPT command appears without a + previous MAIL command, the server MUST return a 503 "Bad sequence of + commands" response. The optional are associated + with negotiated SMTP service extensions (see section 2.2). + + The third step in the procedure is the DATA command (or some + alternative specified in a service extension). + + + +Klensin Standards Track [Page 17] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + DATA + + If accepted, the SMTP server returns a 354 Intermediate reply and + considers all succeeding lines up to but not including the end of + mail data indicator to be the message text. When the end of text is + successfully received and stored the SMTP-receiver sends a 250 OK + reply. + + Since the mail data is sent on the transmission channel, the end of + mail data must be indicated so that the command and reply dialog can + be resumed. SMTP indicates the end of the mail data by sending a + line containing only a "." (period or full stop). A transparency + procedure is used to prevent this from interfering with the user's + text (see section 4.5.2). + + The end of mail data indicator also confirms the mail transaction and + tells the SMTP server to now process the stored recipients and mail + data. If accepted, the SMTP server returns a 250 OK reply. The DATA + command can fail at only two points in the protocol exchange: + + - If there was no MAIL, or no RCPT, command, or all such commands + were rejected, the server MAY return a "command out of sequence" + (503) or "no valid recipients" (554) reply in response to the DATA + command. If one of those replies (or any other 5yz reply) is + received, the client MUST NOT send the message data; more + generally, message data MUST NOT be sent unless a 354 reply is + received. + + - If the verb is initially accepted and the 354 reply issued, the + DATA command should fail only if the mail transaction was + incomplete (for example, no recipients), or if resources were + unavailable (including, of course, the server unexpectedly + becoming unavailable), or if the server determines that the + message should be rejected for policy or other reasons. + + However, in practice, some servers do not perform recipient + verification until after the message text is received. These servers + SHOULD treat a failure for one or more recipients as a "subsequent + failure" and return a mail message as discussed in section 6. Using + a "550 mailbox not found" (or equivalent) reply code after the data + are accepted makes it difficult or impossible for the client to + determine which recipients failed. + + When RFC 822 format [7, 32] is being used, the mail data include the + memo header items such as Date, Subject, To, Cc, From. Server SMTP + systems SHOULD NOT reject messages based on perceived defects in the + RFC 822 or MIME [12] message header or message body. In particular, + + + + +Klensin Standards Track [Page 18] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + they MUST NOT reject messages in which the numbers of Resent-fields + do not match or Resent-to appears without Resent-from and/or Resent- + date. + + Mail transaction commands MUST be used in the order discussed above. + +3.4 Forwarding for Address Correction or Updating + + Forwarding support is most often required to consolidate and simplify + addresses within, or relative to, some enterprise and less frequently + to establish addresses to link a person's prior address with current + one. Silent forwarding of messages (without server notification to + the sender), for security or non-disclosure purposes, is common in + the contemporary Internet. + + In both the enterprise and the "new address" cases, information + hiding (and sometimes security) considerations argue against exposure + of the "final" address through the SMTP protocol as a side-effect of + the forwarding activity. This may be especially important when the + final address may not even be reachable by the sender. Consequently, + the "forwarding" mechanisms described in section 3.2 of RFC 821, and + especially the 251 (corrected destination) and 551 reply codes from + RCPT must be evaluated carefully by implementers and, when they are + available, by those configuring systems. + + In particular: + + * Servers MAY forward messages when they are aware of an address + change. When they do so, they MAY either provide address-updating + information with a 251 code, or may forward "silently" and return + a 250 code. But, if a 251 code is used, they MUST NOT assume that + the client will actually update address information or even return + that information to the user. + + Alternately, + + * Servers MAY reject or bounce messages when they are not + deliverable when addressed. When they do so, they MAY either + provide address-updating information with a 551 code, or may + reject the message as undeliverable with a 550 code and no + address-specific information. But, if a 551 code is used, they + MUST NOT assume that the client will actually update address + information or even return that information to the user. + + SMTP server implementations that support the 251 and/or 551 reply + codes are strongly encouraged to provide configuration mechanisms so + that sites which conclude that they would undesirably disclose + information can disable or restrict their use. + + + +Klensin Standards Track [Page 19] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +3.5 Commands for Debugging Addresses + +3.5.1 Overview + + SMTP provides commands to verify a user name or obtain the content of + a mailing list. This is done with the VRFY and EXPN commands, which + have character string arguments. Implementations SHOULD support VRFY + and EXPN (however, see section 3.5.2 and 7.3). + + For the VRFY command, the string is a user name or a user name and + domain (see below). If a normal (i.e., 250) response is returned, + the response MAY include the full name of the user and MUST include + the mailbox of the user. It MUST be in either of the following + forms: + + User Name + local-part@domain + + When a name that is the argument to VRFY could identify more than one + mailbox, the server MAY either note the ambiguity or identify the + alternatives. In other words, any of the following are legitimate + response to VRFY: + + 553 User ambiguous + + or + + 553- Ambiguous; Possibilities are + 553-Joe Smith + 553-Harry Smith + 553 Melvin Smith + + or + + 553-Ambiguous; Possibilities + 553- + 553- + 553 + + Under normal circumstances, a client receiving a 553 reply would be + expected to expose the result to the user. Use of exactly the forms + given, and the "user ambiguous" or "ambiguous" keywords, possibly + supplemented by extended reply codes such as those described in [34], + will facilitate automated translation into other languages as needed. + Of course, a client that was highly automated or that was operating + in another language than English, might choose to try to translate + the response, to return some other indication to the user than the + + + + +Klensin Standards Track [Page 20] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + literal text of the reply, or to take some automated action such as + consulting a directory service for additional information before + reporting to the user. + + For the EXPN command, the string identifies a mailing list, and the + successful (i.e., 250) multiline response MAY include the full name + of the users and MUST give the mailboxes on the mailing list. + + In some hosts the distinction between a mailing list and an alias for + a single mailbox is a bit fuzzy, since a common data structure may + hold both types of entries, and it is possible to have mailing lists + containing only one mailbox. If a request is made to apply VRFY to a + mailing list, a positive response MAY be given if a message so + addressed would be delivered to everyone on the list, otherwise an + error SHOULD be reported (e.g., "550 That is a mailing list, not a + user" or "252 Unable to verify members of mailing list"). If a + request is made to expand a user name, the server MAY return a + positive response consisting of a list containing one name, or an + error MAY be reported (e.g., "550 That is a user name, not a mailing + list"). + + In the case of a successful multiline reply (normal for EXPN) exactly + one mailbox is to be specified on each line of the reply. The case + of an ambiguous request is discussed above. + + "User name" is a fuzzy term and has been used deliberately. An + implementation of the VRFY or EXPN commands MUST include at least + recognition of local mailboxes as "user names". However, since + current Internet practice often results in a single host handling + mail for multiple domains, hosts, especially hosts that provide this + functionality, SHOULD accept the "local-part@domain" form as a "user + name"; hosts MAY also choose to recognize other strings as "user + names". + + The case of expanding a mailbox list requires a multiline reply, such + as: + + C: EXPN Example-People + S: 250-Jon Postel + S: 250-Fred Fonebone + S: 250 Sam Q. Smith + + or + + C: EXPN Executive-Washroom-List + S: 550 Access Denied to You. + + + + + +Klensin Standards Track [Page 21] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + The character string arguments of the VRFY and EXPN commands cannot + be further restricted due to the variety of implementations of the + user name and mailbox list concepts. On some systems it may be + appropriate for the argument of the EXPN command to be a file name + for a file containing a mailing list, but again there are a variety + of file naming conventions in the Internet. Similarly, historical + variations in what is returned by these commands are such that the + response SHOULD be interpreted very carefully, if at all, and SHOULD + generally only be used for diagnostic purposes. + +3.5.2 VRFY Normal Response + + When normal (2yz or 551) responses are returned from a VRFY or EXPN + request, the reply normally includes the mailbox name, i.e., + "", where "domain" is a fully qualified domain + name, MUST appear in the syntax. In circumstances exceptional enough + to justify violating the intent of this specification, free-form text + MAY be returned. In order to facilitate parsing by both computers + and people, addresses SHOULD appear in pointed brackets. When + addresses, rather than free-form debugging information, are returned, + EXPN and VRFY MUST return only valid domain addresses that are usable + in SMTP RCPT commands. Consequently, if an address implies delivery + to a program or other system, the mailbox name used to reach that + target MUST be given. Paths (explicit source routes) MUST NOT be + returned by VRFY or EXPN. + + Server implementations SHOULD support both VRFY and EXPN. For + security reasons, implementations MAY provide local installations a + way to disable either or both of these commands through configuration + options or the equivalent. When these commands are supported, they + are not required to work across relays when relaying is supported. + Since they were both optional in RFC 821, they MUST be listed as + service extensions in an EHLO response, if they are supported. + +3.5.3 Meaning of VRFY or EXPN Success Response + + A server MUST NOT return a 250 code in response to a VRFY or EXPN + command unless it has actually verified the address. In particular, + a server MUST NOT return 250 if all it has done is to verify that the + syntax given is valid. In that case, 502 (Command not implemented) + or 500 (Syntax error, command unrecognized) SHOULD be returned. As + stated elsewhere, implementation (in the sense of actually validating + addresses and returning information) of VRFY and EXPN are strongly + recommended. Hence, implementations that return 500 or 502 for VRFY + are not in full compliance with this specification. + + + + + + +Klensin Standards Track [Page 22] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + There may be circumstances where an address appears to be valid but + cannot reasonably be verified in real time, particularly when a + server is acting as a mail exchanger for another server or domain. + "Apparent validity" in this case would normally involve at least + syntax checking and might involve verification that any domains + specified were ones to which the host expected to be able to relay + mail. In these situations, reply code 252 SHOULD be returned. These + cases parallel the discussion of RCPT verification discussed in + section 2.1. Similarly, the discussion in section 3.4 applies to the + use of reply codes 251 and 551 with VRFY (and EXPN) to indicate + addresses that are recognized but that would be forwarded or bounced + were mail received for them. Implementations generally SHOULD be + more aggressive about address verification in the case of VRFY than + in the case of RCPT, even if it takes a little longer to do so. + +3.5.4 Semantics and Applications of EXPN + + EXPN is often very useful in debugging and understanding problems + with mailing lists and multiple-target-address aliases. Some systems + have attempted to use source expansion of mailing lists as a means of + eliminating duplicates. The propagation of aliasing systems with + mail on the Internet, for hosts (typically with MX and CNAME DNS + records), for mailboxes (various types of local host aliases), and in + various proxying arrangements, has made it nearly impossible for + these strategies to work consistently, and mail systems SHOULD NOT + attempt them. + +3.6 Domains + + Only resolvable, fully-qualified, domain names (FQDNs) are permitted + when domain names are used in SMTP. In other words, names that can + be resolved to MX RRs or A RRs (as discussed in section 5) are + permitted, as are CNAME RRs whose targets can be resolved, in turn, + to MX or A RRs. Local nicknames or unqualified names MUST NOT be + used. There are two exceptions to the rule requiring FQDNs: + + - The domain name given in the EHLO command MUST BE either a primary + host name (a domain name that resolves to an A RR) or, if the host + has no name, an address literal as described in section 4.1.1.1. + + - The reserved mailbox name "postmaster" may be used in a RCPT + command without domain qualification (see section 4.1.1.3) and + MUST be accepted if so used. + + + + + + + + +Klensin Standards Track [Page 23] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +3.7 Relaying + + In general, the availability of Mail eXchanger records in the domain + name system [22, 27] makes the use of explicit source routes in the + Internet mail system unnecessary. Many historical problems with + their interpretation have made their use undesirable. SMTP clients + SHOULD NOT generate explicit source routes except under unusual + circumstances. SMTP servers MAY decline to act as mail relays or to + accept addresses that specify source routes. When route information + is encountered, SMTP servers are also permitted to ignore the route + information and simply send to the final destination specified as the + last element in the route and SHOULD do so. There has been an + invalid practice of using names that do not appear in the DNS as + destination names, with the senders counting on the intermediate + hosts specified in source routing to resolve any problems. If source + routes are stripped, this practice will cause failures. This is one + of several reasons why SMTP clients MUST NOT generate invalid source + routes or depend on serial resolution of names. + + When source routes are not used, the process described in RFC 821 for + constructing a reverse-path from the forward-path is not applicable + and the reverse-path at the time of delivery will simply be the + address that appeared in the MAIL command. + + A relay SMTP server is usually the target of a DNS MX record that + designates it, rather than the final delivery system. The relay + server may accept or reject the task of relaying the mail in the same + way it accepts or rejects mail for a local user. If it accepts the + task, it then becomes an SMTP client, establishes a transmission + channel to the next SMTP server specified in the DNS (according to + the rules in section 5), and sends it the mail. If it declines to + relay mail to a particular address for policy reasons, a 550 response + SHOULD be returned. + + Many mail-sending clients exist, especially in conjunction with + facilities that receive mail via POP3 or IMAP, that have limited + capability to support some of the requirements of this specification, + such as the ability to queue messages for subsequent delivery + attempts. For these clients, it is common practice to make private + arrangements to send all messages to a single server for processing + and subsequent distribution. SMTP, as specified here, is not ideally + suited for this role, and work is underway on standardized mail + submission protocols that might eventually supercede the current + practices. In any event, because these arrangements are private and + fall outside the scope of this specification, they are not described + here. + + + + + +Klensin Standards Track [Page 24] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + It is important to note that MX records can point to SMTP servers + which act as gateways into other environments, not just SMTP relays + and final delivery systems; see sections 3.8 and 5. + + If an SMTP server has accepted the task of relaying the mail and + later finds that the destination is incorrect or that the mail cannot + be delivered for some other reason, then it MUST construct an + "undeliverable mail" notification message and send it to the + originator of the undeliverable mail (as indicated by the reverse- + path). Formats specified for non-delivery reports by other standards + (see, for example, [24, 25]) SHOULD be used if possible. + + This notification message must be from the SMTP server at the relay + host or the host that first determines that delivery cannot be + accomplished. Of course, SMTP servers MUST NOT send notification + messages about problems transporting notification messages. One way + to prevent loops in error reporting is to specify a null reverse-path + in the MAIL command of a notification message. When such a message + is transmitted the reverse-path MUST be set to null (see section + 4.5.5 for additional discussion). A MAIL command with a null + reverse-path appears as follows: + + MAIL FROM:<> + + As discussed in section 2.4.1, a relay SMTP has no need to inspect or + act upon the headers or body of the message data and MUST NOT do so + except to add its own "Received:" header (section 4.4) and, + optionally, to attempt to detect looping in the mail system (see + section 6.2). + +3.8 Mail Gatewaying + + While the relay function discussed above operates within the Internet + SMTP transport service environment, MX records or various forms of + explicit routing may require that an intermediate SMTP server perform + a translation function between one transport service and another. As + discussed in section 2.3.8, when such a system is at the boundary + between two transport service environments, we refer to it as a + "gateway" or "gateway SMTP". + + Gatewaying mail between different mail environments, such as + different mail formats and protocols, is complex and does not easily + yield to standardization. However, some general requirements may be + given for a gateway between the Internet and another mail + environment. + + + + + + +Klensin Standards Track [Page 25] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +3.8.1 Header Fields in Gatewaying + + Header fields MAY be rewritten when necessary as messages are + gatewayed across mail environment boundaries. This may involve + inspecting the message body or interpreting the local-part of the + destination address in spite of the prohibitions in section 2.4.1. + + Other mail systems gatewayed to the Internet often use a subset of + RFC 822 headers or provide similar functionality with a different + syntax, but some of these mail systems do not have an equivalent to + the SMTP envelope. Therefore, when a message leaves the Internet + environment, it may be necessary to fold the SMTP envelope + information into the message header. A possible solution would be to + create new header fields to carry the envelope information (e.g., + "X-SMTP-MAIL:" and "X-SMTP-RCPT:"); however, this would require + changes in mail programs in foreign environments and might risk + disclosure of private information (see section 7.2). + +3.8.2 Received Lines in Gatewaying + + When forwarding a message into or out of the Internet environment, a + gateway MUST prepend a Received: line, but it MUST NOT alter in any + way a Received: line that is already in the header. + + "Received:" fields of messages originating from other environments + may not conform exactly to this specification. However, the most + important use of Received: lines is for debugging mail faults, and + this debugging can be severely hampered by well-meaning gateways that + try to "fix" a Received: line. As another consequence of trace + fields arising in non-SMTP environments, receiving systems MUST NOT + reject mail based on the format of a trace field and SHOULD be + extremely robust in the light of unexpected information or formats in + those fields. + + The gateway SHOULD indicate the environment and protocol in the "via" + clauses of Received field(s) that it supplies. + +3.8.3 Addresses in Gatewaying + + From the Internet side, the gateway SHOULD accept all valid address + formats in SMTP commands and in RFC 822 headers, and all valid RFC + 822 messages. Addresses and headers generated by gateways MUST + conform to applicable Internet standards (including this one and RFC + 822). Gateways are, of course, subject to the same rules for + handling source routes as those described for other SMTP systems in + section 3.3. + + + + + +Klensin Standards Track [Page 26] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +3.8.4 Other Header Fields in Gatewaying + + The gateway MUST ensure that all header fields of a message that it + forwards into the Internet mail environment meet the requirements for + Internet mail. In particular, all addresses in "From:", "To:", + "Cc:", etc., fields MUST be transformed (if necessary) to satisfy RFC + 822 syntax, MUST reference only fully-qualified domain names, and + MUST be effective and useful for sending replies. The translation + algorithm used to convert mail from the Internet protocols to another + environment's protocol SHOULD ensure that error messages from the + foreign mail environment are delivered to the return path from the + SMTP envelope, not to the sender listed in the "From:" field (or + other fields) of the RFC 822 message. + +3.8.5 Envelopes in Gatewaying + + Similarly, when forwarding a message from another environment into + the Internet, the gateway SHOULD set the envelope return path in + accordance with an error message return address, if supplied by the + foreign environment. If the foreign environment has no equivalent + concept, the gateway must select and use a best approximation, with + the message originator's address as the default of last resort. + +3.9 Terminating Sessions and Connections + + An SMTP connection is terminated when the client sends a QUIT + command. The server responds with a positive reply code, after which + it closes the connection. + + An SMTP server MUST NOT intentionally close the connection except: + + - After receiving a QUIT command and responding with a 221 reply. + + - After detecting the need to shut down the SMTP service and + returning a 421 response code. This response code can be issued + after the server receives any command or, if necessary, + asynchronously from command receipt (on the assumption that the + client will receive it after the next command is issued). + + In particular, a server that closes connections in response to + commands that are not understood is in violation of this + specification. Servers are expected to be tolerant of unknown + commands, issuing a 500 reply and awaiting further instructions from + the client. + + + + + + + +Klensin Standards Track [Page 27] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + An SMTP server which is forcibly shut down via external means SHOULD + attempt to send a line containing a 421 response code to the SMTP + client before exiting. The SMTP client will normally read the 421 + response code after sending its next command. + + SMTP clients that experience a connection close, reset, or other + communications failure due to circumstances not under their control + (in violation of the intent of this specification but sometimes + unavoidable) SHOULD, to maintain the robustness of the mail system, + treat the mail transaction as if a 451 response had been received and + act accordingly. + +3.10 Mailing Lists and Aliases + + An SMTP-capable host SHOULD support both the alias and the list + models of address expansion for multiple delivery. When a message is + delivered or forwarded to each address of an expanded list form, the + return address in the envelope ("MAIL FROM:") MUST be changed to be + the address of a person or other entity who administers the list. + However, in this case, the message header [32] MUST be left + unchanged; in particular, the "From" field of the message header is + unaffected. + + An important mail facility is a mechanism for multi-destination + delivery of a single message, by transforming (or "expanding" or + "exploding") a pseudo-mailbox address into a list of destination + mailbox addresses. When a message is sent to such a pseudo-mailbox + (sometimes called an "exploder"), copies are forwarded or + redistributed to each mailbox in the expanded list. Servers SHOULD + simply utilize the addresses on the list; application of heuristics + or other matching rules to eliminate some addresses, such as that of + the originator, is strongly discouraged. We classify such a pseudo- + mailbox as an "alias" or a "list", depending upon the expansion + rules. + +3.10.1 Alias + + To expand an alias, the recipient mailer simply replaces the pseudo- + mailbox address in the envelope with each of the expanded addresses + in turn; the rest of the envelope and the message body are left + unchanged. The message is then delivered or forwarded to each + expanded address. + +3.10.2 List + + A mailing list may be said to operate by "redistribution" rather than + by "forwarding". To expand a list, the recipient mailer replaces the + pseudo-mailbox address in the envelope with all of the expanded + + + +Klensin Standards Track [Page 28] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + addresses. The return address in the envelope is changed so that all + error messages generated by the final deliveries will be returned to + a list administrator, not to the message originator, who generally + has no control over the contents of the list and will typically find + error messages annoying. + +4. The SMTP Specifications + +4.1 SMTP Commands + +4.1.1 Command Semantics and Syntax + + The SMTP commands define the mail transfer or the mail system + function requested by the user. SMTP commands are character strings + terminated by . The commands themselves are alphabetic + characters terminated by if parameters follow and + otherwise. (In the interest of improved interoperability, SMTP + receivers are encouraged to tolerate trailing white space before the + terminating .) The syntax of the local part of a mailbox must + conform to receiver site conventions and the syntax specified in + section 4.1.2. The SMTP commands are discussed below. The SMTP + replies are discussed in section 4.2. + + A mail transaction involves several data objects which are + communicated as arguments to different commands. The reverse-path is + the argument of the MAIL command, the forward-path is the argument of + the RCPT command, and the mail data is the argument of the DATA + command. These arguments or data objects must be transmitted and + held pending the confirmation communicated by the end of mail data + indication which finalizes the transaction. The model for this is + that distinct buffers are provided to hold the types of data objects, + that is, there is a reverse-path buffer, a forward-path buffer, and a + mail data buffer. Specific commands cause information to be appended + to a specific buffer, or cause one or more buffers to be cleared. + + Several commands (RSET, DATA, QUIT) are specified as not permitting + parameters. In the absence of specific extensions offered by the + server and accepted by the client, clients MUST NOT send such + parameters and servers SHOULD reject commands containing them as + having invalid syntax. + +4.1.1.1 Extended HELLO (EHLO) or HELLO (HELO) + + These commands are used to identify the SMTP client to the SMTP + server. The argument field contains the fully-qualified domain name + of the SMTP client if one is available. In situations in which the + SMTP client system does not have a meaningful domain name (e.g., when + its address is dynamically allocated and no reverse mapping record is + + + +Klensin Standards Track [Page 29] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + available), the client SHOULD send an address literal (see section + 4.1.3), optionally followed by information that will help to identify + the client system. y The SMTP server identifies itself to the SMTP + client in the connection greeting reply and in the response to this + command. + + A client SMTP SHOULD start an SMTP session by issuing the EHLO + command. If the SMTP server supports the SMTP service extensions it + will give a successful response, a failure response, or an error + response. If the SMTP server, in violation of this specification, + does not support any SMTP service extensions it will generate an + error response. Older client SMTP systems MAY, as discussed above, + use HELO (as specified in RFC 821) instead of EHLO, and servers MUST + support the HELO command and reply properly to it. In any event, a + client MUST issue HELO or EHLO before starting a mail transaction. + + These commands, and a "250 OK" reply to one of them, confirm that + both the SMTP client and the SMTP server are in the initial state, + that is, there is no transaction in progress and all state tables and + buffers are cleared. + + Syntax: + + ehlo = "EHLO" SP Domain CRLF + helo = "HELO" SP Domain CRLF + + Normally, the response to EHLO will be a multiline reply. Each line + of the response contains a keyword and, optionally, one or more + parameters. Following the normal syntax for multiline replies, these + keyworks follow the code (250) and a hyphen for all but the last + line, and the code and a space for the last line. The syntax for a + positive response, using the ABNF notation and terminal symbols of + [8], is: + + ehlo-ok-rsp = ( "250" domain [ SP ehlo-greet ] CRLF ) + / ( "250-" domain [ SP ehlo-greet ] CRLF + *( "250-" ehlo-line CRLF ) + "250" SP ehlo-line CRLF ) + + ehlo-greet = 1*(%d0-9 / %d11-12 / %d14-127) + ; string of any characters other than CR or LF + + ehlo-line = ehlo-keyword *( SP ehlo-param ) + + ehlo-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-") + ; additional syntax of ehlo-params depends on + ; ehlo-keyword + + + + +Klensin Standards Track [Page 30] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + ehlo-param = 1*(%d33-127) + ; any CHAR excluding and all + ; control characters (US-ASCII 0-31 inclusive) + + Although EHLO keywords may be specified in upper, lower, or mixed + case, they MUST always be recognized and processed in a case- + insensitive manner. This is simply an extension of practices + specified in RFC 821 and section 2.4.1. + +4.1.1.2 MAIL (MAIL) + + This command is used to initiate a mail transaction in which the mail + data is delivered to an SMTP server which may, in turn, deliver it to + one or more mailboxes or pass it on to another system (possibly using + SMTP). The argument field contains a reverse-path and may contain + optional parameters. In general, the MAIL command may be sent only + when no mail transaction is in progress, see section 4.1.4. + + The reverse-path consists of the sender mailbox. Historically, that + mailbox might optionally have been preceded by a list of hosts, but + that behavior is now deprecated (see appendix C). In some types of + reporting messages for which a reply is likely to cause a mail loop + (for example, mail delivery and nondelivery notifications), the + reverse-path may be null (see section 3.7). + + This command clears the reverse-path buffer, the forward-path buffer, + and the mail data buffer; and inserts the reverse-path information + from this command into the reverse-path buffer. + + If service extensions were negotiated, the MAIL command may also + carry parameters associated with a particular service extension. + + Syntax: + + "MAIL FROM:" ("<>" / Reverse-Path) + [SP Mail-parameters] CRLF + +4.1.1.3 RECIPIENT (RCPT) + + This command is used to identify an individual recipient of the mail + data; multiple recipients are specified by multiple use of this + command. The argument field contains a forward-path and may contain + optional parameters. + + The forward-path normally consists of the required destination + mailbox. Sending systems SHOULD not generate the optional list of + hosts known as a source route. Receiving systems MUST recognize + + + + +Klensin Standards Track [Page 31] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + source route syntax but SHOULD strip off the source route + specification and utilize the domain name associated with the mailbox + as if the source route had not been provided. + + Similarly, relay hosts SHOULD strip or ignore source routes, and + names MUST NOT be copied into the reverse-path. When mail reaches + its ultimate destination (the forward-path contains only a + destination mailbox), the SMTP server inserts it into the destination + mailbox in accordance with its host mail conventions. + + For example, mail received at relay host xyz.com with envelope + commands + + MAIL FROM: + RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org> + + will normally be sent directly on to host d.bar.org with envelope + commands + + MAIL FROM: + RCPT TO: + + As provided in appendix C, xyz.com MAY also choose to relay the + message to hosta.int, using the envelope commands + + MAIL FROM: + RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org> + + or to jkl.org, using the envelope commands + + MAIL FROM: + RCPT TO:<@jkl.org:userc@d.bar.org> + + Of course, since hosts are not required to relay mail at all, xyz.com + may also reject the message entirely when the RCPT command is + received, using a 550 code (since this is a "policy reason"). + + If service extensions were negotiated, the RCPT command may also + carry parameters associated with a particular service extension + offered by the server. The client MUST NOT transmit parameters other + than those associated with a service extension offered by the server + in its EHLO response. + +Syntax: + "RCPT TO:" ("" / "" / Forward-Path) + [SP Rcpt-parameters] CRLF + + + + + +Klensin Standards Track [Page 32] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +4.1.1.4 DATA (DATA) + + The receiver normally sends a 354 response to DATA, and then treats + the lines (strings ending in sequences, as described in + section 2.3.7) following the command as mail data from the sender. + This command causes the mail data to be appended to the mail data + buffer. The mail data may contain any of the 128 ASCII character + codes, although experience has indicated that use of control + characters other than SP, HT, CR, and LF may cause problems and + SHOULD be avoided when possible. + + The mail data is terminated by a line containing only a period, that + is, the character sequence "." (see section 4.5.2). This + is the end of mail data indication. Note that the first of + this terminating sequence is also the that ends the final line + of the data (message text) or, if there was no data, ends the DATA + command itself. An extra MUST NOT be added, as that would + cause an empty line to be added to the message. The only exception + to this rule would arise if the message body were passed to the + originating SMTP-sender with a final "line" that did not end in + ; in that case, the originating SMTP system MUST either reject + the message as invalid or add in order to have the receiving + SMTP server recognize the "end of data" condition. + + The custom of accepting lines ending only in , as a concession to + non-conforming behavior on the part of some UNIX systems, has proven + to cause more interoperability problems than it solves, and SMTP + server systems MUST NOT do this, even in the name of improved + robustness. In particular, the sequence "." (bare line + feeds, without carriage returns) MUST NOT be treated as equivalent to + . as the end of mail data indication. + + Receipt of the end of mail data indication requires the server to + process the stored mail transaction information. This processing + consumes the information in the reverse-path buffer, the forward-path + buffer, and the mail data buffer, and on the completion of this + command these buffers are cleared. If the processing is successful, + the receiver MUST send an OK reply. If the processing fails the + receiver MUST send a failure reply. The SMTP model does not allow + for partial failures at this point: either the message is accepted by + the server for delivery and a positive response is returned or it is + not accepted and a failure reply is returned. In sending a positive + completion reply to the end of data indication, the receiver takes + full responsibility for the message (see section 6.1). Errors that + are diagnosed subsequently MUST be reported in a mail message, as + discussed in section 4.4. + + + + + +Klensin Standards Track [Page 33] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + When the SMTP server accepts a message either for relaying or for + final delivery, it inserts a trace record (also referred to + interchangeably as a "time stamp line" or "Received" line) at the top + of the mail data. This trace record indicates the identity of the + host that sent the message, the identity of the host that received + the message (and is inserting this time stamp), and the date and time + the message was received. Relayed messages will have multiple time + stamp lines. Details for formation of these lines, including their + syntax, is specified in section 4.4. + + Additional discussion about the operation of the DATA command appears + in section 3.3. + + Syntax: + "DATA" CRLF + +4.1.1.5 RESET (RSET) + + This command specifies that the current mail transaction will be + aborted. Any stored sender, recipients, and mail data MUST be + discarded, and all buffers and state tables cleared. The receiver + MUST send a "250 OK" reply to a RSET command with no arguments. A + reset command may be issued by the client at any time. It is + effectively equivalent to a NOOP (i.e., if has no effect) if issued + immediately after EHLO, before EHLO is issued in the session, after + an end-of-data indicator has been sent and acknowledged, or + immediately before a QUIT. An SMTP server MUST NOT close the + connection as the result of receiving a RSET; that action is reserved + for QUIT (see section 4.1.1.10). + + Since EHLO implies some additional processing and response by the + server, RSET will normally be more efficient than reissuing that + command, even though the formal semantics are the same. + + There are circumstances, contrary to the intent of this + specification, in which an SMTP server may receive an indication that + the underlying TCP connection has been closed or reset. To preserve + the robustness of the mail system, SMTP servers SHOULD be prepared + for this condition and SHOULD treat it as if a QUIT had been received + before the connection disappeared. + + Syntax: + "RSET" CRLF + + + + + + + + +Klensin Standards Track [Page 34] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +4.1.1.6 VERIFY (VRFY) + + This command asks the receiver to confirm that the argument + identifies a user or mailbox. If it is a user name, information is + returned as specified in section 3.5. + + This command has no effect on the reverse-path buffer, the forward- + path buffer, or the mail data buffer. + + Syntax: + "VRFY" SP String CRLF + +4.1.1.7 EXPAND (EXPN) + + This command asks the receiver to confirm that the argument + identifies a mailing list, and if so, to return the membership of + that list. If the command is successful, a reply is returned + containing information as described in section 3.5. This reply will + have multiple lines except in the trivial case of a one-member list. + + This command has no effect on the reverse-path buffer, the forward- + path buffer, or the mail data buffer and may be issued at any time. + + Syntax: + "EXPN" SP String CRLF + +4.1.1.8 HELP (HELP) + + This command causes the server to send helpful information to the + client. The command MAY take an argument (e.g., any command name) + and return more specific information as a response. + + This command has no effect on the reverse-path buffer, the forward- + path buffer, or the mail data buffer and may be issued at any time. + + SMTP servers SHOULD support HELP without arguments and MAY support it + with arguments. + + Syntax: + "HELP" [ SP String ] CRLF + +4.1.1.9 NOOP (NOOP) + + This command does not affect any parameters or previously entered + commands. It specifies no action other than that the receiver send + an OK reply. + + + + + +Klensin Standards Track [Page 35] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + This command has no effect on the reverse-path buffer, the forward- + path buffer, or the mail data buffer and may be issued at any time. + If a parameter string is specified, servers SHOULD ignore it. + + Syntax: + "NOOP" [ SP String ] CRLF + +4.1.1.10 QUIT (QUIT) + + This command specifies that the receiver MUST send an OK reply, and + then close the transmission channel. + + The receiver MUST NOT intentionally close the transmission channel + until it receives and replies to a QUIT command (even if there was an + error). The sender MUST NOT intentionally close the transmission + channel until it sends a QUIT command and SHOULD wait until it + receives the reply (even if there was an error response to a previous + command). If the connection is closed prematurely due to violations + of the above or system or network failure, the server MUST cancel any + pending transaction, but not undo any previously completed + transaction, and generally MUST act as if the command or transaction + in progress had received a temporary error (i.e., a 4yz response). + + The QUIT command may be issued at any time. + + Syntax: + "QUIT" CRLF + +4.1.2 Command Argument Syntax + + The syntax of the argument fields of the above commands (using the + syntax specified in [8] where applicable) is given below. Some of + the productions given below are used only in conjunction with source + routes as described in appendix C. Terminals not defined in this + document, such as ALPHA, DIGIT, SP, CR, LF, CRLF, are as defined in + the "core" syntax [8 (section 6)] or in the message format syntax + [32]. + + Reverse-path = Path + Forward-path = Path + Path = "<" [ A-d-l ":" ] Mailbox ">" + A-d-l = At-domain *( "," A-d-l ) + ; Note that this form, the so-called "source route", + ; MUST BE accepted, SHOULD NOT be generated, and SHOULD be + ; ignored. + At-domain = "@" domain + Mail-parameters = esmtp-param *(SP esmtp-param) + Rcpt-parameters = esmtp-param *(SP esmtp-param) + + + +Klensin Standards Track [Page 36] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + esmtp-param = esmtp-keyword ["=" esmtp-value] + esmtp-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-") + esmtp-value = 1*(%d33-60 / %d62-127) + ; any CHAR excluding "=", SP, and control characters + Keyword = Ldh-str + Argument = Atom + Domain = (sub-domain 1*("." sub-domain)) / address-literal + sub-domain = Let-dig [Ldh-str] + + address-literal = "[" IPv4-address-literal / + IPv6-address-literal / + General-address-literal "]" + ; See section 4.1.3 + + Mailbox = Local-part "@" Domain + + Local-part = Dot-string / Quoted-string + ; MAY be case-sensitive + + Dot-string = Atom *("." Atom) + + Atom = 1*atext + + Quoted-string = DQUOTE *qcontent DQUOTE + + String = Atom / Quoted-string + + While the above definition for Local-part is relatively permissive, + for maximum interoperability, a host that expects to receive mail + SHOULD avoid defining mailboxes where the Local-part requires (or + uses) the Quoted-string form or where the Local-part is case- + sensitive. For any purposes that require generating or comparing + Local-parts (e.g., to specific mailbox names), all quoted forms MUST + be treated as equivalent and the sending system SHOULD transmit the + form that uses the minimum quoting possible. + + Systems MUST NOT define mailboxes in such a way as to require the use + in SMTP of non-ASCII characters (octets with the high order bit set + to one) or ASCII "control characters" (decimal value 0-31 and 127). + These characters MUST NOT be used in MAIL or RCPT commands or other + commands that require mailbox names. + + Note that the backslash, "\", is a quote character, which is used to + indicate that the next character is to be used literally (instead of + its normal interpretation). For example, "Joe\,Smith" indicates a + single nine character user field with the comma being the fourth + character of the field. + + + + +Klensin Standards Track [Page 37] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + To promote interoperability and consistent with long-standing + guidance about conservative use of the DNS in naming and applications + (e.g., see section 2.3.1 of the base DNS document, RFC1035 [22]), + characters outside the set of alphas, digits, and hyphen MUST NOT + appear in domain name labels for SMTP clients or servers. In + particular, the underscore character is not permitted. SMTP servers + that receive a command in which invalid character codes have been + employed, and for which there are no other reasons for rejection, + MUST reject that command with a 501 response. + +4.1.3 Address Literals + + Sometimes a host is not known to the domain name system and + communication (and, in particular, communication to report and repair + the error) is blocked. To bypass this barrier a special literal form + of the address is allowed as an alternative to a domain name. For + IPv4 addresses, this form uses four small decimal integers separated + by dots and enclosed by brackets such as [123.255.37.2], which + indicates an (IPv4) Internet Address in sequence-of-octets form. For + IPv6 and other forms of addressing that might eventually be + standardized, the form consists of a standardized "tag" that + identifies the address syntax, a colon, and the address itself, in a + format specified as part of the IPv6 standards [17]. + + Specifically: + + IPv4-address-literal = Snum 3("." Snum) + IPv6-address-literal = "IPv6:" IPv6-addr + General-address-literal = Standardized-tag ":" 1*dcontent + Standardized-tag = Ldh-str + ; MUST be specified in a standards-track RFC + ; and registered with IANA + + Snum = 1*3DIGIT ; representing a decimal integer + ; value in the range 0 through 255 + Let-dig = ALPHA / DIGIT + Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig + + IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp + IPv6-hex = 1*4HEXDIG + IPv6-full = IPv6-hex 7(":" IPv6-hex) + IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" [IPv6-hex *5(":" + IPv6-hex)] + ; The "::" represents at least 2 16-bit groups of zeros + ; No more than 6 groups in addition to the "::" may be + ; present + IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal + IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::" + + + +Klensin Standards Track [Page 38] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + [IPv6-hex *3(":" IPv6-hex) ":"] IPv4-address-literal + ; The "::" represents at least 2 16-bit groups of zeros + ; No more than 4 groups in addition to the "::" and + ; IPv4-address-literal may be present + +4.1.4 Order of Commands + + There are restrictions on the order in which these commands may be + used. + + A session that will contain mail transactions MUST first be + initialized by the use of the EHLO command. An SMTP server SHOULD + accept commands for non-mail transactions (e.g., VRFY or EXPN) + without this initialization. + + An EHLO command MAY be issued by a client later in the session. If + it is issued after the session begins, the SMTP server MUST clear all + buffers and reset the state exactly as if a RSET command had been + issued. In other words, the sequence of RSET followed immediately by + EHLO is redundant, but not harmful other than in the performance cost + of executing unnecessary commands. + + If the EHLO command is not acceptable to the SMTP server, 501, 500, + or 502 failure replies MUST be returned as appropriate. The SMTP + server MUST stay in the same state after transmitting these replies + that it was in before the EHLO was received. + + The SMTP client MUST, if possible, ensure that the domain parameter + to the EHLO command is a valid principal host name (not a CNAME or MX + name) for its host. If this is not possible (e.g., when the client's + address is dynamically assigned and the client does not have an + obvious name), an address literal SHOULD be substituted for the + domain name and supplemental information provided that will assist in + identifying the client. + + An SMTP server MAY verify that the domain name parameter in the EHLO + command actually corresponds to the IP address of the client. + However, the server MUST NOT refuse to accept a message for this + reason if the verification fails: the information about verification + failure is for logging and tracing only. + + The NOOP, HELP, EXPN, VRFY, and RSET commands can be used at any time + during a session, or without previously initializing a session. SMTP + servers SHOULD process these normally (that is, not return a 503 + code) even if no EHLO command has yet been received; clients SHOULD + open a session with EHLO before sending these commands. + + + + + +Klensin Standards Track [Page 39] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + If these rules are followed, the example in RFC 821 that shows "550 + access denied to you" in response to an EXPN command is incorrect + unless an EHLO command precedes the EXPN or the denial of access is + based on the client's IP address or other authentication or + authorization-determining mechanisms. + + The MAIL command (or the obsolete SEND, SOML, or SAML commands) + begins a mail transaction. Once started, a mail transaction consists + of a transaction beginning command, one or more RCPT commands, and a + DATA command, in that order. A mail transaction may be aborted by + the RSET (or a new EHLO) command. There may be zero or more + transactions in a session. MAIL (or SEND, SOML, or SAML) MUST NOT be + sent if a mail transaction is already open, i.e., it should be sent + only if no mail transaction had been started in the session, or it + the previous one successfully concluded with a successful DATA + command, or if the previous one was aborted with a RSET. + + If the transaction beginning command argument is not acceptable, a + 501 failure reply MUST be returned and the SMTP server MUST stay in + the same state. If the commands in a transaction are out of order to + the degree that they cannot be processed by the server, a 503 failure + reply MUST be returned and the SMTP server MUST stay in the same + state. + + The last command in a session MUST be the QUIT command. The QUIT + command cannot be used at any other time in a session, but SHOULD be + used by the client SMTP to request connection closure, even when no + session opening command was sent and accepted. + +4.1.5 Private-use Commands + + As specified in section 2.2.2, commands starting in "X" may be used + by bilateral agreement between the client (sending) and server + (receiving) SMTP agents. An SMTP server that does not recognize such + a command is expected to reply with "500 Command not recognized". An + extended SMTP server MAY list the feature names associated with these + private commands in the response to the EHLO command. + + Commands sent or accepted by SMTP systems that do not start with "X" + MUST conform to the requirements of section 2.2.2. + +4.2 SMTP Replies + + Replies to SMTP commands serve to ensure the synchronization of + requests and actions in the process of mail transfer and to guarantee + that the SMTP client always knows the state of the SMTP server. + Every command MUST generate exactly one reply. + + + + +Klensin Standards Track [Page 40] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + The details of the command-reply sequence are described in section + 4.3. + + An SMTP reply consists of a three digit number (transmitted as three + numeric characters) followed by some text unless specified otherwise + in this document. The number is for use by automata to determine + what state to enter next; the text is for the human user. The three + digits contain enough encoded information that the SMTP client need + not examine the text and may either discard it or pass it on to the + user, as appropriate. Exceptions are as noted elsewhere in this + document. In particular, the 220, 221, 251, 421, and 551 reply codes + are associated with message text that must be parsed and interpreted + by machines. In the general case, the text may be receiver dependent + and context dependent, so there are likely to be varying texts for + each reply code. A discussion of the theory of reply codes is given + in section 4.2.1. Formally, a reply is defined to be the sequence: a + three-digit code, , one line of text, and , or a multiline + reply (as defined in section 4.2.1). Since, in violation of this + specification, the text is sometimes not sent, clients which do not + receive it SHOULD be prepared to process the code alone (with or + without a trailing space character). Only the EHLO, EXPN, and HELP + commands are expected to result in multiline replies in normal + circumstances, however, multiline replies are allowed for any + command. + + In ABNF, server responses are: + + Greeting = "220 " Domain [ SP text ] CRLF + Reply-line = Reply-code [ SP text ] CRLF + + where "Greeting" appears only in the 220 response that announces that + the server is opening its part of the connection. + + An SMTP server SHOULD send only the reply codes listed in this + document. An SMTP server SHOULD use the text shown in the examples + whenever appropriate. + + An SMTP client MUST determine its actions only by the reply code, not + by the text (except for the "change of address" 251 and 551 and, if + necessary, 220, 221, and 421 replies); in the general case, any text, + including no text at all (although senders SHOULD NOT send bare + codes), MUST be acceptable. The space (blank) following the reply + code is considered part of the text. Whenever possible, a receiver- + SMTP SHOULD test the first digit (severity indication) of the reply + code. + + + + + + +Klensin Standards Track [Page 41] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + The list of codes that appears below MUST NOT be construed as + permanent. While the addition of new codes should be a rare and + significant activity, with supplemental information in the textual + part of the response being preferred, new codes may be added as the + result of new Standards or Standards-track specifications. + Consequently, a sender-SMTP MUST be prepared to handle codes not + specified in this document and MUST do so by interpreting the first + digit only. + +4.2.1 Reply Code Severities and Theory + + The three digits of the reply each have a special significance. The + first digit denotes whether the response is good, bad or incomplete. + An unsophisticated SMTP client, or one that receives an unexpected + code, will be able to determine its next action (proceed as planned, + redo, retrench, etc.) by examining this first digit. An SMTP client + that wants to know approximately what kind of error occurred (e.g., + mail system error, command syntax error) may examine the second + digit. The third digit and any supplemental information that may be + present is reserved for the finest gradation of information. + + There are five values for the first digit of the reply code: + + 1yz Positive Preliminary reply + The command has been accepted, but the requested action is being + held in abeyance, pending confirmation of the information in this + reply. The SMTP client should send another command specifying + whether to continue or abort the action. Note: unextended SMTP + does not have any commands that allow this type of reply, and so + does not have continue or abort commands. + + 2yz Positive Completion reply + The requested action has been successfully completed. A new + request may be initiated. + + 3yz Positive Intermediate reply + The command has been accepted, but the requested action is being + held in abeyance, pending receipt of further information. The + SMTP client should send another command specifying this + information. This reply is used in command sequence groups (i.e., + in DATA). + + 4yz Transient Negative Completion reply + The command was not accepted, and the requested action did not + occur. However, the error condition is temporary and the action + may be requested again. The sender should return to the beginning + of the command sequence (if any). It is difficult to assign a + meaning to "transient" when two different sites (receiver- and + + + +Klensin Standards Track [Page 42] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + sender-SMTP agents) must agree on the interpretation. Each reply + in this category might have a different time value, but the SMTP + client is encouraged to try again. A rule of thumb to determine + whether a reply fits into the 4yz or the 5yz category (see below) + is that replies are 4yz if they can be successful if repeated + without any change in command form or in properties of the sender + or receiver (that is, the command is repeated identically and the + receiver does not put up a new implementation.) + + 5yz Permanent Negative Completion reply + The command was not accepted and the requested action did not + occur. The SMTP client is discouraged from repeating the exact + request (in the same sequence). Even some "permanent" error + conditions can be corrected, so the human user may want to direct + the SMTP client to reinitiate the command sequence by direct + action at some point in the future (e.g., after the spelling has + been changed, or the user has altered the account status). + + The second digit encodes responses in specific categories: + + x0z Syntax: These replies refer to syntax errors, syntactically + correct commands that do not fit any functional category, and + unimplemented or superfluous commands. + + x1z Information: These are replies to requests for information, + such as status or help. + + x2z Connections: These are replies referring to the transmission + channel. + + x3z Unspecified. + + x4z Unspecified. + + x5z Mail system: These replies indicate the status of the receiver + mail system vis-a-vis the requested transfer or other mail system + action. + + The third digit gives a finer gradation of meaning in each category + specified by the second digit. The list of replies illustrates this. + Each reply text is recommended rather than mandatory, and may even + change according to the command with which it is associated. On the + other hand, the reply codes must strictly follow the specifications + in this section. Receiver implementations should not invent new + codes for slightly different situations from the ones described here, + but rather adapt codes already defined. + + + + + +Klensin Standards Track [Page 43] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + For example, a command such as NOOP, whose successful execution does + not offer the SMTP client any new information, will return a 250 + reply. The reply is 502 when the command requests an unimplemented + non-site-specific action. A refinement of that is the 504 reply for + a command that is implemented, but that requests an unimplemented + parameter. + + The reply text may be longer than a single line; in these cases the + complete text must be marked so the SMTP client knows when it can + stop reading the reply. This requires a special format to indicate a + multiple line reply. + + The format for multiline replies requires that every line, except the + last, begin with the reply code, followed immediately by a hyphen, + "-" (also known as minus), followed by text. The last line will + begin with the reply code, followed immediately by , optionally + some text, and . As noted above, servers SHOULD send the + if subsequent text is not sent, but clients MUST be prepared for it + to be omitted. + + For example: + + 123-First line + 123-Second line + 123-234 text beginning with numbers + 123 The last line + + In many cases the SMTP client then simply needs to search for a line + beginning with the reply code followed by or and ignore + all preceding lines. In a few cases, there is important data for the + client in the reply "text". The client will be able to identify + these cases from the current context. + +4.2.2 Reply Codes by Function Groups + + 500 Syntax error, command unrecognized + (This may include errors such as command line too long) + 501 Syntax error in parameters or arguments + 502 Command not implemented (see section 4.2.4) + 503 Bad sequence of commands + 504 Command parameter not implemented + + 211 System status, or system help reply + 214 Help message + (Information on how to use the receiver or the meaning of a + particular non-standard command; this reply is useful only + to the human user) + + + + +Klensin Standards Track [Page 44] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + 220 Service ready + 221 Service closing transmission channel + 421 Service not available, closing transmission channel + (This may be a reply to any command if the service knows it + must shut down) + + 250 Requested mail action okay, completed + 251 User not local; will forward to + (See section 3.4) + 252 Cannot VRFY user, but will accept message and attempt + delivery + (See section 3.5.3) + 450 Requested mail action not taken: mailbox unavailable + (e.g., mailbox busy) + 550 Requested action not taken: mailbox unavailable + (e.g., mailbox not found, no access, or command rejected + for policy reasons) + 451 Requested action aborted: error in processing + 551 User not local; please try + (See section 3.4) + 452 Requested action not taken: insufficient system storage + 552 Requested mail action aborted: exceeded storage allocation + 553 Requested action not taken: mailbox name not allowed + (e.g., mailbox syntax incorrect) + 354 Start mail input; end with . + 554 Transaction failed (Or, in the case of a connection-opening + response, "No SMTP service here") + +4.2.3 Reply Codes in Numeric Order + + 211 System status, or system help reply + 214 Help message + (Information on how to use the receiver or the meaning of a + particular non-standard command; this reply is useful only + to the human user) + 220 Service ready + 221 Service closing transmission channel + 250 Requested mail action okay, completed + 251 User not local; will forward to + (See section 3.4) + 252 Cannot VRFY user, but will accept message and attempt + delivery + (See section 3.5.3) + + 354 Start mail input; end with . + + + + + + +Klensin Standards Track [Page 45] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + 421 Service not available, closing transmission channel + (This may be a reply to any command if the service knows it + must shut down) + 450 Requested mail action not taken: mailbox unavailable + (e.g., mailbox busy) + 451 Requested action aborted: local error in processing + 452 Requested action not taken: insufficient system storage + 500 Syntax error, command unrecognized + (This may include errors such as command line too long) + 501 Syntax error in parameters or arguments + 502 Command not implemented (see section 4.2.4) + 503 Bad sequence of commands + 504 Command parameter not implemented + 550 Requested action not taken: mailbox unavailable + (e.g., mailbox not found, no access, or command rejected + for policy reasons) + 551 User not local; please try + (See section 3.4) + 552 Requested mail action aborted: exceeded storage allocation + 553 Requested action not taken: mailbox name not allowed + (e.g., mailbox syntax incorrect) + 554 Transaction failed (Or, in the case of a connection-opening + response, "No SMTP service here") + +4.2.4 Reply Code 502 + + Questions have been raised as to when reply code 502 (Command not + implemented) SHOULD be returned in preference to other codes. 502 + SHOULD be used when the command is actually recognized by the SMTP + server, but not implemented. If the command is not recognized, code + 500 SHOULD be returned. Extended SMTP systems MUST NOT list + capabilities in response to EHLO for which they will return 502 (or + 500) replies. + +4.2.5 Reply Codes After DATA and the Subsequent . + + When an SMTP server returns a positive completion status (2yz code) + after the DATA command is completed with ., it accepts + responsibility for: + + - delivering the message (if the recipient mailbox exists), or + + - if attempts to deliver the message fail due to transient + conditions, retrying delivery some reasonable number of times at + intervals as specified in section 4.5.4. + + + + + + +Klensin Standards Track [Page 46] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + - if attempts to deliver the message fail due to permanent + conditions, or if repeated attempts to deliver the message fail + due to transient conditions, returning appropriate notification to + the sender of the original message (using the address in the SMTP + MAIL command). + + When an SMTP server returns a permanent error status (5yz) code after + the DATA command is completed with ., it MUST NOT make + any subsequent attempt to deliver that message. The SMTP client + retains responsibility for delivery of that message and may either + return it to the user or requeue it for a subsequent attempt (see + section 4.5.4.1). + + The user who originated the message SHOULD be able to interpret the + return of a transient failure status (by mail message or otherwise) + as a non-delivery indication, just as a permanent failure would be + interpreted. I.e., if the client SMTP successfully handles these + conditions, the user will not receive such a reply. + + When an SMTP server returns a permanent error status (5yz) code after + the DATA command is completely with ., it MUST NOT make + any subsequent attempt to deliver the message. As with temporary + error status codes, the SMTP client retains responsibility for the + message, but SHOULD not again attempt delivery to the same server + without user review and intervention of the message. + +4.3 Sequencing of Commands and Replies + +4.3.1 Sequencing Overview + + The communication between the sender and receiver is an alternating + dialogue, controlled by the sender. As such, the sender issues a + command and the receiver responds with a reply. Unless other + arrangements are negotiated through service extensions, the sender + MUST wait for this response before sending further commands. + + One important reply is the connection greeting. Normally, a receiver + will send a 220 "Service ready" reply when the connection is + completed. The sender SHOULD wait for this greeting message before + sending any commands. + + Note: all the greeting-type replies have the official name (the + fully-qualified primary domain name) of the server host as the first + word following the reply code. Sometimes the host will have no + meaningful name. See 4.1.3 for a discussion of alternatives in these + situations. + + + + + +Klensin Standards Track [Page 47] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + For example, + + 220 ISIF.USC.EDU Service ready + or + 220 mail.foo.com SuperSMTP v 6.1.2 Service ready + or + 220 [10.0.0.1] Clueless host service ready + + The table below lists alternative success and failure replies for + each command. These SHOULD be strictly adhered to: a receiver may + substitute text in the replies, but the meaning and action implied by + the code numbers and by the specific command reply sequence cannot be + altered. + +4.3.2 Command-Reply Sequences + + Each command is listed with its usual possible replies. The prefixes + used before the possible replies are "I" for intermediate, "S" for + success, and "E" for error. Since some servers may generate other + replies under special circumstances, and to allow for future + extension, SMTP clients SHOULD, when possible, interpret only the + first digit of the reply and MUST be prepared to deal with + unrecognized reply codes by interpreting the first digit only. + Unless extended using the mechanisms described in section 2.2, SMTP + servers MUST NOT transmit reply codes to an SMTP client that are + other than three digits or that do not start in a digit between 2 and + 5 inclusive. + + These sequencing rules and, in principle, the codes themselves, can + be extended or modified by SMTP extensions offered by the server and + accepted (requested) by the client. + + In addition to the codes listed below, any SMTP command can return + any of the following codes if the corresponding unusual circumstances + are encountered: + + 500 For the "command line too long" case or if the command name was + not recognized. Note that producing a "command not recognized" + error in response to the required subset of these commands is a + violation of this specification. + + 501 Syntax error in command or arguments. In order to provide for + future extensions, commands that are specified in this document as + not accepting arguments (DATA, RSET, QUIT) SHOULD return a 501 + message if arguments are supplied in the absence of EHLO- + advertised extensions. + + 421 Service shutting down and closing transmission channel + + + +Klensin Standards Track [Page 48] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + Specific sequences are: + + CONNECTION ESTABLISHMENT + S: 220 + E: 554 + EHLO or HELO + S: 250 + E: 504, 550 + MAIL + S: 250 + E: 552, 451, 452, 550, 553, 503 + RCPT + S: 250, 251 (but see section 3.4 for discussion of 251 and 551) + E: 550, 551, 552, 553, 450, 451, 452, 503, 550 + DATA + I: 354 -> data -> S: 250 + E: 552, 554, 451, 452 + E: 451, 554, 503 + RSET + S: 250 + VRFY + S: 250, 251, 252 + E: 550, 551, 553, 502, 504 + EXPN + S: 250, 252 + E: 550, 500, 502, 504 + HELP + S: 211, 214 + E: 502, 504 + NOOP + S: 250 + QUIT + S: 221 + +4.4 Trace Information + + When an SMTP server receives a message for delivery or further + processing, it MUST insert trace ("time stamp" or "Received") + information at the beginning of the message content, as discussed in + section 4.1.1.4. + + This line MUST be structured as follows: + + - The FROM field, which MUST be supplied in an SMTP environment, + SHOULD contain both (1) the name of the source host as presented + in the EHLO command and (2) an address literal containing the IP + address of the source, determined from the TCP connection. + + + + +Klensin Standards Track [Page 49] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + - The ID field MAY contain an "@" as suggested in RFC 822, but this + is not required. + + - The FOR field MAY contain a list of entries when multiple + RCPT commands have been given. This may raise some security + issues and is usually not desirable; see section 7.2. + + An Internet mail program MUST NOT change a Received: line that was + previously added to the message header. SMTP servers MUST prepend + Received lines to messages; they MUST NOT change the order of + existing lines or insert Received lines in any other location. + + As the Internet grows, comparability of Received fields is important + for detecting problems, especially slow relays. SMTP servers that + create Received fields SHOULD use explicit offsets in the dates + (e.g., -0800), rather than time zone names of any type. Local time + (with an offset) is preferred to UT when feasible. This formulation + allows slightly more information about local circumstances to be + specified. If UT is needed, the receiver need merely do some simple + arithmetic to convert the values. Use of UT loses information about + the time zone-location of the server. If it is desired to supply a + time zone name, it SHOULD be included in a comment. + + When the delivery SMTP server makes the "final delivery" of a + message, it inserts a return-path line at the beginning of the mail + data. This use of return-path is required; mail systems MUST support + it. The return-path line preserves the information in the from the MAIL command. Here, final delivery means the message + has left the SMTP environment. Normally, this would mean it had been + delivered to the destination user or an associated mail drop, but in + some cases it may be further processed and transmitted by another + mail system. + + It is possible for the mailbox in the return path to be different + from the actual sender's mailbox, for example, if error responses are + to be delivered to a special error handling mailbox rather than to + the message sender. When mailing lists are involved, this + arrangement is common and useful as a means of directing errors to + the list maintainer rather than the message originator. + + The text above implies that the final mail data will begin with a + return path line, followed by one or more time stamp lines. These + lines will be followed by the mail data headers and body [32]. + + It is sometimes difficult for an SMTP server to determine whether or + not it is making final delivery since forwarding or other operations + may occur after the message is accepted for delivery. Consequently, + + + + +Klensin Standards Track [Page 50] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + any further (forwarding, gateway, or relay) systems MAY remove the + return path and rebuild the MAIL command as needed to ensure that + exactly one such line appears in a delivered message. + + A message-originating SMTP system SHOULD NOT send a message that + already contains a Return-path header. SMTP servers performing a + relay function MUST NOT inspect the message data, and especially not + to the extent needed to determine if Return-path headers are present. + SMTP servers making final delivery MAY remove Return-path headers + before adding their own. + + The primary purpose of the Return-path is to designate the address to + which messages indicating non-delivery or other mail system failures + are to be sent. For this to be unambiguous, exactly one return path + SHOULD be present when the message is delivered. Systems using RFC + 822 syntax with non-SMTP transports SHOULD designate an unambiguous + address, associated with the transport envelope, to which error + reports (e.g., non-delivery messages) should be sent. + + Historical note: Text in RFC 822 that appears to contradict the use + of the Return-path header (or the envelope reverse path address from + the MAIL command) as the destination for error messages is not + applicable on the Internet. The reverse path address (as copied into + the Return-path) MUST be used as the target of any mail containing + delivery error messages. + + In particular: + + - a gateway from SMTP->elsewhere SHOULD insert a return-path header, + unless it is known that the "elsewhere" transport also uses + Internet domain addresses and maintains the envelope sender + address separately. + + - a gateway from elsewhere->SMTP SHOULD delete any return-path + header present in the message, and either copy that information to + the SMTP envelope or combine it with information present in the + envelope of the other transport system to construct the reverse + path argument to the MAIL command in the SMTP envelope. + + The server must give special treatment to cases in which the + processing following the end of mail data indication is only + partially successful. This could happen if, after accepting several + recipients and the mail data, the SMTP server finds that the mail + data could be successfully delivered to some, but not all, of the + recipients. In such cases, the response to the DATA command MUST be + an OK reply. However, the SMTP server MUST compose and send an + "undeliverable mail" notification message to the originator of the + message. + + + +Klensin Standards Track [Page 51] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + A single notification listing all of the failed recipients or + separate notification messages MUST be sent for each failed + recipient. For economy of processing by the sender, the former is + preferred when possible. All undeliverable mail notification + messages are sent using the MAIL command (even if they result from + processing the obsolete SEND, SOML, or SAML commands) and use a null + return path as discussed in section 3.7. + + The time stamp line and the return path line are formally defined as + follows: + +Return-path-line = "Return-Path:" FWS Reverse-path + +Time-stamp-line = "Received:" FWS Stamp + +Stamp = From-domain By-domain Opt-info ";" FWS date-time + + ; where "date-time" is as defined in [32] + ; but the "obs-" forms, especially two-digit + ; years, are prohibited in SMTP and MUST NOT be used. + +From-domain = "FROM" FWS Extended-Domain CFWS + +By-domain = "BY" FWS Extended-Domain CFWS + +Extended-Domain = Domain / + ( Domain FWS "(" TCP-info ")" ) / + ( Address-literal FWS "(" TCP-info ")" ) + +TCP-info = Address-literal / ( Domain FWS Address-literal ) + ; Information derived by server from TCP connection + ; not client EHLO. + +Opt-info = [Via] [With] [ID] [For] + +Via = "VIA" FWS Link CFWS + +With = "WITH" FWS Protocol CFWS + +ID = "ID" FWS String / msg-id CFWS + +For = "FOR" FWS 1*( Path / Mailbox ) CFWS + +Link = "TCP" / Addtl-Link +Addtl-Link = Atom + ; Additional standard names for links are registered with the + ; Internet Assigned Numbers Authority (IANA). "Via" is + ; primarily of value with non-Internet transports. SMTP + + + +Klensin Standards Track [Page 52] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + ; servers SHOULD NOT use unregistered names. +Protocol = "ESMTP" / "SMTP" / Attdl-Protocol +Attdl-Protocol = Atom + ; Additional standard names for protocols are registered with the + ; Internet Assigned Numbers Authority (IANA). SMTP servers + ; SHOULD NOT use unregistered names. + +4.5 Additional Implementation Issues + +4.5.1 Minimum Implementation + + In order to make SMTP workable, the following minimum implementation + is required for all receivers. The following commands MUST be + supported to conform to this specification: + + EHLO + HELO + MAIL + RCPT + DATA + RSET + NOOP + QUIT + VRFY + + Any system that includes an SMTP server supporting mail relaying or + delivery MUST support the reserved mailbox "postmaster" as a case- + insensitive local name. This postmaster address is not strictly + necessary if the server always returns 554 on connection opening (as + described in section 3.1). The requirement to accept mail for + postmaster implies that RCPT commands which specify a mailbox for + postmaster at any of the domains for which the SMTP server provides + mail service, as well as the special case of "RCPT TO:" + (with no domain specification), MUST be supported. + + SMTP systems are expected to make every reasonable effort to accept + mail directed to Postmaster from any other system on the Internet. + In extreme cases --such as to contain a denial of service attack or + other breach of security-- an SMTP server may block mail directed to + Postmaster. However, such arrangements SHOULD be narrowly tailored + so as to avoid blocking messages which are not part of such attacks. + +4.5.2 Transparency + + Without some provision for data transparency, the character sequence + "." ends the mail text and cannot be sent by the user. + In general, users are not aware of such "forbidden" sequences. To + + + + +Klensin Standards Track [Page 53] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + allow all user composed text to be transmitted transparently, the + following procedures are used: + + - Before sending a line of mail text, the SMTP client checks the + first character of the line. If it is a period, one additional + period is inserted at the beginning of the line. + + - When a line of mail text is received by the SMTP server, it checks + the line. If the line is composed of a single period, it is + treated as the end of mail indicator. If the first character is a + period and there are other characters on the line, the first + character is deleted. + + The mail data may contain any of the 128 ASCII characters. All + characters are to be delivered to the recipient's mailbox, including + spaces, vertical and horizontal tabs, and other control characters. + If the transmission channel provides an 8-bit byte (octet) data + stream, the 7-bit ASCII codes are transmitted right justified in the + octets, with the high order bits cleared to zero. See 3.7 for + special treatment of these conditions in SMTP systems serving a relay + function. + + In some systems it may be necessary to transform the data as it is + received and stored. This may be necessary for hosts that use a + different character set than ASCII as their local character set, that + store data in records rather than strings, or which use special + character sequences as delimiters inside mailboxes. If such + transformations are necessary, they MUST be reversible, especially if + they are applied to mail being relayed. + +4.5.3 Sizes and Timeouts + +4.5.3.1 Size limits and minimums + + There are several objects that have required minimum/maximum sizes. + Every implementation MUST be able to receive objects of at least + these sizes. Objects larger than these sizes SHOULD be avoided when + possible. However, some Internet mail constructs such as encoded + X.400 addresses [16] will often require larger objects: clients MAY + attempt to transmit these, but MUST be prepared for a server to + reject them if they cannot be handled by it. To the maximum extent + possible, implementation techniques which impose no limits on the + length of these objects should be used. + + local-part + The maximum total length of a user name or other local-part is 64 + characters. + + + + +Klensin Standards Track [Page 54] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + domain + The maximum total length of a domain name or number is 255 + characters. + + path + The maximum total length of a reverse-path or forward-path is 256 + characters (including the punctuation and element separators). + + command line + The maximum total length of a command line including the command + word and the is 512 characters. SMTP extensions may be + used to increase this limit. + + reply line + The maximum total length of a reply line including the reply code + and the is 512 characters. More information may be + conveyed through multiple-line replies. + + text line + The maximum total length of a text line including the is + 1000 characters (not counting the leading dot duplicated for + transparency). This number may be increased by the use of SMTP + Service Extensions. + + message content + The maximum total length of a message content (including any + message headers as well as the message body) MUST BE at least 64K + octets. Since the introduction of Internet standards for + multimedia mail [12], message lengths on the Internet have grown + dramatically, and message size restrictions should be avoided if + at all possible. SMTP server systems that must impose + restrictions SHOULD implement the "SIZE" service extension [18], + and SMTP client systems that will send large messages SHOULD + utilize it when possible. + + recipients buffer + The minimum total number of recipients that must be buffered is + 100 recipients. Rejection of messages (for excessive recipients) + with fewer than 100 RCPT commands is a violation of this + specification. The general principle that relaying SMTP servers + MUST NOT, and delivery SMTP servers SHOULD NOT, perform validation + tests on message headers suggests that rejecting a message based + on the total number of recipients shown in header fields is to be + discouraged. A server which imposes a limit on the number of + recipients MUST behave in an orderly fashion, such as to reject + additional addresses over its limit rather than silently + discarding addresses previously accepted. A client that needs to + + + + +Klensin Standards Track [Page 55] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + deliver a message containing over 100 RCPT commands SHOULD be + prepared to transmit in 100-recipient "chunks" if the server + declines to accept more than 100 recipients in a single message. + + Errors due to exceeding these limits may be reported by using the + reply codes. Some examples of reply codes are: + + 500 Line too long. + or + 501 Path too long + or + 452 Too many recipients (see below) + or + 552 Too much mail data. + + RFC 821 [30] incorrectly listed the error where an SMTP server + exhausts its implementation limit on the number of RCPT commands + ("too many recipients") as having reply code 552. The correct reply + code for this condition is 452. Clients SHOULD treat a 552 code in + this case as a temporary, rather than permanent, failure so the logic + below works. + + When a conforming SMTP server encounters this condition, it has at + least 100 successful RCPT commands in its recipients buffer. If the + server is able to accept the message, then at least these 100 + addresses will be removed from the SMTP client's queue. When the + client attempts retransmission of those addresses which received 452 + responses, at least 100 of these will be able to fit in the SMTP + server's recipients buffer. Each retransmission attempt which is + able to deliver anything will be able to dispose of at least 100 of + these recipients. + + If an SMTP server has an implementation limit on the number of RCPT + commands and this limit is exhausted, it MUST use a response code of + 452 (but the client SHOULD also be prepared for a 552, as noted + above). If the server has a configured site-policy limitation on the + number of RCPT commands, it MAY instead use a 5XX response code. + This would be most appropriate if the policy limitation was intended + to apply if the total recipient count for a particular message body + were enforced even if that message body was sent in multiple mail + transactions. + +4.5.3.2 Timeouts + + An SMTP client MUST provide a timeout mechanism. It MUST use per- + command timeouts rather than somehow trying to time the entire mail + transaction. Timeouts SHOULD be easily reconfigurable, preferably + without recompiling the SMTP code. To implement this, a timer is set + + + +Klensin Standards Track [Page 56] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + for each SMTP command and for each buffer of the data transfer. The + latter means that the overall timeout is inherently proportional to + the size of the message. + + Based on extensive experience with busy mail-relay hosts, the minimum + per-command timeout values SHOULD be as follows: + + Initial 220 Message: 5 minutes + An SMTP client process needs to distinguish between a failed TCP + connection and a delay in receiving the initial 220 greeting + message. Many SMTP servers accept a TCP connection but delay + delivery of the 220 message until their system load permits more + mail to be processed. + + MAIL Command: 5 minutes + + RCPT Command: 5 minutes + A longer timeout is required if processing of mailing lists and + aliases is not deferred until after the message was accepted. + + DATA Initiation: 2 minutes + This is while awaiting the "354 Start Input" reply to a DATA + command. + + Data Block: 3 minutes + This is while awaiting the completion of each TCP SEND call + transmitting a chunk of data. + + DATA Termination: 10 minutes. + This is while awaiting the "250 OK" reply. When the receiver gets + the final period terminating the message data, it typically + performs processing to deliver the message to a user mailbox. A + spurious timeout at this point would be very wasteful and would + typically result in delivery of multiple copies of the message, + since it has been successfully sent and the server has accepted + responsibility for delivery. See section 6.1 for additional + discussion. + + An SMTP server SHOULD have a timeout of at least 5 minutes while it + is awaiting the next command from the sender. + +4.5.4 Retry Strategies + + The common structure of a host SMTP implementation includes user + mailboxes, one or more areas for queuing messages in transit, and one + or more daemon processes for sending and receiving mail. The exact + structure will vary depending on the needs of the users on the host + + + + +Klensin Standards Track [Page 57] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + and the number and size of mailing lists supported by the host. We + describe several optimizations that have proved helpful, particularly + for mailers supporting high traffic levels. + + Any queuing strategy MUST include timeouts on all activities on a + per-command basis. A queuing strategy MUST NOT send error messages + in response to error messages under any circumstances. + +4.5.4.1 Sending Strategy + + The general model for an SMTP client is one or more processes that + periodically attempt to transmit outgoing mail. In a typical system, + the program that composes a message has some method for requesting + immediate attention for a new piece of outgoing mail, while mail that + cannot be transmitted immediately MUST be queued and periodically + retried by the sender. A mail queue entry will include not only the + message itself but also the envelope information. + + The sender MUST delay retrying a particular destination after one + attempt has failed. In general, the retry interval SHOULD be at + least 30 minutes; however, more sophisticated and variable strategies + will be beneficial when the SMTP client can determine the reason for + non-delivery. + + Retries continue until the message is transmitted or the sender gives + up; the give-up time generally needs to be at least 4-5 days. The + parameters to the retry algorithm MUST be configurable. + + A client SHOULD keep a list of hosts it cannot reach and + corresponding connection timeouts, rather than just retrying queued + mail items. + + Experience suggests that failures are typically transient (the target + system or its connection has crashed), favoring a policy of two + connection attempts in the first hour the message is in the queue, + and then backing off to one every two or three hours. + + The SMTP client can shorten the queuing delay in cooperation with the + SMTP server. For example, if mail is received from a particular + address, it is likely that mail queued for that host can now be sent. + Application of this principle may, in many cases, eliminate the + requirement for an explicit "send queues now" function such as ETRN + [9]. + + The strategy may be further modified as a result of multiple + addresses per host (see below) to optimize delivery time vs. resource + usage. + + + + +Klensin Standards Track [Page 58] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + An SMTP client may have a large queue of messages for each + unavailable destination host. If all of these messages were retried + in every retry cycle, there would be excessive Internet overhead and + the sending system would be blocked for a long period. Note that an + SMTP client can generally determine that a delivery attempt has + failed only after a timeout of several minutes and even a one-minute + timeout per connection will result in a very large delay if retries + are repeated for dozens, or even hundreds, of queued messages to the + same host. + + At the same time, SMTP clients SHOULD use great care in caching + negative responses from servers. In an extreme case, if EHLO is + issued multiple times during the same SMTP connection, different + answers may be returned by the server. More significantly, 5yz + responses to the MAIL command MUST NOT be cached. + + When a mail message is to be delivered to multiple recipients, and + the SMTP server to which a copy of the message is to be sent is the + same for multiple recipients, then only one copy of the message + SHOULD be transmitted. That is, the SMTP client SHOULD use the + command sequence: MAIL, RCPT, RCPT,... RCPT, DATA instead of the + sequence: MAIL, RCPT, DATA, ..., MAIL, RCPT, DATA. However, if there + are very many addresses, a limit on the number of RCPT commands per + MAIL command MAY be imposed. Implementation of this efficiency + feature is strongly encouraged. + + Similarly, to achieve timely delivery, the SMTP client MAY support + multiple concurrent outgoing mail transactions. However, some limit + may be appropriate to protect the host from devoting all its + resources to mail. + +4.5.4.2 Receiving Strategy + + The SMTP server SHOULD attempt to keep a pending listen on the SMTP + port at all times. This requires the support of multiple incoming + TCP connections for SMTP. Some limit MAY be imposed but servers that + cannot handle more than one SMTP transaction at a time are not in + conformance with the intent of this specification. + + As discussed above, when the SMTP server receives mail from a + particular host address, it could activate its own SMTP queuing + mechanisms to retry any mail pending for that host address. + +4.5.5 Messages with a null reverse-path + + There are several types of notification messages which are required + by existing and proposed standards to be sent with a null reverse + path, namely non-delivery notifications as discussed in section 3.7, + + + +Klensin Standards Track [Page 59] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + other kinds of Delivery Status Notifications (DSNs) [24], and also + Message Disposition Notifications (MDNs) [10]. All of these kinds of + messages are notifications about a previous message, and they are + sent to the reverse-path of the previous mail message. (If the + delivery of such a notification message fails, that usually indicates + a problem with the mail system of the host to which the notification + message is addressed. For this reason, at some hosts the MTA is set + up to forward such failed notification messages to someone who is + able to fix problems with the mail system, e.g., via the postmaster + alias.) + + All other types of messages (i.e., any message which is not required + by a standards-track RFC to have a null reverse-path) SHOULD be sent + with with a valid, non-null reverse-path. + + Implementors of automated email processors should be careful to make + sure that the various kinds of messages with null reverse-path are + handled correctly, in particular such systems SHOULD NOT reply to + messages with null reverse-path. + +5. Address Resolution and Mail Handling + + Once an SMTP client lexically identifies a domain to which mail will + be delivered for processing (as described in sections 3.6 and 3.7), a + DNS lookup MUST be performed to resolve the domain name [22]. The + names are expected to be fully-qualified domain names (FQDNs): + mechanisms for inferring FQDNs from partial names or local aliases + are outside of this specification and, due to a history of problems, + are generally discouraged. The lookup first attempts to locate an MX + record associated with the name. If a CNAME record is found instead, + the resulting name is processed as if it were the initial name. If + no MX records are found, but an A RR is found, the A RR is treated as + if it was associated with an implicit MX RR, with a preference of 0, + pointing to that host. If one or more MX RRs are found for a given + name, SMTP systems MUST NOT utilize any A RRs associated with that + name unless they are located using the MX RRs; the "implicit MX" rule + above applies only if there are no MX records present. If MX records + are present, but none of them are usable, this situation MUST be + reported as an error. + + When the lookup succeeds, the mapping can result in a list of + alternative delivery addresses rather than a single address, because + of multiple MX records, multihoming, or both. To provide reliable + mail transmission, the SMTP client MUST be able to try (and retry) + each of the relevant addresses in this list in order, until a + delivery attempt succeeds. However, there MAY also be a configurable + limit on the number of alternate addresses that can be tried. In any + case, the SMTP client SHOULD try at least two addresses. + + + +Klensin Standards Track [Page 60] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + Two types of information is used to rank the host addresses: multiple + MX records, and multihomed hosts. + + Multiple MX records contain a preference indication that MUST be used + in sorting (see below). Lower numbers are more preferred than higher + ones. If there are multiple destinations with the same preference + and there is no clear reason to favor one (e.g., by recognition of an + easily-reached address), then the sender-SMTP MUST randomize them to + spread the load across multiple mail exchangers for a specific + organization. + + The destination host (perhaps taken from the preferred MX record) may + be multihomed, in which case the domain name resolver will return a + list of alternative IP addresses. It is the responsibility of the + domain name resolver interface to have ordered this list by + decreasing preference if necessary, and SMTP MUST try them in the + order presented. + + Although the capability to try multiple alternative addresses is + required, specific installations may want to limit or disable the use + of alternative addresses. The question of whether a sender should + attempt retries using the different addresses of a multihomed host + has been controversial. The main argument for using the multiple + addresses is that it maximizes the probability of timely delivery, + and indeed sometimes the probability of any delivery; the counter- + argument is that it may result in unnecessary resource use. Note + that resource use is also strongly determined by the sending strategy + discussed in section 4.5.4.1. + + If an SMTP server receives a message with a destination for which it + is a designated Mail eXchanger, it MAY relay the message (potentially + after having rewritten the MAIL FROM and/or RCPT TO addresses), make + final delivery of the message, or hand it off using some mechanism + outside the SMTP-provided transport environment. Of course, neither + of the latter require that the list of MX records be examined + further. + + If it determines that it should relay the message without rewriting + the address, it MUST sort the MX records to determine candidates for + delivery. The records are first ordered by preference, with the + lowest-numbered records being most preferred. The relay host MUST + then inspect the list for any of the names or addresses by which it + might be known in mail transactions. If a matching record is found, + all records at that preference level and higher-numbered ones MUST be + discarded from consideration. If there are no records left at that + point, it is an error condition, and the message MUST be returned as + undeliverable. If records do remain, they SHOULD be tried, best + preference first, as described above. + + + +Klensin Standards Track [Page 61] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +6. Problem Detection and Handling + +6.1 Reliable Delivery and Replies by Email + + When the receiver-SMTP accepts a piece of mail (by sending a "250 OK" + message in response to DATA), it is accepting responsibility for + delivering or relaying the message. It must take this responsibility + seriously. It MUST NOT lose the message for frivolous reasons, such + as because the host later crashes or because of a predictable + resource shortage. + + If there is a delivery failure after acceptance of a message, the + receiver-SMTP MUST formulate and mail a notification message. This + notification MUST be sent using a null ("<>") reverse path in the + envelope. The recipient of this notification MUST be the address + from the envelope return path (or the Return-Path: line). However, + if this address is null ("<>"), the receiver-SMTP MUST NOT send a + notification. Obviously, nothing in this section can or should + prohibit local decisions (i.e., as part of the same system + environment as the receiver-SMTP) to log or otherwise transmit + information about null address events locally if that is desired. If + the address is an explicit source route, it MUST be stripped down to + its final hop. + + For example, suppose that an error notification must be sent for a + message that arrived with: + + MAIL FROM:<@a,@b:user@d> + + The notification message MUST be sent using: + + RCPT TO: + + Some delivery failures after the message is accepted by SMTP will be + unavoidable. For example, it may be impossible for the receiving + SMTP server to validate all the delivery addresses in RCPT command(s) + due to a "soft" domain system error, because the target is a mailing + list (see earlier discussion of RCPT), or because the server is + acting as a relay and has no immediate access to the delivering + system. + + To avoid receiving duplicate messages as the result of timeouts, a + receiver-SMTP MUST seek to minimize the time required to respond to + the final . end of data indicator. See RFC 1047 [28] for + a discussion of this problem. + + + + + + +Klensin Standards Track [Page 62] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +6.2 Loop Detection + + Simple counting of the number of "Received:" headers in a message has + proven to be an effective, although rarely optimal, method of + detecting loops in mail systems. SMTP servers using this technique + SHOULD use a large rejection threshold, normally at least 100 + Received entries. Whatever mechanisms are used, servers MUST contain + provisions for detecting and stopping trivial loops. + +6.3 Compensating for Irregularities + + Unfortunately, variations, creative interpretations, and outright + violations of Internet mail protocols do occur; some would suggest + that they occur quite frequently. The debate as to whether a well- + behaved SMTP receiver or relay should reject a malformed message, + attempt to pass it on unchanged, or attempt to repair it to increase + the odds of successful delivery (or subsequent reply) began almost + with the dawn of structured network mail and shows no signs of + abating. Advocates of rejection claim that attempted repairs are + rarely completely adequate and that rejection of bad messages is the + only way to get the offending software repaired. Advocates of + "repair" or "deliver no matter what" argue that users prefer that + mail go through it if at all possible and that there are significant + market pressures in that direction. In practice, these market + pressures may be more important to particular vendors than strict + conformance to the standards, regardless of the preference of the + actual developers. + + The problems associated with ill-formed messages were exacerbated by + the introduction of the split-UA mail reading protocols [3, 26, 5, + 21]. These protocols have encouraged the use of SMTP as a posting + protocol, and SMTP servers as relay systems for these client hosts + (which are often only intermittently connected to the Internet). + Historically, many of those client machines lacked some of the + mechanisms and information assumed by SMTP (and indeed, by the mail + format protocol [7]). Some could not keep adequate track of time; + others had no concept of time zones; still others could not identify + their own names or addresses; and, of course, none could satisfy the + assumptions that underlay RFC 822's conception of authenticated + addresses. + + In response to these weak SMTP clients, many SMTP systems now + complete messages that are delivered to them in incomplete or + incorrect form. This strategy is generally considered appropriate + when the server can identify or authenticate the client, and there + are prior agreements between them. By contrast, there is at best + great concern about fixes applied by a relay or delivery SMTP server + that has little or no knowledge of the user or client machine. + + + +Klensin Standards Track [Page 63] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + The following changes to a message being processed MAY be applied + when necessary by an originating SMTP server, or one used as the + target of SMTP as an initial posting protocol: + + - Addition of a message-id field when none appears + + - Addition of a date, time or time zone when none appears + + - Correction of addresses to proper FQDN format + + The less information the server has about the client, the less likely + these changes are to be correct and the more caution and conservatism + should be applied when considering whether or not to perform fixes + and how. These changes MUST NOT be applied by an SMTP server that + provides an intermediate relay function. + + In all cases, properly-operating clients supplying correct + information are preferred to corrections by the SMTP server. In all + cases, documentation of actions performed by the servers (in trace + fields and/or header comments) is strongly encouraged. + +7. Security Considerations + +7.1 Mail Security and Spoofing + + SMTP mail is inherently insecure in that it is feasible for even + fairly casual users to negotiate directly with receiving and relaying + SMTP servers and create messages that will trick a naive recipient + into believing that they came from somewhere else. Constructing such + a message so that the "spoofed" behavior cannot be detected by an + expert is somewhat more difficult, but not sufficiently so as to be a + deterrent to someone who is determined and knowledgeable. + Consequently, as knowledge of Internet mail increases, so does the + knowledge that SMTP mail inherently cannot be authenticated, or + integrity checks provided, at the transport level. Real mail + security lies only in end-to-end methods involving the message + bodies, such as those which use digital signatures (see [14] and, + e.g., PGP [4] or S/MIME [31]). + + Various protocol extensions and configuration options that provide + authentication at the transport level (e.g., from an SMTP client to + an SMTP server) improve somewhat on the traditional situation + described above. However, unless they are accompanied by careful + handoffs of responsibility in a carefully-designed trust environment, + they remain inherently weaker than end-to-end mechanisms which use + digitally signed messages rather than depending on the integrity of + the transport system. + + + + +Klensin Standards Track [Page 64] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + Efforts to make it more difficult for users to set envelope return + path and header "From" fields to point to valid addresses other than + their own are largely misguided: they frustrate legitimate + applications in which mail is sent by one user on behalf of another + or in which error (or normal) replies should be directed to a special + address. (Systems that provide convenient ways for users to alter + these fields on a per-message basis should attempt to establish a + primary and permanent mailbox address for the user so that Sender + fields within the message data can be generated sensibly.) + + This specification does not further address the authentication issues + associated with SMTP other than to advocate that useful functionality + not be disabled in the hope of providing some small margin of + protection against an ignorant user who is trying to fake mail. + +7.2 "Blind" Copies + + Addresses that do not appear in the message headers may appear in the + RCPT commands to an SMTP server for a number of reasons. The two + most common involve the use of a mailing address as a "list exploder" + (a single address that resolves into multiple addresses) and the + appearance of "blind copies". Especially when more than one RCPT + command is present, and in order to avoid defeating some of the + purpose of these mechanisms, SMTP clients and servers SHOULD NOT copy + the full set of RCPT command arguments into the headers, either as + part of trace headers or as informational or private-extension + headers. Since this rule is often violated in practice, and cannot + be enforced, sending SMTP systems that are aware of "bcc" use MAY + find it helpful to send each blind copy as a separate message + transaction containing only a single RCPT command. + + There is no inherent relationship between either "reverse" (from + MAIL, SAML, etc., commands) or "forward" (RCPT) addresses in the SMTP + transaction ("envelope") and the addresses in the headers. Receiving + systems SHOULD NOT attempt to deduce such relationships and use them + to alter the headers of the message for delivery. The popular + "Apparently-to" header is a violation of this principle as well as a + common source of unintended information disclosure and SHOULD NOT be + used. + +7.3 VRFY, EXPN, and Security + + As discussed in section 3.5, individual sites may want to disable + either or both of VRFY or EXPN for security reasons. As a corollary + to the above, implementations that permit this MUST NOT appear to + have verified addresses that are not, in fact, verified. If a site + + + + + +Klensin Standards Track [Page 65] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + disables these commands for security reasons, the SMTP server MUST + return a 252 response, rather than a code that could be confused with + successful or unsuccessful verification. + + Returning a 250 reply code with the address listed in the VRFY + command after having checked it only for syntax violates this rule. + Of course, an implementation that "supports" VRFY by always returning + 550 whether or not the address is valid is equally not in + conformance. + + Within the last few years, the contents of mailing lists have become + popular as an address information source for so-called "spammers." + The use of EXPN to "harvest" addresses has increased as list + administrators have installed protections against inappropriate uses + of the lists themselves. Implementations SHOULD still provide + support for EXPN, but sites SHOULD carefully evaluate the tradeoffs. + As authentication mechanisms are introduced into SMTP, some sites may + choose to make EXPN available only to authenticated requestors. + +7.4 Information Disclosure in Announcements + + There has been an ongoing debate about the tradeoffs between the + debugging advantages of announcing server type and version (and, + sometimes, even server domain name) in the greeting response or in + response to the HELP command and the disadvantages of exposing + information that might be useful in a potential hostile attack. The + utility of the debugging information is beyond doubt. Those who + argue for making it available point out that it is far better to + actually secure an SMTP server rather than hope that trying to + conceal known vulnerabilities by hiding the server's precise identity + will provide more protection. Sites are encouraged to evaluate the + tradeoff with that issue in mind; implementations are strongly + encouraged to minimally provide for making type and version + information available in some way to other network hosts. + +7.5 Information Disclosure in Trace Fields + + In some circumstances, such as when mail originates from within a LAN + whose hosts are not directly on the public Internet, trace + ("Received") fields produced in conformance with this specification + may disclose host names and similar information that would not + normally be available. This ordinarily does not pose a problem, but + sites with special concerns about name disclosure should be aware of + it. Also, the optional FOR clause should be supplied with caution or + not at all when multiple recipients are involved lest it + inadvertently disclose the identities of "blind copy" recipients to + others. + + + + +Klensin Standards Track [Page 66] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +7.6 Information Disclosure in Message Forwarding + + As discussed in section 3.4, use of the 251 or 551 reply codes to + identify the replacement address associated with a mailbox may + inadvertently disclose sensitive information. Sites that are + concerned about those issues should ensure that they select and + configure servers appropriately. + +7.7 Scope of Operation of SMTP Servers + + It is a well-established principle that an SMTP server may refuse to + accept mail for any operational or technical reason that makes sense + to the site providing the server. However, cooperation among sites + and installations makes the Internet possible. If sites take + excessive advantage of the right to reject traffic, the ubiquity of + email availability (one of the strengths of the Internet) will be + threatened; considerable care should be taken and balance maintained + if a site decides to be selective about the traffic it will accept + and process. + + In recent years, use of the relay function through arbitrary sites + has been used as part of hostile efforts to hide the actual origins + of mail. Some sites have decided to limit the use of the relay + function to known or identifiable sources, and implementations SHOULD + provide the capability to perform this type of filtering. When mail + is rejected for these or other policy reasons, a 550 code SHOULD be + used in response to EHLO, MAIL, or RCPT as appropriate. + +8. IANA Considerations + + IANA will maintain three registries in support of this specification. + The first consists of SMTP service extensions with the associated + keywords, and, as needed, parameters and verbs. As specified in + section 2.2.2, no entry may be made in this registry that starts in + an "X". Entries may be made only for service extensions (and + associated keywords, parameters, or verbs) that are defined in + standards-track or experimental RFCs specifically approved by the + IESG for this purpose. + + The second registry consists of "tags" that identify forms of domain + literals other than those for IPv4 addresses (specified in RFC 821 + and in this document) and IPv6 addresses (specified in this + document). Additional literal types require standardization before + being used; none are anticipated at this time. + + The third, established by RFC 821 and renewed by this specification, + is a registry of link and protocol identifiers to be used with the + "via" and "with" subclauses of the time stamp ("Received: header") + + + +Klensin Standards Track [Page 67] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + described in section 4.4. Link and protocol identifiers in addition + to those specified in this document may be registered only by + standardization or by way of an RFC-documented, IESG-approved, + Experimental protocol extension. + +9. References + + [1] American National Standards Institute (formerly United States of + America Standards Institute), X3.4, 1968, "USA Code for + Information Interchange". ANSI X3.4-1968 has been replaced by + newer versions with slight modifications, but the 1968 version + remains definitive for the Internet. + + [2] Braden, R., "Requirements for Internet hosts - application and + support", STD 3, RFC 1123, October 1989. + + [3] Butler, M., Chase, D., Goldberger, J., Postel, J. and J. + Reynolds, "Post Office Protocol - version 2", RFC 937, February + 1985. + + [4] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, "OpenPGP + Message Format", RFC 2440, November 1998. + + [5] Crispin, M., "Interactive Mail Access Protocol - Version 2", RFC + 1176, August 1990. + + [6] Crispin, M., "Internet Message Access Protocol - Version 4", RFC + 2060, December 1996. + + [7] Crocker, D., "Standard for the Format of ARPA Internet Text + Messages", RFC 822, August 1982. + + [8] Crocker, D. and P. Overell, Eds., "Augmented BNF for Syntax + Specifications: ABNF", RFC 2234, November 1997. + + [9] De Winter, J., "SMTP Service Extension for Remote Message Queue + Starting", RFC 1985, August 1996. + + [10] Fajman, R., "An Extensible Message Format for Message + Disposition Notifications", RFC 2298, March 1998. + + [11] Freed, N, "Behavior of and Requirements for Internet Firewalls", + RFC 2979, October 2000. + + [12] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, December 1996. + + + + +Klensin Standards Track [Page 68] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + [13] Freed, N., "SMTP Service Extension for Command Pipelining", RFC + 2920, September 2000. + + [14] Galvin, J., Murphy, S., Crocker, S. and N. Freed, "Security + Multiparts for MIME: Multipart/Signed and Multipart/Encrypted", + RFC 1847, October 1995. + + [15] Gellens, R. and J. Klensin, "Message Submission", RFC 2476, + December 1998. + + [16] Kille, S., "Mapping between X.400 and RFC822/MIME", RFC 2156, + January 1998. + + [17] Hinden, R and S. Deering, Eds. "IP Version 6 Addressing + Architecture", RFC 2373, July 1998. + + [18] Klensin, J., Freed, N. and K. Moore, "SMTP Service Extension for + Message Size Declaration", STD 10, RFC 1870, November 1995. + + [19] Klensin, J., Freed, N., Rose, M., Stefferud, E. and D. Crocker, + "SMTP Service Extensions", STD 10, RFC 1869, November 1995. + + [20] Klensin, J., Freed, N., Rose, M., Stefferud, E. and D. Crocker, + "SMTP Service Extension for 8bit-MIMEtransport", RFC 1652, July + 1994. + + [21] Lambert, M., "PCMAIL: A distributed mail system for personal + computers", RFC 1056, July 1988. + + [22] Mockapetris, P., "Domain names - implementation and + specification", STD 13, RFC 1035, November 1987. + + Mockapetris, P., "Domain names - concepts and facilities", STD + 13, RFC 1034, November 1987. + + [23] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part + Three: Message Header Extensions for Non-ASCII Text", RFC 2047, + December 1996. + + [24] Moore, K., "SMTP Service Extension for Delivery Status + Notifications", RFC 1891, January 1996. + + [25] Moore, K., and G. Vaudreuil, "An Extensible Message Format for + Delivery Status Notifications", RFC 1894, January 1996. + + [26] Myers, J. and M. Rose, "Post Office Protocol - Version 3", STD + 53, RFC 1939, May 1996. + + + + +Klensin Standards Track [Page 69] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + [27] Partridge, C., "Mail routing and the domain system", RFC 974, + January 1986. + + [28] Partridge, C., "Duplicate messages and SMTP", RFC 1047, February + 1988. + + [29] Postel, J., ed., "Transmission Control Protocol - DARPA Internet + Program Protocol Specification", STD 7, RFC 793, September 1981. + + [30] Postel, J., "Simple Mail Transfer Protocol", RFC 821, August + 1982. + + [31] Ramsdell, B., Ed., "S/MIME Version 3 Message Specification", RFC + 2633, June 1999. + + [32] Resnick, P., Ed., "Internet Message Format", RFC 2822, April + 2001. + + [33] Vaudreuil, G., "SMTP Service Extensions for Transmission of + Large and Binary MIME Messages", RFC 1830, August 1995. + + [34] Vaudreuil, G., "Enhanced Mail System Status Codes", RFC 1893, + January 1996. + +10. Editor's Address + + John C. Klensin + AT&T Laboratories + 99 Bedford St + Boston, MA 02111 USA + + Phone: 617-574-3076 + EMail: klensin@research.att.com + +11. Acknowledgments + + Many people worked long and hard on the many iterations of this + document. There was wide-ranging debate in the IETF DRUMS Working + Group, both on its mailing list and in face to face discussions, + about many technical issues and the role of a revised standard for + Internet mail transport, and many contributors helped form the + wording in this specification. The hundreds of participants in the + many discussions since RFC 821 was produced are too numerous to + mention, but they all helped this document become what it is. + + + + + + + +Klensin Standards Track [Page 70] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +APPENDICES + +A. TCP Transport Service + + The TCP connection supports the transmission of 8-bit bytes. The + SMTP data is 7-bit ASCII characters. Each character is transmitted + as an 8-bit byte with the high-order bit cleared to zero. Service + extensions may modify this rule to permit transmission of full 8-bit + data bytes as part of the message body, but not in SMTP commands or + responses. + +B. Generating SMTP Commands from RFC 822 Headers + + Some systems use RFC 822 headers (only) in a mail submission + protocol, or otherwise generate SMTP commands from RFC 822 headers + when such a message is handed to an MTA from a UA. While the MTA-UA + protocol is a private matter, not covered by any Internet Standard, + there are problems with this approach. For example, there have been + repeated problems with proper handling of "bcc" copies and + redistribution lists when information that conceptually belongs to a + mail envelopes is not separated early in processing from header + information (and kept separate). + + It is recommended that the UA provide its initial ("submission + client") MTA with an envelope separate from the message itself. + However, if the envelope is not supplied, SMTP commands SHOULD be + generated as follows: + + 1. Each recipient address from a TO, CC, or BCC header field SHOULD + be copied to a RCPT command (generating multiple message copies if + that is required for queuing or delivery). This includes any + addresses listed in a RFC 822 "group". Any BCC fields SHOULD then + be removed from the headers. Once this process is completed, the + remaining headers SHOULD be checked to verify that at least one + To:, Cc:, or Bcc: header remains. If none do, then a bcc: header + with no additional information SHOULD be inserted as specified in + [32]. + + 2. The return address in the MAIL command SHOULD, if possible, be + derived from the system's identity for the submitting (local) + user, and the "From:" header field otherwise. If there is a + system identity available, it SHOULD also be copied to the Sender + header field if it is different from the address in the From + header field. (Any Sender field that was already there SHOULD be + removed.) Systems may provide a way for submitters to override + the envelope return address, but may want to restrict its use to + privileged users. This will not prevent mail forgery, but may + lessen its incidence; see section 7.1. + + + +Klensin Standards Track [Page 71] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + When an MTA is being used in this way, it bears responsibility for + ensuring that the message being transmitted is valid. The mechanisms + for checking that validity, and for handling (or returning) messages + that are not valid at the time of arrival, are part of the MUA-MTA + interface and not covered by this specification. + + A submission protocol based on Standard RFC 822 information alone + MUST NOT be used to gateway a message from a foreign (non-SMTP) mail + system into an SMTP environment. Additional information to construct + an envelope must come from some source in the other environment, + whether supplemental headers or the foreign system's envelope. + + Attempts to gateway messages using only their header "to" and "cc" + fields have repeatedly caused mail loops and other behavior adverse + to the proper functioning of the Internet mail environment. These + problems have been especially common when the message originates from + an Internet mailing list and is distributed into the foreign + environment using envelope information. When these messages are then + processed by a header-only remailer, loops back to the Internet + environment (and the mailing list) are almost inevitable. + +C. Source Routes + + Historically, the was a reverse source routing list of + hosts and a source mailbox. The first host in the + SHOULD be the host sending the MAIL command. Similarly, the + may be a source routing lists of hosts and a + destination mailbox. However, in general, the SHOULD + contain only a mailbox and domain name, relying on the domain name + system to supply routing information if required. The use of source + routes is deprecated; while servers MUST be prepared to receive and + handle them as discussed in section 3.3 and F.2, clients SHOULD NOT + transmit them and this section was included only to provide context. + + For relay purposes, the forward-path may be a source route of the + form "@ONE,@TWO:JOE@THREE", where ONE, TWO, and THREE MUST BE fully- + qualified domain names. This form is used to emphasize the + distinction between an address and a route. The mailbox is an + absolute address, and the route is information about how to get + there. The two concepts should not be confused. + + If source routes are used, RFC 821 and the text below should be + consulted for the mechanisms for constructing and updating the + forward- and reverse-paths. + + + + + + + +Klensin Standards Track [Page 72] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + The SMTP server transforms the command arguments by moving its own + identifier (its domain name or that of any domain for which it is + acting as a mail exchanger), if it appears, from the forward-path to + the beginning of the reverse-path. + + Notice that the forward-path and reverse-path appear in the SMTP + commands and replies, but not necessarily in the message. That is, + there is no need for these paths and especially this syntax to appear + in the "To:" , "From:", "CC:", etc. fields of the message header. + Conversely, SMTP servers MUST NOT derive final message delivery + information from message header fields. + + When the list of hosts is present, it is a "reverse" source route and + indicates that the mail was relayed through each host on the list + (the first host in the list was the most recent relay). This list is + used as a source route to return non-delivery notices to the sender. + As each relay host adds itself to the beginning of the list, it MUST + use its name as known in the transport environment to which it is + relaying the mail rather than that of the transport environment from + which the mail came (if they are different). + +D. Scenarios + + This section presents complete scenarios of several types of SMTP + sessions. In the examples, "C:" indicates what is said by the SMTP + client, and "S:" indicates what is said by the SMTP server. + +D.1 A Typical SMTP Transaction Scenario + + This SMTP example shows mail sent by Smith at host bar.com, to Jones, + Green, and Brown at host foo.com. Here we assume that host bar.com + contacts host foo.com directly. The mail is accepted for Jones and + Brown. Green does not have a mailbox at host foo.com. + + S: 220 foo.com Simple Mail Transfer Service Ready + C: EHLO bar.com + S: 250-foo.com greets bar.com + S: 250-8BITMIME + S: 250-SIZE + S: 250-DSN + S: 250 HELP + C: MAIL FROM: + S: 250 OK + C: RCPT TO: + S: 250 OK + C: RCPT TO: + S: 550 No such user here + C: RCPT TO: + + + +Klensin Standards Track [Page 73] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + S: 250 OK + C: DATA + S: 354 Start mail input; end with . + C: Blah blah blah... + C: ...etc. etc. etc. + C: . + S: 250 OK + C: QUIT + S: 221 foo.com Service closing transmission channel + +D.2 Aborted SMTP Transaction Scenario + + S: 220 foo.com Simple Mail Transfer Service Ready + C: EHLO bar.com + S: 250-foo.com greets bar.com + S: 250-8BITMIME + S: 250-SIZE + S: 250-DSN + S: 250 HELP + C: MAIL FROM: + S: 250 OK + C: RCPT TO: + S: 250 OK + C: RCPT TO: + S: 550 No such user here + C: RSET + S: 250 OK + C: QUIT + S: 221 foo.com Service closing transmission channel + +D.3 Relayed Mail Scenario + + Step 1 -- Source Host to Relay Host + + S: 220 foo.com Simple Mail Transfer Service Ready + C: EHLO bar.com + S: 250-foo.com greets bar.com + S: 250-8BITMIME + S: 250-SIZE + S: 250-DSN + S: 250 HELP + C: MAIL FROM: + S: 250 OK + C: RCPT TO:<@foo.com:Jones@XYZ.COM> + S: 250 OK + C: DATA + S: 354 Start mail input; end with . + C: Date: Thu, 21 May 1998 05:33:29 -0700 + + + +Klensin Standards Track [Page 74] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + C: From: John Q. Public + C: Subject: The Next Meeting of the Board + C: To: Jones@xyz.com + C: + C: Bill: + C: The next meeting of the board of directors will be + C: on Tuesday. + C: John. + C: . + S: 250 OK + C: QUIT + S: 221 foo.com Service closing transmission channel + + Step 2 -- Relay Host to Destination Host + + S: 220 xyz.com Simple Mail Transfer Service Ready + C: EHLO foo.com + S: 250 xyz.com is on the air + C: MAIL FROM:<@foo.com:JQP@bar.com> + S: 250 OK + C: RCPT TO: + S: 250 OK + C: DATA + S: 354 Start mail input; end with . + C: Received: from bar.com by foo.com ; Thu, 21 May 1998 + C: 05:33:29 -0700 + C: Date: Thu, 21 May 1998 05:33:22 -0700 + C: From: John Q. Public + C: Subject: The Next Meeting of the Board + C: To: Jones@xyz.com + C: + C: Bill: + C: The next meeting of the board of directors will be + C: on Tuesday. + C: John. + C: . + S: 250 OK + C: QUIT + S: 221 foo.com Service closing transmission channel + +D.4 Verifying and Sending Scenario + + S: 220 foo.com Simple Mail Transfer Service Ready + C: EHLO bar.com + S: 250-foo.com greets bar.com + S: 250-8BITMIME + S: 250-SIZE + S: 250-DSN + + + +Klensin Standards Track [Page 75] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + + S: 250-VRFY + S: 250 HELP + C: VRFY Crispin + S: 250 Mark Crispin + C: SEND FROM: + S: 250 OK + C: RCPT TO: + S: 250 OK + C: DATA + S: 354 Start mail input; end with . + C: Blah blah blah... + C: ...etc. etc. etc. + C: . + S: 250 OK + C: QUIT + S: 221 foo.com Service closing transmission channel + +E. Other Gateway Issues + + In general, gateways between the Internet and other mail systems + SHOULD attempt to preserve any layering semantics across the + boundaries between the two mail systems involved. Gateway- + translation approaches that attempt to take shortcuts by mapping, + (such as envelope information from one system to the message headers + or body of another) have generally proven to be inadequate in + important ways. Systems translating between environments that do not + support both envelopes and headers and Internet mail must be written + with the understanding that some information loss is almost + inevitable. + +F. Deprecated Features of RFC 821 + + A few features of RFC 821 have proven to be problematic and SHOULD + NOT be used in Internet mail. + +F.1 TURN + + This command, described in RFC 821, raises important security issues + since, in the absence of strong authentication of the host requesting + that the client and server switch roles, it can easily be used to + divert mail from its correct destination. Its use is deprecated; + SMTP systems SHOULD NOT use it unless the server can authenticate the + client. + + + + + + + + +Klensin Standards Track [Page 76] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +F.2 Source Routing + + RFC 821 utilized the concept of explicit source routing to get mail + from one host to another via a series of relays. The requirement to + utilize source routes in regular mail traffic was eliminated by the + introduction of the domain name system "MX" record and the last + significant justification for them was eliminated by the + introduction, in RFC 1123, of a clear requirement that addresses + following an "@" must all be fully-qualified domain names. + Consequently, the only remaining justifications for the use of source + routes are support for very old SMTP clients or MUAs and in mail + system debugging. They can, however, still be useful in the latter + circumstance and for routing mail around serious, but temporary, + problems such as problems with the relevant DNS records. + + SMTP servers MUST continue to accept source route syntax as specified + in the main body of this document and in RFC 1123. They MAY, if + necessary, ignore the routes and utilize only the target domain in + the address. If they do utilize the source route, the message MUST + be sent to the first domain shown in the address. In particular, a + server MUST NOT guess at shortcuts within the source route. + + Clients SHOULD NOT utilize explicit source routing except under + unusual circumstances, such as debugging or potentially relaying + around firewall or mail system configuration errors. + +F.3 HELO + + As discussed in sections 3.1 and 4.1.1, EHLO is strongly preferred to + HELO when the server will accept the former. Servers must continue + to accept and process HELO in order to support older clients. + +F.4 #-literals + + RFC 821 provided for specifying an Internet address as a decimal + integer host number prefixed by a pound sign, "#". In practice, that + form has been obsolete since the introduction of TCP/IP. It is + deprecated and MUST NOT be used. + +F.5 Dates and Years + + When dates are inserted into messages by SMTP clients or servers + (e.g., in trace fields), four-digit years MUST BE used. Two-digit + years are deprecated; three-digit years were never permitted in the + Internet mail system. + + + + + + +Klensin Standards Track [Page 77] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +F.6 Sending versus Mailing + + In addition to specifying a mechanism for delivering messages to + user's mailboxes, RFC 821 provided additional, optional, commands to + deliver messages directly to the user's terminal screen. These + commands (SEND, SAML, SOML) were rarely implemented, and changes in + workstation technology and the introduction of other protocols may + have rendered them obsolete even where they are implemented. + + Clients SHOULD NOT provide SEND, SAML, or SOML as services. Servers + MAY implement them. If they are implemented by servers, the + implementation model specified in RFC 821 MUST be used and the + command names MUST be published in the response to the EHLO command. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Klensin Standards Track [Page 78] + +RFC 2821 Simple Mail Transfer Protocol April 2001 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2001). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Klensin Standards Track [Page 79] + diff --git a/docs/rfc/rfc2986.txt b/docs/rfc/rfc2986.txt new file mode 100644 index 00000000..ec8f1e33 --- /dev/null +++ b/docs/rfc/rfc2986.txt @@ -0,0 +1,787 @@ + + + + + + +Network Working Group M. Nystrom +Request for Comments: 2986 B. Kaliski +Obsoletes: 2314 RSA Security +Category: Informational November 2000 + + + PKCS #10: Certification Request Syntax Specification + Version 1.7 + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + This memo represents a republication of PKCS #10 v1.7 from RSA + Laboratories' Public-Key Cryptography Standards (PKCS) series, and + change control is retained within the PKCS process. The body of this + document, except for the security considerations section, is taken + directly from the PKCS #9 v2.0 or the PKCS #10 v1.7 document. + + This memo describes a syntax for certification requests. + +Table of Contents + + 1. Introduction ................................................. 2 + 2. Definitions and notation ..................................... 2 + 2.1 Definitions ................................................. 2 + 2.2 Notation .................................................... 4 + 3. Overview ..................................................... 4 + 4. Certification request syntax ................................. 5 + 4.1 CertificationRequestInfo .................................... 5 + 4.2 CertificationRequest ........................................ 7 + 5. Security Considerations ...................................... 8 + 6. Authors' Addresses ........................................... 8 + A. ASN.1 module ................................................. 9 + B. Intellectual property considerations ........................ 10 + C. Revision history ............................................ 10 + D. References .................................................. 11 + E. Contact information & About PKCS ............................ 12 + Full Copyright Statement ........................................ 14 + + + + +Nystrom & Kaliski Informational [Page 1] + +RFC 2986 Certification Request Syntax Specification November 2000 + + +1. Introduction + + This document describes syntax for certification requests. A + certification request consists of a distinguished name, a public key, + and optionally a set of attributes, collectively signed by the entity + requesting certification. Certification requests are sent to a + certification authority, which transforms the request into an X.509 + [9] public-key certificate. (In what form the certification + authority returns the newly signed certificate is outside the scope + of this document. A PKCS #7 [2] message is one possibility.) + + The intention of including a set of attributes is twofold: to provide + other information about a given entity , or a "challenge password" by + which the entity may later request certificate revocation; and to + provide attributes for inclusion in X.509 certificates. A non- + exhaustive list of attributes is given in PKCS #9 [3]. + + Certification authorities may also require non-electronic forms of + request and may return non-electronic replies. It is expected that + descriptions of such forms, which are outside the scope of this + document, will be available from certification authorities. + + The preliminary intended application of this document is to support + PKCS #7 cryptographic messages, but it is expected that other + applications will be developed (see e.g. [4]). + +2. Definitions and notation + + 2.1 Definitions + + For the purposes of this document, the following definitions apply. + + ALGORITHM An information object class defined in X.509 to + describe objects composed of an algorithm (a unique + object identifier) and its parameters (any ASN.1 + type). The values of objects in this class can be + represented by the ASN.1 type AlgorithmIdentifier{}. + ALGORITHM is defined as the "useful" information + object class TYPE-IDENTIFIER, specified in [11], + Annex A. + + AlgorithmIdentifier{} + A useful parameterized version of X.509 type + AlgorithmIdentifier is defined in this document. + This type tightly binds pairs of algorithm object + identifiers to their associated parameter types. + When referenced, the single parameter of + AlgorithmIdentifier{} specifies a constraint on the + + + +Nystrom & Kaliski Informational [Page 2] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + pairs of values that may appear in that instance of + the type. The encoded values of + AlgorithmIdentifier{} are equivalent to those of type + AlgorithmIdentifier. + + ASN.1 Abstract Syntax Notation One, as defined in the ASN.1 + standards ([10], [11], [12], and [13]). + + ATTRIBUTE This class describes objects composed of an attribute + (a unique object identifier) and an associated set of + attribute values (any ASN.1 type). The values of + objects in this class can be represented by type + Attribute{}. + + Attribute{} A useful parameterized version of X.501 [8] type + Attribute is defined in this document. This type + tightly binds pairs of attribute type object + identifiers to one or more attribute values types. + In the ASN.1 open type notation, an attribute type is + defined as ATTRIBUTE.&id and an attribute value as + ATTRIBUTE.&Type. When referenced, the single + parameter of Attribute{} specifies a constraint on + the pairs of values that may appear in an instance of + the type. The encoded values of Attribute{} are + equivalent to those of type Attribute. + + BER Basic Encoding Rules for ASN.1, as defined in X.690 + ([14]). + + Certificate A type that binds a subject entity's distinguished + name to a public key with a digital signature. This + type is defined in X.509. This type also contains + the distinguished name of the certificate issuer (the + signer), an issuer-specific serial number, the + issuer's signature algorithm identifier, a validity + period, and an optional set of certificate + extensions. + + DER Distinguished Encoding Rules for ASN.1, as defined in + X.690. DER is a subset of BER. + + Name A type that uniquely identifies or "distinguishes" + objects in an X.500 [7] directory. This type is + defined in X.501. In an X.509 certificate, the type + identifies the certificate issuer and the certificate + subject, the entity whose public key is certified. + + + + + +Nystrom & Kaliski Informational [Page 3] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + 2.2 Notation + + No special notation is used in this document. + +3. Overview + + A certification request consists of three parts: "certification + request information," a signature algorithm identifier, and a digital + signature on the certification request information. The + certification request information consists of the entity's + distinguished name, the entity's public key, and a set of attributes + providing other information about the entity. + + The process by which a certification request is constructed involves + the following steps: + + 1. A CertificationRequestInfo value containing a subject + distinguished name, a subject public key, and optionally a + set of attributes is constructed by an entity requesting + certification. + + 2. The CertificationRequestInfo value is signed with the subject + entity's private key. (See Section 4.2.) + + 3. The CertificationRequestInfo value, a signature algorithm + identifier, and the entity's signature are collected together + into a CertificationRequest value, defined below. + + A certification authority fulfills the request by authenticating the + requesting entity and verifying the entity's signature, and, if the + request is valid, constructing an X.509 certificate from the + distinguished name and public key, the issuer name, and the + certification authority's choice of serial number, validity period, + and signature algorithm. If the certification request contains any + PKCS #9 attributes, the certification authority may also use the + values in these attributes as well as other information known to the + certification authority to construct X.509 certificate extensions. + + In what form the certification authority returns the new certificate + is outside the scope of this document. One possibility is a PKCS #7 + cryptographic message with content type signedData, following the + degenerate case where there are no signers. The return message may + include a certification path from the new certificate to the + certification authority. It may also include other certificates such + as cross-certificates that the certification authority considers + helpful, and it may include certificate-revocation lists (CRLs). + Another possibility is that the certification authority inserts the + new certificate into a central database. + + + +Nystrom & Kaliski Informational [Page 4] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + Note 1 - An entity would typically send a certification request after + generating a public-key/private-key pair, but may also do so after a + change in the entity's distinguished name. + + Note 2 - The signature on the certification request prevents an + entity from requesting a certificate with another party's public key. + Such an attack would give the entity the minor ability to pretend to + be the originator of any message signed by the other party. This + attack is significant only if the entity does not know the message + being signed and the signed part of the message does not identify the + signer. The entity would still not be able to decrypt messages + intended for the other party, of course. + + Note 3 - How the entity sends the certification request to a + certification authority is outside the scope of this document. Both + paper and electronic forms are possible. + + Note 4 - This document is not compatible with the certification + request syntax for Privacy-Enhanced Mail, as described in RFC 1424 + [5]. The syntax here differs in three respects: It allows a set of + attributes; it does not include issuer name, serial number, or + validity period; and it does not require an "innocuous" message to be + signed. This document is designed to minimize request size, an + important feature for certification authorities accepting requests on + paper. + +4. Certification request syntax + + This section is divided into two parts. The first part describes the + certification-request-information type CertificationRequestInfo, and + the second part describes the top-level type CertificationRequest. + + 4.1 CertificationRequestInfo + + Certification request information shall have ASN.1 type + CertificationRequestInfo: + + CertificationRequestInfo ::= SEQUENCE { + version INTEGER { v1(0) } (v1,...), + subject Name, + subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, + attributes [0] Attributes{{ CRIAttributes }} + } + + SubjectPublicKeyInfo { ALGORITHM : IOSet} ::= SEQUENCE { + algorithm AlgorithmIdentifier {{IOSet}}, + subjectPublicKey BIT STRING + } + + + +Nystrom & Kaliski Informational [Page 5] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + PKInfoAlgorithms ALGORITHM ::= { + ... -- add any locally defined algorithms here -- } + + Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} + + CRIAttributes ATTRIBUTE ::= { + ... -- add any locally defined attributes here -- } + + Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { + type ATTRIBUTE.&id({IOSet}), + values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) + } + + The components of type CertificationRequestInfo have the following + meanings: + + version is the version number, for compatibility with future + revisions of this document. It shall be 0 for this version of + the standard. + + subject is the distinguished name of the certificate subject + (the entity whose public key is to be certified). + + subjectPublicKeyInfo contains information about the public key + being certified. The information identifies the entity's + public-key algorithm (and any associated parameters); examples + of public-key algorithms include the rsaEncryption object + identifier from PKCS #1 [1]. The information also includes a + bit-string representation of the entity's public key. For the + public-key algorithm just mentioned, the bit string contains + the DER encoding of a value of PKCS #1 type RSAPublicKey. The + values of type SubjectPublicKeyInfo{} allowed for + subjectPKInfo are constrained to the values specified by the + information object set PKInfoAlgorithms, which includes the + extension marker (...). Definitions of specific algorithm + objects are left to specifications that reference this + document. Such specifications will be interoperable with + their future versions if any additional algorithm objects are + added after the extension marker. + + attributes is a collection of attributes providing additional + information about the subject of the certificate. Some + attribute types that might be useful here are defined in PKCS + #9. An example is the challenge-password attribute, which + specifies a password by which the entity may request + certificate revocation. Another example is information to + appear in X.509 certificate extensions (e.g. the + extensionRequest attribute from PKCS #9). The values of type + + + +Nystrom & Kaliski Informational [Page 6] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + Attributes{} allowed for attributes are constrained to the + values specified by the information object set CRIAttributes. + Definitions of specific attribute objects are left to + specifications that reference this document. Such + specifications will be interoperable with their future + versions if any additional attribute objects are added after + the extension marker. + + 4.2 CertificationRequest + + A certification request shall have ASN.1 type CertificationRequest: + + CertificationRequest ::= SEQUENCE { + certificationRequestInfo CertificationRequestInfo, + signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, + signature BIT STRING + } + + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + + SignatureAlgorithms ALGORITHM ::= { + ... -- add any locally defined algorithms here -- } + + The components of type CertificationRequest have the following + meanings: + + certificateRequestInfo is the "certification request + information." It is the value being signed. + + signatureAlgorithm identifies the signature algorithm (and any + associated parameters) under which the certification-request + information is signed. For example, a specification might + include an ALGORITHM object for PKCS #1's + md5WithRSAEncryption in the information object set + SignatureAlgorithms: + + SignatureAlgorithms ALGORITHM ::= { + ..., + { NULL IDENTIFIED BY md5WithRSAEncryption } + } + + signature is the result of signing the certification request + information with the certification request subject's private + key. + + + + +Nystrom & Kaliski Informational [Page 7] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + The signature process consists of two steps: + + 1. The value of the certificationRequestInfo component is DER + encoded, yielding an octet string. + + 2. The result of step 1 is signed with the certification request + subject's private key under the specified signature + algorithm, yielding a bit string, the signature. + + Note - An equivalent syntax for CertificationRequest could be + written: + + CertificationRequest ::= SIGNED { EncodedCertificationRequestInfo } + (CONSTRAINED BY { -- Verify or sign encoded + -- CertificationRequestInfo -- }) + + EncodedCertificationRequestInfo ::= + TYPE-IDENTIFIER.&Type(CertificationRequestInfo) + + SIGNED { ToBeSigned } ::= SEQUENCE { + toBeSigned ToBeSigned, + algorithm AlgorithmIdentifier { {SignatureAlgorithms} }, + signature BIT STRING + } + +5. Security Considerations + + Security issues are discussed throughout this memo. + +6. Authors' Addresses + + Magnus Nystrom + RSA Security + Box 10704 + S-121 29 Stockholm + Sweden + + EMail: magnus@rsasecurity.com + + + Burt Kaliski + RSA Security + 20 Crosby Drive + Bedford, MA 01730 USA + + EMail: bkaliski@rsasecurity.com + + + + + +Nystrom & Kaliski Informational [Page 8] + +RFC 2986 Certification Request Syntax Specification November 2000 + + +APPENDICES + +A. ASN.1 Module + + This appendix includes all of the ASN.1 type and value definitions + contained in this document in the form of the ASN.1 module PKCS-10. + + PKCS-10 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) + pkcs-10(10) modules(1) pkcs-10(1)} + + DEFINITIONS IMPLICIT TAGS ::= + + BEGIN + + -- EXPORTS All -- + + -- All types and values defined in this module are exported for use + -- in other ASN.1 modules. + + IMPORTS + + informationFramework, authenticationFramework + FROM UsefulDefinitions {joint-iso-itu-t(2) ds(5) module(1) + usefulDefinitions(0) 3} + + ATTRIBUTE, Name + FROM InformationFramework informationFramework + + ALGORITHM + FROM AuthenticationFramework authenticationFramework; + + -- Certificate requests + CertificationRequestInfo ::= SEQUENCE { + version INTEGER { v1(0) } (v1,...), + subject Name, + subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, + attributes [0] Attributes{{ CRIAttributes }} + } + + SubjectPublicKeyInfo {ALGORITHM: IOSet} ::= SEQUENCE { + algorithm AlgorithmIdentifier {{IOSet}}, + subjectPublicKey BIT STRING + } + + PKInfoAlgorithms ALGORITHM ::= { + ... -- add any locally defined algorithms here -- } + + Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} + + + +Nystrom & Kaliski Informational [Page 9] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + CRIAttributes ATTRIBUTE ::= { + ... -- add any locally defined attributes here -- } + + Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { + type ATTRIBUTE.&id({IOSet}), + values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) + } + + CertificationRequest ::= SEQUENCE { + certificationRequestInfo CertificationRequestInfo, + signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, + signature BIT STRING + } + + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + + SignatureAlgorithms ALGORITHM ::= { + ... -- add any locally defined algorithms here -- } + + END + +B. Intellectual property considerations + + RSA Security makes no patent claims on the general constructions + described in this document, although specific underlying techniques + may be covered. + + License to copy this document is granted provided that it is + identified as "RSA Security Inc. Public-Key Cryptography Standards + (PKCS)" in all material mentioning or referencing this document. + + RSA Security makes no representations regarding intellectual property + claims by other parties. Such determination is the responsibility of + the user. + +C. Revision history + + Version 1.0 + + Version 1.0 was the previous version of this document (also + published as "version 1.5" in [6]). + + + + + + + +Nystrom & Kaliski Informational [Page 10] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + Version 1.7 + + This version incorporates several editorial changes, including + updates to the references, and changes to ASN.1 type + definitions. The following substantive changes have been made: + + - This version refers to X.680-X.690, the current international + standards for ASN.1 and its encoding rules. All references + to X.208 and X.209 have been eliminated. + + - The X.690 standard requires that the encoded values of SET OF + components be sorted in ascending order under DER. + Regardless of this, applications should not rely on the + ordering of attribute components. + + - All references to PKCS #6 Extended-Certificate Syntax + Standard have been removed. With the addition of extensions + to X.509 version 3 certificates, RSA Laboratories is + withdrawing support for PKCS #6. + + Note - The reason for using version 1.7 for this document is to avoid + confusion with [6], which is named version 1.5, and an unsupported + PKCS #10 version named Version 1.6. + +D. References + + [1] RSA Laboratories. PKCS #1: RSA Encryption Standard. Version 2.0, + October 1998. + + [2] RSA Laboratories. PKCS #7: Cryptographic Message Syntax + Standard. Version 1.5, November 1993. + + [3] RSA Laboratories. PKCS #9: Selected Attribute Types. Version + 2.0, February 2000. + + [4] Adams, C. and S. Farrell, "Internet X.509 Public Key + Infrastructure - Certificate Management Protocols", RFC 2510, + March 1999. + + [5] Kaliski, B., "Privacy Enhancement for Internet Electronic Mail: + Part IV: Key Certification and Related Services", RFC 1424, + February 1993. + + [6] Kaliski, B., "PKCS #10: Certification Request Syntax Version + 1.5", RFC 2314, March 1998. + + + + + + +Nystrom & Kaliski Informational [Page 11] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + [7] ITU-T Recommendation X.500 (1997) | ISO/IEC 9594-1:1998, + Information technology - Open Systems Interconnection - The + Directory: Overview of concepts, models and services. + + [8] ITU-T Recommendation X.501 (1993) | ISO/IEC 9594-2:1995, + Information technology - Open Systems Interconnection - The + Directory: Models. + + [9] ITU-T Recommendation X.509 (1997) | ISO/IEC 9594-8:1998, + Information technology - Open Systems Interconnection -The + Directory: Authentication framework. + + [10] ITU-T Recommendation X.680 (1997) | ISO/IEC 8824-1:1998, + Information Technology - Abstract Syntax Notation One (ASN.1): + Specification of Basic Notation. + + [11] ITU-T Recommendation X.681 (1997) | ISO/IEC 8824-2:1998, + Information Technology - Abstract Syntax Notation One (ASN.1): + Information Object Specification. + + [12] ITU-T Recommendation X.682 (1997) | ISO/IEC 8824-3:1998, + Information Technology - Abstract Syntax Notation One (ASN.1): + Constraint Specification. + + [13] ITU-T Recommendation X.683 (1997) | ISO/IEC 8824-4:1998, + Information Technology - Abstract Syntax Notation One (ASN.1): + Parameterization of ASN.1 Specifications. + + [14] ITU-T Recommendation X.690 (1997) | ISO/IEC 8825-1:1998, + Information Technology - ASN.1 Encoding Rules: Specification of + Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and + Distinguished Encoding Rules (DER). + +E. Contact Information & About PKCS + + The Public-Key Cryptography Standards are specifications produced by + RSA Laboratories in cooperation with secure systems developers + worldwide for the purpose of accelerating the deployment of public- + key cryptography. First published in 1991 as a result of meetings + with a small group of early adopters of public-key technology, the + PKCS documents have become widely referenced and implemented. + Contributions from the PKCS series have become part of many formal + and de facto standards, including ANSI X9 documents, PKIX, SET, + S/MIME, and SSL. + + + + + + + +Nystrom & Kaliski Informational [Page 12] + +RFC 2986 Certification Request Syntax Specification November 2000 + + + Further development of PKCS occurs through mailing list discussions + and occasional workshops, and suggestions for improvement are + welcome. For more information, contact: + + PKCS Editor + RSA Laboratories + 20 Crosby Drive + Bedford, MA 01730 USA + pkcs-editor@rsasecurity.com + http://www.rsasecurity.com/rsalabs/pkcs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Nystrom & Kaliski Informational [Page 13] + +RFC 2986 Certification Request Syntax Specification November 2000 + + +Full Copyright Statement + + Copyright (C) The Internet Society 2000. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others provided that the above copyright notice and this paragraph + are included on all such copies. However, this document itself may + not be modified in any way, such as by removing the copyright notice + or references to the Internet Society or other Internet + organizations, except as required to translate it into languages + other than English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + + + + + + + +Nystrom & Kaliski Informational [Page 14] + diff --git a/docs/rfc/rfc4055.txt b/docs/rfc/rfc4055.txt index 8e574f4c..76e7ce6e 100644 --- a/docs/rfc/rfc4055.txt +++ b/docs/rfc/rfc4055.txt @@ -1,3 +1,9 @@ + + + + + + Network Working Group J. Schaad Request for Comments: 4055 Soaring Hawk Consulting Updates: 3279 B. Kaliski @@ -1394,3 +1400,4 @@ Acknowledgement Schaad, et al. Standards Track [Page 25] + diff --git a/docs/rfc/rfc5019.txt b/docs/rfc/rfc5019.txt new file mode 100644 index 00000000..a3403d6f --- /dev/null +++ b/docs/rfc/rfc5019.txt @@ -0,0 +1,1235 @@ + + + + + + +Network Working Group A. Deacon +Request for Comments: 5019 VeriSign +Category: Standards Track R. Hurst + Microsoft + September 2007 + + + The Lightweight Online Certificate Status Protocol (OCSP) Profile + for High-Volume Environments + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Abstract + + This specification defines a profile of the Online Certificate Status + Protocol (OCSP) that addresses the scalability issues inherent when + using OCSP in large scale (high volume) Public Key Infrastructure + (PKI) environments and/or in PKI environments that require a + lightweight solution to minimize communication bandwidth and client- + side processing. + + + + + + + + + + + + + + + + + + + + + + + + + +Deacon & Hurst Standards Track [Page 1] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +Table of Contents + + 1. Introduction ....................................................3 + 1.1. Requirements Terminology ...................................4 + 2. OCSP Message Profile ............................................4 + 2.1. OCSP Request Profile .......................................4 + 2.1.1. OCSPRequest Structure ...............................4 + 2.1.2. Signed OCSPRequests .................................5 + 2.2. OCSP Response Profile ......................................5 + 2.2.1. OCSPResponse Structure ..............................5 + 2.2.2. Signed OCSPResponses ................................6 + 2.2.3. OCSPResponseStatus Values ...........................6 + 2.2.4. thisUpdate, nextUpdate, and producedAt ..............7 + 3. Client Behavior .................................................7 + 3.1. OCSP Responder Discovery ...................................7 + 3.2. Sending an OCSP Request ....................................7 + 4. Ensuring an OCSPResponse Is Fresh ...............................8 + 5. Transport Profile ...............................................9 + 6. Caching Recommendations .........................................9 + 6.1. Caching at the Client .....................................10 + 6.2. HTTP Proxies ..............................................10 + 6.3. Caching at Servers ........................................12 + 7. Security Considerations ........................................12 + 7.1. Replay Attacks ............................................12 + 7.2. Man-in-the-Middle Attacks .................................13 + 7.3. Impersonation Attacks .....................................13 + 7.4. Denial-of-Service Attacks .................................13 + 7.5. Modification of HTTP Headers ..............................14 + 7.6. Request Authentication and Authorization ..................14 + 8. Acknowledgements ...............................................14 + 9. References .....................................................14 + 9.1. Normative References ......................................14 + 9.2. Informative References ....................................15 + Appendix A. Example OCSP Messages .................................16 + A.1. OCSP Request ..............................................16 + A.2. OCSP Response .............................................16 + + + + + + + + + + + + + + + +Deacon & Hurst Standards Track [Page 2] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +1. Introduction + + The Online Certificate Status Protocol [OCSP] specifies a mechanism + used to determine the status of digital certificates, in lieu of + using Certificate Revocation Lists (CRLs). Since its definition in + 1999, it has been deployed in a variety of environments and has + proven to be a useful certificate status checking mechanism. (For + brevity we refer to OCSP as being used to verify certificate status, + but only the revocation status of a certificate is checked via this + protocol.) + + To date, many OCSP deployments have been used to ensure timely and + secure certificate status information for high-value electronic + transactions or highly sensitive information, such as in the banking + and financial environments. As such, the requirement for an OCSP + responder to respond in "real time" (i.e., generating a new OCSP + response for each OCSP request) has been important. In addition, + these deployments have operated in environments where bandwidth usage + is not an issue, and have run on client and server systems where + processing power is not constrained. + + As the use of PKI continues to grow and move into diverse + environments, so does the need for a scalable and cost-effective + certificate status mechanism. Although OCSP as currently defined and + deployed meets the need of small to medium-sized PKIs that operate on + powerful systems on wired networks, there is a limit as to how these + OCSP deployments scale from both an efficiency and cost perspective. + Mobile environments, where network bandwidth may be at a premium and + client-side devices are constrained from a processing point of view, + require the careful use of OCSP to minimize bandwidth usage and + client-side processing complexity. [OCSPMP] + + PKI continues to be deployed into environments where millions if not + hundreds of millions of certificates have been issued. In many of + these environments, an even larger number of users (also known as + relying parties) have the need to ensure that the certificate they + are relying upon has not been revoked. As such, it is important that + OCSP is used in such a way that ensures the load on OCSP responders + and the network infrastructure required to host those responders are + kept to a minimum. + + This document addresses the scalability issues inherent when using + OCSP in PKI environments described above by defining a message + profile and clarifying OCSP client and responder behavior that will + permit: + + + + + + +Deacon & Hurst Standards Track [Page 3] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + 1) OCSP response pre-production and distribution. + 2) Reduced OCSP message size to lower bandwidth usage. + 3) Response message caching both in the network and on the client. + + It is intended that the normative requirements defined in this + profile will be adopted by OCSP clients and OCSP responders operating + in very large-scale (high-volume) PKI environments or PKI + environments that require a lightweight solution to minimize + bandwidth and client-side processing power (or both), as described + above. As OCSP does not have the means to signal responder + capabilities within the protocol, clients needing to differentiate + between OCSP responses produced by responders conformant with this + profile and those that are not need to rely on out-of-band mechanisms + to determine when a responder operates according to this profile and, + as such, when the requirements of this profile apply. In the case + where out-of-band mechanisms may not be available, this profile + ensures that interoperability will still occur between a fully + conformant OCSP 2560 client and a responder that is operating in a + mode as described in this specification. + +1.1. Requirements Terminology + + 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]. + +2. OCSP Message Profile + + This section defines a subset of OCSPRequest and OCSPResponse + functionality as defined in [OCSP]. + +2.1. OCSP Request Profile + +2.1.1. OCSPRequest Structure + + OCSPRequests conformant to this profile MUST include only one Request + in the OCSPRequest.RequestList structure. + + Clients MUST use SHA1 as the hashing algorithm for the + CertID.issuerNameHash and the CertID.issuerKeyHash values. + + Clients MUST NOT include the singleRequestExtensions structure. + + Clients SHOULD NOT include the requestExtensions structure. If a + requestExtensions structure is included, this profile RECOMMENDS that + it contain only the nonce extension (id-pkix-ocsp-nonce). See + Section 4 for issues concerning the use of a nonce in high-volume + OCSP environments. + + + +Deacon & Hurst Standards Track [Page 4] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +2.1.2. Signed OCSPRequests + + Clients SHOULD NOT send signed OCSPRequests. Responders MAY ignore + the signature on OCSPRequests. + + If the OCSPRequest is signed, the client SHALL specify its name in + the OCSPRequest.requestorName field; otherwise, clients SHOULD NOT + include the requestorName field in the OCSPRequest. OCSP servers + MUST be prepared to receive unsigned OCSP requests that contain the + requestorName field, but must realize that the provided value is not + authenticated. + +2.2. OCSP Response Profile + +2.2.1. OCSPResponse Structure + + Responders MUST generate a BasicOCSPResponse as identified by the + id-pkix-ocsp-basic OID. Clients MUST be able to parse and accept a + BasicOCSPResponse. OCSPResponses conformant to this profile SHOULD + include only one SingleResponse in the ResponseData.responses + structure, but MAY include additional SingleResponse elements if + necessary to improve response pre-generation performance or cache + efficiency. + + The responder SHOULD NOT include responseExtensions. As specified in + [OCSP], clients MUST ignore unrecognized non-critical + responseExtensions in the response. + + In the case where a responder does not have the ability to respond to + an OCSP request containing a option not supported by the server, it + SHOULD return the most complete response it can. For example, in the + case where a responder only supports pre-produced responses and does + not have the ability to respond to an OCSP request containing a + nonce, it SHOULD return a response that does not include a nonce. + + Clients SHOULD attempt to process a response even if the response + does not include a nonce. See Section 4 for details on validating + responses that do not contain a nonce. See also Section 7 for + relevant security considerations. + + Responders that do not have the ability to respond to OCSP requests + that contain an unsupported option such as a nonce MAY forward the + request to an OCSP responder capable of doing so. + + The responder MAY include the singleResponse.singleResponse + extensions structure. + + + + + +Deacon & Hurst Standards Track [Page 5] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +2.2.2. Signed OCSPResponses + + Clients MUST validate the signature on the returned OCSPResponse. + + If the response is signed by a delegate of the issuing certification + authority (CA), a valid responder certificate MUST be referenced in + the BasicOCSPResponse.certs structure. + + It is RECOMMENDED that the OCSP responder's certificate contain the + id-pkix-ocsp-nocheck extension, as defined in [OCSP], to indicate to + the client that it need not check the certificate's status. In + addition, it is RECOMMENDED that neither an OCSP authorityInfoAccess + (AIA) extension nor cRLDistributionPoints (CRLDP) extension be + included in the OCSP responder's certificate. Accordingly, the + responder's signing certificate SHOULD be relatively short-lived and + renewed regularly. + + Clients MUST be able to identify OCSP responder certificates using + both the byName and byKey ResponseData.ResponderID choices. + Responders SHOULD use byKey to further reduce the size of the + response in scenarios where reducing bandwidth is an issue. + +2.2.3. OCSPResponseStatus Values + + As long as the OCSP infrastructure has authoritative records for a + particular certificate, an OCSPResponseStatus of "successful" will be + returned. When access to authoritative records for a particular + certificate is not available, the responder MUST return an + OCSPResponseStatus of "unauthorized". As such, this profile extends + the RFC 2560 [OCSP] definition of "unauthorized" as follows: + + The response "unauthorized" is returned in cases where the client + is not authorized to make this query to this server or the server + is not capable of responding authoritatively. + + For example, OCSP responders that do not have access to authoritative + records for a requested certificate, such as those that generate and + distribute OCSP responses in advance and thus do not have the ability + to properly respond with a signed "successful" yet "unknown" + response, will respond with an OCSPResponseStatus of "unauthorized". + Also, in order to ensure the database of revocation information does + not grow unbounded over time, the responder MAY remove the status + records of expired certificates. Requests from clients for + certificates whose record has been removed will result in an + OCSPResponseStatus of "unauthorized". + + Security considerations regarding the use of unsigned responses are + discussed in [OCSP]. + + + +Deacon & Hurst Standards Track [Page 6] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +2.2.4. thisUpdate, nextUpdate, and producedAt + + When pre-producing OCSPResponse messages, the responder MUST set the + thisUpdate, nextUpdate, and producedAt times as follows: + + thisUpdate The time at which the status being indicated is known + to be correct. + + nextUpdate The time at or before which newer information will be + available about the status of the certificate. + Responders MUST always include this value to aid in + response caching. See Section 6 for additional + information on caching. + + producedAt The time at which the OCSP response was signed. + + Note: In many cases the value of thisUpdate and producedAt will be + the same. + + For the purposes of this profile, ASN.1-encoded GeneralizedTime + values such as thisUpdate, nextUpdate, and producedAt MUST be + expressed Greenwich Mean Time (Zulu) and MUST include seconds (i.e., + times are YYYYMMDDHHMMSSZ), even where the number of seconds is zero. + GeneralizedTime values MUST NOT include fractional seconds. + +3. Client Behavior + +3.1. OCSP Responder Discovery + + Clients MUST support the authorityInfoAccess extension as defined in + [PKIX] and MUST recognize the id-ad-ocsp access method. This enables + CAs to inform clients how they can contact the OCSP service. + + In the case where a client is checking the status of a certificate + that contains both an authorityInformationAccess (AIA) extension + pointing to an OCSP responder and a cRLDistributionPoints extension + pointing to a CRL, the client SHOULD attempt to contact the OCSP + responder first. Clients MAY attempt to retrieve the CRL if no + OCSPResponse is received from the responder after a locally + configured timeout and number of retries. + +3.2. Sending an OCSP Request + + To avoid needless network traffic, applications MUST verify the + signature of signed data before asking an OCSP client to check the + status of certificates used to verify the data. If the signature is + invalid or the application is not able to verify it, an OCSP check + MUST NOT be requested. + + + +Deacon & Hurst Standards Track [Page 7] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + Similarly, an application MUST validate the signature on certificates + in a chain, before asking an OCSP client to check the status of the + certificate. If the certificate signature is invalid or the + application is not able to verify it, an OCSP check MUST NOT be + requested. Clients SHOULD NOT make a request to check the status of + expired certificates. + +4. Ensuring an OCSPResponse Is Fresh + + In order to ensure that a client does not accept an out-of-date + response that indicates a 'good' status when in fact there is a more + up-to-date response that specifies the status of 'revoked', a client + must ensure the responses they receive are fresh. + + In general, two mechanisms are available to clients to ensure a + response is fresh. The first uses nonces, and the second is based on + time. In order for time-based mechanisms to work, both clients and + responders MUST have access to an accurate source of time. + + Because this profile specifies that clients SHOULD NOT include a + requestExtensions structure in OCSPRequests (see Section 2.1), + clients MUST be able to determine OCSPResponse freshness based on an + accurate source of time. Clients that opt to include a nonce in the + request SHOULD NOT reject a corresponding OCSPResponse solely on the + basis of the nonexistent expected nonce, but MUST fall back to + validating the OCSPResponse based on time. + + Clients that do not include a nonce in the request MUST ignore any + nonce that may be present in the response. + + Clients MUST check for the existence of the nextUpdate field and MUST + ensure the current time, expressed in GMT time as described in + Section 2.2.4, falls between the thisUpdate and nextUpdate times. If + the nextUpdate field is absent, the client MUST reject the response. + + If the nextUpdate field is present, the client MUST ensure that it is + not earlier than the current time. If the current time on the client + is later than the time specified in the nextUpdate field, the client + MUST reject the response as stale. Clients MAY allow configuration + of a small tolerance period for acceptance of responses after + nextUpdate to handle minor clock differences relative to responders + and caches. This tolerance period should be chosen based on the + accuracy and precision of time synchronization technology available + to the calling application environment. For example, Internet peers + with low latency connections typically expect NTP time + synchronization to keep them accurate within parts of a second; + higher latency environments or where an NTP analogue is not available + may have to be more liberal in their tolerance. + + + +Deacon & Hurst Standards Track [Page 8] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + See the security considerations in Section 7 for additional details + on replay and man-in-the-middle attacks. + +5. Transport Profile + + The OCSP responder MUST support requests and responses over HTTP. + When sending requests that are less than or equal to 255 bytes in + total (after encoding) including the scheme and delimiters (http://), + server name and base64-encoded OCSPRequest structure, clients MUST + use the GET method (to enable OCSP response caching). OCSP requests + larger than 255 bytes SHOULD be submitted using the POST method. In + all cases, clients MUST follow the descriptions in A.1.1 of [OCSP] + when constructing these messages. + + When constructing a GET message, OCSP clients MUST base64 encode the + OCSPRequest structure and append it to the URI specified in the AIA + extension [PKIX]. Clients MUST NOT include CR or LF characters in + the base64-encoded string. Clients MUST properly URL-encode the + base64 encoded OCSPRequest. For example: + + http://ocsp.example.com/MEowSDBGMEQwQjAKBggqhkiG9w0CBQQQ7sp6GTKpL + 2dAdeGaW267owQQqInESWQD0mGeBArSgv%2FBWQIQLJx%2Fg9xF8oySYzol80Mbpg + %3D%3D + + In response to properly formatted OCSPRequests that are cachable + (i.e., responses that contain a nextUpdate value), the responder will + include the binary value of the DER encoding of the OCSPResponse + preceded by the following HTTP [HTTP] headers. + + content-type: application/ocsp-response + content-length: + last-modified: + ETag: "" + expires: + cache-control: max-age=, public, no-transform, must-revalidate + date: + + See Section 6.2 for details on the use of these headers. + +6. Caching Recommendations + + The ability to cache OCSP responses throughout the network is an + important factor in high volume OCSP deployments. This section + discusses the recommended caching behavior of OCSP clients and HTTP + proxies and the steps that should be taken to minimize the number of + times that OCSP clients "hit the wire". In addition, the concept of + including OCSP responses in protocol exchanges (aka stapling or + piggybacking), such as has been defined in TLS, is also discussed. + + + +Deacon & Hurst Standards Track [Page 9] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +6.1. Caching at the Client + + To minimize bandwidth usage, clients MUST locally cache authoritative + OCSP responses (i.e., a response with a signature that has been + successfully validated and that indicate an OCSPResponseStatus of + 'successful'). + + Most OCSP clients will send OCSPRequests at or near the nextUpdate + time (when a cached response expires). To avoid large spikes in + responder load that might occur when many clients refresh cached + responses for a popular certificate, responders MAY indicate when the + client should fetch an updated OCSP response by using the cache- + control:max-age directive. Clients SHOULD fetch the updated OCSP + Response on or after the max-age time. To ensure that clients + receive an updated OCSP response, OCSP responders MUST refresh the + OCSP response before the max-age time. + +6.2. HTTP Proxies + + The responder SHOULD set the HTTP headers of the OCSP response in + such a way as to allow for the intelligent use of intermediate HTTP + proxy servers. See [HTTP] for the full definition of these headers + and the proper format of any date and time values. + + HTTP Header Description + =========== ==================================================== + date The date and time at which the OCSP server generated + the HTTP response. + + last-modified This value specifies the date and time at which the + OCSP responder last modified the response. This date + and time will be the same as the thisUpdate timestamp + in the request itself. + + expires Specifies how long the response is considered fresh. + This date and time will be the same as the nextUpdate + timestamp in the OCSP response itself. + + ETag A string that identifies a particular version of the + associated data. This profile RECOMMENDS that the + ETag value be the ASCII HEX representation of the + SHA1 hash of the OCSPResponse structure. + + cache-control Contains a number of caching directives. + + * max-age= -where n is a time value later than + thisUpdate but earlier than + nextUpdate. + + + +Deacon & Hurst Standards Track [Page 10] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + * public -makes normally uncachable response + cachable by both shared and nonshared + caches. + + * no-transform -specifies that a proxy cache cannot + change the type, length, or encoding + of the object content. + + * must-revalidate -prevents caches from intentionally + returning stale responses. + + OCSP responders MUST NOT include a "Pragma: no-cache", "Cache- + Control: no-cache", or "Cache-Control: no-store" header in + authoritative OCSP responses. + + OCSP responders SHOULD include one or more of these headers in non- + authoritative OCSP responses. + + For example, assume that an OCSP response has the following timestamp + values: + + thisUpdate = May 1, 2005 01:00:00 GMT + nextUpdate = May 3, 2005 01:00:00 GMT + productedAt = May 1, 2005 01:00:00 GMT + + and that an OCSP client requests the response on May 2, 2005 01:00:00 + GMT. In this scenario, the HTTP response may look like this: + + content-type: application/ocsp-response + content-length: 1000 + date: Fri, 02 May 2005 01:00:00 GMT + last-modified: Thu, 01 May 2005 01:00:00 GMT + ETag: "c66c0341abd7b9346321d5470fd0ec7cc4dae713" + expires: Sat, 03 May 2005 01:00:00 GMT + cache-control: max-age=86000,public,no-transform,must-revalidate + <...> + + OCSP clients MUST NOT include a no-cache header in OCSP request + messages, unless the client encounters an expired response which may + be a result of an intermediate proxy caching stale data. In this + situation, clients SHOULD resend the request specifying that proxies + should be bypassed by including an appropriate HTTP header in the + request (i.e., Pragma: no-cache or Cache-Control: no-cache). + + + + + + + + +Deacon & Hurst Standards Track [Page 11] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +6.3. Caching at Servers + + In some scenarios, it is advantageous to include OCSP response + information within the protocol being utilized between the client and + server. Including OCSP responses in this manner has a few attractive + effects. + + First, it allows for the caching of OCSP responses on the server, + thus lowering the number of hits to the OCSP responder. + + Second, it enables certificate validation in the event the client is + not connected to a network and thus eliminates the need for clients + to establish a new HTTP session with the responder. + + Third, it reduces the number of round trips the client needs to make + in order to complete a handshake. + + Fourth, it simplifies the client-side OCSP implementation by enabling + a situation where the client need only the ability to parse and + recognize OCSP responses. + + This functionality has been specified as an extension to the TLS + [TLS] protocol in Section 3.6 [TLSEXT], but can be applied to any + client-server protocol. + + This profile RECOMMENDS that both TLS clients and servers implement + the certificate status request extension mechanism for TLS. + + Further information regarding caching issues can be obtained from RFC + 3143 [RFC3143]. + +7. Security Considerations + + The following considerations apply in addition to the security + considerations addressed in Section 5 of [OCSP]. + +7.1. Replay Attacks + + Because the use of nonces in this profile is optional, there is a + possibility that an out of date OCSP response could be replayed, thus + causing a client to accept a good response when in fact there is a + more up-to-date response that specifies the status of revoked. In + order to mitigate this attack, clients MUST have access to an + accurate source of time and ensure that the OCSP responses they + receive are sufficiently fresh. + + + + + + +Deacon & Hurst Standards Track [Page 12] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + Clients that do not have an accurate source of date and time are + vulnerable to service disruption. For example, a client with a + sufficiently fast clock may reject a fresh OCSP response. Similarly + a client with a sufficiently slow clock may incorrectly accept + expired valid responses for certificates that may in fact be revoked. + + Future versions of the OCSP protocol may provide a way for the client + to know whether the server supports nonces or does not support + nonces. If a client can determine that the server supports nonces, + it MUST reject a reply that does not contain an expected nonce. + Otherwise, clients that opt to include a nonce in the request SHOULD + NOT reject a corresponding OCSPResponse solely on the basis of the + nonexistent expected nonce, but MUST fall back to validating the + OCSPResponse based on time. + +7.2. Man-in-the-Middle Attacks + + To mitigate risk associated with this class of attack, the client + must properly validate the signature on the response. + + The use of signed responses in OCSP serves to authenticate the + identity of the OCSP responder and to verify that it is authorized to + sign responses on the CA's behalf. + + Clients MUST ensure that they are communicating with an authorized + responder by the rules described in [OCSP], Section 4.2.2.2. + +7.3. Impersonation Attacks + + The use of signed responses in OCSP serves to authenticate the + identity of OCSP responder. + + As detailed in [OCSP], clients must properly validate the signature + of the OCSP response and the signature on the OCSP response signer + certificate to ensure an authorized responder created it. + +7.4. Denial-of-Service Attacks + + OCSP responders should take measures to prevent or mitigate denial- + of-service attacks. As this profile specifies the use of unsigned + OCSPRequests, access to the responder may be implicitly given to + everyone who can send a request to a responder, and thus the ability + to mount a denial-of-service attack via a flood of requests may be + greater. For example, a responder could limit the rate of incoming + requests from a particular IP address if questionable behavior is + detected. + + + + + +Deacon & Hurst Standards Track [Page 13] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +7.5. Modification of HTTP Headers + + Values included in HTTP headers, as described in Sections 5 and 6, + are not cryptographically protected; they may be manipulated by an + attacker. Clients SHOULD use these values for caching guidance only + and ultimately SHOULD rely only on the values present in the signed + OCSPResponse. Clients SHOULD NOT rely on cached responses beyond the + nextUpdate time. + +7.6. Request Authentication and Authorization + + The suggested use of unsigned requests in this environment removes an + option that allows the responder to determine the authenticity of + incoming request. Thus, access to the responder may be implicitly + given to everyone who can send a request to a responder. + Environments where explicit authorization to access the OCSP + responder is necessary can utilize other mechanisms to authenticate + requestors or restrict or meter service. + +8. Acknowledgements + + The authors wish to thank Magnus Nystrom of RSA Security, Inc., + Jagjeet Sondh of Vodafone Group R&D, and David Engberg of CoreStreet, + Ltd. for their contributions to this specification. + +9. References + +9.1. Normative References + + [HTTP] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, + L., Leach, P., and T. Berners-Lee, "Hypertext Transfer + Protocol -- HTTP/1.1", RFC 2616, June 1999. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [OCSP] Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. + Adams, "X.509 Internet Public Key Infrastructure: Online + Certificate Status Protocol - OCSP", RFC 2560, June 1999. + + [PKIX] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet + Public Key Infrastructure - Certificate and Certificate + Revocation List (CRL) Profile", RFC 3280, April 2002. + + [TLS] Dierks, T. and E. Rescorla, "The Transport Layer Security + Protocol Version 1.1", RFC 4346, April 2006. + + + + + +Deacon & Hurst Standards Track [Page 14] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + [TLSEXT] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., + and T. Wright, "Transport Layer Security (TLS) Extensions", + RFC 4366, April 2006. + +9.2. Informative References + + [OCSPMP] "OCSP Mobile Profile V1.0", Open Mobile Alliance, + www.openmobilealliance.org. + + [RFC3143] Cooper, I. and J. Dilley, "Known HTTP Proxy/Caching + Problems", RFC 3143, June 2001. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deacon & Hurst Standards Track [Page 15] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +Appendix A. Example OCSP Messages + +A.1. OCSP Request + + SEQUENCE { + SEQUENCE { + SEQUENCE { + SEQUENCE { + SEQUENCE { + SEQUENCE { + OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + NULL + } + OCTET STRING + C0 FE 02 78 FC 99 18 88 91 B3 F2 12 E9 C7 E1 B2 + 1A B7 BF C0 + OCTET STRING + 0D FC 1D F0 A9 E0 F0 1C E7 F2 B2 13 17 7E 6F 8D + 15 7C D4 F6 + INTEGER + 09 34 23 72 E2 3A EF 46 7C 83 2D 07 F8 DC 22 BA + } + } + } + } + } + +A.2. OCSP Response + + SEQUENCE { + ENUMERATED 0 + [0] { + SEQUENCE { + OBJECT IDENTIFIER ocspBasic (1 3 6 1 5 5 7 48 1 1) + OCTET STRING, encapsulates { + SEQUENCE { + SEQUENCE { + [0] { + INTEGER 0 + } + [1] { + SEQUENCE { + SET { + SEQUENCE { + OBJECT IDENTIFIER organizationName (2 5 4 10) + PrintableString 'Example Trust Network' + } + } + + + +Deacon & Hurst Standards Track [Page 16] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString 'Example, Inc.' + } + } + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString + 'Example OCSP Responder' + } + } + } + } + GeneralizedTime 07/11/2005 23:52:44 GMT + SEQUENCE { + SEQUENCE { + SEQUENCE { + SEQUENCE { + OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) + NULL + } + OCTET STRING + C0 FE 02 78 FC 99 18 88 91 B3 F2 12 E9 C7 E1 B2 + 1A B7 BF C0 + OCTET STRING + 0D FC 1D F0 A9 E0 F0 1C E7 F2 B2 13 17 7E 6F 8D + 15 7C D4 F6 + INTEGER + 09 34 23 72 E2 3A EF 46 7C 83 2D 07 F8 DC 22 BA + } + [0] + Error: Object has zero length. + GeneralizedTime 07/11/2005 23:52:44 GMT + [0] { + GeneralizedTime 14/11/2005 23:52:44 GMT + } + } + } + } + SEQUENCE { + OBJECT IDENTIFIER + sha1withRSAEncryption (1 2 840 113549 1 1 5) + NULL + } + + + +Deacon & Hurst Standards Track [Page 17] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + BIT STRING + 0E 9F F0 52 B1 A7 42 B8 6E C1 35 E1 0E D5 A9 E2 + F5 C5 3C 16 B1 A3 A7 A2 03 8A 2B 4D 2C F1 B4 98 + 8E 19 DB BA 1E 1E 72 FF 32 F4 44 E0 B2 77 1C D7 + 3C 9E 78 F3 D1 82 68 86 63 12 7F A4 6F F0 4D 84 + EA F8 E2 F7 5D E3 48 44 57 28 80 C7 57 3C FE E1 + 42 0E 5E 17 FC 60 D8 05 D9 EF E2 53 E7 AB 7F 3A + A8 84 AA 5E 46 5B E7 B8 1F C6 B1 35 AD FF D1 CC + BA 58 7D E8 29 60 79 F7 41 02 EA E0 82 0E A6 30 + [0] { + SEQUENCE { + SEQUENCE { + SEQUENCE { + [0] { + INTEGER 2 + } + INTEGER + 49 4A 02 37 1B 1E 70 67 41 6C 9F 06 2F D8 FE DA + SEQUENCE { + OBJECT IDENTIFIER + sha1withRSAEncryption (1 2 840 113549 1 1 5) + NULL + } + SEQUENCE { + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationName (2 5 4 10) + PrintableString 'Example Trust Network' + } + } + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString 'Example, Inc.' + } + } + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString + 'Example CA' + } + } + } + SEQUENCE { + + + +Deacon & Hurst Standards Track [Page 18] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + UTCTime 08/10/2005 00:00:00 GMT + UTCTime 06/01/2006 23:59:59 GMT + } + SEQUENCE { + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationName (2 5 4 10) + PrintableString 'Example Trust Network' + } + } + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString 'Example, Inc.' + } + } + SET { + SEQUENCE { + OBJECT IDENTIFIER + organizationalUnitName (2 5 4 11) + PrintableString + 'Example OCSP Responder' + } + } + } + SEQUENCE { + SEQUENCE { + OBJECT IDENTIFIER + rsaEncryption (1 2 840 113549 1 1 1) + NULL + } + BIT STRING, encapsulates { + SEQUENCE { + INTEGER + 00 AF C9 7A F5 09 CA D1 08 8C 82 6D AC D9 63 4D + D2 64 17 79 CB 1E 1C 1C 0C 6E 28 56 B5 16 4A 4A + 00 1A C1 B0 74 D7 B4 55 9D 2A 99 1F 0E 4A E3 5F + 81 AF 8D 07 23 C3 30 28 61 3F B0 C8 1D 4E A8 9C + A6 32 B4 D2 63 EC F7 C1 55 7A 73 2A 51 99 00 D5 + 0F B2 4E 11 5B 83 55 83 4C 0E DD 12 0C BD 7E 41 + 04 3F 5F D9 2A 65 88 3C 2A BA 20 76 1D 1F 59 3E + D1 85 F7 4B E2 81 50 9C 78 96 1B 37 73 12 1A D2 + [ Another 1 bytes skipped ] + INTEGER 65537 + } + } + + + +Deacon & Hurst Standards Track [Page 19] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + } + [3] { + SEQUENCE { + SEQUENCE { + OBJECT IDENTIFIER + basicConstraints (2 5 29 19) + OCTET STRING, encapsulates { + SEQUENCE {} + } + } + SEQUENCE { + OBJECT IDENTIFIER extKeyUsage (2 5 29 37) + OCTET STRING, encapsulates { + SEQUENCE { + OBJECT IDENTIFIER + ocspSigning (1 3 6 1 5 5 7 3 9) + } + } + } + SEQUENCE { + OBJECT IDENTIFIER keyUsage (2 5 29 15) + OCTET STRING, encapsulates { + BIT STRING 7 unused bits + '1'B (bit 0) + } + } + SEQUENCE { + OBJECT IDENTIFIER + ocspNoCheck (1 3 6 1 5 5 7 48 1 5) + OCTET STRING, encapsulates { + NULL + } + } + } + } + } + SEQUENCE { + OBJECT IDENTIFIER + sha1withRSAEncryption (1 2 840 113549 1 1 5) + NULL + } + BIT STRING + 3A 68 5F 6A F8 87 36 4A E2 22 46 5C C8 F5 0E CE + 1A FA F2 25 E1 51 AB 37 BE D4 10 C8 15 93 39 73 + C8 59 0F F0 39 67 29 C2 60 20 F7 3F FE A0 37 AB + 80 0B F9 3D 38 D4 48 67 E4 FA FD 4E 12 BF 55 29 + 14 E9 CC CB DD 13 82 E9 C4 4D D3 85 33 C1 35 E5 + 8F 38 01 A7 F7 FD EB CD DE F2 F7 85 86 AE E3 1B + + + +Deacon & Hurst Standards Track [Page 20] + +RFC 5019 Lightweight OCSP Profile September 2007 + + + 9C FD 1D 07 E5 28 F2 A0 5E AC BF 9E 0B 34 A1 B4 + 3A A9 0E C5 8A 34 3F 65 D3 10 63 A4 5E 21 71 5A + } + } + } + } + } + } + } + } + +Authors' Addresses + + Alex Deacon + VeriSign, Inc. + 487 E. Middlefield Road + Mountain View, CA 94043 + USA + + Phone: 1-650-426-3478 + EMail: alex@verisign.com + + + Ryan Hurst + Microsoft + One Microsoft Way + Redmond, WA 98052 + USA + + Phone: 1-425-707-8979 + EMail: rmh@microsoft.com + + + + + + + + + + + + + + + + + + + + +Deacon & Hurst Standards Track [Page 21] + +RFC 5019 Lightweight OCSP Profile September 2007 + + +Full Copyright Statement + + Copyright (C) The IETF Trust (2007). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND + THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at + ietf-ipr@ietf.org. + + + + + + + + + + + + +Deacon & Hurst Standards Track [Page 22] + diff --git a/docs/rfc/rfc5280.txt b/docs/rfc/rfc5280.txt index fa936300..34d56992 100644 --- a/docs/rfc/rfc5280.txt +++ b/docs/rfc/rfc5280.txt @@ -1,3 +1,9 @@ + + + + + + Network Working Group D. Cooper Request for Comments: 5280 NIST Obsoletes: 3280, 4325, 4630 S. Santesson @@ -8450,3 +8456,4 @@ Intellectual Property Cooper, et al. Standards Track [Page 151] + diff --git a/docs/rfc/rfc5753.txt b/docs/rfc/rfc5753.txt new file mode 100644 index 00000000..9c7962e3 --- /dev/null +++ b/docs/rfc/rfc5753.txt @@ -0,0 +1,3419 @@ + + + + + + +Internet Engineering Task Force (IETF) S. Turner +Request for Comments: 5753 IECA +Obsoletes: 3278 D. Brown +Category: Informational Certicom +ISSN: 2070-1721 January 2010 + + + Use of Elliptic Curve Cryptography (ECC) Algorithms + in Cryptographic Message Syntax (CMS) + +Abstract + + This document describes how to use Elliptic Curve Cryptography (ECC) + public key algorithms in the Cryptographic Message Syntax (CMS). The + ECC algorithms support the creation of digital signatures and the + exchange of keys to encrypt or authenticate content. The definition + of the algorithm processing is based on the NIST FIPS 186-3 for + digital signature, NIST SP800-56A and SEC1 for key agreement, RFC + 3370 and RFC 3565 for key wrap and content encryption, NIST FIPS + 180-3 for message digest, SEC1 for key derivation, and RFC 2104 and + RFC 4231 for message authentication code standards. This document + obsoletes RFC 3278. + +Status of This Memo + + This document is not an Internet Standards Track specification; it is + published for informational purposes. + + 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). Not all documents + approved by the IESG are a candidate for any level of Internet + Standard; see Section 2 of RFC 5741. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + http://www.rfc-editor.org/info/rfc5753. + +Copyright Notice + + Copyright (c) 2010 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) in effect on the date of + publication of this document. Please review these documents + + + +Turner & Brown Informational [Page 1] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + This document may contain material from IETF Documents or IETF + Contributions published or made publicly available before November + 10, 2008. The person(s) controlling the copyright in some of this + material may not have granted the IETF Trust the right to allow + modifications of such material outside the IETF Standards Process. + Without obtaining an adequate license from the person(s) controlling + the copyright in such materials, this document may not be modified + outside the IETF Standards Process, and derivative works of it may + not be created outside the IETF Standards Process, except to format + it for publication as an RFC or to translate it into languages other + than English. + +Table of Contents + + 1. Introduction ....................................................3 + 1.1. Requirements Terminology ...................................3 + 2. SignedData Using ECC ............................................3 + 2.1. SignedData Using ECDSA .....................................4 + 3. EnvelopedData Using ECC Algorithms ..............................5 + 3.1. EnvelopedData Using (ephemeral-static) ECDH ................5 + 3.2. EnvelopedData Using 1-Pass ECMQV ...........................8 + 4. AuthenticatedData and AuthEnvelopedData Using ECC ..............11 + 4.1. AuthenticatedData Using 1-Pass ECMQV ......................11 + 4.2. AuthEnvelopedData Using 1-Pass ECMQV ......................12 + 5. Certificates Using ECC .........................................13 + 6. SMIMECapabilities Attribute and ECC ............................13 + 7. ASN.1 Syntax ...................................................21 + 7.1. Algorithm Identifiers .....................................21 + 7.2. Other Syntax ..............................................24 + 8. Recommended Algorithms and Elliptic Curves .....................26 + 9. Security Considerations ........................................28 + 10. IANA Considerations ...........................................33 + 11. References ....................................................33 + 11.1. Normative References .....................................33 + 11.2. Informative References ...................................35 + Appendix A. ASN.1 Modules.........................................37 + A.1. 1988 ASN.1 Module.........................................37 + A.2. 2004 ASN.1 Module.........................................45 + Appendix B. Changes since RFC 3278.................................59 + Acknowledgements...................................................61 + + + + + +Turner & Brown Informational [Page 2] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +1. Introduction + + The Cryptographic Message Syntax (CMS) is cryptographic algorithm + independent. This specification defines a profile for the use of + Elliptic Curve Cryptography (ECC) public key algorithms in the CMS. + The ECC algorithms are incorporated into the following CMS content + types: + + - 'SignedData' to support ECC-based digital signature methods + (ECDSA) to sign content; + + - 'EnvelopedData' to support ECC-based public key agreement methods + (ECDH and ECMQV) to generate pairwise key-encryption keys to + encrypt content-encryption keys used for content encryption; + + - 'AuthenticatedData' to support ECC-based public key agreement + methods (ECMQV) to generate pairwise key-encryption keys to + encrypt message-authentication keys used for content + authentication and integrity; and + + - 'AuthEnvelopedData' to support ECC-based public key agreement + methods (ECMQV) to generate pairwise key-encryption keys to + encrypt message-authentication and content-encryption keys used + for content authentication, integrity, and encryption. + + Certification of EC public keys is also described to provide public + key distribution in support of the specified techniques. + + The document will obsolete [CMS-ECC]. The technical changes + performed since RFC 3278 are detailed in Appendix B. + +1.1. Requirements Terminology + + 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 [MUST]. + +2. SignedData Using ECC + + This section describes how to use ECC algorithms with the CMS + SignedData format to sign data. + + + + + + + + + + +Turner & Brown Informational [Page 3] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +2.1. SignedData Using ECDSA + + This section describes how to use the Elliptic Curve Digital + Signature Algorithm (ECDSA) with SignedData. ECDSA is specified in + [FIPS186-3]. The method is the elliptic curve analog of the Digital + Signature Algorithm (DSA) [FIPS186-3]. ECDSA is used with the Secure + Hash Algorithm (SHA) [FIPS180-3]. + + In an implementation that uses ECDSA with CMS SignedData, the + following techniques and formats MUST be used. + +2.1.1. Fields of the SignedData + + When using ECDSA with SignedData, the fields of SignerInfo are as in + [CMS], but with the following restrictions: + + - digestAlgorithm MUST contain the algorithm identifier of the hash + algorithm (see Section 7.1.1), which MUST be one of the following: + id-sha1, id-sha224, id-sha256, id-sha384, or id-sha512. + + - signatureAlgorithm contains the signature algorithm identifier + (see Section 7.1.3): ecdsa-with-SHA1, ecdsa-with-SHA224, ecdsa- + with-SHA256, ecdsa-with-SHA384, or ecdsa-with-SHA512. The hash + algorithm identified in the name of the signature algorithm MUST + be the same as the digestAlgorithm (e.g., digestAlgorithm is id- + sha256 therefore signatureAlgorithm is ecdsa-with-SHA256). + + - signature MUST contain the DER encoding (as an octet string) of a + value of the ASN.1 type ECDSA-Sig-Value (see Section 7.2). + + When using ECDSA, the SignedData certificates field MAY include the + certificate(s) for the EC public key(s) used in the generation of the + ECDSA signatures in SignedData. ECC certificates are discussed in + Section 5. + +2.1.2. Actions of the Sending Agent + + When using ECDSA with SignedData, the sending agent uses the message + digest calculation process and signature generation process for + SignedData that are specified in [CMS]. To sign data, the sending + agent uses the signature method specified in [FIPS186-3]. + + The sending agent encodes the resulting signature using the ECDSA- + Sig-Value syntax (see Section 7.2) and places it in the SignerInfo + signature field. + + + + + + +Turner & Brown Informational [Page 4] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +2.1.3. Actions of the Receiving Agent + + When using ECDSA with SignedData, the receiving agent uses the + message digest calculation process and signature verification process + for SignedData that are specified in [CMS]. To verify SignedData, + the receiving agent uses the signature verification method specified + in [FIPS186-3]. + + In order to verify the signature, the receiving agent retrieves the + integers r and s from the SignerInfo signature field of the received + message. + +3. EnvelopedData Using ECC Algorithms + + This section describes how to use ECC algorithms with the CMS + EnvelopedData format. + + This document does not specify the static-static ECDH, method C(0,2, + ECC CDH) from [SP800-56A]. Static-static ECDH is analogous to + static-static DH, which is specified in [CMS-ALG]. Ephemeral-static + ECDH and 1-Pass ECMQV were specified because they provide better + security due to the originator's ephemeral contribution to the key + agreement scheme. + +3.1. EnvelopedData Using (ephemeral-static) ECDH + + This section describes how to use the ephemeral-static Elliptic Curve + Diffie-Hellman (ECDH) key agreement algorithm with EnvelopedData. + This algorithm has two variations: + + - 'Standard' ECDH, described as the 'Elliptic Curve Diffie-Hellman + Scheme' with the 'Elliptic Curve Diffie-Hellman Primitive' in + [SEC1], and + + - 'Co-factor' ECDH, described as the 'One-Pass Diffie-Hellman scheme' + (method C(1, 1, ECC CDH)) in [SP800-56A]. + + Both variations of ephemeral-static ECDH are elliptic curve analogs + of the ephemeral-static Diffie-Hellman key agreement algorithm + specified jointly in the documents [CMS-ALG] and [CMS-DH]. + + If an implementation uses ECDH with CMS EnvelopedData, then the + following techniques and formats MUST be used. + + The fields of EnvelopedData are as in [CMS]; as ECDH is a key + agreement algorithm, the RecipientInfo kari choice is used. + + + + + +Turner & Brown Informational [Page 5] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +3.1.1. Fields of KeyAgreeRecipientInfo + + When using ephemeral-static ECDH with EnvelopedData, the fields of + KeyAgreeRecipientInfo are as follows: + + - version MUST be 3. + + - originator MUST be the alternative originatorKey. The + originatorKey algorithm field MUST contain the id-ecPublicKey + object identifier (see Section 7.1.2). The parameters associated + with id-ecPublicKey MUST be absent, ECParameters, or NULL. The + parameters associated with id-ecPublicKey SHOULD be absent or + ECParameters, and NULL is allowed to support legacy + implementations. The previous version of this document required + NULL to be present. If the parameters are ECParameters, then they + MUST be namedCurve. The originatorKey publicKey field MUST + contain the DER encoding of the value of the ASN.1 type ECPoint + (see Section 7.2), which represents the sending agent's ephemeral + EC public key. The ECPoint in uncompressed form MUST be + supported. + + - ukm MAY be present or absent. However, message originators SHOULD + include the ukm. As specified in RFC 3852 [CMS], implementations + MUST support ukm message recipient processing, so interoperability + is not a concern if the ukm is present or absent. The ukm is + placed in the entityUInfo field of the ECC-CMS-SharedInfo + structure. When present, the ukm is used to ensure that a + different key-encryption key is generated, even when the ephemeral + private key is improperly used more than once, by using the ECC- + CMS-SharedInfo as an input to the key derivation function (see + Section 7.2). + + - keyEncryptionAlgorithm MUST contain the object identifier of the + key-encryption algorithm, which in this case is a key agreement + algorithm (see Section 7.1.4). The parameters field contains + KeyWrapAlgorithm. The KeyWrapAlgorithm is the algorithm + identifier that indicates the symmetric encryption algorithm used + to encrypt the content-encryption key (CEK) with the key- + encryption key (KEK) and any associated parameters (see Section + 7.1.5). Algorithm requirements are found in Section 8. + + - recipientEncryptedKeys contains an identifier and an encrypted key + for each recipient. The RecipientEncryptedKey + KeyAgreeRecipientIdentifier MUST contain either the + issuerAndSerialNumber identifying the recipient's certificate or + the RecipientKeyIdentifier containing the subject key identifier + from the recipient's certificate. In both cases, the recipient's + certificate contains the recipient's static ECDH public key. + + + +Turner & Brown Informational [Page 6] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + RecipientEncryptedKey EncryptedKey MUST contain the content- + encryption key encrypted with the ephemeral-static, ECDH-generated + pairwise key-encryption key using the algorithm specified by the + KeyWrapAlgorithm. + +3.1.2. Actions of the Sending Agent + + When using ephemeral-static ECDH with EnvelopedData, the sending + agent first obtains the recipient's EC public key and domain + parameters (e.g., from the recipient's certificate). The sending + agent then performs one of the two ECDH variations mentioned above: + + - If the value of keyEncryptionAlgorithm indicates the use of + 'standard' Diffie-Hellman, then the sending agent performs the + 'Elliptic Curve Diffie-Hellman Scheme' with the 'Elliptic Curve + Diffie-Hellman Primitive' in [SEC1]. + + - If the value of keyEncryptionAlgorithm indicates the use of 'co- + factor' Diffie-Hellman, then the sending agent performs the 'One- + Pass Diffie-Hellman scheme' (method C(1, 1, ECC CDH)) in + [SP800-56A]. + + In both of these cases, the sending agent uses the KDF defined in + Section 3.6.1 of [SEC1] with the hash algorithm identified by the + value of keyEncryptionAlgorithm. As a result, the sending agent + obtains: + + - an ephemeral public key, which is represented as a value of the + type ECPoint (see Section 7.2), encapsulated in a bit string and + placed in the KeyAgreeRecipientInfo originator originatorKey + publicKey field, and + + - a shared secret bit string "K", which is used as the pairwise key- + encryption key for that recipient, as specified in [CMS]. + + In a single message, if there are multiple layers for a recipient, + then the ephemeral public key can be reused by the originator for + that recipient in each of the different layers. + +3.1.3. Actions of the Receiving Agent + + When using ephemeral-static ECDH with EnvelopedData, the receiving + agent determines the bit string "SharedInfo", which is the DER + encoding of ECC-CMS-SharedInfo (see Section 7.2), and the integer + "keydatalen" from the key size, in bits, of the KeyWrapAlgorithm. + The receiving agent retrieves the ephemeral EC public key from the + bit string KeyAgreeRecipientInfo originator, with a value of the type + ECPoint (see Section 7.2) encapsulated as a bit string, and if + + + +Turner & Brown Informational [Page 7] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + present, originally supplied additional user key material from the + ukm field. The receiving agent then performs one of the two ECDH + variations mentioned above: + + - If the value of keyEncryptionAlgorithm indicates the use of + 'standard' Diffie-Hellman, then the receiving agent performs the + 'Elliptic Curve Diffie-Hellman Scheme' with the 'Elliptic Curve + Diffie-Hellman Primitive' in [SEC1]. + + - If the value of keyEncryptionAlgorithm indicates the use of 'co- + factor' Diffie-Hellman, then the receiving agent performs the 'One- + Pass Diffie-Hellman scheme' (method C(1, 1, ECC CDH)) in + [SP800-56A]. + + In both of these cases, the receiving agent uses the KDF defined in + Section 3.6.1 of [SEC1] with the hash algorithm identified by the + value of keyEncryptionAlgorithm. As a result, the receiving agent + obtains a shared secret bit string "K", which is used as the pairwise + key-encryption key to unwrap the CEK. + +3.2. EnvelopedData Using 1-Pass ECMQV + + This section describes how to use the 1-Pass Elliptic Curve Menezes- + Qu-Vanstone (ECMQV) key agreement algorithm with EnvelopedData, + method C(1, 2, ECC MQV) from [SP800-56A]. Like the KEA algorithm + [CMS-KEA], 1-Pass ECMQV uses three key pairs: an ephemeral key pair, + a static key pair of the sending agent, and a static key pair of the + receiving agent. Using an algorithm with the sender static key pair + allows for knowledge of the message creator; this means that + authentication can, in some circumstances, be obtained for + AuthEnvelopedData and AuthenticatedData. This means that 1-Pass + ECMQV can be a common algorithm for EnvelopedData, AuthenticatedData, + and AuthEnvelopedData, while ECDH can only be used in EnvelopedData. + + If an implementation uses 1-Pass ECMQV with CMS EnvelopedData, then + the following techniques and formats MUST be used. + + The fields of EnvelopedData are as in [CMS]; as 1-Pass ECMQV is a key + agreement algorithm, the RecipientInfo kari choice is used. When + using 1-Pass ECMQV, the EnvelopedData originatorInfo field MAY + include the certificate(s) for the EC public key(s) used in the + formation of the pairwise key. ECC certificates are discussed in + Section 5. + + + + + + + + +Turner & Brown Informational [Page 8] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +3.2.1. Fields of KeyAgreeRecipientInfo + + When using 1-Pass ECMQV with EnvelopedData, the fields of + KeyAgreeRecipientInfo are as follows: + + - version MUST be 3. + + - originator identifies the static EC public key of the sender. It + SHOULD be one of the alternatives, issuerAndSerialNumber or + subjectKeyIdentifier, and point to one of the sending agent's + certificates. + + - ukm MUST be present. The ukm field is an octet string that MUST + contain the DER encoding of the type MQVuserKeyingMaterial (see + Section 7.2). The MQVuserKeyingMaterial ephemeralPublicKey + algorithm field MUST contain the id-ecPublicKey object identifier + (see Section 7.1.2). The parameters associated with id- + ecPublicKey MUST be absent, ECParameters, or NULL. The parameters + associated with id-ecPublicKey SHOULD be absent or ECParameters, + as NULL is allowed to support legacy implementations. The + previous version of this document required NULL to be present. If + the parameters are ECParameters, then they MUST be namedCurve. + The MQVuserKeyingMaterial ephemeralPublicKey publicKey field MUST + contain the DER encoding of the ASN.1 type ECPoint (see Section + 7.2) representing the sending agent's ephemeral EC public key. + The MQVuserKeyingMaterial addedukm field, if present, contains + additional user keying material from the sending agent. + + - keyEncryptionAlgorithm MUST contain the object identifier of the + key-encryption algorithm, which in this case is a key agreement + algorithm (see Section 7.1.4). The parameters field contains + KeyWrapAlgorithm. The KeyWrapAlgorithm indicates the symmetric + encryption algorithm used to encrypt the CEK with the KEK + generated using the 1-Pass ECMQV algorithm and any associated + parameters (see Section 7.1.5). Algorithm requirements are found + in Section 8. + + - recipientEncryptedKeys contains an identifier and an encrypted key + for each recipient. The RecipientEncryptedKey + KeyAgreeRecipientIdentifier MUST contain either the + issuerAndSerialNumber identifying the recipient's certificate or + the RecipientKeyIdentifier containing the subject key identifier + from the recipient's certificate. In both cases, the recipient's + certificate contains the recipient's static ECMQV public key. + RecipientEncryptedKey EncryptedKey MUST contain the content- + encryption key encrypted with the 1-Pass ECMQV-generated pairwise + key-encryption key using the algorithm specified by the + KeyWrapAlgorithm. + + + +Turner & Brown Informational [Page 9] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +3.2.2. Actions of the Sending Agent + + When using 1-Pass ECMQV with EnvelopedData, the sending agent first + obtains the recipient's EC public key and domain parameters (e.g., + from the recipient's certificate), and checks that the domain + parameters are the same as the sender's domain parameters. The + sending agent then determines an integer "keydatalen", which is the + KeyWrapAlgorithm symmetric key size in bits, and also a bit string + "SharedInfo", which is the DER encoding of ECC-CMS-SharedInfo (see + Section 7.2). The sending agent then performs the key deployment and + key agreement operations of the Elliptic Curve MQV Scheme specified + in [SP800-56A], but uses the KDF defined in Section 3.6.1 of [SEC1]. + As a result, the sending agent obtains: + + - an ephemeral public key, which is represented as a value of type + ECPoint (see Section 7.2), encapsulated in a bit string, placed in + an MQVuserKeyingMaterial ephemeralPublicKey publicKey field (see + Section 7.2), and + + - a shared secret bit string "K", which is used as the pairwise key- + encryption key for that recipient, as specified in [CMS]. + + In a single message, if there are multiple layers for a recipient, + then the ephemeral public key can be reused by the originator for + that recipient in each of the different layers. + +3.2.3. Actions of the Receiving Agent + + When using 1-Pass ECMQV with EnvelopedData, the receiving agent + determines the bit string "SharedInfo", which is the DER encoding of + ECC-CMS-SharedInfo (see Section 7.2), and the integer "keydatalen" + from the key size, in bits, of the KeyWrapAlgorithm. The receiving + agent then retrieves the static and ephemeral EC public keys of the + originator, from the originator and ukm fields as described in + Section 3.2.1, and its static EC public key identified in the rid + field and checks that the originator's domain parameters are the same + as the recipient's domain parameters. The receiving agent then + performs the key agreement operation of the Elliptic Curve MQV Scheme + [SP800-56A], but uses the KDF defined in Section 3.6.1 of [SEC1]. As + a result, the receiving agent obtains a shared secret bit string "K", + which is used as the pairwise key-encryption key to unwrap the CEK. + + + + + + + + + + +Turner & Brown Informational [Page 10] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +4. AuthenticatedData and AuthEnvelopedData Using ECC + + This section describes how to use ECC algorithms with the CMS + AuthenticatedData format. AuthenticatedData lacks non-repudiation, + and so in some instances is preferable to SignedData. (For example, + the sending agent might not want the message to be authenticated when + forwarded.) + + This section also describes how to use ECC algorithms with the CMS + AuthEnvelopedData format [CMS-AUTHENV]. AuthEnvelopedData supports + authentication and encryption, and in some instances is preferable to + signing and then encrypting data. + + For both AuthenticatedData and AuthEnvelopedData, data origin + authentication with 1-Pass ECMQV can only be provided when there is + one and only one recipient. When there are multiple recipients, an + attack is possible where one recipient modifies the content without + other recipients noticing [BON]. A sending agent who is concerned + with such an attack SHOULD use a separate AuthenticatedData or + AuthEnvelopedData for each recipient. + + Using an algorithm with the sender static key pair allows for + knowledge of the message creator; this means that authentication can, + in some circumstances, be obtained for AuthEnvelopedData and + AuthenticatedData. This means that 1-Pass ECMQV can be a common + algorithm for EnvelopedData, AuthenticatedData, and AuthEnvelopedData + while ECDH can only be used in EnvelopedData. + +4.1. AuthenticatedData Using 1-Pass ECMQV + + This section describes how to use the 1-Pass ECMQV key agreement + algorithm with AuthenticatedData. ECMQV is method C(1, 2, ECC MQV) + from [SP800-56A]. + + When using ECMQV with AuthenticatedData, the fields of + AuthenticatedData are as in [CMS], but with the following + restrictions: + + - macAlgorithm MUST contain the algorithm identifier of the message + authentication code (MAC) algorithm (see Section 7.1.7), which MUST + be one of the following: hmac-SHA1, id-hmacWITHSHA224, id- + hmacWITHSHA256, id-hmacWITHSHA384, or id-hmacWITHSHA512. + + - digestAlgorithm MUST contain the algorithm identifier of the hash + algorithm (see Section 7.1.1), which MUST be one of the following: + id-sha1, id-sha224, id-sha256, id-sha384, or id-sha512. + + + + + +Turner & Brown Informational [Page 11] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + As 1-Pass ECMQV is a key agreement algorithm, the RecipientInfo kari + choice is used in the AuthenticatedData. When using 1-Pass ECMQV, + the AuthenticatedData originatorInfo field MAY include the + certificate(s) for the EC public key(s) used in the formation of the + pairwise key. ECC certificates are discussed in Section 5. + +4.1.1. Fields of the KeyAgreeRecipientInfo + + The AuthenticatedData KeyAgreeRecipientInfo fields are used in the + same manner as the fields for the corresponding EnvelopedData + KeyAgreeRecipientInfo fields of Section 3.2.1 of this document. + +4.1.2. Actions of the Sending Agent + + The sending agent uses the same actions as for EnvelopedData with + 1-Pass ECMQV, as specified in Section 3.2.2 of this document. + + In a single message, if there are multiple layers for a recipient, + then the ephemeral public key can be reused by the originator for + that recipient in each of the different layers. + +4.1.3. Actions of the Receiving Agent + + The receiving agent uses the same actions as for EnvelopedData with + 1-Pass ECMQV, as specified in Section 3.2.3 of this document. + +4.2. AuthEnvelopedData Using 1-Pass ECMQV + + This section describes how to use the 1-Pass ECMQV key agreement + algorithm with AuthEnvelopedData. ECMQV is method C(1, 2, ECC MQV) + from [SP800-56A]. + + When using ECMQV with AuthEnvelopedData, the fields of + AuthEnvelopedData are as in [CMS-AUTHENV]. + + As 1-Pass ECMQV is a key agreement algorithm, the RecipientInfo kari + choice is used. When using 1-Pass ECMQV, the AuthEnvelopedData + originatorInfo field MAY include the certificate(s) for the EC public + key used in the formation of the pairwise key. ECC certificates are + discussed in Section 5. + +4.2.1. Fields of the KeyAgreeRecipientInfo + + The AuthEnvelopedData KeyAgreeRecipientInfo fields are used in the + same manner as the fields for the corresponding EnvelopedData + KeyAgreeRecipientInfo fields of Section 3.2.1 of this document. + + + + + +Turner & Brown Informational [Page 12] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +4.2.2. Actions of the Sending Agent + + The sending agent uses the same actions as for EnvelopedData with + 1-Pass ECMQV, as specified in Section 3.2.2 of this document. + + In a single message, if there are multiple layers for a recipient, + then the ephemeral public key can be reused by the originator for + that recipient in each of the different layers. + +4.2.3. Actions of the Receiving Agent + + The receiving agent uses the same actions as for EnvelopedData with + 1-Pass ECMQV, as specified in Section 3.2.3 of this document. + +5. Certificates Using ECC + + Internet X.509 certificates [PKI] can be used in conjunction with + this specification to distribute agents' public keys. The use of ECC + algorithms and keys within X.509 certificates is specified in + [PKI-ALG]. + +6. SMIMECapabilities Attribute and ECC + + A sending agent MAY announce to receiving agents that it supports one + or more of the ECC algorithms specified in this document by using the + SMIMECapabilities signed attribute [MSG] in either a signed message + or a certificate [CERTCAP]. + + The SMIMECapabilities attribute value indicates support for one of + the ECDSA signature algorithms in a SEQUENCE with the capabilityID + field containing the object identifier ecdsa-with-SHA1 with NULL + parameters and ecdsa-with-SHA* (where * is 224, 256, 384, or 512) + with absent parameters. The DER encodings are: + + ecdsa-with-SHA1: 30 0b 06 07 2a 86 48 ce 3d 04 01 05 00 + + ecdsa-with-SHA224: 30 0a 06 08 2a 86 48 ce 3d 04 03 01 + + ecdsa-with-SHA256: 30 0a 06 08 2a 86 48 ce 3d 04 03 02 + + ecdsa-with-SHA384: 30 0a 06 08 2a 86 48 ce 3d 04 03 03 + + ecdsa-with-SHA512: 30 0a 06 08 2a 86 48 ce 3d 04 03 04 + + NOTE: The SMIMECapabilities attribute indicates that parameters for + ECDSA with SHA-1 are NULL; however, the parameters are absent when + used to generate a digital signature. + + + + +Turner & Brown Informational [Page 13] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + The SMIMECapabilities attribute value indicates support for + + a) the standard ECDH key agreement algorithm, + b) the cofactor ECDH key agreement algorithm, or + c) the 1-Pass ECMQV key agreement algorithm and + + is a SEQUENCE with the capabilityID field containing the object + identifier + + a) dhSinglePass-stdDH-sha*kdf-scheme, + b) dhSinglePass-cofactorDH-sha*kdf-scheme, or + c) mqvSinglePass-sha*kdf-scheme + + respectively (where * is 1, 224, 256, 384, or 512) with the + parameters present. The parameters indicate the supported key- + encryption algorithm with the KeyWrapAlgorithm algorithm identifier. + + The DER encodings that indicate capabilities are as follows (KA is + key agreement, KDF is key derivation function, and Wrap is key wrap + algorithm): + + KA=ECDH standard KDF=SHA-1 Wrap=Triple-DES + + 30 1c 06 09 2b 81 05 10 86 48 3f 00 02 30 0f 06 0b 2a 86 48 86 + f7 0d 01 09 10 03 06 05 00 + + KA=ECDH standard KDF=SHA-224 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0B 00 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH standard KDF=SHA-256 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0B 01 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH standard KDF=SHA-384 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0B 02 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH standard KDF=SHA-512 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0B 03 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + + + + + +Turner & Brown Informational [Page 14] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECDH standard KDF=SHA-1 Wrap=AES-128 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 02 30 0b 06 09 60 86 48 01 + 65 03 04 01 05 + + KA=ECDH standard KDF=SHA-224 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0B 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH standard KDF=SHA-256 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0B 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH standard KDF=SHA-384 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0B 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH standard KDF=SHA-512 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0B 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH standard KDF=SHA-1 Wrap=AES-192 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 02 30 0b 06 09 60 86 48 01 + 65 03 04 01 19 + + KA=ECDH standard KDF=SHA-224 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0B 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH standard KDF=SHA-256 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0B 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH standard KDF=SHA-384 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0B 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + + + + + + +Turner & Brown Informational [Page 15] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECDH standard KDF=SHA-512 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0B 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH standard KDF=SHA-1 Wrap=AES-256 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 02 30 0b 06 09 60 86 48 01 + 65 03 04 01 2D + + KA=ECDH standard KDF=SHA-224 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0B 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH standard KDF=SHA-256 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0B 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH standard KDF=SHA-384 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0B 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D 05 00 + + KA=ECDH standard KDF=SHA-512 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0B 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH cofactor KDF=SHA-1 Wrap=Triple-DES + + 30 1c 06 09 2b 81 05 10 86 48 3f 00 03 30 0f 06 0b 2a 86 48 86 + f7 0d 01 09 10 03 06 05 00 + + KA=ECDH cofactor KDF=SHA-224 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0E 00 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH cofactor KDF=SHA-256 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0E 01 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + + + + + + +Turner & Brown Informational [Page 16] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECDH cofactor KDF=SHA-384 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0E 02 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH cofactor KDF=SHA-512 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0E 03 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECDH cofactor KDF=SHA-1 Wrap=AES-128 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 03 30 0b 06 09 60 86 48 01 + 65 03 04 01 05 + + KA=ECDH cofactor KDF=SHA-224 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0E 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH cofactor KDF=SHA-256 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0E 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH cofactor KDF=SHA-384 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0E 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH cofactor KDF=SHA-512 Wrap=AES-128 + + 30 17 06 06 2b 81 04 01 0E 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECDH cofactor KDF=SHA-1 Wrap=AES-192 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 03 30 0b 06 09 60 86 48 01 + 65 03 04 01 19 + + KA=ECDH cofactor KDF=SHA-224 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0E 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + + + + + + +Turner & Brown Informational [Page 17] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECDH cofactor KDF=SHA-256 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0E 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH cofactor KDF=SHA-384 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0E 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH cofactor KDF=SHA-512 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0E 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECDH cofactor KDF=SHA-1 Wrap=AES-256 + + 30 15 06 09 2b 81 05 10 86 48 3f 00 03 30 0b 06 09 60 86 48 01 + 65 03 04 01 2D + + KA=ECDH cofactor KDF=SHA-224 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0E 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH cofactor KDF=SHA-256 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0E 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH cofactor KDF=SHA-384 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0E 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECDH cofactor KDF=SHA-512 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0E 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECMQV 1-Pass KDF=SHA-1 Wrap=Triple-DES + + 30 1c 06 09 2b 81 05 10 86 48 3f 00 10 30 0f 06 0b 2a 86 48 86 + f7 0d 01 09 10 03 06 05 00 + + + + + + + +Turner & Brown Informational [Page 18] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECMQV 1-Pass KDF=SHA-224 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0F 00 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECMQV 1-Pass KDF=SHA-256 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0F 01 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECMQV 1-Pass KDF=SHA-384 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0F 02 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECMQV 1-Pass KDF=SHA-512 Wrap=Triple-DES + + 30 17 06 06 2b 81 04 01 0F 03 30 0d 06 0b 2a 86 48 86 f7 0d 01 + 09 10 03 06 + + KA=ECMQV 1-Pass KDF=SHA-1 Wrap=AES-128 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 10 30 0b 06 09 60 86 48 01 + 65 03 04 01 05 + + KA=ECMQV 1-Pass KDF=SHA-224 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0F 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECMQV 1-Pass KDF=SHA-256 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0F 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECMQV 1-Pass KDF=SHA-384 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0F 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + KA=ECMQV 1-Pass KDF=SHA-512 Wrap=AES-128 + + 30 15 06 06 2b 81 04 01 0F 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 05 + + + + + + + +Turner & Brown Informational [Page 19] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECMQV 1-Pass KDF=SHA-1 Wrap=AES-192 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 10 30 0b 06 09 60 86 48 01 + 65 03 04 01 19 + + KA=ECMQV 1-Pass KDF=SHA-224 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0F 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECMQV 1-Pass KDF=SHA-256 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0F 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECMQV 1-Pass KDF=SHA-384 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0F 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECMQV 1-Pass KDF=SHA-512 Wrap=AES-192 + + 30 15 06 06 2b 81 04 01 0F 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 19 + + KA=ECMQV 1-Pass KDF=SHA-1 Wrap=AES-256 + + 30 18 06 09 2b 81 05 10 86 48 3f 00 10 30 0b 06 09 60 86 48 01 + 65 03 04 01 2D + + KA=ECMQV 1-Pass KDF=SHA-224 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0F 00 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECMQV 1-Pass KDF=SHA-256 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0F 01 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + KA=ECMQV 1-Pass KDF=SHA-384 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0F 02 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + + + + + + +Turner & Brown Informational [Page 20] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KA=ECMQV 1-Pass KDF=SHA-512 Wrap=AES-256 + + 30 15 06 06 2b 81 04 01 0F 03 30 0b 06 09 60 86 48 01 65 03 04 + 01 2D + + NOTE: The S/MIME Capabilities for the supported AES content- + encryption key sizes are defined in [CMS-AES]. + + NOTE: The S/MIME Capabilities for the supported MAC algorithms are + defined in [CMS-ASN]. + +7. ASN.1 Syntax + + The ASN.1 syntax [X.680], [X.681], [X.682], [X.683] used in this + document is gathered in this section for reference purposes. + +7.1. Algorithm Identifiers + + This section provides the object identifiers for the algorithms used + in this document along with any associated parameters. + +7.1.1. Digest Algorithms + + Digest algorithm object identifiers are used in the SignedData + digestAlgorithms and digestAlgorithm fields and the AuthenticatedData + digestAlgorithm field. The digest algorithms used in this document + are SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512. The object + identifiers and parameters associated with these algorithms are found + in [CMS-ALG] and [CMS-SHA2]. + +7.1.2. Originator Public Key + + The KeyAgreeRecipientInfo originator field uses the following object + identifier to indicate an elliptic curve public key: + + id-ecPublicKey OBJECT IDENTIFIER ::= { + ansi-x9-62 keyType(2) 1 } + + where + + ansi-x9-62 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) 10045 } + + When the object identifier id-ecPublicKey is used here with an + algorithm identifier, the associated parameters MUST be either absent + or ECParameters. Implementations MUST accept id-ecPublicKey with + absent and ECParameters parameters. If ECParameters is present, its + + + + +Turner & Brown Informational [Page 21] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + value MUST match the recipient's ECParameters. Implementations + SHOULD generate absent parameters for the id-ecPublicKey object + identifier in the KeyAgreeRecipientInfo originator field. + + [CMS-ECC] indicated the parameters were NULL. Support for this + legacy form is OPTIONAL. + +7.1.3. Signature Algorithms + + Signature algorithm identifiers are used in the SignedData + signatureAlgorithm and signature fields. The signature algorithms + used in this document are ECDSA with SHA-1, ECDSA with SHA-224, ECDSA + with SHA-256, ECDSA with SHA-384, and ECDSA with SHA-512. The object + identifiers and parameters associated with these algorithms are found + in [PKI-ALG]. + + [CMS-ECC] indicated the parameters were NULL. Support for this + legacy form is OPTIONAL. + +7.1.4. Key Agreement Algorithms + + Key agreement algorithms are used in EnvelopedData, + AuthenticatedData, and AuthEnvelopedData in the KeyAgreeRecipientInfo + keyEncryptionAlgorithm field. The following object identifiers + indicate the key agreement algorithms used in this document + [SP800-56A], [SEC1]: + + dhSinglePass-stdDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 2 } + + dhSinglePass-stdDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 0 } + + dhSinglePass-stdDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 1 } + + dhSinglePass-stdDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 2 } + + dhSinglePass-stdDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 3 } + + dhSinglePass-cofactorDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 3 } + + dhSinglePass-cofactorDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 0 } + + + + +Turner & Brown Informational [Page 22] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + dhSinglePass-cofactorDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 1 } + + dhSinglePass-cofactorDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 2 } + + dhSinglePass-cofactorDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 3 } + + mqvSinglePass-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 16 } + + mqvSinglePass-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 0 } + + mqvSinglePass-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 1 } + + mqvSinglePass-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 2 } + + mqvSinglePass-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 3 } + + where + + x9-63-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) tc68(133) country(16) + x9(840) x9-63(63) schemes(0) } + + and + + secg-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) certicom(132) schemes(1) } + + When the object identifiers are used here within an algorithm + identifier, the associated parameters field contains KeyWrapAlgorithm + to indicate the key wrap algorithm and any associated parameters. + +7.1.5. Key Wrap Algorithms + + Key wrap algorithms are used as part of the parameters in the key + agreement algorithm. The key wrap algorithms used in this document + are Triple-DES, AES-128, AES-192, and AES-256. The object + identifiers and parameters for these algorithms are found in + [CMS-ALG] and [CMS-AES]. + + + + + +Turner & Brown Informational [Page 23] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +7.1.6. Content Encryption Algorithms + + Content encryption algorithms are used in EnvelopedData and + AuthEnvelopedData in the EncryptedContentInfo + contentEncryptionAlgorithm field. The content encryption algorithms + used with EnvelopedData in this document are 3-Key Triple DES in CBC + mode, AES-128 in CBC mode, AES-192 in CBC mode, and AES-256 in CBC + mode. The object identifiers and parameters associated with these + algorithms are found in [CMS-ALG] and [CMS-AES]. The content + encryption algorithms used with AuthEnvelopedData in this document + are AES-128 in CCM mode, AES-192 in CCM mode, AES-256 in CCM mode, + AES-128 in GCM mode, AES-192 in GCM mode, and AES-256 in GCM mode. + The object identifiers and parameters associated with these + algorithms are found in [CMS-AESCG]. + +7.1.7. Message Authentication Code Algorithms + + Message authentication code algorithms are used in AuthenticatedData + in the macAlgorithm field. The message authentication code + algorithms used in this document are HMAC with SHA-1, HMAC with + SHA-224, HMAC with SHA-256, HMAC with SHA-384, and HMAC with SHA-512. + The object identifiers and parameters associated with these + algorithms are found in [CMS-ALG] and [HMAC-SHA2]. + + NOTE: [HMAC-SHA2] defines the object identifiers for HMAC with + SHA-224, HMAC with SHA-256, HMAC with SHA-384, and HMAC with SHA-512, + but there is no ASN.1 module from which to import these object + identifiers. Therefore, the object identifiers for these algorithms + are included in the ASN.1 modules defined in Appendix A. + +7.1.8. Key Derivation Algorithm + + The KDF used in this document is as specified in Section 3.6.1 of + [SEC1]. The hash algorithm is identified in the key agreement + algorithm. For example, dhSinglePass-stdDH-sha256kdf-scheme uses the + KDF from [SEC1] but uses SHA-256 instead of SHA-1. + +7.2. Other Syntax + + The following additional syntax is used here. + + When using ECDSA with SignedData, ECDSA signatures are encoded using + the type: + + ECDSA-Sig-Value ::= SEQUENCE { + r INTEGER, + s INTEGER } + + + + +Turner & Brown Informational [Page 24] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + ECDSA-Sig-Value is specified in [PKI-ALG]. Within CMS, ECDSA-Sig- + Value is DER-encoded and placed within a signature field of + SignedData. + + When using ECDH and ECMQV with EnvelopedData, AuthenticatedData, and + AuthEnvelopedData, ephemeral and static public keys are encoded using + the type ECPoint. Implementations MUST support uncompressed keys, + MAY support compressed keys, and MUST NOT support hybrid keys. + + ECPoint ::= OCTET STRING + + When using ECMQV with EnvelopedData, AuthenticatedData, and + AuthEnvelopedData, the sending agent's ephemeral public key and + additional keying material are encoded using the type: + + MQVuserKeyingMaterial ::= SEQUENCE { + ephemeralPublicKey OriginatorPublicKey, + addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL } + + The ECPoint syntax is used to represent the ephemeral public key and + is placed in the ephemeralPublicKey publicKey field. The additional + user keying material is placed in the addedukm field. Then the + MQVuserKeyingMaterial value is DER-encoded and placed within the ukm + field of EnvelopedData, AuthenticatedData, or AuthEnvelopedData. + + When using ECDH or ECMQV with EnvelopedData, AuthenticatedData, or + AuthEnvelopedData, the key-encryption keys are derived by using the + type: + + ECC-CMS-SharedInfo ::= SEQUENCE { + keyInfo AlgorithmIdentifier, + entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL, + suppPubInfo [2] EXPLICIT OCTET STRING } + + The fields of ECC-CMS-SharedInfo are as follows: + + keyInfo contains the object identifier of the key-encryption + algorithm (used to wrap the CEK) and associated parameters. In + this specification, 3DES wrap has NULL parameters while the AES + wraps have absent parameters. + + entityUInfo optionally contains additional keying material + supplied by the sending agent. When used with ECDH and CMS, the + entityUInfo field contains the octet string ukm. When used with + ECMQV and CMS, the entityUInfo contains the octet string addedukm + (encoded in MQVuserKeyingMaterial). + + + + + +Turner & Brown Informational [Page 25] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + suppPubInfo contains the length of the generated KEK, in bits, + represented as a 32-bit number, as in [CMS-DH] and [CMS-AES]. + (For example, for AES-256 it would be 00 00 01 00.) + + Within CMS, ECC-CMS-SharedInfo is DER-encoded and used as input to + the key derivation function, as specified in Section 3.6.1 of [SEC1]. + + NOTE: ECC-CMS-SharedInfo differs from the OtherInfo specified in + [CMS-DH]. Here, a counter value is not included in the keyInfo field + because the key derivation function specified in Section 3.6.1 of + [SEC1] ensures that sufficient keying data is provided. + +8. Recommended Algorithms and Elliptic Curves + + It is RECOMMENDED that implementations of this specification support + SignedData and EnvelopedData. Support for AuthenticatedData and + AuthEnvelopedData is OPTIONAL. + + In order to encourage interoperability, implementations SHOULD use + the elliptic curve domain parameters specified by [PKI-ALG]. + + Implementations that support SignedData with ECDSA: + + - MUST support ECDSA with SHA-256; and + + - MAY support ECDSA with SHA-1, ECDSA with SHA-224, ECDSA with + SHA-384, and ECDSA with SHA-512; other digital signature + algorithms MAY also be supported. + + When using ECDSA, to promote interoperability it is RECOMMENDED that + the P-192, P-224, and P-256 curves be used with SHA-256; the P-384 + curve be used with SHA-384; and the P-521 curve be used with SHA-512. + + If EnvelopedData is supported, then ephemeral-static ECDH standard + primitive MUST be supported. Support for ephemeral-static ECDH co- + factor is OPTIONAL, and support for 1-Pass ECMQV is also OPTIONAL. + + Implementations that support EnvelopedData with the ephemeral-static + ECDH standard primitive: + + - MUST support the dhSinglePass-stdDH-sha256kdf-scheme key + agreement algorithm, the id-aes128-wrap key wrap algorithm, and + the id-aes128-cbc content encryption algorithm; and + + + + + + + + +Turner & Brown Informational [Page 26] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + - MAY support the dhSinglePass-stdDH-sha1kdf-scheme, dhSinglePass- + stdDH-sha224kdf-scheme, dhSinglePass-stdDH-sha384kdf-scheme, and + dhSinglePass-stdDH-sha512kdf-scheme key agreement algorithms; + the id-alg-CMS3DESwrap, id-aes192-wrap, and id-aes256-wrap key + wrap algorithms; and the des-ede3-cbc, id-aes192-cbc, and id- + aes256-cbc content encryption algorithms; other algorithms MAY + also be supported. + + Implementations that support EnvelopedData with the ephemeral-static + ECDH cofactor primitive: + + - MUST support the dhSinglePass-cofactorDH-sha256kdf-scheme key + agreement algorithm, the id-aes128-wrap key wrap algorithm, and + the id-aes128-cbc content encryption algorithm; and + + - MAY support the dhSinglePass-cofactorDH-sha1kdf-scheme, + dhSinglePass-cofactorDH-sha224kdf-scheme, dhSinglePass- + cofactorDH-sha384kdf-scheme, and dhSinglePass-cofactorDH- + sha512kdf-scheme key agreement; the id-alg-CMS3DESwrap, id- + aes192-wrap, and id-aes256-wrap key wrap algorithms; and the + des-ede3-cbc, id-aes192-cbc, and id-aes256-cbc content + encryption algorithms; other algorithms MAY also be supported. + + Implementations that support EnvelopedData with 1-Pass ECMQV: + + - MUST support the mqvSinglePass-sha256kdf-scheme key agreement + algorithm, the id-aes128-wrap key wrap algorithm, and the id- + aes128-cbc content encryption algorithm; and + + - MAY support the mqvSinglePass-sha1kdf-scheme, mqvSinglePass- + sha224kdf-scheme, mqvSinglePass-sha384kdf-scheme, and + mqvSinglePass-sha512kdf-scheme key agreement algorithms; the id- + alg-CMS3DESwrap, id-aes192-wrap, and id-aes256-wrap key wrap + algorithms; and the des-ede3-cbc, id-aes192-cbc, and id- + aes256-cbc content encryption algorithms; other algorithms MAY + also be supported. + + Implementations that support AuthenticatedData with 1-Pass ECMQV: + + - MUST support the mqvSinglePass-sha256kdf-scheme key agreement, + the id-aes128-wrap key wrap, the id-sha256 message digest, and + id-hmacWithSHA256 message authentication code algorithms; and + + - MAY support the mqvSinglePass-sha1kdf-scheme, mqvSinglePass- + sha224kdf-scheme, mqvSinglePass-sha384kdf-scheme, mqvSinglePass- + sha512kdf-scheme key agreement algorithms; the id-alg- + CMS3DESwrap, id-aes192-wrap, and id-aes256-wrap key wrap + algorithms; the id-sha1, id-sha224, id-sha384, and id-sha512, + + + +Turner & Brown Informational [Page 27] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + message digest algorithms; and the hmac-SHA1, id-hmacWithSHA224, + id-hmacWithSHA384, and id-hmacWithSHA512 message authentication + code algorithms; other algorithms MAY also be supported. + + Implementations that support AuthEnvelopedData with 1-Pass ECMQV: + + - MUST support the mqvSinglePass-sha256kdf-scheme key agreement, + the id-aes128-wrap key wrap, and the id-aes128-ccm + authenticated-content encryption; and + + - MAY support the mqvSinglePass-sha1kdf-scheme, mqvSinglePass- + sha224kdf-scheme, mqvSinglePass-sha384kdf-scheme, and + mqvSinglePass-sha512kdf-scheme key agreement algorithms; the id- + alg-CMS3DESwrap, id-aes192-wrap, and id-aes256-wrap key wrap + algorithms; and the id-aes192-ccm, id-aes256-ccm, id-aes128-gcm, + id-aes192-gcm, and id-aes256-ccm authenticated-content + encryption algorithms; other algorithms MAY also be supported. + +9. Security Considerations + + Cryptographic algorithms will be broken or weakened over time. + Implementers and users need to check that the cryptographic + algorithms listed in this document continue to provide the expected + level of security. The IETF from time to time may issue documents + dealing with the current state of the art. + + Cryptographic algorithms rely on random numbers. See [RANDOM] for + guidance on generation of random numbers. + + Receiving agents that validate signatures and sending agents that + encrypt messages need to be cautious of cryptographic processing + usage when validating signatures and encrypting messages using keys + larger than those mandated in this specification. An attacker could + send keys and/or certificates with keys that would result in + excessive cryptographic processing, for example, keys larger than + those mandated in this specification, which could swamp the + processing element. Agents that use such keys without first + validating the certificate to a trust anchor are advised to have some + sort of cryptographic resource management system to prevent such + attacks. + + Using secret keys of an appropriate size is crucial to the security + of a Diffie-Hellman exchange. For elliptic curve groups, the size of + the secret key must be equal to the size of n (the order of the group + generated by the point g). Using larger secret keys provides + absolutely no additional security, and using smaller secret keys is + likely to result in dramatically less security. (See [SP800-56A] for + more information on selecting secret keys.) + + + +Turner & Brown Informational [Page 28] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + This specification is based on [CMS], [CMS-AES], [CMS-AESCG], + [CMS-ALG], [CMS-AUTHENV], [CMS-DH], [CMS-SHA2], [FIPS180-3], + [FIPS186-3], and [HMAC-SHA2], and the appropriate security + considerations of those documents apply. + + In addition, implementers of AuthenticatedData and AuthEnvelopedData + should be aware of the concerns expressed in [BON] when using + AuthenticatedData and AuthEnvelopedData to send messages to more than + one recipient. Also, users of MQV should be aware of the + vulnerability described in [K]. + + When implementing EnvelopedData, AuthenticatedData, and + AuthEnvelopedData, there are five algorithm-related choices that need + to be made: + + 1) What is the public key size? + 2) What is the KDF? + 3) What is the key wrap algorithm? + 4) What is the content encryption algorithm? + 5) What is the curve? + + Consideration must be given to the strength of the security provided + by each of these choices. Security algorithm strength is measured in + bits, where bits is measured in equivalence to a symmetric cipher + algorithm. Thus, a strong symmetric cipher algorithm with a key of X + bits is said to provide X bits of security. For other algorithms, + the key size is mapped to an equivalent symmetric cipher strength. + It is recommended that the bits of security provided by each are + roughly equivalent. The following table provides comparable minimum + bits of security [SP800-57] for the ECDH/ECMQV key sizes, KDFs, key + wrapping algorithms, and content encryption algorithms. It also + lists curves [PKI-ALG] for the key sizes. + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 29] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + Minimum | ECDH or | Key | Key | Content | Curves + Bits of | ECMQV | Derivation | Wrap | Encryption | + Security | Key Size | Function | Alg. | Alg. | + ---------+----------+------------+----------+-------------+---------- + 80 | 160-223 | SHA-1 | 3DES | 3DES CBC | sect163k1 + | | SHA-224 | AES-128 | AES-128 CBC | secp163r2 + | | SHA-256 | AES-192 | AES-192 CBC | secp192r1 + | | SHA-384 | AES-256 | AES-256 CBC | + | | SHA-512 | | | + ---------+----------+------------+----------+-------------+--------- + 112 | 224-255 | SHA-1 | 3DES | 3DES CBC | secp224r1 + | | SHA-224 | AES-128 | AES-128 CBC | sect233k1 + | | SHA-256 | AES-192 | AES-192 CBC | sect233r1 + | | SHA-384 | AES-256 | AES-256 CBC | + | | SHA-512 | | | + ---------+----------+------------+----------+-------------+--------- + 128 | 256-383 | SHA-1 | AES-128 | AES-128 CBC | secp256r1 + | | SHA-224 | AES-192 | AES-192 CBC | sect283k1 + | | SHA-256 | AES-256 | AES-256 CBC | sect283r1 + | | SHA-384 | | | + | | SHA-512 | | | + ---------+----------+------------+----------+-------------+--------- + 192 | 384-511 | SHA-224 | AES-192 | AES-192 CBC | secp384r1 + | | SHA-256 | AES-256 | AES-256 CBC | sect409k1 + | | SHA-384 | | | sect409r1 + | | SHA-512 | | | + ---------+----------+------------+----------+-------------+--------- + 256 | 512+ | SHA-256 | AES-256 | AES-256 CBC | secp521r1 + | | SHA-384 | | | sect571k1 + | | SHA-512 | | | sect571r1 + ---------+----------+------------+----------+-------------+--------- + + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 30] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + To promote interoperability, the following choices are RECOMMENDED: + + Minimum | ECDH or | Key | Key | Content | Curve + Bits of | ECMQV | Derivation | Wrap | Encryption | + Security | Key Size | Function | Alg. | Alg. | + ---------+----------+------------+----------+-------------+---------- + 80 | 192 | SHA-256 | 3DES | 3DES CBC | secp192r1 + ---------+----------+------------+----------+-------------+---------- + 112 | 224 | SHA-256 | 3DES | 3DES CBC | secp224r1 + ---------+----------+------------+----------+-------------+---------- + 128 | 256 | SHA-256 | AES-128 | AES-128 CBC | secp256r1 + ---------+----------+------------+----------+-------------+---------- + 192 | 384 | SHA-384 | AES-256 | AES-256 CBC | secp384r1 + ---------+----------+------------+----------+-------------+---------- + 256 | 512+ | SHA-512 | AES-256 | AES-256 CBC | secp521r1 + ---------+----------+------------+----------+-------------+---------- + + When implementing SignedData, there are three algorithm-related + choices that need to be made: + + 1) What is the public key size? + 2) What is the hash algorithm? + 3) What is the curve? + + Consideration must be given to the bits of security provided by each + of these choices. Security is measured in bits, where a strong + symmetric cipher with a key of X bits is said to provide X bits of + security. It is recommended that the bits of security provided by + each choice are roughly equivalent. The following table provides + comparable minimum bits of security [SP800-57] for the ECDSA key + sizes and message digest algorithms. It also lists curves [PKI-ALG] + for the key sizes. + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 31] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + Minimum | ECDSA | Message | Curve + Bits of | Key Size | Digest | + Security | | Algorithm | + ---------+----------+-----------+----------- + 80 | 160-223 | SHA-1 | sect163k1 + | | SHA-224 | secp163r2 + | | SHA-256 | secp192r1 + | | SHA-384 | + | | SHA-512 | + ---------+----------+-----------+----------- + 112 | 224-255 | SHA-224 | secp224r1 + | | SHA-256 | sect233k1 + | | SHA-384 | sect233r1 + | | SHA-512 | + ---------+----------+-----------+----------- + 128 | 256-383 | SHA-256 | secp256r1 + | | SHA-384 | sect283k1 + | | SHA-512 | sect283r1 + ---------+----------+-----------+----------- + 192 | 384-511 | SHA-384 | secp384r1 + | | SHA-512 | sect409k1 + | | | sect409r1 + ---------+----------+-----------+----------- + 256 | 512+ | SHA-512 | secp521r1 + | | | sect571k1 + | | | sect571r1 + ---------+----------+-----------+----------- + + To promote interoperability, the following choices are RECOMMENDED: + + Minimum | ECDSA | Message | Curve + Bits of | Key Size | Digest | + Security | | Algorithm | + ---------+----------+-----------+----------- + 80 | 192 | SHA-256 | sect192r1 + ---------+----------+-----------+----------- + 112 | 224 | SHA-256 | secp224r1 + ---------+----------+-----------+----------- + 128 | 256 | SHA-256 | secp256r1 + ---------+----------+-----------+----------- + 192 | 384 | SHA-384 | secp384r1 + ---------+----------+-----------+----------- + 256 | 512+ | SHA-512 | secp521r1 + ---------+----------+-----------+----------- + + + + + + + +Turner & Brown Informational [Page 32] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +10. IANA Considerations + + This document makes extensive use of object identifiers to register + originator public key types and algorithms. The algorithm object + identifiers are registered in the ANSI X9.62, ANSI X9.63, NIST, RSA, + and SECG arcs. Additionally, object identifiers are used to identify + the ASN.1 modules found in Appendix A (there are two). These are + defined by the SMIME WG Registrar in an arc delegated by RSA to the + SMIME Working Group: iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs-9(9) smime(16) modules(0). No action by IANA is + necessary for this document or any anticipated updates. + +11. References + +11.1. Normative References + + [CMS] Housley, R., "Cryptographic Message Syntax (CMS)", RFC + 5652, September 2009. + + [CMS-AES] Schaad, J., "Use of the Advanced Encryption Standard + (AES) Encryption Algorithm in Cryptographic Message + Syntax (CMS)", RFC 3565, July 2003. + + [CMS-AESCG] Housley, R., "Using AES-CCM and AES-GCM Authenticated + Encryption in the Cryptographic Message Syntax (CMS)", + RFC 5084, December 2007. + + [CMS-ALG] Housley, R., "Cryptographic Message Syntax (CMS) + Algorithms", RFC 3370, August 2002. + + [CMS-AUTHENV] Housley, R., "Cryptographic Message Syntax (CMS) + Authenticated-Enveloped-Data Content Type", RFC 5083, + November 2007. + + [CMS-DH] Rescorla, E., "Diffie-Hellman Key Agreement Method", + RFC 2631, June 1999. + + [CMS-SHA2] Turner, S., "Using SHA2 Algorithms with Cryptographic + Message Syntax", RFC 5754, January 2010. + + [FIPS180-3] National Institute of Standards and Technology (NIST), + FIPS Publication 180-3: Secure Hash Standard, October + 2008. + + [FIPS186-3] National Institute of Standards and Technology (NIST), + FIPS Publication 186-3: Digital Signature Standard, + June 2009. + + + + +Turner & Brown Informational [Page 33] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + [HMAC-SHA2] Nystrom, M., "Identifiers and Test Vectors for HMAC- + SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC- + SHA-512", RFC 4231, December 2005. + + [MUST] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [MSG] Ramsdell, B. and S. Turner, "Secure/Multipurpose + Internet Mail Extensions (S/MIME) Version 3.2 Message + Specification", RFC 5751, January 2010. + + [PKI] 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, May 2008. + + [PKI-ALG] Turner, S., Brown, D., Yiu, K., Housley, R., and T. + Polk, "Elliptic Curve Cryptography Subject Public Key + Information", RFC 5480, March 2009. + + [RANDOM] Eastlake, D., 3rd, Schiller, J., and S. Crocker, + "Randomness Requirements for Security", BCP 106, RFC + 4086, June 2005. + + [RSAOAEP] Schaad, J., Kaliski, B., and R. Housley, "Additional + Algorithms and Identifiers for RSA Cryptography for + use in the Internet X.509 Public Key Infrastructure + Certificate and Certificate Revocation List (CRL) + Profile", RFC 4055, June 2005. + + [SEC1] Standards for Efficient Cryptography Group, "SEC 1: + Elliptic Curve Cryptography", version 2.0, May 2009, + available from www.secg.org. + + [SP800-56A] National Institute of Standards and Technology (NIST), + Special Publication 800-56A: Recommendation Pair-Wise + Key Establishment Schemes Using Discrete Logarithm + Cryptography (Revised), March 2007. + + [X.680] ITU-T Recommendation X.680 (2002) | ISO/IEC + 8824-1:2002. Information Technology - Abstract Syntax + Notation One. + + + + + + + + + +Turner & Brown Informational [Page 34] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +11.2. Informative References + + [BON] D. Boneh, "The Security of Multicast MAC", + Presentation at Selected Areas of Cryptography 2000, + Center for Applied Cryptographic Research, University + of Waterloo, 2000. Paper version available from + http://crypto.stanford.edu/~dabo/papers/mmac.ps + + [CERTCAP] Santesson, S., "X.509 Certificate Extension for + Secure/Multipurpose Internet Mail Extensions (S/MIME) + Capabilities", RFC 4262, December 2005. + + [CMS-ASN] Hoffman, P. and J. Schaad, "New ASN.1 Modules for CMS + and S/MIME", Work in Progress, August 2009. + + [CMS-ECC] Blake-Wilson, S., Brown, D., and P. Lambert, "Use of + Elliptic Curve Cryptography (ECC) Algorithms in + Cryptographic Message Syntax (CMS)", RFC 3278, April + 2002. + + [CMS-KEA] Pawling, J., "Use of the KEA and SKIPJACK Algorithms + in CMS", RFC 2876, July 2000. + + [K] B. Kaliski, "MQV Vulnerability", Posting to ANSI X9F1 + and IEEE P1363 newsgroups, 1998. + + [PKI-ASN] Hoffman, P. and J. Schaad, "New ASN.1 Modules for + PKIX", Work in Progress, August 2009. + + [SP800-57] National Institute of Standards and Technology (NIST), + Special Publication 800-57: Recommendation for Key + Management - Part 1 (Revised), March 2007. + + [X.681] ITU-T Recommendation X.681 (2002) | ISO/IEC + 8824-2:2002. Information Technology - Abstract Syntax + Notation One: Information Object Specification. + + [X.682] ITU-T Recommendation X.682 (2002) | ISO/IEC + 8824-3:2002. Information Technology - Abstract Syntax + Notation One: Constraint Specification. + + [X.683] ITU-T Recommendation X.683 (2002) | ISO/IEC + 8824-4:2002. Information Technology - Abstract Syntax + Notation One: Parameterization of ASN.1 + Specifications, 2002. + + + + + + +Turner & Brown Informational [Page 35] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + [X9.62] X9.62-2005, "Public Key Cryptography for the Financial + Services Industry: The Elliptic Curve Digital + Signature Standard (ECDSA)", November, 2005. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 36] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +Appendix A. ASN.1 Modules + + Appendix A.1 provides the normative ASN.1 definitions for the + structures described in this specification using ASN.1 as defined in + [X.680] for compilers that support the 1988 ASN.1. + + Appendix A.2 provides informative ASN.1 definitions for the + structures described in this specification using ASN.1 as defined in + [X.680], [X.681], [X.682], and [X.683] for compilers that support the + 2002 ASN.1. This appendix contains the same information as Appendix + A.1 in a more recent (and precise) ASN.1 notation; however, Appendix + A.1 takes precedence in case of conflict. + +A.1. 1988 ASN.1 Module + + CMSECCAlgs-2009-88 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-ecc-alg-2009-88(45) } + + DEFINITIONS IMPLICIT TAGS ::= + + BEGIN + + -- EXPORTS ALL + + IMPORTS + + -- From [PKI] + + AlgorithmIdentifier + FROM PKIX1Explicit88 + { iso(1) identified-organization(3) dod(6) + internet(1) security(5) mechanisms(5) pkix(7) mod(0) + pkix1-explicit(18) } + + -- From [RSAOAEP] + + id-sha224, id-sha256, id-sha384, id-sha512 + FROM PKIX1-PSS-OAEP-Algorithms + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) + id-mod-pkix1-rsa-pkalgs(33) } + + + + + + + + + +Turner & Brown Informational [Page 37] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + -- From [PKI-ALG] + + id-sha1, ecdsa-with-SHA1, ecdsa-with-SHA224, + ecdsa-with-SHA256, ecdsa-with-SHA384, ecdsa-with-SHA512, + id-ecPublicKey, ECDSA-Sig-Value, ECPoint, ECParameters + FROM PKIX1Algorithms2008 + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) 45 } + + -- From [CMS] + + OriginatorPublicKey, UserKeyingMaterial + FROM CryptographicMessageSyntax2004 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) cms-2004(24) } + + -- From [CMS-ALG] + + hMAC-SHA1, des-ede3-cbc, id-alg-CMS3DESwrap, CBCParameter + FROM CryptographicMessageSyntaxAlgorithms + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) cmsalg-2001(16) } + + -- From [CMS-AES] + + id-aes128-CBC, id-aes192-CBC, id-aes256-CBC, AES-IV, + id-aes128-wrap, id-aes192-wrap, id-aes256-wrap + FROM CMSAesRsaesOaep + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-aes(19) } + + -- From [CMS-AESCG] + + id-aes128-CCM, id-aes192-CCM, id-aes256-CCM, CCMParameters + id-aes128-GCM, id-aes192-GCM, id-aes256-GCM, GCMParameters + FROM CMS-AES-CCM-and-AES-GCM + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-aes(32) } + + ; + + -- + -- Message Digest Algorithms: Imported from [PKI-ALG] and [RSAOAEP] + -- + + -- id-sha1 Parameters are preferred absent + -- id-sha224 Parameters are preferred absent + -- id-sha256 Parameters are preferred absent + + + +Turner & Brown Informational [Page 38] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + -- id-sha384 Parameters are preferred absent + -- id-sha512 Parameters are preferred absent + + -- + -- Signature Algorithms: Imported from [PKI-ALG] + -- + + -- ecdsa-with-SHA1 Parameters are NULL + -- ecdsa-with-SHA224 Parameters are absent + -- ecdsa-with-SHA256 Parameters are absent + -- ecdsa-with-SHA384 Parameters are absent + -- ecdsa-with-SHA512 Parameters are absent + + -- ECDSA Signature Value + -- Contents of SignatureValue OCTET STRING + + -- ECDSA-Sig-Value ::= SEQUENCE { + -- r INTEGER, + -- s INTEGER + -- } + + -- + -- Key Agreement Algorithms + -- + + x9-63-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) tc68(133) country(16) x9(840) + x9-63(63) schemes(0) } + secg-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) certicom(132) schemes(1) } + + -- + -- Diffie-Hellman Single Pass, Standard, with KDFs + -- + + -- Parameters are always present and indicate the key wrap algorithm + -- with KeyWrapAlgorithm. + + dhSinglePass-stdDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 2 } + + dhSinglePass-stdDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 0 } + + dhSinglePass-stdDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 1 } + + + + + +Turner & Brown Informational [Page 39] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + dhSinglePass-stdDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 2 } + + dhSinglePass-stdDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 3 } + + -- + -- Diffie-Hellman Single Pass, Cofactor, with KDFs + -- + + dhSinglePass-cofactorDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 3 } + + dhSinglePass-cofactorDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 0 } + + dhSinglePass-cofactorDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 1 } + + dhSinglePass-cofactorDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 2 } + + dhSinglePass-cofactorDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 3 } + + -- + -- MQV Single Pass, Cofactor, with KDFs + -- + + mqvSinglePass-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 16 } + + mqvSinglePass-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 0 } + + mqvSinglePass-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 1 } + + mqvSinglePass-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 2 } + + mqvSinglePass-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 3 } + + -- + -- Key Wrap Algorithms: Imported from [CMS-ALG] and [CMS-AES] + -- + + + + +Turner & Brown Informational [Page 40] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + KeyWrapAlgorithm ::= AlgorithmIdentifier + + -- id-alg-CMS3DESwrap Parameters are NULL + -- id-aes128-wrap Parameters are absent + -- id-aes192-wrap Parameters are absent + -- id-aes256-wrap Parameters are absent + + -- + -- Content Encryption Algorithms: Imported from [CMS-ALG] + -- and [CMS-AES] + -- + + -- des-ede3-cbc Parameters are CBCParameter + -- id-aes128-CBC Parameters are AES-IV + -- id-aes192-CBC Parameters are AES-IV + -- id-aes256-CBC Parameters are AES-IV + -- id-aes128-CCM Parameters are CCMParameters + -- id-aes192-CCM Parameters are CCMParameters + -- id-aes256-CCM Parameters are CCMParameters + -- id-aes128-GCM Parameters are GCMParameters + -- id-aes192-GCM Parameters are GCMParameters + -- id-aes256-GCM Parameters are GCMParameters + + -- + -- Message Authentication Code Algorithms + -- + + -- hMAC-SHA1 Parameters are preferred absent + + -- HMAC with SHA-224, SHA-256, SHA_384, and SHA-512 Parameters are + -- absent + + id-hmacWithSHA224 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 8 } + + id-hmacWithSHA256 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 9 } + + id-hmacWithSHA384 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 10 } + + id-hmacWithSHA512 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 11 } + + + + +Turner & Brown Informational [Page 41] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + -- + -- Originator Public Key Algorithms: Imported from [PKI-ALG] + -- + + -- id-ecPublicKey Parameters are absent, NULL, or ECParameters + + -- Format for both ephemeral and static public keys: Imported from + -- [PKI-ALG] + + -- ECPoint ::= OCTET STRING + + -- ECParameters ::= CHOICE { + -- namedCurve OBJECT IDENTIFIER + -- commented out in [PKI-ALG] implicitCurve NULL + -- commented out in [PKI-ALG] specifiedCurve SpecifiedECDomain + -- commented out in [PKI-ALG] ... + -- } + -- implicitCurve and specifiedCurve MUST NOT be used in PKIX. + -- Details for SpecifiedECDomain can be found in [X9.62]. + -- Any future additions to this CHOICE should be coordinated + -- with ANSI X9. + + -- Format of KeyAgreeRecipientInfo ukm field when used with + -- ECMQV + + MQVuserKeyingMaterial ::= SEQUENCE { + ephemeralPublicKey OriginatorPublicKey, + addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL + } + + -- 'SharedInfo' for input to KDF when using ECDH and ECMQV with + -- EnvelopedData, AuthenticatedData, or AuthEnvelopedData + + ECC-CMS-SharedInfo ::= SEQUENCE { + keyInfo AlgorithmIdentifier, + entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL, + suppPubInfo [2] EXPLICIT OCTET STRING + } + + -- + -- S/MIME Capabilities + -- An identifier followed by type. + -- + + + + + + + + +Turner & Brown Informational [Page 42] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + -- + -- S/MIME Capabilities: Message Digest Algorithms + -- + + -- Found in [CMS-SHA2]. + + -- + -- S/MIME Capabilities: Signature Algorithms + -- + + -- ecdsa-with-SHA1 Type NULL + -- ecdsa-with-SHA224 Type absent + -- ecdsa-with-SHA256 Type absent + -- ecdsa-with-SHA384 Type absent + -- ecdsa-with-SHA512 Type absent + + -- + -- S/MIME Capabilities: ECDH, Single Pass, Standard + -- + + -- dhSinglePass-stdDH-sha1kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-stdDH-sha224kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-stdDH-sha256kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-stdDH-sha384kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-stdDH-sha512kdf Type is the KeyWrapAlgorithm + + + -- + -- S/MIME Capabilities: ECDH, Single Pass, Cofactor + -- + + -- dhSinglePass-cofactorDH-sha1kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-cofactorDH-sha224kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-cofactorDH-sha256kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-cofactorDH-sha384kdf Type is the KeyWrapAlgorithm + -- dhSinglePass-cofactorDH-sha512kdf Type is the KeyWrapAlgorithm + + -- + -- S/MIME Capabilities: ECMQV, Single Pass, Standard + -- + + -- mqvSinglePass-sha1kdf Type is the KeyWrapAlgorithm + -- mqvSinglePass-sha224kdf Type is the KeyWrapAlgorithm + -- mqvSinglePass-sha256kdf Type is the KeyWrapAlgorithm + -- mqvSinglePass-sha384kdf Type is the KeyWrapAlgorithm + -- mqvSinglePass-sha512kdf Type is the KeyWrapAlgorithm + + + + + +Turner & Brown Informational [Page 43] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + -- + -- S/MIME Capabilities: Message Authentication Code Algorithms + -- + + -- hMACSHA1 Type is preferred absent + -- id-hmacWithSHA224 Type is absent + -- if-hmacWithSHA256 Type is absent + -- id-hmacWithSHA384 Type is absent + -- id-hmacWithSHA512 Type is absent + + END + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 44] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +A.2. 2004 ASN.1 Module + +CMSECCAlgs-2009-02 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-ecc-alg-2009-02(46) } + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL + +IMPORTS + +-- From [PKI-ASN] + +mda-sha1, sa-ecdsaWithSHA1, sa-ecdsaWithSHA224, sa-ecdsaWithSHA256, +sa-ecdsaWithSHA384, sa-ecdsaWithSHA512, id-ecPublicKey, +ECDSA-Sig-Value, ECPoint, ECParameters + FROM PKIXAlgs-2009 + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) + id-mod-pkix1-algorithms2008-02(56) } + +-- From [PKI-ASN] + +mda-sha224, mda-sha256, mda-sha384, mda-sha512 + FROM PKIX1-PSS-OAEP-Algorithms-2009 + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) + id-mod-pkix1-rsa-pkalgs-02(54) } + +-- FROM [CMS-ASN] + +KEY-WRAP, SIGNATURE-ALGORITHM, DIGEST-ALGORITHM, ALGORITHM, +PUBLIC-KEY, MAC-ALGORITHM, CONTENT-ENCRYPTION, KEY-AGREE, SMIME-CAPS, +AlgorithmIdentifier{} + FROM AlgorithmInformation-2009 + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) + id-mod-algorithmInformation-02(58) } + +-- From [CMS-ASN] + +OriginatorPublicKey, UserKeyingMaterial + FROM CryptographicMessageSyntax-2009 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-2004-02(41) } + + + +Turner & Brown Informational [Page 45] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +-- From [CMS-ASN] + +maca-hMAC-SHA1, cea-3DES-cbc, kwa-3DESWrap, CBCParameter + FROM CryptographicMessageSyntaxAlgorithms-2009 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cmsalg-2001-02(37) } + +-- From [CMS-ASN] + +cea-aes128-cbc, cea-aes192-cbc, cea-aes256-cbc, kwa-aes128-wrap, +kwa-aes192-wrap, kwa-aes256-wrap + FROM CMSAesRsaesOaep-2009 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-aes-02(38) } + +-- From [CMS-ASN] + +cea-aes128-CCM, cea-aes192-CCM, cea-aes256-CCM, cea-aes128-GCM, +cea-aes192-GCM, cea-aes256-GCM + FROM CMS-AES-CCM-and-AES-GCM-2009 + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) id-mod-cms-aes-ccm-gcm-02(44) } + +; + +-- Constrains the SignedData digestAlgorithms field +-- Constrains the SignedData SignerInfo digestAlgorithm field +-- Constrains the AuthenticatedData digestAlgorithm field + +-- Message Digest Algorithms: Imported from [PKI-ASN] + +-- MessageDigestAlgs DIGEST-ALGORITHM ::= { +-- mda-sha1 | +-- mda-sha224 | +-- mda-sha256 | +-- mda-sha384 | +-- mda-sha512, +-- ... +-- } + +-- Constrains the SignedData SignerInfo signatureAlgorithm field + +-- Signature Algorithms: Imported from [PKI-ASN] + +-- SignatureAlgs SIGNATURE-ALGORITHM ::= { +-- sa-ecdsaWithSHA1 | +-- sa-ecdsaWithSHA224 | +-- sa-ecdsaWithSHA256 | + + + +Turner & Brown Informational [Page 46] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +-- sa-ecdsaWithSHA384 | +-- sa-ecdsaWithSHA512, +-- ... +-- } + +-- ECDSA Signature Value: Imported from [PKI-ALG] +-- Contents of SignatureValue OCTET STRING + +-- ECDSA-Sig-Value ::= SEQUENCE { +-- r INTEGER, +-- s INTEGER +-- } + +-- +-- Key Agreement Algorithms +-- + +-- Constrains the EnvelopedData RecipientInfo KeyAgreeRecipientInfo +-- keyEncryption Algorithm field +-- Constrains the AuthenticatedData RecipientInfo +-- KeyAgreeRecipientInfo keyEncryption Algorithm field +-- Constrains the AuthEnvelopedData RecipientInfo +-- KeyAgreeRecipientInfo keyEncryption Algorithm field + +-- DH variants are not used with AuthenticatedData or +-- AuthEnvelopedData + +KeyAgreementAlgs KEY-AGREE ::= { + kaa-dhSinglePass-stdDH-sha1kdf-scheme | + kaa-dhSinglePass-stdDH-sha224kdf-scheme | + kaa-dhSinglePass-stdDH-sha256kdf-scheme | + kaa-dhSinglePass-stdDH-sha384kdf-scheme | + kaa-dhSinglePass-stdDH-sha512kdf-scheme | + kaa-dhSinglePass-cofactorDH-sha1kdf-scheme | + kaa-dhSinglePass-cofactorDH-sha224kdf-scheme | + kaa-dhSinglePass-cofactorDH-sha256kdf-scheme | + kaa-dhSinglePass-cofactorDH-sha384kdf-scheme | + kaa-dhSinglePass-cofactorDH-sha512kdf-scheme | + kaa-mqvSinglePass-sha1kdf-scheme | + kaa-mqvSinglePass-sha224kdf-scheme | + kaa-mqvSinglePass-sha256kdf-scheme | + kaa-mqvSinglePass-sha384kdf-scheme | + kaa-mqvSinglePass-sha512kdf-scheme, + ... +} + + + + + + +Turner & Brown Informational [Page 47] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +x9-63-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) tc68(133) country(16) x9(840) + x9-63(63) schemes(0) } + +secg-scheme OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) certicom(132) schemes(1) } + +-- +-- Diffie-Hellman Single Pass, Standard, with KDFs +-- + +-- Parameters are always present and indicate the Key Wrap Algorithm + +kaa-dhSinglePass-stdDH-sha1kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-stdDH-sha1kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-stdDH-sha1kdf-scheme +} + +dhSinglePass-stdDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 2 } + +kaa-dhSinglePass-stdDH-sha224kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-stdDH-sha224kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-stdDH-sha224kdf-scheme +} + +dhSinglePass-stdDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 0 } + +kaa-dhSinglePass-stdDH-sha256kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-stdDH-sha256kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-stdDH-sha256kdf-scheme +} + +dhSinglePass-stdDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 1 } + + + + + + + + + +Turner & Brown Informational [Page 48] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +kaa-dhSinglePass-stdDH-sha384kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-stdDH-sha384kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-stdDH-sha384kdf-scheme +} + +dhSinglePass-stdDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 2 } + +kaa-dhSinglePass-stdDH-sha512kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-stdDH-sha512kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-stdDH-sha512kdf-scheme +} + +dhSinglePass-stdDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 11 3 } + +-- +-- Diffie-Hellman Single Pass, Cofactor, with KDFs +-- + +kaa-dhSinglePass-cofactorDH-sha1kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-cofactorDH-sha1kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-cofactorDH-sha1kdf-scheme +} + +dhSinglePass-cofactorDH-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 3 } + +kaa-dhSinglePass-cofactorDH-sha224kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-cofactorDH-sha224kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-cofactorDH-sha224kdf-scheme +} + +dhSinglePass-cofactorDH-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 0 } + + + + + + + + +Turner & Brown Informational [Page 49] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +kaa-dhSinglePass-cofactorDH-sha256kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-cofactorDH-sha256kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-cofactorDH-sha256kdf-scheme +} + +dhSinglePass-cofactorDH-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 1 } + +kaa-dhSinglePass-cofactorDH-sha384kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-cofactorDH-sha384kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-cofactorDH-sha384kdf-scheme +} + +dhSinglePass-cofactorDH-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 2 } + +kaa-dhSinglePass-cofactorDH-sha512kdf-scheme KEY-AGREE ::= { + IDENTIFIER dhSinglePass-cofactorDH-sha512kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-dhSinglePass-cofactorDH-sha512kdf-scheme +} + +dhSinglePass-cofactorDH-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 14 3 } + +-- +-- MQV Single Pass, Cofactor, with KDFs +-- + +kaa-mqvSinglePass-sha1kdf-scheme KEY-AGREE ::= { + IDENTIFIER mqvSinglePass-sha1kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-mqvSinglePass-sha1kdf-scheme +} + +mqvSinglePass-sha1kdf-scheme OBJECT IDENTIFIER ::= { + x9-63-scheme 16 } + + + + + + + + +Turner & Brown Informational [Page 50] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +kaa-mqvSinglePass-sha224kdf-scheme KEY-AGREE ::= { + IDENTIFIER mqvSinglePass-sha224kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-mqvSinglePass-sha224kdf-scheme +} + +mqvSinglePass-sha224kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 0 } + +kaa-mqvSinglePass-sha256kdf-scheme KEY-AGREE ::= { + IDENTIFIER mqvSinglePass-sha256kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-mqvSinglePass-sha256kdf-scheme +} + +mqvSinglePass-sha256kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 1 } + +kaa-mqvSinglePass-sha384kdf-scheme KEY-AGREE ::= { + IDENTIFIER mqvSinglePass-sha384kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-mqvSinglePass-sha384kdf-scheme +} + +mqvSinglePass-sha384kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 2 } + +kaa-mqvSinglePass-sha512kdf-scheme KEY-AGREE ::= { + IDENTIFIER mqvSinglePass-sha512kdf-scheme + PARAMS TYPE KeyWrapAlgorithm ARE required + UKM -- TYPE unencoded data -- ARE preferredPresent + SMIME-CAPS cap-kaa-mqvSinglePass-sha512kdf-scheme +} + +mqvSinglePass-sha512kdf-scheme OBJECT IDENTIFIER ::= { + secg-scheme 15 3 } + +-- +-- Key Wrap Algorithms: Imported from [CMS-ASN] +-- + + + + + + + + +Turner & Brown Informational [Page 51] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +KeyWrapAlgorithm ::= AlgorithmIdentifier { KEY-WRAP, { KeyWrapAlgs } } + +KeyWrapAlgs KEY-WRAP ::= { + kwa-3DESWrap | + kwa-aes128-wrap | + kwa-aes192-wrap | + kwa-aes256-wrap, + ... +} + +-- +-- Content Encryption Algorithms: Imported from [CMS-ASN] +-- + +-- Constrains the EnvelopedData EncryptedContentInfo encryptedContent +-- field and the AuthEnvelopedData EncryptedContentInfo +-- contentEncryptionAlgorithm field + +-- ContentEncryptionAlgs CONTENT-ENCRYPTION ::= { +-- cea-3DES-cbc | +-- cea-aes128-cbc | +-- cea-aes192-cbc | +-- cea-aes256-cbc | +-- cea-aes128-ccm | +-- cea-aes192-ccm | +-- cea-aes256-ccm | +-- cea-aes128-gcm | +-- cea-aes192-gcm | +-- cea-aes256-gcm, +-- ... +-- } + +-- des-ede3-cbc and aes*-cbc are used with EnvelopedData and +-- EncryptedData +-- aes*-ccm are used with AuthEnvelopedData +-- aes*-gcm are used with AuthEnvelopedData +-- (where * is 128, 192, and 256) + +-- +-- Message Authentication Code Algorithms +-- + +-- Constrains the AuthenticatedData +-- MessageAuthenticationCodeAlgorithm field +-- + + + + + + +Turner & Brown Informational [Page 52] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +MessageAuthAlgs MAC-ALGORITHM ::= { +-- maca-hMAC-SHA1 | + maca-hMAC-SHA224 | + maca-hMAC-SHA256 | + maca-hMAC-SHA384 | + maca-hMAC-SHA512, + ... +} + +maca-hMAC-SHA224 MAC-ALGORITHM ::= { + IDENTIFIER id-hmacWithSHA224 + PARAMS ARE absent + IS-KEYED-MAC TRUE + SMIME-CAPS cap-hMAC-SHA224 +} + +id-hmacWithSHA224 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 8 } + +maca-hMAC-SHA256 MAC-ALGORITHM ::= { + IDENTIFIER id-hmacWithSHA256 + PARAMS ARE absent + IS-KEYED-MAC TRUE + SMIME-CAPS cap-hMAC-SHA256 +} + +id-hmacWithSHA256 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 9 } + +maca-hMAC-SHA384 MAC-ALGORITHM ::= { + IDENTIFIER id-hmacWithSHA384 + PARAMS ARE absent + IS-KEYED-MAC TRUE + SMIME-CAPS cap-hMAC-SHA384 +} + +id-hmacWithSHA384 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 10 } + +maca-hMAC-SHA512 MAC-ALGORITHM ::= { + IDENTIFIER id-hmacWithSHA512 + PARAMS ARE absent + IS-KEYED-MAC TRUE + SMIME-CAPS cap-hMAC-SHA512 +} + + + +Turner & Brown Informational [Page 53] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +id-hmacWithSHA512 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) + digestAlgorithm(2) 11 } + +-- +-- Originator Public Key Algorithms +-- + +-- Constraints on KeyAgreeRecipientInfo OriginatorIdentifierOrKey +-- OriginatorPublicKey algorithm field + +OriginatorPKAlgorithms PUBLIC-KEY ::= { + opka-ec, + ... +} + +opka-ec PUBLIC-KEY ::={ + IDENTIFIER id-ecPublicKey + KEY ECPoint + PARAMS TYPE CHOICE { n NULL, p ECParameters } ARE preferredAbsent +} + +-- Format for both ephemeral and static public keys: Imported from +-- [PKI-ALG] + +-- ECPoint ::= OCTET STRING + +-- ECParameters ::= CHOICE { +-- namedCurve CURVE.&id({NamedCurve}) +-- commented out in [PKI-ALG] implicitCurve NULL +-- commented out in [PKI-ALG] specifiedCurve SpecifiedECDomain +-- commented out in [PKI-ALG] ... +-- } + -- implicitCurve and specifiedCurve MUST NOT be used in PKIX. + -- Details for SpecifiedECDomain can be found in [X9.62]. + -- Any future additions to this CHOICE should be coordinated + -- with ANSI X.9. + +-- Format of KeyAgreeRecipientInfo ukm field when used with +-- ECMQV + +MQVuserKeyingMaterial ::= SEQUENCE { + ephemeralPublicKey OriginatorPublicKey, + addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL +} + + + + + + +Turner & Brown Informational [Page 54] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +-- 'SharedInfo' for input to KDF when using ECDH and ECMQV with +-- EnvelopedData, AuthenticatedData, or AuthEnvelopedData + +ECC-CMS-SharedInfo ::= SEQUENCE { + keyInfo KeyWrapAlgorithm, + entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL, + suppPubInfo [2] EXPLICIT OCTET STRING +} + +-- +-- S/MIME CAPS for algorithms in this document +-- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 55] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +SMimeCAPS SMIME-CAPS ::= { +-- mda-sha1.&smimeCaps | +-- mda-sha224.&smimeCaps | +-- mda-sha256.&smimeCaps | +-- mda-sha384.&smimeCaps | +-- mda-sha512.&smimeCaps | +-- sa-ecdsaWithSHA1.&smimeCaps | +-- sa-ecdsaWithSHA224.&smimeCaps | +-- sa-ecdsaWithSHA256.&smimeCaps | +-- sa-ecdsaWithSHA384.&smimeCaps | +-- sa-ecdsaWithSHA512.&smimeCaps | + kaa-dhSinglePass-stdDH-sha1kdf-scheme.&smimeCaps | + kaa-dhSinglePass-stdDH-sha224kdf-scheme.&smimeCaps | + kaa-dhSinglePass-stdDH-sha256kdf-scheme.&smimeCaps | + kaa-dhSinglePass-stdDH-sha384kdf-scheme.&smimeCaps | + kaa-dhSinglePass-stdDH-sha512kdf-scheme.&smimeCaps | + kaa-dhSinglePass-cofactorDH-sha1kdf-scheme.&smimeCaps | + kaa-dhSinglePass-cofactorDH-sha224kdf-scheme.&smimeCaps | + kaa-dhSinglePass-cofactorDH-sha256kdf-scheme.&smimeCaps | + kaa-dhSinglePass-cofactorDH-sha384kdf-scheme.&smimeCaps | + kaa-dhSinglePass-cofactorDH-sha512kdf-scheme.&smimeCaps | + kaa-mqvSinglePass-sha1kdf-scheme.&smimeCaps | + kaa-mqvSinglePass-sha224kdf-scheme.&smimeCaps | + kaa-mqvSinglePass-sha256kdf-scheme.&smimeCaps | + kaa-mqvSinglePass-sha384kdf-scheme.&smimeCaps | + kaa-mqvSinglePass-sha512kdf-scheme.&smimeCaps | +-- kwa-3des.&smimeCaps | +-- kwa-aes128.&smimeCaps | +-- kwa-aes192.&smimeCaps | +-- kwa-aes256.&smimeCaps | +-- cea-3DES-cbc.&smimeCaps | +-- cea-aes128-cbc.&smimeCaps | +-- cea-aes192-cbc.&smimeCaps | +-- cea-aes256-cbc.&smimeCaps | +-- cea-aes128-ccm.&smimeCaps | +-- cea-aes192-ccm.&smimeCaps | +-- cea-aes256-ccm.&smimeCaps | +-- cea-aes128-gcm.&smimeCaps | +-- cea-aes192-gcm.&smimeCaps | +-- cea-aes256-gcm.&smimeCaps | +-- maca-hMAC-SHA1.&smimeCaps | + maca-hMAC-SHA224.&smimeCaps | + maca-hMAC-SHA256.&smimeCaps | + maca-hMAC-SHA384.&smimeCaps | + maca-hMAC-SHA512.&smimeCaps, + ... +} + + + + +Turner & Brown Informational [Page 56] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +cap-kaa-dhSinglePass-stdDH-sha1kdf-scheme SMIME-CAPS ::= { + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-stdDH-sha1kdf-scheme +} + +cap-kaa-dhSinglePass-stdDH-sha224kdf-scheme SMIME-CAPS ::= { + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-stdDH-sha224kdf-scheme +} + +cap-kaa-dhSinglePass-stdDH-sha256kdf-scheme SMIME-CAPS ::= { + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-stdDH-sha256kdf-scheme +} + +cap-kaa-dhSinglePass-stdDH-sha384kdf-scheme SMIME-CAPS ::= { + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-stdDH-sha384kdf-scheme +} + +cap-kaa-dhSinglePass-stdDH-sha512kdf-scheme SMIME-CAPS ::= { + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-stdDH-sha512kdf-scheme +} + +cap-kaa-dhSinglePass-cofactorDH-sha1kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-cofactorDH-sha1kdf-scheme +} + +cap-kaa-dhSinglePass-cofactorDH-sha224kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-cofactorDH-sha224kdf-scheme +} + +cap-kaa-dhSinglePass-cofactorDH-sha256kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-cofactorDH-sha256kdf-scheme +} + +cap-kaa-dhSinglePass-cofactorDH-sha384kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-cofactorDH-sha384kdf-scheme +} + + + + + + + +Turner & Brown Informational [Page 57] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +cap-kaa-dhSinglePass-cofactorDH-sha512kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY dhSinglePass-cofactorDH-sha512kdf-scheme +} + +cap-kaa-mqvSinglePass-sha1kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY mqvSinglePass-sha1kdf-scheme +} + +cap-kaa-mqvSinglePass-sha224kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY mqvSinglePass-sha224kdf-scheme +} + +cap-kaa-mqvSinglePass-sha256kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY mqvSinglePass-sha256kdf-scheme +} + +cap-kaa-mqvSinglePass-sha384kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY mqvSinglePass-sha384kdf-scheme +} + +cap-kaa-mqvSinglePass-sha512kdf-scheme SMIME-CAPS ::={ + TYPE KeyWrapAlgorithm + IDENTIFIED BY mqvSinglePass-sha512kdf-scheme +} + +cap-hMAC-SHA224 SMIME-CAPS ::={ IDENTIFIED BY id-hmacWithSHA224 } + +cap-hMAC-SHA256 SMIME-CAPS ::={ IDENTIFIED BY id-hmacWithSHA256 } + +cap-hMAC-SHA384 SMIME-CAPS ::={ IDENTIFIED BY id-hmacWithSHA384 } + +cap-hMAC-SHA512 SMIME-CAPS ::={ IDENTIFIED BY id-hmacWithSHA512 } + +END + + + + + + + + + + + + +Turner & Brown Informational [Page 58] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +Appendix B. Changes since RFC 3278 + + The following summarizes the changes: + + - Abstract: The basis of the document was changed to refer to NIST + FIPS 186-3 and SP800-56A. However, to maintain backwards + compatibility the Key Derivation Function from ANSI/SEC1 is + retained. + + - Section 1: A bullet was added to address AuthEnvelopedData. + + - Section 2.1: A sentence was added to indicate FIPS180-3 is used + with ECDSA. Replaced reference to ANSI X9.62 with FIPS186-3. + + - Section 2.1.1: The permitted digest algorithms were expanded from + SHA-1 to SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512. + + - Section 2.1.2 and 2.1.3: The bullet addressing integer "e" was + deleted. + + - Section 3: Added explanation of why static-static ECDH is not + included. + + - Section 3.1: The reference for DH was changed from RFC 3852 to RFC + 3370. Provided text to indicate fields of EnvelopedData are as in + CMS. + + - Section 3.1.1: The text was updated to include description of all + KeyAgreeRecipientInfo fields. Parameters for id-ecPublicKey field + changed from NULL to absent or ECParameter. Additional information + about ukm was added. + + - Section 3.2: The sentence describing the advantages of 1-Pass ECMQV + was rewritten. + + - Section 3.2.1: The text was updated to include description of all + fields. Parameters for id-ecPublicKey field changed from NULL to + absent or ECParameters. + + - Sections 3.2.2 and 4.1.2: The re-use of ephemeral keys paragraph + was reworded. + + - Section 4.1: The sentences describing the advantages of 1-Pass + ECMQV was moved to Section 4. + + - Section 4.1.2: The note about the attack was moved to Section 4. + + + + + +Turner & Brown Informational [Page 59] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + + - Section 4.2: This section was added to address AuthEnvelopedData + with ECMQV. + + - Section 5: This section was moved to Section 8. The 1st paragraph + was modified to recommend both SignedData and EnvelopedData. The + requirements were updated for hash algorithms and recommendations + for matching curves and hash algorithms. Also, the requirements + were expanded to indicate which ECDH and ECMQV variants, key wrap + algorithms, and content encryption algorithms are required for each + of the content types used in this document. The permitted digest + algorithms used in KDFs were expanded from SHA-1 to SHA-1, SHA-224, + SHA-256, SHA-384, and SHA-512. + + - Section 6 (formerly 7): This section was updated to allow for + SMIMECapabilities to be present in certificates. The S/MIME + capabilities for ECDSA with SHA-224, SHA-256, SHA-384, and SHA-512 + were added to the list of S/MIME Capabilities. Also, updated to + include S/MIME capabilities for ECDH and ECMQV using the SHA-224, + SHA-256, SHA-384, and SHA-512 algorithms as the KDF. + + - Section 7.1 (formerly 8.1): Added sub-sections for digest, + signature, originator public key, key agreement, content + encryption, key wrap, and message authentication code algorithms. + Pointed to algorithms and parameters in appropriate documents for: + SHA-224, SHA-256, SHA-384, and SHA-512 as well as SHA-224, SHA-256, + SHA-384, and SHA-512 with ECDSA. Also, added algorithm identifiers + for ECDH std, ECDH cofactor, and ECMQV with SHA-224, SHA-256, + SHA-384, and SHA-512 algorithms as the KDF. Changed id-ecPublicKey + parameters to be absent, NULL, or ECParameters, and if present the + originator's ECParameters must match the recipient's ECParameters. + + - Section 7.2 (formerly 8.2): Updated to include AuthEnvelopedData. + Also, added text to address support requirement for compressed, + uncompressed, and hybrid keys; changed pointers from ANSI X9.61 to + PKIX (where ECDSA-Sig-Value is imported); changed pointers from + SECG to NIST specs; and updated example of suppPubInfo to be + AES-256. keyInfo's parameters changed from NULL to any associated + parameters (AES wraps have absent parameters). + + - Section 9: Replaced text, which was a summary paragraph, with an + updated security considerations section. Paragraph referring to + definitions of SHA-224, SHA-256, SHA-384, and SHA-512 is deleted. + + - Updated references. + + - Added ASN.1 modules. + + - Updated acknowledgements section. + + + +Turner & Brown Informational [Page 60] + +RFC 5753 Use of ECC Algorithms in CMS January 2010 + + +Acknowledgements + + The methods described in this document are based on work done by the + ANSI X9F1 working group. The authors wish to extend their thanks to + ANSI X9F1 for their assistance. The authors also wish to thank Peter + de Rooij for his patient assistance. The technical comments of + Francois Rousseau were valuable contributions. + + Many thanks go out to the other authors of RFC 3278: Simon Blake- + Wilson and Paul Lambert. Without RFC 3278, this version wouldn't + exist. + + The authors also wish to thank Alfred Hoenes, Jonathan Herzog, Paul + Hoffman, Russ Housley, and Jim Schaad for their valuable input. + +Authors' Addresses + + Sean Turner + IECA, Inc. + 3057 Nutley Street, Suite 106 + Fairfax, VA 22031 + USA + + EMail: turners@ieca.com + + + Daniel R. L. Brown + Certicom Corp + 5520 Explorer Drive #400 + Mississauga, ON L4W 5L1 + Canada + + EMail: dbrown@certicom.com + + + + + + + + + + + + + + + + + + +Turner & Brown Informational [Page 61] + diff --git a/docs/rfc/rfc5754.txt b/docs/rfc/rfc5754.txt new file mode 100644 index 00000000..58c03337 --- /dev/null +++ b/docs/rfc/rfc5754.txt @@ -0,0 +1,563 @@ + + + + + + +Internet Engineering Task Force (IETF) S. Turner +Request for Comments: 5754 IECA +Updates: 3370 January 2010 +Category: Standards Track +ISSN: 2070-1721 + + + Using SHA2 Algorithms with Cryptographic Message Syntax + +Abstract + + This document describes the conventions for using the Secure Hash + Algorithm (SHA) message digest algorithms (SHA-224, SHA-256, SHA-384, + SHA-512) with the Cryptographic Message Syntax (CMS). It also + describes the conventions for using these algorithms with the CMS and + the Digital Signature Algorithm (DSA), Rivest Shamir Adleman (RSA), + and Elliptic Curve DSA (ECDSA) signature algorithms. Further, it + provides SMIMECapabilities attribute values for each algorithm. + +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 5741. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + http://www.rfc-editor.org/info/rfc5754. + +Copyright Notice + + Copyright (c) 2010 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) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + + + +Turner Standards Track [Page 1] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + This document may contain material from IETF Documents or IETF + Contributions published or made publicly available before November + 10, 2008. The person(s) controlling the copyright in some of this + material may not have granted the IETF Trust the right to allow + modifications of such material outside the IETF Standards Process. + Without obtaining an adequate license from the person(s) controlling + the copyright in such materials, this document may not be modified + outside the IETF Standards Process, and derivative works of it may + not be created outside the IETF Standards Process, except to format + it for publication as an RFC or to translate it into languages other + than English. + +Table of Contents + + 1. Introduction ....................................................2 + 1.1. Conventions Used in This Document ..........................3 + 2. Message Digest Algorithms .......................................3 + 2.1. SHA-224 ....................................................4 + 2.2. SHA-256 ....................................................5 + 2.3. SHA-384 ....................................................5 + 2.4. SHA-512 ....................................................5 + 3. Signature Algorithms ............................................6 + 3.1. DSA ........................................................6 + 3.2. RSA ........................................................7 + 3.3. ECDSA ......................................................8 + 4. Security Considerations .........................................9 + 5. References ......................................................9 + 5.1. Normative References .......................................9 + 5.2. Informative References ....................................10 + +1. Introduction + + This document specifies the algorithm identifiers and specifies + parameters for the message digest algorithms SHA-224, SHA-256, + SHA-384, and SHA-512 for use with the Cryptographic Message Syntax + (CMS) [RFC5652]. The message digest algorithms are defined in [SHS] + and reference code is provided in [RFC4634]. + + This document also specifies the algorithm identifiers and parameters + for use of SHA-224, SHA-256, SHA-384, and SHA-512 with DSA [DSS], RSA + (RSASSA-PKCS1-v1_5) [RFC3447], and ECDSA [DSS]. + + This document does not define new identifiers; they are taken from + [RFC3874], [RFC4055], and [RFC5758]. Additionally, the parameters + follow the conventions specified therein. Therefore, there is no + Abstract Syntax Notation One (ASN.1) module included in this + document. + + + + +Turner Standards Track [Page 2] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + Note that [RFC4231] specifies the conventions for the message + authentication code (MAC) algorithms: Hashed MAC (HMAC) with SHA-224, + HMAC with SHA-256, HMAC with SHA-384, and HMAC with SHA-512. + + In the CMS, the various algorithm identifiers use the + AlgorithmIdentifier syntax, which is included here for convenience: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + + This document also specifies the SMIMECapabilities attribute values + [RFC5751] for each algorithm. The values provided are for the + SMIMECapability field, which is included here for convenience: + + SMIMECapability ::= SEQUENCE { + capabilityID OBJECT IDENTIFIER, + parameters ANY DEFINED BY capabilityID OPTIONAL } + +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]. + +2. Message Digest Algorithms + + Digest algorithm identifiers are located in the SignedData + digestAlgorithms field, the SignerInfo digestAlgorithm field, the + DigestedData digestAlgorithm field, and the AuthenticatedData + digestAlgorithm field. The object identifiers are taken from + [RFC4055]. + + Digest values are located in the DigestedData digest field and the + Message Digest authenticated attribute. In addition, digest values + are input to signature algorithms. + + The digest algorithm identifiers use the AlgorithmIdentifier syntax + elaborated upon in Section 1. + + The algorithm field and SMIMECapabilities attribute are discussed in + Sections 2.1-2.4 for each message digest algorithm. Section 3 + provides some signatures that use SHA2 algorithms. Consult the + signature algorithm definitions for the procedures to compute the + digest values (i.e., DigestInfo). + + + + + + +Turner Standards Track [Page 3] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + The AlgorithmIdentifier parameters field is OPTIONAL. + Implementations MUST accept SHA2 AlgorithmIdentifiers with absent + parameters. Implementations MUST accept SHA2 AlgorithmIdentifiers + with NULL parameters. Implementations MUST generate SHA2 + AlgorithmIdentifiers with absent parameters. + + NOTE: There are two possible encodings for the AlgorithmIdentifier + parameters field associated with these object identifiers. The two + alternatives arise from the loss of the OPTIONAL associated with the + algorithm identifier parameters when the 1988 syntax for + AlgorithmIdentifier was translated into the 1997 syntax. Later, the + OPTIONAL was recovered via a defect report, but by then many people + thought that algorithm parameters were mandatory. Because of this + history, some implementations encode parameters as a NULL element + while others omit them entirely. The correct encoding is to omit the + parameters field; however, when some uses of these algorithms were + defined, it was done using the NULL parameters rather than absent + parameters. For example, PKCS#1 [RFC3447] requires that the padding + used for RSA signatures (EMSA-PKCS1-v1_5) MUST use SHA2 + AlgorithmIdentifiers with NULL parameters (to clarify, the + requirement "MUST generate SHA2 AlgorithmIdentifiers with absent + parameters" in the previous paragraph does not apply to this + padding). + +2.1. SHA-224 + + The SHA-224 message digest algorithm is defined in [SHS]. The + algorithm identifier for SHA-224 is: + + id-sha224 OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + csor(3) nistalgorithm(4) hashalgs(2) 4 } + + The parameters are as specified in the beginning of Section 2. + + The SMIMECapabilities attribute value indicates support for SHA-224 + in a SEQUENCE with the capabilityID field containing the object + identifier id-sha224 with absent parameters. The DER encoding for + this SMIMECapability is: + + id-sha224: 30 0b 06 09 60 86 48 01 65 03 04 02 04 + + + + + + + + + + +Turner Standards Track [Page 4] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + +2.2. SHA-256 + + The SHA-256 message digest algorithm is defined in [SHS]. The + algorithm identifier for SHA-256 is: + + id-sha256 OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + csor(3) nistalgorithm(4) hashalgs(2) 1 } + + The parameters are as specified in the beginning of Section 2. + + The SMIMECapabilities attribute value indicates support for SHA-256 + in a SEQUENCE with the capabilityID field containing the object + identifier id-sha256 with absent parameters. The DER encoding for + this SMIMECapability value is: + + id-sha256: 30 0b 06 09 60 86 48 01 65 03 04 02 01 + +2.3. SHA-384 + + The SHA-384 message digest algorithm is defined in [SHS]. The + algorithm identifier for SHA-384 is: + + id-sha384 OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + csor(3) nistalgorithm(4) hashalgs(2) 2 } + + The parameters are as specified in the beginning of Section 2. + + The SMIMECapabilities attribute value indicates support for SHA-384 + in a SEQUENCE with the capabilityID field containing the object + identifier id-sha384 with absent parameters. The DER encoding for + this SMIMECapability value is: + + id-sha384: 30 0b 06 09 60 86 48 01 65 03 04 02 02 + +2.4. SHA-512 + + The SHA-512 message digest algorithm is defined in [SHS]. The + algorithm identifier for SHA-512 is: + + id-sha512 OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + csor(3) nistalgorithm(4) hashalgs(2) 3 } + + The parameters are as specified in the beginning of Section 2. + + + + + +Turner Standards Track [Page 5] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + The SMIMECapabilities attribute value indicates support for SHA-384 + in a SEQUENCE with the capabilityID field containing the object + identifier id-sha384 with absent parameters. The DER encoding for + this SMIMECapability value is: + + id-sha512: 30 0b 06 09 60 86 48 01 65 03 04 02 03 + +3. Signature Algorithms + + This section specifies the conventions employed by CMS + implementations that support DSA, RSA, and ECDSA with SHA2 + algorithms. + + Signature algorithm identifiers are located in the SignerInfo + signatureAlgorithm field of SignedData. Also, signature algorithm + identifiers are located in the SignerInfo signatureAlgorithm field of + countersignature attributes. + + Signature values are located in the SignerInfo signature field of + SignedData. Also, signature values are located in the SignerInfo + signature field of countersignature attributes. + +3.1. DSA + + [RFC3370], Section 3.1, specifies the conventions for DSA with SHA-1 + public key algorithm identifiers, parameters, public keys, and + signature values. DSA with SHA2 algorithms uses the same conventions + for these public key algorithm identifiers, parameters, public keys, + and signature values. DSA MAY be used with SHA-224 and SHA-256. The + object identifiers are taken from [RFC5758]. + + DSA has not been specified with SHA-384 and SHA-512. SHA-384 and + SHA-512 are not supported because the maximum bit length of p + (specified as L) is 3072 for DSA. For consistent cryptographic + strength, SHA-384 would be used with DSA where L is 7680, and SHA-512 + would be used with DSA where L is 15360. + + The algorithm identifier for DSA with SHA-224 signature values is: + + id-dsa-with-sha224 OBJECT IDENTIFIER ::= { + joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101) + csor(3) algorithms(4) id-dsa-with-sha2(3) 1 } + + The algorithm identifier for DSA with SHA-256 signature values is: + + id-dsa-with-sha256 OBJECT IDENTIFIER ::= { + joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101) + csor(3) algorithms(4) id-dsa-with-sha2(3) 2 } + + + +Turner Standards Track [Page 6] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + When either of these algorithm identifiers is used, the + AlgorithmIdentifier parameters field MUST be absent. + + The SMIMECapabilities attribute value indicates support for one of + the DSA signature algorithms in a SEQUENCE with the capabilityID + field containing the object identifier id-dsa-with-sha* (where * is + 224 or 256) with absent parameters. The DER encodings for these + SMIMECapability values are: + + id-dsa-with-sha224: 30 0b 06 09 60 86 48 01 65 03 04 03 01 + + id-dsa-with-sha256: 30 0b 06 09 60 86 48 01 65 03 04 03 02 + +3.2. RSA + + [RFC3370], Section 3.2, specifies the conventions for RSA with SHA-1 + (RSASSA-PKCS1-v1_5) public key algorithm identifiers, parameters, + public keys, and signature values. RSA with SHA2 algorithms uses the + same conventions for these public key algorithm identifiers, + parameters, public keys, and signature values. RSA + (RSASSA-PKCS1-v1_5) [RFC3447] MAY be used with SHA-224, SHA-256, + SHA-384, or SHA-512. The object identifiers are taken from + [RFC4055]. + + The object identifier for RSA with SHA-224 signature values is: + + sha224WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) + member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 14 } + + The object identifier for RSA with SHA-256 signature values is: + + sha256WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) + member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 11 } + + The object identifier for RSA with SHA-384 signature values is: + + sha384WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) + member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 12 } + + The object identifier for RSA with SHA-512 signature values is: + + sha512WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) + member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 13 } + + + + + + + + +Turner Standards Track [Page 7] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + When any of these four object identifiers appears within an + AlgorithmIdentifier, the parameters MUST be NULL. Implementations + MUST accept the parameters being absent as well as present. + + The SMIMECapabilities attribute value indicates support for one of + the DSA signature algorithms in a SEQUENCE with the capabilityID + field containing the object identifier sha*WithRSAEncryption (where * + is 224, 256, 384, or 512) with NULL parameters. The DER encodings + for these SMIMECapability values are: + + sha224WithRSAEncryption: 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0e + 05 00 + + sha256WithRSAEncryption: 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b + 05 00 + + sha384WithRSAEncryption: 30 0d 06 09 2a 86 48 86 f7 0d 01 01 Oc + 05 00 + + sha512WithRSAEncryption: 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0d + 05 00 + +3.3. ECDSA + + [RFC5753], Section 2.1, specifies the conventions for ECDSA with + SHA-* (where * is 1, 224, 256, 384, or 512) public key algorithm + identifiers, parameters, public keys, and signature values. The + object identifiers, which are included below for convenience, are + taken from [RFC5758]. + + The algorithm identifier for ECDSA with SHA-224 signature values is: + + ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 } + + The algorithm identifier for ECDSA with SHA-256 signature values is: + + ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840)ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } + + The algorithm identifier for ECDSA with SHA-384 signature values is: + + ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 } + + + + + + + +Turner Standards Track [Page 8] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + The algorithm identifier for ECDSA with SHA-512 signature values is: + + ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 } + + When any of these four object identifiers appears within an + AlgorithmIdentifier, the parameters field MUST be absent. That is, + the AlgorithmIdentifier SHALL be a SEQUENCE of one component: the OID + ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or ecdsa- + with-SHA512. + + The SMIMECapabilities attribute value indicates support for one of + the ECDSA signature algorithms in a SEQUENCE with the capabilityID + field containing the object identifier ecdsa-with-SHA1* (where * is + 224, 256, 384, or 512) with absent parameters. The DER encodings for + these SMIMECapability values are: + + ecdsa-with-SHA224: 30 0a 06 08 2a 86 48 ce 3d 04 03 01 + + ecdsa-with-SHA256: 30 0a 06 08 2a 86 48 ce 3d 04 03 02 + + ecdsa-with-SHA384: 30 0a 06 08 2a 86 48 ce 3d 04 03 03 + + ecdsa-with-SHA512: 30 0a 06 08 2a 86 48 ce 3d 04 03 04 + +4. Security Considerations + + The security considerations in [RFC3370], [RFC3874], [RFC4055], + [RFC5753], and [RFC5758] apply. No new security considerations are + introduced as a result of this specification. + +5. References + +5.1. Normative References + + [DSS] National Institute of Standards and Technology (NIST), + FIPS Publication 186-3: Digital Signature Standard, June + 2009. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC3370] Housley, R., "Cryptographic Message Syntax (CMS) + Algorithms", RFC 3370, August 2002. + + [RFC3447] Jonsson, J. and B. Kaliski, "Public-Key Cryptography + Standards (PKCS) #1: RSA Cryptography Specifications + Version 2.1", RFC 3447, February 2003. + + + +Turner Standards Track [Page 9] + +RFC 5754 Using SHA2 Algorithms with CMS January 2010 + + + [RFC3874] Housley, R., "A 224-bit One-way Hash Function: SHA-224", + RFC 3874, September 2004. + + [RFC4055] Schaad, J., Kaliski, B., and R. Housley, "Additional + Algorithms and Identifiers for RSA Cryptography for use + in the Internet X.509 Public Key Infrastructure + Certificate and Certificate Revocation List (CRL) + Profile", RFC 4055, June 2005. + + [RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)", RFC + 5652, September 2009. + + [RFC5751] Ramsdell, B. and S. Turner, "Secure/Multipurpose Internet + Mail Extensions (S/MIME) Version 3.2 Message + Specification", RFC 5751, January 2010. + + [RFC5753] Turner, S. and D. Brown, "Use of Elliptic Curve + Cryptography (ECC) Algorithms in Cryptographic Message + Syntax (CMS)", RFC 5753, January 2010. + + [RFC5758] Dang, Q., Santesson, S., Moriarty, K., Brown, D., and T. + Polk, "Internet X.509 Public Key Infrastructure: + Additional Algorithms and Identifiers for DSA and ECDSA", + RFC 5758, January 2010. + + [SHS] National Institute of Standards and Technology (NIST), + FIPS Publication 180-3: Secure Hash Standard, October + 2008. + +5.2. Informative References + + [RFC4231] Nystrom, M., "Identifiers and Test Vectors for HMAC- + SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512", + RFC 4231, December 2005. + + [RFC4634] Eastlake 3rd, D. and T. Hansen, "US Secure Hash + Algorithms (SHA and HMAC-SHA)", RFC 4634, July 2006. + +Author's Address + + Sean Turner + IECA, Inc. + 3057 Nutley Street, Suite 106 + Fairfax, VA 22031 + USA + + EMail: turners@ieca.com + + + + +Turner Standards Track [Page 10] + diff --git a/docs/rfc/rfc5756.txt b/docs/rfc/rfc5756.txt index 119d68fb..27ca737e 100644 --- a/docs/rfc/rfc5756.txt +++ b/docs/rfc/rfc5756.txt @@ -1,3 +1,9 @@ + + + + + + Internet Engineering Task Force (IETF) S. Turner Request for Comments: 5756 IECA Updates: 4055 D. Brown @@ -330,3 +336,4 @@ Authors' Addresses Turner, et al. Standards Track [Page 6] + diff --git a/docs/rfc/rfc5758.txt b/docs/rfc/rfc5758.txt index cb2c4c1c..55b0b05d 100644 --- a/docs/rfc/rfc5758.txt +++ b/docs/rfc/rfc5758.txt @@ -1,3 +1,9 @@ + + + + + + Internet Engineering Task Force (IETF) Q. Dang Request for Comments: 5758 NIST Updates: 3279 S. Santesson @@ -442,3 +448,4 @@ Authors' Addresses Dang, et al. Standards Track [Page 8] + diff --git a/docs/rfc/rfc6125.txt b/docs/rfc/rfc6125.txt index e7f7afd9..236d5d81 100644 --- a/docs/rfc/rfc6125.txt +++ b/docs/rfc/rfc6125.txt @@ -1,3 +1,9 @@ + + + + + + Internet Engineering Task Force (IETF) P. Saint-Andre Request for Comments: 6125 Cisco Category: Standards Track J. Hodges @@ -3186,3 +3192,4 @@ Authors' Addresses Saint-Andre & Hodges Standards Track [Page 57] + diff --git a/docs/rfc/rfc6818.txt b/docs/rfc/rfc6818.txt index 1d462fb4..22bcc42a 100644 --- a/docs/rfc/rfc6818.txt +++ b/docs/rfc/rfc6818.txt @@ -1,3 +1,9 @@ + + + + + + Internet Engineering Task Force (IETF) P. Yee Request for Comments: 6818 AKAYLA Updates: 5280 January 2013 @@ -442,3 +448,4 @@ Author's Address Yee Standards Track [Page 8] + diff --git a/docs/rfc/rfc6960.txt b/docs/rfc/rfc6960.txt index bbafe932..9faf9b5c 100644 --- a/docs/rfc/rfc6960.txt +++ b/docs/rfc/rfc6960.txt @@ -1,3 +1,9 @@ + + + + + + Internet Engineering Task Force (IETF) S. Santesson Request for Comments: 6960 3xA Security Obsoletes: 2560, 6277 M. Myers @@ -2290,4 +2296,4 @@ Authors' Addresses Santesson, et al. Standards Track [Page 41] - \ No newline at end of file + diff --git a/docs/rfc/rfc8419.txt b/docs/rfc/rfc8419.txt new file mode 100644 index 00000000..bf20a489 --- /dev/null +++ b/docs/rfc/rfc8419.txt @@ -0,0 +1,507 @@ + + + + + + +Internet Engineering Task Force (IETF) R. Housley +Request for Comments: 8419 Vigil Security +Category: Standards Track August 2018 +ISSN: 2070-1721 + + + Use of Edwards-Curve Digital Signature Algorithm (EdDSA) Signatures + in the Cryptographic Message Syntax (CMS) + +Abstract + + This document specifies the conventions for using the Edwards-curve + Digital Signature Algorithm (EdDSA) for curve25519 and curve448 in + the Cryptographic Message Syntax (CMS). For each curve, EdDSA + defines the PureEdDSA and HashEdDSA modes. However, the HashEdDSA + mode is not used with the CMS. In addition, no context string is + used with the CMS. + +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. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc8419. + +Copyright Notice + + Copyright (c) 2018 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, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + + + + +Housley Standards Track [Page 1] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + +Table of Contents + + 1. Introduction ....................................................2 + 1.1. Terminology ................................................2 + 1.2. ASN.1 ......................................................2 + 2. EdDSA Signature Algorithm .......................................3 + 2.1. Algorithm Identifiers ......................................3 + 2.2. EdDSA Algorithm Identifiers ................................3 + 2.3. Message Digest Algorithm Identifiers .......................4 + 2.4. EdDSA Signatures ...........................................4 + 3. Signed-data Conventions .........................................5 + 3.1. Signed-data Conventions with Signed Attributes .............5 + 3.2. Signed-data Conventions without Signed Attributes ..........6 + 4. Implementation Considerations ...................................6 + 5. Security Considerations .........................................6 + 6. IANA Considerations .............................................7 + 7. References ......................................................7 + 7.1. Normative References .......................................7 + 7.2. Informative References .....................................8 + Acknowledgments ....................................................9 + Author's Address ...................................................9 + +1. Introduction + + This document specifies the conventions for using the Edwards-curve + Digital Signature Algorithm (EdDSA) [RFC8032] for curve25519 + [CURVE25519] and curve448 [CURVE448] with the Cryptographic Message + Syntax (CMS) [RFC5652] signed-data content type. For each curve, + [RFC8032] defines the PureEdDSA and HashEdDSA modes; however, the + HashEdDSA mode is not used with the CMS. In addition, no context + string is used with CMS. EdDSA with curve25519 is referred to as + "Ed25519", and EdDSA with curve448 is referred to as "Ed448". The + CMS conventions for PureEdDSA with Ed25519 and Ed448 are described in + this document. + +1.1. Terminology + + 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. + +1.2. ASN.1 + + CMS values are generated using ASN.1 [X680], which uses the Basic + Encoding Rules (BER) and the Distinguished Encoding Rules (DER) + [X690]. + + + +Housley Standards Track [Page 2] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + +2. EdDSA Signature Algorithm + + The Edwards-curve Digital Signature Algorithm (EdDSA) [RFC8032] is a + variant of Schnorr's signature system with (possibly twisted) Edwards + curves. Ed25519 is intended to operate at around the 128-bit + security level; Ed448 is intended to operate at around the 224-bit + security level. + + One of the parameters of the EdDSA algorithm is the "prehash" + function. This may be the identity function, resulting in an + algorithm called "PureEdDSA", or a collision-resistant hash function, + resulting in an algorithm called "HashEdDSA". In most situations, + the CMS SignedData includes signed attributes, including the message + digest of the content. Since HashEdDSA offers no benefit when signed + attributes are present, only PureEdDSA is used with the CMS. + +2.1. Algorithm Identifiers + + Each algorithm is identified by an object identifier, and the + algorithm identifier may contain parameters if needed. + + The ALGORITHM definition is repeated here for convenience: + + ALGORITHM ::= CLASS { + &id OBJECT IDENTIFIER UNIQUE, + &Type OPTIONAL } + WITH SYNTAX { + OID &id [PARMS &Type] } + +2.2. EdDSA Algorithm Identifiers + + The EdDSA signature algorithm is defined in [RFC8032], and the + conventions for encoding the public key are defined in [RFC8410]. + + The id-Ed25519 and id-Ed448 object identifiers are used to identify + EdDSA public keys in certificates. The object identifiers are + specified in [RFC8410], and they are repeated here for convenience: + + sigAlg-Ed25519 ALGORITHM ::= { OID id-Ed25519 } + + sigAlg-Ed448 ALGORITHM ::= { OID id-Ed448 } + + id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } + + id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } + + + + + + +Housley Standards Track [Page 3] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + +2.3. Message Digest Algorithm Identifiers + + When the signer includes signed attributes, a message digest + algorithm is used to compute the message digest on the eContent + value. When signing with Ed25519, the message digest algorithm MUST + be SHA-512 [FIPS180]. Additional information on SHA-512 is available + in [RFC6234]. When signing with Ed448, the message digest algorithm + MUST be SHAKE256 [FIPS202] with a 512-bit output value. + + Signing with Ed25519 uses SHA-512 as part of the signing operation, + and signing with Ed448 uses SHAKE256 as part of the signing + operation. + + For convenience, the object identifiers and parameter syntax for + these algorithms are repeated here: + + hashAlg-SHA-512 ALGORITHM ::= { OID id-sha512 } + + hashAlg-SHAKE256 ALGORITHM ::= { OID id-shake256 } + hashAlg-SHAKE256-LEN ALGORITHM ::= { OID id-shake256-len + PARMS ShakeOutputLen } + + hashalgs OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) + country(16) us(840) organization(1) + gov(101) csor(3) nistalgorithm(4) 2 } + + id-sha512 OBJECT IDENTIFIER ::= { hashAlgs 3 } + + id-shake256 OBJECT IDENTIFIER ::= { hashAlgs 12 } + + id-shake256-len OBJECT IDENTIFIER ::= { hashAlgs 18 } + + ShakeOutputLen ::= INTEGER -- Output length in bits + + When using the id-sha512 or id-shake256 algorithm identifier, the + parameters MUST be absent. + + When using the id-shake256-len algorithm identifier, the parameters + MUST be present, and the parameter MUST contain 512, encoded as a + positive integer value. + +2.4. EdDSA Signatures + + The id-Ed25519 and id-Ed448 object identifiers are also used for + signature values. When used to identify signature algorithms, the + AlgorithmIdentifier parameters field MUST be absent. + + + + + +Housley Standards Track [Page 4] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + + The data to be signed is processed using PureEdDSA, and then a + private key operation generates the signature value. As described in + Section 3.3 of [RFC8032], the signature value is the opaque value + ENC(R) || ENC(S), where || represents concatenation. As described in + Section 5.3 of [RFC5652], the signature value is ASN.1 encoded as an + OCTET STRING and included in the signature field of SignerInfo. + +3. Signed-data Conventions + + The processing depends on whether the signer includes signed + attributes. + + The inclusion of signed attributes is preferred, but the conventions + for signed-data without signed attributes are provided for + completeness. + +3.1. Signed-data Conventions with Signed Attributes + + The SignedData digestAlgorithms field includes the identifiers of the + message digest algorithms used by one or more signer. There MAY be + any number of elements in the collection, including zero. When + signing with Ed25519, the digestAlgorithm SHOULD include id-sha512, + and if present, the algorithm parameters field MUST be absent. When + signing with Ed448, the digestAlgorithm SHOULD include + id-shake256-len, and if present, the algorithm parameters field MUST + also be present, and the parameter MUST contain 512, encoded as a + positive integer value. + + The SignerInfo digestAlgorithm field includes the identifier of the + message digest algorithms used by the signer. When signing with + Ed25519, the digestAlgorithm MUST be id-sha512, and the algorithm + parameters field MUST be absent. When signing with Ed448, the + digestAlgorithm MUST be id-shake256-len, the algorithm parameters + field MUST be present, and the parameter MUST contain 512, encoded as + a positive integer value. + + The SignerInfo signedAttributes MUST include the message-digest + attribute as specified in Section 11.2 of [RFC5652]. When signing + with Ed25519, the message-digest attribute MUST contain the message + digest computed over the eContent value using SHA-512. When signing + with Ed448, the message-digest attribute MUST contain the message + digest computed over the eContent value using SHAKE256 with an output + length of 512 bits. + + The SignerInfo signatureAlgorithm field MUST contain either + id-Ed25519 or id-Ed448, depending on the elliptic curve that was used + by the signer. The algorithm parameters field MUST be absent. + + + + +Housley Standards Track [Page 5] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + + The SignerInfo signature field contains the octet string resulting + from the EdDSA private key signing operation. + +3.2. Signed-data Conventions without Signed Attributes + + The SignedData digestAlgorithms field includes the identifiers of the + message digest algorithms used by one or more signer. There MAY be + any number of elements in the collection, including zero. When + signing with Ed25519, the list of identifiers MAY include id-sha512, + and if present, the algorithm parameters field MUST be absent. When + signing with Ed448, the list of identifiers MAY include id-shake256, + and if present, the algorithm parameters field MUST be absent. + + The SignerInfo digestAlgorithm field includes the identifier of the + message digest algorithms used by the signer. When signing with + Ed25519, the digestAlgorithm MUST be id-sha512, and the algorithm + parameters field MUST be absent. When signing with Ed448, the + digestAlgorithm MUST be id-shake256, and the algorithm parameters + field MUST be absent. + + NOTE: Either id-sha512 or id-shake256 is used as part to the + private key signing operation. However, the private key signing + operation does not take a message digest computed with one of + these algorithms as an input. + + The SignerInfo signatureAlgorithm field MUST contain either + id-Ed25519 or id-Ed448, depending on the elliptic curve that was used + by the signer. The algorithm parameters field MUST be absent. + + The SignerInfo signature field contains the octet string resulting + from the EdDSA private key signing operation. + +4. Implementation Considerations + + The EdDSA specification [RFC8032] includes the following warning. It + deserves highlighting, especially when signed-data is used without + signed attributes and the content to be signed might be quite large: + + PureEdDSA requires two passes over the input. Many existing APIs, + protocols, and environments assume digital signature algorithms + only need one pass over the input and may have API or bandwidth + concerns supporting anything else. + +5. Security Considerations + + Implementations must protect the EdDSA private key. Compromise of + the EdDSA private key may result in the ability to forge signatures. + + + + +Housley Standards Track [Page 6] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + + The generation of EdDSA private key relies on random numbers. The + use of inadequate pseudo-random number generators (PRNGs) to generate + these values can result in little or no security. An attacker may + find it much easier to reproduce the PRNG environment that produced + the keys, searching the resulting small set of possibilities, rather + than brute-force searching the whole key space. The generation of + quality random numbers is difficult. RFC 4086 [RANDOM] offers + important guidance in this area. + + Unlike DSA and Elliptic Curve Digital Signature Algorithm (ECDSA), + EdDSA does not require the generation of a random value for each + signature operation. + + Using the same private key with different algorithms has the + potential to leak extra information about the private key to an + attacker. For this reason, the same private key SHOULD NOT be used + with more than one set of EdDSA parameters, although it appears that + there are no security concerns when using the same private key with + PureEdDSA and HashEdDSA [RFC8032]. + + When computing signatures, the same hash function SHOULD be used for + all operations. This reduces the number of failure points in the + signature process. + +6. IANA Considerations + + This document has no IANA actions. + +7. References + +7.1. Normative References + + [FIPS180] National Institute of Standards and Technology, "Secure + Hash Standard (SHS)", FIPS PUB 180-4, + DOI 10.6028/NIST.FIPS.180-4, August 2015. + + [FIPS202] National Institute of Standards and Technology, "SHA-3 + Standard: Permutation-Based Hash and Extendable-Output + Functions", FIPS PUB 202, DOI 10.6028/NIST.FIPS.202, + August 2015. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + + + + + +Housley Standards Track [Page 7] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + + [RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)", + STD 70, RFC 5652, DOI 10.17487/RFC5652, September 2009, + . + + [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital + Signature Algorithm (EdDSA)", RFC 8032, + DOI 10.17487/RFC8032, January 2017, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + + [RFC8410] Josefsson, S. and J. Schaad, "Algorithm Identifiers for + Ed25519, Ed448, X25519, and X448 for Use in the Internet + X.509 Public Key Infrastructure", RFC 8410, + DOI 10.17487/RFC8410, August 2018, + . + + [X680] ITU-T, "Information technology -- Abstract Syntax + Notation One (ASN.1): Specification of basic notation", + ITU-T Recommendation X.680, ISO/IEC 8824-1, August 2015, + . + + [X690] ITU-T, "Information technology -- ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), Canonical + Encoding Rules (CER) and Distinguished Encoding Rules + (DER)", ITU-T Recommendation X.690, ISO/IEC 8825-1, + August 2015, . + +7.2. Informative References + + [CURVE25519] Bernstein, D., "Curve25519: new Diffie-Hellman speed + records", DOI 10.1007/11745853_14, February 2006, + . + + [CURVE448] Hamburg, M., "Ed448-Goldilocks, a new elliptic curve", + June 2015, . + + [RANDOM] Eastlake 3rd, D., Schiller, J., and S. Crocker, + "Randomness Requirements for Security", BCP 106, + RFC 4086, DOI 10.17487/RFC4086, June 2005, + . + + [RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash + Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, + DOI 10.17487/RFC6234, May 2011, + . + + + +Housley Standards Track [Page 8] + +RFC 8419 Using EdDSA Signatures with CMS August 2018 + + +Acknowledgements + + Many thanks to Jim Schaad, Daniel Migault, and Adam Roach for the + careful review and comments. Thanks to Quynh Dang for coordinating + the object identifiers assignment by NIST. + +Author's Address + + Russ Housley + 918 Spring Knoll Drive + Herndon, VA 20170 + United States of America + + Email: housley@vigilsec.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Housley Standards Track [Page 9] + diff --git a/docs/rfc/rfc9525.txt b/docs/rfc/rfc9525.txt new file mode 100644 index 00000000..7e0d8cf6 --- /dev/null +++ b/docs/rfc/rfc9525.txt @@ -0,0 +1,1440 @@ + + + + +Internet Engineering Task Force (IETF) P. Saint-Andre +Request for Comments: 9525 Independent +Obsoletes: 6125 R. Salz +Category: Standards Track Akamai Technologies +ISSN: 2070-1721 November 2023 + + + Service Identity in TLS + +Abstract + + Many application technologies enable secure communication between two + entities by means of Transport Layer Security (TLS) with Internet + Public Key Infrastructure using X.509 (PKIX) certificates. This + document specifies procedures for representing and verifying the + identity of application services in such interactions. + + This document obsoletes RFC 6125. + +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. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc9525. + +Copyright Notice + + Copyright (c) 2023 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, as 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 are provided without warranty as described + in the Revised BSD License. + +Table of Contents + + 1. Introduction + 1.1. Motivation + 1.2. Applicability + 1.3. Overview of Recommendations + 1.4. Scope + 1.4.1. In Scope + 1.4.2. Out of Scope + 1.5. Terminology + 2. Identifying Application Services + 3. Designing Application Protocols + 4. Representing Server Identity + 4.1. Rules + 4.2. Examples + 5. Requesting Server Certificates + 6. Verifying Service Identity + 6.1. Constructing a List of Reference Identifiers + 6.1.1. Rules + 6.1.2. Examples + 6.2. Preparing to Seek a Match + 6.3. Matching the DNS Domain Name Portion + 6.4. Matching an IP Address Portion + 6.5. Matching the Application Service Type Portion + 6.6. Outcome + 7. Security Considerations + 7.1. Wildcard Certificates + 7.2. Uniform Resource Identifiers + 7.3. Internationalized Domain Names + 7.4. IP Addresses + 7.5. Multiple Presented Identifiers + 7.6. Multiple Reference Identifiers + 7.7. Certificate Trust + 8. IANA Considerations + 9. References + 9.1. Normative References + 9.2. Informative References + Appendix A. Changes from RFC 6125 + Acknowledgements + Contributors + Authors' Addresses + +1. Introduction + +1.1. Motivation + + The visible face of the Internet largely consists of services that + employ a client-server architecture in which a client communicates + with an application service. When a client communicates with an + application service using [TLS], [DTLS], or a protocol built on those + ([QUIC] being a notable example), it has some notion of the server's + identity (e.g., "the website at bigcompany.example") while attempting + to establish secure communication. Likewise, during TLS negotiation, + the server presents its notion of the service's identity in the form + of a public key certificate that was issued by a certification + authority (CA) in the context of the Internet Public Key + Infrastructure using X.509 [PKIX]. Informally, we can think of these + identities as the client's "reference identity" and the server's + "presented identity"; more formal definitions are given later. A + client needs to verify that the server's presented identity matches + its reference identity so it can deterministically and automatically + authenticate the communication. + + This document defines procedures for how clients perform this + verification. It therefore defines requirements on other parties, + such as the certification authorities that issue certificates, the + service administrators requesting them, and the protocol designers + defining interactions between clients and servers. + + This document obsoletes RFC 6125 [VERIFY]. Changes from RFC 6125 + [VERIFY] are described under Appendix A. + +1.2. Applicability + + This document does not supersede the rules for certificate issuance + or validation specified by [PKIX]. That document also governs any + certificate-related topic on which this document is silent. This + includes certificate syntax, extensions such as name constraints or + extended key usage, and handling of certification paths. + + This document addresses only name forms in the leaf "end entity" + server certificate. It does not address the name forms in the chain + of certificates used to validate a certificate, nor does it create or + check the validity of such a chain. In order to ensure proper + authentication, applications need to verify the entire certification + path. + +1.3. Overview of Recommendations + + The previous version of this specification, [VERIFY], surveyed the + then-current practice from many IETF standards and tried to + generalize best practices (see Appendix A of [VERIFY] for details). + + This document takes the lessons learned since then and codifies them. + The following is a summary of the rules, which are described at + greater length in the remainder of this document: + + * Only check DNS domain names via the subjectAltName extension + designed for that purpose: dNSName. + + * Allow use of even more specific subjectAltName extensions where + appropriate such as uniformResourceIdentifier, iPAddress, and the + otherName form SRVName. + + * Wildcard support is now the default in certificates. Constrain + wildcard certificates so that the wildcard can only be the + complete left-most label of a domain name. + + * Do not include or check strings that look like domain names in the + subject's Common Name. + +1.4. Scope + +1.4.1. In Scope + + This document applies only to service identities that are used in TLS + or DTLS and that are included in PKIX certificates. + + With regard to TLS and DTLS, these security protocols are used to + protect data exchanged over a wide variety of application protocols, + which use both the TLS or DTLS handshake protocol and the TLS or DTLS + record layer, either directly or through a profile as in Network Time + Security [NTS]. The TLS handshake protocol can also be used with + different record layers to define secure transport protocols; at + present, the most prominent example is QUIC [RFC9000]. The rules + specified here are intended to apply to all protocols in this + extended TLS "family". + + With regard to PKIX certificates, the primary usage is in the context + of the public key infrastructure described in [PKIX]. In addition, + technologies such as DNS-Based Authentication of Named Entities + (DANE) [DANE] sometimes use certificates based on PKIX (more + precisely, certificates structured via [X.509] or specific encodings + thereof such as [X.690]), at least in certain modes. Alternatively, + a TLS peer could issue delegated credentials that are based on a CA- + issued certificate, as in [TLS-SUBCERTS]. In both cases, a TLS + client could learn of a service identity through its inclusion in the + relevant certificate. The rules specified here are intended to apply + whenever service identities are included in X.509 certificates or + credentials that are derived from such certificates. + +1.4.2. Out of Scope + + The following topics are out of scope for this specification: + + * Security protocols other than those described above. + + * Keys or certificates employed outside the context of PKIX-based + systems. + + * Client or end-user identities. Other than as described above, + certificates representing client identities (e.g., rfc822Name) are + beyond the scope of this document. + + * Identification of servers using other than a domain name, an IP + address, or an SRV service name. This document discusses Uniform + Resource Identifiers [URI] only to the extent that they are + expressed in certificates. Other aspects of a service such as a + specific resource (the URI "path" component) or parameters (the + URI "query" component) are the responsibility of specific + protocols or URI schemes. + + * Certification authority policies. This includes items such as the + following: + + - How to certify or validate fully qualified domain names (FQDNs) + and application service types (see [ACME]). + + - What types or "classes" of certificates to issue and whether to + apply different policies for them. + + - How to certify or validate other kinds of information that + might be included in a certificate (e.g., organization name). + + * Resolution of DNS domain names. Although the process whereby a + client resolves the DNS domain name of an application service can + involve several steps, for the purposes of this specification, the + only relevant consideration is that the client needs to verify the + identity of the entity with which it will communicate once the + resolution process is complete. Thus, the resolution process + itself is out of scope for this specification. + + * User interface issues. In general, such issues are properly the + responsibility of client software developers and standards + development organizations dedicated to particular application + technologies (for example, see [WSC-UI]). + +1.5. Terminology + + Because many concepts related to "identity" are often too vague to be + actionable in application protocols, we define a set of more concrete + terms for use in this specification. + + application service: A service on the Internet that enables clients + to connect for the purpose of retrieving or uploading information, + communicating with other entities, or connecting to a broader + network of services. + + application service provider: An entity that hosts or deploys an + application service. + + application service type: A formal identifier for the application + protocol used to provide a particular kind of application service + at a domain. This often appears as a URI scheme [URI], a DNS SRV + Service [DNS-SRV], or an Application-Layer Protocol Negotiation + (ALPN) [ALPN] identifier. + + identifier: A particular instance of an identifier type that is + either presented by a server in a certificate or referenced by a + client for matching purposes. + + identifier type: A formally defined category of identifier that can + be included in a certificate and therefore be used for matching + purposes. For conciseness and convenience, we define the + following identifier types of interest: + + DNS-ID: A subjectAltName entry of type dNSName as defined in + [PKIX]. + + IP-ID: A subjectAltName entry of type iPAddress as defined in + [PKIX]. + + SRV-ID: A subjectAltName entry of type otherName whose name form + is SRVName as defined in [SRVNAME]. + + URI-ID: A subjectAltName entry of type uniformResourceIdentifier + as defined in [PKIX]. See further discussion in Section 7.2. + + PKIX: The short name for the Internet Public Key Infrastructure + using X.509 defined in [PKIX]. That document provides a profile + of the X.509v3 certificate specifications and X.509v2 certificate + revocation list (CRL) specifications for use on the Internet. + + presented identifier: An identifier presented by a server to a + client within a PKIX certificate when the client attempts to + establish secure communication with the server. The certificate + can include one or more presented identifiers of different types, + and if the server hosts more than one domain, then the certificate + might present distinct identifiers for each domain. + + reference identifier: An identifier expected by the client when + examining presented identifiers. It is constructed from the + source domain and, optionally, an application service type. + + Relative Distinguished Name (RDN): An ASN.1-based construction that + is itself a building-block component of Distinguished Names. See + [LDAP-DN], Section 2. + + source domain: The FQDN that a client expects an application service + to present in the certificate. This is typically input by a human + user, configured into a client, or provided by reference such as a + URL. The combination of a source domain and, optionally, an + application service type enables a client to construct one or more + reference identifiers. This specification covers FQDNs. Use of + any names that are not fully qualified is out of scope and may + result in unexpected or undefined behavior. + + subjectAltName entry: An identifier placed in a subjectAltName + extension. + + subjectAltName extension: A standard PKIX extension enabling + identifiers of various types to be bound to the certificate + subject. + + subjectName: The name of a PKIX certificate's subject, encoded in a + certificate's subject field (see [PKIX], Section 4.1.2.6). + + TLS uses the words "client" and "server", where the client is the + entity that initiates the connection. In many cases, this is + consistent with common practice, such as a browser connecting to a + web origin. For the sake of clarity, and to follow the usage in + [TLS] and related specifications, we will continue to use the terms + client and server in this document. However, these are TLS-layer + roles, and the application protocol could support the TLS server + making requests to the TLS client after the TLS handshake; there is + no requirement that the roles at the application layer match the TLS + layer. + + Security-related terms used in this document, but not defined here or + in [PKIX], should be understood in the sense defined in [SECTERMS]. + Such terms include "attack", "authentication", "identity", "trust", + "validate", and "verify". + + 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. + +2. Identifying Application Services + + This document assumes that an application service is identified by a + DNS domain name (e.g., bigcompany.example), an IP address (IPv4 or + IPv6), or an identifier that contains additional supplementary + information. Supplementary information is limited to the application + service type as expressed in a DNS SRV record (e.g., "the IMAP server + at isp.example" for "_imap.isp.example") or a URI. + + In a DNS-ID -- and in the DNS domain name portion of an SRV-ID or + URI-ID -- any characters outside the range described in [US-ASCII] + are prohibited, and internationalized domain labels are represented + as A-labels [IDNA-DEFS]. + + An IP address is either a 4-octet IPv4 address [IPv4] or a 16-octet + IPv6 address [IPv6]. The identifier might need to be converted from + a textual representation to obtain this value. + + From the perspective of the application client or user, some + identifiers are _direct_ because they are provided directly by a + human user. This includes runtime input, prior configuration, or + explicit acceptance of a client communication attempt. Other names + are _indirect_ because they are automatically resolved by the + application based on user input, such as a target name resolved from + a source name using DNS SRV or the records described in [NAPTR]. The + distinction matters most for certificate consumption, specifically + verification as discussed in this document. + + From the perspective of the application service, some identifiers are + _unrestricted_ because they can be used in any type of service, such + as a single certificate being used for both the HTTP and IMAP + services at the host "bigcompany.example". Other identifiers are + _restricted_ because they can only be used for one type of service, + such as a special-purpose certificate that can only be used for an + IMAP service. This distinction matters most for certificate + issuance. + + The four identifier types can be categorized as follows: + + * A DNS-ID is direct and unrestricted. + + * An IP-ID is direct and unrestricted. + + * An SRV-ID is typically indirect but can be direct, and it is + restricted. + + * A URI-ID is direct and restricted. + + It is important to keep these distinctions in mind because best + practices for the deployment and use of the identifiers differ. Note + that cross-protocol attacks such as those described in [ALPACA] are + possible when two different protocol services use the same + certificate. This can be addressed by using restricted identifiers + or deploying services so that they do not share certificates. + Protocol specifications MUST specify which identifiers are mandatory + to implement and SHOULD provide operational guidance when necessary. + + The Common Name RDN MUST NOT be used to identify a service because it + is not strongly typed (it is essentially free-form text) and + therefore suffers from ambiguities in interpretation. + + For similar reasons, other RDNs within the subjectName MUST NOT be + used to identify a service. + + An IP address that is the result of a DNS query is indirect. Use of + IP-IDs that are indirect is out of scope for this document. + + The IETF continues to define methods for looking up information + needed to make connections to network services. One recent example + is service binding via the "SVCB" and "HTTPS" DNS resource record + (RR) types. This document does not define any identity + representation or verification procedures that are specific to SVCB- + compatible records, because the use of such records during connection + establishment does not currently alter any of the PKIX validation + requirements specified herein or in any other relevant specification. + For example, the PKIX validation rules for [HTTP] and [DNS-OVER-TLS] + do not change when the client uses the DNS resource records defined + in [SVCB-FOR-HTTPS] or [SVCB-FOR-DNS] to look up connection + information. However, it is possible that future SVCB mapping + documents could specify altered PKIX rules for new use cases. + +3. Designing Application Protocols + + This section defines how protocol designers should reference this + document, which would typically be a normative reference in their + specification. + + A specification MAY choose to allow only one of the identifier types + defined here. + + If the technology does not use DNS SRV records to resolve the DNS + domain names of application services, then the specification MUST + state that SRV-ID as defined in this document is not supported. Note + that many existing application technologies use DNS SRV records to + resolve the DNS domain names of application services, but they do not + rely on representations of those records in PKIX certificates by + means of SRV-IDs as defined in [SRVNAME]. + + If the technology does not use URIs to identify application services, + then the specification MUST state that URI-ID as defined in this + document is not supported. Note that many existing application + technologies use URIs to identify application services, but they do + not rely on representation of those URIs in PKIX certificates by + means of URI-IDs. + + A technology MAY disallow the use of the wildcard character in + presented identifiers. If it does so, then the specification MUST + state that wildcard certificates as defined in this document are not + supported. + + A protocol can allow the use of an IP address in place of a DNS name. + This might use the same field without distinguishing the type of + identifier as, for example, in the "host" components of a URI. In + this case, applications need to be aware that the textual + representation of an IPv4 address is a valid DNS name. The two types + can be distinguished by first testing if the identifier is a valid + IPv4 address, as is done by the "first-match-wins" algorithm in + Section 3.2.2 of [URI]. + +4. Representing Server Identity + + This section provides instructions for issuers of certificates. + +4.1. Rules + + When a certification authority issues a certificate based on the FQDN + at which the application service provider will provide the relevant + application, the following rules apply to the representation of + application service identities. Note that some of these rules are + cumulative and can interact in important ways that are illustrated + later in this document. + + 1. The certificate MUST include at least one identifier. + + 2. The certificate SHOULD include a DNS-ID as a baseline for + interoperability. This is not mandatory because it is legitimate + for a certificate to include only an SRV-ID or URI-ID so as to + scope its use to a particular application type. + + 3. If the service using the certificate deploys a technology for + which the relevant specification stipulates that certificates + should include identifiers of type SRV-ID (e.g., this is true of + the Extensible Messaging and Presence Protocol (XMPP) as + described in [XMPP]), then the certificate SHOULD include an SRV- + ID. This identifier type could supplement the DNS-ID, unless the + certificate is meant to be scoped to only the protocol in + question. + + 4. If the service using the certificate deploys a technology for + which the relevant specification stipulates that certificates + should include identifiers of type URI-ID (e.g., this is true of + the Session Initiation Protocol [SIP] as specified by + [SIP-CERTS]), then the certificate SHOULD include a URI-ID. The + scheme MUST be that of the protocol associated with the + application service type, and the "host" component MUST be the + FQDN of the service. The application protocol specification MUST + specify which URI schemes are acceptable in URI-IDs contained in + PKIX certificates used for the application protocol (e.g., sip + but not sips or tel for SIP as described in [SIP-SIPS]). + Typically, this identifier type would supplement the DNS-ID, + unless the certificate is meant to be scoped to only the protocol + in question. + + 5. The certificate MAY contain more than one DNS-ID, SRV-ID, URI-ID, + or IP-ID as further explained in Section 7.5. + + 6. The certificate MAY include other application-specific + identifiers for compatibility with a deployed base, especially + identifiers for types that were defined before publication of + [SRVNAME] or for which SRV service names or URI schemes do not + exist. Such identifiers are out of scope for this specification. + +4.2. Examples + + Consider a simple website at , which is not + discoverable via DNS SRV lookups. Because HTTP does not specify the + use of URIs in server certificates, a certificate for this service + might include only a DNS-ID of . + + Consider another website, which is reachable by a fixed IP address of + 2001:db8::5c. If the two sites refer to the same web service, then + the certificate might also include this value in an IP-ID to allow + clients to use the fixed IP address as a reference identity. + + Consider an IMAP-accessible email server at the host mail.isp.example + servicing email addresses of the form user@isp.example and + discoverable via DNS SRV lookups on the application service name of + isp.example. A certificate for this service might include SRV-IDs of + _imap.isp.example and _imaps.isp.example (see [EMAIL-SRV]) along with + DNS-IDs of isp.example and mail.isp.example. + + Consider a SIP-accessible voice-over-IP (VoIP) server at the host + voice.college.example servicing SIP addresses of the form + user@voice.college.example and identified by a URI of + . A certificate for this service would + include a URI-ID of (see [SIP-CERTS]) + along with a DNS-ID of voice.college.example. + + Consider an XMPP-compatible instant messaging (IM) server at the host + messenger.example that services IM addresses of the form + user@messenger.example and that is discoverable via DNS SRV lookups + on the messenger.example domain. A certificate for this service + might include SRV-IDs of _xmpp-client.messenger.example and _xmpp- + server.messenger.example (see [XMPP]), as well as a DNS-ID of + messenger.example. + +5. Requesting Server Certificates + + This section provides instructions for service providers regarding + the information to include in certificate signing requests (CSRs). + In general, service providers SHOULD request certificates that + include all the identifier types that are required or recommended for + the application service type that will be secured using the + certificate to be issued. + + A service provider SHOULD request certificates with as few + identifiers as necessary to identify a single service; see + Section 7.5. + + If the certificate will be used for only a single type of application + service, the service provider SHOULD request a certificate that + includes DNS-ID or IP-ID values that identify that service or, if + appropriate for the application service type, SRV-ID or URI-ID values + that limit the deployment scope of the certificate to only the + defined application service type. + + If the certificate might be used for any type of application service, + the service provider SHOULD request a certificate that includes only + DNS-IDs or IP-IDs. Again, because of multiprotocol attacks, this + practice is discouraged; it can be mitigated by deploying only one + service on a host. + + If a service provider offers multiple application service types and + wishes to limit the applicability of certificates using SRV-IDs or + URI-IDs, it SHOULD request that multiple certificates rather than a + single certificate containing multiple SRV-IDs or URI-IDs each + identify a different application service type. This rule does not + apply to application service type "bundles" that identify distinct + access methods to the same underlying application such as an email + application with access methods denoted by the application service + types of imap, imaps, pop3, pop3s, and submission as described in + [EMAIL-SRV]. + +6. Verifying Service Identity + + At a high level, the client verifies the application service's + identity by performing the following actions: + + 1. The client constructs a list of reference identifiers it would + find acceptable based on the source domain and, if applicable, + the type of service to which the client is connecting. + + 2. The server provides its presented identifiers in the form of a + PKIX certificate. + + 3. The client checks each of its reference identifiers against the + server's presented identifiers for the purpose of finding a + match. When checking a reference identifier against a presented + identifier, the client matches the source domain of the + identifiers and, optionally, their application service type. + + Naturally, in addition to checking identifiers, a client should + perform further checks, such as expiration and revocation, to ensure + that the server is authorized to provide the requested service. + Because such checking is not a matter of verifying the application + service identity presented in a certificate, methods for doing so are + out of scope for this document. + +6.1. Constructing a List of Reference Identifiers + +6.1.1. Rules + + The client MUST construct a list of acceptable reference identifiers + and MUST do so independently of the identifiers presented by the + server. + + The inputs used by the client to construct its list of reference + identifiers might be a URI that a user has typed into an interface + (e.g., an HTTPS URL for a website), configured account information + (e.g., the domain name of a host for retrieving email, which might be + different from the DNS domain name portion of a username), a + hyperlink in a web page that triggers a browser to retrieve a media + object or script, or some other combination of information that can + yield a source domain and an application service type. + + This document does not precisely define how reference identifiers are + generated. Defining reference identifiers is the responsibility of + applications or protocols that use this document. Because the + security of a system that uses this document will depend on how + reference identifiers are generated, great care should be taken in + this process. For example, a protocol or application could specify + that the application service type is obtained through a one-to-one + mapping of URI schemes to service types or that the protocol or + application supports only a restricted set of URI schemes. + Similarly, it could specify that a domain name or an IP address taken + as input to the reference identifier must be obtained in a secure + context such as a hyperlink embedded in a web page that was delivered + over an authenticated and encrypted channel (for instance, see + [SECURE-CONTEXTS] with regard to the web platform). + + Naturally, if the inputs themselves are invalid or corrupt (e.g., a + user has clicked a hyperlink provided by a malicious entity in a + phishing attack), then the client might end up communicating with an + unexpected application service. + + During the course of processing, a client might be exposed to + identifiers that look like, but are not, reference identifiers. For + example, DNS resolution that starts at a DNS-ID reference identifier + might produce intermediate domain names that need to be further + resolved. Unless an application defines a process for authenticating + intermediate identifiers in a way that then allows them to be used as + a reference identifier (for example, see [SMTP-TLS]), any + intermediate values are not reference identifiers and MUST NOT be + treated as such. In the DNS case, not treating intermediate domain + names as reference identifiers removes DNS and DNS resolution from + the attack surface. + + As one example of the process of generating a reference identifier, + from the user input of the URI , a + client could derive the application service type sip from the URI + scheme and parse the domain name college.example from the "host" + component. + + Using the combination of one or more FQDNs or IP addresses, plus + optionally an application service type, the client MUST construct its + list of reference identifiers in accordance with the following rules: + + * If a server for the application service type is typically + associated with a URI for security purposes (i.e., a formal + protocol document specifies the use of URIs in server + certificates), the reference identifier SHOULD be a URI-ID. + + * If a server for the application service type is typically + discovered by means of DNS SRV records, the reference identifier + SHOULD be an SRV-ID. + + * If the reference identifier is an IP address, the reference + identifier is an IP-ID. + + * In the absence of more specific identifiers, the reference + identifier is a DNS-ID. A reference identifier of type DNS-ID can + be directly constructed from an FQDN that is (a) contained in or + securely derived from the inputs or (b) explicitly associated with + the source domain by means of user configuration. + + Which identifier types a client includes in its list of reference + identifiers, and their priority, is a matter of local policy. For + example, a client that is built to connect only to a particular kind + of service might be configured to accept as valid only certificates + that include an SRV-ID for that application service type. By + contrast, a more lenient client, even if built to connect only to a + particular kind of service, might include SRV-IDs, DNS-IDs, and IP- + IDs in its list of reference identifiers. + +6.1.2. Examples + + The following examples are for illustrative purposes only and are not + intended to be comprehensive. + + 1. A web browser that is connecting via HTTPS to the website at + would have a single reference + identifier: a DNS-ID of www.bigcompany.example. + + 2. A web browser connecting to would have a + single IP-ID reference identifier of 192.0.2.107. Likewise, if + connecting to , it would have a single + IP-ID reference identifier of 2001:db8::abcd. + + 3. A mail user agent that is connecting via IMAPS to the email + service at isp.example (resolved as mail.isp.example) might have + three reference identifiers: an SRV-ID of _imaps.isp.example (see + [EMAIL-SRV]) and DNS-IDs of isp.example and mail.isp.example. An + email user agent that does not support [EMAIL-SRV] would probably + be explicitly configured to connect to mail.isp.example, whereas + an SRV-aware user agent would derive isp.example from an email + address of the form user@isp.example but might also accept + mail.isp.example as the DNS domain name portion of reference + identifiers for the service. + + 4. A VoIP user agent that is connecting via SIP to the voice service + at voice.college.example might have only one reference + identifier: a URI-ID of sip:voice.college.example (see + [SIP-CERTS]). + + 5. An IM client that is connecting via XMPP to the IM service at + messenger.example might have three reference identifiers: an SRV- + ID of _xmpp-client.messenger.example (see [XMPP]), a DNS-ID of + messenger.example, and an XMPP-specific XmppAddr of + messenger.example (see [XMPP]). + + In all these cases, presented identifiers that do not match the + reference identifier(s) would be rejected; for instance: + + * With regard to the first example, a DNS-ID of + web.bigcompany.example would be rejected because the DNS domain + name portion does not match www.bigcompany.example. + + * With regard to the third example, a URI-ID of + would be rejected because the DNS domain + name portion does not match "voice.college.example", and a DNS-ID + of "voice.college.example" would be rejected because it lacks the + appropriate application service type portion (i.e., it does not + specify a "sip:" URI). + +6.2. Preparing to Seek a Match + + Once the client has constructed its list of reference identifiers and + has received the server's presented identifiers, the client checks + its reference identifiers against the presented identifiers for the + purpose of finding a match. The search fails if the client exhausts + its list of reference identifiers without finding a match. The + search succeeds if any presented identifier matches one of the + reference identifiers, at which point the client SHOULD stop the + search. + + Before applying the comparison rules provided in the following + sections, the client might need to split the reference identifier + into components. Each reference identifier produces either a domain + name or an IP address and optionally an application service type as + follows: + + * A DNS-ID reference identifier MUST be used directly as the DNS + domain name, and there is no application service type. + + * An IP-ID reference identifier MUST exactly match the value of an + iPAddress entry in subjectAltName, with no partial (e.g., network- + level) matching. There is no application service type. + + * For an SRV-ID reference identifier, the DNS domain name portion is + the Name and the application service type portion is the Service. + For example, an SRV-ID of _imaps.isp.example has a DNS domain name + portion of isp.example and an application service type portion of + imaps, which maps to the IMAP application protocol as explained in + [EMAIL-SRV]. + + * For a reference identifier of type URI-ID, the DNS domain name + portion is the "reg-name" part of the "host" component and the + application service type portion is the scheme, as defined above. + Matching only the "reg-name" rule from [URI] limits the additional + domain name validation (Section 6.3) to DNS domain names or non-IP + hostnames. A URI that contains an IP address might be matched + against an IP-ID in place of a URI-ID by some lenient clients. + This document does not describe how a URI that contains no "host" + component can be matched. Note that extraction of the "reg-name" + might necessitate normalization of the URI (as explained in + Section 6 of [URI]). For example, a URI-ID of + would be split into a DNS domain name + portion of voice.college.example and an application service type + of sip (associated with an application protocol of SIP as + explained in [SIP-CERTS]). + + If the reference identifier produces a domain name, the client MUST + match the DNS name; see Section 6.3. If the reference identifier + produces an IP address, the client MUST match the IP address; see + Section 6.4. If an application service type is present, it MUST also + match the service type; see Section 6.5. + +6.3. Matching the DNS Domain Name Portion + + This section describes how the client must determine if the presented + DNS name matches the reference DNS name. The rules differ depending + on whether the domain to be checked is an internationalized domain + name, as defined in Section 2, or not. For clients that support + presented identifiers containing the wildcard character "*", this + section also specifies a supplemental rule for such "wildcard + certificates". This section uses the description of labels and + domain names in [DNS-CONCEPTS]. + + If the DNS domain name portion of a reference identifier is not an + internationalized domain name (i.e., an FQDN that conforms to + "preferred name syntax" as described in Section 3.5 of + [DNS-CONCEPTS]), then the matching of the reference identifier + against the presented identifier MUST be performed by comparing the + set of domain name labels using a case-insensitive ASCII comparison, + as clarified by [DNS-CASE]. For example, WWW.BigCompany.Example + would be lower-cased to www.bigcompany.example for comparison + purposes. Each label MUST match in order for the names to be + considered a match, except as supplemented by the rule about checking + wildcard labels in presented identifiers given below. + + If the DNS domain name portion of a reference identifier is an + internationalized domain name, then the client MUST convert any + U-labels [IDNA-DEFS] in the domain name to A-labels before checking + the domain name or comparing it with others. In accordance with + [IDNA-PROTO], A-labels MUST be compared as case-insensitive ASCII. + Each label MUST match in order for the domain names to be considered + to match, except as supplemented by the rule about checking wildcard + labels in presented identifiers given below. + + If the technology specification supports wildcards in presented + identifiers, then the client MUST match the reference identifier + against a presented identifier whose DNS domain name portion contains + the wildcard character "*" in a label, provided these requirements + are met: + + 1. There is only one wildcard character. + + 2. The wildcard character appears only as the complete content of + the left-most label. + + If the requirements are not met, the presented identifier is invalid + and MUST be ignored. + + A wildcard in a presented identifier can only match one label in a + reference identifier. This specification covers only wildcard + characters in presented identifiers, not wildcard characters in + reference identifiers or in DNS domain names more generally. + Therefore, the use of wildcard characters as described herein is not + to be confused with DNS wildcard matching, where the "*" label always + matches at least one whole label and sometimes more; see + [DNS-CONCEPTS], Section 4.3.3 and [DNS-WILDCARDS]. In particular, it + also deviates from [DNS-WILDCARDS], Section 2.1.3. + + For information regarding the security characteristics of wildcard + certificates, see Section 7.1. + +6.4. Matching an IP Address Portion + + Matching of an IP-ID is based on an octet-for-octet comparison of the + bytes of the reference identity with the bytes contained in the + iPAddress subjectAltName. + + For an IP address that appears in a URI-ID, the "host" component of + both the reference identity and the presented identifier must match. + These are parsed as either an "IPv6address" (following [URI], + Section 3.2.2) or an "IPv4address" (following [IPv4]). If the + resulting octets are equal, the IP address matches. + + This document does not specify how an SRV-ID reference identity can + include an IP address, as [SRVNAME] only defines string names, not + octet identifiers such as an IP address. + +6.5. Matching the Application Service Type Portion + + The rules for matching the application service type depend on whether + the identifier is an SRV-ID or a URI-ID. + + These identifiers provide an application service type portion to be + checked, but that portion is combined only with the DNS domain name + portion of the SRV-ID or URI-ID itself. Consider the example of a + messaging client that has two reference identifiers: (1) an SRV-ID of + _xmpp-client.messenger.example and (2) a DNS-ID of app.example. The + client MUST check (1) the combination of (a) an application service + type of xmpp-client and (b) a DNS domain name of messenger.example as + well as (2) a DNS domain name of app.example. However, the client + MUST NOT check the combination of an application service type of + xmpp-client and a DNS domain name of app.example because it does not + have an SRV-ID of _xmpp-client.app.example in its list of reference + identifiers. + + If the identifier is an SRV-ID, then the application service name + MUST be matched in a case-insensitive manner, in accordance with + [DNS-SRV]. Note that per [SRVNAME], the underscore "_" is part of + the service name in DNS SRV records and in SRV-IDs. + + If the identifier is a URI-ID, then the scheme name portion MUST be + matched in a case-insensitive manner, in accordance with [URI]. Note + that the colon ":" is a separator between the scheme name and the + rest of the URI and thus does not need to be included in any + comparison. + +6.6. Outcome + + If the client has found a presented identifier that matches a + reference identifier, then the service identity check has succeeded. + In this case, the client MUST use the matched reference identifier as + the validated identity of the application service. + + If the client does not find a presented identifier matching any of + the reference identifiers, then the client MUST proceed as follows. + + If the client is an automated application, then it SHOULD terminate + the communication attempt with a bad certificate error and log the + error appropriately. The application MAY provide a configuration + setting to disable this behavior, but it MUST NOT disable this + security control by default. + + If the client is one that is directly controlled by a human user, + then it SHOULD inform the user of the identity mismatch and + automatically terminate the communication attempt with a bad + certificate error in order to prevent users from inadvertently + bypassing security protections in hostile situations. Such clients + MAY give advanced users the option of proceeding with acceptance + despite the identity mismatch. Although this behavior can be + appropriate in certain specialized circumstances, it needs to be + handled with extreme caution, for example by first encouraging even + an advanced user to terminate the communication attempt and, if they + choose to proceed anyway, by forcing the user to view the entire + certification path before proceeding. + + The application MAY also present the user with the ability to accept + the presented certificate as valid for subsequent connections. Such + ad hoc "pinning" SHOULD NOT restrict future connections to just the + pinned certificate. Local policy that statically enforces a given + certificate for a given peer SHOULD be made available only as prior + configuration rather than a just-in-time override for a failed + connection. + +7. Security Considerations + +7.1. Wildcard Certificates + + Wildcard certificates automatically vouch for any single-label + hostnames within their domain, but not multiple levels of domains. + This can be convenient for administrators but also poses the risk of + vouching for rogue or buggy hosts. For example, see [Defeating-SSL] + (beginning at slide 91) and [HTTPSbytes] (slides 38-40). + + As specified in Section 6.3, restricting the presented identifiers in + certificates to only one wildcard character (e.g., + "*.bigcompany.example" but not "*.*.bigcompany.example") and + restricting the use of wildcards to only the left-most domain label + can help to mitigate certain aspects of the attack described in + [Defeating-SSL]. + + That same attack also relies on the initial use of a cleartext HTTP + connection, which is hijacked by an active on-path attacker and + subsequently upgraded to HTTPS. In order to mitigate such an attack, + administrators and software developers are advised to follow the + strict TLS guidelines provided in [TLS-REC], Section 3.2. + + Because the attack described in [HTTPSbytes] relies on an underlying + cross-site scripting (XSS) attack, web browsers and applications are + advised to follow best practices to prevent XSS attacks; for example, + see [XSS], which was published by the Open Web Application Security + Project (OWASP). + + Protection against a wildcard that identifies a public suffix + [Public-Suffix], such as *.co.uk or *.com, is beyond the scope of + this document. + + As noted in Section 3, application protocols can disallow the use of + wildcard certificates entirely as a more foolproof mitigation. + +7.2. Uniform Resource Identifiers + + The URI-ID type is a subjectAltName entry of type + uniformResourceIdentifier as defined in [PKIX]. For the purposes of + this specification, the URI-ID MUST include both a "scheme" and a + "host" component that matches the "reg-name" rule; if the entry does + not include both, it is not a valid URI-ID and MUST be ignored. Any + other components are ignored because only the "scheme" and "host" + components are used for certificate matching as specified under + Section 6. + + The quoted component names in the previous paragraph represent the + associated [ABNF] productions from the IETF Proposed Standard for + Uniform Resource Identifiers [URI]. Although the reader should be + aware that some applications (e.g., web browsers) might instead + conform to the Uniform Resource Locator (URL) specification + maintained by the WHATWG [URL], it is not expected that differences + between the URI and URL specifications would manifest themselves in + certificate matching. + +7.3. Internationalized Domain Names + + This document specifies only matching between reference identifiers + and presented identifiers, not the visual presentation of domain + names. Specifically, the matching of internationalized domain names + is performed on A-labels only (Section 6.3). The limited scope of + this specification likely mitigates potential confusion caused by the + use of visually similar characters in domain names (for example, as + described in Section 4.4 of [IDNA-DEFS], [UTS-36], and [UTS-39]); in + any case, such concerns are a matter for application-level protocols + and user interfaces, not the matching of certificates. + +7.4. IP Addresses + + The TLS Server Name Indication (SNI) extension only conveys domain + names. Therefore, a client with an IP-ID reference identity cannot + present any information about its reference identity when connecting + to a server. Servers that wish to present an IP-ID therefore need to + present this identity when a connection is made without SNI. + + The textual representation of an IPv4 address might be misinterpreted + as a valid FQDN in some contexts. This can result in different + security treatment that might cause different components of a system + to classify the value differently, which might lead to + vulnerabilities. Consider a system in which one component enforces a + security rule that is conditional on the type of identifier but + misclassifies an IP address as an FQDN, whereas a second component + correctly classifies the identifier but incorrectly assumes that + rules regarding IP addresses have been enforced by the first + component. As a result, the system as a whole might behave in an + insecure manner. Consistent classification of identifiers avoids + this problem. + + See also Section 3, particularly the last paragraph. + +7.5. Multiple Presented Identifiers + + A given application service might be addressed by multiple DNS domain + names for a variety of reasons, and a given deployment might service + multiple domains or protocols. TLS extensions such as the Server + Name Indication (SNI), as discussed in [TLS-EXT], Section 3, and + ALPN, as discussed in [ALPN], provide a way for the application to + indicate the desired identifier and protocol to the server, which it + can then use to select the most appropriate certificate. + + This specification allows multiple DNS-IDs, IP-IDs, SRV-IDs, or URI- + IDs in a certificate. As a result, an application service can use + the same certificate for multiple hostnames, such as when a client + does not support the TLS SNI extension, or for multiple protocols, + such as SMTP and HTTP, on a single hostname. Note that the set of + names in a certificate is the set of names that could be affected by + a compromise of any other server named in the set: the strength of + any server in the set of names is determined by the weakest of those + servers that offer the names. + + The way to mitigate this risk is to limit the number of names that + any server can speak for and to ensure that all servers in the set + have a strong minimum configuration as described in [TLS-REC], + Section 3.9. + +7.6. Multiple Reference Identifiers + + This specification describes how a client may construct multiple + acceptable reference identifiers and may match any of those reference + identifiers with the set of presented identifiers. [PKIX], + Section 4.2.1.10 describes a mechanism to allow CA certificates to be + constrained in the set of presented identifiers that they may include + within server certificates. However, these constraints only apply to + the explicitly enumerated name forms. For example, a CA that is only + name-constrained for DNS-IDs is not constrained for SRV-IDs and URI- + IDs, unless those name forms are also explicitly included within the + name constraints extension. + + A client that constructs multiple reference identifiers of different + types, such as both DNS-IDs and SRV-IDs as described in + Section 6.1.1, SHOULD take care to ensure that CAs issuing such + certificates are appropriately constrained. This MAY take the form + of local policy through agreement with the issuing CA or MAY be + enforced by the client requiring that if one form of presented + identifier is constrained, such as a dNSName name constraint for DNS- + IDs, then all other forms of acceptable reference identities are also + constrained, such as requiring a uniformResourceIndicator name + constraint for URI-IDs. + +7.7. Certificate Trust + + This document assumes that if a client trusts a given CA, it trusts + all certificates issued by that CA. The certificate checking process + does not include additional checks for bad behavior by the hosts + identified with such certificates, for instance, rogue servers or + buggy applications. Any additional checks (e.g., checking the server + name against trusted block lists) are the responsibility of the + application protocol or the client itself. + +8. IANA Considerations + + This document has no IANA actions. + +9. References + +9.1. Normative References + + [DNS-CONCEPTS] + Mockapetris, P., "Domain names - concepts and facilities", + STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, + . + + [DNS-SRV] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for + specifying the location of services (DNS SRV)", RFC 2782, + DOI 10.17487/RFC2782, February 2000, + . + + [DNS-WILDCARDS] + Lewis, E., "The Role of Wildcards in the Domain Name + System", RFC 4592, DOI 10.17487/RFC4592, July 2006, + . + + [IDNA-DEFS] + Klensin, J., "Internationalized Domain Names for + Applications (IDNA): Definitions and Document Framework", + RFC 5890, DOI 10.17487/RFC5890, August 2010, + . + + [IDNA-PROTO] + Klensin, J., "Internationalized Domain Names in + Applications (IDNA): Protocol", RFC 5891, + DOI 10.17487/RFC5891, August 2010, + . + + [IPv4] Postel, J., "Internet Protocol", STD 5, RFC 791, + DOI 10.17487/RFC0791, September 1981, + . + + [IPv6] Hinden, R. and S. Deering, "IP Version 6 Addressing + Architecture", RFC 4291, DOI 10.17487/RFC4291, February + 2006, . + + [LDAP-DN] Zeilenga, K., Ed., "Lightweight Directory Access Protocol + (LDAP): String Representation of Distinguished Names", + RFC 4514, DOI 10.17487/RFC4514, June 2006, + . + + [PKIX] 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, + . + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + + [SRVNAME] Santesson, S., "Internet X.509 Public Key Infrastructure + Subject Alternative Name for Expression of Service Name", + RFC 4985, DOI 10.17487/RFC4985, August 2007, + . + + [TLS-REC] Sheffer, Y., Saint-Andre, P., and T. Fossati, + "Recommendations for Secure Use of Transport Layer + Security (TLS) and Datagram Transport Layer Security + (DTLS)", BCP 195, RFC 9325, DOI 10.17487/RFC9325, November + 2022, . + + [URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform + Resource Identifier (URI): Generic Syntax", STD 66, + RFC 3986, DOI 10.17487/RFC3986, January 2005, + . + +9.2. Informative References + + [ABNF] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", STD 68, RFC 5234, + DOI 10.17487/RFC5234, January 2008, + . + + [ACME] Barnes, R., Hoffman-Andrews, J., McCarney, D., and J. + Kasten, "Automatic Certificate Management Environment + (ACME)", RFC 8555, DOI 10.17487/RFC8555, March 2019, + . + + [ALPACA] Brinkmann, M., Dresen, C., Merget, R., Poddebniak, D., + Müller, J., Somorovsky, J., Schwenk, J., and S. Schinzel, + "ALPACA: Application Layer Protocol Confusion - Analyzing + and Mitigating Cracks in TLS Authentication", 30th USENIX + Security Symposium (USENIX Security 21), September 2021, + . + + [ALPN] Friedl, S., Popov, A., Langley, A., and E. Stephan, + "Transport Layer Security (TLS) Application-Layer Protocol + Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301, + July 2014, . + + [DANE] Hoffman, P. and J. Schlyter, "The DNS-Based Authentication + of Named Entities (DANE) Transport Layer Security (TLS) + Protocol: TLSA", RFC 6698, DOI 10.17487/RFC6698, August + 2012, . + + [Defeating-SSL] + Marlinspike, M., "New Tricks for Defeating SSL in + Practice", Black Hat DC, February 2009, + . + + [DNS-CASE] Eastlake 3rd, D., "Domain Name System (DNS) Case + Insensitivity Clarification", RFC 4343, + DOI 10.17487/RFC4343, January 2006, + . + + [DNS-OVER-TLS] + Hu, Z., Zhu, L., Heidemann, J., Mankin, A., Wessels, D., + and P. Hoffman, "Specification for DNS over Transport + Layer Security (TLS)", RFC 7858, DOI 10.17487/RFC7858, May + 2016, . + + [DTLS] Rescorla, E., Tschofenig, H., and N. Modadugu, "The + Datagram Transport Layer Security (DTLS) Protocol Version + 1.3", RFC 9147, DOI 10.17487/RFC9147, April 2022, + . + + [EMAIL-SRV] + Daboo, C., "Use of SRV Records for Locating Email + Submission/Access Services", RFC 6186, + DOI 10.17487/RFC6186, March 2011, + . + + [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, + Ed., "HTTP Semantics", STD 97, RFC 9110, + DOI 10.17487/RFC9110, June 2022, + . + + [HTTPSbytes] + Sokol, J. and R. Hansen, "HTTPS Can Byte Me", Black Hat + Briefings, November 2010, . + + [NAPTR] Mealling, M., "Dynamic Delegation Discovery System (DDDS) + Part Three: The Domain Name System (DNS) Database", + RFC 3403, DOI 10.17487/RFC3403, October 2002, + . + + [NTS] Franke, D., Sibold, D., Teichel, K., Dansarie, M., and R. + Sundblad, "Network Time Security for the Network Time + Protocol", RFC 8915, DOI 10.17487/RFC8915, September 2020, + . + + [Public-Suffix] + Mozilla Foundation, "Public Suffix List", + . + + [QUIC] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure + QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021, + . + + [RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based + Multiplexed and Secure Transport", RFC 9000, + DOI 10.17487/RFC9000, May 2021, + . + + [SECTERMS] Shirey, R., "Internet Security Glossary, Version 2", + FYI 36, RFC 4949, DOI 10.17487/RFC4949, August 2007, + . + + [SECURE-CONTEXTS] + West, M., "Secure Contexts", W3C Candidate Recommendation + Draft, September 2021, + . + + [SIP] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, + A., Peterson, J., Sparks, R., Handley, M., and E. + Schooler, "SIP: Session Initiation Protocol", RFC 3261, + DOI 10.17487/RFC3261, June 2002, + . + + [SIP-CERTS] + Gurbani, V., Lawrence, S., and A. Jeffrey, "Domain + Certificates in the Session Initiation Protocol (SIP)", + RFC 5922, DOI 10.17487/RFC5922, June 2010, + . + + [SIP-SIPS] Audet, F., "The Use of the SIPS URI Scheme in the Session + Initiation Protocol (SIP)", RFC 5630, + DOI 10.17487/RFC5630, October 2009, + . + + [SMTP-TLS] Fenton, J., "SMTP Require TLS Option", RFC 8689, + DOI 10.17487/RFC8689, November 2019, + . + + [SVCB-FOR-DNS] + Schwartz, B., "Service Binding Mapping for DNS Servers", + RFC 9461, DOI 10.17487/RFC9461, November 2023, + . + + [SVCB-FOR-HTTPS] + Schwartz, B., Bishop, M., and E. Nygren, "Service Binding + and Parameter Specification via the DNS (SVCB and HTTPS + Resource Records)", RFC 9460, DOI 10.17487/RFC9460, + November 2023, . + + [TLS] Rescorla, E., "The Transport Layer Security (TLS) Protocol + Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, + . + + [TLS-EXT] Eastlake 3rd, D., "Transport Layer Security (TLS) + Extensions: Extension Definitions", RFC 6066, + DOI 10.17487/RFC6066, January 2011, + . + + [TLS-SUBCERTS] + Barnes, R., Iyengar, S., Sullivan, N., and E. Rescorla, + "Delegated Credentials for TLS and DTLS", RFC 9345, + DOI 10.17487/RFC9345, July 2023, + . + + [URL] van Kesteren, A., "URL", WHATWG Living Standard, September + 2023, . + + [US-ASCII] American National Standards Institute, "Coded Character + Sets - 7-bit American Standard Code for Information + Interchange (7-Bit ASCII)", ANSI INCITS 4-1986 (R2007), + June 2007. + + [UTS-36] Davis, M. and M. Suignard, "Unicode Security + Considerations", Revision 15, Unicode Technical + Report #36, September 2014, + . + + [UTS-39] Davis, M. and M. Suignard, "Unicode Security Mechanisms", + Version 15.1.0, Revision 28, Unicode Technical + Standard #39, September 2023, + . + + [VERIFY] Saint-Andre, P. and J. Hodges, "Representation and + Verification of Domain-Based Application Service Identity + within Internet Public Key Infrastructure Using X.509 + (PKIX) Certificates in the Context of Transport Layer + Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March + 2011, . + + [WSC-UI] Saldhana, A. and T. Roessler, "Web Security Context: User + Interface Guidelines", W3C Recommendation REC-wsc-ui- + 20100812, August 2010, + . + + [X.509] ITU-T, "Information Technology - Open Systems + Interconnection - The Directory: Public-key and attribute + certificate frameworks", ISO/IEC 9594-8, ITU-T + Recommendation X.509, October 2019. + + [X.690] ITU-T, "Information Technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), Canonical + Encoding Rules (CER) and Distinguished Encoding Rules + (DER)", ISO/IEC 8825-1:2021 (E), ITU-T + Recommendation X.690, February 2021. + + [XMPP] Saint-Andre, P., "Extensible Messaging and Presence + Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120, + March 2011, . + + [XSS] Kirsten, S., et al., "Cross Site Scripting (XSS)", OWASP + Foundation, 2020, + . + +Appendix A. Changes from RFC 6125 + + This document revises and obsoletes [VERIFY] based on the decade of + experience and changes since it was published. The major changes, in + no particular order, include: + + * The only legal place for a certificate wildcard is as the complete + left-most label in a domain name. + + * The server identity can only be expressed in the subjectAltNames + extension; it is no longer valid to use the commonName RDN, known + as CN-ID in [VERIFY]. + + * Detailed discussion of pinning (configuring use of a certificate + that doesn't match the criteria in this document) has been removed + and replaced with two paragraphs in Section 6.6. + + * The sections detailing different target audiences and which + sections to read (first) have been removed. + + * References to the X.500 directory, the survey of prior art, and + the sample text in Appendix A have been removed. + + * All references have been updated to the latest versions. + + * The TLS SNI extension is no longer new; it is commonplace. + + * Additional text on multiple identifiers, and their security + considerations, has been added. + + * IP-ID reference identifiers have been added. This builds on the + definition in [HTTP], Section 4.3.5. + + * The document title has been shortened because the previous title + was difficult to cite. + +Acknowledgements + + We gratefully acknowledge everyone who contributed to the previous + version of this specification [VERIFY]. Thanks also to Carsten + Bormann for converting the previous version of this specification to + Markdown so that we could more easily use Martin Thomson's + i-d-template software. + + In addition to discussions within the UTA Working Group, the + following people provided official reviews or especially significant + feedback: Corey Bonnell, Roman Danyliw, Viktor Dukhovni, Lars Eggert, + Patrik Fältström, Jim Fenton, Olle Johansson, John Klensin, Murray + Kucherawy, Warren Kumari, John Mattson, Alexey Melnikov, Derrell + Piper, Maria Ines Robles, Rob Sayre, Yaron Sheffer, Ryan Sleevi, + Brian Smith, Petr Špaček, Orie Steele, Martin Thomson, Joe Touch, + Éric Vyncke, Paul Wouters, and Qin Wu. + + A few descriptive sentences were borrowed from [TLS-REC]. + +Contributors + + Jeff Hodges coauthored the previous version of this specification + [VERIFY]. The authors gratefully acknowledge his essential + contributions to this work. + + Martin Thomson contributed the text on the handling of IP-IDs. + +Authors' Addresses + + Peter Saint-Andre + Independent + United States of America + Email: stpeter@stpeter.im + + + Rich Salz + Akamai Technologies + United States of America + Email: rsalz@akamai.com diff --git a/docs/rfc/rfc9549.txt b/docs/rfc/rfc9549.txt index e9f566a5..060d228e 100644 --- a/docs/rfc/rfc9549.txt +++ b/docs/rfc/rfc9549.txt @@ -1,8 +1,12 @@ + + + + Internet Engineering Task Force (IETF) R. Housley Request for Comments: 9549 Vigil Security Obsoletes: 8399 March 2024 -Updates: 5280 -Category: Standards Track +Updates: 5280 +Category: Standards Track ISSN: 2070-1721 @@ -212,13 +216,13 @@ Table of Contents | extension. Each of these extensions uses the GeneralName type; | one choice in GeneralName is the dNSName field, which is defined | as type IA5String. - | + | | IA5String is limited to the set of ASCII characters. To | accommodate IDNs, U-labels are converted to A-labels. The A-label | is the encoding of the U-label according to the Punycode algorithm | [RFC3492] with the ACE prefix "xn--" added at the beginning of the | string. - | + | | When comparing DNS names for equality, conforming implementations | MUST perform a case-insensitive exact match on the entire DNS | name. When evaluating name constraints, conforming @@ -227,11 +231,11 @@ Table of Contents | that may be constructed by adding labels to the left-hand side of | the domain name given as the constraint is considered to fall | within the indicated subtree. - | + | | Implementations that have a user interface SHOULD convert IDNs to | Unicode for display. Specifically, conforming implementations | convert A-labels to U-labels for display purposes. - | + | | Implementation consideration: There are increased memory | requirements for IDNs. An IDN ACE label will begin with the four | additional characters "xn--", and an IDN can require as many as @@ -286,26 +290,26 @@ Table of Contents | address cannot be represented in ASCII, then the internationalized | email address is placed in the otherName choice of GeneralName | using the conventions in RFC 8398 [RFC8398]. - | + | | When the host-part contains an IDN, conforming implementations | MUST convert all U-labels to A-labels. - | + | | 7.5.1. Local-Part Contains Only ASCII Characters - | + | | Two email addresses are considered to match if: - | + | | 1) The local-part of each name is an exact match, AND - | + | | 2) The host-part of each name matches using a case-insensitive | ASCII comparison. - | + | | Implementations that have a user interface SHOULD convert the | host-part of internationalized email addresses specified in these | extensions to Unicode before display. Specifically, conforming | implementations convert A-labels to U-labels for display purposes. - | + | | 7.5.2. Local-Part Contains Non-ASCII Characters - | + | | When the local-part contains non-ASCII characters, conforming | implementations MUST place the internationalized email address in | the SmtpUTF8Mailbox within the otherName choice of GeneralName as @@ -314,14 +318,14 @@ Table of Contents | Byte-Order-Mark (BOM) [RFC3629] to aid comparison. The email | address local-part within the SmtpUTF8Mailbox MUST conform to the | requirements of [RFC6530] and [RFC6531]. - | + | | Two email addresses are considered to match if: - | + | | 1) The local-part of each name is an exact match, AND - | + | | 2) The host-part of each name matches using a case-insensitive | ASCII comparison. - | + | | Implementations that have a user interface SHOULD convert the | host-part of internationalized email addresses specified in these | extensions to Unicode before display. Specifically, conforming diff --git a/docs/rfc/rfc9598.txt b/docs/rfc/rfc9598.txt index 69ac7b1c..31479cbd 100644 --- a/docs/rfc/rfc9598.txt +++ b/docs/rfc/rfc9598.txt @@ -1,3 +1,7 @@ + + + + Internet Engineering Task Force (IETF) A. Melnikov Request for Comments: 9598 Isode Ltd Obsoletes: 8398 W. Chuang diff --git a/docs/rfc/rfc9608.txt b/docs/rfc/rfc9608.txt index 4691538e..04f5018b 100644 --- a/docs/rfc/rfc9608.txt +++ b/docs/rfc/rfc9608.txt @@ -1,3 +1,7 @@ + + + + Internet Engineering Task Force (IETF) R. Housley Request for Comments: 9608 Vigil Security Updates: 5280 T. Okubo diff --git a/docs/rfc/rfc9618.txt b/docs/rfc/rfc9618.txt index 552f72f5..a4d39a5d 100644 --- a/docs/rfc/rfc9618.txt +++ b/docs/rfc/rfc9618.txt @@ -1,3 +1,7 @@ + + + + Internet Engineering Task Force (IETF) D. Benjamin Request for Comments: 9618 Google LLC Updates: 5280 August 2024 diff --git a/package.json b/package.json index a7d184ea..f6516295 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "prepublishOnly": "[ -n \"${GITHUB_ACTIONS:-}\" ] || { printf '%s\\n' 'manual npm publish blocked; use release workflow for provenance' >&2; exit 1; }", "publish:jsr": "[ -n \"${GITHUB_ACTIONS:-}\" ] || { printf '%s\\n' 'manual JSR publish blocked; use release workflow' >&2; exit 1; }; bunx jsr publish", "publish:pkgprnew": "bunx pkg-pr-new publish --packageManager='npm,pnpm,bun' --bun --template './examples/vite'", + "rfc": "test -n \"${RFC}\" && curl -fsSLo \"${PWD}/docs/rfc/rfc${RFC}.txt\" \"https://www.rfc-editor.org/rfc/rfc${RFC}.txt\"", "site:build": "run --dir site/.vitepress build", "site:dev": "run --dir site/.vitepress dev", "site:import-maps": "deno run --allow-read --allow-net --allow-write --allow-run scripts/site-import-maps.deno.ts", diff --git a/src/internal/asn1/der.ts b/src/internal/asn1/der.ts index 43ed7ed5..bb9f8460 100644 --- a/src/internal/asn1/der.ts +++ b/src/internal/asn1/der.ts @@ -191,7 +191,7 @@ export function utf8String(value: string): Uint8Array { /** * Encodes a DER PrintableString (tag `0x13`). * - * @throws if the input contains characters outside the X.520 PrintableString set. + * @throws if the input contains characters outside the ITU-T X.680 §41.4 Table 10 PrintableString set. */ export function printableString(value: string): Uint8Array { if (!/^[A-Za-z0-9 '()+,\-./:=?]*$/.test(value)) { @@ -275,7 +275,8 @@ function encodeBase128(value: bigint): number[] { /** * Encodes a dotted-decimal OID string as a DER OBJECT IDENTIFIER (tag `0x06`). * - * Validates arc constraints per X.660: first arc must be 0–2, second < 40 for arcs 0 and 1.\ + * Validates arc constraints: the root arc must be 0–2 (X.660 Annex A), and for + * roots 0 and 1 the second arc must be < 40 (the X.690 §8.19.4 `(X*40)+Y` packing).\ * Sub-identifiers are encoded with base-128 continuation. */ export function objectIdentifier(oid: string): Uint8Array { diff --git a/src/internal/crypto/pbes2.ts b/src/internal/crypto/pbes2.ts index 66275999..dd4406fd 100644 --- a/src/internal/crypto/pbes2.ts +++ b/src/internal/crypto/pbes2.ts @@ -191,7 +191,10 @@ export function encodePbes2AlgorithmIdentifier(parameters: Pbes2Parameters): Uin export function parsePbes2AlgorithmIdentifier(algorithmIdentifierDer: Uint8Array): Pbes2Parameters { const { paramsDer, kdf, scheme } = parsePbes2OuterFields(algorithmIdentifierDer); const { pbkdf2Der, pbkdf2Params } = parsePbes2KdfFields(paramsDer, kdf); - // PBKDF2 params: SEQUENCE { salt OCTET STRING, iterationCount INTEGER, [keyLength INTEGER], [prf AlgorithmIdentifier] } + // RFC 8018 A.2 PBKDF2-params: SEQUENCE { salt CHOICE { specified OCTET STRING, + // otherSource AlgorithmIdentifier }, iterationCount INTEGER, keyLength INTEGER + // OPTIONAL, prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 }. Only the + // `specified` salt alternative is accepted. const salt = pbkdf2Params[0]; const iterations = pbkdf2Params[1]; if (salt === undefined || iterations === undefined || salt.tag !== 0x04) { diff --git a/src/keys/keys.ts b/src/keys/keys.ts index 87cde01b..d263a5d4 100644 --- a/src/keys/keys.ts +++ b/src/keys/keys.ts @@ -1609,8 +1609,9 @@ function readPkcs8Version(content: Uint8Array): number { /** * Extract the optional `parameters [0]` curve identifier from a SEC 1 ECPrivateKey. * - * RFC 5915: `ECPrivateKey ::= SEQUENCE { version INTEGER, privateKey OCTET STRING, - * parameters [0] ECParameters OPTIONAL, publicKey [1] BIT STRING OPTIONAL }`. + * RFC 5915 §3: `ECPrivateKey ::= SEQUENCE { version INTEGER { ecPrivkeyVer1(1) } + * (ecPrivkeyVer1), privateKey OCTET STRING, parameters [0] ECParameters + * {{ NamedCurve }} OPTIONAL, publicKey [1] BIT STRING OPTIONAL }`. */ function parseSec1PrivateKey(der: Uint8Array): { /** Optional ECParameters tag inside `parameters [0]` (0x06 for a named curve). */ @@ -1948,11 +1949,11 @@ function opensslBytesToKey(password: string, salt: Uint8Array, length: number): return out; } -/** Parse a PEM block into its label, RFC 1421 headers, and base64 body. */ +/** Parse a PEM block into its label, OpenSSL-style headers, and base64 body. */ function parseTraditionalPem(pem: string): { /** PEM type label between `BEGIN` and `END` markers. */ readonly label: string; - /** RFC 1421 encapsulated headers (e.g. `Proc-Type`, `DEK-Info`). */ + /** OpenSSL-style encapsulated headers (e.g. `Proc-Type`, `DEK-Info`). */ readonly headers: ReadonlyMap; /** Base64-encoded payload after the headers. */ readonly base64Body: string; @@ -1984,7 +1985,7 @@ function parseTraditionalPem(pem: string): { index += 1; break; } - const delimiter = line.indexOf(': '); + const delimiter = line.indexOf(':'); if (delimiter === -1) { break; } @@ -1992,7 +1993,7 @@ function parseTraditionalPem(pem: string): { if (headers.has(headerName)) { throw new Error(`Duplicate PEM header: ${headerName}`); } - headers.set(headerName, line.slice(delimiter + 2)); + headers.set(headerName, line.slice(delimiter + 1).trimStart()); index += 1; } const body = lines.slice(index, lines.length - 1).join(''); diff --git a/src/pkcs/pkcs7.ts b/src/pkcs/pkcs7.ts index 9c95e146..9baca355 100644 --- a/src/pkcs/pkcs7.ts +++ b/src/pkcs/pkcs7.ts @@ -1,8 +1,10 @@ /** * PKCS#7/CMS certificate bags and SignedData. * - * Creates degenerate (signature-less) certificate bags, parses RFC 2315 / RFC 5652 - * SignedData structures, and verifies signer signatures including signed-attribute flows. + * Creates degenerate (signature-less) certificate bags, parses RFC 5652 + * SignedData (and the RFC 2315 form whose contentInfo content is an OCTET + * STRING and whose certificates are X.509), and verifies signer signatures + * including signed-attribute flows. * * @module */ @@ -885,9 +887,9 @@ function signerHasNamedCurve(algorithm: KeyAlgorithm): algorithm is EcKeyAlgorit /** * Resolves the content-digest hash and its OID for a signer key. * - * Pairs each key with the digest used by its signature algorithm (RFC 5754): - * P-256/RSA-SHA256 → SHA-256, P-384 → SHA-384, P-521 → SHA-512. Ed25519 uses - * SHA-512 for the messageDigest attribute, per RFC 8419. + * Curve pairing follows RFC 5753 §8: P-256/RSA-SHA256 → SHA-256, P-384 → SHA-384, P-521 → SHA-512. + * Digest OIDs are from RFC 5754 §2. + * Ed25519 uses SHA-512 for the messageDigest attribute, per RFC 8419. */ function contentDigestForPrivateKey( privateKey: CryptoKey, diff --git a/src/revocation/ocsp.ts b/src/revocation/ocsp.ts index 7f033950..9a814035 100644 --- a/src/revocation/ocsp.ts +++ b/src/revocation/ocsp.ts @@ -70,7 +70,7 @@ import type { } from '#micro509/x509/parse'; import { parseCertificateDerOrThrow, parseCertificateFromSource } from '#micro509/x509/parse'; -/** Hash algorithm used to compute OCSP CertID fields. SHA-1 is the RFC 6960 default. */ +/** Hash algorithm used to compute OCSP CertID fields. RFC 5019 §2.1.1 requires SHA-1 for the lightweight OCSP profile; RFC 6960 defines no default. */ export type OcspHashAlgorithm = 'SHA-1' | 'SHA-256'; /** PEM string, DER bytes, or already-parsed certificate. */ export type OcspCertificateSource = string | Uint8Array | ParsedCertificate; @@ -1918,7 +1918,7 @@ function prepareOcspNameCompareString(value: string): string | undefined { return normalized.toLowerCase().trim().replace(/\s+/gu, ' '); } -/** Maps an X.500 attribute type OID to its friendly key name for responder name parsing. */ +/** Maps a directory attribute type OID (X.520 `id-at` arc plus the legacy PKCS #9 emailAddress) to its friendly key name for responder name parsing. */ function responderNameKeyFromOid(oid: string): ParsedNameAttribute['key'] { switch (oid) { case OIDS.commonName: diff --git a/src/verify/identity.ts b/src/verify/identity.ts index 80ceb0ef..52a50d25 100644 --- a/src/verify/identity.ts +++ b/src/verify/identity.ts @@ -1,5 +1,6 @@ /** - * Service-identity matching (RFC 6125 / RFC 9525). + * Service-identity matching (RFC 9525), with opt-in CN fallback from the + * obsoleted RFC 6125 §6.4.4. * * Compares a reference identifier (hostname, IP, URI, SRV name) against the * presented identifiers in a certificate's SAN extension, with optional @@ -24,6 +25,7 @@ export interface DnsServiceIdentityInput { /** * When `true`, falls back to the subject CN if the SAN extension has no * dns/uri/srv entries. Suppressed when any supported SAN type is present. + * RFC 9525 §4.1 forbids identifying a service by the Common Name RDN. * @default false */ readonly allowCommonNameFallback?: boolean; diff --git a/src/verify/policy.ts b/src/verify/policy.ts index 992ced55..b1f0c353 100644 --- a/src/verify/policy.ts +++ b/src/verify/policy.ts @@ -41,6 +41,11 @@ export interface ConstrainedPolicy { export interface PolicyValidationOutcome { /** Policies valid under the authority's (CA chain) constraints alone. */ readonly authorityConstrainedPolicies: readonly ConstrainedPolicy[]; - /** Policies that also satisfy the caller's {@linkcode PolicyValidationInput.initialPolicySet}. */ + /** + * Policies from {@linkcode PolicyValidationInput.initialPolicySet} the chain + * establishes, per RFC 9618 §5.5 step (g)(5)-(6). Includes OIDs covered only + * by an authority-constrained anyPolicy, so this is not necessarily a subset + * of {@linkcode authorityConstrainedPolicies}. + */ readonly userConstrainedPolicies: readonly ConstrainedPolicy[]; } diff --git a/src/x509/extensions.ts b/src/x509/extensions.ts index 8d4a77b1..32a06672 100644 --- a/src/x509/extensions.ts +++ b/src/x509/extensions.ts @@ -122,7 +122,7 @@ export type SubjectAltName = | { /** Email address (rfc822Name [1]). */ readonly type: 'email'; - /** RFC 822 mailbox, e.g. `"admin@example.com"`. */ + /** RFC 2821 §4.1.2 Mailbox (`Local-part@Domain`), e.g. `"admin@example.com"`. */ readonly value: string; } | { @@ -393,11 +393,12 @@ export interface PolicyConstraints { /** * RFC 5280 §4.2.1.14 Inhibit anyPolicy. * - * After `skipCerts` additional certificates in the path, the special - * anyPolicy OID is no longer considered a match. + * After `skipCerts` additional non-self-issued certificates in the path, the + * special anyPolicy OID is no longer considered a match, except when it + * appears in an intermediate self-issued CA certificate. */ export interface InhibitAnyPolicy { - /** Number of additional certificates before anyPolicy stops being valid. */ + /** Number of additional non-self-issued certificates before anyPolicy stops being valid. */ readonly skipCerts: number; } diff --git a/src/x509/name.ts b/src/x509/name.ts index ccb77f55..75997bec 100644 --- a/src/x509/name.ts +++ b/src/x509/name.ts @@ -80,7 +80,7 @@ function throwNameEncoderError(code: NameEncoderErrorCode, message: string): nev } /** - * Union of recognized X.501 attribute type shorthand names. + * Union of recognized distinguished-name attribute type shorthand names. * * Each key maps to an OID + ASN.1 string encoding in `NAME_FIELD_DEFINITIONS`. */ @@ -131,7 +131,7 @@ export interface NameObject { readonly title?: string; /** First / given name (GN). */ readonly givenName?: string; - /** RFC 822 email address. Encoded as IA5String, not UTF-8. */ + /** PKCS #9 emailAddress attribute (RFC 2985 §5.2.1). Encoded as IA5String, not UTF-8. RFC 5280 §4.1.2.6 deprecates it in favour of a subjectAltName rfc822Name. */ readonly emailAddress?: string; } diff --git a/src/x509/parse.ts b/src/x509/parse.ts index bdc91064..bf6334a1 100644 --- a/src/x509/parse.ts +++ b/src/x509/parse.ts @@ -397,7 +397,7 @@ export interface ParsedCertificate, > { - /** PKCS#10 version number (always 1). */ + /** PKCS#10 version, normalized to the v1 ordinal `1`. The encoded CertificationRequestInfo version INTEGER is `0` (RFC 2986 §4.1). */ readonly version: number; /** DER encoding of the CertificationRequestInfo, used for signature verification. */ readonly certificationRequestInfoDer: Uint8Array; diff --git a/test/keys.test.ts b/test/keys.test.ts index de16aed8..b0b110eb 100644 --- a/test/keys.test.ts +++ b/test/keys.test.ts @@ -169,6 +169,14 @@ describe('keys', () => { }), ); expect(await exportPkcs8Der(importedCrOnlyRsa)).toEqual(await exportPkcs8Der(rsa.privateKey)); + // OpenSSL-style encapsulated headers permit no space after the colon. + const noSpaceHeaderPem = encryptedRsaPem + .replace('Proc-Type: ', 'Proc-Type:') + .replace('DEK-Info: ', 'DEK-Info:'); + const importedNoSpaceRsa = unwrap( + await importEncryptedPkcs1Pem(noSpaceHeaderPem, 'secret123', { kind: 'rsa' }), + ); + expect(await exportPkcs8Der(importedNoSpaceRsa)).toEqual(await exportPkcs8Der(rsa.privateKey)); await expectImportFailure( importEncryptedPkcs1Pem(encryptedRsaPem, 'wrong', { kind: 'rsa' }), 'invalid_password', From 40f0a4c4666dad76a7052a7952e274356b5adeac Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Fri, 24 Jul 2026 18:23:45 +0200 Subject: [PATCH 02/11] docs(changelog): link #89 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 741266af..c9beedc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 an encapsulated header with no space after the colon (`DEK-Info:AES-256-CBC,…`). The parser keyed on `': '`, so a conformant no-space header ended the header scan early and folded into the base64 body. + (https://github.com/kjanat/micro509/pull/89) - `importPkcs8Der` accepts a `OneAsymmetricKey` (RFC 5958 §2 / RFC 8410 §7) that carries both `attributes [0]` and `publicKey [1]`. The parser capped at four elements, so a five-element v2 key that OpenSSL and Node WebCrypto both accept From 20dbec13a11455cf53d3f1305b4a5ab6b24f7bee Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 06:04:10 +0200 Subject: [PATCH 03/11] fix: tighten PEM and CMS parsing Reject malformed traditional PEM header names and accept the tagged non-X.509 CertificateChoices CMS permits while rejecting unknown tags. Correct related standards citations and replace the RFC fetch shell snippet with a typed CLI that reports HTTP failures. --- package.json | 2 +- scripts/fetch-rfc.bun.ts | 21 +++++++++++++++++ src/internal/asn1/der.ts | 5 ++-- src/keys/keys.ts | 6 +++++ src/pkcs/pkcs7.ts | 30 ++++++++++++++++++++---- test/helpers.ts | 7 ++++-- test/keys.test.ts | 49 ++++++++++++++++++++++++++++++++++++++++ test/pkcs7.test.ts | 31 +++++++++++++++++++++++++ 8 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 scripts/fetch-rfc.bun.ts diff --git a/package.json b/package.json index d59fcf15..408f86e0 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "prepublishOnly": "[ -n \"${GITHUB_ACTIONS:-}\" ] || { printf '%s\\n' 'manual npm publish blocked; use release workflow for provenance' >&2; exit 1; }", "publish:jsr": "[ -n \"${GITHUB_ACTIONS:-}\" ] || { printf '%s\\n' 'manual JSR publish blocked; use release workflow' >&2; exit 1; }; BIN=\"${BIN:-bun}\"; $BIN x jsr publish", "publish:pkgprnew": "BIN=\"${BIN:-bun}\"; $BIN x pkg-pr-new publish --packageManager='npm,pnpm,bun' --bun --template './examples/vite'", - "rfc": "test -n \"${RFC}\" && curl -fsSLo \"${PWD}/docs/rfc/rfc${RFC}.txt\" \"https://www.rfc-editor.org/rfc/rfc${RFC}.txt\"", + "rfc": "bun scripts/fetch-rfc.bun.ts", "site:build": "run --dir site/.vitepress build", "site:dev": "run --dir site/.vitepress dev", "site:import-maps": "deno run --allow-read --allow-net --allow-write --allow-run scripts/site-import-maps.deno.ts", diff --git a/scripts/fetch-rfc.bun.ts b/scripts/fetch-rfc.bun.ts new file mode 100644 index 00000000..db10f889 --- /dev/null +++ b/scripts/fetch-rfc.bun.ts @@ -0,0 +1,21 @@ +import { arg, CLIError, cli, command } from 'dreamcli'; + +const fetchRfc = command('rfc') + .description('Refresh a vendored RFC text file from the RFC Editor') + .arg('number', arg.number().int().min(1).env('RFC').describe('RFC number, e.g. 822')) + .action(async ({ args, out }) => { + const url = `https://www.rfc-editor.org/rfc/rfc${args.number}.txt`; + out.status(`fetching ${url}`); + const response = await fetch(url); + if (!response.ok) { + throw new CLIError(`rfc${args.number}: ${response.status} ${response.statusText}`, { + code: 'RFC_FETCH_FAILED', + suggest: 'Check the number against https://www.rfc-editor.org/', + }); + } + const destination = `docs/rfc/rfc${args.number}.txt`; + await Bun.write(destination, await response.bytes()); + out.log(destination); + }); + +cli('rfc').default(fetchRfc).run(); diff --git a/src/internal/asn1/der.ts b/src/internal/asn1/der.ts index bb9f8460..e1b471b3 100644 --- a/src/internal/asn1/der.ts +++ b/src/internal/asn1/der.ts @@ -275,8 +275,9 @@ function encodeBase128(value: bigint): number[] { /** * Encodes a dotted-decimal OID string as a DER OBJECT IDENTIFIER (tag `0x06`). * - * Validates arc constraints: the root arc must be 0–2 (X.660 Annex A), and for - * roots 0 and 1 the second arc must be < 40 (the X.690 §8.19.4 `(X*40)+Y` packing).\ + * Validates arc constraints per X.660 §7.6: the root arc must be 0–2, and under + * roots 0 and 1 the second arc must be 0–39. X.690 §8.19.4 defines the `(X*40)+Y` + * packing of the first two arcs into one subidentifier.\ * Sub-identifiers are encoded with base-128 continuation. */ export function objectIdentifier(oid: string): Uint8Array { diff --git a/src/keys/keys.ts b/src/keys/keys.ts index a618f3d3..e55f1168 100644 --- a/src/keys/keys.ts +++ b/src/keys/keys.ts @@ -2020,6 +2020,9 @@ function opensslBytesToKey(password: string, salt: Uint8Array, length: number): return out; } +/** RFC 822 §3.2: `field-name = 1*`. */ +const RFC822_FIELD_NAME = /^[\x21-\x39\x3b-\x7e]+$/; + /** Parse a PEM block into its label, OpenSSL-style headers, and base64 body. */ function parseTraditionalPem(pem: string): { /** PEM type label between `BEGIN` and `END` markers. */ @@ -2061,6 +2064,9 @@ function parseTraditionalPem(pem: string): { break; } const headerName = line.slice(0, delimiter); + if (!RFC822_FIELD_NAME.test(headerName)) { + throw new Error(`Invalid PEM header name: ${headerName}`); + } if (headers.has(headerName)) { throw new Error(`Duplicate PEM header: ${headerName}`); } diff --git a/src/pkcs/pkcs7.ts b/src/pkcs/pkcs7.ts index 9baca355..ade7fe73 100644 --- a/src/pkcs/pkcs7.ts +++ b/src/pkcs/pkcs7.ts @@ -3,8 +3,10 @@ * * Creates degenerate (signature-less) certificate bags, parses RFC 5652 * SignedData (and the RFC 2315 form whose contentInfo content is an OCTET - * STRING and whose certificates are X.509), and verifies signer signatures - * including signed-attribute flows. + * STRING), and verifies signer signatures including signed-attribute flows. + * A CertificateSet may carry the RFC 5652 §10.2.2 attribute-certificate and + * other-format alternatives; those are skipped and only X.509 certificates are + * returned. * * @module */ @@ -887,7 +889,8 @@ function signerHasNamedCurve(algorithm: KeyAlgorithm): algorithm is EcKeyAlgorit /** * Resolves the content-digest hash and its OID for a signer key. * - * Curve pairing follows RFC 5753 §8: P-256/RSA-SHA256 → SHA-256, P-384 → SHA-384, P-521 → SHA-512. + * ECDSA curve pairing follows RFC 5753 §8: P-256 → SHA-256, P-384 → SHA-384, + * P-521 → SHA-512. RSA uses the hash bound to the key. * Digest OIDs are from RFC 5754 §2. * Ed25519 uses SHA-512 for the messageDigest attribute, per RFC 8419. */ @@ -952,7 +955,20 @@ function buildSignedAttributes( return { setForSigning, implicitForEmit }; } -/** Parses the IMPLICIT [0] certificate set from a SignedData structure. */ +/** + * RFC 5652 §10.2.2 CertificateChoices: `extendedCertificate [0]`, `v1AttrCert [1]`, + * `v2AttrCert [2]`, and `other [3]`, each IMPLICIT over a SEQUENCE. + */ +const NON_X509_CERTIFICATE_CHOICE_TAGS: ReadonlySet = new Set([0xa0, 0xa1, 0xa2, 0xa3]); + +/** + * Parses the IMPLICIT [0] certificate set from a SignedData structure. + * + * RFC 5652 §10.2.2 encodes an X.509 certificate as a bare SEQUENCE and every other + * CertificateChoices alternative behind a context tag; the tagged + * attribute-certificate and other-format entries are skipped. Any other tag is not + * a CertificateChoices alternative at all. + */ function parseCertificateSet( source: Uint8Array, certificates: ReturnType | undefined, @@ -964,7 +980,11 @@ function parseCertificateSet( let offset = certificates.start; while (offset < certificates.end) { const element = readElement(source, offset); - parsed.push(parseCertificateDerOrThrow(source.slice(offset, element.end))); + if (element.tag === 0x30) { + parsed.push(parseCertificateDerOrThrow(source.slice(offset, element.end))); + } else if (!NON_X509_CERTIFICATE_CHOICE_TAGS.has(element.tag)) { + throw new Error(`Unsupported CertificateChoices tag: ${element.tag}`); + } offset = element.end; } return parsed; diff --git a/test/helpers.ts b/test/helpers.ts index adebfe6c..9fac555c 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -604,7 +604,10 @@ function toPemBlock(label: string, der: Uint8Array): string { return `-----BEGIN ${label}-----\n${lines.join('\n')}\n-----END ${label}-----\n`; } -export function createSyntheticPkcs7SignedData(signer: ParsedCertificate): Uint8Array { +export function createSyntheticPkcs7SignedData( + signer: ParsedCertificate, + extraCertificateChoices: readonly Uint8Array[] = [], +): Uint8Array { const signerInfo = sequence([ integerFromNumber(1), sequence([hexToBytes(signer.issuer.derHex), integer(hexToBytes(signer.serialNumberHex))]), @@ -616,7 +619,7 @@ export function createSyntheticPkcs7SignedData(signer: ParsedCertificate): Uint8 integerFromNumber(1), setOf([sequence([objectIdentifier(OIDS.sha256), nullValue()])]), sequence([objectIdentifier(OIDS.pkcs7Data)]), - explicitContext(0, signer.der), + explicitContext(0, concatBytes([signer.der, ...extraCertificateChoices])), setOf([signerInfo]), ]); return sequence([objectIdentifier(OIDS.pkcs7SignedData), explicitContext(0, signedData)]); diff --git a/test/keys.test.ts b/test/keys.test.ts index 6b4f31f8..34ef90f7 100644 --- a/test/keys.test.ts +++ b/test/keys.test.ts @@ -25,9 +25,11 @@ import { exportSpkiPem, generateKeyPair, importEncryptedPkcs1Pem, + importEncryptedPkcs1PemOrThrow, importEncryptedPkcs8Der, importEncryptedPkcs8Pem, importEncryptedSec1Pem, + importEncryptedSec1PemOrThrow, importPkcs1Der, importPkcs1Pem, importPkcs8Base64, @@ -71,6 +73,28 @@ async function expectImportFailure( if (messagePart !== undefined) expect(result.error.message).toContain(messagePart); } +/** Assert a throwing-variant promise rejected with a message containing `messagePart`. */ +async function expectRejection(pending: Promise, messagePart: string): Promise { + try { + await pending; + } catch (error) { + expect(error instanceof Error ? error.message : String(error)).toContain(messagePart); + return; + } + throw new Error(`expected a rejection containing '${messagePart}', but it resolved`); +} + +/** + * Header lines RFC 822 §3.2 excludes from `field-name`: empty, embedded SPACE, + * an embedded CTL, and non-ASCII. + */ +const MALFORMED_PEM_HEADER_NAMES = [ + ':junk', + 'Bad Name:thing', + 'Bad\u0001Name:thing', + 'Ünicode:thing', +] as const; + /** Encrypt arbitrary DER as a traditional RSA PEM fixture for structural-error tests. */ async function encryptTraditionalRsaFixture(der: Uint8Array, password: string): Promise { const iv = Uint8Array.from({ length: 16 }, (_, index) => index); @@ -297,6 +321,17 @@ describe('keys', () => { await importEncryptedPkcs1Pem(noSpaceHeaderPem, 'secret123', { kind: 'rsa' }), ); expect(await exportPkcs8Der(importedNoSpaceRsa)).toEqual(await exportPkcs8Der(rsa.privateKey)); + for (const badName of MALFORMED_PEM_HEADER_NAMES) { + const badHeaderPem = encryptedRsaPem.replace('Proc-Type: ', `${badName}\nProc-Type: `); + await expectImportFailure( + importEncryptedPkcs1Pem(badHeaderPem, 'secret123', { kind: 'rsa' }), + 'malformed', + ); + await expectRejection( + importEncryptedPkcs1PemOrThrow(badHeaderPem, 'secret123', { kind: 'rsa' }), + 'Invalid PEM header name', + ); + } await expectImportFailure( importEncryptedPkcs1Pem(encryptedRsaPem, 'wrong', { kind: 'rsa' }), 'invalid_password', @@ -314,6 +349,20 @@ describe('keys', () => { }), ); expect(await exportPkcs8Der(importedEc)).toEqual(await exportPkcs8Der(ec.privateKey)); + for (const badName of MALFORMED_PEM_HEADER_NAMES) { + const badHeaderPem = encryptedEcPem.replace('Proc-Type: ', `${badName}\nProc-Type: `); + await expectImportFailure( + importEncryptedSec1Pem(badHeaderPem, 'secret123', { kind: 'ecdsa', curve: 'P-256' }), + 'malformed', + ); + await expectRejection( + importEncryptedSec1PemOrThrow(badHeaderPem, 'secret123', { + kind: 'ecdsa', + curve: 'P-256', + }), + 'Invalid PEM header name', + ); + } }); it('roundtrips keys through PEM, base64, and JWK imports', async () => { diff --git a/test/pkcs7.test.ts b/test/pkcs7.test.ts index 135c54a4..45cca2d9 100644 --- a/test/pkcs7.test.ts +++ b/test/pkcs7.test.ts @@ -136,6 +136,37 @@ describe('pkcs7', () => { }); }); + it('skips non-X.509 CertificateChoices alternatives (RFC 5652 §10.2.2)', async () => { + const signer = await createSelfSignedCertificate({ + subject: { commonName: 'CMS Signer' }, + }); + const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); + // v2AttrCert [2]: an attribute certificate is not an X.509 certificate, so it + // is skipped rather than failing the whole SignedData parse. + const attributeCertificate = tlv(0xa2, sequence([integerFromNumber(1)])); + const parsed = parsePkcs7SignedDataDer( + createSyntheticPkcs7SignedData(parsedSigner, [attributeCertificate]), + ); + expect(parsed.ok).toBe(true); + if (!parsed.ok) throw new Error('unreachable'); + expect(parsed.value.certificates).toHaveLength(1); + expect(parsed.value.certificates[0]?.subject.values.commonName).toBe('CMS Signer'); + }); + + it.each([ + ['an INTEGER', integerFromNumber(1)], + ['an unknown context tag [4]', tlv(0xa4, sequence([integerFromNumber(1)]))], + ])('rejects %s in the CertificateSet (RFC 5652 §10.2.2)', async (_label, element) => { + const signer = await createSelfSignedCertificate({ + subject: { commonName: 'CMS Signer' }, + }); + const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); + const parsed = parsePkcs7SignedDataDer(createSyntheticPkcs7SignedData(parsedSigner, [element])); + expect(parsed.ok).toBe(false); + if (parsed.ok) throw new Error('unreachable'); + expect(parsed.error.code).toBe('malformed'); + }); + // ----------------------------------------------------------------------- // Parse error paths // ----------------------------------------------------------------------- From abfbb6ed52d9c2ebc172b807176fb933abb7cd6e Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 06:13:35 +0200 Subject: [PATCH 04/11] feat(pkcs): preserve CMS certificate choices Expose every RFC 5652 CertificateChoices alternative instead of silently dropping non-X.509 entries. Keep tagged DER for round-tripping and decode the other-format OID so callers can distinguish mixed certificate sets. --- CHANGELOG.md | 12 ++++ src/index.ts | 1 + src/pkcs/index.ts | 1 + src/pkcs/pkcs7.ts | 122 +++++++++++++++++++++++++++------- test/pkcs7-signeddata.test.ts | 6 +- test/pkcs7.test.ts | 58 ++++++++++++---- 6 files changed, 161 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ff88b98..aa9b8e40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `ParsedPkcs7SignedData.certificates: readonly ParsedCertificate[]` becomes + `certificateChoices: readonly ParsedCertificateChoice[]`, modelling RFC 5652 + §10.2.2 CertificateChoices as a discriminated union rather than discarding + four of its five alternatives. `certificate` carries the decoded X.509; + `extendedCertificate` (`[0]`, obsolete), `attributeCertificateV1` (`[1]`, + obsolete), `attributeCertificateV2` (`[2]`), and `other` (`[3]`, with its + `otherCertFormat` OID decoded) keep their DER including the context tag, so a + CertificateSet round-trips and a caller can tell an X.509-only bag from a + mixed one. A certificate set entry whose tag is none of these is rejected as + `malformed`; previously any non-SEQUENCE element was silently dropped. + `parsePkcs7CertBagDer` and `parsePkcs7CertBagPem` still return + `readonly ParsedCertificate[]`, now the X.509 projection of the set. - Builder input-validation now throws a `ResultError` carrying a stable machine-readable `code` rather than a bare `Error`. `createCertificate`, the `encode*` extension helpers, distinguished-name encoding, and CRL/IDP encoding diff --git a/src/index.ts b/src/index.ts index e9a9775d..f29891a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -184,6 +184,7 @@ export type { CreatePkcs7SignedDataFailure, CreatePkcs7SignedDataInput, CreatePkcs7SignedDataResult, + ParsedCertificateChoice, ParsedPfx, ParsedPfxAttribute, ParsedPfxBag, diff --git a/src/pkcs/index.ts b/src/pkcs/index.ts index d2199035..27459e72 100644 --- a/src/pkcs/index.ts +++ b/src/pkcs/index.ts @@ -39,6 +39,7 @@ export type { CreatePkcs7SignedDataFailure, CreatePkcs7SignedDataInput, CreatePkcs7SignedDataResult, + ParsedCertificateChoice, ParsedPkcs7SignedData, ParsedPkcs7SignerInfo, ParsedPkcs7SignerInfoBase, diff --git a/src/pkcs/pkcs7.ts b/src/pkcs/pkcs7.ts index ade7fe73..8c1a272e 100644 --- a/src/pkcs/pkcs7.ts +++ b/src/pkcs/pkcs7.ts @@ -4,9 +4,8 @@ * Creates degenerate (signature-less) certificate bags, parses RFC 5652 * SignedData (and the RFC 2315 form whose contentInfo content is an OCTET * STRING), and verifies signer signatures including signed-attribute flows. - * A CertificateSet may carry the RFC 5652 §10.2.2 attribute-certificate and - * other-format alternatives; those are skipped and only X.509 certificates are - * returned. + * A CertificateSet is decoded as RFC 5652 §10.2.2 CertificateChoices, so an + * attribute certificate or other-format entry is preserved rather than dropped. * * @module */ @@ -133,6 +132,48 @@ interface ParsedSignedAttributeFields { contentTypeOid?: string; } +/** + * One RFC 5652 §10.2.2 CertificateChoices alternative. + * + * X.509 is the only alternative this library decodes. The rest keep their DER, + * including the context tag, so a CertificateSet round-trips and a caller can + * tell an X.509-only bag from one carrying attribute certificates. RFC 5652 + * marks `extendedCertificate` and `attributeCertificateV1` obsolete. + */ +export type ParsedCertificateChoice = + | { + /** X.509 certificate (untagged `Certificate`). */ + readonly type: 'certificate'; + /** The decoded certificate. */ + readonly certificate: ParsedCertificate; + } + | { + /** PKCS #6 extended certificate (`[0]`), obsolete. */ + readonly type: 'extendedCertificate'; + /** Raw DER of the element, including its context tag. */ + readonly der: Uint8Array; + } + | { + /** Version 1 X.509 attribute certificate (`[1]`), obsolete. */ + readonly type: 'attributeCertificateV1'; + /** Raw DER of the element, including its context tag. */ + readonly der: Uint8Array; + } + | { + /** Version 2 X.509 attribute certificate (`[2]`). */ + readonly type: 'attributeCertificateV2'; + /** Raw DER of the element, including its context tag. */ + readonly der: Uint8Array; + } + | { + /** Any other certificate format (`[3] OtherCertificateFormat`). */ + readonly type: 'other'; + /** `otherCertFormat` OID identifying the format. */ + readonly formatOid: string; + /** Raw DER of the element, including its context tag. */ + readonly der: Uint8Array; + }; + /** Decoded PKCS#7 SignedData content, including certificates and signer info. */ export interface ParsedPkcs7SignedData { /** Original DER bytes when this object came from {@linkcode parsePkcs7SignedDataDer} or PEM parsing. */ @@ -149,8 +190,8 @@ export interface ParsedPkcs7SignedData { readonly encapsulatedContentTypeOid: string; /** Raw encapsulated content bytes. Absent in degenerate (certs-only) bags. */ readonly encapsulatedContent?: Uint8Array; - /** Certificates included in the SignedData certificate set. */ - readonly certificates: readonly ParsedCertificate[]; + /** RFC 5652 §10.2.2 CertificateChoices entries from the SignedData certificate set. */ + readonly certificateChoices: readonly ParsedCertificateChoice[]; /** Decoded signer info entries. Empty for degenerate cert bags. */ readonly signerInfos: readonly ParsedPkcs7SignerInfo[]; } @@ -572,7 +613,7 @@ export function parsePkcs7CertBagDer(der: Uint8Array): ParsePkcs7CertBagResult { if (!result.ok) { return result; } - return { ok: true, value: result.value.certificates }; + return { ok: true, value: x509CertificatesOf(result.value.certificateChoices) }; } /** Parses a PEM-armored PKCS#7 cert bag. Expects exactly one `PKCS7` PEM block. */ @@ -659,7 +700,7 @@ export function parsePkcs7SignedDataDer(der: Uint8Array): ParsePkcs7SignedDataRe : { encapsulatedContent: extractEncapsulatedContent(encapDer, encapContent), }), - certificates: parseCertificateSet(der, optionalFields.value.certificates), + certificateChoices: parseCertificateSet(der, optionalFields.value.certificates), signerInfos: parseSignerInfos(der, signerInfos), }, }; @@ -783,7 +824,7 @@ async function verifyPkcs7SignerInfo( signerInfo: ParsedPkcs7SignerInfo, content: Uint8Array, ): Promise<{ readonly ok: true } | Extract> { - const signer = parsed.certificates.find((certificate) => + const signer = x509CertificatesOf(parsed.certificateChoices).find((certificate) => signerIdentifierMatches(certificate, signerInfo), ); if (signer === undefined) { @@ -955,36 +996,69 @@ function buildSignedAttributes( return { setForSigning, implicitForEmit }; } +/** The X.509 subset of a decoded CertificateSet. */ +function x509CertificatesOf( + choices: readonly ParsedCertificateChoice[], +): readonly ParsedCertificate[] { + return choices.flatMap((choice) => (choice.type === 'certificate' ? [choice.certificate] : [])); +} + /** - * RFC 5652 §10.2.2 CertificateChoices: `extendedCertificate [0]`, `v1AttrCert [1]`, - * `v2AttrCert [2]`, and `other [3]`, each IMPLICIT over a SEQUENCE. + * `otherCertFormat` from an `other [3] IMPLICIT OtherCertificateFormat` entry. + * + * The IMPLICIT tag replaces the SEQUENCE tag, so the OID and the `ANY DEFINED BY` + * value are direct children of the `[3]` element. */ -const NON_X509_CERTIFICATE_CHOICE_TAGS: ReadonlySet = new Set([0xa0, 0xa1, 0xa2, 0xa3]); +function parseOtherCertificateFormatOid(source: Uint8Array, element: DerElement): string { + const formatOid = requireElement(childrenOf(source, element)[0], 'otherCertFormat'); + if (formatOid.tag !== 0x06) { + throw new Error('otherCertFormat must be an OBJECT IDENTIFIER'); + } + return decodeObjectIdentifier(formatOid.value); +} + +/** Decodes one RFC 5652 §10.2.2 CertificateChoices alternative. */ +function parseCertificateChoice( + source: Uint8Array, + element: DerElement, + der: Uint8Array, +): ParsedCertificateChoice { + switch (element.tag) { + case 0x30: + return { type: 'certificate', certificate: parseCertificateDerOrThrow(der) }; + case 0xa0: + return { type: 'extendedCertificate', der }; + case 0xa1: + return { type: 'attributeCertificateV1', der }; + case 0xa2: + return { type: 'attributeCertificateV2', der }; + case 0xa3: + return { + type: 'other', + formatOid: parseOtherCertificateFormatOid(source, element), + der, + }; + default: + throw new Error(`Unsupported CertificateChoices tag: ${element.tag}`); + } +} /** - * Parses the IMPLICIT [0] certificate set from a SignedData structure. - * - * RFC 5652 §10.2.2 encodes an X.509 certificate as a bare SEQUENCE and every other - * CertificateChoices alternative behind a context tag; the tagged - * attribute-certificate and other-format entries are skipped. Any other tag is not - * a CertificateChoices alternative at all. + * Parses the IMPLICIT [0] certificate set from a SignedData structure as + * RFC 5652 §10.2.3 `CertificateSet ::= SET OF CertificateChoices`. */ function parseCertificateSet( source: Uint8Array, certificates: ReturnType | undefined, -): readonly ParsedCertificate[] { +): readonly ParsedCertificateChoice[] { if (certificates === undefined || certificates.tag !== 0xa0) { return []; } - const parsed: ParsedCertificate[] = []; + const parsed: ParsedCertificateChoice[] = []; let offset = certificates.start; while (offset < certificates.end) { const element = readElement(source, offset); - if (element.tag === 0x30) { - parsed.push(parseCertificateDerOrThrow(source.slice(offset, element.end))); - } else if (!NON_X509_CERTIFICATE_CHOICE_TAGS.has(element.tag)) { - throw new Error(`Unsupported CertificateChoices tag: ${element.tag}`); - } + parsed.push(parseCertificateChoice(source, element, source.slice(offset, element.end))); offset = element.end; } return parsed; diff --git a/test/pkcs7-signeddata.test.ts b/test/pkcs7-signeddata.test.ts index 1c424f8f..b8c0a800 100644 --- a/test/pkcs7-signeddata.test.ts +++ b/test/pkcs7-signeddata.test.ts @@ -100,7 +100,7 @@ describe('createPkcs7SignedData', () => { expect(parsed.ok).toBe(true); if (!parsed.ok) throw new Error(parsed.error.code); expect(parsed.value.version).toBe(1); - expect(parsed.value.certificates).toHaveLength(1); + expect(parsed.value.certificateChoices).toHaveLength(1); const verified = await verifyPkcs7SignedData(parsed.value); expect(verified.ok).toBe(true); @@ -143,7 +143,7 @@ describe('createPkcs7SignedData', () => { expect(result.ok).toBe(true); if (!result.ok) throw new Error(result.error.code); expect(result.value.signerInfos).toHaveLength(2); - expect(result.value.certificates).toHaveLength(2); + expect(result.value.certificateChoices).toHaveLength(2); }); it('embeds additional certificates without duplicating the signer', async () => { @@ -164,7 +164,7 @@ describe('createPkcs7SignedData', () => { expect(result.ok).toBe(true); if (!result.ok) throw new Error(result.error.code); // signer + CA, deduplicated (signer also passed via additionalCertificates). - expect(result.value.certificates).toHaveLength(2); + expect(result.value.certificateChoices).toHaveLength(2); }); it('returns no_signers when no signers are provided', async () => { diff --git a/test/pkcs7.test.ts b/test/pkcs7.test.ts index 45cca2d9..53442ab7 100644 --- a/test/pkcs7.test.ts +++ b/test/pkcs7.test.ts @@ -124,7 +124,7 @@ describe('pkcs7', () => { expect(parsed.ok).toBe(true); if (!parsed.ok) throw new Error('unreachable'); expect(parsed.value.contentTypeOid).toBe(OIDS.pkcs7SignedData); - expect(parsed.value.certificates).toHaveLength(1); + expect(parsed.value.certificateChoices).toHaveLength(1); expect(parsed.value.digestAlgorithmNames).toEqual(['SHA-256']); expect(parsed.value.signerInfos[0]).toMatchObject({ version: 1, @@ -136,21 +136,55 @@ describe('pkcs7', () => { }); }); - it('skips non-X.509 CertificateChoices alternatives (RFC 5652 §10.2.2)', async () => { + it.each([ + ['extendedCertificate', 0xa0], + ['attributeCertificateV1', 0xa1], + ['attributeCertificateV2', 0xa2], + ] as const)('preserves a %s CertificateChoices entry (RFC 5652 §10.2.2)', async (type, tag) => { const signer = await createSelfSignedCertificate({ subject: { commonName: 'CMS Signer' }, }); const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); - // v2AttrCert [2]: an attribute certificate is not an X.509 certificate, so it - // is skipped rather than failing the whole SignedData parse. - const attributeCertificate = tlv(0xa2, sequence([integerFromNumber(1)])); - const parsed = parsePkcs7SignedDataDer( - createSyntheticPkcs7SignedData(parsedSigner, [attributeCertificate]), - ); + const other = tlv(tag, sequence([integerFromNumber(1)])); + const parsed = parsePkcs7SignedDataDer(createSyntheticPkcs7SignedData(parsedSigner, [other])); + expect(parsed.ok).toBe(true); + if (!parsed.ok) throw new Error('unreachable'); + expect(parsed.value.certificateChoices.map((choice) => choice.type)).toEqual([ + 'certificate', + type, + ]); + const [first, second] = parsed.value.certificateChoices; + if (first?.type !== 'certificate') throw new Error('unreachable'); + expect(first.certificate.subject.values.commonName).toBe('CMS Signer'); + if (second === undefined || second.type === 'certificate') throw new Error('unreachable'); + expect(second.der).toEqual(other); + }); + + it('decodes the otherCertFormat OID of an other [3] entry (RFC 5652 §10.2.2)', async () => { + const signer = await createSelfSignedCertificate({ + subject: { commonName: 'CMS Signer' }, + }); + const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); + // [3] IMPLICIT OtherCertificateFormat, so the OID and the ANY value are + // direct children of the tag rather than nested in a SEQUENCE. + const other = tlv(0xa3, concatBytes([objectIdentifier('1.2.3.4'), integerFromNumber(1)])); + const parsed = parsePkcs7SignedDataDer(createSyntheticPkcs7SignedData(parsedSigner, [other])); expect(parsed.ok).toBe(true); if (!parsed.ok) throw new Error('unreachable'); - expect(parsed.value.certificates).toHaveLength(1); - expect(parsed.value.certificates[0]?.subject.values.commonName).toBe('CMS Signer'); + const [, second] = parsed.value.certificateChoices; + expect(second).toMatchObject({ type: 'other', formatOid: '1.2.3.4' }); + }); + + it('rejects an other [3] entry whose first element is not an OID', async () => { + const signer = await createSelfSignedCertificate({ + subject: { commonName: 'CMS Signer' }, + }); + const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); + const other = tlv(0xa3, concatBytes([integerFromNumber(1), integerFromNumber(2)])); + const parsed = parsePkcs7SignedDataDer(createSyntheticPkcs7SignedData(parsedSigner, [other])); + expect(parsed.ok).toBe(false); + if (parsed.ok) throw new Error('unreachable'); + expect(parsed.error.code).toBe('malformed'); }); it.each([ @@ -1010,7 +1044,7 @@ describe('pkcs7', () => { const result = parsePkcs7SignedDataDer(der); expect(result.ok).toBe(true); if (!result.ok) throw new Error('unreachable'); - expect(result.value.certificates).toHaveLength(0); + expect(result.value.certificateChoices).toHaveLength(0); }); it('parsePkcs7SignedDataDer rejects duplicate certificates fields', async () => { @@ -1130,7 +1164,7 @@ describe('pkcs7', () => { const result = parsePkcs7SignedDataDer(der); expect(result.ok).toBe(true); if (!result.ok) throw new Error('unreachable'); - expect(result.value.certificates).toHaveLength(1); + expect(result.value.certificateChoices).toHaveLength(1); }); it('createPkcs7CertBag rejects a PEM source with no certificate blocks', () => { From 13d31ea931df143807645a2669e98b9037e706e5 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 06:36:43 +0200 Subject: [PATCH 05/11] refactor(types): model ASN.1 choices explicitly Represent CMS signer identifiers, CRL distribution-point names, and OCSP statuses as discriminated unions. Callers can narrow each wire choice without handling impossible combinations of optional fields. --- src/index.ts | 3 + src/internal/x509/extension-errors.ts | 2 - src/pkcs/index.ts | 1 + src/pkcs/pkcs7.ts | 59 +++++----- src/revocation/crl.ts | 83 +++++--------- src/revocation/index.ts | 2 + src/revocation/ocsp.ts | 84 +++++++++----- src/x509/extensions.ts | 87 ++++++-------- src/x509/parse.ts | 30 +++-- test/certificate.test.ts | 9 +- test/chain-revocation.test.ts | 1 + test/crl.test.ts | 157 +++++++++++++++++--------- test/csr.test.ts | 2 + test/extension-registry.test.ts | 4 + test/internals.test.ts | 36 +++--- test/malformed-der.test.ts | 7 +- test/ocsp.test.ts | 23 ++-- test/pkcs7.test.ts | 47 +------- test/revocation.test.ts | 10 ++ test/root-barrel.types.ts | 2 +- tsconfig.other.json | 1 - tsconfig.src.json | 1 - 22 files changed, 346 insertions(+), 305 deletions(-) diff --git a/src/index.ts b/src/index.ts index f29891a5..5a914f0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -193,6 +193,7 @@ export type { ParsedPkcs7SignerInfo, ParsedPkcs7SignerInfoBase, ParsedPkcs12MacData, + ParsedSignerIdentifier, ParsePfxErrorCode, ParsePfxFailure, ParsePfxOptions, @@ -266,6 +267,7 @@ export type { ConfiguredOcspResponder, ConfiguredOcspResponderCertificate, CreateCertificateRevocationListInput, + CreateOcspCertStatusInput, CreateOcspRequestInput, CreateOcspRequestItemInput, CreateOcspResponseInput, @@ -296,6 +298,7 @@ export type { ParsedCertificateRevocationList, ParsedIssuingDistributionPoint, ParsedOcspCertId, + ParsedOcspCertStatus, ParsedOcspRequest, ParsedOcspResponderId, ParsedOcspResponse, diff --git a/src/internal/x509/extension-errors.ts b/src/internal/x509/extension-errors.ts index 45bba579..0e31bf09 100644 --- a/src/internal/x509/extension-errors.ts +++ b/src/internal/x509/extension-errors.ts @@ -23,8 +23,6 @@ export type ExtensionEncoderErrorCode = | 'distribution_point_crl_issuer_not_directory_name' | 'distribution_point_empty' | 'distribution_point_full_name_empty' - | 'distribution_point_name_conflict' - | 'distribution_point_name_empty' | 'distribution_point_relative_name_multiple_crl_issuers' | 'duplicate_extension_oid' | 'duplicate_policy_oid' diff --git a/src/pkcs/index.ts b/src/pkcs/index.ts index 27459e72..11c21ab4 100644 --- a/src/pkcs/index.ts +++ b/src/pkcs/index.ts @@ -43,6 +43,7 @@ export type { ParsedPkcs7SignedData, ParsedPkcs7SignerInfo, ParsedPkcs7SignerInfoBase, + ParsedSignerIdentifier, ParsePkcs7CertBagResult, ParsePkcs7ErrorCode, ParsePkcs7Failure, diff --git a/src/pkcs/pkcs7.ts b/src/pkcs/pkcs7.ts index 8c1a272e..5a5e514b 100644 --- a/src/pkcs/pkcs7.ts +++ b/src/pkcs/pkcs7.ts @@ -76,16 +76,32 @@ export interface Pkcs7CertBagMaterial { readonly base64: string; } +/** + * RFC 5652 §5.3 `SignerIdentifier ::= CHOICE { issuerAndSerialNumber, + * subjectKeyIdentifier [0] }`, which locates the signer's certificate. + */ +export type ParsedSignerIdentifier = + | { + /** Issuer name plus serial number. */ + readonly type: 'issuerAndSerialNumber'; + /** Parsed issuer distinguished name. */ + readonly issuer: ParsedName; + /** Hex-encoded certificate serial number. */ + readonly serialNumberHex: string; + } + | { + /** SubjectKeyIdentifier (`[0]`). */ + readonly type: 'subjectKeyIdentifier'; + /** Hex-encoded SubjectKeyIdentifier of the signer certificate. */ + readonly subjectKeyIdentifier: string; + }; + /** Fields shared by every decoded SignerInfo, regardless of signed-attribute presence. */ export interface ParsedPkcs7SignerInfoBase { /** CMS SignerInfo version (typically 1 for issuerAndSerialNumber). */ readonly version: number; - /** Parsed issuer distinguished name, if present (issuerAndSerialNumber signer identifier). */ - readonly issuer?: ParsedName; - /** Hex-encoded serial number used to locate the signer certificate, if present. */ - readonly serialNumberHex?: string; - /** Hex-encoded SubjectKeyIdentifier used to locate the signer certificate, if present. */ - readonly subjectKeyIdentifier?: string; + /** Which of the two RFC 5652 §5.3 SignerIdentifier alternatives this SignerInfo uses. */ + readonly signerIdentifier: ParsedSignerIdentifier; /** OID of the digest algorithm used to hash the content. */ readonly digestAlgorithmOid: string; /** Human-readable digest algorithm name (e.g. `"SHA-256"`). */ @@ -1134,16 +1150,9 @@ function parseSignerInfo(source: Uint8Array, signerInfo: DerElement): ParsedPkcs requireElement(signatureAlgorithmChildren[0], 'signature algorithm OID').value, ); const signatureAlgorithmParams = signatureAlgorithmChildren[1]; - const parsedSid = parseSignerIdentifier(signerDer.slice(sid.start - sid.headerLength, sid.end)); return { version: decodeIntegerNumber(version.value), - ...(parsedSid.issuer === undefined ? {} : { issuer: parsedSid.issuer }), - ...(parsedSid.serialNumberHex === undefined - ? {} - : { serialNumberHex: parsedSid.serialNumberHex }), - ...(parsedSid.subjectKeyIdentifier === undefined - ? {} - : { subjectKeyIdentifier: parsedSid.subjectKeyIdentifier }), + signerIdentifier: parseSignerIdentifier(signerDer.slice(sid.start - sid.headerLength, sid.end)), digestAlgorithmOid, digestAlgorithmName: describeHashAlgorithm(digestAlgorithmOid), signatureAlgorithmOid, @@ -1205,11 +1214,7 @@ function extractEncapsulatedContent( } /** Extracts issuer Name and serial number from an issuerAndSerialNumber SEQUENCE, or subjectKeyIdentifier from [0] IMPLICIT. */ -function parseSignerIdentifier(der: Uint8Array): { - readonly issuer?: ParsedName; - readonly serialNumberHex?: string; - readonly subjectKeyIdentifier?: string; -} { +function parseSignerIdentifier(der: Uint8Array): ParsedSignerIdentifier { const element = readRootElement(der, { maxDepth: DEFAULT_MAX_DER_DEPTH }); // [0] IMPLICIT SubjectKeyIdentifier if (element.tag === 0x80) { @@ -1217,6 +1222,7 @@ function parseSignerIdentifier(der: Uint8Array): { throw new Error('SignerIdentifier subjectKeyIdentifier must not be empty'); } return { + type: 'subjectKeyIdentifier', subjectKeyIdentifier: toHex(element.value), }; } @@ -1236,6 +1242,7 @@ function parseSignerIdentifier(der: Uint8Array): { } assertImplicitSerialNumberEncoding(serial.value, 'SignerIdentifier serialNumber'); return { + type: 'issuerAndSerialNumber', issuer: parseSignerIssuerName(der, issuerElement), serialNumberHex: toHex(serial.value), }; @@ -1500,18 +1507,14 @@ function signerIdentifierMatches( certificate: ParsedCertificate, signerInfo: ParsedPkcs7SignerInfo, ): boolean { - if (signerInfo.issuer !== undefined || signerInfo.serialNumberHex !== undefined) { + const identifier = signerInfo.signerIdentifier; + if (identifier.type === 'issuerAndSerialNumber') { return ( - signerInfo.issuer !== undefined && - signerInfo.serialNumberHex !== undefined && - certificate.serialNumberHex === signerInfo.serialNumberHex && - compareDistinguishedNames(certificate.issuer, signerInfo.issuer) + certificate.serialNumberHex === identifier.serialNumberHex && + compareDistinguishedNames(certificate.issuer, identifier.issuer) ); } - return ( - signerInfo.subjectKeyIdentifier !== undefined && - certificate.subjectKeyIdentifier === signerInfo.subjectKeyIdentifier - ); + return certificate.subjectKeyIdentifier === identifier.subjectKeyIdentifier; } function assertImplicitSignedAttrsDer(signedAttrsDer: Uint8Array): void { diff --git a/src/revocation/crl.ts b/src/revocation/crl.ts index c1825973..7f354c92 100644 --- a/src/revocation/crl.ts +++ b/src/revocation/crl.ts @@ -1189,6 +1189,7 @@ function issuerFallbackDistributionPointName( certificate: ParsedCertificate, ): ParsedDistributionPointName { return { + type: 'fullName', fullName: [ { type: 'directoryName', derHex: certificate.issuer.derHex }, ...(certificate.issuerAltNames ?? []), @@ -1531,26 +1532,21 @@ function matchesDistributionPointName( if (certificatePoint === undefined) { return matchesIdpNameAgainstCrlIssuer(crlPoint, certificateCrlIssuer, crlIssuer); } - // Both have fullName — direct comparison - if (certificatePoint.fullName !== undefined && crlPoint.fullName !== undefined) { - return certificatePoint.fullName.some( - (leftName) => - crlPoint.fullName?.some((rightName) => compareGeneralNames(leftName, rightName)) === true, + if (certificatePoint.type === 'fullName' && crlPoint.type === 'fullName') { + return certificatePoint.fullName.some((leftName) => + crlPoint.fullName.some((rightName) => compareGeneralNames(leftName, rightName)), ); } - // Cert has relativeName, CRL has fullName — resolve relativeName to full DN - if (certificatePoint.relativeName !== undefined && crlPoint.fullName !== undefined) { + if (certificatePoint.type === 'relativeName' && crlPoint.type === 'fullName') { const resolvedDnHex = resolveRelativeNameToDnHex(crlIssuer, certificatePoint.relativeName); return crlPoint.fullName.some( (name) => name.type === 'directoryName' && name.derHex === resolvedDnHex, ); } - // Both have relativeName — direct RDN comparison - if (certificatePoint.relativeName !== undefined && crlPoint.relativeName !== undefined) { + if (certificatePoint.type === 'relativeName' && crlPoint.type === 'relativeName') { return compareRelativeDistinguishedNames(certificatePoint.relativeName, crlPoint.relativeName); } - // Cert has fullName, CRL has relativeName — resolve CRL relativeName to full DN - if (certificatePoint.fullName !== undefined && crlPoint.relativeName !== undefined) { + if (certificatePoint.type === 'fullName' && crlPoint.type === 'relativeName') { const resolvedDnHex = resolveRelativeNameToDnHex(crlIssuer, crlPoint.relativeName); return certificatePoint.fullName.some( (name) => name.type === 'directoryName' && name.derHex === resolvedDnHex, @@ -1572,19 +1568,15 @@ function matchesIdpNameAgainstCrlIssuer( if (certificateCrlIssuer === undefined) { return false; } - if (crlPoint.fullName !== undefined) { - return certificateCrlIssuer.some( - (issuerName) => - crlPoint.fullName?.some((name) => compareGeneralNames(issuerName, name)) === true, - ); - } - if (crlPoint.relativeName !== undefined) { - const resolvedDnHex = resolveRelativeNameToDnHex(crlIssuer, crlPoint.relativeName); - return certificateCrlIssuer.some( - (issuerName) => issuerName.type === 'directoryName' && issuerName.derHex === resolvedDnHex, + if (crlPoint.type === 'fullName') { + return certificateCrlIssuer.some((issuerName) => + crlPoint.fullName.some((name) => compareGeneralNames(issuerName, name)), ); } - return false; + const resolvedDnHex = resolveRelativeNameToDnHex(crlIssuer, crlPoint.relativeName); + return certificateCrlIssuer.some( + (issuerName) => issuerName.type === 'directoryName' && issuerName.derHex === resolvedDnHex, + ); } /** Constructs a full DN by appending an RDN to an existing Name, returning hex-encoded DER. */ @@ -1637,16 +1629,13 @@ function sameDistributionPointName( if (left === undefined || right === undefined) { return left === right; } - if (left.fullName !== undefined || right.fullName !== undefined) { - if (left.fullName === undefined || right.fullName === undefined) { - return false; - } + if (left.type === 'fullName' && right.type === 'fullName') { return sameGeneralNameSet(left.fullName, right.fullName); } - if (left.relativeName === undefined || right.relativeName === undefined) { - return false; + if (left.type === 'relativeName' && right.type === 'relativeName') { + return compareRelativeDistinguishedNames(left.relativeName, right.relativeName); } - return compareRelativeDistinguishedNames(left.relativeName, right.relativeName); + return false; } /** Set-equality comparison for GeneralName arrays (order-independent). */ @@ -2172,12 +2161,15 @@ function parseDistributionPointName( } } return { + type: 'fullName', fullName: fullName.map((name) => parseGeneralName(valueDer, name)), }; } if (distributionPointName.tag === 0xa1) { - const relativeName = parseRelativeName(valueDer, distributionPointName); - return { relativeName }; + return { + type: 'relativeName', + relativeName: parseRelativeName(valueDer, distributionPointName), + }; } throw new Error(`Unsupported distributionPointName tag: ${String(distributionPointName.tag)}`); } @@ -2275,10 +2267,7 @@ function parseImplicitBoolean(element: DerElement): boolean { } /** Machine-readable reason a CRL encoder rejected its construction input. */ -export type CrlEncoderErrorCode = - | 'distribution_point_name_conflict' - | 'distribution_point_full_name_empty' - | 'distribution_point_name_empty'; +export type CrlEncoderErrorCode = 'distribution_point_full_name_empty'; /** Throws a {@link ResultError} for a CRL encoder input-validation failure. */ function throwCrlEncoderError(code: CrlEncoderErrorCode, message: string): never { @@ -2330,13 +2319,7 @@ function encodeDistributionPointName( if (value === undefined) { throw new Error('IssuingDistributionPoint distributionPoint is required'); } - if (value.fullName !== undefined && value.relativeName !== undefined) { - throwCrlEncoderError( - 'distribution_point_name_conflict', - 'DistributionPointName cannot contain both fullName and relativeName', - ); - } - if (value.fullName !== undefined) { + if (value.type === 'fullName') { if (value.fullName.length === 0) { throwCrlEncoderError( 'distribution_point_full_name_empty', @@ -2345,17 +2328,11 @@ function encodeDistributionPointName( } return implicitConstructedContext(0, concatGeneralNames(value.fullName)); } - if (value.relativeName !== undefined) { - const relativeName = encodeRelativeDistinguishedName(value.relativeName); - const relativeNameElement = readElement(relativeName); - return implicitConstructedContext( - 1, - relativeName.slice(relativeNameElement.start, relativeNameElement.end), - ); - } - throwCrlEncoderError( - 'distribution_point_name_empty', - 'DistributionPointName must contain fullName or relativeName', + const relativeName = encodeRelativeDistinguishedName(value.relativeName); + const relativeNameElement = readElement(relativeName); + return implicitConstructedContext( + 1, + relativeName.slice(relativeNameElement.start, relativeNameElement.end), ); } diff --git a/src/revocation/index.ts b/src/revocation/index.ts index 1e7fc20c..81e76785 100644 --- a/src/revocation/index.ts +++ b/src/revocation/index.ts @@ -59,6 +59,7 @@ export { } from '#micro509/revocation/crl'; export type { + CreateOcspCertStatusInput, CreateOcspRequestInput, CreateOcspRequestItemInput, CreateOcspResponseInput, @@ -72,6 +73,7 @@ export type { OcspResponseMaterial, OcspResponseStatus, ParsedOcspCertId, + ParsedOcspCertStatus, ParsedOcspRequest, ParsedOcspResponderId, ParsedOcspResponse, diff --git a/src/revocation/ocsp.ts b/src/revocation/ocsp.ts index 465213e9..1c778bbc 100644 --- a/src/revocation/ocsp.ts +++ b/src/revocation/ocsp.ts @@ -156,20 +156,40 @@ export type OcspResponseStatus = /** * Status of one certificate inside an OCSP BasicResponse. */ -export interface ParsedOcspSingleResponse { +export type ParsedOcspSingleResponse = { /** Which certificate this status applies to. */ readonly certId: ParsedOcspCertId; - /** Responder's verdict: `good`, `revoked`, or `unknown`. */ - readonly certStatus: OcspCertStatus; /** Start of the validity window for this status assertion. */ readonly thisUpdate: Date; /** End of the validity window. Absent if the responder does not commit to a schedule. */ readonly nextUpdate?: Date; - /** When the certificate was revoked (only for `certStatus === 'revoked'`). */ - readonly revokedAt?: Date; - /** CRLReason integer (only for `certStatus === 'revoked'`). */ - readonly revocationReasonCode?: number; -} +} & ParsedOcspCertStatus; + +/** + * RFC 6960 §4.2.1 `CertStatus ::= CHOICE { good [0] NULL, revoked [1] RevokedInfo, + * unknown [2] UnknownInfo }`. + * + * Only `revoked` carries data, so `RevokedInfo`'s fields exist only on that + * alternative. `revocationReasonCode` stays optional because `revocationReason` + * is OPTIONAL within `RevokedInfo`. + */ +export type ParsedOcspCertStatus = + | { + /** Responder asserts the certificate is not revoked. */ + readonly certStatus: 'good'; + } + | { + /** Responder asserts the certificate is revoked. */ + readonly certStatus: 'revoked'; + /** `RevokedInfo.revocationTime`. */ + readonly revokedAt: Date; + /** `RevokedInfo.revocationReason` CRLReason integer, when present. */ + readonly revocationReasonCode?: number; + } + | { + /** Responder has no record of the certificate. */ + readonly certStatus: 'unknown'; + }; /** * How the OCSP responder identifies itself — either by distinguished name or @@ -225,18 +245,35 @@ export interface ParsedOcspResponse { * One certificate's status entry for {@linkcode CreateOcspResponseInput.responses}. * Extends {@linkcode CreateOcspRequestItemInput} with status and timing fields. */ -export interface CreateOcspSingleResponseInput extends CreateOcspRequestItemInput { - /** Status to assert for this certificate. */ - readonly certStatus: OcspCertStatus; +export type CreateOcspSingleResponseInput = CreateOcspRequestItemInput & { /** Start of the validity window for this status assertion. Defaults to `new Date()`. */ readonly thisUpdate?: Date; /** End of the validity window. Omit for open-ended assertions. */ readonly nextUpdate?: Date; - /** Revocation time (required when `certStatus` is `'revoked'`). Defaults to `thisUpdate`. */ - readonly revokedAt?: Date; - /** CRLReason integer code (only meaningful when `certStatus` is `'revoked'`). */ - readonly revocationReasonCode?: number; -} +} & CreateOcspCertStatusInput; + +/** + * Status to assert for one certificate, mirroring RFC 6960 §4.2.1 `CertStatus`. + * + * `RevokedInfo`'s fields are reachable only under `'revoked'`. + */ +export type CreateOcspCertStatusInput = + | { + /** Assert the certificate is not revoked. */ + readonly certStatus: 'good'; + } + | { + /** Assert the certificate is revoked. */ + readonly certStatus: 'revoked'; + /** `RevokedInfo.revocationTime`. Defaults to `thisUpdate`. */ + readonly revokedAt?: Date; + /** `RevokedInfo.revocationReason` CRLReason integer code. */ + readonly revocationReasonCode?: number; + } + | { + /** Assert no record of the certificate exists. */ + readonly certStatus: 'unknown'; + }; /** * Input for {@linkcode createOcspResponse}. @@ -393,12 +430,6 @@ interface NormalizedOcspValidationInput { readonly signer: ParsedCertificate; } -interface ParsedOcspCertStatusFields { - readonly certStatus: ParsedOcspSingleResponse['certStatus']; - readonly revokedAt?: Date; - readonly revocationReasonCode?: number; -} - /** * Builds a DER-encoded OCSP request containing one or more CertID entries * and an optional nonce extension. @@ -1675,16 +1706,11 @@ function parseSingleResponse(source: Uint8Array, element: DerElement): ParsedOcs if (children.length !== cursor + (singleExtensions === undefined ? 0 : 1)) { throw new Error('Malformed OCSP SingleResponse'); } - const statusFields = parseOcspCertStatusFields(source, certStatus); return { certId: parseOcspCertId(source.slice(certId.start - certId.headerLength, certId.end)), - certStatus: statusFields.certStatus, thisUpdate: parseTime(thisUpdate), ...parseOcspSingleResponseNextUpdate(source, nextUpdateElement), - ...(statusFields.revokedAt === undefined ? {} : { revokedAt: statusFields.revokedAt }), - ...(statusFields.revocationReasonCode === undefined - ? {} - : { revocationReasonCode: statusFields.revocationReasonCode }), + ...parseOcspCertStatusFields(source, certStatus), }; } @@ -1704,7 +1730,7 @@ function parseOcspSingleResponseNextUpdate( function parseOcspCertStatusFields( source: Uint8Array, certStatus: DerElement, -): ParsedOcspCertStatusFields { +): ParsedOcspCertStatus { if (certStatus.tag === 0x80) { if (certStatus.value.length !== 0) { throw new Error('OCSP good certStatus must be empty'); diff --git a/src/x509/extensions.ts b/src/x509/extensions.ts index cb332781..7a9e4a56 100644 --- a/src/x509/extensions.ts +++ b/src/x509/extensions.ts @@ -172,16 +172,23 @@ export type DistributionPointReason = | 'aACompromise'; /** - * Name component of a CRL Distribution Point (RFC 5280 §4.2.1.13). - * - * Supply exactly one of `fullName` or `relativeName`. + * Name component of a CRL Distribution Point, mirroring RFC 5280 §4.2.1.13 + * `DistributionPointName ::= CHOICE { fullName [0] GeneralNames, + * nameRelativeToCRLIssuer [1] RelativeDistinguishedName }`. */ -export interface DistributionPointName { - /** Absolute {@linkcode GeneralName}(s) identifying the distribution point (usually a URI). */ - readonly fullName?: readonly GeneralName[]; - /** Name relative to the issuer's DN; mutually exclusive with `fullName`. */ - readonly relativeName?: RelativeDistinguishedNameInput; -} +export type DistributionPointName = + | { + /** The `fullName [0]` alternative. */ + readonly type: 'fullName'; + /** Absolute {@linkcode GeneralName}(s) identifying the distribution point (usually a URI). */ + readonly fullName: readonly GeneralName[]; + } + | { + /** The `nameRelativeToCRLIssuer [1]` alternative. */ + readonly type: 'relativeName'; + /** Name relative to the issuer's DN. */ + readonly relativeName: RelativeDistinguishedNameInput; + }; /** * Input for a single CRL Distribution Point (RFC 5280 §4.2.1.13). @@ -904,12 +911,9 @@ function findCustomExtensionValue( } /** The subset of a DistributionPointName the RFC 5280 §4.2.1.13 rules read. */ -interface ProfileDistributionPointName { - /** Absolute GeneralName(s) identifying the distribution point. */ - readonly fullName?: readonly GeneralName[]; - /** Name relative to the CRL issuer, in whichever form the caller holds. */ - readonly relativeName?: TRelativeName; -} +type ProfileDistributionPointName = + | { readonly type: 'fullName'; readonly fullName: readonly GeneralName[] } + | { readonly type: 'relativeName'; readonly relativeName: TRelativeName }; /** The subset of a distribution point the RFC 5280 §4.2.1.13 rules read. */ interface ProfileDistributionPoint { @@ -919,11 +923,6 @@ interface ProfileDistributionPoint { readonly crlIssuer?: readonly GeneralName[]; } -/** The DistributionPointName alternative in use, once proven to be exactly one. */ -type DistributionPointNameChoice = - | { readonly kind: 'fullName'; readonly fullName: readonly GeneralName[] } - | { readonly kind: 'relativeName'; readonly relativeName: TRelativeName }; - /** * Rejects a custom extension carrying a known OID whose payload is not the DER * that OID's schema defines, and a known extension offered in the wrong context. @@ -1369,8 +1368,14 @@ function assertDistributionPointProfile( ); } assertCrlIssuerDistinguishedNames(point); - if (point.distributionPoint !== undefined) { - resolveDistributionPointNameChoice(point.distributionPoint); + if ( + point.distributionPoint?.type === 'fullName' && + point.distributionPoint.fullName.length === 0 + ) { + throwExtensionEncoderError( + 'distribution_point_full_name_empty', + 'DistributionPointName fullName must not be empty', + ); } } @@ -1635,7 +1640,7 @@ function assertCrlIssuerDistinguishedNames( 'DistributionPoint cRLIssuer must only contain directoryName entries', ); } - if (point.distributionPoint?.relativeName !== undefined && point.crlIssuer.length > 1) { + if (point.distributionPoint?.type === 'relativeName' && point.crlIssuer.length > 1) { throwExtensionEncoderError( 'distribution_point_relative_name_multiple_crl_issuers', 'DistributionPointName relativeName requires at most one cRLIssuer distinguished name', @@ -1664,44 +1669,18 @@ function encodeDistributionPoint(point: DistributionPoint): Uint8Array[] { return fields; } -/** - * RFC 5280 §4.2.1.13: a DistributionPointName holds exactly one of fullName and - * relativeName, and a fullName holds at least one GeneralName. - */ -function resolveDistributionPointNameChoice( - name: ProfileDistributionPointName, -): DistributionPointNameChoice { - if (name.fullName !== undefined && name.relativeName !== undefined) { - throwExtensionEncoderError( - 'distribution_point_name_conflict', - 'DistributionPointName cannot contain both fullName and relativeName', - ); - } - if (name.fullName !== undefined) { +/** DER-encode a DistributionPointName (fullName or relativeName). */ +function encodeDistributionPointName(name: DistributionPointName): Uint8Array { + if (name.type === 'fullName') { if (name.fullName.length === 0) { throwExtensionEncoderError( 'distribution_point_full_name_empty', 'DistributionPointName fullName must not be empty', ); } - return { kind: 'fullName', fullName: name.fullName }; - } - if (name.relativeName !== undefined) { - return { kind: 'relativeName', relativeName: name.relativeName }; - } - throwExtensionEncoderError( - 'distribution_point_name_empty', - 'DistributionPointName must contain fullName or relativeName', - ); -} - -/** DER-encode a DistributionPointName (fullName or relativeName). */ -function encodeDistributionPointName(name: DistributionPointName): Uint8Array { - const choice = resolveDistributionPointNameChoice(name); - if (choice.kind === 'fullName') { - return implicitConstructedContext(0, concatBytes(choice.fullName.map(encodeSubjectAltName))); + return implicitConstructedContext(0, concatBytes(name.fullName.map(encodeSubjectAltName))); } - const relativeName = encodeRelativeDistinguishedName(choice.relativeName); + const relativeName = encodeRelativeDistinguishedName(name.relativeName); const relativeNameElement = readElement(relativeName); return implicitConstructedContext( 1, diff --git a/src/x509/parse.ts b/src/x509/parse.ts index f3b5982d..381f8716 100644 --- a/src/x509/parse.ts +++ b/src/x509/parse.ts @@ -189,15 +189,23 @@ export interface ParsedRelativeDistinguishedName { } /** - * The name component of a CRL Distribution Point (RFC 5280 §4.2.1.13). - * Exactly one of `fullName` or `relativeName` will be present. + * The name component of a CRL Distribution Point, mirroring RFC 5280 §4.2.1.13 + * `DistributionPointName ::= CHOICE { fullName [0] GeneralNames, + * nameRelativeToCRLIssuer [1] RelativeDistinguishedName }`. */ -export interface ParsedDistributionPointName { - /** Absolute GeneralName(s) identifying the distribution point. */ - readonly fullName?: readonly GeneralName[]; - /** Name relative to the CRL issuer's distinguished name. */ - readonly relativeName?: ParsedRelativeDistinguishedName; -} +export type ParsedDistributionPointName = + | { + /** The `fullName [0]` alternative. */ + readonly type: 'fullName'; + /** Absolute GeneralName(s) identifying the distribution point. */ + readonly fullName: readonly GeneralName[]; + } + | { + /** The `nameRelativeToCRLIssuer [1]` alternative. */ + readonly type: 'relativeName'; + /** Name relative to the CRL issuer's distinguished name. */ + readonly relativeName: ParsedRelativeDistinguishedName; + }; /** A decoded DistributionPoint from the CRL Distribution Points extension. */ export interface ParsedDistributionPoint { @@ -2076,11 +2084,15 @@ function parseDistributionPointName( } } return { + type: 'fullName', fullName: fullName.map((name) => parseGeneralName(source, name)), }; } if (distributionPointName.tag === 0xa1) { - return { relativeName: parseRelativeDistinguishedName(source, distributionPointName) }; + return { + type: 'relativeName', + relativeName: parseRelativeDistinguishedName(source, distributionPointName), + }; } throw new Error(`Unsupported distributionPointName tag: ${distributionPointName.tag}`); } diff --git a/test/certificate.test.ts b/test/certificate.test.ts index ff358bf9..1e59ed45 100644 --- a/test/certificate.test.ts +++ b/test/certificate.test.ts @@ -97,6 +97,7 @@ describe('certificate', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://issuer.example.test/ca.crl' }], }, }, @@ -132,6 +133,7 @@ describe('certificate', () => { expect(parsed.crlDistributionPoints).toEqual([ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://issuer.example.test/ca.crl' }], }, }, @@ -289,6 +291,7 @@ describe('certificate', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'relativeName', relativeName: [ { type: 'organization', value: 'Example PKI' }, { type: 'commonName', value: 'leaf-partition' }, @@ -299,6 +302,7 @@ describe('certificate', () => { }, { distributionPoint: { + type: 'fullName', fullName: [ { type: 'uri', value: 'http://issuer.example.test/full.crl' }, { type: 'dns', value: 'full-crl.example.test' }, @@ -314,6 +318,7 @@ describe('certificate', () => { expect(parsed.crlDistributionPoints).toHaveLength(2); expect(parsed.crlDistributionPoints?.[0]).toMatchObject({ distributionPoint: { + type: 'relativeName', relativeName: { values: { organization: 'Example PKI', @@ -326,6 +331,7 @@ describe('certificate', () => { }); expect(parsed.crlDistributionPoints?.[1]).toEqual({ distributionPoint: { + type: 'fullName', fullName: [ { type: 'uri', value: 'http://issuer.example.test/full.crl' }, { type: 'dns', value: 'full-crl.example.test' }, @@ -373,6 +379,7 @@ describe('certificate', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/nondn.crl' }], }, crlIssuer: [{ type: 'uri', value: 'http://example.test/issuer.crl' }], @@ -739,7 +746,7 @@ describe('certificate', () => { createSelfSignedCertificate({ subject: { commonName: 'bad-dp.example' }, extensions: { - crlDistributionPoints: [{ distributionPoint: { fullName: [] } }], + crlDistributionPoints: [{ distributionPoint: { type: 'fullName', fullName: [] } }], }, }), 'distribution_point_full_name_empty', diff --git a/test/chain-revocation.test.ts b/test/chain-revocation.test.ts index a0e3319f..716614a5 100644 --- a/test/chain-revocation.test.ts +++ b/test/chain-revocation.test.ts @@ -106,6 +106,7 @@ describe('checkChainRevocation', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/partial.crl' }], }, reasons: ['keyCompromise'], diff --git a/test/crl.test.ts b/test/crl.test.ts index c4784bb9..e450101f 100644 --- a/test/crl.test.ts +++ b/test/crl.test.ts @@ -6,6 +6,7 @@ import { createSelfSignedCertificate, generateKeyPair, isCertificateRevoked, + type ParsedCertificateRevocationList, parseCertificatePem, parseCertificateRevocationListDer, parseCertificateRevocationListDerOrThrow, @@ -108,6 +109,7 @@ describe('crl', () => { baseCrlNumber: 8, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/idp.crl' }], }, onlyContainsUserCerts: true, @@ -117,6 +119,7 @@ describe('crl', () => { freshestCrlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/freshest.crl' }], }, }, @@ -133,6 +136,7 @@ describe('crl', () => { expect(parsed.baseCrlNumber).toBe(8); expect(parsed.issuingDistributionPoint).toEqual({ distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/idp.crl' }], }, onlyContainsUserCerts: true, @@ -142,6 +146,7 @@ describe('crl', () => { expect(parsed.freshestCrlDistributionPoints).toEqual([ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/freshest.crl' }], }, }, @@ -170,6 +175,7 @@ describe('crl', () => { issuerPublicKey: issuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'relativeName', relativeName: [ { type: 'organizationalUnit', value: 'CRLs' }, { type: 'commonName', value: 'ca-scope' }, @@ -181,6 +187,7 @@ describe('crl', () => { freshestCrlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [ { type: 'uri', value: 'http://example.test/delta.crl' }, { type: 'dns', value: 'delta.example.test' }, @@ -191,6 +198,7 @@ describe('crl', () => { }, { distributionPoint: { + type: 'relativeName', relativeName: [{ type: 'commonName', value: 'delta-relative' }], }, }, @@ -200,6 +208,7 @@ describe('crl', () => { const parsed = parseCertificateRevocationListPemOrThrow(crl.pem); expect(parsed.issuingDistributionPoint).toMatchObject({ distributionPoint: { + type: 'relativeName', relativeName: { values: { organizationalUnit: 'CRLs', @@ -213,6 +222,7 @@ describe('crl', () => { expect(parsed.freshestCrlDistributionPoints).toHaveLength(2); expect(parsed.freshestCrlDistributionPoints?.[0]).toEqual({ distributionPoint: { + type: 'fullName', fullName: [ { type: 'uri', value: 'http://example.test/delta.crl' }, { type: 'dns', value: 'delta.example.test' }, @@ -223,6 +233,7 @@ describe('crl', () => { }); expect(parsed.freshestCrlDistributionPoints?.[1]).toMatchObject({ distributionPoint: { + type: 'relativeName', relativeName: { values: { commonName: 'delta-relative' }, }, @@ -270,6 +281,7 @@ describe('crl', () => { freshestCrlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [ { type: 'email', value: 'pki@example.test' }, { type: 'ip', value: '2001:db8::7' }, @@ -284,6 +296,7 @@ describe('crl', () => { [ { distributionPoint: { + type: 'fullName', fullName: [ { type: 'email', value: 'pki@example.test' }, { type: 'ip', value: '2001:db8:0:0:0:0:0:7' }, @@ -402,6 +415,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/leaf.crl' }], }, }, @@ -415,6 +429,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/leaf.crl' }], }, }, @@ -433,6 +448,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/other.crl' }], }, }, @@ -471,6 +487,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/reasons.crl' }], }, reasons: ['keyCompromise'], @@ -485,6 +502,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/reasons.crl' }], }, onlySomeReasons: ['cessationOfOperation'], @@ -517,6 +535,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/ca-only.crl' }], }, }, @@ -529,6 +548,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/ca-only.crl' }], }, onlyContainsCACerts: true, @@ -581,6 +601,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/direct.crl' }], }, }, @@ -633,6 +654,7 @@ describe('crl', () => { issuerPublicKey: certIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/direct.crl' }], }, }, @@ -672,6 +694,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/no-idp-delta.crl' }], }, }, @@ -792,7 +815,10 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'directoryName', derHex: caDnHex }] }, + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'directoryName', derHex: caDnHex }], + }, }, }); expect( @@ -833,7 +859,10 @@ describe('crl', () => { signerPrivateKey: crlCa.keyPair.privateKey, issuerPublicKey: crlCa.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'directoryName', derHex: crlCaDnHex }] }, + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'directoryName', derHex: crlCaDnHex }], + }, indirectCrl: true, }, }); @@ -851,6 +880,7 @@ describe('crl', () => { issuerPublicKey: crlCa.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/other.crl' }], }, indirectCrl: true, @@ -885,6 +915,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/partial.crl' }], }, reasons: ['keyCompromise', 'cACompromise'], @@ -914,6 +945,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/partial.crl' }], }, onlySomeReasons: ['cACompromise', 'superseded'], @@ -947,12 +979,14 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/a.crl' }], }, reasons: ['keyCompromise'], }, { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/a.crl' }], }, reasons: ['cACompromise'], @@ -1001,7 +1035,7 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'dns', value: 'crl.example' }] }, + distributionPoint: { type: 'fullName', fullName: [{ type: 'dns', value: 'crl.example' }] }, }, }); expect( @@ -1029,6 +1063,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'srv', value: '_ldap.crl.example' }], }, }, @@ -1041,7 +1076,7 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'srv', value: idpName }] }, + distributionPoint: { type: 'fullName', fullName: [{ type: 'srv', value: idpName }] }, }, }); expect( @@ -1058,7 +1093,10 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'srv', value: '_imaps.crl.example' }] }, + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'srv', value: '_imaps.crl.example' }], + }, }, }); expect( @@ -1098,7 +1136,12 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, extensions: { crlDistributionPoints: [ - { distributionPoint: { fullName: [{ type: 'uri', value: certificateUri }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: certificateUri }], + }, + }, ], }, }); @@ -1107,7 +1150,7 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'uri', value: crlUri }] }, + distributionPoint: { type: 'fullName', fullName: [{ type: 'uri', value: crlUri }] }, }, }); expect( @@ -1145,7 +1188,12 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, extensions: { crlDistributionPoints: [ - { distributionPoint: { fullName: [{ type: 'uri', value: certificateUri }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: certificateUri }], + }, + }, ], }, }); @@ -1154,7 +1202,7 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { - distributionPoint: { fullName: [{ type: 'uri', value: crlUri }] }, + distributionPoint: { type: 'fullName', fullName: [{ type: 'uri', value: crlUri }] }, }, }); expect( @@ -1231,6 +1279,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/scoped.crl' }], }, }, @@ -1302,6 +1351,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/unsupported.crl' }], }, }, @@ -1314,6 +1364,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/unsupported.crl' }], }, indirectCrl: true, @@ -1622,6 +1673,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-scope-a.crl' }], }, }, @@ -1635,6 +1687,7 @@ describe('crl', () => { crlNumber: 7, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-scope-a.crl' }], }, }, @@ -1647,6 +1700,7 @@ describe('crl', () => { baseCrlNumber: 7, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-scope-b.crl' }], }, }, @@ -1849,6 +1903,7 @@ describe('crl', () => { const distributionPoints = [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect.crl' }], }, crlIssuer: [{ type: 'directoryName', derHex: parsedCrlIssuer.subject.derHex }], @@ -1878,6 +1933,7 @@ describe('crl', () => { issuerPublicKey: crlIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect.crl' }], }, indirectCrl: true, @@ -1939,6 +1995,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect-applicability.crl' }], }, }, @@ -1951,6 +2008,7 @@ describe('crl', () => { issuerPublicKey: crlIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect-applicability.crl' }], }, indirectCrl: true, @@ -2057,6 +2115,7 @@ describe('crl', () => { issuerPublicKey: crlIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/unsupported-crl-issuer.crl' }], }, indirectCrl: true, @@ -2105,6 +2164,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-unsupported-entry.crl' }], }, crlIssuer: [{ type: 'directoryName', derHex: parsedCrlIssuer.subject.derHex }], @@ -2119,6 +2179,7 @@ describe('crl', () => { crlNumber: 10, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-unsupported-entry.crl' }], }, indirectCrl: true, @@ -2132,6 +2193,7 @@ describe('crl', () => { baseCrlNumber: 10, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-unsupported-entry.crl' }], }, indirectCrl: true, @@ -2186,6 +2248,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/parsed-delta-compat.crl' }], }, }, @@ -2201,6 +2264,7 @@ describe('crl', () => { crlNumber: 4, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/parsed-delta-compat.crl' }], }, }, @@ -2217,6 +2281,7 @@ describe('crl', () => { baseCrlNumber: 4, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/parsed-delta-compat.crl' }], }, }, @@ -2281,6 +2346,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/complex-idp.crl' }], }, }, @@ -2295,7 +2361,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, crlNumber: 12, issuingDistributionPoint: { - distributionPoint: { fullName: complexNames }, + distributionPoint: { type: 'fullName', fullName: complexNames }, }, }) ).pem, @@ -2309,7 +2375,7 @@ describe('crl', () => { crlNumber: 13, baseCrlNumber: 12, issuingDistributionPoint: { - distributionPoint: { fullName: shuffledNames }, + distributionPoint: { type: 'fullName', fullName: shuffledNames }, }, }) ).pem, @@ -2350,6 +2416,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/complex-idp-mismatch.crl' }], }, }, @@ -2364,7 +2431,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, crlNumber: 20, issuingDistributionPoint: { - distributionPoint: { fullName: names }, + distributionPoint: { type: 'fullName', fullName: names }, onlySomeReasons: ['keyCompromise'], }, }) @@ -2380,6 +2447,7 @@ describe('crl', () => { baseCrlNumber: 20, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [ { type: 'uri', value: 'http://example.test/complex-idp-mismatch.crl' }, { type: 'directoryName', derHex: parsedCa.subject.derHex }, @@ -2426,6 +2494,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'relativeName', relativeName: [{ type: 'commonName', value: 'team alpha' }], }, }, @@ -2441,6 +2510,7 @@ describe('crl', () => { crlNumber: 30, issuingDistributionPoint: { distributionPoint: { + type: 'relativeName', relativeName: [{ type: 'commonName', value: ' Team Alpha ' }], }, }, @@ -2457,6 +2527,7 @@ describe('crl', () => { baseCrlNumber: 30, issuingDistributionPoint: { distributionPoint: { + type: 'relativeName', relativeName: [{ type: 'commonName', value: 'TEAM ALPHA' }], }, }, @@ -2475,15 +2546,11 @@ describe('crl', () => { const issuingDistributionPoint = delta.issuingDistributionPoint; const distributionPoint = issuingDistributionPoint?.distributionPoint; - const relativeName = distributionPoint?.relativeName; - if ( - issuingDistributionPoint === undefined || - distributionPoint === undefined || - relativeName === undefined - ) { + if (issuingDistributionPoint === undefined || distributionPoint?.type !== 'relativeName') { throw new Error('Expected relativeName issuing distribution point'); } - const poisonedDelta = { + const relativeName = distributionPoint.relativeName; + const poisonedDelta: ParsedCertificateRevocationList = { ...delta, issuingDistributionPoint: { ...issuingDistributionPoint, @@ -2539,6 +2606,7 @@ describe('crl', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/entry-mismatch.crl' }], }, crlIssuer: [{ type: 'directoryName', derHex: parsedCrlIssuer.subject.derHex }], @@ -2552,6 +2620,7 @@ describe('crl', () => { issuerPublicKey: crlIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/entry-mismatch.crl' }], }, indirectCrl: true, @@ -2973,6 +3042,7 @@ describe('crl', () => { issuerPublicKey: issuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [], }, }, @@ -2981,40 +3051,6 @@ describe('crl', () => { ); }); - it('rejects invalid issuing distribution point construction', async () => { - const issuer = await createSelfSignedCertificate({ - subject: { commonName: 'Bad IDP CRL Issuer' }, - extensions: { - basicConstraints: { ca: true, pathLength: 0 }, - keyUsage: ['keyCertSign', 'cRLSign'], - }, - }); - const base = { - issuer: { commonName: 'Bad IDP CRL Issuer' }, - signerPrivateKey: issuer.keyPair.privateKey, - issuerPublicKey: issuer.keyPair.publicKey, - } as const; - await expectRejectedErrorCode( - createCertificateRevocationList({ - ...base, - issuingDistributionPoint: { - distributionPoint: { - fullName: [{ type: 'uri', value: 'http://example.test/crl' }], - relativeName: [{ type: 'commonName', value: 'bad' }], - }, - }, - }), - 'distribution_point_name_conflict', - ); - await expectRejectedErrorCode( - createCertificateRevocationList({ - ...base, - issuingDistributionPoint: { distributionPoint: {} }, - }), - 'distribution_point_name_empty', - ); - }); - it('rejects empty freshest CRL issuer lists', async () => { const issuer = await createSelfSignedCertificate({ subject: { commonName: 'Bad Freshest CRL Issuer' }, @@ -3067,6 +3103,7 @@ describe('crl', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://crl.example.com/crl.pem' }], }, }, @@ -3484,7 +3521,12 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, freshestCrlDistributionPoints: [ - { distributionPoint: { fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }], + }, + }, ], }); expect(() => @@ -3511,7 +3553,12 @@ describe('crl', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, freshestCrlDistributionPoints: [ - { distributionPoint: { fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }], + }, + }, ], }); expect(() => diff --git a/test/csr.test.ts b/test/csr.test.ts index 6035af72..d09f3d77 100644 --- a/test/csr.test.ts +++ b/test/csr.test.ts @@ -157,6 +157,7 @@ describe('csr', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://csr.example/crl' }], }, }, @@ -196,6 +197,7 @@ describe('csr', () => { expect(parsed.crlDistributionPoints).toEqual([ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://csr.example/crl' }], }, }, diff --git a/test/extension-registry.test.ts b/test/extension-registry.test.ts index 19ddf2a0..6d292955 100644 --- a/test/extension-registry.test.ts +++ b/test/extension-registry.test.ts @@ -191,6 +191,7 @@ describe('extension registry', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'https://example.test/root.crl' }], }, }, @@ -222,6 +223,7 @@ describe('extension registry', () => { expect(parsed.crlDistributionPoints).toEqual([ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'https://example.test/root.crl' }], }, }, @@ -255,6 +257,7 @@ describe('extension registry', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'https://example.test/csr.crl' }], }, }, @@ -282,6 +285,7 @@ describe('extension registry', () => { expect(parsed.crlDistributionPoints).toEqual([ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'https://example.test/csr.crl' }], }, }, diff --git a/test/internals.test.ts b/test/internals.test.ts index 436f940e..3b74c9b1 100644 --- a/test/internals.test.ts +++ b/test/internals.test.ts @@ -900,7 +900,7 @@ describe('extensions encoding', () => { () => encodeCrlDistributionPoints([ { - distributionPoint: { relativeName }, + distributionPoint: { type: 'relativeName', relativeName }, crlIssuer: [ { type: 'directoryName', derHex: issuerA }, { type: 'directoryName', derHex: issuerB }, @@ -913,7 +913,7 @@ describe('extensions encoding', () => { () => encodeCrlDistributionPoints([ { - distributionPoint: { relativeName }, + distributionPoint: { type: 'relativeName', relativeName }, crlIssuer: [ { type: 'directoryName', derHex: issuerA }, { type: 'uri', value: 'http://example.test/backup.crl' }, @@ -926,7 +926,7 @@ describe('extensions encoding', () => { () => encodeCrlDistributionPoints([ { - distributionPoint: { relativeName }, + distributionPoint: { type: 'relativeName', relativeName }, crlIssuer: [ { type: 'unknown', @@ -1098,7 +1098,12 @@ describe('extensions encoding', () => { [ 'a fullName URI', encodeCrlDistributionPoints([ - { distributionPoint: { fullName: [{ type: 'uri', value: 'http://crl.example/a.crl' }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: 'http://crl.example/a.crl' }], + }, + }, ]), ], [ @@ -1270,7 +1275,12 @@ describe('extensions encoding', () => { [ OIDS.cRLDistributionPoints, encodeCrlDistributionPoints([ - { distributionPoint: { fullName: [{ type: 'uri', value: 'http://crl.example/a.crl' }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: 'http://crl.example/a.crl' }], + }, + }, ]), ], [OIDS.subjectKeyIdentifier, octetString(Uint8Array.of(1, 2, 3))], @@ -1710,22 +1720,6 @@ describe('extensions encoding', () => { Reflect.apply(encodeCrlDistributionPoints, undefined, [[{ reasons: ['keyCompromise'] }]]), 'distribution_point_empty', ); - expectEncoderErrorCode( - () => - encodeCrlDistributionPoints([ - { - distributionPoint: { - fullName: [{ type: 'uri', value: 'http://example.test/crl' }], - relativeName: [{ type: 'commonName', value: 'bad' }], - }, - }, - ]), - 'distribution_point_name_conflict', - ); - expectEncoderErrorCode( - () => encodeCrlDistributionPoints([{ distributionPoint: {} }]), - 'distribution_point_name_empty', - ); }); it('rejects non-SEQUENCE directoryName DER when encoding names', () => { diff --git a/test/malformed-der.test.ts b/test/malformed-der.test.ts index e2b1b41f..7f4708d4 100644 --- a/test/malformed-der.test.ts +++ b/test/malformed-der.test.ts @@ -762,7 +762,12 @@ describe('malformed DER corpus', () => { signerPrivateKey: ca.keyPair.privateKey, issuerPublicKey: ca.keyPair.publicKey, freshestCrlDistributionPoints: [ - { distributionPoint: { fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }] } }, + { + distributionPoint: { + type: 'fullName', + fullName: [{ type: 'uri', value: 'http://example.test/ok.crl' }], + }, + }, ], }); const ocspResponse = await createOcspResponse({ diff --git a/test/ocsp.test.ts b/test/ocsp.test.ts index 31713b60..33d600fe 100644 --- a/test/ocsp.test.ts +++ b/test/ocsp.test.ts @@ -258,8 +258,11 @@ describe('ocsp', () => { ], }); const parsedRevoked = parseOcspResponsePemOrThrow(revokedResponse.pem); - expect(parsedRevoked.responses?.[0]?.certStatus).toBe('revoked'); - expect(parsedRevoked.responses?.[0]?.revokedAt?.toISOString()).toBe('2024-06-15T00:00:00.000Z'); + const revokedEntry = parsedRevoked.responses?.[0]; + if (revokedEntry?.certStatus !== 'revoked') { + throw new Error('expected revoked certStatus'); + } + expect(revokedEntry.revokedAt.toISOString()).toBe('2024-06-15T00:00:00.000Z'); const unknownResponse = await createOcspResponse({ signerPrivateKey: issuer.keyPair.privateKey, @@ -308,8 +311,11 @@ describe('ocsp', () => { ], }); const parsed = parseOcspResponsePemOrThrow(response.pem); - expect(parsed.responses?.[0]?.certStatus).toBe('revoked'); - expect(parsed.responses?.[0]?.revocationReasonCode).toBe(1); + const entry = parsed.responses?.[0]; + if (entry?.certStatus !== 'revoked') { + throw new Error('expected revoked certStatus'); + } + expect(entry.revocationReasonCode).toBe(1); }); it('verifyOcspResponseSignature with DER input', async () => { @@ -1014,6 +1020,7 @@ describe('ocsp', () => { responses: parsed.responses.map((entry) => ({ ...entry, certStatus: 'revoked' as const, + revokedAt: future, thisUpdate: future, })), }), @@ -2392,9 +2399,11 @@ describe('ocsp', () => { expect(parsed.responseStatus).toBe('successful'); expect(parsed.responses).toBeDefined(); const certResponse = parsed.responses?.[0]; - expect(certResponse?.certStatus).toBe('revoked'); - expect(certResponse?.revokedAt?.getTime()).toBe(revokedAt.getTime()); - expect(certResponse?.revocationReasonCode).toBe(1); + if (certResponse?.certStatus !== 'revoked') { + throw new Error('expected revoked certStatus'); + } + expect(certResponse.revokedAt.getTime()).toBe(revokedAt.getTime()); + expect(certResponse.revocationReasonCode).toBe(1); }); it('parseOcspResponseDerOrThrow skips version tag [0] if present (line 254)', async () => { diff --git a/test/pkcs7.test.ts b/test/pkcs7.test.ts index 53442ab7..1a6cee3b 100644 --- a/test/pkcs7.test.ts +++ b/test/pkcs7.test.ts @@ -132,7 +132,10 @@ describe('pkcs7', () => { digestAlgorithmName: 'SHA-256', signatureAlgorithmOid: OIDS.sha256WithRSAEncryption, signatureAlgorithmName: 'RSA PKCS#1 v1.5 with SHA-256', - serialNumberHex: parsedSigner.serialNumberHex, + signerIdentifier: { + type: 'issuerAndSerialNumber', + serialNumberHex: parsedSigner.serialNumberHex, + }, }); }); @@ -344,52 +347,12 @@ describe('pkcs7', () => { if (signerInfo === undefined) { throw new Error('expected signer info'); } - const { - issuer: _ignoredIssuer, - serialNumberHex: _ignoredSerialNumberHex, - ...signerInfoWithoutIssuerAndSerial - } = signerInfo; - const result = await verifyPkcs7SignedData({ - ...parsed.value, - signerInfos: [ - { - ...signerInfoWithoutIssuerAndSerial, - subjectKeyIdentifier, - }, - ], - }); - expect(result.ok).toBe(true); - }); - - it('verifyPkcs7SignedData ignores tampered dual signer identifiers on pre-parsed input', async () => { - const signer = await createSelfSignedCertificate({ - subject: { commonName: 'Dual Identifier Signer' }, - }); - const parsedSigner = unwrap(parseCertificatePem(signer.certificate.pem)); - const subjectKeyIdentifier = parsedSigner.subjectKeyIdentifier; - if (subjectKeyIdentifier === undefined) { - throw new Error('expected subjectKeyIdentifier'); - } - const content = new TextEncoder().encode('Dual identifier test'); - const der = await createCmsSignedDataWithSignedAttrs( - parsedSigner, - signer.keyPair.privateKey, - content, - ); - const parsed = parsePkcs7SignedDataDer(der); - expect(parsed.ok).toBe(true); - if (!parsed.ok) throw new Error('unreachable'); - const signerInfo = parsed.value.signerInfos[0]; - if (signerInfo === undefined) { - throw new Error('expected signer info'); - } const result = await verifyPkcs7SignedData({ ...parsed.value, signerInfos: [ { ...signerInfo, - serialNumberHex: 'deadbeef', - subjectKeyIdentifier, + signerIdentifier: { type: 'subjectKeyIdentifier', subjectKeyIdentifier }, }, ], }); diff --git a/test/revocation.test.ts b/test/revocation.test.ts index df0c367b..b893ab76 100644 --- a/test/revocation.test.ts +++ b/test/revocation.test.ts @@ -159,6 +159,7 @@ describe('revocation boundary', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/revocation-scoped.crl' }], }, }, @@ -172,6 +173,7 @@ describe('revocation boundary', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/revocation-scoped.crl' }], }, }, @@ -215,6 +217,7 @@ describe('revocation boundary', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/partial.crl' }], }, reasons: ['keyCompromise'], @@ -262,6 +265,7 @@ describe('revocation boundary', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-revocation.crl' }], }, }, @@ -276,6 +280,7 @@ describe('revocation boundary', () => { crlNumber: 4, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-revocation.crl' }], }, }, @@ -288,6 +293,7 @@ describe('revocation boundary', () => { baseCrlNumber: 4, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/delta-revocation.crl' }], }, }, @@ -345,6 +351,7 @@ describe('revocation boundary', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect-revocation.crl' }], }, crlIssuer: [{ type: 'directoryName', derHex: parsedCrlIssuer.subject.derHex }], @@ -358,6 +365,7 @@ describe('revocation boundary', () => { issuerPublicKey: crlIssuer.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/indirect-revocation.crl' }], }, indirectCrl: true, @@ -410,6 +418,7 @@ describe('revocation boundary', () => { crlDistributionPoints: [ { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/scope-a.crl' }], }, }, @@ -423,6 +432,7 @@ describe('revocation boundary', () => { issuerPublicKey: ca.keyPair.publicKey, issuingDistributionPoint: { distributionPoint: { + type: 'fullName', fullName: [{ type: 'uri', value: 'http://example.test/scope-b.crl' }], }, }, diff --git a/test/root-barrel.types.ts b/test/root-barrel.types.ts index b3eec2f0..8711ef5e 100644 --- a/test/root-barrel.types.ts +++ b/test/root-barrel.types.ts @@ -31,5 +31,5 @@ assertRootTypes({ certificateError: 'validity_not_after_before_not_before', extensionError: 'key_usage_empty', nameError: 'invalid_country_code', - crlError: 'distribution_point_name_conflict', + crlError: 'distribution_point_full_name_empty', }); diff --git a/tsconfig.other.json b/tsconfig.other.json index 71f67548..22b8c1a3 100644 --- a/tsconfig.other.json +++ b/tsconfig.other.json @@ -9,7 +9,6 @@ "skipLibCheck": true, "strict": true, "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noFallthroughCasesInSwitch": true, "forceConsistentCasingInFileNames": true, diff --git a/tsconfig.src.json b/tsconfig.src.json index e56925b1..e1d0dd5a 100644 --- a/tsconfig.src.json +++ b/tsconfig.src.json @@ -7,7 +7,6 @@ "lib": ["ES2024", "DOM"], "strict": true, "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noFallthroughCasesInSwitch": true, "forceConsistentCasingInFileNames": true, From 18eb4a22c325f69d5f1850f138cf66f18955fcec Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 11:18:53 +0200 Subject: [PATCH 06/11] fix: throw on unhandled union variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourteen switches over closed unions had no default, so a value from outside the union fell off the end. Four were `assert*` helpers in `keys.ts` returning void, where an unrecognized `algorithm.kind` made the SPKI, PKCS#8, and JWK checks pass silently; the rest returned `undefined` into WebCrypto, DER encoding, or a `Result`. Each now ends in an `_exhaustive` default, which also turns a future variant into a compile error. `CreateSelfSignedCertificateInput` splits into a base and a key-source union. `algorithm` was documented as ignored when `keyPair` is present; supplying both no longer compiles. `ParsedIssuingDistributionPoint` gains the scope union its builder input already had, recording the RFC 5280 §5.2.5 at-most-one rule the parser only enforced at runtime. An explicitly encoded FALSE stays distinct from an omitted flag. --- src/index.ts | 4 ++ src/internal/crypto/pbes2.ts | 4 ++ src/internal/crypto/rsa-pss.ts | 8 +++ src/keys/keys.ts | 28 ++++++++++ src/revocation/chain.ts | 4 ++ src/revocation/crl.ts | 95 ++++++++++++++++++++++++---------- src/revocation/index.ts | 6 ++- src/revocation/ocsp.ts | 4 ++ src/x509/certificate.ts | 45 +++++++++++----- src/x509/extensions.ts | 32 +++++++----- src/x509/index.ts | 2 + src/x509/name-text.ts | 8 +++ src/x509/parse.ts | 58 ++++++++++++++++++--- test/crl.test.ts | 48 +++++++++++++++++ test/root-barrel.types.ts | 47 +++++++++++++++++ 15 files changed, 332 insertions(+), 61 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5a914f0e..0ae73eae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -297,6 +297,8 @@ export type { ParseCertificateRevocationListResult, ParsedCertificateRevocationList, ParsedIssuingDistributionPoint, + ParsedIssuingDistributionPointBase, + ParsedIssuingDistributionPointScope, ParsedOcspCertId, ParsedOcspCertStatus, ParsedOcspRequest, @@ -445,6 +447,7 @@ export type { CreateCertificateErrorCode, CreateCertificateInput, CreateCsrInput, + CreateSelfSignedCertificateBase, CreateSelfSignedCertificateInput, CsrMaterial, DecodedExtensionMap, @@ -496,6 +499,7 @@ export type { PolicyQualifierInfo, RelativeDistinguishedNameInput, SelfSignedCertificateResult, + SelfSignedKeySource, SubjectAltName, SubjectAltNameTextOptions, ValidityInput, diff --git a/src/internal/crypto/pbes2.ts b/src/internal/crypto/pbes2.ts index dd4406fd..d41825f8 100644 --- a/src/internal/crypto/pbes2.ts +++ b/src/internal/crypto/pbes2.ts @@ -410,5 +410,9 @@ function resolvePrfProfile(name: Pbes2Prf): { return { oid: OIDS.hmacWithSHA1, hash: 'SHA-1' }; case 'HMAC-SHA-256': return { oid: OIDS.hmacWithSHA256, hash: 'SHA-256' }; + default: { + const _exhaustive: never = name; + throw new Error(`Unhandled Pbes2Prf: ${String(_exhaustive)}`); + } } } diff --git a/src/internal/crypto/rsa-pss.ts b/src/internal/crypto/rsa-pss.ts index 87b7e5ba..1cc3c65f 100644 --- a/src/internal/crypto/rsa-pss.ts +++ b/src/internal/crypto/rsa-pss.ts @@ -154,6 +154,10 @@ export function rsaPssParametersForHash(hash: RsaPssHash): RsaPssParameters { saltLength: 64, trailerField: 1, }; + default: { + const _exhaustive: never = hash; + throw new Error(`Unhandled RsaPssHash: ${String(_exhaustive)}`); + } } } @@ -395,6 +399,10 @@ function hashOidForName(hash: RsaPssHash): string { return OIDS.sha384; case 'SHA-512': return OIDS.sha512; + default: { + const _exhaustive: never = hash; + throw new Error(`Unhandled RsaPssHash: ${String(_exhaustive)}`); + } } } diff --git a/src/keys/keys.ts b/src/keys/keys.ts index e55f1168..f2289441 100644 --- a/src/keys/keys.ts +++ b/src/keys/keys.ts @@ -1486,6 +1486,10 @@ function toGenerateKeyAlgorithm( }; case 'ed25519': return { name: 'Ed25519' }; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled KeyAlgorithmInput kind: ${String(_exhaustive)}`); + } } } @@ -1506,6 +1510,10 @@ function toImportAlgorithm( }; case 'ed25519': return { name: 'Ed25519' }; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled PublicKeyImportInput kind: ${String(_exhaustive)}`); + } } } @@ -1989,6 +1997,10 @@ function traditionalPemCipherKeyLength( return 192; case 'AES-256-CBC': return 256; + default: { + const _exhaustive: never = cipher; + throw new Error(`Unhandled traditional PEM cipher: ${String(_exhaustive)}`); + } } } @@ -2269,6 +2281,10 @@ function assertSpkiMatchesRequestedAlgorithm( throw new Error('SubjectPublicKeyInfo algorithm does not match requested import algorithm'); } return; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled PublicKeyImportInput kind: ${String(_exhaustive)}`); + } } } @@ -2306,6 +2322,10 @@ function assertPkcs8MatchesRequestedAlgorithm( throw new Error('PKCS#8 private key algorithm does not match requested import algorithm'); } return; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled PrivateKeyImportInput kind: ${String(_exhaustive)}`); + } } } @@ -2365,6 +2385,10 @@ function assertPublicJwkMatchesRequestedAlgorithm( throw new Error('Public JWK algorithm does not match requested import algorithm'); } return; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled PublicKeyImportInput kind: ${String(_exhaustive)}`); + } } } @@ -2408,5 +2432,9 @@ function assertPrivateJwkMatchesRequestedAlgorithm( throw new Error('Private JWK algorithm does not match requested import algorithm'); } return; + default: { + const _exhaustive: never = algorithm; + throw new Error(`Unhandled PrivateKeyImportInput kind: ${String(_exhaustive)}`); + } } } diff --git a/src/revocation/chain.ts b/src/revocation/chain.ts index e7da3024..3dc6ccad 100644 --- a/src/revocation/chain.ts +++ b/src/revocation/chain.ts @@ -683,6 +683,10 @@ function ocspIndeterminateReasonFromFailure( case 'nonce_mismatch': case 'request_mismatch': return 'no_applicable_ocsp'; + default: { + const _exhaustive: never = code; + throw new Error(`Unhandled ValidateOcspResponse failure code: ${String(_exhaustive)}`); + } } } diff --git a/src/revocation/crl.ts b/src/revocation/crl.ts index 7f354c92..3ea25c69 100644 --- a/src/revocation/crl.ts +++ b/src/revocation/crl.ts @@ -85,6 +85,7 @@ import type { ParsedDistributionPoint, ParsedDistributionPointName, ParsedIssuingDistributionPoint, + ParsedIssuingDistributionPointScope, ParsedName, ParsedNameAttribute, ParsedRelativeDistinguishedName, @@ -2035,32 +2036,62 @@ function parseIssuingDistributionPoint(valueDer: Uint8Array): ParsedIssuingDistr for (const child of childrenOf(valueDer, sequenceElement)) { parseIssuingDistributionPointField(valueDer, child, fields); } - const scopeFlags = [ - fields.onlyContainsUserCerts, - fields.onlyContainsCACerts, - fields.onlyContainsAttributeCerts, - ].filter((value) => value === true).length; - if (scopeFlags > 1) { - throw new Error('IssuingDistributionPoint scope booleans are mutually exclusive'); - } return { ...(fields.distributionPoint === undefined ? {} : { distributionPoint: fields.distributionPoint }), - ...(fields.onlyContainsUserCerts === undefined - ? {} - : { onlyContainsUserCerts: fields.onlyContainsUserCerts }), - ...(fields.onlyContainsCACerts === undefined - ? {} - : { onlyContainsCACerts: fields.onlyContainsCACerts }), ...(fields.onlySomeReasons === undefined ? {} : { onlySomeReasons: fields.onlySomeReasons }), ...(fields.indirectCrl === undefined ? {} : { indirectCrl: fields.indirectCrl }), - ...(fields.onlyContainsAttributeCerts === undefined + ...parseIssuingDistributionPointScope(fields), + }; +} + +/** RFC 5280 §5.2.5: at most one `onlyContains*` flag may be TRUE. */ +function parseIssuingDistributionPointScope( + fields: MutableIssuingDistributionPointFields, +): ParsedIssuingDistributionPointScope { + const userCerts = fields.onlyContainsUserCerts; + const caCerts = fields.onlyContainsCACerts; + const attributeCerts = fields.onlyContainsAttributeCerts; + if (userCerts === true) { + if (caCerts === true || attributeCerts === true) { + throw new Error(IDP_SCOPE_CONFLICT); + } + return { onlyContainsUserCerts: true, ...unselectedScopeFlags({ caCerts, attributeCerts }) }; + } + if (caCerts === true) { + if (attributeCerts === true) { + throw new Error(IDP_SCOPE_CONFLICT); + } + return { onlyContainsCACerts: true, ...unselectedScopeFlags({ userCerts, attributeCerts }) }; + } + if (attributeCerts === true) { + return { onlyContainsAttributeCerts: true, ...unselectedScopeFlags({ userCerts, caCerts }) }; + } + return unselectedScopeFlags({ userCerts, caCerts, attributeCerts }); +} + +/** Keeps the explicit-FALSE flags the encoding carried, omitting the ones it left out. */ +function unselectedScopeFlags(flags: { + readonly userCerts?: false; + readonly caCerts?: false; + readonly attributeCerts?: false; +}): { + readonly onlyContainsUserCerts?: false; + readonly onlyContainsCACerts?: false; + readonly onlyContainsAttributeCerts?: false; +} { + return { + ...(flags.userCerts === undefined ? {} : { onlyContainsUserCerts: flags.userCerts }), + ...(flags.caCerts === undefined ? {} : { onlyContainsCACerts: flags.caCerts }), + ...(flags.attributeCerts === undefined ? {} - : { onlyContainsAttributeCerts: fields.onlyContainsAttributeCerts }), + : { onlyContainsAttributeCerts: flags.attributeCerts }), }; } +const IDP_SCOPE_CONFLICT = 'IssuingDistributionPoint scope booleans are mutually exclusive'; + function parseIssuingDistributionPointField( valueDer: Uint8Array, child: DerElement, @@ -2319,21 +2350,29 @@ function encodeDistributionPointName( if (value === undefined) { throw new Error('IssuingDistributionPoint distributionPoint is required'); } - if (value.type === 'fullName') { - if (value.fullName.length === 0) { - throwCrlEncoderError( - 'distribution_point_full_name_empty', - 'DistributionPointName fullName must not be empty', + switch (value.type) { + case 'fullName': { + if (value.fullName.length === 0) { + throwCrlEncoderError( + 'distribution_point_full_name_empty', + 'DistributionPointName fullName must not be empty', + ); + } + return implicitConstructedContext(0, concatGeneralNames(value.fullName)); + } + case 'relativeName': { + const relativeName = encodeRelativeDistinguishedName(value.relativeName); + const relativeNameElement = readElement(relativeName); + return implicitConstructedContext( + 1, + relativeName.slice(relativeNameElement.start, relativeNameElement.end), ); } - return implicitConstructedContext(0, concatGeneralNames(value.fullName)); + default: { + const _exhaustive: never = value; + throw new Error(`Unhandled DistributionPointName type: ${String(_exhaustive)}`); + } } - const relativeName = encodeRelativeDistinguishedName(value.relativeName); - const relativeNameElement = readElement(relativeName); - return implicitConstructedContext( - 1, - relativeName.slice(relativeNameElement.start, relativeNameElement.end), - ); } /** DER-encodes and concatenates a list of GeneralName values. */ diff --git a/src/revocation/index.ts b/src/revocation/index.ts index 81e76785..d14a07a7 100644 --- a/src/revocation/index.ts +++ b/src/revocation/index.ts @@ -145,4 +145,8 @@ export type { IssuingDistributionPointForUserCerts, } from '#micro509/x509/extensions'; -export type { ParsedIssuingDistributionPoint } from '#micro509/x509/parse'; +export type { + ParsedIssuingDistributionPoint, + ParsedIssuingDistributionPointBase, + ParsedIssuingDistributionPointScope, +} from '#micro509/x509/parse'; diff --git a/src/revocation/ocsp.ts b/src/revocation/ocsp.ts index 1c778bbc..e24b0a18 100644 --- a/src/revocation/ocsp.ts +++ b/src/revocation/ocsp.ts @@ -1627,6 +1627,10 @@ function encodeOcspCertStatus(input: CreateOcspSingleResponseInput): Uint8Array } return tlv(0xa1, concatBytes(revokedFields)); } + default: { + const _exhaustive: never = input; + throw new Error(`Unhandled CertStatus type: ${String(_exhaustive)}`); + } } } diff --git a/src/x509/certificate.ts b/src/x509/certificate.ts index 87c07236..a9b5b4c4 100644 --- a/src/x509/certificate.ts +++ b/src/x509/certificate.ts @@ -121,23 +121,42 @@ export interface CreateCertificateInput { /** * Input for {@linkcode createSelfSignedCertificate}. */ -export interface CreateSelfSignedCertificateInput { +export type CreateSelfSignedCertificateInput = CreateSelfSignedCertificateBase & + SelfSignedKeySource; + +/** + * Where {@linkcode createSelfSignedCertificate} gets its key pair. + * + * Supplying `keyPair` makes `algorithm` unreachable, since generation is skipped. + */ +export type SelfSignedKeySource = + | { + /** + * Existing key pair to reuse for both subject and issuer. + */ + readonly keyPair: KeyPairMaterial; + /** + * Unavailable in this variant; the supplied `keyPair` is used as-is. + */ + readonly algorithm?: never; + } + | { + /** + * Generate a new key pair for both subject and issuer. + */ + readonly keyPair?: never; + /** + * Key generation parameters. Defaults to the {@linkcode generateKeyPair} default. + */ + readonly algorithm?: KeyAlgorithmInput; + }; + +/** Fields common to both {@linkcode SelfSignedKeySource} variants. */ +export interface CreateSelfSignedCertificateBase { /** * Subject distinguished name used as both subject and issuer. */ readonly subject: NameInput; - /** - * Key generation parameters. - * - * Ignored when `keyPair` is provided. - */ - readonly algorithm?: KeyAlgorithmInput; - /** - * Existing key pair to reuse for both subject and issuer. - * - * When omitted, a new key pair is generated. - */ - readonly keyPair?: KeyPairMaterial; /** * Validity window configuration. */ diff --git a/src/x509/extensions.ts b/src/x509/extensions.ts index 7a9e4a56..9aa680de 100644 --- a/src/x509/extensions.ts +++ b/src/x509/extensions.ts @@ -1671,21 +1671,29 @@ function encodeDistributionPoint(point: DistributionPoint): Uint8Array[] { /** DER-encode a DistributionPointName (fullName or relativeName). */ function encodeDistributionPointName(name: DistributionPointName): Uint8Array { - if (name.type === 'fullName') { - if (name.fullName.length === 0) { - throwExtensionEncoderError( - 'distribution_point_full_name_empty', - 'DistributionPointName fullName must not be empty', + switch (name.type) { + case 'fullName': { + if (name.fullName.length === 0) { + throwExtensionEncoderError( + 'distribution_point_full_name_empty', + 'DistributionPointName fullName must not be empty', + ); + } + return implicitConstructedContext(0, concatBytes(name.fullName.map(encodeSubjectAltName))); + } + case 'relativeName': { + const relativeName = encodeRelativeDistinguishedName(name.relativeName); + const relativeNameElement = readElement(relativeName); + return implicitConstructedContext( + 1, + relativeName.slice(relativeNameElement.start, relativeNameElement.end), ); } - return implicitConstructedContext(0, concatBytes(name.fullName.map(encodeSubjectAltName))); + default: { + const _exhaustive: never = name; + throw new Error(`Unhandled DistributionPointName type: ${String(_exhaustive)}`); + } } - const relativeName = encodeRelativeDistinguishedName(name.relativeName); - const relativeNameElement = readElement(relativeName); - return implicitConstructedContext( - 1, - relativeName.slice(relativeNameElement.start, relativeNameElement.end), - ); } /** DER-encode a NameConstraintForm as an implicit-tagged {@linkcode GeneralName}. */ diff --git a/src/x509/index.ts b/src/x509/index.ts index 0a078fbd..5a31401e 100644 --- a/src/x509/index.ts +++ b/src/x509/index.ts @@ -13,8 +13,10 @@ export type { CertificateMaterial, CreateCertificateErrorCode, CreateCertificateInput, + CreateSelfSignedCertificateBase, CreateSelfSignedCertificateInput, SelfSignedCertificateResult, + SelfSignedKeySource, SignatureProfileInput, ValidityInput, } from '#micro509/x509/certificate'; diff --git a/src/x509/name-text.ts b/src/x509/name-text.ts index 6ff7ad17..2b070e54 100644 --- a/src/x509/name-text.ts +++ b/src/x509/name-text.ts @@ -68,6 +68,10 @@ export function subjectAltNameLabel(name: SubjectAltName): string { return 'DirName'; case 'unknown': return `[tag ${String(name.tag)}]`; + default: { + const _exhaustive: never = name; + throw new Error(`Unhandled SubjectAltName type: ${String(_exhaustive)}`); + } } } @@ -135,6 +139,10 @@ function subjectAltNameText(name: SubjectAltName): string { return directoryNameText(name.derHex); case 'unknown': return toHex(name.value); + default: { + const _exhaustive: never = name; + throw new Error(`Unhandled SubjectAltName type: ${String(_exhaustive)}`); + } } } diff --git a/src/x509/parse.ts b/src/x509/parse.ts index 381f8716..604c5083 100644 --- a/src/x509/parse.ts +++ b/src/x509/parse.ts @@ -221,21 +221,61 @@ export interface ParsedDistributionPoint { * Decoded Issuing Distribution Point CRL extension (RFC 5280 §5.2.5). * Constrains which certificates a CRL covers (scope, reasons, indirection). */ -export interface ParsedIssuingDistributionPoint { +export type ParsedIssuingDistributionPoint = ParsedIssuingDistributionPointBase & + ParsedIssuingDistributionPointScope; + +/** Scope-independent fields of a decoded Issuing Distribution Point. */ +export interface ParsedIssuingDistributionPointBase { /** Where to fetch this CRL, if specified. */ readonly distributionPoint?: ParsedDistributionPointName; - /** When true, this CRL only covers end-entity certificates. Default false. */ - readonly onlyContainsUserCerts?: boolean; - /** When true, this CRL only covers CA certificates. Default false. */ - readonly onlyContainsCACerts?: boolean; /** Limits the CRL to these revocation reasons. Absent means all reasons. */ readonly onlySomeReasons?: ParsedBitFlags; /** When true, this CRL may contain entries from CAs other than the issuer. Default false. */ readonly indirectCrl?: boolean; - /** When true, this CRL only covers attribute certificates. Default false. */ - readonly onlyContainsAttributeCerts?: boolean; } +/** + * Which certificate kind a CRL is scoped to. RFC 5280 §5.2.5 allows at most one + * of `onlyContainsUserCerts`, `onlyContainsCACerts`, and + * `onlyContainsAttributeCerts` to be TRUE, so the union admits one at a time. + * + * A flag is absent when the encoding omitted it and `false` when the encoding + * carried an explicit FALSE. + */ +export type ParsedIssuingDistributionPointScope = + | { + /** No scope restriction; this CRL covers every certificate kind. */ + readonly onlyContainsUserCerts?: false; + /** No scope restriction. */ + readonly onlyContainsCACerts?: false; + /** No scope restriction. */ + readonly onlyContainsAttributeCerts?: false; + } + | { + /** This CRL only covers end-entity certificates. */ + readonly onlyContainsUserCerts: true; + /** Excluded by the user-cert scope. */ + readonly onlyContainsCACerts?: false; + /** Excluded by the user-cert scope. */ + readonly onlyContainsAttributeCerts?: false; + } + | { + /** Excluded by the CA-cert scope. */ + readonly onlyContainsUserCerts?: false; + /** This CRL only covers CA certificates. */ + readonly onlyContainsCACerts: true; + /** Excluded by the CA-cert scope. */ + readonly onlyContainsAttributeCerts?: false; + } + | { + /** Excluded by the attribute-cert scope. */ + readonly onlyContainsUserCerts?: false; + /** Excluded by the attribute-cert scope. */ + readonly onlyContainsCACerts?: false; + /** This CRL only covers attribute certificates. */ + readonly onlyContainsAttributeCerts: true; + }; + /** A raw X.509v3 extension before type-specific decoding. */ export interface ParsedExtension { /** Dotted-decimal OID identifying this extension. */ @@ -1296,6 +1336,10 @@ export async function matchCertificatePrivateKey< 'key_type_mismatch', "Private key algorithm does not match the certificate's subject public key algorithm", ); + default: { + const _exhaustive: never = comparison; + throw new Error(`Unhandled key comparison result: ${String(_exhaustive)}`); + } } } diff --git a/test/crl.test.ts b/test/crl.test.ts index e450101f..8104dac5 100644 --- a/test/crl.test.ts +++ b/test/crl.test.ts @@ -3483,6 +3483,54 @@ describe('crl', () => { ).toThrow('IssuingDistributionPoint scope booleans are mutually exclusive'); }); + it('preserves explicitly encoded false issuingDistributionPoint scope booleans', async () => { + const ca = await createSelfSignedCertificate({ + subject: { commonName: 'Explicit False IDP Scope CA' }, + extensions: { + basicConstraints: { ca: true }, + keyUsage: ['keyCertSign', 'cRLSign'], + }, + }); + const crl = await createCertificateRevocationList({ + issuer: { commonName: 'Explicit False IDP Scope CA' }, + signerPrivateKey: ca.keyPair.privateKey, + issuerPublicKey: ca.keyPair.publicKey, + issuingDistributionPoint: { onlyContainsUserCerts: true }, + }); + const crlDer = new Uint8Array(pemDecodeOrThrow('X509 CRL', crl.pem)); + const allFalse = rewriteCrlExtensionValuePayload( + crlDer, + OIDS.issuingDistributionPoint, + sequence([ + tlv(0x81, Uint8Array.of(0x00)), + tlv(0x82, Uint8Array.of(0x00)), + tlv(0x85, Uint8Array.of(0x00)), + ]), + ); + const userCertsOnly = rewriteCrlExtensionValuePayload( + crlDer, + OIDS.issuingDistributionPoint, + sequence([ + tlv(0x81, Uint8Array.of(0xff)), + tlv(0x82, Uint8Array.of(0x00)), + tlv(0x85, Uint8Array.of(0x00)), + ]), + ); + + expect(parseCertificateRevocationListDerOrThrow(allFalse).issuingDistributionPoint).toEqual({ + onlyContainsUserCerts: false, + onlyContainsCACerts: false, + onlyContainsAttributeCerts: false, + }); + expect( + parseCertificateRevocationListDerOrThrow(userCertsOnly).issuingDistributionPoint, + ).toEqual({ + onlyContainsUserCerts: true, + onlyContainsCACerts: false, + onlyContainsAttributeCerts: false, + }); + }); + it('parseCertificateRevocationListDerOrThrow rejects unsupported issuingDistributionPoint distributionPointName tags', async () => { const ca = await createSelfSignedCertificate({ subject: { commonName: 'Bad IDP Name Tag CA' }, diff --git a/test/root-barrel.types.ts b/test/root-barrel.types.ts index 8711ef5e..f8bb214d 100644 --- a/test/root-barrel.types.ts +++ b/test/root-barrel.types.ts @@ -2,15 +2,24 @@ import type { CreateCertificateErrorCode, CreateCertificateInput, CreatePfxInput, + CreateSelfSignedCertificateBase, + CreateSelfSignedCertificateInput, CrlEncoderErrorCode, ExtensionEncoderErrorCode, + KeyAlgorithmInput, + KeyPairMaterial, NameEncoderErrorCode, + ParsedIssuingDistributionPointScope, Result, VerifyCertificateChainInput, } from '#micro509'; import type { SignatureProfileInput } from '#micro509/internal/crypto/signing'; import type { ParsedPkcs12MacData } from '#micro509/pkcs'; +type Assert = Condition; +type IsAssignable = [Source] extends [Target] ? true : false; +type IsNotAssignable = [Source] extends [Target] ? false : true; + type RootPkcs12MacData = ParsedPkcs12MacData; type RootSignatureProfileInput = SignatureProfileInput; @@ -25,6 +34,39 @@ function assertRootTypes(_input: { readonly extensionError?: ExtensionEncoderErrorCode; readonly nameError?: NameEncoderErrorCode; readonly crlError?: CrlEncoderErrorCode; + readonly selfSignedExistingKeyPair?: Assert< + IsAssignable< + CreateSelfSignedCertificateBase & { readonly keyPair: KeyPairMaterial }, + CreateSelfSignedCertificateInput + > + >; + readonly selfSignedGeneratedKeyPair?: Assert< + IsAssignable< + CreateSelfSignedCertificateBase & { readonly algorithm: KeyAlgorithmInput }, + CreateSelfSignedCertificateInput + > + >; + readonly selfSignedRejectsBothKeySources?: Assert< + IsNotAssignable< + CreateSelfSignedCertificateBase & { + readonly keyPair: KeyPairMaterial; + readonly algorithm: KeyAlgorithmInput; + }, + CreateSelfSignedCertificateInput + > + >; + readonly issuingDistributionPointAcceptsOneScope?: Assert< + IsAssignable<{ readonly onlyContainsUserCerts: true }, ParsedIssuingDistributionPointScope> + >; + readonly issuingDistributionPointRejectsConflictingScopes?: Assert< + IsNotAssignable< + { + readonly onlyContainsUserCerts: true; + readonly onlyContainsCACerts: true; + }, + ParsedIssuingDistributionPointScope + > + >; }): void {} assertRootTypes({ @@ -32,4 +74,9 @@ assertRootTypes({ extensionError: 'key_usage_empty', nameError: 'invalid_country_code', crlError: 'distribution_point_full_name_empty', + selfSignedExistingKeyPair: true, + selfSignedGeneratedKeyPair: true, + selfSignedRejectsBothKeySources: true, + issuingDistributionPointAcceptsOneScope: true, + issuingDistributionPointRejectsConflictingScopes: true, }); From c231814ad02943b6b6a36b7ff0c1bb8b56440d84 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 11:48:11 +0200 Subject: [PATCH 07/11] fix(ocsp): reject status-field mismatches Disallow revocation-only fields on good and unknown OCSP builder inputs, including structurally typed values that bypass excess-property checks. Add compile-time coverage and document the exported type contract migrations in the changelog. --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ src/revocation/ocsp.ts | 8 ++++++++ test/root-barrel.types.ts | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa9b8e40..2c8215ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Tighten four exported TypeScript contracts to make invalid states + unrepresentable. These changes can require source updates: + - `CrlEncoderErrorCode` now contains only + `'distribution_point_full_name_empty'`. + `'distribution_point_name_conflict'` and + `'distribution_point_name_empty'` are removed because + `DistributionPointName` is now a discriminated union that cannot express + either invalid shape. + - `ParsedOcspSingleResponse` is now discriminated by `certStatus`. + `revokedAt` and `revocationReasonCode` are available only after narrowing to + `certStatus === 'revoked'`; `revokedAt` is then required. + - `CreateOcspCertStatusInput` rejects `revokedAt` and + `revocationReasonCode` unless `certStatus` is `'revoked'`, including when a + previously declared object is passed instead of an object literal. + - `CreateSelfSignedCertificateInput` no longer accepts both `keyPair` and + `algorithm`. Supply `keyPair` to reuse existing keys, or `algorithm` to + generate a new pair. + + ```ts + if (singleResponse.certStatus === 'revoked') { + singleResponse.revokedAt; // Date + singleResponse.revocationReasonCode; // number | undefined + } + + await createSelfSignedCertificate({ subject, keyPair }); + await createSelfSignedCertificate({ + subject, + algorithm: { kind: 'ecdsa', curve: 'P-256' }, + }); + ``` + - `ParsedPkcs7SignedData.certificates: readonly ParsedCertificate[]` becomes `certificateChoices: readonly ParsedCertificateChoice[]`, modelling RFC 5652 §10.2.2 CertificateChoices as a discriminated union rather than discarding diff --git a/src/revocation/ocsp.ts b/src/revocation/ocsp.ts index e24b0a18..f003d91e 100644 --- a/src/revocation/ocsp.ts +++ b/src/revocation/ocsp.ts @@ -261,6 +261,10 @@ export type CreateOcspCertStatusInput = | { /** Assert the certificate is not revoked. */ readonly certStatus: 'good'; + /** Unavailable unless `certStatus` is `'revoked'`. */ + readonly revokedAt?: never; + /** Unavailable unless `certStatus` is `'revoked'`. */ + readonly revocationReasonCode?: never; } | { /** Assert the certificate is revoked. */ @@ -273,6 +277,10 @@ export type CreateOcspCertStatusInput = | { /** Assert no record of the certificate exists. */ readonly certStatus: 'unknown'; + /** Unavailable unless `certStatus` is `'revoked'`. */ + readonly revokedAt?: never; + /** Unavailable unless `certStatus` is `'revoked'`. */ + readonly revocationReasonCode?: never; }; /** diff --git a/test/root-barrel.types.ts b/test/root-barrel.types.ts index f8bb214d..2d5c5f93 100644 --- a/test/root-barrel.types.ts +++ b/test/root-barrel.types.ts @@ -1,6 +1,7 @@ import type { CreateCertificateErrorCode, CreateCertificateInput, + CreateOcspCertStatusInput, CreatePfxInput, CreateSelfSignedCertificateBase, CreateSelfSignedCertificateInput, @@ -67,6 +68,36 @@ function assertRootTypes(_input: { ParsedIssuingDistributionPointScope > >; + readonly ocspAcceptsRevocationFieldsForRevoked?: Assert< + IsAssignable< + { + readonly certStatus: 'revoked'; + readonly revokedAt: Date; + readonly revocationReasonCode: number; + }, + CreateOcspCertStatusInput + > + >; + readonly ocspRejectsRevocationFieldsForGood?: Assert< + IsNotAssignable< + { + readonly certStatus: 'good'; + readonly revokedAt: Date; + readonly revocationReasonCode: number; + }, + CreateOcspCertStatusInput + > + >; + readonly ocspRejectsRevocationFieldsForUnknown?: Assert< + IsNotAssignable< + { + readonly certStatus: 'unknown'; + readonly revokedAt: Date; + readonly revocationReasonCode: number; + }, + CreateOcspCertStatusInput + > + >; }): void {} assertRootTypes({ @@ -79,4 +110,7 @@ assertRootTypes({ selfSignedRejectsBothKeySources: true, issuingDistributionPointAcceptsOneScope: true, issuingDistributionPointRejectsConflictingScopes: true, + ocspAcceptsRevocationFieldsForRevoked: true, + ocspRejectsRevocationFieldsForGood: true, + ocspRejectsRevocationFieldsForUnknown: true, }); From 4d6ca520356aa82c0eb84c03090a859d5c23a61a Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 12:02:01 +0200 Subject: [PATCH 08/11] fix(pkcs): enforce certificate set bounds Parse certificate choices through the bounded child iterator so a malformed entry cannot consume bytes from the following SignedData field. Cover the overrun and keep verification fixtures type-safe. --- src/pkcs/pkcs7.ts | 15 +++++++-------- test/pkcs7.test.ts | 20 ++++++++++++++++++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/pkcs/pkcs7.ts b/src/pkcs/pkcs7.ts index 5a5e514b..2b6adebb 100644 --- a/src/pkcs/pkcs7.ts +++ b/src/pkcs/pkcs7.ts @@ -1070,14 +1070,13 @@ function parseCertificateSet( if (certificates === undefined || certificates.tag !== 0xa0) { return []; } - const parsed: ParsedCertificateChoice[] = []; - let offset = certificates.start; - while (offset < certificates.end) { - const element = readElement(source, offset); - parsed.push(parseCertificateChoice(source, element, source.slice(offset, element.end))); - offset = element.end; - } - return parsed; + return childrenOf(source, certificates).map((element) => + parseCertificateChoice( + source, + element, + source.slice(element.start - element.headerLength, element.end), + ), + ); } /** Extracts the list of digest algorithm OIDs from the digestAlgorithms SET. */ diff --git a/test/pkcs7.test.ts b/test/pkcs7.test.ts index 1a6cee3b..9fff2e73 100644 --- a/test/pkcs7.test.ts +++ b/test/pkcs7.test.ts @@ -5,6 +5,7 @@ import { createPkcs7CertBag, createSelfSignedCertificate, generateKeyPair, + type ParsedPkcs7SignedData, parseCertificatePem, parsePkcs7CertBagDer, parsePkcs7CertBagPem, @@ -204,6 +205,21 @@ describe('pkcs7', () => { expect(parsed.error.code).toBe('malformed'); }); + it('rejects a CertificateChoices entry that overruns the CertificateSet boundary', () => { + const signedData = sequence([ + integerFromNumber(1), + setOf([sequence([objectIdentifier(OIDS.sha256)])]), + sequence([objectIdentifier(OIDS.pkcs7Data)]), + // The [1] child claims two content bytes, which overlap the following + // empty signerInfos SET beyond the two-byte CertificateSet contents. + Uint8Array.of(0xa0, 0x02, 0xa1, 0x02), + setOf([]), + ]); + const der = sequence([objectIdentifier(OIDS.pkcs7SignedData), explicitContext(0, signedData)]); + const parsed = parsePkcs7SignedDataDer(der); + expect(parsed).toMatchObject({ ok: false, code: 'malformed' }); + }); + // ----------------------------------------------------------------------- // Parse error paths // ----------------------------------------------------------------------- @@ -396,9 +412,9 @@ describe('pkcs7', () => { const otherParsed = unwrap(parseCertificatePem(other.certificate.pem)); const tampered = { ...parsed.value, - certificates: [otherParsed], + certificateChoices: [{ type: 'certificate', certificate: otherParsed }], encapsulatedContent: new TextEncoder().encode('test'), - }; + } satisfies ParsedPkcs7SignedData; const result = await verifyPkcs7SignedData(tampered); expect(result.ok).toBe(true); }); From 302d0c4995bc33638a55762ce438637850cbf086 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 12:20:19 +0200 Subject: [PATCH 09/11] test: cover runtime exhaustiveness guards Exercise invalid runtime variants across key, extension, revocation, and crypto helpers so closed-union fallthrough regressions fail explicitly. --- test/runtime-exhaustiveness.test.ts | 261 ++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 test/runtime-exhaustiveness.test.ts diff --git a/test/runtime-exhaustiveness.test.ts b/test/runtime-exhaustiveness.test.ts new file mode 100644 index 00000000..dc88dea2 --- /dev/null +++ b/test/runtime-exhaustiveness.test.ts @@ -0,0 +1,261 @@ +import { describe, expect, it } from 'bun:test'; +import { + createCertificateRevocationList, + createOcspResponse, + createSelfSignedCertificate, + exportPkcs8Der, + exportPrivateJwk, + exportPublicJwk, + exportSpkiDer, + generateKeyPair, + importPkcs8DerOrThrow, + importPrivateJwkOrThrow, + importPublicJwkOrThrow, + importSpkiDerOrThrow, + subjectAltNameLabel, + subjectAltNameToString, +} from '#micro509'; +import { encodePbes2AlgorithmIdentifier } from '#micro509/internal/crypto/pbes2'; +import { encodeRsaPssParameters, rsaPssParametersForHash } from '#micro509/internal/crypto/rsa-pss'; +import { encodeCrlDistributionPoints } from '#micro509/x509/extensions'; + +interface RuntimeGuardCase { + readonly name: string; + readonly expectedMessage: string; + readonly run: () => unknown; +} + +interface AsyncRuntimeGuardCase { + readonly name: string; + readonly expectedMessage: string; + readonly run: () => Promise; +} + +interface KeyFixtures { + readonly spki: Uint8Array; + readonly pkcs8: Uint8Array; + readonly publicJwk: JsonWebKey; + readonly privateJwk: JsonWebKey; +} + +async function expectRejectedMessage( + run: () => Promise, + expectedMessage: string, +): Promise { + try { + await run(); + } catch (error) { + expect(error).toBeInstanceOf(Error); + if (!(error instanceof Error)) throw new Error('unreachable'); + expect(error.message).toContain(expectedMessage); + return; + } + throw new Error(`Expected rejection containing: ${expectedMessage}`); +} + +let keyFixturesPromise: Promise | undefined; + +function getKeyFixtures(): Promise { + keyFixturesPromise ??= (async () => { + const keyPair = await generateKeyPair(); + return { + spki: await exportSpkiDer(keyPair.publicKey), + pkcs8: await exportPkcs8Der(keyPair.privateKey), + publicJwk: await exportPublicJwk(keyPair.publicKey), + privateJwk: await exportPrivateJwk(keyPair.privateKey), + }; + })(); + return keyFixturesPromise; +} + +type SignerFixture = Awaited>; + +let signerFixturePromise: Promise | undefined; + +function getSignerFixture(): Promise { + signerFixturePromise ??= createSelfSignedCertificate({ + subject: { commonName: 'Runtime Guard Signer' }, + extensions: { + basicConstraints: { ca: true, pathLength: 0 }, + keyUsage: ['keyCertSign', 'cRLSign'], + }, + }); + return signerFixturePromise; +} + +describe('runtime exhaustiveness guards', () => { + const synchronousCases = [ + { + name: 'RSA-PSS profile hash', + expectedMessage: 'Unhandled RsaPssHash', + run: () => Reflect.apply(rsaPssParametersForHash, undefined, ['SHA-999']), + }, + { + name: 'RSA-PSS encoder hash', + expectedMessage: 'Unhandled RsaPssHash', + run: () => + Reflect.apply(encodeRsaPssParameters, undefined, [ + { + hash: 'SHA-999', + mgfHash: 'SHA-999', + saltLength: 32, + trailerField: 1, + }, + ]), + }, + { + name: 'PBES2 PRF', + expectedMessage: 'Unhandled Pbes2Prf', + run: () => + Reflect.apply(encodePbes2AlgorithmIdentifier, undefined, [ + { + iterations: 1, + salt: Uint8Array.of(1), + iv: new Uint8Array(16), + cipher: 'AES-128-CBC', + prf: 'HMAC-SHA-999', + }, + ]), + }, + { + name: 'subjectAltNameLabel variant', + expectedMessage: 'Unhandled SubjectAltName type', + run: () => Reflect.apply(subjectAltNameLabel, undefined, [{ type: 'unsupported' }]), + }, + { + name: 'subjectAltNameToString variant', + expectedMessage: 'Unhandled SubjectAltName type', + run: () => Reflect.apply(subjectAltNameToString, undefined, [{ type: 'unsupported' }]), + }, + { + name: 'CRL distribution-point variant', + expectedMessage: 'Unhandled DistributionPointName type', + run: () => + Reflect.apply(encodeCrlDistributionPoints, undefined, [ + [{ distributionPoint: { type: 'unsupported' } }], + ]), + }, + { + name: 'late empty CRL fullName', + expectedMessage: 'DistributionPointName fullName must not be empty', + run: () => { + let reads = 0; + const distributionPoint = { + type: 'fullName', + get fullName() { + reads += 1; + return reads === 1 ? [{ type: 'dns', value: 'crl.example' }] : []; + }, + }; + return Reflect.apply(encodeCrlDistributionPoints, undefined, [[{ distributionPoint }]]); + }, + }, + ] satisfies RuntimeGuardCase[]; + + it.each(synchronousCases)('throws for an unhandled $name', ({ run, expectedMessage }) => { + expect(run).toThrow(expectedMessage); + }); + + const asynchronousCases = [ + { + name: 'key generation', + expectedMessage: 'Unhandled KeyAlgorithmInput kind', + run: () => Reflect.apply(generateKeyPair, undefined, [{ kind: 'unsupported' }]), + }, + { + name: 'SPKI algorithm assertion', + expectedMessage: 'Unhandled PublicKeyImportInput kind', + run: async () => { + const { spki } = await getKeyFixtures(); + return Reflect.apply(importSpkiDerOrThrow, undefined, [spki, { kind: 'unsupported' }]); + }, + }, + { + name: 'PKCS#8 algorithm assertion', + expectedMessage: 'Unhandled PrivateKeyImportInput kind', + run: async () => { + const { pkcs8 } = await getKeyFixtures(); + return Reflect.apply(importPkcs8DerOrThrow, undefined, [pkcs8, { kind: 'unsupported' }]); + }, + }, + { + name: 'public JWK algorithm assertion', + expectedMessage: 'Unhandled PublicKeyImportInput kind', + run: async () => { + const { publicJwk } = await getKeyFixtures(); + return Reflect.apply(importPublicJwkOrThrow, undefined, [ + publicJwk, + { kind: 'unsupported' }, + ]); + }, + }, + { + name: 'private JWK algorithm assertion', + expectedMessage: 'Unhandled PrivateKeyImportInput kind', + run: async () => { + const { privateJwk } = await getKeyFixtures(); + return Reflect.apply(importPrivateJwkOrThrow, undefined, [ + privateJwk, + { kind: 'unsupported' }, + ]); + }, + }, + { + name: 'WebCrypto import algorithm mapping', + expectedMessage: 'Malformed SubjectPublicKeyInfo', + run: async () => { + const { spki } = await getKeyFixtures(); + let reads = 0; + const algorithm = { + curve: 'P-256', + get kind() { + reads += 1; + return reads === 1 ? 'ecdsa' : 'unsupported'; + }, + }; + return Reflect.apply(importSpkiDerOrThrow, undefined, [spki, algorithm]); + }, + }, + { + name: 'CRL distribution-point variant', + expectedMessage: 'Unhandled DistributionPointName type', + run: async () => { + const signer = await getSignerFixture(); + return Reflect.apply(createCertificateRevocationList, undefined, [ + { + issuer: { commonName: 'Runtime Guard Signer' }, + signerPrivateKey: signer.keyPair.privateKey, + issuerPublicKey: signer.keyPair.publicKey, + issuingDistributionPoint: { + distributionPoint: { type: 'unsupported' }, + }, + }, + ]); + }, + }, + { + name: 'OCSP certificate status variant', + expectedMessage: 'Unhandled CertStatus type', + run: async () => { + const signer = await getSignerFixture(); + return Reflect.apply(createOcspResponse, undefined, [ + { + signerPrivateKey: signer.keyPair.privateKey, + signerCertificate: signer.certificate.pem, + responses: [ + { + certificate: signer.certificate.pem, + issuerCertificate: signer.certificate.pem, + certStatus: 'unsupported', + }, + ], + }, + ]); + }, + }, + ] satisfies AsyncRuntimeGuardCase[]; + + it.each(asynchronousCases)('rejects an unhandled $name', async ({ run, expectedMessage }) => { + await expectRejectedMessage(run, expectedMessage); + }); +}); From e3ab3fe35fdfa911d879fbf715c602976770f023 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 12:24:36 +0200 Subject: [PATCH 10/11] test(ci): run OpenSSL differential coverage Enable differential verification during the coverage job so CI catches behavioral divergence from OpenSSL on every test run. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84c58bb0..0a8abfd1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,7 @@ jobs: - name: Deno lint + type-check + doc-lint (full source tree) run: run -p check:deno lint:deno docs:lint - run: run test:coverage + env: { DIFFERENTIAL_OPENSSL: "1" } - name: Upload coverage to Codecov uses: codecov/codecov-action@v7 with: { flags: bun, fail_ci_if_error: true, use_oidc: true, report_type: coverage } From b7ec74e1866aa655c5a77fa6d1a680df1f8c5767 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sat, 25 Jul 2026 12:31:57 +0200 Subject: [PATCH 11/11] test(types): isolate OCSP field exclusions Check `revokedAt` and `revocationReasonCode` separately for good and unknown statuses so either field becoming assignable fails the type suite. --- test/root-barrel.types.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/test/root-barrel.types.ts b/test/root-barrel.types.ts index 2d5c5f93..351fb5ca 100644 --- a/test/root-barrel.types.ts +++ b/test/root-barrel.types.ts @@ -78,21 +78,37 @@ function assertRootTypes(_input: { CreateOcspCertStatusInput > >; - readonly ocspRejectsRevocationFieldsForGood?: Assert< + readonly ocspRejectsRevokedAtForGood?: Assert< IsNotAssignable< { readonly certStatus: 'good'; readonly revokedAt: Date; + }, + CreateOcspCertStatusInput + > + >; + readonly ocspRejectsRevocationReasonForGood?: Assert< + IsNotAssignable< + { + readonly certStatus: 'good'; readonly revocationReasonCode: number; }, CreateOcspCertStatusInput > >; - readonly ocspRejectsRevocationFieldsForUnknown?: Assert< + readonly ocspRejectsRevokedAtForUnknown?: Assert< IsNotAssignable< { readonly certStatus: 'unknown'; readonly revokedAt: Date; + }, + CreateOcspCertStatusInput + > + >; + readonly ocspRejectsRevocationReasonForUnknown?: Assert< + IsNotAssignable< + { + readonly certStatus: 'unknown'; readonly revocationReasonCode: number; }, CreateOcspCertStatusInput @@ -111,6 +127,8 @@ assertRootTypes({ issuingDistributionPointAcceptsOneScope: true, issuingDistributionPointRejectsConflictingScopes: true, ocspAcceptsRevocationFieldsForRevoked: true, - ocspRejectsRevocationFieldsForGood: true, - ocspRejectsRevocationFieldsForUnknown: true, + ocspRejectsRevokedAtForGood: true, + ocspRejectsRevocationReasonForGood: true, + ocspRejectsRevokedAtForUnknown: true, + ocspRejectsRevocationReasonForUnknown: true, });