====== PHP RFC: Add CMS Support ======
  * Version: 0.9
  * Date: 2020-05-13
  * Author: Eliot Lear, lear@lear.ch
  * Status: Implemented (PHP 8.0)
  * First Published at: http://wiki.php.net/rfc/add-cms-support
===== Introduction =====
PHP has for some time incorporated support for PKCS#7 sign, verify, encrypt, decrypt, and read operations.  
Cryptographic Message Syntax (CMS) is a newer version of PKCS#7.  Having been around some time, CMS is used in both
email messaging as well as signature verification operations relating to IoT devices.
===== Proposal =====
It is proposed that analogous functions be created for CMS.  These would be as follows:
^ PKCS#7 function        ^ new CMS function ^
|openssl_pkcs7_encrypt() | openssl_cms_encrypt()|
|openssl_pkcs7_decrypt() | openssl_cms_decrypt()|
|openssl_pkcs7_sign() | openssl_cms_sign()|
|openssl_pkcs7_verify () | openssl_cms_verify()|
|openssl_pkcs7_read   () | openssl_cms_read()|
As currently stands, the CMS sign and verify functions now can take as an argument the encoding method (DER/CMS/PEM).
=== Calling Interface ===
function openssl_cms_sign(string $infile, string $outfile, $signcert, $signkey, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, ?string $extracertsfilename = null): bool {}
This function signs a file with an X.509 certificate and key.
Arguments:
  * $infile - the name of the file to be signed
  * $outfile - the name of the file to deposit the results
  * $signcert - the name of the file containing the signing certificate
  * $signkey - the name of file containing the key associated with $signcert
  * $headers - an array of headers to be included in S/MIME output
  * $flags - flags to be passed to cms_sign()
  * $encoding - the encoding of the output file
  * $extracertsfilename - intermediate certificates to be included in the signature
function openssl_cms_verify(string $filename, int $flags = 0, string $signerscerts = UNKNOWN, array $cainfo = UNKNOWN, string $extracerts = UNKNOWN, string $content = UNKNOWN, string $pk7 = UNKNOWN, string $sigfile = UNKNOWN, $encoding = OPENSSL_ENCODING_SMIME ): bool {}
This function verifies a CMS signature, either attached or detached, with the specified encoding.
Arguments: 
  * $filename - the input file
  * $flags - flags that would be passed to cms_verify
  * $signercerts - a file that the signer certificate and optionally intermediate certificates
  * $cainfo - an array containing self-signed certificate authority certificates
  * $extracerts - a file containing additional intermediarte certificates
  * $content - a file pointing to the content when signatures are detached
  * $pk7 - a file to save the signature to
  * $encoding - one of three supported encodings (PEM/DER/SMIME).
Returns TRUE on success and FALSE on failure.
function openssl_cms_encrypt(string $infile, string $outfile, $recipcerts, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME,  int $cipher = OPENSSL_CIPHER_RC2_40): bool {}
This function encrypts content to one or more recipients, based on the certificates that are passed to it.
Arguments:
  * $infile - the file to be encrypted
  * $outfile - the output file
  * $recipcerts - recipients to encrypt to
  * $headers - headers to include when S/MIME is usd
  * $flags - Flags to be passed to CMS_sign
  * $encoding - an encoding to output
  * $cipher - a cypher to use
Return values: TRUE on success or FALSE on failure.
function openssl_cms_decrypt(string $infilename, string $outfilename, $recipcert, $recipkey = UNKNOWN, int $encoding = OPENSSL_ENCODING_SMIME): bool {}
Decrypts a CMS message.
Arguments:
  * $infilename - the name of a file containing encrypted content
  * $outfilename - the name of the file to deposit the decrypted content
  * $recipcert - the name of the file containing a certificate of the recipient
  * $recipkey - the name of the file containing a PKCS#8 key
  * $encoding - the encoding of the input file.
Returns TRUE on success and FALSE on failure.
function openssl_cms_read(string $infilename, &$certs): bool {}
Performs the exact analog to openssl_pkcs7_read().
This is **nearly** identical to the PKCS#7 calling interface, the only exception being $encoding.
===== Backward Incompatible Changes =====
None.
===== Proposed PHP Version(s) =====
PHP 8.0
===== RFC Impact =====
==== To SAPIs ====
The only change is an additional API.  No modifications to existing APIs.
==== To Existing Extensions ====
New functions are added to ext/openssl.  No existing functions are changed.
==== To Opcache ====
No known impact.
==== New Constants ====
Several new constants are defined to indicate encoding, as follows:
  OPENSSL_ENCODING_CMS /* encoding is a CMS-encoded message */
  OPENSSL_ENCODING_DER /* encoding is DER (Distinguished Encoding Rules) */
  OPENSSL_ENCODING_PEM /* encoding is PEM (Privacy-Enhanced Mail) */
The following analogs to PKCS#7 are also added:
  OPENSSL_CMS_DETACHED
  OPENSSL_CMS_TEXT
  OPENSSL_CMS_NOINTERN
  OPENSSL_CMS_NOVERIFY
  OPENSSL_CMS_NOCERTS
  OPENSSL_CMS_NOATTR
  OPENSSL_CMS_BINARY
  OPENSSL_CMS_NOSIGS
  
==== php.ini Defaults ====
No change.
===== Open Issues =====
No known issues.
===== Unaffected PHP Functionality =====
As these are new functions, no side effects to other functions should be expected.
===== Future Scope =====
Currently, as with the PKCS#7 calls, these calls take files as arguments.  Future work should
focus on in-memory signing/encrypting/verifying/decrypting operations.
===== Proposed Voting Choices =====
Include these so readers know where you are heading and can discuss the proposed voting options.
===== Patches and Tests =====
This capability is available for inspection as [[https://github.com/php/php-src/pull/5251|PR #5251]].
Tests are available in that PR.  This PR is subject to change of course, based on community feedback.
===== Proposed Voting Choices =====
Yes/No.
===== Implementation =====
After the project is implemented, this section should contain 
  - the version(s) it was merged into
  - a link to the git commit(s)
  - a link to the PHP manual entry for the feature
  - a link to the language specification section (if any)
===== References =====
  - [[https://www.rfc-editor.org/rfc/rfc5652.html|RFC 5652]]
  - [[https://www.rfc-editor.org/rfc/rfc8520.html|RFC 8520]]
  - [[https://github.com/php/php-src/pull/5251|Git Pull Request 5251]]
===== Rejected Features =====
Keep this updated with features that were discussed on the mail lists.