PKCS7 SMIME Functions OpenSSL Support in PHP

238 not signed with the PHP OpenSSL extension can also be verified with this function, as long as it was signed using the SHA1 message digest algorithm.

9.3.4 PKCS7 SMIME Functions

The final set of functions that the PHP OpenSSL extension offers is for PKCS7, which are provided as structures encapsulated in MIME types defined by SMIME. These functions provide for encryption, decryption, signing, and signature verification using X.509 certificates. The functions were added in PHP 4.0.6. They are not available in prior versions. These functions require use of the OpenSSL PRNG, and the PRNG must be seeded before you can use them safely. Unfortunately, there is no way to do this with PHP itself, as detailed in the warning in the previous section. bool openssl_pkcs7_encryptstring infile, string outfile, mixed certs, array headers [, long flags] This function encrypts the data contained in the file named by the first argument, infile , and places it in the file named by the second argument, outfile . The encryption always uses a weak RC2 40-bit cipher, which is a limitation of the PHP interface. SMIMEv2 supports both RC2 40-bit and 3DES, but the PHP implementation has unfortunately chosen to restrict the cipher to the weaker of the two. Public keys to use for encryption are obtained from the third argument, certs . The certificates to use for encryption are specified as an array, allowing for multiple recipients of the same message. The fourth argument, headers , is an array of data that will be prepended to the output file in plaintext. The array can be either indexed or associative. In the former case, each element of the array is a single line of text to be placed in the output file. In the latter case, each line is composed from the key and the value, joining them with a colon and a space. The fifth argument, flags , is optional and specifies options that can be used to control the encryption process. The argument is a bit mask, so you may specify multiple constants if theyre appropriate. Table 9-3 lists the possible flag constants. If the function is successful, the return from the function will be true. If an error occurs in the encryption process, the return will be false and openssl_error_string should be used to obtain error information. On a successful run, the file specified by the second argument will contain the encrypted data. The process must have write access to the file, and it will be created if it does not exist. If it does exist, the existing file will be truncated before the output from this function is written to it. Table 9-3. Flags: openssl_pkcs7_encrypt, openssl_pkcs7_sign, openssl_pkcs7_verify Constant Description PKCS7_TEXT When encrypting or signing, adds a Content-type: textplain header to the output. When verifying a signature, the Content-type header is stripped. PKCS7_BINARY When encrypting or signing, prevents the conversion of bare linefeeds to carriage returns and linefeeds as required by the SMIME specification to mark end of line. PKCS7_NOINTERN When verifying a signature, only the certificates supplied to the function are trusted, causing any included certificates to be considered untrusted. PKCS7_NOVERIFY Prevents the verification of the signers certificate of a signed message. PKCS7_NOCHAIN Prevents chained verification of the signers certificate. Causes certificates in the signed message to be ignored. PKCS7_NOCERTS When signing a message, prevents the signers certificate from being included in the output. 239 PKCS7_NOATTR When signing a message, prevents attributes such as the signing time from being included in the output. PKCS7_DETACHED When signing a message, this is the default if no flags are specified. It causes the MIME type multipartsigned to be used. Its a good idea to include this option because some mail relays cant handle messages signed with this option turned off. PKCS7_NOSIGS Prevents verification of the signatures on a message bool openssl_pkcs7_decryptstring infile, string outfile, mixed certificate, mixed key This function decrypts an encrypted message from the file named by the first argument, infile , and writes the plaintext into the file named by the second argument, outfile . The decryption is done using an RC2 40-bit cipher. The third argument, certificate , specifies the certificate to use, and the fourth argument, key , specifies the private key that matches the certificate. If the function is successful, the return value will be true. If an error occurs, the return value will be false, and openssl_error_string should be used to obtain error information. The process must have write access to the output file. The file will be created if it does not exist, or if it does exist, it will be truncated before the output from this function is written to it. bool openssl_pkcs7_signstring infile, string outfile, mixed certificate,mixed key, array headers [, long flags [, string extra_certificates]] This signs the contents of the file named by the first argument, infile , and writes the result to the file named by the second argument, outfile . Unless PKCS7_NOCERTS is specified as part of the option flags argument, the certificate specified by the third argument, certificate , will be included in the result. The key specified by the fourth argument, key , should be a private key obtained from openssl_get_private , and will be used to sign the message. The fifth argument, headers , can be either an indexed or an associative array. The contents of the array will be prepended to the output after it has been signed. If the array is indexed, each element of the array is treated as a single line to be output. If the array is associative, one line will be written for each key, composed of the key and the value joined by a colon and a space. The sixth argument, flags , is optional and specifies signing options. It is a bit mask and can be composed of the constants described in Table 9-3 . If the seventh argument, extra_certificates , is present, the certificates contained in the file that it names will also be included in the signed result. If the function is successful, the signed message will be written to the output file named by the second argument, outfile , and the return from the function will be true. If an error occurs, the return will be false, and openssl_error_string should be used to obtain error information. The process must have write access to the output file, and it will be created if it does not exist. If the file does exist, it will be truncated before the output from this function is written to it. bool openssl_pkcs7_verifystring infile, int flags [, string outfile [, array cainfo [, string extra_certificates]]] This function verifies the signature on the contents of the file named by the first argument, infile . The second argument, flags , specifies a bit mask of options that control the verification process. Table 9-3 lists the constant definitions and their meanings. If the TE AM FL Y Team-Fly ® 240 third argument, outfile , is present and not null, it specifies the name of a file that the certificates contained in the signed message will be written to. The fourth argument, cainfo , if present, contains a list of trusted certificates that should be used in verifying the signature. The fifth argument, extra_certificates , if present, specifies the name of a file that contains any untrusted certificates that should be used in verifying the signature. If a list of trusted certificates for verification is supplied, the array should contain the names of files andor directories. Files that are specified as such may contain multiple certificates. Any directory that is specified should contain one file per certificate, and the file should have a name composed of the certificate subjects hash value and an extension of .0. Symbolic links named in this manner referring to real files of any other name are acceptable. The return from this function is true if the signature is valid. If the signature is not valid, but no errors otherwise occurred, the return from the function is false. If an error occurs in the verification process, the return value will be -1, and openssl_error_string should be used to obtain error information. If an output file is specified, the process must have write access to it, and it will be created if it does not already exist. If the file does exist, it will be truncated before the output of this function is written to it. 241

Chapter 10. Advanced Programming Topics

We have explained quite a bit about using the OpenSSL library. Often, tasks such as certificate management are most easily accomplished with the command-line tool. For other tasks, such as SSL communications, we must flex our knowledge of the API. By this point it should be clear, though we have not explicitly stated it, that the command-line utilities all use various parts of the OpenSSL API, some of which we have not yet discussed in any detail. In this chapter, we tackle some of the more advanced topics of programming with OpenSSL, including the programmatic interfaces to some features weve discussed only when using the command-line tool. In addition, well cover the interface for reading program variables at runtime. Using the details in this chapter, we will investigate how OpenSSL provides for a variety of other tasks, such as creating SMIME secure email, importing certificates into common web browsers, and hooking into certificates to access public key components for more primitive cryptographic functions.

10.1 Object Stacks

OpenSSL has a large number of macros for dealing with stacks of typed objects. The API can perform only a small number of operations on a stack; however, there are a large number of macros to ensure type safety for objects on the stacks. For instance, if we had a stack of X509 objects and a generic push method for adding an object to the stack, nothing would prevent us from accidentally pushing a non- X509 object onto the stack. To alleviate this problem, OpenSSL provides type-specific macros on top of the generic operations. When manipulating stacks, the type-specific macros should always be used instead of the generic routines. Since the actual operations for a single type have the same behavior as the operations for any type, we will look at them generically. See Example 10-1 . Example 10-1. Stack manipulation functions in generic form STACK_OFTYPE sk_TYPE_new_nullvoid; void sk_TYPE_freeSTACK_OFTYPE st; void sk_TYPE_pop_freeSTACK_OFTYPE st, void free_funcTYPE ; void sk_TYPE_zeroSTACK_OFTYPE st; STACK_OFTYPE sk_TYPE_dupSTACK_OFTYPE st; int sk_TYPE_pushSTACK_OFTYPE st, TYPE val; TYPE sk_TYPE_popSTACK_OFTYPE st; int sk_TYPE_unshiftSTACK_OFTYPE st, TYPE val; TYPE sk_TYPE_shiftSTACK_OFTYPE st; int sk_TYPE_numSTACK_OFTYPE st; TYPE sk_TYPE_valueSTACK_OFTYPE st, int i; TYPE sk_TYPE_setSTACK_OFTYPE st, int i, TYPE val; TYPE sk_TYPE_deleteSTACK_OFTYPE st, int i; TYPE sk_TYPE_delete_ptrSTACK_OFTYPE st, TYPE ptr; int sk_TYPE_insertSTACK_OFTYPE st, TYPE val, int i; Example 10-1 shows the prototypes for some of the generic stack functions in OpenSSL. The type of a stack is implemented through the macro STACK_OF . Stacks are opaque types; an application should not check or set members directly. By replacing the TYPE placeholder used by the sample declarations in Example 10-1 with a specific object type, we get a good look at the prototypes of the actual stack manipulation calls for that type.